1 /*
2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
123 public PropertyKind getKind() {
124 return PropertyKind.MAP;
125 }
126
127 public void buildChildElementUnmarshallers(UnmarshallerChain chain, QNameMap<ChildLoader> handlers) {
128 keyLoader = keyBeanInfo.getLoader(chain.context,true);
129 valueLoader = valueBeanInfo.getLoader(chain.context,true);
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<BeanT> target = new ThreadLocal<BeanT>();
144 private ThreadLocal<ValueT> map = new ThreadLocal<ValueT>();
145 private int depthCounter = 0; // needed to clean ThreadLocals
146
147 @Override
148 public void startElement(UnmarshallingContext.State state, TagName ea) throws SAXException {
149 // create or obtain the Map object
150 try {
151 target.set((BeanT)state.prev.target);
152 map.set(acc.get(target.get()));
153 depthCounter++;
154 if(map.get() == null) {
155 map.set(ClassFactory.create(mapImplClass));
156 }
157 map.get().clear();
158 state.target = map.get();
159 } catch (AccessorException e) {
160 // recover from error by setting a dummy Map that receives and discards the values
161 handleGenericException(e,true);
162 state.target = new HashMap();
163 }
164 }
165
166 @Override
167 public void leaveElement(State state, TagName ea) throws SAXException {
168 super.leaveElement(state, ea);
169 try {
170 acc.set(target.get(), map.get());
171 if (--depthCounter == 0) {
172 target.remove();
173 map.remove();
174 }
175 } catch (AccessorException ex) {
176 handleGenericException(ex,true);
177 }
178 }
179
180 @Override
181 public void childElement(UnmarshallingContext.State state, TagName ea) throws SAXException {
182 if(ea.matches(entryTag)) {
183 state.loader = entryLoader;
184 } else {
185 super.childElement(state,ea);
186 }
187 }
188
189 @Override
190 public Collection<QName> getExpectedChildElements() {
191 return Collections.singleton(entryTag.toQName());
192 }
193 };
194
272 } else
273 if(nillable) {
274 w.startElement(tagName,null);
275 w.writeXsiNilTrue();
276 w.endElement();
277 }
278 }
279
280 private void bareStartTag(XMLSerializer w, Name tagName, Object peer) throws IOException, XMLStreamException, SAXException {
281 w.startElement(tagName,peer);
282 w.endNamespaceDecls(peer);
283 w.endAttributes();
284 }
285
286 @Override
287 public Accessor getElementPropertyAccessor(String nsUri, String localName) {
288 if(tagName.equals(nsUri,localName))
289 return acc;
290 return null;
291 }
292 }
|
1 /*
2 * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
123 public PropertyKind getKind() {
124 return PropertyKind.MAP;
125 }
126
127 public void buildChildElementUnmarshallers(UnmarshallerChain chain, QNameMap<ChildLoader> handlers) {
128 keyLoader = keyBeanInfo.getLoader(chain.context,true);
129 valueLoader = valueBeanInfo.getLoader(chain.context,true);
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
269 } else
270 if(nillable) {
271 w.startElement(tagName,null);
272 w.writeXsiNilTrue();
273 w.endElement();
274 }
275 }
276
277 private void bareStartTag(XMLSerializer w, Name tagName, Object peer) throws IOException, XMLStreamException, SAXException {
278 w.startElement(tagName,peer);
279 w.endNamespaceDecls(peer);
280 w.endAttributes();
281 }
282
283 @Override
284 public Accessor getElementPropertyAccessor(String nsUri, String localName) {
285 if(tagName.equals(nsUri,localName))
286 return acc;
287 return null;
288 }
289
290 private static final class Stack<T> {
291 private Stack<T> parent;
292 private T value;
293
294 private Stack(Stack<T> parent, T value) {
295 this.parent = parent;
296 this.value = value;
297 }
298
299 private Stack(T value) {
300 this.value = value;
301 }
302
303 private static <T> void push(ThreadLocal<Stack<T>> holder, T value) {
304 Stack<T> parent = holder.get();
305 if (parent == null)
306 holder.set(new Stack<T>(value));
307 else
308 holder.set(new Stack<T>(parent, value));
309 }
310
311 private static <T> T pop(ThreadLocal<Stack<T>> holder) {
312 Stack<T> current = holder.get();
313 if (current.parent == null)
314 holder.remove();
315 else
316 holder.set(current.parent);
317 return current.value;
318 }
319
320 }
321 }
|