private void visitPackage()

in versioning/versioning-checker/src/main/java/org/apache/aries/versioning/check/BundleCompatibility.java [289:410]


  private void visitPackage(String pkgName, Map<String, IFile> baseClazz,
      Map<String, IFile> curClazz, VersionChangeReason majorChange, VersionChangeReason minorChange) {
    StringBuilder major_reason = new StringBuilder();
    StringBuilder minor_reason = new StringBuilder();
    boolean is_major_change = false;
    boolean is_minor_change = false;
    String fatal_class = null;
    boolean foundNewAbstract = false;
    for (Map.Entry<String, IFile> file : baseClazz.entrySet()) {
      // scan the latest version of the class
      IFile curFile = curClazz.get(file.getKey());
      String changeClass = file.getValue().getName();
      //Scan the base version
      SemanticVersioningClassVisitor oldcv = getVisitor(file.getValue(), oldJarsLoader);
      // skip the property files as they are compiled as class file as well
      ClassDeclaration cd = oldcv.getClassDeclaration();
      if ((cd != null) && (!SemanticVersioningUtils.isPropertyFile(cd))) {

        if (curFile == null) {
          // the class we are scanning has been deleted from the current version of the bundle
          // This should be a major increase
          major_reason.append(twoLineBreaks + "The class/interface " + getClassName(changeClass) + " has been deleted from the package.");
          //majorChange.update(reason, changeClass);
          is_major_change = true;
          // only replace the fatal class if not set as the class won't be found in cmvc due to the fact it has been deleted.
          if (fatal_class == null) {
            fatal_class = changeClass;
          }
        } else {
          // check for binary compatibility
          // load the class from the current version of the bundle
          // remove it from the curClazz collection as we would like to know whether there are more classes added
          curClazz.remove(file.getKey());
          SemanticVersioningClassVisitor newcv = getVisitor(curFile, newJarsLoader);
          // check for binary compatibility
          ClassDeclaration newcd = newcv.getClassDeclaration();
          BinaryCompatibilityStatus bcs = newcd.getBinaryCompatibleStatus(oldcv.getClassDeclaration());

          if (!bcs.isCompatible()) {
            major_reason.append(twoLineBreaks + "In the " + getClassName(changeClass) + " class or its supers, the following changes have been made since the last release.");
            // break binary compatibility
            for (String reason : bcs) {
              major_reason.append(oneLineBreak).append(reason);
            }
            is_major_change = true;
            fatal_class = changeClass;
          } else {
            //check to see whether more methods are added
            ClassDeclaration oldcd = oldcv.getClassDeclaration();
            Collection<MethodDeclaration> extraMethods = newcd.getExtraMethods(oldcd);

            boolean containsConcrete = false;
            boolean containsAbstract = false;

            boolean abstractClass = newcd.isAbstract();

            StringBuilder subRemarks = new StringBuilder();
            String concreteSubRemarks = null;
            for (MethodDeclaration extraMethod : extraMethods) {
              //only interested in the visible methods not the system generated ones
              if (!extraMethod.getName().contains("$")) {
                if (abstractClass) {
                  if (extraMethod.isAbstract()) {
                    foundNewAbstract = true;
                    containsAbstract = true;
                    subRemarks.append(oneLineBreak + SemanticVersioningUtils.getReadableMethodSignature(extraMethod.getName(), extraMethod.getDesc()));
                  } else {
                    //only list one abstract method, no need to list all
                    containsConcrete = true;
                    concreteSubRemarks = oneLineBreak + SemanticVersioningUtils.getReadableMethodSignature(extraMethod.getName(), extraMethod.getDesc());
                  }
                } else {
                  containsConcrete = true;
                  concreteSubRemarks = oneLineBreak + SemanticVersioningUtils.getReadableMethodSignature(extraMethod.getName(), extraMethod.getDesc());
                  break;
                }
              }
            }

            if (containsConcrete || containsAbstract) {
              is_minor_change = true;
              if (!is_major_change) {
                fatal_class = changeClass;
              }
              if (containsAbstract) {

                minor_reason.append(twoLineBreaks + "In the " + getClassName(changeClass) + " class or its supers, the following abstract methods have been added since the last release of this bundle.");
                minor_reason.append(subRemarks);
              } else {
                minor_reason.append(twoLineBreaks + "In the " + getClassName(changeClass) + " class or its supers, the following method has been added since the last release of this bundle.");
                minor_reason.append(concreteSubRemarks);
              }
            }
            //check to see whether there are extra public/protected fields if there is no additional methods

            if (!is_minor_change) {
              for (FieldDeclaration field : newcd.getExtraFields(oldcd)) {
                if (field.isPublic() || field.isProtected()) {
                  is_minor_change = true;
                  String extraFieldRemarks = oneLineBreak + " " + SemanticVersioningUtils.transform(field.getDesc()) + " " + field.getName();
                  if (!is_major_change) {
                    fatal_class = changeClass;
                  }
                  minor_reason.append(twoLineBreaks + "In the " + getClassName(changeClass) + " class or its supers, the following fields have been added since the last release of this bundle.");
                  minor_reason.append(extraFieldRemarks);
                  break;
                }
              }

            }

          }
        }
      }
    }
    if (is_major_change) {
      majorChange.update(major_reason.toString(), fatal_class, false);
    }
    if (is_minor_change) {
      minorChange.update(minor_reason.toString(), fatal_class, (foundNewAbstract ? true : false));
    }
  }