1 package org.modeshape.sequencer.java;
2
3 import java.util.ArrayList;
4 import java.util.LinkedList;
5 import java.util.List;
6 import java.util.Map;
7 import org.modeshape.graph.JcrLexicon;
8 import org.modeshape.graph.property.DateTimeFactory;
9 import org.modeshape.graph.property.Path;
10 import org.modeshape.graph.property.PathFactory;
11 import org.modeshape.graph.property.Path.Segment;
12 import org.modeshape.graph.sequencer.SequencerOutput;
13 import org.modeshape.graph.sequencer.StreamSequencerContext;
14 import org.modeshape.sequencer.classfile.ClassFileSequencerLexicon;
15 import org.modeshape.sequencer.classfile.metadata.Visibility;
16 import org.modeshape.sequencer.java.metadata.AnnotationMetadata;
17 import org.modeshape.sequencer.java.metadata.EnumMetadata;
18 import org.modeshape.sequencer.java.metadata.FieldMetadata;
19 import org.modeshape.sequencer.java.metadata.InterfaceMetadata;
20 import org.modeshape.sequencer.java.metadata.JavaMetadata;
21 import org.modeshape.sequencer.java.metadata.MethodMetadata;
22 import org.modeshape.sequencer.java.metadata.TypeMetadata;
23
24
25
26
27
28 public class ClassSourceFileRecorder implements SourceFileRecorder {
29
30 public void record( StreamSequencerContext context,
31 SequencerOutput output,
32 JavaMetadata javaMetadata ) {
33
34 PathFactory pathFactory = pathFactoryFor(context);
35 DateTimeFactory dateFactory = dateFactoryFor(context);
36
37 writeJavaMetadata(output, pathFactory, dateFactory, javaMetadata);
38
39 }
40
41 private DateTimeFactory dateFactoryFor( StreamSequencerContext context ) {
42 return context.getValueFactories().getDateFactory();
43 }
44
45 private PathFactory pathFactoryFor( StreamSequencerContext context ) {
46 return context.getValueFactories().getPathFactory();
47 }
48
49 private Path pathFor( PathFactory pathFactory,
50 TypeMetadata tmd ) {
51 List<Segment> segments = new LinkedList<Segment>();
52
53 for (String segment : tmd.getName().split("\\.")) {
54 segments.add(pathFactory.createSegment(segment));
55 }
56
57 return pathFactory.createRelativePath(segments);
58 }
59
60 private void writeJavaMetadata( SequencerOutput output,
61 PathFactory pathFactory,
62 DateTimeFactory dateFactory,
63 JavaMetadata javaMetadata ) {
64
65 for (TypeMetadata typeMetadata : javaMetadata.getTypeMetadata()) {
66 writeClassMetadata(output, pathFactory, dateFactory, pathFor(pathFactory, typeMetadata), typeMetadata);
67 }
68 }
69
70 private void writeClassMetadata( SequencerOutput output,
71 PathFactory pathFactory,
72 DateTimeFactory dateFactory,
73 Path classPath,
74 TypeMetadata cmd ) {
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91 int numberOfMethods = cmd.getMethods().size();
92 List<MethodMetadata> methods = new ArrayList<MethodMetadata>(numberOfMethods);
93 List<MethodMetadata> ctors = new ArrayList<MethodMetadata>(numberOfMethods);
94
95 for (MethodMetadata method : cmd.getMethods()) {
96 if (method.isContructor()) {
97 ctors.add(method);
98 } else {
99 methods.add(method);
100 }
101 }
102
103 output.setProperty(classPath, ClassFileSequencerLexicon.NAME, cmd.getName());
104 output.setProperty(classPath, ClassFileSequencerLexicon.SEQUENCED_DATE, dateFactory.create());
105 String superClassName = cmd.getSuperClassName();
106 if (superClassName == null || superClassName.length() == 0) {
107 superClassName = Object.class.getCanonicalName();
108 }
109 output.setProperty(classPath, ClassFileSequencerLexicon.SUPER_CLASS_NAME, superClassName);
110 output.setProperty(classPath, ClassFileSequencerLexicon.VISIBILITY, visibilityFor(cmd).getDescription());
111 output.setProperty(classPath, ClassFileSequencerLexicon.ABSTRACT, cmd.hasModifierNamed("abstract"));
112 output.setProperty(classPath, ClassFileSequencerLexicon.INTERFACE, (cmd instanceof InterfaceMetadata));
113 output.setProperty(classPath, ClassFileSequencerLexicon.FINAL, cmd.hasModifierNamed("final"));
114 output.setProperty(classPath, ClassFileSequencerLexicon.STRICT_FP, cmd.hasModifierNamed("strictfp"));
115 output.setProperty(classPath, ClassFileSequencerLexicon.INTERFACES, cmd.getInterfaceNames().toArray());
116
117 Path constructorsPath = pathFactory.create(classPath, ClassFileSequencerLexicon.CONSTRUCTORS);
118 output.setProperty(constructorsPath, JcrLexicon.PRIMARY_TYPE, ClassFileSequencerLexicon.CONSTRUCTORS);
119 writeMethods(output, pathFactory, constructorsPath, ctors);
120
121 Path methodsPath = pathFactory.create(classPath, ClassFileSequencerLexicon.METHODS);
122 output.setProperty(methodsPath, JcrLexicon.PRIMARY_TYPE, ClassFileSequencerLexicon.METHODS);
123 writeMethods(output, pathFactory, methodsPath, methods);
124
125 writeFieldsNode(output, pathFactory, classPath, cmd.getFields());
126 writeAnnotationsNode(output, pathFactory, classPath, cmd.getAnnotations());
127
128 if (cmd instanceof EnumMetadata) {
129 output.setProperty(classPath, JcrLexicon.PRIMARY_TYPE, ClassFileSequencerLexicon.ENUM);
130
131 output.setProperty(classPath, ClassFileSequencerLexicon.ENUM_VALUES, ((EnumMetadata)cmd).getValues().toArray());
132 } else {
133 output.setProperty(classPath, JcrLexicon.PRIMARY_TYPE, ClassFileSequencerLexicon.CLASS);
134 }
135 }
136
137 private Visibility visibilityFor( TypeMetadata cmd ) {
138 if (cmd.hasModifierNamed("public")) return Visibility.PUBLIC;
139 if (cmd.hasModifierNamed("protected")) return Visibility.PROTECTED;
140 if (cmd.hasModifierNamed("private")) return Visibility.PRIVATE;
141
142 return Visibility.PACKAGE;
143 }
144
145 private Visibility visibilityFor( FieldMetadata cmd ) {
146 if (cmd.hasModifierNamed("public")) return Visibility.PUBLIC;
147 if (cmd.hasModifierNamed("protected")) return Visibility.PROTECTED;
148 if (cmd.hasModifierNamed("private")) return Visibility.PRIVATE;
149
150 return Visibility.PACKAGE;
151 }
152
153 private Visibility visibilityFor( MethodMetadata cmd ) {
154 if (cmd.hasModifierNamed("public")) return Visibility.PUBLIC;
155 if (cmd.hasModifierNamed("protected")) return Visibility.PROTECTED;
156 if (cmd.hasModifierNamed("private")) return Visibility.PRIVATE;
157
158 return Visibility.PACKAGE;
159 }
160
161 private void writeAnnotationsNode( SequencerOutput output,
162 PathFactory pathFactory,
163 Path parentPath,
164 List<AnnotationMetadata> annotations ) {
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179 Path annotationsPath = pathFactory.create(parentPath, ClassFileSequencerLexicon.ANNOTATIONS);
180 output.setProperty(annotationsPath, JcrLexicon.PRIMARY_TYPE, ClassFileSequencerLexicon.ANNOTATIONS);
181
182 for (AnnotationMetadata annotation : annotations) {
183 Path annotationPath = pathFactory.create(annotationsPath, annotation.getName());
184 output.setProperty(annotationPath, JcrLexicon.PRIMARY_TYPE, ClassFileSequencerLexicon.ANNOTATION);
185
186 for (Map.Entry<String, String> entry : annotation.getMemberValues().entrySet()) {
187 String key = entry.getKey();
188 if (key == null) key = "default";
189
190 Path annotationMemberPath = pathFactory.create(annotationPath, key);
191 output.setProperty(annotationMemberPath, JcrLexicon.PRIMARY_TYPE, ClassFileSequencerLexicon.ANNOTATION_MEMBER);
192 output.setProperty(annotationMemberPath, ClassFileSequencerLexicon.NAME, entry.getKey());
193 output.setProperty(annotationMemberPath, ClassFileSequencerLexicon.VALUE, entry.getValue());
194
195 }
196 }
197 }
198
199 private void writeFieldsNode( SequencerOutput output,
200 PathFactory pathFactory,
201 Path classPath,
202 List<FieldMetadata> fields ) {
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219 Path fieldsPath = pathFactory.create(classPath, ClassFileSequencerLexicon.FIELDS);
220 output.setProperty(fieldsPath, JcrLexicon.PRIMARY_TYPE, ClassFileSequencerLexicon.FIELDS);
221
222 for (FieldMetadata field : fields) {
223 Path fieldPath = pathFactory.create(fieldsPath, field.getName());
224
225 output.setProperty(fieldPath, JcrLexicon.PRIMARY_TYPE, ClassFileSequencerLexicon.FIELD);
226 output.setProperty(fieldPath, ClassFileSequencerLexicon.NAME, field.getName());
227 output.setProperty(fieldPath, ClassFileSequencerLexicon.TYPE_CLASS_NAME, field.getType());
228 output.setProperty(fieldPath, ClassFileSequencerLexicon.VISIBILITY, visibilityFor(field).getDescription());
229 output.setProperty(classPath, ClassFileSequencerLexicon.STATIC, field.hasModifierNamed("static"));
230 output.setProperty(classPath, ClassFileSequencerLexicon.FINAL, field.hasModifierNamed("final"));
231 output.setProperty(classPath, ClassFileSequencerLexicon.TRANSIENT, field.hasModifierNamed("transient"));
232 output.setProperty(classPath, ClassFileSequencerLexicon.VOLATILE, field.hasModifierNamed("volatile"));
233
234 writeAnnotationsNode(output, pathFactory, fieldPath, field.getAnnotations());
235
236 }
237 }
238
239 private void writeMethods( SequencerOutput output,
240 PathFactory pathFactory,
241 Path methodsPath,
242 List<MethodMetadata> methods ) {
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259 for (MethodMetadata method : methods) {
260 Path methodPath = pathFactory.create(methodsPath, method.getId());
261
262 output.setProperty(methodPath, JcrLexicon.PRIMARY_TYPE, ClassFileSequencerLexicon.METHOD);
263 output.setProperty(methodPath, ClassFileSequencerLexicon.NAME, method.getName());
264 output.setProperty(methodPath, ClassFileSequencerLexicon.RETURN_TYPE_CLASS_NAME, method.getReturnTypeName());
265 output.setProperty(methodPath, ClassFileSequencerLexicon.VISIBILITY, visibilityFor(method).getDescription());
266 output.setProperty(methodPath, ClassFileSequencerLexicon.STATIC, method.hasModifierNamed("static"));
267 output.setProperty(methodPath, ClassFileSequencerLexicon.FINAL, method.hasModifierNamed("final"));
268 output.setProperty(methodPath, ClassFileSequencerLexicon.ABSTRACT, method.hasModifierNamed("abstract"));
269 output.setProperty(methodPath, ClassFileSequencerLexicon.STRICT_FP, method.hasModifierNamed("strictfp"));
270 output.setProperty(methodPath, ClassFileSequencerLexicon.NATIVE, method.hasModifierNamed("native"));
271 output.setProperty(methodPath, ClassFileSequencerLexicon.SYNCHRONIZED, method.hasModifierNamed("synchronized"));
272 output.setProperty(methodPath, ClassFileSequencerLexicon.PARAMETERS, method.getParameterTypes().toArray());
273
274 writeAnnotationsNode(output, pathFactory, methodPath, method.getAnnotations());
275
276 }
277
278 }
279
280 }