1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.any23.validator;
19
20 import org.w3c.dom.Element;
21
22 import java.io.OutputStream;
23 import java.io.PrintStream;
24 import java.io.UnsupportedEncodingException;
25 import java.lang.annotation.Documented;
26 import java.lang.annotation.ElementType;
27 import java.lang.annotation.Retention;
28 import java.lang.annotation.RetentionPolicy;
29 import java.lang.annotation.Target;
30 import java.lang.reflect.Array;
31 import java.lang.reflect.Method;
32 import java.lang.reflect.Modifier;
33 import java.util.ArrayList;
34 import java.util.Collection;
35 import java.util.List;
36 import java.util.Locale;
37
38
39
40
41
42
43 public class XMLValidationReportSerializer implements ValidationReportSerializer {
44
45 @Override
46 public void serialize(ValidationReport vr, OutputStream os) throws SerializationException {
47 PrintStream ps;
48 try {
49 ps = new PrintStream(os, true, "UTF-8");
50 } catch (UnsupportedEncodingException e) {
51 throw new RuntimeException("Error serializing the OuputStream as UTF-8 encoding.", e);
52 }
53 try {
54 serializeObject(vr, ps);
55 } finally {
56 ps.flush();
57 }
58 }
59
60 private void serializeObject(Object o, PrintStream ps) throws SerializationException {
61 if (o == null) {
62 return;
63 }
64 final Class<? extends Object> oClass = o.getClass();
65 final String oClassName = getClassName(oClass);
66 ps.printf(Locale.ROOT, "<%s>%n", oClassName);
67 List<Method> getters = filterGetters(o.getClass());
68 if (getters.isEmpty()) {
69 ps.print(o.toString());
70 return;
71 }
72 for (Method getter : getters) {
73 serializeGetterValue(o, getter, ps);
74 }
75 ps.printf(Locale.ROOT, "</%s>%n", oClassName);
76 }
77
78 private String getClassName(Class<? extends Object> oClass) {
79 final NodeName nodeName = oClass.getAnnotation(NodeName.class);
80 if (nodeName != null) {
81 return nodeName.value();
82 }
83 final String simpleName = oClass.getSimpleName();
84 return Character.toLowerCase(simpleName.charAt(0)) + simpleName.substring(1);
85 }
86
87 private List<Method> filterGetters(Class<? extends Object> c) {
88 Method[] methods = c.getDeclaredMethods();
89 List<Method> filtered = new ArrayList<>();
90 for (Method method : methods) {
91 if (Modifier.isStatic(method.getModifiers())) {
92 continue;
93 }
94 final String methodName = method.getName();
95 if (method.getParameterTypes().length == 0 && ((methodName.length() > 3 && methodName.indexOf("get") == 0)
96 || (methodName.length() > 2 && methodName.indexOf("is") == 0))) {
97 filtered.add(method);
98 }
99 }
100 return filtered;
101 }
102
103 public void serializeGetterValue(Object o, Method m, PrintStream ps) throws SerializationException {
104 final Object value;
105 final String methodName = m.getName();
106 try {
107 value = m.invoke(o);
108 } catch (Exception e) {
109 throw new SerializationException(String.format(Locale.ROOT, "Error while reading method '%s'", methodName),
110 e);
111 }
112 final String property = getPropertyFromMethodName(methodName);
113 if (isManaged(value)) {
114 ps.printf(Locale.ROOT, "<%s>%n", property);
115 printObject(value, ps);
116 ps.printf(Locale.ROOT, "</%s>%n", property);
117 } else {
118 List<Method> getters = filterGetters(value.getClass());
119 for (Method getter : getters) {
120 serializeGetterValue(value, getter, ps);
121 }
122 }
123 }
124
125 private String getPropertyFromMethodName(String methodName) {
126 int i = methodName.indexOf("is");
127 if (i == 0) {
128 return Character.toLowerCase(methodName.charAt(2)) + methodName.substring(3);
129 }
130 return Character.toLowerCase(methodName.charAt(3)) + methodName.substring(4);
131 }
132
133 private void printObject(Object o, PrintStream ps) throws SerializationException {
134 if (o == null) {
135 return;
136 }
137 if (o instanceof Element) {
138 ps.print(o.toString());
139 return;
140 }
141 if (o instanceof Array) {
142 Object[] array = (Object[]) o;
143 if (array.length == 0) {
144 return;
145 }
146 for (Object a : array) {
147 serializeObject(a, ps);
148 }
149 return;
150 }
151 if (o instanceof Collection) {
152 Collection<?> collection = (Collection<?>) o;
153 if (collection.isEmpty()) {
154 return;
155 }
156 for (Object e : collection) {
157 serializeObject(e, ps);
158 }
159 return;
160 }
161 ps.print(o.toString());
162 }
163
164 private boolean isManaged(Object o) {
165 return o == null || o instanceof String || o.getClass().isPrimitive() || (o instanceof Collection)
166 || o instanceof Element;
167 }
168
169
170
171
172 @Documented
173 @Retention(RetentionPolicy.RUNTIME)
174 @Target(ElementType.TYPE)
175 public @interface NodeName {
176 String value();
177 }
178
179 }