001    /*
002     * JBoss DNA (http://www.jboss.org/dna)
003     * See the COPYRIGHT.txt file distributed with this work for information
004     * regarding copyright ownership.  Some portions may be licensed
005     * to Red Hat, Inc. under one or more contributor license agreements.
006     * See the AUTHORS.txt file in the distribution for a full listing of 
007     * individual contributors. 
008     *
009     * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
010     * is licensed to you under the terms of the GNU Lesser General Public License as
011     * published by the Free Software Foundation; either version 2.1 of
012     * the License, or (at your option) any later version.
013     *
014     * JBoss DNA is distributed in the hope that it will be useful,
015     * but WITHOUT ANY WARRANTY; without even the implied warranty of
016     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017     * Lesser General Public License for more details.
018     *
019     * You should have received a copy of the GNU Lesser General Public
020     * License along with this software; if not, write to the Free
021     * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
022     * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
023     */
024    package org.jboss.dna.sequencer.java;
025    
026    import java.io.IOException;
027    import java.io.InputStream;
028    import java.util.List;
029    import org.jboss.dna.graph.property.NameFactory;
030    import org.jboss.dna.graph.property.Path;
031    import org.jboss.dna.graph.property.PathFactory;
032    import org.jboss.dna.graph.sequencer.SequencerContext;
033    import org.jboss.dna.graph.sequencer.SequencerOutput;
034    import org.jboss.dna.graph.sequencer.StreamSequencer;
035    import org.jboss.dna.sequencer.java.metadata.AnnotationMetadata;
036    import org.jboss.dna.sequencer.java.metadata.ArrayTypeFieldMetadata;
037    import org.jboss.dna.sequencer.java.metadata.ClassMetadata;
038    import org.jboss.dna.sequencer.java.metadata.ConstructorMetadata;
039    import org.jboss.dna.sequencer.java.metadata.FieldMetadata;
040    import org.jboss.dna.sequencer.java.metadata.ImportMetadata;
041    import org.jboss.dna.sequencer.java.metadata.ImportOnDemandMetadata;
042    import org.jboss.dna.sequencer.java.metadata.JavaMetadata;
043    import org.jboss.dna.sequencer.java.metadata.MarkerAnnotationMetadata;
044    import org.jboss.dna.sequencer.java.metadata.MethodMetadata;
045    import org.jboss.dna.sequencer.java.metadata.MethodTypeMemberMetadata;
046    import org.jboss.dna.sequencer.java.metadata.ModifierMetadata;
047    import org.jboss.dna.sequencer.java.metadata.NormalAnnotationMetadata;
048    import org.jboss.dna.sequencer.java.metadata.PackageMetadata;
049    import org.jboss.dna.sequencer.java.metadata.ParameterizedTypeFieldMetadata;
050    import org.jboss.dna.sequencer.java.metadata.PrimitiveFieldMetadata;
051    import org.jboss.dna.sequencer.java.metadata.QualifiedTypeFieldMetadata;
052    import org.jboss.dna.sequencer.java.metadata.SimpleTypeFieldMetadata;
053    import org.jboss.dna.sequencer.java.metadata.SingleImportMetadata;
054    import org.jboss.dna.sequencer.java.metadata.SingleMemberAnnotationMetadata;
055    import org.jboss.dna.sequencer.java.metadata.TypeMetadata;
056    import org.jboss.dna.sequencer.java.metadata.Variable;
057    
058    /**
059     * A Java sequencer that processes a compilation unit, extracts the meta data for the compilation unit, and then writes these
060     * informations to the repository.
061     * <p>
062     * The structural representation of the informations from the compilation unit looks like this:
063     * <ul>
064     * <li><strong>java:compilationUnit</strong> node of type <code>java:compilationUnit</code>
065     * <ul>
066     * <li> <strong>java:package</strong> - optional child node that represents the package child node of the compilation unit.
067     * <ul>
068     * <li> <strong>java:packageDeclaration</strong> - the package declaration.
069     * <ul>
070     * <li><strong>java:packageName</strong></li> - the package name.
071     * </ul>
072     * </li>
073     * </ul>
074     * </li>
075     * <li> <strong>java:import</strong> - optional child node that represents the import declaration of the compilation unit
076     * <ul>
077     * <li> <strong>java:importDeclaration</strong> - the import declaration
078     * <ul>
079     * <li><strong>java:singleImport</strong>
080     * <ul>
081     * <li> <strong>java:singleTypeImportDeclaration</strong>
082     * <ul>
083     * <li> <strong>java:singleTypeImportkeyword</strong> - the keyword "import"
084     * <li><strong>java:singleImportName</strong></li> - the name of a single import. </li>
085     * </ul>
086     * </li>
087     * </ul>
088     * </li>
089     * <li><strong>java:importOnDemand</strong>
090     * <li> <strong>java:typeImportOnDemandDeclaration</strong>
091     * <ul>
092     * <li> <strong>java:onDemandImportKeyword</strong> - the keyword "import"
093     * <li><strong>java:onDemandImportName</strong></li> - the name of the on demand import. </li>
094     * </ul>
095     * </li>
096     * </li>
097     * </ul>
098     * </li>
099     * </ul>
100     * </li>
101     * <li><strong>java:unitType</strong> - optional child node that represents the top level type (class, interface, enum,
102     * annotation) declaration of the compilation unit</li>
103     * <ul>
104     * <li> <strong>java:classDeclaration</strong> - optional child node that represents the class declaration of the compilation
105     * unit
106     * <ul>
107     * <li> <strong>java:normalClass</strong> - the normal class.
108     * <ul>
109     * <li> <strong>java:normalClassDeclaration</strong> - the normal class declaration
110     * <ul>
111     * <li> <strong>java:modifier</strong> - modifier child node.
112     * <ul>
113     * <li><strong>java:modifierDeclaration</strong> - the modifier declaration.
114     * <ul>
115     * <li><strong>java:modifierName</strong> - modifier name.</li>
116     * </ul>
117     * </li>
118     * </ul>
119     * </li>
120     * <li> <strong>java:normalClassName</strong> - class name.</li>
121     * <li> <strong>java:field</strong> - field child node.
122     * <ul>
123     * <li><strong>java:fieldType</strong> - field type child node.
124     * <ul>
125     * <li><strong>java:type</strong> - type child node.
126     * <ul>
127     * <li>[java:primitiveType, java:simpleType, java:parameterizedType] - can be primitive type or simple type and or parameterized
128     * type<.</li>
129     * </ul>
130     * </li>
131     * </ul>
132     * </li>
133     * </ul>
134     * </li>
135     * <li> <strong>java:constructor</strong> - the constructor child node
136     * <ul>
137     * <li><strong>java:constructorDeclaration</strong> - the constructor declaration.
138     * <ul>
139     * <li><strong>java:constructorName</strong> - constructor name. </li>
140     * <li><strong>java:modifier </strong> - the modifier child node.</li> +
141     * <li><strong>java:parameter </strong> - the parameter child node</li>
142     * </ul>
143     * </li>
144     * </ul>
145     * </li>
146     * <li> <strong>java:method</strong> - method child node.
147     * <ul>
148     * <li></strong>java:methodDeclaration</strong> - method declaration.
149     * <ul>
150     * <li><strong>java:methodName </strong> - method name. </li>
151     * <li><strong>java:modifier </strong> - the modifier child node.</li> +
152     * <li><strong>java:resultType </strong> - the result type child node </li> +
153     * <li><strong>java:parameter </strong> - the parameter child node</li>
154     * </ul>
155     * </li>
156     * </ul>
157     * </li>
158     * </ul>
159     * </li>
160     * </ul>
161     * </li>
162     * </ul>
163     * </li>
164     * </ul>
165     * </li>
166     * </ul>
167     * </p>
168     * 
169     * @author Serge Pagop
170     * @author John Verhaeg
171     */
172    public class JavaMetadataSequencer implements JavaSourceCndDefinition, StreamSequencer {
173    
174        /**
175         * {@inheritDoc}
176         * 
177         * @see org.jboss.dna.graph.sequencer.StreamSequencer#sequence(java.io.InputStream,
178         *      org.jboss.dna.graph.sequencer.SequencerOutput, org.jboss.dna.graph.sequencer.SequencerContext)
179         */
180        public void sequence( InputStream stream,
181                              SequencerOutput output,
182                              SequencerContext context ) {
183            JavaMetadata javaMetadata = null;
184            NameFactory nameFactory = context.getValueFactories().getNameFactory();
185            PathFactory pathFactory = context.getValueFactories().getPathFactory();
186    
187            try {
188                javaMetadata = JavaMetadata.instance(stream, JavaMetadataUtil.length(stream), null);
189            } catch (IOException e) {
190                e.printStackTrace();
191                return;
192            }
193            if (javaMetadata != null) {
194                Path javaCompilationUnitNode = pathFactory.create(JAVA_COMPILATION_UNIT_NODE);
195                output.setProperty(javaCompilationUnitNode,
196                                   nameFactory.create(JAVA_COMPILATION_UNIT_PRIMARY_TYPE),
197                                   "java:compilationUnit");
198    
199                // sequence package declaration of a unit.
200                PackageMetadata packageMetadata = javaMetadata.getPackageMetadata();
201                if (packageMetadata != null) {
202                    String packageName = packageMetadata.getName();
203                    if (packageName != null && packageName.length() != 0) {
204    
205                        Path javaPackageDeclarationChildNode = pathFactory.create(JAVA_COMPILATION_UNIT_NODE + SLASH
206                                                                                  + JAVA_PACKAGE_CHILD_NODE + SLASH
207                                                                                  + JAVA_PACKAGE_DECLARATION_CHILD_NODE);
208                        output.setProperty(javaPackageDeclarationChildNode,
209                                           nameFactory.create(JAVA_PACKAGE_NAME),
210                                           javaMetadata.getPackageMetadata().getName());
211                    }
212    
213                    int markerAnnotationIndex = 1;
214                    int singleAnnatationIndex = 1;
215                    int normalAnnotationIndex = 1;
216                    for (AnnotationMetadata annotationMetadata : packageMetadata.getAnnotationMetada()) {
217                        if (annotationMetadata instanceof MarkerAnnotationMetadata) {
218                            MarkerAnnotationMetadata markerAnnotationMetadata = (MarkerAnnotationMetadata)annotationMetadata;
219                            Path markerAnnotationChildNode = pathFactory.create(JAVA_COMPILATION_UNIT_NODE + SLASH
220                                                                                + JAVA_PACKAGE_CHILD_NODE + SLASH
221                                                                                + JAVA_PACKAGE_DECLARATION_CHILD_NODE + SLASH
222                                                                                + JAVA_ANNOTATION_CHILD_NODE + SLASH
223                                                                                + JAVA_ANNOTATION_DECLARATION_CHILD_NODE + SLASH
224                                                                                + JAVA_ANNOTATION_TYPE_CHILD_NODE + SLASH
225                                                                                + JAVA_MARKER_ANNOTATION_CHILD_NODE + "["
226                                                                                + markerAnnotationIndex + "]");
227                            output.setProperty(markerAnnotationChildNode,
228                                               nameFactory.create(JAVA_MARKER_ANNOTATION_NAME),
229                                               markerAnnotationMetadata.getName());
230                            markerAnnotationIndex++;
231                        }
232                        if (annotationMetadata instanceof SingleMemberAnnotationMetadata) {
233                            SingleMemberAnnotationMetadata singleMemberAnnotationMetadata = (SingleMemberAnnotationMetadata)annotationMetadata;
234                            Path singleMemberAnnotationChildNode = pathFactory.create(JAVA_COMPILATION_UNIT_NODE + SLASH
235                                                                                      + JAVA_PACKAGE_CHILD_NODE + SLASH
236                                                                                      + JAVA_PACKAGE_DECLARATION_CHILD_NODE + SLASH
237                                                                                      + JAVA_ANNOTATION_CHILD_NODE + SLASH
238                                                                                      + JAVA_ANNOTATION_DECLARATION_CHILD_NODE
239                                                                                      + SLASH + JAVA_ANNOTATION_TYPE_CHILD_NODE
240                                                                                      + SLASH
241                                                                                      + JAVA_SINGLE_ELEMENT_ANNOTATION_CHILD_NODE
242                                                                                      + "[" + singleAnnatationIndex + "]");
243                            output.setProperty(singleMemberAnnotationChildNode,
244                                               nameFactory.create(JAVA_SINGLE_ANNOTATION_NAME),
245                                               singleMemberAnnotationMetadata.getName());
246                            singleAnnatationIndex++;
247                        }
248                        if (annotationMetadata instanceof NormalAnnotationMetadata) {
249                            NormalAnnotationMetadata normalAnnotationMetadata = (NormalAnnotationMetadata)annotationMetadata;
250                            Path normalAnnotationChildNode = pathFactory.create(JAVA_COMPILATION_UNIT_NODE + SLASH
251                                                                                + JAVA_PACKAGE_CHILD_NODE + SLASH
252                                                                                + JAVA_PACKAGE_DECLARATION_CHILD_NODE + SLASH
253                                                                                + JAVA_ANNOTATION_CHILD_NODE + SLASH
254                                                                                + JAVA_ANNOTATION_DECLARATION_CHILD_NODE + SLASH
255                                                                                + JAVA_ANNOTATION_TYPE_CHILD_NODE + SLASH
256                                                                                + JAVA_NORMAL_ANNOTATION_CHILD_NODE + "["
257                                                                                + normalAnnotationIndex + "]");
258    
259                            output.setProperty(normalAnnotationChildNode,
260                                               nameFactory.create(JAVA_NORMALANNOTATION_NAME),
261                                               normalAnnotationMetadata.getName());
262                            normalAnnotationIndex++;
263                        }
264                    }
265                }
266    
267                // sequence import declarations of a unit
268                int importOnDemandIndex = 1;
269                int singleImportIndex = 1;
270                for (ImportMetadata importMetadata : javaMetadata.getImports()) {
271                    if (importMetadata instanceof ImportOnDemandMetadata) {
272                        ImportOnDemandMetadata importOnDemandMetadata = (ImportOnDemandMetadata)importMetadata;
273                        Path importOnDemandChildNode = pathFactory.create(JAVA_COMPILATION_UNIT_NODE + SLASH + JAVA_IMPORT_CHILD_NODE
274                                                                          + SLASH + JAVA_IMPORT_DECLARATION_CHILD_NODE + SLASH
275                                                                          + JAVA_ON_DEMAND_IMPORT_CHILD_NODE + SLASH
276                                                                          + JAVA_ON_DEMAND_IMPORT_TYPE_DECLARATION_CHILD_NODE + "["
277                                                                          + importOnDemandIndex + "]");
278                        output.setProperty(importOnDemandChildNode,
279                                           nameFactory.create(JAVA_ON_DEMAND_IMPORT_NAME),
280                                           importOnDemandMetadata.getName());
281                        importOnDemandIndex++;
282                    }
283                    if (importMetadata instanceof SingleImportMetadata) {
284                        SingleImportMetadata singleImportMetadata = (SingleImportMetadata)importMetadata;
285                        Path singleImportChildNode = pathFactory.create(JAVA_COMPILATION_UNIT_NODE + SLASH + JAVA_IMPORT_CHILD_NODE
286                                                                        + SLASH + JAVA_IMPORT_DECLARATION_CHILD_NODE + SLASH
287                                                                        + JAVA_SINGLE_IMPORT_CHILD_NODE + SLASH
288                                                                        + JAVA_SINGLE_IMPORT_TYPE_DECLARATION_CHILD_NODE + "["
289                                                                        + singleImportIndex + "]");
290                        output.setProperty(singleImportChildNode,
291                                           nameFactory.create(JAVA_SINGLE_IMPORT_NAME),
292                                           singleImportMetadata.getName());
293                        singleImportIndex++;
294                    }
295                }
296    
297                // sequence type declaration (class declaration) information
298                for (TypeMetadata typeMetadata : javaMetadata.getTypeMetadata()) {
299                    // class declaration
300                    if (typeMetadata instanceof ClassMetadata) {
301    
302                        String normalClassRootPath = JAVA_COMPILATION_UNIT_NODE + SLASH + JAVA_UNIT_TYPE_CHILD_NODE + SLASH
303                                                     + JAVA_CLASS_DECLARATION_CHILD_NODE + SLASH + JAVA_NORMAL_CLASS_CHILD_NODE
304                                                     + SLASH + JAVA_NORMAL_CLASS_DECLARATION_CHILD_NODE;
305    
306                        ClassMetadata classMetadata = (ClassMetadata)typeMetadata;
307                        Path classChildNode = pathFactory.create(normalClassRootPath);
308                        output.setProperty(classChildNode, nameFactory.create(JAVA_NORMAL_CLASS_NAME), classMetadata.getName());
309    
310                        // process modifiers of the class declaration
311                        List<ModifierMetadata> classModifiers = classMetadata.getModifiers();
312                        int modifierIndex = 1;
313                        for (ModifierMetadata modifierMetadata : classModifiers) {
314    
315                            Path classModifierChildNode = pathFactory.create(normalClassRootPath + SLASH + JAVA_MODIFIER_CHILD_NODE
316                                                                             + SLASH + JAVA_MODIFIER_DECLARATION_CHILD_NODE + "["
317                                                                             + modifierIndex + "]");
318    
319                            output.setProperty(classModifierChildNode,
320                                               nameFactory.create(JAVA_MODIFIER_NAME),
321                                               modifierMetadata.getName());
322                        }
323    
324                        // process fields of the class unit.
325                        int primitiveIndex = 1;
326                        int simpleIndex = 1;
327                        int parameterizedIndex = 1;
328                        int arrayIndex = 1;
329                        for (FieldMetadata fieldMetadata : classMetadata.getFields()) {
330                            String fieldMemberDataRootPath = JavaMetadataUtil.createPath(normalClassRootPath + SLASH
331                                                                                         + JAVA_FIELD_CHILD_NODE + SLASH
332                                                                                         + JAVA_FIELD_TYPE_CHILD_NODE + SLASH
333                                                                                         + JAVA_TYPE_CHILD_NODE);
334                            if (fieldMetadata instanceof PrimitiveFieldMetadata) {
335                                // primitive type
336                                PrimitiveFieldMetadata primitiveFieldMetadata = (PrimitiveFieldMetadata)fieldMetadata;
337                                String primitiveFieldRootPath = JavaMetadataUtil.createPathWithIndex(fieldMemberDataRootPath + SLASH
338                                                                                                     + JAVA_PRIMITIVE_TYPE_CHILD_NODE,
339                                                                                                     primitiveIndex);
340                                // type
341                                Path primitiveTypeChildNode = pathFactory.create(primitiveFieldRootPath);
342                                output.setProperty(primitiveTypeChildNode,
343                                                   nameFactory.create(JAVA_PRIMITIVE_TYPE_NAME),
344                                                   primitiveFieldMetadata.getType());
345                                // modifiers
346                                List<ModifierMetadata> modifiers = primitiveFieldMetadata.getModifiers();
347                                int primitiveModifierIndex = 1;
348                                for (ModifierMetadata modifierMetadata : modifiers) {
349                                    String modifierPath = JavaMetadataUtil.createPathWithIndex(primitiveFieldRootPath + SLASH
350                                                                                               + JAVA_MODIFIER_CHILD_NODE + SLASH
351                                                                                               + JAVA_MODIFIER_DECLARATION_CHILD_NODE,
352                                                                                               primitiveModifierIndex);
353                                    Path modifierChildNode = pathFactory.create(modifierPath);
354                                    output.setProperty(modifierChildNode,
355                                                       nameFactory.create(JAVA_MODIFIER_NAME),
356                                                       modifierMetadata.getName());
357                                    primitiveModifierIndex++;
358                                }
359                                // variables
360                                List<Variable> variables = primitiveFieldMetadata.getVariables();
361                                int primitiveVariableIndex = 1;
362                                for (Variable variable : variables) {
363                                    String variablePath = JavaMetadataUtil.createPathWithIndex(primitiveFieldRootPath + SLASH
364                                                                                               + JAVA_PRIMITIVE_TYPE_VARIABLE + SLASH
365                                                                                               + JAVA_VARIABLE,
366                                                                                               primitiveVariableIndex);
367                                    Path primitiveChildNode = pathFactory.create(variablePath);
368                                    VariableSequencer.sequenceTheVariable(output, nameFactory, variable, primitiveChildNode);
369                                    primitiveVariableIndex++;
370                                }
371                                primitiveIndex++;
372                            }
373    
374                            // Array type
375                            if (fieldMetadata instanceof ArrayTypeFieldMetadata) {
376                                ArrayTypeFieldMetadata arrayTypeFieldMetadata = (ArrayTypeFieldMetadata)fieldMetadata;
377                                String arrayTypeRootPath = JavaMetadataUtil.createPathWithIndex(fieldMemberDataRootPath + SLASH
378                                                                                                + JAVA_ARRAY_TYPE_CHILD_NODE,
379                                                                                                arrayIndex);
380                                ArrayTypeFieldMetadataSequencer.sequenceFieldMemberData(arrayTypeFieldMetadata,
381                                                                                        pathFactory,
382                                                                                        nameFactory,
383                                                                                        output,
384                                                                                        arrayTypeRootPath,
385                                                                                        arrayIndex);
386                                arrayIndex++;
387                            }
388    
389                            // Simple type
390                            if (fieldMetadata instanceof SimpleTypeFieldMetadata) {
391                                SimpleTypeFieldMetadata simpleTypeFieldMetadata = (SimpleTypeFieldMetadata)fieldMetadata;
392                                String simpleTypeFieldRootPath = JavaMetadataUtil.createPathWithIndex(JAVA_COMPILATION_UNIT_NODE
393                                                                                                      + SLASH
394                                                                                                      + JAVA_UNIT_TYPE_CHILD_NODE
395                                                                                                      + SLASH
396                                                                                                      + JAVA_CLASS_DECLARATION_CHILD_NODE
397                                                                                                      + SLASH
398                                                                                                      + JAVA_NORMAL_CLASS_CHILD_NODE
399                                                                                                      + SLASH
400                                                                                                      + JAVA_NORMAL_CLASS_DECLARATION_CHILD_NODE
401                                                                                                      + SLASH + JAVA_FIELD_CHILD_NODE
402                                                                                                      + SLASH
403                                                                                                      + JAVA_FIELD_TYPE_CHILD_NODE
404                                                                                                      + SLASH + JAVA_TYPE_CHILD_NODE
405                                                                                                      + SLASH
406                                                                                                      + JAVA_SIMPLE_TYPE_CHILD_NODE,
407                                                                                                      simpleIndex);
408                                Path simpleTypeFieldChildNode = pathFactory.create(simpleTypeFieldRootPath);
409                                output.setProperty(simpleTypeFieldChildNode,
410                                                   nameFactory.create(JAVA_SIMPLE_TYPE_NAME),
411                                                   simpleTypeFieldMetadata.getType());
412    
413                                // Simple type modifies
414                                List<ModifierMetadata> simpleModifiers = simpleTypeFieldMetadata.getModifiers();
415                                int simpleTypeModifierIndex = 1;
416                                for (ModifierMetadata modifierMetadata : simpleModifiers) {
417                                    String simpleTypeModifierPath = JavaMetadataUtil.createPathWithIndex(simpleTypeFieldRootPath
418                                                                                                         + SLASH
419                                                                                                         + JAVA_SIMPLE_TYPE_MODIFIER_CHILD_NODE
420                                                                                                         + SLASH
421                                                                                                         + JAVA_MODIFIER_DECLARATION_CHILD_NODE,
422                                                                                                         simpleTypeModifierIndex);
423                                    Path simpleTypeModifierChildNode = pathFactory.create(simpleTypeModifierPath);
424                                    output.setProperty(simpleTypeModifierChildNode,
425                                                       nameFactory.create(JAVA_MODIFIER_NAME),
426                                                       modifierMetadata.getName());
427                                    simpleTypeModifierIndex++;
428                                }
429    
430                                // Simple type variables
431                                List<Variable> variables = simpleTypeFieldMetadata.getVariables();
432                                int simpleTypeVariableIndex = 1;
433                                for (Variable variable : variables) {
434                                    String variablePath = JavaMetadataUtil.createPathWithIndex(simpleTypeFieldRootPath + SLASH
435                                                                                               + JAVA_SIMPLE_TYPE_VARIABLE + SLASH
436                                                                                               + JAVA_VARIABLE,
437                                                                                               simpleTypeVariableIndex);
438                                    Path primitiveChildNode = pathFactory.create(variablePath);
439                                    VariableSequencer.sequenceTheVariable(output, nameFactory, variable, primitiveChildNode);
440                                    simpleTypeVariableIndex++;
441                                }
442    
443                                simpleIndex++;
444                            }
445    
446                            // Qualified type
447                            if (fieldMetadata instanceof QualifiedTypeFieldMetadata) {
448                                @SuppressWarnings( "unused" )
449                                QualifiedTypeFieldMetadata qualifiedTypeFieldMetadata = (QualifiedTypeFieldMetadata)fieldMetadata;
450                            }
451    
452                            // Parameterized type
453                            if (fieldMetadata instanceof ParameterizedTypeFieldMetadata) {
454                                ParameterizedTypeFieldMetadata parameterizedTypeFieldMetadata = (ParameterizedTypeFieldMetadata)fieldMetadata;
455                                String parameterizedTypeFieldRootPath = ParameterizedTypeFieldMetadataSequencer.getParameterizedTypeFieldRootPath(parameterizedIndex);
456                                ParameterizedTypeFieldMetadataSequencer.sequenceTheParameterizedTypeName(parameterizedTypeFieldMetadata,
457                                                                                                         parameterizedTypeFieldRootPath,
458                                                                                                         pathFactory,
459                                                                                                         nameFactory,
460                                                                                                         output);
461                                // Parameterized type modifiers
462                                List<ModifierMetadata> parameterizedTypeModifiers = parameterizedTypeFieldMetadata.getModifiers();
463                                int parameterizedTypeModifierIndex = 1;
464                                for (ModifierMetadata modifierMetadata : parameterizedTypeModifiers) {
465                                    String parameterizedTypeModifierPath = ParameterizedTypeFieldMetadataSequencer.getParameterizedTypeFieldRModifierPath(parameterizedTypeFieldRootPath,
466                                                                                                                                                          parameterizedTypeModifierIndex);
467                                    ParameterizedTypeFieldMetadataSequencer.sequenceTheParameterizedTypeModifier(modifierMetadata,
468                                                                                                                 parameterizedTypeModifierPath,
469                                                                                                                 pathFactory,
470                                                                                                                 nameFactory,
471                                                                                                                 output);
472                                    parameterizedTypeModifierIndex++;
473                                }
474                                // Parameterized type variables
475                                List<Variable> parameterizedTypeVariables = parameterizedTypeFieldMetadata.getVariables();
476                                int parameterizedTypeVariableIndex = 1;
477                                for (Variable variable : parameterizedTypeVariables) {
478    
479                                    Path parameterizedTypeVariableChildNode = ParameterizedTypeFieldMetadataSequencer.getParameterizedTypeFieldVariablePath(pathFactory,
480                                                                                                                                                            parameterizedTypeFieldRootPath,
481                                                                                                                                                            parameterizedTypeVariableIndex);
482                                    VariableSequencer.sequenceTheVariable(output,
483                                                                          nameFactory,
484                                                                          variable,
485                                                                          parameterizedTypeVariableChildNode);
486                                    parameterizedTypeVariableIndex++;
487                                }
488    
489                                parameterizedIndex++;
490                            }
491    
492                        }
493    
494                        // process methods of the unit.
495                        List<MethodMetadata> methods = classMetadata.getMethods();
496                        int methodIndex = 1;
497                        int constructorIndex = 1;
498                        for (MethodMetadata methodMetadata : methods) {
499                            if (methodMetadata.isContructor()) {
500                                // process constructor
501                                ConstructorMetadata constructorMetadata = (ConstructorMetadata)methodMetadata;
502                                String constructorRootPath = JavaMetadataUtil.createPathWithIndex(JAVA_COMPILATION_UNIT_NODE
503                                                                                                  + SLASH
504                                                                                                  + JAVA_UNIT_TYPE_CHILD_NODE
505                                                                                                  + SLASH
506                                                                                                  + JAVA_CLASS_DECLARATION_CHILD_NODE
507                                                                                                  + SLASH
508                                                                                                  + JAVA_NORMAL_CLASS_CHILD_NODE
509                                                                                                  + SLASH
510                                                                                                  + JAVA_NORMAL_CLASS_DECLARATION_CHILD_NODE
511                                                                                                  + SLASH
512                                                                                                  + JAVA_CONSTRUCTOR_CHILD_NODE
513                                                                                                  + SLASH
514                                                                                                  + JAVA_CONSTRUCTOR_DECLARATION_CHILD_NODE,
515                                                                                                  constructorIndex);
516                                Path constructorChildNode = pathFactory.create(constructorRootPath);
517                                output.setProperty(constructorChildNode,
518                                                   nameFactory.create(JAVA_CONSTRUCTOR_NAME),
519                                                   constructorMetadata.getName());
520                                List<ModifierMetadata> modifiers = constructorMetadata.getModifiers();
521                                // modifiers
522                                int constructorModifierIndex = 1;
523                                for (ModifierMetadata modifierMetadata : modifiers) {
524                                    String contructorModifierPath = JavaMetadataUtil.createPathWithIndex(constructorRootPath
525                                                                                                         + SLASH
526                                                                                                         + JAVA_MODIFIER_CHILD_NODE
527                                                                                                         + SLASH
528                                                                                                         + JAVA_MODIFIER_DECLARATION_CHILD_NODE,
529                                                                                                         constructorModifierIndex);
530    
531                                    Path constructorModifierChildNode = pathFactory.create(contructorModifierPath);
532                                    output.setProperty(constructorModifierChildNode,
533                                                       nameFactory.create(JAVA_MODIFIER_NAME),
534                                                       modifierMetadata.getName());
535                                    constructorModifierIndex++;
536                                }
537    
538                                // constructor parameters
539                                int constructorParameterIndex = 1;
540                                for (FieldMetadata fieldMetadata : constructorMetadata.getParameters()) {
541    
542                                    String constructorParameterRootPath = JavaMetadataUtil.createPathWithIndex(constructorRootPath
543                                                                                                               + SLASH
544                                                                                                               + JAVA_PARAMETER
545                                                                                                               + SLASH
546                                                                                                               + JAVA_FORMAL_PARAMETER,
547                                                                                                               constructorParameterIndex);
548                                    // primitive type
549                                    if (fieldMetadata instanceof PrimitiveFieldMetadata) {
550    
551                                        PrimitiveFieldMetadata primitiveMetadata = (PrimitiveFieldMetadata)fieldMetadata;
552                                        String constructPrimitiveFormalParamRootPath = MethodMetadataSequencer.createMethodParamRootPath(constructorParameterRootPath);
553                                        // type
554                                        Path constructorPrimitiveTypeParamChildNode = pathFactory.create(constructPrimitiveFormalParamRootPath);
555                                        output.setProperty(constructorPrimitiveTypeParamChildNode,
556                                                           nameFactory.create(JAVA_PRIMITIVE_TYPE_NAME),
557                                                           primitiveMetadata.getType());
558    
559                                        Path constructorPrimitiveParamChildNode = MethodMetadataSequencer.createMethodParamPath(pathFactory,
560                                                                                                                                constructPrimitiveFormalParamRootPath);
561                                        // variables
562                                        for (Variable variable : primitiveMetadata.getVariables()) {
563                                            VariableSequencer.sequenceTheVariable(output,
564                                                                                  nameFactory,
565                                                                                  variable,
566                                                                                  constructorPrimitiveParamChildNode);
567                                        }
568                                    }
569                                    // Simple type
570                                    if (fieldMetadata instanceof SimpleTypeFieldMetadata) {
571                                        SimpleTypeFieldMetadata simpleTypeFieldMetadata = (SimpleTypeFieldMetadata)fieldMetadata;
572                                        SimpleTypeMetadataSequencer.sequenceMethodFormalParam(output,
573                                                                                              nameFactory,
574                                                                                              pathFactory,
575                                                                                              simpleTypeFieldMetadata,
576                                                                                              constructorParameterRootPath);
577    
578                                    }
579                                    // parameterized type
580                                    if (fieldMetadata instanceof ParameterizedTypeFieldMetadata) {
581                                        @SuppressWarnings( "unused" )
582                                        ParameterizedTypeFieldMetadata parameterizedTypeFieldMetadata = (ParameterizedTypeFieldMetadata)fieldMetadata;
583    
584                                    }
585                                    // TODO support for more types
586    
587                                    constructorParameterIndex++;
588                                }
589    
590                                constructorIndex++;
591                            } else {
592    
593                                // normal method
594                                MethodTypeMemberMetadata methodTypeMemberMetadata = (MethodTypeMemberMetadata)methodMetadata;
595                                String methodRootPath = JavaMetadataUtil.createPathWithIndex(JAVA_COMPILATION_UNIT_NODE
596                                                                                             + SLASH
597                                                                                             + JAVA_UNIT_TYPE_CHILD_NODE
598                                                                                             + SLASH
599                                                                                             + JAVA_CLASS_DECLARATION_CHILD_NODE
600                                                                                             + SLASH
601                                                                                             + JAVA_NORMAL_CLASS_CHILD_NODE
602                                                                                             + SLASH
603                                                                                             + JAVA_NORMAL_CLASS_DECLARATION_CHILD_NODE
604                                                                                             + SLASH + JAVA_METHOD_CHILD_NODE + SLASH
605                                                                                             + JAVA_METHOD_DECLARATION_CHILD_NODE,
606                                                                                             methodIndex);
607                                Path methodChildNode = pathFactory.create(methodRootPath);
608                                output.setProperty(methodChildNode,
609                                                   nameFactory.create(JAVA_METHOD_NAME),
610                                                   methodTypeMemberMetadata.getName());
611    
612                                // method modifiers
613                                int methodModierIndex = 1;
614                                for (ModifierMetadata modifierMetadata : methodTypeMemberMetadata.getModifiers()) {
615                                    String methodModifierPath = JavaMetadataUtil.createPathWithIndex(methodRootPath
616                                                                                                     + SLASH
617                                                                                                     + JAVA_MODIFIER_CHILD_NODE
618                                                                                                     + SLASH
619                                                                                                     + JAVA_MODIFIER_DECLARATION_CHILD_NODE,
620                                                                                                     methodModierIndex);
621                                    Path methodModifierChildNode = pathFactory.create(methodModifierPath);
622                                    output.setProperty(methodModifierChildNode,
623                                                       nameFactory.create(JAVA_MODIFIER_NAME),
624                                                       modifierMetadata.getName());
625                                    methodModierIndex++;
626                                }
627    
628                                int methodParameterIndex = 1;
629                                for (FieldMetadata fieldMetadata : methodMetadata.getParameters()) {
630    
631                                    String methodParamRootPath = JavaMetadataUtil.createPathWithIndex(methodRootPath + SLASH
632                                                                                                      + JAVA_PARAMETER + SLASH
633                                                                                                      + JAVA_FORMAL_PARAMETER,
634                                                                                                      methodParameterIndex);
635    
636                                    if (fieldMetadata instanceof PrimitiveFieldMetadata) {
637    
638                                        PrimitiveFieldMetadata primitive = (PrimitiveFieldMetadata)fieldMetadata;
639    
640                                        String methodPrimitiveFormalParamRootPath = JavaMetadataUtil.createPath(methodParamRootPath
641                                                                                                                + SLASH
642                                                                                                                + JAVA_TYPE_CHILD_NODE
643                                                                                                                + SLASH
644                                                                                                                + JAVA_PRIMITIVE_TYPE_CHILD_NODE);
645    
646                                        Path methodParamChildNode = MethodMetadataSequencer.createMethodParamPath(pathFactory,
647                                                                                                                  methodPrimitiveFormalParamRootPath);
648                                        // variables
649                                        for (Variable variable : primitive.getVariables()) {
650                                            VariableSequencer.sequenceTheVariable(output, nameFactory, variable, methodParamChildNode);
651                                        }
652                                        // type
653                                        Path methodPrimitiveTypeParamChildNode = pathFactory.create(methodPrimitiveFormalParamRootPath);
654                                        output.setProperty(methodPrimitiveTypeParamChildNode,
655                                                           nameFactory.create(JAVA_PRIMITIVE_TYPE_NAME),
656                                                           primitive.getType());
657    
658                                    }
659    
660                                    if (fieldMetadata instanceof SimpleTypeFieldMetadata) {
661                                        SimpleTypeFieldMetadata simpleTypeFieldMetadata = (SimpleTypeFieldMetadata)fieldMetadata;
662                                        SimpleTypeMetadataSequencer.sequenceMethodFormalParam(output,
663                                                                                              nameFactory,
664                                                                                              pathFactory,
665                                                                                              simpleTypeFieldMetadata,
666                                                                                              methodParamRootPath);
667                                    }
668                                    if (fieldMetadata instanceof ArrayTypeFieldMetadata) {
669                                        ArrayTypeFieldMetadata arrayTypeFieldMetadata = (ArrayTypeFieldMetadata)fieldMetadata;
670                                        ArrayTypeFieldMetadataSequencer.sequenceMethodFormalParam(output,
671                                                                                                  nameFactory,
672                                                                                                  pathFactory,
673                                                                                                  arrayTypeFieldMetadata,
674                                                                                                  methodParamRootPath);
675    
676                                    }
677    
678                                    // TODO parameter reference types
679    
680                                    methodParameterIndex++;
681                                }
682    
683                                // method return type
684                                FieldMetadata methodReturnType = methodTypeMemberMetadata.getReturnType();
685    
686                                if (methodReturnType instanceof PrimitiveFieldMetadata) {
687                                    PrimitiveFieldMetadata methodReturnPrimitiveType = (PrimitiveFieldMetadata)methodReturnType;
688                                    String methodReturnPrimitiveTypePath = JavaMetadataUtil.createPath(methodRootPath
689                                                                                                       + SLASH
690                                                                                                       + JAVA_RETURN_TYPE
691                                                                                                       + SLASH
692                                                                                                       + JAVA_PRIMITIVE_TYPE_CHILD_NODE);
693                                    Path methodReturnPrimitiveTypeChildNode = pathFactory.create(methodReturnPrimitiveTypePath);
694                                    output.setProperty(methodReturnPrimitiveTypeChildNode,
695                                                       nameFactory.create(JAVA_PRIMITIVE_TYPE_NAME),
696                                                       methodReturnPrimitiveType.getType());
697    
698                                }
699                                if (methodReturnType instanceof SimpleTypeFieldMetadata) {
700                                    SimpleTypeFieldMetadata simpleTypeFieldMetadata = (SimpleTypeFieldMetadata)methodReturnType;
701                                    SimpleTypeMetadataSequencer.sequenceMethodReturnType(output,
702                                                                                         nameFactory,
703                                                                                         pathFactory,
704                                                                                         simpleTypeFieldMetadata,
705                                                                                         methodRootPath);
706                                }
707    
708                                // TODO method return reference type
709    
710                                methodIndex++;
711                            }
712                        }
713                    }
714                    // interface declaration
715    
716                    // enumeration declaration
717                }
718            }
719        }
720    }