/**
   * ********************************************************************************************************************************************************************
   * 1) Process the TypeDeclaration Descriptors Resolve names Normalize field descriptors
   * ********************************************************************************************************************************************************************
   */
  public void processTypeDeclarations(
      Collection<? extends PackageDescr> packageDescrs,
      Collection<AbstractClassTypeDeclarationDescr> unsortedDescrs,
      List<TypeDefinition> unresolvedTypes,
      Map<String, AbstractClassTypeDeclarationDescr> unprocesseableDescrs) {

    // init package to ensure type resolvers are available
    for (PackageDescr packageDescr : packageDescrs) {
      if (kbuilder.getPackageRegistry(packageDescr.getName()) == null) {
        kbuilder.createPackageRegistry(packageDescr);
      }
    }

    setResourcesInDescriptors(packageDescrs);

    // ensure all names are fully qualified before continuing
    typeDeclarationNameResolver.resolveTypes(packageDescrs, unresolvedTypes);

    // create "implicit" packages
    for (PackageDescr packageDescr : packageDescrs) {
      normalizeForeignPackages(packageDescr);
    }

    // merge "duplicate" definitions and declarations
    unsortedDescrs = compactDefinitionsAndDeclarations(unsortedDescrs, unprocesseableDescrs);

    // now sort declarations by mutual dependencies
    ClassHierarchyManager classHierarchyManager =
        new ClassHierarchyManager(unsortedDescrs, kbuilder);

    for (AbstractClassTypeDeclarationDescr typeDescr :
        classHierarchyManager.getSortedDescriptors()) {
      PackageRegistry pkgRegistry = kbuilder.getPackageRegistry(typeDescr.getNamespace());
      createBean(
          typeDescr, pkgRegistry, classHierarchyManager, unresolvedTypes, unprocesseableDescrs);
    }

    for (AbstractClassTypeDeclarationDescr typeDescr :
        classHierarchyManager.getSortedDescriptors()) {
      if (!unprocesseableDescrs.containsKey(typeDescr.getType().getFullName())) {
        PackageRegistry pkgRegistry = kbuilder.getPackageRegistry(typeDescr.getNamespace());
        typeDeclarationConfigurator.wireFieldAccessors(
            pkgRegistry,
            typeDescr,
            pkgRegistry.getPackage().getTypeDeclaration(typeDescr.getType().getName()));
      }
    }
  }
  protected void createBean(
      AbstractClassTypeDeclarationDescr typeDescr,
      PackageRegistry pkgRegistry,
      ClassHierarchyManager hierarchyManager,
      List<TypeDefinition> unresolvedTypes,
      Map<String, AbstractClassTypeDeclarationDescr> unprocesseableDescrs) {

    // descriptor needs fields inherited from superclass
    if (typeDescr instanceof TypeDeclarationDescr) {
      hierarchyManager.inheritFields(
          pkgRegistry,
          typeDescr,
          hierarchyManager.getSortedDescriptors(),
          unresolvedTypes,
          unprocesseableDescrs);
    }

    TypeDeclaration type = typeDeclarationFactory.processTypeDeclaration(pkgRegistry, typeDescr);
    boolean success = !kbuilder.hasErrors();

    try {
      // the type declaration is generated in any case (to be used by subclasses, if any)
      // the actual class will be generated only if needed
      ClassDefinition def = null;
      if (success) {
        def =
            classDefinitionFactory.generateDeclaredBean(
                typeDescr, type, pkgRegistry, unresolvedTypes, unprocesseableDescrs);

        // now use the definition to compare redeclarations, if any
        // this has to be done after the classDef has been generated
        if (!type.isNovel()) {
          typeDeclarationFactory.checkRedeclaration(typeDescr, type, pkgRegistry);
        }
      }
      success = (def != null) && (!kbuilder.hasErrors());

      if (success) {
        updateTraitInformation(typeDescr, type, def, pkgRegistry);
      }
      success = !kbuilder.hasErrors();

      if (success) {
        declaredClassBuilder.generateBeanFromDefinition(typeDescr, type, pkgRegistry, def);
      }
      success = !kbuilder.hasErrors();

      if (success) {
        Class<?> clazz =
            pkgRegistry.getTypeResolver().resolveType(typeDescr.getType().getFullName());
        type.setTypeClass(clazz);
        type.setValid(true);
      } else {
        unprocesseableDescrs.put(typeDescr.getType().getFullName(), typeDescr);
        type.setValid(false);
      }

      typeDeclarationConfigurator.finalize(
          type, typeDescr, pkgRegistry, kbuilder.getPackageRegistry(), hierarchyManager);

    } catch (final ClassNotFoundException e) {
      unprocesseableDescrs.put(typeDescr.getType().getFullName(), typeDescr);
      kbuilder.addBuilderResult(
          new TypeDeclarationError(
              typeDescr,
              "Class '"
                  + type.getTypeClassName()
                  + "' not found for type declaration of '"
                  + type.getTypeName()
                  + "'"));
    }

    if (!success) {
      unresolvedTypes.add(new TypeDefinition(type, typeDescr));
    } else {
      registerGeneratedType(typeDescr);
    }
  }