static boolean checkAbstractValueType(Element element, Collection<String> violations) {
    boolean ofSupportedKind = false
        || element.getKind() == ElementKind.INTERFACE
        || element.getKind() == ElementKind.ANNOTATION_TYPE
        || element.getKind() == ElementKind.CLASS;

    boolean staticOrTopLevel = false
        || element.getEnclosingElement().getKind() == ElementKind.PACKAGE
        || element.getModifiers().contains(Modifier.STATIC);

    boolean nonFinal = !element.getModifiers().contains(Modifier.FINAL);

    boolean publicOrPackageVisible =
        !element.getModifiers().contains(Modifier.PRIVATE)
            && !element.getModifiers().contains(Modifier.PROTECTED);

    if (!ofSupportedKind) {
      violations.add("must be class or interface or annotation type");
    }

    if (!nonFinal) {
      violations.add("must be non-final");
    }

    if (!publicOrPackageVisible) {
      violations.add("should be public or package-visible");
    }

    if (!staticOrTopLevel) {
      violations.add("should be top-level or static inner class");
    }

    return violations.isEmpty();
  }
It may grow later in some better abstraction, but as it stands now, currently it is
just a glue between new "protoclass" model and old discovery routines.
value-processor/src/org/immutables/value/processor/meta/ValueTypeComposer.java