docs: @SuppressWarnings( "unchecked" )
      protected List<TypeMetadata> createTypeMetadata( CompilationUnit unit ) {
          List<TypeMetadata> metadata = new ArrayList<TypeMetadata>();
          List<AbstractTypeDeclaration> topLevelType = unit.types();
  
          for (AbstractTypeDeclaration abstractTypeDeclaration : topLevelType) {
              // process TypeDeclaration (class, interface)
              if (abstractTypeDeclaration instanceof TypeDeclaration) {
                  TypeDeclaration typeDeclaration = (TypeDeclaration)abstractTypeDeclaration;
                  if (typeDeclaration.isInterface()) {
                      // is an interface top level type
                      TypeMetadata interfaceMetadata = TypeMetadata.interfaceType(JavaMetadataUtil.getName(typeDeclaration.getName()));
  
                      // detect the interfaces, if any
                      for (Type superInterfaceType : (List<Type>)typeDeclaration.superInterfaceTypes()) {
                          interfaceMetadata.getInterfaceNames().add(getTypeName(superInterfaceType));
                      }
  
                      metadata.add(interfaceMetadata);
                  } else {
                      // is a class top level type
                      TypeMetadata classMetadata = TypeMetadata.classType(JavaMetadataUtil.getName(typeDeclaration.getName()));
                      processModifiersOfTypeDeclaration(typeDeclaration, classMetadata);
  
                      // set the superclass, if any
                      Type superClassType = typeDeclaration.getSuperclassType();
                      if (superClassType != null) {
                          classMetadata.setSuperTypeName(getTypeName(superClassType));
                      }
  
                      // detect the interfaces, if any
                      for (Type superInterfaceType : (List<Type>)typeDeclaration.superInterfaceTypes()) {
                          classMetadata.getInterfaceNames().add(getTypeName(superInterfaceType));
                      }
  
                      // fields of the class top level type
                      FieldDeclaration[] fieldDeclarations = typeDeclaration.getFields();
                      for (FieldDeclaration fieldDeclaration : fieldDeclarations) {
                          FieldMetadata fieldMetadata = getFieldMetadataFrom(fieldDeclaration);
                          classMetadata.getFields().add(fieldMetadata);
                      }
                      // methods of the class top level type
                      MethodDeclaration[] methodDeclarations = typeDeclaration.getMethods();
                      for (MethodDeclaration methodDeclaration : methodDeclarations) {
                          MethodMetadata methodMetadata = getMethodMetadataFrom(methodDeclaration);
                          classMetadata.getMethods().add(methodMetadata);
                      }
                      metadata.add(classMetadata);
                  }
              }
  
              // process EnumDeclaration
              if (abstractTypeDeclaration instanceof EnumDeclaration) {
                  EnumDeclaration enumDeclaration = (EnumDeclaration)abstractTypeDeclaration;
  
                  // is a class top level type
                  EnumMetadata enumMetadata = TypeMetadata.enumType(JavaMetadataUtil.getName(enumDeclaration.getName()));
                  processModifiersOfTypeDeclaration(enumDeclaration, enumMetadata);
  
                  // Store the enum values
                  List<EnumConstantDeclaration> enumValues = enumDeclaration.enumConstants();
                  for (EnumConstantDeclaration enumValue : enumValues) {
                      enumMetadata.getValues().add(enumValue.getName().getIdentifier());
                  }
  
                  // Enums don't have superclasses
  
                  // detect the interfaces, if any
                  for (Type superInterfaceType : (List<Type>)enumDeclaration.superInterfaceTypes()) {
                      enumMetadata.getInterfaceNames().add(getTypeName(superInterfaceType));
                  }
  
                  /*
                   * It would be nice to be able to reuse the convenience methods from AbstractTypeDeclaration,
                   * but they don't exist in EnumDeclaration.  So we improvise!
                   */
  
                  List<BodyDeclaration> bodyDecls = enumDeclaration.bodyDeclarations();
                  for (BodyDeclaration bodyDecl : bodyDecls) {
                      if (bodyDecl instanceof FieldDeclaration) {
                          // fields of the class top level type
                          FieldMetadata fieldMetadata = getFieldMetadataFrom((FieldDeclaration)bodyDecl);
                          enumMetadata.getFields().add(fieldMetadata);
                      } else if (bodyDecl instanceof MethodDeclaration) {
                          // methods of the class top level type
                          MethodMetadata methodMetadata = getMethodMetadataFrom((MethodDeclaration)bodyDecl);
                          enumMetadata.getMethods().add(methodMetadata);
                      }
                  }
  
                  metadata.add(enumMetadata);
              }
  
              // process annotationTypeDeclaration
              if (abstractTypeDeclaration instanceof AnnotationTypeDeclaration) {
                  // AnnotationTypeDeclaration annotationTypeDeclaration = (AnnotationTypeDeclaration)abstractTypeDeclaration;
                  // TODO get infos from annotation type declaration and create a annotation meta data object.
              }
          }
          return metadata;
      }