1
10
11 package com.sun.xml.bind.v2.runtime.reflect;
12
13 import java.lang.ref.WeakReference;
14 import java.lang.reflect.Array;
15 import java.lang.reflect.ParameterizedType;
16 import java.lang.reflect.Type;
17 import java.util.ArrayList;
18 import java.util.Collection;
19 import java.util.Collections;
20 import java.util.HashMap;
21 import java.util.Iterator;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.WeakHashMap;
25 import java.util.LinkedList;
26 import java.util.HashSet;
27 import java.util.TreeSet;
28 import java.util.Stack;
29 import java.util.concurrent.Callable;
30
31 import javax.xml.bind.JAXBException;
32
33 import com.sun.istack.SAXException2;
34 import com.sun.xml.bind.api.AccessorException;
35 import com.sun.xml.bind.v2.ClassFactory;
36 import com.sun.xml.bind.v2.TODO;
37 import com.sun.xml.bind.v2.model.core.Adapter;
38 import com.sun.xml.bind.v2.model.core.ID;
39 import com.sun.xml.bind.v2.runtime.XMLSerializer;
40 import com.sun.xml.bind.v2.runtime.unmarshaller.Patcher;
41 import com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext;
42 import com.sun.xml.bind.v2.runtime.unmarshaller.LocatorEx;
43
44 import org.xml.sax.SAXException;
45
46
52 public abstract class Lister<BeanT,PropT,ItemT,PackT> {
53
54 protected Lister() {}
55
56
62 public abstract ListIterator<ItemT> iterator(PropT multiValueProp, XMLSerializer context);
63
64
68 public abstract PackT startPacking(BeanT bean, Accessor<BeanT, PropT> acc) throws AccessorException;
69
70
74 public abstract void addToPack( PackT pack, ItemT newValue ) throws AccessorException;
75
76
81 public abstract void endPacking( PackT pack, BeanT bean, Accessor<BeanT,PropT> acc ) throws AccessorException;
82
83
86 public abstract void reset(BeanT o,Accessor<BeanT,PropT> acc) throws AccessorException;
87
88
89
100 public static <BeanT,PropT,ItemT,PackT>
101 Lister<BeanT,PropT,ItemT,PackT> create(Type fieldType,ID idness, Adapter<Type,Class> adapter) {
102
103 Class rawType = (Class) Utils.REFLECTION_NAVIGATOR.erasure(fieldType);
104 Class itemType;
105
106 Lister l;
107 if( rawType.isArray() ) {
108 itemType = rawType.getComponentType();
109 l = getArrayLister(itemType);
110 } else
111 if( Collection.class.isAssignableFrom(rawType) ) {
112 Type bt = Utils.REFLECTION_NAVIGATOR.getBaseClass(fieldType,Collection.class);
113 if(bt instanceof ParameterizedType)
114 itemType = (Class) Utils.REFLECTION_NAVIGATOR.erasure(((ParameterizedType)bt).getActualTypeArguments()[0]);
115 else
116 itemType = Object.class;
117 l = new CollectionLister(getImplClass(rawType));
118 } else
119 return null;
120
121 if(idness==ID.IDREF)
122 l = new IDREFS(l,itemType);
123
124 if(adapter!=null)
125 l = new AdaptedLister(l,adapter.adapterType);
126
127 return l;
128 }
129
130 private static Class getImplClass(Class<?> fieldType) {
131 return ClassFactory.inferImplClass(fieldType,COLLECTION_IMPL_CLASSES);
132 }
133
134
137 private static final Map<Class,WeakReference<Lister>> arrayListerCache =
138 Collections.synchronizedMap(new WeakHashMap<Class,WeakReference<Lister>>());
139
140
143 private static Lister getArrayLister( Class componentType ) {
144 Lister l=null;
145 if(componentType.isPrimitive())
146 l = primitiveArrayListers.get(componentType);
147 else {
148 WeakReference<Lister> wr = arrayListerCache.get(componentType);
149 if(wr!=null)
150 l = wr.get();
151 if(l==null) {
152 l = new ArrayLister(componentType);
153 arrayListerCache.put(componentType,new WeakReference<Lister>(l));
154 }
155 }
156 assert l!=null;
157 return l;
158 }
159
160
167 private static final class ArrayLister<BeanT,ItemT> extends Lister<BeanT,ItemT[],ItemT,Pack<ItemT>> {
168
169 private final Class<ItemT> itemType;
170
171 public ArrayLister(Class<ItemT> itemType) {
172 this.itemType = itemType;
173 }
174
175 public ListIterator<ItemT> iterator(final ItemT[] objects, XMLSerializer context) {
176 return new ListIterator<ItemT>() {
177 int idx=0;
178 public boolean hasNext() {
179 return idx<objects.length;
180 }
181
182 public ItemT next() {
183 return objects[idx++];
184 }
185 };
186 }
187
188 public Pack startPacking(BeanT current, Accessor<BeanT, ItemT[]> acc) {
189 return new Pack<ItemT>(itemType);
190 }
191
192 public void addToPack(Pack<ItemT> objects, ItemT o) {
193 objects.add(o);
194 }
195
196 public void endPacking( Pack<ItemT> pack, BeanT bean, Accessor<BeanT,ItemT[]> acc ) throws AccessorException {
197 acc.set(bean,pack.build());
198 }
199
200 public void reset(BeanT o,Accessor<BeanT,ItemT[]> acc) throws AccessorException {
201 acc.set(o,(ItemT[])Array.newInstance(itemType,0));
202 }
203
204 }
205
206 public static final class Pack<ItemT> extends ArrayList<ItemT> {
207 private final Class<ItemT> itemType;
208
209 public Pack(Class<ItemT> itemType) {
210 this.itemType = itemType;
211 }
212
213 public ItemT[] build() {
214 return super.toArray( (ItemT[])Array.newInstance(itemType,size()) );
215 }
216 }
217
218
221 static final Map<Class,Lister> primitiveArrayListers = new HashMap<Class,Lister>();
222
223 static {
224
225 PrimitiveArrayListerBoolean.register();
226 PrimitiveArrayListerByte.register();
227 PrimitiveArrayListerCharacter.register();
228 PrimitiveArrayListerDouble.register();
229 PrimitiveArrayListerFloat.register();
230 PrimitiveArrayListerInteger.register();
231 PrimitiveArrayListerLong.register();
232 PrimitiveArrayListerShort.register();
233 }
234
235
238 public static final class CollectionLister<BeanT,T extends Collection> extends Lister<BeanT,T,Object,T> {
239
240
244 private final Class<? extends T> implClass;
245
246 public CollectionLister(Class<? extends T> implClass) {
247 this.implClass = implClass;
248 }
249
250 public ListIterator iterator(T collection, XMLSerializer context) {
251 final Iterator itr = collection.iterator();
252 return new ListIterator() {
253 public boolean hasNext() {
254 return itr.hasNext();
255 }
256 public Object next() {
257 return itr.next();
258 }
259 };
260 }
261
262 public T startPacking(BeanT bean, Accessor<BeanT, T> acc) throws AccessorException {
263 T collection = acc.get(bean);
264 if(collection==null) {
265 collection = ClassFactory.create(implClass);
266 if(!acc.isAdapted())
267 acc.set(bean,collection);
268 }
269 collection.clear();
270 return collection;
271 }
272
273 public void addToPack(T collection, Object o) {
274 collection.add(o);
275 }
276
277 public void endPacking( T collection, BeanT bean, Accessor<BeanT,T> acc ) throws AccessorException {
278
279
280
281
282
283
284
285
286 try {
287 if (acc.isAdapted()) {
288 acc.set(bean,collection);
289 }
290 } catch (AccessorException ae) {
291 if(acc.isAdapted()) throw ae;
292 }
293 }
294
295 public void reset(BeanT bean, Accessor<BeanT, T> acc) throws AccessorException {
296 T collection = acc.get(bean);
297 if(collection == null) {
298 return;
299 }
300 collection.clear();
301 }
302 }
303
304
307 private static final class IDREFS<BeanT,PropT> extends Lister<BeanT,PropT,String,IDREFS<BeanT,PropT>.Pack> {
308 private final Lister<BeanT,PropT,Object,Object> core;
309
312 private final Class itemType;
313
314 public IDREFS(Lister core, Class itemType) {
315 this.core = core;
316 this.itemType = itemType;
317 }
318
319 public ListIterator<String> iterator(PropT prop, XMLSerializer context) {
320 final ListIterator i = core.iterator(prop,context);
321
322 return new IDREFSIterator(i, context);
323 }
324
325 public Pack startPacking(BeanT bean, Accessor<BeanT, PropT> acc) {
326 return new Pack(bean,acc);
327 }
328
329 public void addToPack(Pack pack, String item) {
330 pack.add(item);
331 }
332
333 public void endPacking(Pack pack, BeanT bean, Accessor<BeanT, PropT> acc) {
334 }
335
336 public void reset(BeanT bean, Accessor<BeanT, PropT> acc) throws AccessorException {
337 core.reset(bean,acc);
338 }
339
340
343 private class Pack implements Patcher {
344 private final BeanT bean;
345 private final List<String> idrefs = new ArrayList<String>();
346 private final UnmarshallingContext context;
347 private final Accessor<BeanT,PropT> acc;
348 private final LocatorEx location;
349
350 public Pack(BeanT bean, Accessor<BeanT,PropT> acc) {
351 this.bean = bean;
352 this.acc = acc;
353 this.context = UnmarshallingContext.getInstance();
354 this.location = new LocatorEx.Snapshot(context.getLocator());
355 context.addPatcher(this);
356 }
357
358 public void add(String item) {
359 idrefs.add(item);
360 }
361
362
365 public void run() throws SAXException {
366 try {
367 Object pack = core.startPacking(bean,acc);
368
369 for( String id : idrefs ) {
370 Callable callable = context.getObjectFromId(id,itemType);
371 Object t;
372
373 try {
374 t = (callable!=null) ? callable.call() : null;
375 } catch (SAXException e) {
376 throw e;
377 } catch (Exception e) {
378 throw new SAXException2(e);
379 }
380
381 if(t==null) {
382 context.errorUnresolvedIDREF(bean,id,location);
383 } else {
384 TODO.prototype();
385 core.addToPack(pack,t);
386 }
387 }
388
389 core.endPacking(pack,bean,acc);
390 } catch (AccessorException e) {
391 context.handleError(e);
392 }
393 }
394 }
395 }
396
397
404 public static final class IDREFSIterator implements ListIterator<String> {
405 private final ListIterator i;
406 private final XMLSerializer context;
407 private Object last;
408
409 private IDREFSIterator(ListIterator i, XMLSerializer context) {
410 this.i = i;
411 this.context = context;
412 }
413
414 public boolean hasNext() {
415 return i.hasNext();
416 }
417
418
421 public Object last() {
422 return last;
423 }
424
425 public String next() throws SAXException, JAXBException {
426 last = i.next();
427 String id = context.grammar.getBeanInfo(last,true).getId(last,context);
428 if(id==null) {
429 context.errorMissingId(last);
430 }
431 return id;
432 }
433 }
434
435
438 @SuppressWarnings("unchecked")
439 public static <A,B,C,D> Lister<A,B,C,D> getErrorInstance() {
440 return ERROR;
441 }
442
443 public static final Lister ERROR = new Lister() {
444 public ListIterator iterator(Object o, XMLSerializer context) {
445 return EMPTY_ITERATOR;
446 }
447
448 public Object startPacking(Object o, Accessor accessor) {
449 return null;
450 }
451
452 public void addToPack(Object o, Object o1) {
453 }
454
455 public void endPacking(Object o, Object o1, Accessor accessor) {
456 }
457
458 public void reset(Object o, Accessor accessor) {
459 }
460 };
461
462 private static final ListIterator EMPTY_ITERATOR = new ListIterator() {
463 public boolean hasNext() {
464 return false;
465 }
466
467 public Object next() {
468 throw new IllegalStateException();
469 }
470 };
471
472 private static final Class[] COLLECTION_IMPL_CLASSES = new Class[] {
473 ArrayList.class,
474 LinkedList.class,
475 HashSet.class,
476 TreeSet.class,
477 Stack.class
478 };
479 }
480