Esempio n. 1
0
  protected int compareTypeDeclarations(
      TypeDeclaration oldDeclaration, TypeDeclaration newDeclaration)
      throws IncompatibleClassChangeError {

    // different formats -> incompatible
    if (!oldDeclaration.getFormat().equals(newDeclaration.getFormat())) {
      throw new IncompatibleClassChangeError(
          "Type Declaration "
              + newDeclaration.getTypeName()
              + " has a different"
              + " format that its previous definition: "
              + newDeclaration.getFormat()
              + "!="
              + oldDeclaration.getFormat());
    }

    // different superclasses -> Incompatible (TODO: check for hierarchy)
    if (!oldDeclaration
        .getTypeClassDef()
        .getSuperClass()
        .equals(newDeclaration.getTypeClassDef().getSuperClass())) {
      if (oldDeclaration.getNature() == TypeDeclaration.Nature.DEFINITION
          && newDeclaration.getNature() == TypeDeclaration.Nature.DECLARATION
          && Object.class.getName().equals(newDeclaration.getTypeClassDef().getSuperClass())) {
        // actually do nothing. The new declaration just recalls the previous definition, probably
        // to extend it.
      } else {
        throw new IncompatibleClassChangeError(
            "Type Declaration "
                + newDeclaration.getTypeName()
                + " has a different"
                + " superclass that its previous definition: "
                + newDeclaration.getTypeClassDef().getSuperClass()
                + " != "
                + oldDeclaration.getTypeClassDef().getSuperClass());
      }
    }

    // different duration -> Incompatible
    if (!nullSafeEqualityComparison(
        oldDeclaration.getDurationAttribute(), newDeclaration.getDurationAttribute())) {
      throw new IncompatibleClassChangeError(
          "Type Declaration "
              + newDeclaration.getTypeName()
              + " has a different"
              + " duration: "
              + newDeclaration.getDurationAttribute()
              + " != "
              + oldDeclaration.getDurationAttribute());
    }

    //        //different masks -> incompatible
    if (newDeclaration.getNature().equals(TypeDeclaration.Nature.DEFINITION)) {
      if (oldDeclaration.getSetMask() != newDeclaration.getSetMask()) {
        throw new IncompatibleClassChangeError(
            "Type Declaration "
                + newDeclaration.getTypeName()
                + " is incompatible with"
                + " the previous definition: "
                + newDeclaration
                + " != "
                + oldDeclaration);
      }
    }

    // TODO: further comparison?

    // Field comparison
    List<FactField> oldFields = oldDeclaration.getTypeClassDef().getFields();
    Map<String, FactField> newFieldsMap = new HashMap<String, FactField>();
    for (FactField factField : newDeclaration.getTypeClassDef().getFields()) {
      newFieldsMap.put(factField.getName(), factField);
    }

    // each of the fields in the old definition that are also present in the
    // new definition must have the same type. If not -> Incompatible
    boolean allFieldsInOldDeclarationAreStillPresent = true;
    for (FactField oldFactField : oldFields) {
      FactField newFactField = newFieldsMap.get(oldFactField.getName());

      if (newFactField != null) {
        // we can't use newFactField.getType() since it throws a NPE at this point.
        String newFactType = ((FieldDefinition) newFactField).getTypeName();

        if (!newFactType.equals(((FieldDefinition) oldFactField).getTypeName())) {
          throw new IncompatibleClassChangeError(
              "Type Declaration "
                  + newDeclaration.getTypeName()
                  + "."
                  + newFactField.getName()
                  + " has a different"
                  + " type that its previous definition: "
                  + newFactType
                  + " != "
                  + oldFactField.getType().getCanonicalName());
        }
      } else {
        allFieldsInOldDeclarationAreStillPresent = false;
      }
    }

    // If the old declaration has less fields than the new declaration, oldDefinition <
    // newDefinition
    if (oldFields.size() < newFieldsMap.size()) {
      return -1;
    }

    // If the old declaration has more fields than the new declaration, oldDefinition >
    // newDefinition
    if (oldFields.size() > newFieldsMap.size()) {
      return 1;
    }

    // If the old declaration has the same fields as the new declaration,
    // and all the fieds present in the old declaration are also present in
    // the new declaration, then they are considered "equal", otherwise
    // they are incompatible
    if (allFieldsInOldDeclarationAreStillPresent) {
      return 0;
    }

    // Both declarations have the same number of fields, but not all the
    // fields in the old declaration are present in the new declaration.
    throw new IncompatibleClassChangeError(
        newDeclaration.getTypeName()
            + " introduces"
            + " fields that are not present in its previous version.");
  }