Search in sources :

Example 16 with VariableElement

use of javax.lang.model.element.VariableElement in project realm-java by realm.

the class RealmProxyClassGenerator method emitValidateTableMethod.

private void emitValidateTableMethod(JavaWriter writer) throws IOException {
    writer.beginMethod(// Return type
    columnInfoClassName(), // Method name
    "validateTable", // Modifiers
    EnumSet.of(Modifier.PUBLIC, Modifier.STATIC), // Argument type & argument name
    "SharedRealm", // Argument type & argument name
    "sharedRealm", "boolean", "allowExtraColumns");
    writer.beginControlFlow("if (!sharedRealm.hasTable(\"" + Constants.TABLE_PREFIX + this.simpleClassName + "\"))");
    emitMigrationNeededException(writer, "\"The '%s' class is missing from the schema for this Realm.\")", metadata.getSimpleClassName());
    writer.endControlFlow();
    writer.emitStatement("Table table = sharedRealm.getTable(\"%s%s\")", Constants.TABLE_PREFIX, this.simpleClassName);
    // verify number of columns
    writer.emitStatement("final long columnCount = table.getColumnCount()");
    writer.beginControlFlow("if (columnCount != %d)", metadata.getFields().size());
    writer.beginControlFlow("if (columnCount < %d)", metadata.getFields().size());
    emitMigrationNeededException(writer, "\"Field count is less than expected - expected %d but was \" + columnCount)", metadata.getFields().size());
    writer.endControlFlow();
    writer.beginControlFlow("if (allowExtraColumns)");
    writer.emitStatement("RealmLog.debug(\"Field count is more than expected - expected %d but was %%1$d\", columnCount)", metadata.getFields().size());
    writer.nextControlFlow("else");
    emitMigrationNeededException(writer, "\"Field count is more than expected - expected %d but was \" + columnCount)", metadata.getFields().size());
    writer.endControlFlow();
    writer.endControlFlow();
    // create type dictionary for lookup
    writer.emitStatement("Map<String, RealmFieldType> columnTypes = new HashMap<String, RealmFieldType>()");
    writer.beginControlFlow("for (long i = 0; i < columnCount; i++)").emitStatement("columnTypes.put(table.getColumnName(i), table.getColumnType(i))").endControlFlow().emitEmptyLine();
    // create an instance of ColumnInfo
    writer.emitStatement("final %1$s columnInfo = new %1$s(sharedRealm.getPath(), table)", columnInfoClassName()).emitEmptyLine();
    // verify primary key definition was not altered
    if (metadata.hasPrimaryKey()) {
        // the current model defines a PK, make sure it's defined in the Realm schema
        String fieldName = metadata.getPrimaryKey().getSimpleName().toString();
        writer.beginControlFlow("if (!table.hasPrimaryKey())");
        emitMigrationNeededException(writer, "\"Primary key not defined for field '%s' in existing Realm file. @PrimaryKey was added.\")", metadata.getPrimaryKey().getSimpleName().toString());
        writer.nextControlFlow("else").beginControlFlow("if (table.getPrimaryKey() != columnInfo.%sIndex)", fieldName);
        emitMigrationNeededException(writer, "\"Primary Key annotation definition was changed, from field \" + table.getColumnName(table.getPrimaryKey()) + \" to field %s\")", metadata.getPrimaryKey().getSimpleName().toString());
        writer.endControlFlow().endControlFlow();
    } else {
        // the current model doesn't define a PK, make sure it's not defined in the Realm schema
        writer.beginControlFlow("if (table.hasPrimaryKey())");
        emitMigrationNeededException(writer, "\"Primary Key defined for field \" + table.getColumnName(table.getPrimaryKey()) + \" was removed.\")");
        writer.endControlFlow();
    }
    writer.emitEmptyLine();
    // For each field verify there is a corresponding
    long fieldIndex = -1;
    for (VariableElement field : metadata.getFields()) {
        fieldIndex++;
        String fieldName = field.getSimpleName().toString();
        String fieldTypeQualifiedName = Utils.getFieldTypeQualifiedName(field);
        if (Constants.JAVA_TO_REALM_TYPES.containsKey(fieldTypeQualifiedName)) {
            emitValidateRealmType(writer, field, fieldName, fieldTypeQualifiedName);
        } else if (Utils.isRealmModel(field)) {
            // Links
            emitValidateRealmModelType(writer, field, fieldIndex, fieldName);
        } else if (Utils.isRealmList(field)) {
            // Link Lists
            emitValidateRealmListType(writer, field, fieldIndex, fieldName);
        }
    }
    // verify the backlinks
    Set<Backlink> backlinks = metadata.getBacklinkFields();
    if (backlinks.size() > 0) {
        writer.emitEmptyLine().emitStatement("long backlinkFieldIndex").emitStatement("Table backlinkSourceTable").emitStatement("Table backlinkTargetTable").emitStatement("RealmFieldType backlinkFieldType");
        for (Backlink backlink : metadata.getBacklinkFields()) {
            emitValidateBacklink(writer, backlink);
        }
    }
    writer.emitEmptyLine();
    writer.emitStatement("return %s", "columnInfo");
    writer.endMethod();
    writer.emitEmptyLine();
}
Also used : VariableElement(javax.lang.model.element.VariableElement)

