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