public int compare(Declaration d1, Declaration d2) {
      if (equals(d1, d2)) return 0;

      SourcePosition p1 = d1.getPosition();
      SourcePosition p2 = d2.getPosition();

      if (p1 == null && p2 != null) return 1;
      else if (p1 != null && p2 == null) return -1;
      else if (p1 == null && p2 == null) return compareEqualPosition(d1, d2);
      else {
        assert p1 != null && p2 != null;
        int fileComp = p1.file().compareTo(p2.file());
        if (fileComp == 0) {
          long diff = (long) p1.line() - (long) p2.line();
          if (diff == 0) {
            diff = Long.signum((long) p1.column() - (long) p2.column());
            if (diff != 0) return (int) diff;
            else {
              // declarations may be two
              // compiler-generated members with the
              // same source position
              return compareEqualPosition(d1, d2);
            }
          } else return (diff < 0) ? -1 : 1;
        } else return fileComp;
      }
    }
    @SuppressWarnings("cast")
    private int compareEqualPosition(Declaration d1, Declaration d2) {
      assert d1.getPosition() == d2.getPosition();

      DeclPartialOrder dpo1 = new DeclPartialOrder();
      DeclPartialOrder dpo2 = new DeclPartialOrder();

      d1.accept(dpo1);
      d2.accept(dpo2);

      int difference = dpo1.getValue() - dpo2.getValue();
      if (difference != 0) return difference;
      else {
        int result = d1.getSimpleName().compareTo(d2.getSimpleName());
        if (result != 0) return result;
        return (int)
            (Long.signum((long) System.identityHashCode(d1) - (long) System.identityHashCode(d2)));
      }
    }
  @Override
  public ValidationResult validateRootElement(RootElementDeclaration rootElementDeclaration) {
    ValidationResult result = super.validateRootElement(rootElementDeclaration);
    String namespace = rootElementDeclaration.getNamespace();
    if (namespace == null) {
      namespace = "";
    }

    if (namespace.isEmpty()) {
      result.addError(rootElementDeclaration, "Root element should not be in the empty namespace.");
    }

    if (rootElementDeclaration.getName().toLowerCase().startsWith("web")) {
      result.addWarning(
          rootElementDeclaration,
          "You probably don't want a root element that starts with the name 'web'. Consider renaming using the @XmlRootElement annotation.");
    }

    JsonElementWrapper elementWrapper =
        rootElementDeclaration.getAnnotation(JsonElementWrapper.class);
    if (namespace.startsWith(CommonModels.GEDCOMX_DOMAIN) && elementWrapper == null) {
      result.addWarning(
          rootElementDeclaration,
          "Root elements in the '"
              + CommonModels.GEDCOMX_DOMAIN
              + "' namespace should probably be annotated with @"
              + JsonElementWrapper.class.getSimpleName()
              + ".");
    }

    if (elementWrapper != null) {
      String jsonName = elementWrapper.namespace() + elementWrapper.name();
      Declaration previous = this.jsonNameDeclarations.put(jsonName, rootElementDeclaration);
      if (previous != null) {
        result.addError(
            rootElementDeclaration,
            "JSON name conflict with " + String.valueOf(previous.getPosition()));
      }
    }

    return result;
  }
 @Override
 public ValidationResult validate(EnunciateFreemarkerModel model) {
   ValidationResult result = super.validate(model);
   for (SchemaInfo schemaInfo : model.getNamespacesToSchemas().values()) {
     for (Registry registry : schemaInfo.getRegistries()) {
       Collection<LocalElementDeclaration> localElements = registry.getLocalElementDeclarations();
       for (LocalElementDeclaration localElement : localElements) {
         JsonElementWrapper elementWrapper = localElement.getAnnotation(JsonElementWrapper.class);
         if (elementWrapper != null) {
           String jsonName = elementWrapper.namespace() + elementWrapper.name();
           Declaration previous = this.jsonNameDeclarations.put(jsonName, localElement);
           if (previous != null) {
             result.addError(
                 localElement,
                 "JSON name conflict with " + String.valueOf(previous.getPosition()));
           }
         }
       }
     }
   }
   return result;
 }
 public void error(Declaration declaration, String message) {
   env_.getMessager().printError(declaration.getPosition(), message);
 }