Example 17 with VariableElement

use of javax.lang.model.element.VariableElement in project realm-java by realm.

the class RealmProxyClassGenerator method emitColumnIndicesClass.

private void emitColumnIndicesClass(JavaWriter writer) throws IOException {
    writer.beginType(// full qualified name of the item to generate
    columnInfoClassName(), // the type of the item
    "class", // modifiers to apply
    EnumSet.of(Modifier.STATIC, Modifier.FINAL), // base class
    "ColumnInfo", // interfaces
    "Cloneable").emitEmptyLine();
    // fields
    for (VariableElement variableElement : metadata.getFields()) {
        writer.emitField("long", columnIndexVarName(variableElement), EnumSet.of(Modifier.PUBLIC));
    }
    writer.emitEmptyLine();
    // constructor
    writer.beginConstructor(EnumSet.noneOf(Modifier.class), "String", "path", "Table", "table");
    writer.emitStatement("final Map<String, Long> indicesMap = new HashMap<String, Long>(%s)", metadata.getFields().size());
    for (VariableElement variableElement : metadata.getFields()) {
        final String columnName = variableElement.getSimpleName().toString();
        final String columnIndexVarName = columnIndexVarName(variableElement);
        writer.emitStatement("this.%s = getValidColumnIndex(path, table, \"%s\", \"%s\")", columnIndexVarName, simpleClassName, columnName).emitStatement("indicesMap.put(\"%s\", this.%s)", columnName, columnIndexVarName);
    }
    writer.emitEmptyLine().emitStatement("setIndicesMap(indicesMap)");
    writer.endConstructor().emitEmptyLine();
    // copyColumnInfoFrom method
    writer.emitAnnotation("Override").beginMethod(// return type
    "void", // method name
    "copyColumnInfoFrom", // modifiers
    EnumSet.of(Modifier.PUBLIC, Modifier.FINAL), "ColumnInfo", // parameters
    "other");
    {
        writer.emitStatement("final %1$s otherInfo = (%1$s) other", columnInfoClassName());
        // copy field values
        for (VariableElement variableElement : metadata.getFields()) {
            writer.emitStatement("this.%1$s = otherInfo.%1$s", columnIndexVarName(variableElement));
        }
        writer.emitEmptyLine().emitStatement("setIndicesMap(otherInfo.getIndicesMap())");
    }
    writer.endMethod().emitEmptyLine();
    // clone method
    writer.emitAnnotation("Override").beginMethod(// return type
    columnInfoClassName(), // method name
    "clone", // modifiers
    EnumSet.of(Modifier.PUBLIC, Modifier.FINAL)).emitStatement("return (%1$s) super.clone()", columnInfoClassName()).endMethod().emitEmptyLine();
    writer.endType();
}
Also used : VariableElement(javax.lang.model.element.VariableElement) Modifier(javax.lang.model.element.Modifier)

