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.util.ArrayList;
027    import java.util.List;
028    import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
029    import org.eclipse.jdt.core.dom.Annotation;
030    import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration;
031    import org.eclipse.jdt.core.dom.ArrayType;
032    import org.eclipse.jdt.core.dom.CompilationUnit;
033    import org.eclipse.jdt.core.dom.EnumDeclaration;
034    import org.eclipse.jdt.core.dom.FieldDeclaration;
035    import org.eclipse.jdt.core.dom.IExtendedModifier;
036    import org.eclipse.jdt.core.dom.ImportDeclaration;
037    import org.eclipse.jdt.core.dom.MarkerAnnotation;
038    import org.eclipse.jdt.core.dom.MethodDeclaration;
039    import org.eclipse.jdt.core.dom.Modifier;
040    import org.eclipse.jdt.core.dom.NormalAnnotation;
041    import org.eclipse.jdt.core.dom.PackageDeclaration;
042    import org.eclipse.jdt.core.dom.ParameterizedType;
043    import org.eclipse.jdt.core.dom.PrimitiveType;
044    import org.eclipse.jdt.core.dom.SimpleType;
045    import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
046    import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
047    import org.eclipse.jdt.core.dom.Type;
048    import org.eclipse.jdt.core.dom.TypeDeclaration;
049    import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
050    import org.jboss.dna.common.util.CheckArg;
051    import org.jboss.dna.sequencer.java.metadata.ArrayTypeFieldMetadata;
052    import org.jboss.dna.sequencer.java.metadata.ClassMetadata;
053    import org.jboss.dna.sequencer.java.metadata.ConstructorMetadata;
054    import org.jboss.dna.sequencer.java.metadata.FieldMetadata;
055    import org.jboss.dna.sequencer.java.metadata.ImportMetadata;
056    import org.jboss.dna.sequencer.java.metadata.ImportOnDemandMetadata;
057    import org.jboss.dna.sequencer.java.metadata.InterfaceMetadata;
058    import org.jboss.dna.sequencer.java.metadata.MarkerAnnotationMetadata;
059    import org.jboss.dna.sequencer.java.metadata.MethodMetadata;
060    import org.jboss.dna.sequencer.java.metadata.MethodTypeMemberMetadata;
061    import org.jboss.dna.sequencer.java.metadata.ModifierMetadata;
062    import org.jboss.dna.sequencer.java.metadata.NormalAnnotationMetadata;
063    import org.jboss.dna.sequencer.java.metadata.PackageMetadata;
064    import org.jboss.dna.sequencer.java.metadata.ParameterizedTypeFieldMetadata;
065    import org.jboss.dna.sequencer.java.metadata.PrimitiveFieldMetadata;
066    import org.jboss.dna.sequencer.java.metadata.SimpleTypeFieldMetadata;
067    import org.jboss.dna.sequencer.java.metadata.SingleImportMetadata;
068    import org.jboss.dna.sequencer.java.metadata.SingleMemberAnnotationMetadata;
069    import org.jboss.dna.sequencer.java.metadata.TypeMetadata;
070    import org.jboss.dna.sequencer.java.metadata.Variable;
071    
072    /**
073     * Abstract definition of a <code>JavaMetadata<code>. This class exposes some useful methods, that can
074     * be used to create meta data of a compilation unit. Methods can also separately be used.
075     * 
076     * @author Serge Pagop
077     */
078    public abstract class AbstractJavaMetadata {
079    
080        /**
081         * Create a set of <code>ImportMetadata</code> of a compilation unit.
082         * 
083         * @param unit - the compilation unit.
084         * @return all static import declarations from the compilation unit.
085         */
086        @SuppressWarnings( "unchecked" )
087        protected List<ImportMetadata> createImportMetadata( CompilationUnit unit ) {
088            List<ImportMetadata> metadata = new ArrayList<ImportMetadata>();
089            List<ImportDeclaration> imports = unit.imports();
090            if (!imports.isEmpty()) {
091                for (ImportDeclaration importDeclaration : imports) {
092                    if (importDeclaration.isOnDemand()) {
093                        // typeImportOnDemand and staticImportOnDemand
094                        ImportOnDemandMetadata onDemandMetadata = new ImportOnDemandMetadata();
095                        onDemandMetadata.setName(JavaMetadataUtil.getName(importDeclaration.getName()));
096                        metadata.add(onDemandMetadata);
097                    } else {
098                        // singleTypeImport and singleStaticImport
099                        SingleImportMetadata singleImportMetadata = new SingleImportMetadata();
100                        singleImportMetadata.setName(JavaMetadataUtil.getName(importDeclaration.getName()));
101                        metadata.add(singleImportMetadata);
102                    }
103    
104                }
105            }
106            return metadata;
107        }
108    
109        /**
110         * Create a <code>PackageMetadata</code> of a compilation unit.
111         * 
112         * @param unit - the compilation unit.
113         * @return the package meta data of a compilation unit.
114         */
115        @SuppressWarnings( "unchecked" )
116        protected PackageMetadata createPackageMetadata( CompilationUnit unit ) {
117            PackageMetadata packageMetadata = null;
118            List<Annotation> annotations = null;
119            PackageDeclaration packageDeclaration = unit.getPackage();
120            if (packageDeclaration != null) {
121                annotations = packageDeclaration.annotations();
122                packageMetadata = new PackageMetadata();
123                packageMetadata.setName(JavaMetadataUtil.getName(unit.getPackage().getName()));
124                if (!annotations.isEmpty()) {
125                    for (Object object : annotations) {
126    
127                        if (object instanceof NormalAnnotation) {
128                            NormalAnnotation normalAnnotation = (NormalAnnotation)object;
129                            NormalAnnotationMetadata normalAnnotationMetadata = new NormalAnnotationMetadata();
130                            normalAnnotationMetadata.setName(JavaMetadataUtil.getName(normalAnnotation.getTypeName()));
131                            normalAnnotationMetadata.setNormal(Boolean.TRUE);
132                            packageMetadata.getAnnotationMetada().add(normalAnnotationMetadata);
133                        }
134                        if (object instanceof MarkerAnnotation) {
135                            MarkerAnnotation markerAnnotation = (MarkerAnnotation)object;
136                            MarkerAnnotationMetadata markerAnnotationMetadata = new MarkerAnnotationMetadata();
137                            markerAnnotationMetadata.setName(JavaMetadataUtil.getName(markerAnnotation.getTypeName()));
138                            markerAnnotationMetadata.setMarker(Boolean.TRUE);
139                            packageMetadata.getAnnotationMetada().add(markerAnnotationMetadata);
140                        }
141                        if (object instanceof SingleMemberAnnotation) {
142                            SingleMemberAnnotation singleMemberAnnotation = (SingleMemberAnnotation)object;
143                            SingleMemberAnnotationMetadata singleMemberAnnotationMetadata = new SingleMemberAnnotationMetadata();
144                            singleMemberAnnotationMetadata.setName(JavaMetadataUtil.getName(singleMemberAnnotation.getTypeName()));
145                            singleMemberAnnotationMetadata.setSingle(Boolean.TRUE);
146                            packageMetadata.getAnnotationMetada().add(singleMemberAnnotationMetadata);
147    
148                        }
149                    }
150                }
151            }
152            return packageMetadata;
153        }
154    
155        /**
156         * Create a list with all top level types of a compilation unit.
157         * 
158         * @param unit - the compilation unit.
159         * @return meta data for types in this compilation unit.
160         */
161        @SuppressWarnings( "unchecked" )
162        protected List<TypeMetadata> createTypeMetadata( CompilationUnit unit ) {
163            List<TypeMetadata> metadata = new ArrayList<TypeMetadata>();
164            List<AbstractTypeDeclaration> topLevelType = unit.types();
165    
166            for (AbstractTypeDeclaration abstractTypeDeclaration : topLevelType) {
167                // process TypeDeclaration (class, interface)
168                if (abstractTypeDeclaration instanceof TypeDeclaration) {
169                    TypeDeclaration typeDeclaration = (TypeDeclaration)abstractTypeDeclaration;
170                    if (typeDeclaration.isInterface()) {
171                        // is an interface top level type
172                        InterfaceMetadata interfaceMetadata = new InterfaceMetadata();
173                        interfaceMetadata.setName(JavaMetadataUtil.getName(typeDeclaration.getName()));
174                        metadata.add(interfaceMetadata);
175                    } else {
176                        // is a class top level type
177                        ClassMetadata classMetadata = new ClassMetadata();
178                        processModifiersOfTypDeclaration(typeDeclaration, classMetadata);
179                        classMetadata.setName(JavaMetadataUtil.getName(typeDeclaration.getName()));
180                        // fields of the class top level type
181                        FieldDeclaration[] fieldDeclarations = typeDeclaration.getFields();
182                        for (FieldDeclaration fieldDeclaration : fieldDeclarations) {
183                            FieldMetadata fieldMetadata = getFieldMetadataFrom(fieldDeclaration);
184                            classMetadata.getFields().add(fieldMetadata);
185                        }
186                        // methods of the class top level type
187                        MethodDeclaration[] methodDeclarations = typeDeclaration.getMethods();
188                        for (MethodDeclaration methodDeclaration : methodDeclarations) {
189                            MethodMetadata methodMetadata = getMethodMetadataFrom(methodDeclaration);
190                            classMetadata.getMethods().add(methodMetadata);
191                        }
192                        metadata.add(classMetadata);
193                    }
194                }
195    
196                // process EnumDeclaration
197                if (abstractTypeDeclaration instanceof EnumDeclaration) {
198                    // EnumDeclaration enumDeclaration = (EnumDeclaration)abstractTypeDeclaration;
199                    // TODO get infos from enum declaration and create a enum meta data object.
200                }
201    
202                // process annotationTypeDeclaration
203                if (abstractTypeDeclaration instanceof AnnotationTypeDeclaration) {
204                    // AnnotationTypeDeclaration annotationTypeDeclaration = (AnnotationTypeDeclaration)abstractTypeDeclaration;
205                    // TODO get infos from annotation type declaration and create a annotation meta data object.
206                }
207            }
208            return metadata;
209        }
210    
211        /**
212         * Process modifiers of {@link TypeDeclaration}.
213         * 
214         * @param typeDeclaration - the type declaration.
215         * @param classMetadata - class meta data.
216         */
217        @SuppressWarnings( "unchecked" )
218        protected void processModifiersOfTypDeclaration( TypeDeclaration typeDeclaration,
219                                                         ClassMetadata classMetadata ) {
220            List<IExtendedModifier> modifiers = typeDeclaration.modifiers();
221    
222            for (IExtendedModifier extendedModifier : modifiers) {
223                ModifierMetadata modifierMetadata = new ModifierMetadata();
224                if (extendedModifier.isAnnotation()) {
225                    if (extendedModifier instanceof MarkerAnnotation) {
226                        MarkerAnnotation marker = (MarkerAnnotation)extendedModifier;
227                        MarkerAnnotationMetadata markerAnnotationMetadata = new MarkerAnnotationMetadata();
228                        markerAnnotationMetadata.setName(JavaMetadataUtil.getName(marker.getTypeName()));
229                        classMetadata.getAnnotations().add(markerAnnotationMetadata);
230                    }
231                } else {
232    
233                    Modifier modifier = (Modifier)extendedModifier;
234                    modifierMetadata.setName(modifier.getKeyword().toString());
235                    classMetadata.getModifiers().add(modifierMetadata);
236                }
237            }
238        }
239    
240        /**
241         * Gets a method meta data from {@link MethodDeclaration}.
242         * 
243         * @param methodDeclaration - the MethodDeclaration.
244         * @return methodMetadata - the method meta data.
245         */
246        protected MethodMetadata getMethodMetadataFrom( MethodDeclaration methodDeclaration ) {
247            if (methodDeclaration != null) {
248                if (methodDeclaration.isConstructor()) {
249                    return getConstructorMetadataFrom(methodDeclaration);
250                }
251                return getMethodTypeMemberMetadataFrom(methodDeclaration);
252    
253            }
254            return null;
255        }
256    
257        /**
258         * Get {@link MethodTypeMemberMetadata}
259         * 
260         * @param methodDeclaration
261         * @return methodTypeMemberMetadata
262         */
263        @SuppressWarnings( "unchecked" )
264        protected MethodMetadata getMethodTypeMemberMetadataFrom( MethodDeclaration methodDeclaration ) {
265            MethodTypeMemberMetadata methodTypeMemberMetadata = new MethodTypeMemberMetadata();
266            processReturnTypeOfMethodDeclaration(methodDeclaration, methodTypeMemberMetadata);
267            processModifiersOfMethodDeclaration(methodDeclaration, methodTypeMemberMetadata);
268            processParametersOfMethodDeclaration(methodDeclaration, methodTypeMemberMetadata);
269            methodTypeMemberMetadata.setName(JavaMetadataUtil.getName(methodDeclaration.getName()));
270            List<SingleVariableDeclaration> params = methodDeclaration.parameters();
271            for (SingleVariableDeclaration singleVariableDeclaration : params) {
272                singleVariableDeclaration.getName();
273            }
274            return methodTypeMemberMetadata;
275        }
276    
277        /**
278         * Process return type of a {@link MethodDeclaration}.
279         * 
280         * @param methodDeclaration - the method declaration.
281         * @param methodMetadata - the method meta data.
282         */
283        protected void processReturnTypeOfMethodDeclaration( MethodDeclaration methodDeclaration,
284                                                             MethodMetadata methodMetadata ) {
285            Type type = methodDeclaration.getReturnType2();
286            if (type.isPrimitiveType()) {
287                PrimitiveFieldMetadata primitive = new PrimitiveFieldMetadata();
288                primitive.setType(((PrimitiveType)type).getPrimitiveTypeCode().toString());
289                methodMetadata.setReturnType(primitive);
290            }
291            if (type.isSimpleType()) {
292                SimpleTypeFieldMetadata simpleTypeFieldMetadata = new SimpleTypeFieldMetadata();
293                simpleTypeFieldMetadata.setType(JavaMetadataUtil.getName(((SimpleType)type).getName()));
294                methodMetadata.setReturnType(simpleTypeFieldMetadata);
295            }
296        }
297    
298        /**
299         * Process parameters of a {@link MethodDeclaration}.
300         * 
301         * @param methodDeclaration - the method declaration.
302         * @param methodMetadata - the method meta data.
303         */
304        @SuppressWarnings( "unchecked" )
305        protected void processParametersOfMethodDeclaration( MethodDeclaration methodDeclaration,
306                                                             MethodMetadata methodMetadata ) {
307            for (SingleVariableDeclaration singleVariableDeclaration : (List<SingleVariableDeclaration>)methodDeclaration.parameters()) {
308                Type type = singleVariableDeclaration.getType();
309                if (type.isPrimitiveType()) {
310                    PrimitiveFieldMetadata primitiveFieldMetadata = (PrimitiveFieldMetadata)processVariableDeclaration(singleVariableDeclaration,
311                                                                                                                       type);
312                    methodMetadata.getParameters().add(primitiveFieldMetadata);
313                }
314                if (type.isParameterizedType()) {
315                    ParameterizedTypeFieldMetadata parameterizedTypeFieldMetadata = (ParameterizedTypeFieldMetadata)processVariableDeclaration(singleVariableDeclaration,
316                                                                                                                                               type);
317                    methodMetadata.getParameters().add(parameterizedTypeFieldMetadata);
318                }
319                if (type.isQualifiedType()) {
320                    // TODO
321                }
322                if (type.isSimpleType()) {
323                    SimpleTypeFieldMetadata simpleTypeFieldMetadata = (SimpleTypeFieldMetadata)processVariableDeclaration(singleVariableDeclaration, type);
324                    methodMetadata.getParameters().add(simpleTypeFieldMetadata);
325                }
326                if (type.isArrayType()) {
327                    ArrayTypeFieldMetadata arrayTypeFieldMetadata = (ArrayTypeFieldMetadata)processVariableDeclaration(singleVariableDeclaration, type);
328                    methodMetadata.getParameters().add(arrayTypeFieldMetadata);
329                }
330                if (type.isWildcardType()) {
331                    // TODO
332                }
333            }
334    
335        }
336    
337        /**
338         * Process a {@link SingleVariableDeclaration} of a {@link MethodDeclaration}.
339         * 
340         * @param singleVariableDeclaration
341         * @param type
342         * @return a field meta data.
343         */
344        @SuppressWarnings( "unchecked" )
345        private FieldMetadata processVariableDeclaration( SingleVariableDeclaration singleVariableDeclaration,
346                                                          Type type ) {
347    
348            Variable variable;
349            if (type.isPrimitiveType()) {
350                PrimitiveFieldMetadata primitiveFieldMetadata = new PrimitiveFieldMetadata();
351                primitiveFieldMetadata.setType(((PrimitiveType)type).getPrimitiveTypeCode().toString());
352                variable = new Variable();
353                variable.setName(JavaMetadataUtil.getName(singleVariableDeclaration.getName()));
354                primitiveFieldMetadata.getVariables().add(variable);
355                for (IExtendedModifier extendedModifier : (List<IExtendedModifier>)singleVariableDeclaration.modifiers()) {
356                    ModifierMetadata modifierMetadata = new ModifierMetadata();
357                    if (extendedModifier.isAnnotation()) {
358                        // TODO
359                    } else {
360                        Modifier modifier = (Modifier)extendedModifier;
361                        modifierMetadata.setName(modifier.getKeyword().toString());
362                        primitiveFieldMetadata.getModifiers().add(modifierMetadata);
363                    }
364                }
365                return primitiveFieldMetadata;
366            }
367            if(type.isSimpleType()) {
368                SimpleType simpleType = (SimpleType)type;
369                SimpleTypeFieldMetadata simpleTypeFieldMetadata = new SimpleTypeFieldMetadata();
370                simpleTypeFieldMetadata.setType(JavaMetadataUtil.getName(simpleType.getName()));
371                variable = new Variable();
372                variable.setName(JavaMetadataUtil.getName(singleVariableDeclaration.getName()));
373                simpleTypeFieldMetadata.getVariables().add(variable);
374                for (IExtendedModifier simpleTypeExtendedModifier : (List<IExtendedModifier> )singleVariableDeclaration.modifiers()) {
375                    ModifierMetadata modifierMetadata = new ModifierMetadata();
376                    if (simpleTypeExtendedModifier.isAnnotation()) {
377                        // TODO
378                    } else {
379                        Modifier modifier = (Modifier)simpleTypeExtendedModifier;
380                        modifierMetadata.setName(modifier.getKeyword().toString());
381                        simpleTypeFieldMetadata.getModifiers().add(modifierMetadata);
382                    }
383                }
384                return simpleTypeFieldMetadata;
385            }
386            if (type.isParameterizedType()) {
387                ParameterizedTypeFieldMetadata parameterizedTypeFieldMetadata = new ParameterizedTypeFieldMetadata();
388                ParameterizedType parameterizedType = (ParameterizedType)type;
389                parameterizedTypeFieldMetadata.setType(getTypeName(parameterizedType));
390                variable = new Variable();
391                variable.setName(JavaMetadataUtil.getName(singleVariableDeclaration.getName()));
392                parameterizedTypeFieldMetadata.getVariables().add(variable);
393                for (IExtendedModifier parameterizedExtendedModifier : (List<IExtendedModifier>)singleVariableDeclaration.modifiers()) {
394                    ModifierMetadata modifierMetadata = new ModifierMetadata();
395                    if(parameterizedExtendedModifier.isAnnotation()) {
396                        // TODO
397                    } else {
398                        Modifier modifier = (Modifier)parameterizedExtendedModifier;
399                        modifierMetadata.setName(modifier.getKeyword().toString());
400                        parameterizedTypeFieldMetadata.getModifiers().add(modifierMetadata); 
401                    }
402                }
403                return parameterizedTypeFieldMetadata;
404            }
405            if(type.isArrayType()) {
406                ArrayTypeFieldMetadata arrayTypeFieldMetadata = new ArrayTypeFieldMetadata();
407                ArrayType arrayType = (ArrayType)type;
408                arrayTypeFieldMetadata.setType(getTypeName(arrayType));
409                variable = new Variable();
410                variable.setName(JavaMetadataUtil.getName(singleVariableDeclaration.getName()));
411                arrayTypeFieldMetadata.getVariables().add(variable);
412                
413                for (IExtendedModifier arrayTypeExtendedModifier : (List<IExtendedModifier>)singleVariableDeclaration.modifiers()) {
414                    ModifierMetadata modifierMetadata = new ModifierMetadata();
415                    if(arrayTypeExtendedModifier.isAnnotation()) {
416                        // TODO
417                    } else {
418                        Modifier modifier = (Modifier)arrayTypeExtendedModifier;
419                        modifierMetadata.setName(modifier.getKeyword().toString());
420                        arrayTypeFieldMetadata.getModifiers().add(modifierMetadata); 
421                    }
422                }
423                return arrayTypeFieldMetadata;
424            }
425            return null;
426        }
427    
428        /**
429         * Extract the type name
430         * 
431         * @param type - the type to be processed. This can be primitive, simple, parameterized ...
432         * @return the name of a type.
433         * @throws IllegalArgumentException if type is null.
434         */
435        private String getTypeName( Type type ) {
436            CheckArg.isNotNull(type, "type");
437            if (type.isPrimitiveType()) {
438                PrimitiveType primitiveType = (PrimitiveType)type;
439                return primitiveType.getPrimitiveTypeCode().toString();
440            }
441            if (type.isSimpleType()) {
442                SimpleType simpleType = (SimpleType)type;
443                return JavaMetadataUtil.getName(simpleType.getName());
444            }
445            if(type.isArrayType()) {
446                ArrayType arrayType = (ArrayType)type;
447                // the element type is never an array type
448                Type elementType = arrayType.getElementType();
449                if (elementType.isPrimitiveType()) {
450                 return ((PrimitiveType)elementType).getPrimitiveTypeCode().toString();
451    
452                }
453                // can't be an array type
454                if (elementType.isSimpleType()) {
455                    return JavaMetadataUtil.getName(((SimpleType)elementType).getName());
456                }
457                
458            }
459            return null;
460        }
461    
462        /**
463         * Get {@link ConstructorMetadata}
464         * 
465         * @param methodDeclaration
466         * @return constructorMetadata
467         */
468        protected MethodMetadata getConstructorMetadataFrom( MethodDeclaration methodDeclaration ) {
469            ConstructorMetadata constructorMetadata = new ConstructorMetadata();
470            // modifiers
471            processModifiersOfMethodDeclaration(methodDeclaration, constructorMetadata);
472            processParametersOfMethodDeclaration(methodDeclaration, constructorMetadata);
473            constructorMetadata.setName(JavaMetadataUtil.getName(methodDeclaration.getName()));
474            // arguments list
475            return constructorMetadata;
476        }
477    
478        /**
479         * Gets a field meta data from {@link FieldDeclaration}.
480         * 
481         * @param fieldDeclaration - the declaration.
482         * @return fieldMetadata - meta data.
483         */
484        protected FieldMetadata getFieldMetadataFrom( FieldDeclaration fieldDeclaration ) {
485            if (fieldDeclaration != null && fieldDeclaration.getType() != null && (!fieldDeclaration.fragments().isEmpty())) {
486                // type
487                Type type = fieldDeclaration.getType();
488                // Primitive type
489                if (type.isPrimitiveType()) {
490                    PrimitiveFieldMetadata primitiveFieldMetadata = processPrimitiveType(fieldDeclaration);
491                    return primitiveFieldMetadata;
492                }
493                // ParameterizedType
494                if (type.isParameterizedType()) {
495                    ParameterizedTypeFieldMetadata referenceFieldMetadata = processParameterizedType(fieldDeclaration);
496                    return referenceFieldMetadata;
497                }
498                // SimpleType
499                if (type.isSimpleType()) {
500                    SimpleTypeFieldMetadata simpleTypeFieldMetadata = processSimpleType(fieldDeclaration);
501                    return simpleTypeFieldMetadata;
502                }
503                // ArrayType
504                if (type.isArrayType()) {
505                    ArrayTypeFieldMetadata arrayFieldMetadata = processArrayTypeFrom(fieldDeclaration);
506                    return arrayFieldMetadata;
507                }
508                // QualifiedType
509                if (type.isQualifiedType()) {
510                    // TODO
511    
512                }
513                // WildcardType
514                if (type.isWildcardType()) {
515    
516                }
517            }
518            return null;
519        }
520    
521        /**
522         * Process a {@link FieldDeclaration} to win information for an array type.
523         * 
524         * @param fieldDeclaration - field declaration
525         * @return an ArrayTypeFieldMetadata, that contains information about an array type.
526         */
527        protected ArrayTypeFieldMetadata processArrayTypeFrom( FieldDeclaration fieldDeclaration ) {
528            ArrayTypeFieldMetadata arrayTypeFieldMetadata = null;
529            ArrayType arrayType = (ArrayType)fieldDeclaration.getType();
530            // the element type is never an array type
531            Type type = arrayType.getElementType();
532            if (type.isPrimitiveType()) {
533                PrimitiveType primitiveType = (PrimitiveType)type;
534                arrayTypeFieldMetadata = new ArrayTypeFieldMetadata();
535                arrayTypeFieldMetadata.setType(primitiveType.getPrimitiveTypeCode().toString());
536                processModifiersAndVariablesOfFieldDeclaration(fieldDeclaration, arrayTypeFieldMetadata);
537                return arrayTypeFieldMetadata;
538    
539            }
540            // can't be an array type
541            if (type.isSimpleType()) {
542                SimpleType simpleType = (SimpleType)type;
543                arrayTypeFieldMetadata = new ArrayTypeFieldMetadata();
544                arrayTypeFieldMetadata.setType(JavaMetadataUtil.getName(simpleType.getName()));
545                processModifiersAndVariablesOfFieldDeclaration(fieldDeclaration, arrayTypeFieldMetadata);
546                return arrayTypeFieldMetadata;
547            }
548    
549            return null;
550        }
551    
552        /**
553         * Process together modifiers and variables of a {@link FieldDeclaration}.
554         * 
555         * @param fieldDeclaration - the field declaration instance.
556         * @param arrayTypeFieldMetadata - the meta data.
557         */
558        private void processModifiersAndVariablesOfFieldDeclaration( FieldDeclaration fieldDeclaration,
559                                                                     ArrayTypeFieldMetadata arrayTypeFieldMetadata ) {
560            processModifiersOfFieldDeclaration(fieldDeclaration, arrayTypeFieldMetadata);
561            processVariablesOfVariableDeclarationFragment(fieldDeclaration, arrayTypeFieldMetadata);
562        }
563    
564        /**
565         * Process the simple type of a {@link FieldDeclaration}.
566         * 
567         * @param fieldDeclaration - the field declaration.
568         * @return SimpleTypeFieldMetadata.
569         */
570        protected SimpleTypeFieldMetadata processSimpleType( FieldDeclaration fieldDeclaration ) {
571            SimpleType simpleType = (SimpleType)fieldDeclaration.getType();
572            SimpleTypeFieldMetadata simpleTypeFieldMetadata = new SimpleTypeFieldMetadata();
573            simpleTypeFieldMetadata.setType(JavaMetadataUtil.getName(simpleType.getName()));
574            // modifiers
575            processModifiersOfFieldDeclaration(fieldDeclaration, simpleTypeFieldMetadata);
576            processVariablesOfVariableDeclarationFragment(fieldDeclaration, simpleTypeFieldMetadata);
577            return simpleTypeFieldMetadata;
578        }
579    
580        /**
581         * Process the parameterized type of a {@link FieldDeclaration}.
582         * 
583         * @param fieldDeclaration - the field declaration.
584         * @return ParameterizedTypeFieldMetadata.
585         */
586        protected ParameterizedTypeFieldMetadata processParameterizedType( FieldDeclaration fieldDeclaration ) {
587            ParameterizedType parameterizedType = (ParameterizedType)fieldDeclaration.getType();
588            Type typeOfParameterizedType = parameterizedType.getType(); // type may be a simple type or a qualified type.
589            ParameterizedTypeFieldMetadata referenceFieldMetadata = (ParameterizedTypeFieldMetadata)createParameterizedFieldMetadataFrom(typeOfParameterizedType);
590            // modifiers
591            processModifiersOfFieldDeclaration(fieldDeclaration, referenceFieldMetadata);
592            // variables
593            processVariablesOfVariableDeclarationFragment(fieldDeclaration, referenceFieldMetadata);
594            return referenceFieldMetadata;
595        }
596    
597        /**
598         * Process the primitive type of a {@link FieldDeclaration}.
599         * 
600         * @param fieldDeclaration - the field declaration.
601         * @return PrimitiveFieldMetadata.
602         */
603        protected PrimitiveFieldMetadata processPrimitiveType( FieldDeclaration fieldDeclaration ) {
604            PrimitiveType primitiveType = (PrimitiveType)fieldDeclaration.getType();
605            PrimitiveFieldMetadata primitiveFieldMetadata = new PrimitiveFieldMetadata();
606            primitiveFieldMetadata.setType(primitiveType.getPrimitiveTypeCode().toString());
607            // modifiers
608            processModifiersOfFieldDeclaration(fieldDeclaration, primitiveFieldMetadata);
609            // variables
610            processVariablesOfVariableDeclarationFragment(fieldDeclaration, primitiveFieldMetadata);
611            return primitiveFieldMetadata;
612        }
613    
614        /**
615         * Process modifiers of a {@link FieldDeclaration}
616         * 
617         * @param fieldDeclaration
618         * @param fieldMetadata
619         */
620        @SuppressWarnings( "unchecked" )
621        protected void processModifiersOfFieldDeclaration( FieldDeclaration fieldDeclaration,
622                                                           FieldMetadata fieldMetadata ) {
623            List<IExtendedModifier> extendedModifiers = fieldDeclaration.modifiers();
624            for (IExtendedModifier extendedModifier : extendedModifiers) {
625                ModifierMetadata modifierMetadata = new ModifierMetadata();
626                if (extendedModifier.isAnnotation()) {
627                    // TODO annotation modifiers
628                } else {
629                    Modifier modifier = (Modifier)extendedModifier;
630                    modifierMetadata.setName(modifier.getKeyword().toString());
631                    fieldMetadata.getModifiers().add(modifierMetadata);
632                }
633            }
634    
635        }
636    
637        /**
638         * Process modifiers of a {@link MethodDeclaration}.
639         * 
640         * @param methodDeclaration
641         * @param methodMetadata
642         */
643        @SuppressWarnings( "unchecked" )
644        protected void processModifiersOfMethodDeclaration( MethodDeclaration methodDeclaration,
645                                                            MethodMetadata methodMetadata ) {
646            List<IExtendedModifier> extendedModifiers = methodDeclaration.modifiers();
647            for (IExtendedModifier extendedModifier : extendedModifiers) {
648                ModifierMetadata modifierMetadata = new ModifierMetadata();
649                if (extendedModifier.isAnnotation()) {
650                    // TODO
651                } else {
652                    Modifier modifier = (Modifier)extendedModifier;
653                    modifierMetadata.setName(modifier.getKeyword().toString());
654                    methodMetadata.getModifiers().add(modifierMetadata);
655                }
656            }
657        }
658    
659        /**
660         * Create a <code>FieldMetadata</code> from a {@link Type} instance.
661         * 
662         * @param type - The {@link Type}
663         * @return the specific type of <code>FieldMetadata</code>
664         */
665        protected FieldMetadata createParameterizedFieldMetadataFrom( Type type ) {
666            ParameterizedTypeFieldMetadata parameterizedTypeFieldMetadata = null;
667            if (type.isSimpleType()) {
668                SimpleType simpleType = (SimpleType)type;
669                parameterizedTypeFieldMetadata = new ParameterizedTypeFieldMetadata();
670                parameterizedTypeFieldMetadata.setType(JavaMetadataUtil.getName(simpleType.getName()));
671            }
672            // TODO also process QualifiedType
673            return parameterizedTypeFieldMetadata;
674        }
675    
676        /**
677         * Process variables of a {@link VariableDeclarationFragment}.
678         * 
679         * @param fieldDeclaration - the {@link FieldDeclaration}
680         * @param fieldMetadata - where to transfer the meta data.
681         */
682        @SuppressWarnings( "unchecked" )
683        protected void processVariablesOfVariableDeclarationFragment( FieldDeclaration fieldDeclaration,
684                                                                      FieldMetadata fieldMetadata ) {
685            List<VariableDeclarationFragment> fragments = fieldDeclaration.fragments();
686            for (VariableDeclarationFragment fragment : fragments) {
687                fieldMetadata.getVariables().add(new Variable(JavaMetadataUtil.getName(fragment.getName())));
688            }
689        }
690    }