130 handlers.put(tagName,new ChildLoader(itemsLoader,null)); 131 } 132 133 private Loader keyLoader; 134 private Loader valueLoader; 135 136 /** 137 * Handles <items> and </items>. 138 * 139 * The target will be set to a {@link Map}. 140 */ 141 private final Loader itemsLoader = new Loader(false) { 142 143 private ThreadLocal<Stack<BeanT>> target = new ThreadLocal<Stack<BeanT>>(); 144 private ThreadLocal<Stack<ValueT>> map = new ThreadLocal<Stack<ValueT>>(); 145 146 @Override 147 public void startElement(UnmarshallingContext.State state, TagName ea) throws SAXException { 148 // create or obtain the Map object 149 try { 150 BeanT target = (BeanT) state.prev.target; 151 ValueT mapValue = acc.get(target); 152 if(mapValue == null) 153 mapValue = ClassFactory.create(mapImplClass); 154 else 155 mapValue.clear(); 156 157 Stack.push(this.target, target); 158 Stack.push(map, mapValue); 159 state.target = mapValue; 160 } catch (AccessorException e) { 161 // recover from error by setting a dummy Map that receives and discards the values 162 handleGenericException(e,true); 163 state.target = new HashMap(); 164 } 165 } 166 167 @Override 168 public void leaveElement(State state, TagName ea) throws SAXException { 169 super.leaveElement(state, ea); 170 try { 171 acc.set(Stack.pop(target), Stack.pop(map)); 172 } catch (AccessorException ex) { 173 handleGenericException(ex,true); 174 } 175 } 176 177 @Override 178 public void childElement(UnmarshallingContext.State state, TagName ea) throws SAXException { 179 if(ea.matches(entryTag)) { 180 state.loader = entryLoader; 181 } else { 182 super.childElement(state,ea); 183 } 184 } 185 186 @Override 187 public Collection<QName> getExpectedChildElements() { 188 return Collections.singleton(entryTag.toQName()); 189 } 190 }; 191 192 /** 193 * Handles <entry> and </entry>. 194 * 195 * The target will be set to a {@link Map}. 196 */ 197 private final Loader entryLoader = new Loader(false) { 198 @Override 199 public void startElement(UnmarshallingContext.State state, TagName ea) { 200 state.target = new Object[2]; // this is inefficient 201 } 202 203 @Override 204 public void leaveElement(UnmarshallingContext.State state, TagName ea) { 205 Object[] keyValue = (Object[])state.target; 206 Map map = (Map) state.prev.target; 207 map.put(keyValue[0],keyValue[1]); 208 } 209 210 @Override 211 public void childElement(UnmarshallingContext.State state, TagName ea) throws SAXException { 212 if(ea.matches(keyTag)) { 213 state.loader = keyLoader; 214 state.receiver = keyReceiver; 215 return; 216 } 217 if(ea.matches(valueTag)) { 218 state.loader = valueLoader; 219 state.receiver = valueReceiver; 220 return; 221 } 222 super.childElement(state,ea); 223 } 224 225 @Override 226 public Collection<QName> getExpectedChildElements() { 227 return Arrays.asList(keyTag.toQName(),valueTag.toQName()); 228 } 229 }; 230 231 private static final class ReceiverImpl implements Receiver { 232 private final int index; 233 public ReceiverImpl(int index) { 234 this.index = index; 235 } 236 public void receive(UnmarshallingContext.State state, Object o) { 237 ((Object[])state.target)[index] = o; 238 } 239 } 240 241 private static final Receiver keyReceiver = new ReceiverImpl(0); 242 private static final Receiver valueReceiver = new ReceiverImpl(1); 243 244 @Override 245 public void serializeBody(BeanT o, XMLSerializer w, Object outerPeer) throws SAXException, AccessorException, IOException, XMLStreamException { 246 ValueT v = acc.get(o); 247 if(v!=null) { 248 bareStartTag(w,tagName,v); 249 for( Map.Entry e : (Set<Map.Entry>)v.entrySet() ) { 250 bareStartTag(w,entryTag,null); 251 252 Object key = e.getKey(); 253 if(key!=null) { 254 w.startElement(keyTag,key); 255 w.childAsXsiType(key,fieldName,keyBeanInfo, false); 256 w.endElement(); 257 } | 130 handlers.put(tagName,new ChildLoader(itemsLoader,null)); 131 } 132 133 private Loader keyLoader; 134 private Loader valueLoader; 135 136 /** 137 * Handles <items> and </items>. 138 * 139 * The target will be set to a {@link Map}. 140 */ 141 private final Loader itemsLoader = new Loader(false) { 142 143 private ThreadLocal<Stack<BeanT>> target = new ThreadLocal<Stack<BeanT>>(); 144 private ThreadLocal<Stack<ValueT>> map = new ThreadLocal<Stack<ValueT>>(); 145 146 @Override 147 public void startElement(UnmarshallingContext.State state, TagName ea) throws SAXException { 148 // create or obtain the Map object 149 try { 150 BeanT target = (BeanT) state.getPrev().getTarget(); 151 ValueT mapValue = acc.get(target); 152 if(mapValue == null) 153 mapValue = ClassFactory.create(mapImplClass); 154 else 155 mapValue.clear(); 156 157 Stack.push(this.target, target); 158 Stack.push(map, mapValue); 159 state.setTarget(mapValue); 160 } catch (AccessorException e) { 161 // recover from error by setting a dummy Map that receives and discards the values 162 handleGenericException(e,true); 163 state.setTarget(new HashMap()); 164 } 165 } 166 167 @Override 168 public void leaveElement(State state, TagName ea) throws SAXException { 169 super.leaveElement(state, ea); 170 try { 171 acc.set(Stack.pop(target), Stack.pop(map)); 172 } catch (AccessorException ex) { 173 handleGenericException(ex,true); 174 } 175 } 176 177 @Override 178 public void childElement(UnmarshallingContext.State state, TagName ea) throws SAXException { 179 if(ea.matches(entryTag)) { 180 state.setLoader(entryLoader); 181 } else { 182 super.childElement(state,ea); 183 } 184 } 185 186 @Override 187 public Collection<QName> getExpectedChildElements() { 188 return Collections.singleton(entryTag.toQName()); 189 } 190 }; 191 192 /** 193 * Handles <entry> and </entry>. 194 * 195 * The target will be set to a {@link Map}. 196 */ 197 private final Loader entryLoader = new Loader(false) { 198 @Override 199 public void startElement(UnmarshallingContext.State state, TagName ea) { 200 state.setTarget(new Object[2]); // this is inefficient 201 } 202 203 @Override 204 public void leaveElement(UnmarshallingContext.State state, TagName ea) { 205 Object[] keyValue = (Object[])state.getTarget(); 206 Map map = (Map) state.getPrev().getTarget(); 207 map.put(keyValue[0],keyValue[1]); 208 } 209 210 @Override 211 public void childElement(UnmarshallingContext.State state, TagName ea) throws SAXException { 212 if(ea.matches(keyTag)) { 213 state.setLoader(keyLoader); 214 state.setReceiver(keyReceiver); 215 return; 216 } 217 if(ea.matches(valueTag)) { 218 state.setLoader(valueLoader); 219 state.setReceiver(valueReceiver); 220 return; 221 } 222 super.childElement(state,ea); 223 } 224 225 @Override 226 public Collection<QName> getExpectedChildElements() { 227 return Arrays.asList(keyTag.toQName(),valueTag.toQName()); 228 } 229 }; 230 231 private static final class ReceiverImpl implements Receiver { 232 private final int index; 233 public ReceiverImpl(int index) { 234 this.index = index; 235 } 236 public void receive(UnmarshallingContext.State state, Object o) { 237 ((Object[])state.getTarget())[index] = o; 238 } 239 } 240 241 private static final Receiver keyReceiver = new ReceiverImpl(0); 242 private static final Receiver valueReceiver = new ReceiverImpl(1); 243 244 @Override 245 public void serializeBody(BeanT o, XMLSerializer w, Object outerPeer) throws SAXException, AccessorException, IOException, XMLStreamException { 246 ValueT v = acc.get(o); 247 if(v!=null) { 248 bareStartTag(w,tagName,v); 249 for( Map.Entry e : (Set<Map.Entry>)v.entrySet() ) { 250 bareStartTag(w,entryTag,null); 251 252 Object key = e.getKey(); 253 if(key!=null) { 254 w.startElement(keyTag,key); 255 w.childAsXsiType(key,fieldName,keyBeanInfo, false); 256 w.endElement(); 257 } |