private void addRealmAnnotations(Field f, SpannableStringBuilder builder) { List<Class<? extends Annotation>> classes = new ArrayList<>(3); classes.add(PrimaryKey.class); classes.add(Ignore.class); classes.add(Index.class); for (Class<? extends Annotation> c : classes) { if (f.isAnnotationPresent(c)) { addAnnotationName(builder, f.getAnnotation(c)); } } }
private void processFields(TypeElement typeElement, FieldDataBuilder fdBuilder) { for (VariableElement var : ElementFilter.fieldsIn(typeElement.getEnclosedElements())) { if (!SuperficialValidation.validateElement(var)) continue; // Ignore if this isn't a field (it could be an enum constant). if (var.getKind() != ElementKind.FIELD) continue; // Ignore if it has Realm's @Ignore or our @Hide annotation. if (MoreElements.isAnnotationPresent(var, Ignore.class) || MoreElements.isAnnotationPresent(var, Hide.class)) continue; // Ignore static fields. if (var.getModifiers().contains(Modifier.STATIC)) continue; // Ignore if not a valid field. TypeMirror varMirror = var.asType(); if (!isValidFieldType(varMirror)) continue; // The field is valid! Start getting data about it; real name first. String realFieldName = var.getSimpleName().toString(); // Check for @VisibleAs. String visibleFieldName = null; if (MoreElements.isAnnotationPresent(var, VisibleAs.class)) { VisibleAs vaAnnot = var.getAnnotation(VisibleAs.class); visibleFieldName = vaAnnot.string(); } if (visibleFieldName == null || visibleFieldName.isEmpty()) // Generate a name from camelCase. visibleFieldName = Utils.makeVisName(realFieldName); // Field type. TypeName fieldType = TypeName.get(varMirror); // If field is a RealmList, we need to get the parameter's type too. ClassName realmListType = null; if (isRealmList(fieldType)) { List<? extends TypeMirror> parameterTypes = MoreTypes.asDeclared(varMirror).getTypeArguments(); realmListType = ClassName.bestGuess(parameterTypes.get(0).toString()); } // Add this field's data to the field data builder. fdBuilder.addField(realFieldName, visibleFieldName, fieldType, realmListType); } }
@Override public Set<String> getSupportedAnnotationTypes() { Set<String> types = new LinkedHashSet<>(); // Our annotations. types.add(Queryable.class.getCanonicalName()); types.add(Hide.class.getCanonicalName()); types.add(VisibleAs.class.getCanonicalName()); types.add(Transformer.class.getCanonicalName()); // Realm annotations. types.add(RealmClass.class.getCanonicalName()); types.add(Ignore.class.getCanonicalName()); return types; }
private boolean categorizeField(Element element) { VariableElement field = (VariableElement) element; // completely ignore any static fields if (field.getModifiers().contains(Modifier.STATIC)) { return true; } // Ignore fields marked with @Ignore or if they are transient if (field.getAnnotation(Ignore.class) != null || field.getModifiers().contains(Modifier.TRANSIENT)) { return true; } if (field.getAnnotation(Index.class) != null) { if (!categorizeIndexField(element, field)) { return false; } } // @Required annotation of RealmList field only affects its value type, not field itself. if (Utils.isRealmList(field)) { // We only check @Required annotation. @org.jetbrains.annotations.NotNull annotation should not affect nullability of the list values. if (!hasRequiredAnnotation(field)) { final List<? extends TypeMirror> fieldTypeArguments = ((DeclaredType) field.asType()).getTypeArguments(); if (fieldTypeArguments.isEmpty() || !Utils.isRealmModel(fieldTypeArguments.get(0))) { nullableValueListFields.add(field); } } } else if (isRequiredField(field)) { categorizeRequiredField(element, field); } else { // The field doesn't have the @Required and @org.jetbrains.annotations.NotNull annotation. // Without @Required annotation, boxed types/RealmObject/Date/String/bytes should be added to // nullableFields. // RealmList of models, RealmResults(backlinks) and primitive types are NOT nullable. @Required annotation is not supported. if (!Utils.isPrimitiveType(field) && !Utils.isRealmResults(field)) { nullableFields.add(field); } } if (field.getAnnotation(PrimaryKey.class) != null) { if (!categorizePrimaryKeyField(field)) { return false; } } // @LinkingObjects cannot be @PrimaryKey or @Index. if (field.getAnnotation(LinkingObjects.class) != null) { // Do not add backlinks to fields list. return categorizeBacklinkField(field); } // Similarly, a MutableRealmInteger cannot be a @PrimaryKey or @LinkingObject. if (Utils.isMutableRealmInteger(field)) { if (!categorizeMutableRealmIntegerField(field)) { return false; } } // Standard field that appears to be valid (more fine grained checks might fail later). fields.add(field); return true; }
public void generate() throws IOException { String qualifiedGeneratedInterfaceName = String.format(Locale.US, "%s.%s", Constants.REALM_PACKAGE_NAME, Utils.getProxyInterfaceName(className)); JavaFileObject sourceFile = processingEnvironment.getFiler().createSourceFile(qualifiedGeneratedInterfaceName); JavaWriter writer = new JavaWriter(new BufferedWriter(sourceFile.openWriter())); writer.setIndent(Constants.INDENT); writer .emitPackage(Constants.REALM_PACKAGE_NAME) .emitEmptyLine() .beginType(qualifiedGeneratedInterfaceName, "interface", EnumSet.of(Modifier.PUBLIC)); for (VariableElement field : metaData.getFields()) { if (field.getModifiers().contains(Modifier.STATIC) || (field.getAnnotation(Ignore.class) != null)) { continue; } // The field is neither static nor ignored String fieldName = field.getSimpleName().toString(); String fieldTypeCanonicalName = field.asType().toString(); writer .beginMethod( fieldTypeCanonicalName, metaData.getInternalGetter(fieldName), EnumSet.of(Modifier.PUBLIC)) .endMethod(); // MutableRealmIntegers do not have setters. if (Utils.isMutableRealmInteger(field)) { continue; } writer .beginMethod( "void", metaData.getInternalSetter(fieldName), EnumSet.of(Modifier.PUBLIC), fieldTypeCanonicalName, "value") .endMethod(); } // backlinks are final and have only a getter. for (Backlink backlink : metaData.getBacklinkFields()) { writer .beginMethod( backlink.getTargetFieldType(), metaData.getInternalGetter(backlink.getTargetField()), EnumSet.of(Modifier.PUBLIC)) .endMethod(); } writer.endType(); writer.close(); }