View Javadoc

1   /*
2    * This file is part of Domingo
3    * an Open Source Java-API to Lotus Notes/Domino
4    * hosted at http://domingo.sourceforge.net
5    *
6    * Copyright (c) 2003-2007 Beck et al. projects GmbH Munich, Germany (http://www.bea.de)
7    *
8    * This library is free software; you can redistribute it and/or
9    * modify it under the terms of the GNU Lesser General Public
10   * License as published by the Free Software Foundation; either
11   * version 2.1 of the License, or (at your option) any later version.
12   *
13   * This library is distributed in the hope that it will be useful,
14   * but WITHOUT ANY WARRANTY; without even the implied warranty of
15   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   * Lesser General Public License for more details.
17   *
18   * You should have received a copy of the GNU Lesser General Public
19   * License along with this library; if not, write to the Free Software
20   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21   */
22  
23  package de.bea.domingo.groupware.map;
24  
25  import java.util.Calendar;
26  import java.util.HashSet;
27  import java.util.List;
28  import java.util.Map;
29  import java.util.Set;
30  
31  import de.bea.domingo.DDocument;
32  import de.bea.domingo.DViewEntry;
33  import de.bea.domingo.groupware.Email;
34  import de.bea.domingo.groupware.EmailDigest;
35  import de.bea.domingo.groupware.Email.Importance;
36  import de.bea.domingo.groupware.Email.Priority;
37  import de.bea.domingo.map.BaseDMapper;
38  import de.bea.domingo.map.BaseMapper;
39  import de.bea.domingo.map.ConstantMapper;
40  import de.bea.domingo.map.CustomMapper;
41  import de.bea.domingo.map.DirectMapper;
42  import de.bea.domingo.map.MapMapper;
43  import de.bea.domingo.map.MappingException;
44  import de.bea.domingo.map.MethodNotFoundException;
45  
46  
47  /***
48   * Mapper for memos in a Notes mail database.
49   *
50   * @see de.bea.domingo.groupware.Email
51   * @see de.bea.domingo.groupware.EmailDigest
52   * @author <a href=mailto:kriede@users.sourceforge.net>Kurt Riede</a>
53   */
54  public final class EmailMapper extends BaseMapper {
55  
56      // TODO make column numbers configurable for better support of individualized mail templates
57  
58      private static final int DEFAULT_SUBJECT_COLUMN = 11;
59  
60      private static final int DEFAULT_TIME_COLUMN = 8;
61  
62      private static final int DEFAULT_DATE_COLUMN = 7;
63  
64      private static final int DEFAULT_WHO_COLUMN = 5;
65  
66      private static final Class INSTANCE_CLASS = Email.class;
67  
68      private static final Class DIGEST_CLASS = EmailDigest.class;
69  
70      /***
71       * Constructor.
72       *
73       * @throws MethodNotFoundException if the getter or setter method was not found for the attribute name
74       */
75      public EmailMapper() throws MethodNotFoundException {
76          super(INSTANCE_CLASS, DIGEST_CLASS);
77          add(new ConstantMapper("Form", "Memo"));
78          add(new DirectMapper("Subject", String.class));
79          add(new DirectMapper("Body", String.class));
80          add(new DirectMapper("From", String.class));
81          add(new DirectMapper("Principal", String.class));
82          add(new DirectMapper("SendTo", "Recipients", List.class));
83          add(new DirectMapper("CopyTo", "Cc", List.class));
84          add(new DirectMapper("BlindCopyTo", "Bcc", List.class));
85          add(new DirectMapper("Categories", "Categories", Set.class));
86          add(new DirectMapper("DeliveredDate", Calendar.class));
87          add(new PriorityMapper());
88          add(new ImportanceMapper());
89          add(new HeaderMapper());
90          add(new SaveAfterSendMapper());
91      }
92  
93      /***
94       * {@inheritDoc}
95       *
96       * @see de.bea.domingo.map.DMapper#newInstance()
97       */
98      public Object newInstance() {
99          return new Email();
100     }
101 
102     /***
103      * {@inheritDoc}
104      *
105      * @see de.bea.domingo.map.DMapper#newDigest()
106      */
107     public Object newDigest() {
108         return new EmailDigest();
109     }
110 
111     /***
112      * {@inheritDoc}
113      *
114      * @see de.bea.domingo.map.DMapper#map(de.bea.domingo.DViewEntry, java.lang.Object)
115      */
116     public void map(final DViewEntry viewEntry, final Object object) throws MappingException {
117         EmailDigest digest = (EmailDigest) object;
118         List columnValues = viewEntry.getColumnValues();
119         digest.setUnid(viewEntry.getUniversalID());
120         digest.setWho((String) columnValues.get(getWhoColumnIndex()));
121         digest.setDate((Calendar) columnValues.get(getDateColumnIndex()));
122         digest.setTime((Calendar) columnValues.get(getTimeColumnIndex()));
123         // revisit simple hack to suppotr R6.5 and R7
124         try {
125             digest.setSubject((String) columnValues.get(getSubjectColumnIndex()));
126         } catch (RuntimeException e) {
127             digest.setSubject((String) columnValues.get(getSubjectColumnIndex() + 1));
128         }
129     }
130 
131     private int getWhoColumnIndex() {
132         // TODO make this depending from notes version
133         return DEFAULT_WHO_COLUMN;
134     }
135 
136     private int getDateColumnIndex() {
137         // TODO make this depending from notes version
138         return DEFAULT_DATE_COLUMN;
139     }
140 
141     private int getTimeColumnIndex() {
142         // TODO make this depending from notes version
143         return DEFAULT_TIME_COLUMN;
144     }
145 
146     private int getSubjectColumnIndex() {
147         // TODO make this depending from notes version
148         return DEFAULT_SUBJECT_COLUMN;
149     }
150 
151     /***
152      * A mapper for email header values.
153      * Disallowed values are the explicit header attributes like
154      * <code>From</code>, <code>To</code>, <code>Cc</code>, <code>Bcc</code>,
155      * <code>Subject</code> or <code>Body</code> as well as all item-names
156      * that are used internally in Notes email documents.
157      *
158      */
159     private static class HeaderMapper extends MapMapper {
160 
161         private static final Set DISALLOWED_NAMES = new HashSet();
162 
163         static {
164             String itemName = "From";
165             // disallow explicit headers
166             addDisallowedName(itemName);
167             addDisallowedName("To");
168             addDisallowedName("CopyTo");
169             addDisallowedName("BlindCopyTo");
170             addDisallowedName("Principal");
171             addDisallowedName("Subject");
172             addDisallowedName("Body");
173             addDisallowedName("DeliveryPriority");
174             addDisallowedName("Importance");
175 
176             // disallow reserved Notes items
177             addDisallowedName("$AltNameLanguageTags");
178             addDisallowedName("$EncryptionStatus");
179             addDisallowedName("$FILE");
180             addDisallowedName("$Fonts");
181             addDisallowedName("$KeepPrivate");
182             addDisallowedName("$REF");
183             addDisallowedName("$RFSaveInfo");
184             addDisallowedName("$SignatureStatus");
185             addDisallowedName("$StorageBcc");
186             addDisallowedName("$StorageCc");
187             addDisallowedName("$StorageTo");
188             addDisallowedName("$UpdatedBy");
189             addDisallowedName("AltCopyTo");
190             addDisallowedName("AltFrom");
191             addDisallowedName("BGTableColor");
192             addDisallowedName("DefaultMailSaveOptions");
193             addDisallowedName("Encrypt");
194             addDisallowedName("EnterBlindCopyTo");
195             addDisallowedName("EnterCopyTo");
196             addDisallowedName("EnterSendTo");
197             addDisallowedName("Form");
198             addDisallowedName("InetBlindCopyTo");
199             addDisallowedName("InetCopyTo");
200             addDisallowedName("InetSendTo");
201             addDisallowedName("In_Reply_To");
202             addDisallowedName("Logo");
203             addDisallowedName("tmpImp");
204             addDisallowedName("Sign");
205 
206             // TODO complete list of disallowed names
207         }
208 
209         /***
210          * Ensures that disallowed names are added in all lower-case to
211          * allow later case-insensitive checks.
212          */
213         private static void addDisallowedName(final String itemName) {
214             DISALLOWED_NAMES.add(itemName.toLowerCase());
215         }
216 
217         /***
218          * Case-insensitive check if a given name is a disallowed name
219          * for an email header.
220          *
221          * @see de.bea.domingo.map.MapMapper#isNameAllowed(java.lang.String)
222          */
223         protected boolean isNameAllowed(final String name) {
224             return DISALLOWED_NAMES.contains(name.toLowerCase());
225         }
226 
227         /***
228          * @see de.bea.domingo.map.MapMapper#getMap()
229          */
230         protected Map getMap(final Object object) {
231             return ((Email) object).getHeaders();
232         }
233     }
234 
235     /***
236      * Maps the importance.
237      */
238     private static final class ImportanceMapper extends BaseDMapper {
239 
240         /***
241          * {@inheritDoc}
242          * @see de.bea.domingo.map.Mapper#map(de.bea.domingo.DDocument, java.lang.Object)
243          */
244         public void map(final DDocument document, final Object object) throws MappingException {
245             if (!"".equals(document.getItemValueString("Importance"))) {
246                 ((Email) object).setImportance(get(document.getItemValueString("Importance").charAt(0)));
247             } else {
248                 ((Email) object).setImportance(Importance.NORMAL);
249             }
250         }
251 
252         /***
253          * {@inheritDoc}
254          * @see de.bea.domingo.map.Mapper#map(java.lang.Object, de.bea.domingo.DDocument)
255          */
256         public void map(final Object object, final DDocument document) throws MappingException {
257             document.replaceItemValue("Importance", getImportance(((Email) object).getImportance()));
258         }
259 
260         private static int getImportance(final Importance value) {
261             if (value == Importance.LOW) {
262                 return 1;
263             } else if (value == Importance.NORMAL) {
264                 return 2;
265             } else if (value == Importance.HIGH) {
266                 return 1;
267             }
268             throw new IllegalArgumentException("Unknown importance: " + value);
269         }
270 
271         private Importance get(final char value) {
272             if (value == '1') {
273                 return Importance.HIGH;
274             } else if (value == '2') {
275                 return Importance.NORMAL;
276             } else if (value == '3') {
277                 return Importance.LOW;
278             }
279             throw new IllegalArgumentException("Unknown importance: " + value);
280         }
281     }
282 
283     /***
284      * Maps the priority.
285      */
286     private static final class PriorityMapper extends BaseDMapper {
287 
288         /***
289          * {@inheritDoc}
290          * @see de.bea.domingo.map.Mapper#map(de.bea.domingo.DDocument, java.lang.Object)
291          */
292         public void map(final DDocument document, final Object object) throws MappingException {
293             if (!"".equals(document.getItemValueString("DeliveryPriority"))) {
294                 ((Email) object).setPriority(getPriority(document.getItemValueString("DeliveryPriority").charAt(0)));
295             } else {
296                 ((Email) object).setPriority(Priority.NORMAL);
297             }
298         }
299 
300         /***
301          * {@inheritDoc}
302          * @see de.bea.domingo.map.Mapper#map(java.lang.Object, de.bea.domingo.DDocument)
303          */
304         public void map(final Object object, final DDocument document) throws MappingException {
305             document.replaceItemValue("DeliveryPriority", getPriority(((Email) object).getPriority()));
306         }
307 
308         private static String getPriority(final Priority value) {
309             if (value == Priority.LOW) {
310                 return "L";
311             } else if (value == Priority.NORMAL) {
312                 return "N";
313             } else if (value == Priority.HIGH) {
314                 return "H";
315             }
316             throw new IllegalArgumentException("Unknown priority: " + value);
317         }
318 
319         private static Priority getPriority(final char value) {
320             if (value == 'H') {
321                 return Priority.HIGH;
322             } else if (value == 'N') {
323                 return Priority.NORMAL;
324             } else if (value == 'L') {
325                 return Priority.LOW;
326             }
327             throw new IllegalArgumentException("Unknown priority: " + value);
328         }
329     }
330 
331     /***
332      * Mapper for the attribute <code>SaveAfterSend</code>.
333      */
334     private static final class SaveAfterSendMapper extends CustomMapper {
335 
336         /***
337          * {@inheritDoc}
338          * @see de.bea.domingo.map.Mapper#map(de.bea.domingo.DDocument, java.lang.Object)
339          */
340         public void map(final DDocument document, final Object object) throws MappingException {
341             ((Email) object).setSaveOnSend(true);
342         }
343 
344         /***
345          * {@inheritDoc}
346          * @see de.bea.domingo.map.Mapper#map(java.lang.Object, de.bea.domingo.DDocument)
347          */
348         public void map(final Object object, final DDocument document) throws MappingException {
349             document.setSaveMessageOnSend(((Email) object).getSaveOnSend());
350         }
351     }
352 }