public TypeDeclaration processTypeDeclaration(
      PackageRegistry pkgRegistry, AbstractClassTypeDeclarationDescr typeDescr) {

    TypeDeclaration type =
        kbuilder.getTypeBuilder().getExistingTypeDeclaration(typeDescr.getFullTypeName());
    if (type == null) {
      type = new TypeDeclaration(typeDescr.getTypeName());
      type.setResource(typeDescr.getResource());

      // if is not new, search the already existing declaration and
      // compare them o see if they are at least compatibles
      // check whether it is necessary to build the class or not
      type.setNovel(TypeDeclarationUtils.isNovelClass(typeDescr, pkgRegistry));
      type.setNature(
          type.isNovel() ? TypeDeclaration.Nature.DEFINITION : TypeDeclaration.Nature.DECLARATION);
    }

    processTypeAnnotations(typeDescr, type);
    return type;
  }
  protected void checkRedeclaration(
      AbstractClassTypeDeclarationDescr typeDescr,
      TypeDeclaration type,
      PackageRegistry pkgRegistry) {
    TypeDeclaration previousTypeDeclaration =
        kbuilder
            .getPackageRegistry(typeDescr.getNamespace())
            .getPackage()
            .getTypeDeclaration(typeDescr.getTypeName());

    try {
      // if there is no previous declaration, then the original declaration was a POJO
      // to the behavior previous these changes
      if (previousTypeDeclaration == null) {
        // new declarations of a POJO can't declare new fields,
        // except if the POJO was previously generated/compiled and saved into the kjar
        Class<?> existingDeclarationClass =
            TypeDeclarationUtils.getExistingDeclarationClass(typeDescr, pkgRegistry);
        if (!kbuilder.getBuilderConfiguration().isPreCompiled()
            && !GeneratedFact.class.isAssignableFrom(existingDeclarationClass)
            && !type.getTypeClassDef().getFields().isEmpty()) {
          try {
            Class existingClass =
                pkgRegistry
                    .getPackage()
                    .getTypeResolver()
                    .resolveType(typeDescr.getType().getFullName());
            ClassFieldInspector cfi = new ClassFieldInspector(existingClass);

            int fieldCount = 0;
            for (String existingFieldName : cfi.getFieldTypesField().keySet()) {
              if (!cfi.isNonGetter(existingFieldName)
                  && !"class".equals(existingFieldName)
                  && cfi.getSetterMethods().containsKey(existingFieldName)
                  && cfi.getGetterMethods().containsKey(existingFieldName)) {
                if (!typeDescr.getFields().containsKey(existingFieldName)) {
                  type.setValid(false);
                  kbuilder.addBuilderResult(
                      new TypeDeclarationError(
                          typeDescr,
                          "New declaration of "
                              + typeDescr.getType().getFullName()
                              + " does not include field "
                              + existingFieldName));
                } else {
                  String fldType = cfi.getFieldTypes().get(existingFieldName).getName();
                  fldType =
                      TypeDeclarationUtils.toBuildableType(fldType, kbuilder.getRootClassLoader());
                  TypeFieldDescr declaredField = typeDescr.getFields().get(existingFieldName);
                  if (!fldType.equals(
                      type.getTypeClassDef().getField(existingFieldName).getTypeName())) {
                    type.setValid(false);
                    kbuilder.addBuilderResult(
                        new TypeDeclarationError(
                            typeDescr,
                            "New declaration of "
                                + typeDescr.getType().getFullName()
                                + " redeclared field "
                                + existingFieldName
                                + " : \n"
                                + "existing : "
                                + fldType
                                + " vs declared : "
                                + declaredField.getPattern().getObjectType()));
                  } else {
                    fieldCount++;
                  }
                }
              }
            }

            if (fieldCount != typeDescr.getFields().size()) {
              kbuilder.addBuilderResult(reportDeclarationDiff(cfi, typeDescr));
            }
          } catch (IOException e) {
            e.printStackTrace();
            type.setValid(false);
            kbuilder.addBuilderResult(
                new TypeDeclarationError(
                    typeDescr,
                    "Unable to redeclare "
                        + typeDescr.getType().getFullName()
                        + " : "
                        + e.getMessage()));
          } catch (ClassNotFoundException e) {
            type.setValid(false);
            kbuilder.addBuilderResult(
                new TypeDeclarationError(
                    typeDescr,
                    "Unable to redeclare "
                        + typeDescr.getType().getFullName()
                        + " : "
                        + e.getMessage()));
          }
        }
      } else {

        int typeComparisonResult = this.compareTypeDeclarations(previousTypeDeclaration, type);

        if (typeComparisonResult < 0) {
          // oldDeclaration is "less" than newDeclaration -> error
          kbuilder.addBuilderResult(
              new TypeDeclarationError(
                  typeDescr,
                  typeDescr.getType().getFullName()
                      + " declares more fields than the already existing version"));
          type.setValid(false);
        } else if (typeComparisonResult > 0 && !type.getTypeClassDef().getFields().isEmpty()) {
          // oldDeclaration is "grater" than newDeclaration -> error
          kbuilder.addBuilderResult(
              new TypeDeclarationError(
                  typeDescr,
                  typeDescr.getType().getFullName()
                      + " declares less fields than the already existing version"));
          type.setValid(false);
        }

        // if they are "equal" -> no problem

        // in the case of a declaration, we need to copy all the
        // fields present in the previous declaration
        if (type.getNature() == TypeDeclaration.Nature.DECLARATION) {
          mergeTypeDeclarations(previousTypeDeclaration, type);
        }
      }

    } catch (IncompatibleClassChangeError error) {
      // if the types are incompatible -> error
      kbuilder.addBuilderResult(new TypeDeclarationError(typeDescr, error.getMessage()));
    }
  }