1 /* ====================================================================
2 * Bigyo Software License, version 1.1
3 *
4 * Copyright (c) 2004, Zsombor Gegesy. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 *
17 * 3. Neither the name of the Bigyo Group nor the name "Bigyo" nor
18 * the names of its contributors may be used to endorse or promote
19 * products derived from this software without specific prior
20 * written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 *
35 * ====================================================================
36 */
37
38 package net.sf.bigyo.container;
39
40 import java.util.ArrayList;
41 import java.util.Iterator;
42 import java.util.List;
43
44 import com.thoughtworks.xstream.XStream;
45 import com.thoughtworks.xstream.alias.ClassMapper;
46 import com.thoughtworks.xstream.converters.Converter;
47 import com.thoughtworks.xstream.converters.ConverterLookup;
48 import com.thoughtworks.xstream.converters.ErrorWriter;
49 import com.thoughtworks.xstream.converters.MarshallingContext;
50 import com.thoughtworks.xstream.converters.UnmarshallingContext;
51 import com.thoughtworks.xstream.converters.reflection.ReflectionProvider;
52 import com.thoughtworks.xstream.core.JVM;
53 import com.thoughtworks.xstream.io.HierarchicalStreamReader;
54 import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
55
56 /***
57 * Creates a more 'compact' xml, instead of the verbose default. Usage: XStream
58 * xs = .... xs.registerConverter(new CompactReflectionConverter(xs));
59 *
60 * Created on 2004.04.17.
61 * @author zombi@mailbox.hu
62 *
63 *
64 */
65 public class CompactReflectionConverter implements Converter {
66
67 private ClassMapper classMapper;
68 private String classAttributeIdentifier;
69 ReflectionProvider reflectionProvider;
70 ConverterLookup lookup;
71 private String definedInAttributeIdentifier = "defined-in";
72 private boolean accept = true;
73
74 public CompactReflectionConverter(ClassMapper classMapper, String classAttributeIdentifier,
75 ReflectionProvider reflectionProvider, ConverterLookup lookup) {
76 this.classMapper = classMapper;
77 this.classAttributeIdentifier = classAttributeIdentifier;
78 this.reflectionProvider = reflectionProvider;
79 this.lookup = lookup;
80 }
81
82 /***
83 * @param xstream
84 */
85 public CompactReflectionConverter(XStream xstream) {
86 this(xstream.getClassMapper(), "class-name", new JVM().bestReflectionProvider(), xstream.getConverterLookup());
87 }
88
89 /*
90 * (non-Javadoc)
91 *
92 * @see com.thoughtworks.xstream.converters.reflection.ReflectionConverter#canConvert(java.lang.Class)
93 */
94 public boolean canConvert(Class cls) {
95 if (accept) {
96 if (!cls.isPrimitive() && !cls.isArray() && !cls.isInterface()) {
97 return !cls.getName().startsWith("java.");
98 }
99 }
100 return false;
101 }
102
103 public void setAccept(boolean b) {
104 this.accept = b;
105 }
106
107
108 static class Record {
109 String fieldName;
110 Class fieldType;
111 Object newObj;
112
113 /***
114 * @param fieldName
115 * @param fieldType
116 * @param newObj
117 */
118 public Record(String fieldName, Class fieldType, Object newObj) {
119 super();
120 this.fieldName = fieldName;
121 this.fieldType = fieldType;
122 this.newObj = newObj;
123 }
124 }
125
126 public void marshal(final Object source, final HierarchicalStreamWriter writer, final MarshallingContext context) {
127 final List complexFields = new ArrayList();
128 reflectionProvider.visitSerializableFields(source, new ReflectionProvider.Visitor() {
129
130 public void visit(String fieldName, Class fieldType, Class definedIn, Object value) {
131
132 /*
133 * Object newObj = reflectionProvider.readField(source,
134 * fieldName); if (newObj != null) { Class actualType =
135 * newObj.getClass(); if
136 * (actualType.getName().startsWith("java.lang.")) {
137 * writer.addAttribute(fieldName, newObj.toString()); } else {
138 * complexFields.add(new Record(fieldName, fieldType, newObj));
139 * } }
140 */
141
142 if (value != null) {
143 Class actualType = value.getClass();
144 if (actualType.getName().startsWith("java.lang.")) {
145 writer.addAttribute(fieldName, value.toString());
146 } else {
147 complexFields.add(new Record(fieldName, fieldType, value));
148 }
149 }
150 }
151 });
152 for (Iterator iter = complexFields.iterator(); iter.hasNext();) {
153 Record r = (Record) iter.next();
154 writer.startNode(classMapper.mapNameToXML(r.fieldName));
155 Class defaultType = classMapper.lookupDefaultType(r.fieldType);
156 Class actualType = r.newObj.getClass();
157 if (!actualType.equals(defaultType)) {
158 writer.addAttribute(classAttributeIdentifier, classMapper.lookupName(actualType));
159 }
160
161 context.convertAnother(r.newObj);
162
163 writer.endNode();
164
165 }
166
167 }
168
169 public Object unmarshal(final HierarchicalStreamReader reader, UnmarshallingContext context) {
170 // copy from ReflectionProvider
171 Object result = context.currentObject();
172
173 if (result == null) {
174 result = reflectionProvider.newInstance(context.getRequiredType());
175 }
176 // de-serialize simple fields
177
178 final Object finalResult = result;
179 reflectionProvider.visitSerializableFields(result, new ReflectionProvider.Visitor() {
180
181 /*
182 * (non-Javadoc)
183 *
184 * @see com.thoughtworks.xstream.converters.reflection.ReflectionProvider.Visitor#visit(java.lang.String,
185 * java.lang.Class, java.lang.Class, java.lang.Object)
186 */
187 public void visit(String fieldName, Class fieldType, Class definedIn, Object value) {
188 if (fieldType.getName().startsWith("java.lang.") || fieldType.isPrimitive()) {
189 Converter converter = lookup.lookupConverterForType(fieldType);
190 final String fieldAttr = reader.getAttribute(fieldName);
191 if (fieldAttr != null) {
192
193 Object fieldValue = converter.unmarshal(new HierarchicalStreamReader() {
194 /*
195 * (non-Javadoc)
196 *
197 * @see com.thoughtworks.xstream.io.HierarchicalStreamReader#getValue()
198 */
199 public String getValue() {
200 return fieldAttr;
201 }
202
203 public boolean hasMoreChildren() {
204 return false;
205 }
206
207 public void moveDown() {
208
209 }
210
211 public void moveUp() {
212
213 }
214
215 public String getNodeName() {
216 return null;
217 }
218
219 public String getAttribute(String arg0) {
220 return null;
221 }
222
223 public Object peekUnderlyingNode() {
224 return null;
225 }
226
227 public void appendErrors(ErrorWriter errorWriter) {
228 // TODO Auto-generated method stub
229
230 }
231 }, null);
232 reflectionProvider.writeField(finalResult, fieldName, fieldValue, definedIn);
233 //writeField(finalResult, fieldName, fieldValue);
234 }
235 }
236 }
237 });
238
239 // copy from ReflectionProvider
240
241 while (reader.hasMoreChildren()) {
242 reader.moveDown();
243
244 String fieldName = classMapper.mapNameFromXML(reader.getNodeName());
245
246 String definedIn = reader.getAttribute(definedInAttributeIdentifier);
247 Class definedInCls = definedIn == null ? null : classMapper.lookupType(definedIn);
248
249 Class type;
250 String classAttribute = reader.getAttribute(classAttributeIdentifier);
251 if (classAttribute == null) {
252 type = classMapper.lookupDefaultType(reflectionProvider.getFieldType(result, fieldName, definedInCls));
253 } else {
254 type = classMapper.lookupType(classAttribute);
255 }
256
257 Object fieldValue = context.convertAnother(result, type);
258
259 reflectionProvider.writeField(result, fieldName, fieldValue, definedInCls);
260
261 reader.moveUp();
262 }
263
264 return result;
265 }
266 }
This page was automatically generated by Maven