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