001: /*
002: * This file is part of PFIXCORE.
003: *
004: * PFIXCORE is free software; you can redistribute it and/or modify
005: * it under the terms of the GNU Lesser General Public License as published by
006: * the Free Software Foundation; either version 2 of the License, or
007: * (at your option) any later version.
008: *
009: * PFIXCORE is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012: * GNU Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public License
015: * along with PFIXCORE; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: *
018: */
019: package de.schlund.pfixcore.oxm.impl.serializers;
020:
021: import java.lang.annotation.Annotation;
022: import java.lang.reflect.Field;
023: import java.lang.reflect.Method;
024: import java.util.HashMap;
025: import java.util.Iterator;
026: import java.util.Map;
027: import java.util.Set;
028:
029: import de.schlund.pfixcore.beans.BeanDescriptor;
030: import de.schlund.pfixcore.beans.BeanDescriptorFactory;
031: import de.schlund.pfixcore.oxm.impl.AnnotationAware;
032: import de.schlund.pfixcore.oxm.impl.ComplexTypeSerializer;
033: import de.schlund.pfixcore.oxm.impl.SerializationContext;
034: import de.schlund.pfixcore.oxm.impl.SimpleTypeSerializer;
035: import de.schlund.pfixcore.oxm.impl.XMLWriter;
036:
037: /**
038: * @author mleidig@schlund.de
039: * @author Stephan Schmidt <schst@stubbles.net>
040: */
041: public class BeanSerializer implements ComplexTypeSerializer {
042:
043: BeanDescriptorFactory beanDescFactory;
044: Map<Class<?>, Map<String, SimpleTypeSerializer>> customSimpleSerializerCache;
045: Map<Class<?>, Map<String, ComplexTypeSerializer>> customComplexSerializerCache;
046:
047: public BeanSerializer(BeanDescriptorFactory beanDescFactory) {
048: this .beanDescFactory = beanDescFactory;
049: customSimpleSerializerCache = new HashMap<Class<?>, Map<String, SimpleTypeSerializer>>();
050: customComplexSerializerCache = new HashMap<Class<?>, Map<String, ComplexTypeSerializer>>();
051: }
052:
053: public void serialize(Object obj, SerializationContext ctx,
054: XMLWriter writer) {
055: BeanDescriptor bd = beanDescFactory.getBeanDescriptor(obj
056: .getClass());
057: readCustomSerializers(obj.getClass(), bd);
058: Set<String> props = bd.getReadableProperties();
059: Iterator<String> it = props.iterator();
060: while (it.hasNext()) {
061: String prop = it.next();
062: try {
063: Object val = null;
064: Method meth = bd.getGetMethod(prop);
065: if (meth != null) {
066: val = meth.invoke(obj, new Object[0]);
067: } else {
068: Field field = bd.getDirectAccessField(prop);
069: if (field != null)
070: val = field.get(obj);
071: else
072: throw new RuntimeException(
073: "Bean of type '"
074: + obj.getClass().getName()
075: + "' doesn't "
076: + " have getter method or direct access to property '"
077: + prop + "'.");
078: }
079: if (val != null) {
080: SimpleTypeSerializer simpleSerializer = getCustomSimpleTypeSerializer(
081: obj.getClass(), prop);
082: if (simpleSerializer != null) {
083: String value = ctx.serialize(val,
084: simpleSerializer);
085: ComplexTypeSerializer complexSerializer = getCustomComplexTypeSerializer(
086: obj.getClass(), prop);
087: if (complexSerializer != null) {
088: writer.writeStartElement(prop);
089: ctx.serialize(value, writer,
090: complexSerializer);
091: writer.writeEndElement();
092: } else {
093: writer.writeAttribute(prop, value);
094: }
095: } else {
096: ComplexTypeSerializer complexSerializer = getCustomComplexTypeSerializer(
097: obj.getClass(), prop);
098: if (complexSerializer != null) {
099: writer.writeStartElement(prop);
100: ctx.serialize(val, writer,
101: complexSerializer);
102: writer.writeEndElement();
103: } else if (ctx.hasSimpleTypeSerializer(val
104: .getClass())) {
105: writer.writeAttribute(prop, ctx
106: .serialize(val));
107: } else {
108: writer.writeStartElement(prop);
109: ctx.serialize(val, writer);
110: writer.writeEndElement();
111: }
112: }
113: }
114: } catch (Exception x) {
115: throw new RuntimeException(
116: "Error during serialization.", x);
117: }
118: }
119: }
120:
121: private SimpleTypeSerializer getCustomSimpleTypeSerializer(
122: Class<?> clazz, String prop) {
123: Map<String, SimpleTypeSerializer> simpleSerializers = customSimpleSerializerCache
124: .get(clazz);
125: if (simpleSerializers != null && !simpleSerializers.isEmpty()) {
126: return simpleSerializers.get(prop);
127: }
128: return null;
129: }
130:
131: private ComplexTypeSerializer getCustomComplexTypeSerializer(
132: Class<?> clazz, String prop) {
133: Map<String, ComplexTypeSerializer> complexSerializers = customComplexSerializerCache
134: .get(clazz);
135: if (complexSerializers != null && !complexSerializers.isEmpty()) {
136: return complexSerializers.get(prop);
137: }
138: return null;
139: }
140:
141: private void readCustomSerializers(Class<?> clazz,
142: BeanDescriptor beanDesc) {
143: if (customSimpleSerializerCache.containsKey(clazz))
144: return;
145: Map<String, SimpleTypeSerializer> simpleSerializers = new HashMap<String, SimpleTypeSerializer>();
146: Map<String, ComplexTypeSerializer> complexSerializers = new HashMap<String, ComplexTypeSerializer>();
147: Set<String> props = beanDesc.getReadableProperties();
148: Iterator<String> it = props.iterator();
149: while (it.hasNext()) {
150: String prop = it.next();
151: try {
152: Method meth = beanDesc.getGetMethod(prop);
153: if (meth != null) {
154: Annotation[] annos = meth.getAnnotations();
155: for (Annotation anno : annos) {
156: if (anno
157: .annotationType()
158: .isAnnotationPresent(
159: de.schlund.pfixcore.oxm.impl.annotation.SimpleTypeSerializerClass.class)) {
160: de.schlund.pfixcore.oxm.impl.annotation.SimpleTypeSerializerClass serAnno = anno
161: .annotationType()
162: .getAnnotation(
163: de.schlund.pfixcore.oxm.impl.annotation.SimpleTypeSerializerClass.class);
164: Class<? extends SimpleTypeSerializer> serClass = serAnno
165: .value();
166: SimpleTypeSerializer serializer = serClass
167: .newInstance();
168: if (AnnotationAware.class
169: .isAssignableFrom(serClass)) {
170: AnnotationAware aa = (AnnotationAware) serializer;
171: aa.setAnnotation(anno);
172: }
173: simpleSerializers.put(prop, serializer);
174: } else if (anno
175: .annotationType()
176: .isAnnotationPresent(
177: de.schlund.pfixcore.oxm.impl.annotation.ComplexTypeSerializerClass.class)) {
178: de.schlund.pfixcore.oxm.impl.annotation.ComplexTypeSerializerClass serAnno = anno
179: .annotationType()
180: .getAnnotation(
181: de.schlund.pfixcore.oxm.impl.annotation.ComplexTypeSerializerClass.class);
182: Class<? extends ComplexTypeSerializer> serClass = serAnno
183: .value();
184: ComplexTypeSerializer serializer = serClass
185: .newInstance();
186: if (AnnotationAware.class
187: .isAssignableFrom(serClass)) {
188: AnnotationAware aa = (AnnotationAware) serializer;
189: aa.setAnnotation(anno);
190: }
191: complexSerializers.put(prop, serializer);
192: }
193: }
194: }
195: Field field = beanDesc.getDirectAccessField(prop);
196: if (field != null) {
197: Annotation[] annos = field.getAnnotations();
198: for (Annotation anno : annos) {
199: if (anno
200: .annotationType()
201: .isAnnotationPresent(
202: de.schlund.pfixcore.oxm.impl.annotation.SimpleTypeSerializerClass.class)) {
203: de.schlund.pfixcore.oxm.impl.annotation.SimpleTypeSerializerClass serAnno = anno
204: .annotationType()
205: .getAnnotation(
206: de.schlund.pfixcore.oxm.impl.annotation.SimpleTypeSerializerClass.class);
207: Class<? extends SimpleTypeSerializer> serClass = serAnno
208: .value();
209: SimpleTypeSerializer serializer = serClass
210: .newInstance();
211: if (AnnotationAware.class
212: .isAssignableFrom(serClass)) {
213: AnnotationAware aa = (AnnotationAware) serializer;
214: aa.setAnnotation(anno);
215: }
216: simpleSerializers.put(prop, serializer);
217: } else if (anno
218: .annotationType()
219: .isAnnotationPresent(
220: de.schlund.pfixcore.oxm.impl.annotation.ComplexTypeSerializerClass.class)) {
221: de.schlund.pfixcore.oxm.impl.annotation.ComplexTypeSerializerClass serAnno = anno
222: .annotationType()
223: .getAnnotation(
224: de.schlund.pfixcore.oxm.impl.annotation.ComplexTypeSerializerClass.class);
225: Class<? extends ComplexTypeSerializer> serClass = serAnno
226: .value();
227: ComplexTypeSerializer serializer = serClass
228: .newInstance();
229: if (AnnotationAware.class
230: .isAssignableFrom(serClass)) {
231: AnnotationAware aa = (AnnotationAware) serializer;
232: aa.setAnnotation(anno);
233: }
234: complexSerializers.put(prop, serializer);
235: }
236: }
237: }
238: } catch (Exception x) {
239: throw new RuntimeException(
240: "Error during serialization.", x);
241: }
242: }
243: customSimpleSerializerCache.put(clazz, simpleSerializers);
244: customComplexSerializerCache.put(clazz, complexSerializers);
245: }
246: }
|