Example 18 with VariableElement

use of javax.lang.model.element.VariableElement in project realm-java by realm.

the class RealmProxyClassGenerator method emitInsertListMethod.

private void emitInsertListMethod(JavaWriter writer) throws IOException {
    writer.beginMethod(// Return type
    "void", // Method name
    "insert", // Modifiers
    EnumSet.of(Modifier.PUBLIC, Modifier.STATIC), // Argument type & argument name
    "Realm", // Argument type & argument name
    "realm", // Argument type & argument name
    "Iterator<? extends RealmModel>", // Argument type & argument name
    "objects", // Argument type & argument name
    "Map<RealmModel,Long>", // Argument type & argument name
    "cache");
    writer.emitStatement("Table table = realm.getTable(%s.class)", qualifiedClassName);
    writer.emitStatement("long tableNativePtr = table.getNativeTablePointer()");
    writer.emitStatement("%s columnInfo = (%s) realm.schema.getColumnInfo(%s.class)", columnInfoClassName(), columnInfoClassName(), qualifiedClassName);
    if (metadata.hasPrimaryKey()) {
        writer.emitStatement("long pkColumnIndex = table.getPrimaryKey()");
    }
    writer.emitStatement("%s object = null", qualifiedClassName);
    writer.beginControlFlow("while (objects.hasNext())").emitStatement("object = (%s) objects.next()", qualifiedClassName);
    writer.beginControlFlow("if(!cache.containsKey(object))");
    writer.beginControlFlow("if (object instanceof RealmObjectProxy && ((RealmObjectProxy)object).realmGet$proxyState().getRealm$realm() != null && ((RealmObjectProxy)object).realmGet$proxyState().getRealm$realm().getPath().equals(realm.getPath()))");
    writer.emitStatement("cache.put(object, ((RealmObjectProxy)object).realmGet$proxyState().getRow$realm().getIndex())").emitStatement("continue");
    writer.endControlFlow();
    addPrimaryKeyCheckIfNeeded(metadata, true, writer);
    for (VariableElement field : metadata.getFields()) {
        String fieldName = field.getSimpleName().toString();
        String fieldType = field.asType().toString();
        String getter = metadata.getInternalGetter(fieldName);
        if (Utils.isRealmModel(field)) {
            writer.emitEmptyLine().emitStatement("%s %sObj = ((%s) object).%s()", fieldType, fieldName, interfaceName, getter).beginControlFlow("if (%sObj != null)", fieldName).emitStatement("Long cache%1$s = cache.get(%1$sObj)", fieldName).beginControlFlow("if (cache%s == null)", fieldName).emitStatement("cache%s = %s.insert(realm, %sObj, cache)", fieldName, Utils.getProxyClassSimpleName(field), fieldName).endControlFlow().emitStatement("table.setLink(columnInfo.%1$sIndex, rowIndex, cache%1$s, false)", fieldName).endControlFlow();
        } else if (Utils.isRealmList(field)) {
            final String genericType = Utils.getGenericTypeQualifiedName(field);
            writer.emitEmptyLine().emitStatement("RealmList<%s> %sList = ((%s) object).%s()", genericType, fieldName, interfaceName, getter).beginControlFlow("if (%sList != null)", fieldName).emitStatement("long %1$sNativeLinkViewPtr = Table.nativeGetLinkView(tableNativePtr, columnInfo.%1$sIndex, rowIndex)", fieldName).beginControlFlow("for (%1$s %2$sItem : %2$sList)", genericType, fieldName).emitStatement("Long cacheItemIndex%1$s = cache.get(%1$sItem)", fieldName).beginControlFlow("if (cacheItemIndex%s == null)", fieldName).emitStatement("cacheItemIndex%1$s = %2$s.insert(realm, %1$sItem, cache)", fieldName, Utils.getProxyClassSimpleName(field)).endControlFlow().emitStatement("LinkView.nativeAdd(%1$sNativeLinkViewPtr, cacheItemIndex%1$s)", fieldName).endControlFlow().endControlFlow().emitEmptyLine();
        } else {
            if (metadata.getPrimaryKey() != field) {
                setTableValues(writer, fieldType, fieldName, interfaceName, getter, false);
            }
        }
    }
    writer.endControlFlow();
    writer.endControlFlow();
    writer.endMethod();
    writer.emitEmptyLine();
}
Also used : VariableElement(javax.lang.model.element.VariableElement)

