1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package de.bea.domingo.map;
24
25 import java.lang.reflect.Method;
26 import java.util.ArrayList;
27 import java.util.HashMap;
28 import java.util.Iterator;
29 import java.util.List;
30 import java.util.Map;
31
32 import de.bea.domingo.DDocument;
33
34 /***
35 * Class defining and performing a mapping of Lists of business objects from and
36 * to a document.
37 *
38 * @author <a href="mailto:kriede@users.sourceforge.net">Kurt Riede</a>
39 */
40 public abstract class ListMapper extends BaseDMapper {
41
42 /*** Notes item name in the Notes document. */
43 private String mItemName;
44
45 /*** Name of getter method of list attribute. */
46 private String mGetName;
47
48 /*** Set of list item attributes. */
49 private List mAttributes = new ArrayList();
50
51 /***
52 * Constructor. Creates a direct mapper where the Notes item name is equal
53 * to the <tt>itemName</tt> attribute and the names of the get/set methods
54 * in the business class are equal to <tt>"get" + itemName</tt> and
55 * <tt>"set" + itemName</tt>.
56 *
57 * @param itemName name of Notes item
58 */
59 public ListMapper(final String itemName) {
60 this(itemName, "get" + itemName);
61 }
62
63 /***
64 * Constructor. Creates a direct mapper where the Notes item name is equal
65 * to the <tt>itemName</tt> attribute and the names of the get/set methods
66 * in the business class are equal to <tt>getName</tt> and
67 * <tt>setName</tt>.
68 *
69 * @param itemName name of Notes item
70 * @param getName name of get-method
71 */
72 public ListMapper(final String itemName, final String getName) {
73 this.mItemName = itemName;
74 this.mGetName = getName;
75 }
76
77 /***
78 * Adds a mapper where the Notes item name is equal to the <tt>itemName</tt>
79 * attribute and the names of the get/set methods in the business class are
80 * equal to <tt>"get" + itemName</tt> and <tt>"set" + itemName</tt>.
81 *
82 * @param itemName name of Notes item
83 * @param clazz the value type
84 */
85 protected final void add(final String itemName, final Class clazz) {
86 add(itemName, itemName, clazz);
87 }
88
89 /***
90 * Adds a mapper where the Notes item name is equal to the <tt>itemName</tt>
91 * attribute and the names of the get/set methods in the business class are
92 * equal to <tt>"get" + attributeName</tt> and
93 * <tt>"set" + attributeName</tt>.
94 *
95 * @param itemName name of Notes item
96 * @param attributeName name of Java attribute
97 * @param clazz the value type
98 */
99 protected final void add(final String itemName, final String attributeName, final Class clazz) {
100 add(itemName, "get" + attributeName, "set" + attributeName, clazz);
101 }
102
103 /***
104 * Adds a mapper where the Notes item name is equal to the <tt>itemName</tt>
105 * attribute and the names of the get/set methods in the business class are
106 * equal to <tt>getName</tt> and <tt>setName</tt>.
107 *
108 * @param itemName name of Notes item
109 * @param getName name of get-method
110 * @param setName name of set-method
111 * @param clazz the value type
112 */
113 protected final void add(final String itemName, final String getName, final String setName, final Class clazz) {
114 mAttributes.add(new Attribute(itemName, getName, setName, clazz));
115 }
116
117 private static final class Attribute {
118
119 private final String mItemName;
120
121 private final String mGetName;
122
123 private final String mSetName;
124
125 private final Class mClazz;
126
127 private Attribute(final String itemName, final String getName, final String setName, final Class clazz) {
128 this.mItemName = itemName;
129 this.mGetName = getName;
130 this.mSetName = setName;
131 this.mClazz = clazz;
132 }
133 }
134
135 /***
136 * {@inheritDoc}
137 * @see de.bea.domingo.map.Mapper#map(de.bea.domingo.DDocument,
138 * java.lang.Object)
139 */
140 public final void map(final DDocument document, final Object object) throws MappingException {
141
142 final Map values = new HashMap(mAttributes.size());
143 int minSize = Integer.MAX_VALUE;
144 int maxSize = 0;
145 final Iterator i2 = mAttributes.iterator();
146 while (i2.hasNext()) {
147 final Attribute attribute = (Attribute) i2.next();
148 final List itemValue = document.getItemValue(attribute.mItemName);
149 minSize = itemValue.size() < minSize ? itemValue.size() : minSize;
150 maxSize = itemValue.size() > maxSize ? itemValue.size() : maxSize;
151 values.put(attribute, itemValue);
152 }
153 if (minSize != maxSize) {
154 System.out.println("not all items have the same number of values");
155 }
156 for (int k = 0; k < minSize; k++) {
157 Object item = createItem(object);
158 final Iterator i3 = mAttributes.iterator();
159 while (i3.hasNext()) {
160 final Attribute attribute = (Attribute) i3.next();
161 setValue(item, attribute.mSetName, ((List) values.get(attribute)).get(k), attribute.mClazz);
162 }
163 }
164 }
165
166 /***
167 * Creates a new instance of a list item. Must be implemented by concrete
168 * list mappers.
169 *
170 * @param object parent object
171 * @return new instance of list item
172 */
173 protected abstract Object createItem(final Object object);
174
175 /***
176 * {@inheritDoc}
177 * @see de.bea.domingo.map.Mapper#map(java.lang.Object,
178 * de.bea.domingo.DDocument)
179 */
180 public final void map(final Object object, final DDocument document) throws MappingException {
181 List items = getList(object);
182 int size = items.size();
183
184 Map values = new HashMap(mAttributes.size());
185 Iterator i = mAttributes.iterator();
186 while (i.hasNext()) {
187 Attribute attribute = (Attribute) i.next();
188 values.put(attribute, new ArrayList(size));
189 }
190
191 Iterator iterator = items.iterator();
192 while (iterator.hasNext()) {
193 Object item = iterator.next();
194 Iterator i3 = mAttributes.iterator();
195 while (i3.hasNext()) {
196 Attribute attribute = (Attribute) i3.next();
197 List list = (List) values.get(attribute);
198 list.add(getValue(item, attribute.mGetName));
199 }
200 }
201
202 Iterator i2 = mAttributes.iterator();
203 while (i2.hasNext()) {
204 Attribute attribute = (Attribute) i2.next();
205 replaceItemValue(document, attribute.mItemName, (List) values.get(attribute));
206 }
207 }
208
209 /***
210 * Returns the list attribute defined by the getter method as defined in the
211 * constructor.
212 *
213 * @return the list
214 * @throws MappingException if the list attribute cannot be read from the
215 * given object
216 */
217 private List getList(final Object object) throws MappingException {
218 Class[] parameterTypes = {};
219 try {
220 Method method = object.getClass().getMethod(mGetName, parameterTypes);
221 Object[] args = {};
222 return (List) method.invoke(object, args);
223 } catch (Exception e) {
224 throw new MappingException("Cannot get list attribute " + mItemName, e);
225 }
226 }
227 }