Example 19 with VariableElement

use of javax.lang.model.element.VariableElement in project realm-java by realm.

the class RealmProxyInterfaceGenerator method generate.

public void generate() throws IOException {
    String qualifiedGeneratedInterfaceName = String.format("%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()) {
        // The field is neither static nor ignored
        if (!field.getModifiers().contains(Modifier.STATIC) && field.getAnnotation(Ignore.class) == null) {
            String fieldName = field.getSimpleName().toString();
            String fieldTypeCanonicalName = field.asType().toString();
            writer.beginMethod(fieldTypeCanonicalName, metaData.getInternalGetter(fieldName), EnumSet.of(Modifier.PUBLIC)).endMethod().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();
}
Also used : JavaFileObject(javax.tools.JavaFileObject) JavaWriter(com.squareup.javawriter.JavaWriter) VariableElement(javax.lang.model.element.VariableElement) BufferedWriter(java.io.BufferedWriter)

Example 20 with VariableElement

use of javax.lang.model.element.VariableElement in project realm-java by realm.

the class Backlink method validateTarget.

public boolean validateTarget(ClassMetaData clazz) {
    VariableElement field = clazz.getDeclaredField(sourceField);
    if (field == null) {
        Utils.error(String.format("Field \"%s\", the target of the @LinkedObjects annotation on field \"%s.%s\", does not exist in class \"%s\".", sourceField, targetClass, targetField, sourceClass));
        return false;
    }
    String fieldType = field.asType().toString();
    if (!(targetClass.equals(fieldType) || targetClass.equals(Utils.getRealmListType(field)))) {
        Utils.error(String.format("Field \"%s.%s\", the target of the @LinkedObjects annotation on field \"%s.%s\", has type \"%s\" instead of \"%3$s\".", sourceClass, sourceField, targetClass, targetField, fieldType));
        return false;
    }
    return true;
}
Also used : VariableElement(javax.lang.model.element.VariableElement)

Aggregations

VariableElement (javax.lang.model.element.VariableElement)248 ExecutableElement (javax.lang.model.element.ExecutableElement)75 TypeElement (javax.lang.model.element.TypeElement)75 TypeMirror (javax.lang.model.type.TypeMirror)72 GeneratedVariableElement (com.google.devtools.j2objc.types.GeneratedVariableElement)35 Element (javax.lang.model.element.Element)35 Expression (com.google.devtools.j2objc.ast.Expression)30 SimpleName (com.google.devtools.j2objc.ast.SimpleName)28 JVar (com.helger.jcodemodel.JVar)25 InfixExpression (com.google.devtools.j2objc.ast.InfixExpression)23 ArrayList (java.util.ArrayList)23 PostfixExpression (com.google.devtools.j2objc.ast.PostfixExpression)16 PrefixExpression (com.google.devtools.j2objc.ast.PrefixExpression)16 JInvocation (com.helger.jcodemodel.JInvocation)16 DeclaredType (javax.lang.model.type.DeclaredType)16 JBlock (com.helger.jcodemodel.JBlock)15 AbstractJClass (com.helger.jcodemodel.AbstractJClass)14 SingleVariableDeclaration (com.google.devtools.j2objc.ast.SingleVariableDeclaration)13 Elements (javax.lang.model.util.Elements)13 VariableDeclarationStatement (com.google.devtools.j2objc.ast.VariableDeclarationStatement)12