All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.greenrobot.greendao.generator.Entity Maven / Gradle / Ivy

There is a newer version: 3.3.0
Show newest version
/*
 * Copyright (C) 2011-2016 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * This file is part of greenDAO Generator.
 *
 * greenDAO Generator is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * greenDAO Generator is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with greenDAO Generator.  If not, see .
 */

package org.greenrobot.greendao.generator;

import org.greenrobot.greendao.generator.Property.PropertyBuilder;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

/**
 * Model class for an entity: a Java data object mapped to a data base table. A new entity is added to a {@link Schema}
 * by the method {@link Schema#addEntity(String)} (there is no public constructor for {@link Entity} itself). 
*
Use the various addXXX methods to add entity properties, indexes, and relations to other entities (addToOne, * addToMany).

There are further configuration possibilities:
  • {@link * Entity#implementsInterface(String...)} and {@link #implementsSerializable()} to specify interfaces the entity will * implement
  • {@link #setSuperclass(String)} to specify a class of which the entity will extend from
  • *
  • Various setXXX methods
* * @see Modelling Entities (Documentation page) * @see Relations (Documentation page) */ @SuppressWarnings("unused") public class Entity { private final Schema schema; private final String className; private final List properties; private List propertiesColumns; private final List propertiesPk; private final List propertiesNonPk; private final Set propertyNames; private final List indexes; private final List multiIndexes; private final List toOneRelations; private final List toManyRelations; private final List incomingToManyRelations; private final Collection additionalImportsEntity; private final Collection additionalImportsDao; private final List interfacesToImplement; private final List contentProviders; private String dbName; private boolean nonDefaultDbName; private String classNameDao; private String classNameTest; private String javaPackage; private String javaPackageDao; private String javaPackageTest; private Property pkProperty; private String pkType; private String superclass; private String javaDoc; private String codeBeforeClass; private boolean protobuf; private boolean constructors; private boolean skipGeneration; private boolean skipGenerationTest; private boolean skipCreationInDb; private Boolean active; private Boolean hasKeepSections; Entity(Schema schema, String className) { this.schema = schema; this.className = className; properties = new ArrayList<>(); propertiesPk = new ArrayList<>(); propertiesNonPk = new ArrayList<>(); propertyNames = new HashSet<>(); indexes = new ArrayList<>(); multiIndexes = new ArrayList<>(); toOneRelations = new ArrayList<>(); toManyRelations = new ArrayList<>(); incomingToManyRelations = new ArrayList<>(); additionalImportsEntity = new TreeSet<>(); additionalImportsDao = new TreeSet<>(); interfacesToImplement = new ArrayList<>(); contentProviders = new ArrayList<>(); constructors = true; } public PropertyBuilder addBooleanProperty(String propertyName) { return addProperty(PropertyType.Boolean, propertyName); } public PropertyBuilder addByteProperty(String propertyName) { return addProperty(PropertyType.Byte, propertyName); } public PropertyBuilder addShortProperty(String propertyName) { return addProperty(PropertyType.Short, propertyName); } public PropertyBuilder addIntProperty(String propertyName) { return addProperty(PropertyType.Int, propertyName); } public PropertyBuilder addLongProperty(String propertyName) { return addProperty(PropertyType.Long, propertyName); } public PropertyBuilder addFloatProperty(String propertyName) { return addProperty(PropertyType.Float, propertyName); } public PropertyBuilder addDoubleProperty(String propertyName) { return addProperty(PropertyType.Double, propertyName); } public PropertyBuilder addByteArrayProperty(String propertyName) { return addProperty(PropertyType.ByteArray, propertyName); } public PropertyBuilder addStringProperty(String propertyName) { return addProperty(PropertyType.String, propertyName); } public PropertyBuilder addDateProperty(String propertyName) { return addProperty(PropertyType.Date, propertyName); } public PropertyBuilder addProperty(PropertyType propertyType, String propertyName) { if (!propertyNames.add(propertyName)) { throw new RuntimeException("Property already defined: " + propertyName); } PropertyBuilder builder = new PropertyBuilder(schema, this, propertyType, propertyName); properties.add(builder.getProperty()); return builder; } /** Adds a standard _id column required by standard Android classes, e.g. list adapters. */ public PropertyBuilder addIdProperty() { PropertyBuilder builder = addLongProperty("id"); builder.dbName("_id").primaryKey(); return builder; } /** Adds a to-many relationship; the target entity is joined to the PK property of this entity (typically the ID). */ public ToMany addToMany(Entity target, Property targetProperty) { Property[] targetProperties = {targetProperty}; return addToMany(null, target, targetProperties); } /** * Convenience method for {@link Entity#addToMany(Entity, Property)} with a subsequent call to {@link * ToMany#setName(String)}. */ public ToMany addToMany(Entity target, Property targetProperty, String name) { ToMany toMany = addToMany(target, targetProperty); toMany.setName(name); return toMany; } /** * Add a to-many relationship; the target entity is joined using the given target property (of the target entity) * and given source property (of this entity). */ public ToMany addToMany(Property sourceProperty, Entity target, Property targetProperty) { Property[] sourceProperties = {sourceProperty}; Property[] targetProperties = {targetProperty}; return addToMany(sourceProperties, target, targetProperties); } public ToMany addToMany(Property[] sourceProperties, Entity target, Property[] targetProperties) { if (protobuf) { throw new IllegalStateException("Protobuf entities do not support relations, currently"); } ToMany toMany = new ToMany(schema, this, sourceProperties, target, targetProperties); toManyRelations.add(toMany); target.incomingToManyRelations.add(toMany); return toMany; } public ToManyWithJoinEntity addToMany(Entity target, Entity joinEntity, Property id1, Property id2) { ToManyWithJoinEntity toMany = new ToManyWithJoinEntity(schema, this, target, joinEntity, id1, id2); toManyRelations.add(toMany); target.incomingToManyRelations.add(toMany); return toMany; } /** * Adds a to-one relationship to the given target entity using the given given foreign key property (which belongs * to this entity). */ public ToOne addToOne(Entity target, Property fkProperty) { if (protobuf) { throw new IllegalStateException("Protobuf entities do not support realtions, currently"); } Property[] fkProperties = {fkProperty}; ToOne toOne = new ToOne(schema, this, target, fkProperties, true); toOneRelations.add(toOne); return toOne; } /** Convenience for {@link #addToOne(Entity, Property)} with a subsequent call to {@link ToOne#setName(String)}. */ public ToOne addToOne(Entity target, Property fkProperty, String name) { ToOne toOne = addToOne(target, fkProperty); toOne.setName(name); return toOne; } public ToOne addToOneWithoutProperty(String name, Entity target, String fkColumnName) { return addToOneWithoutProperty(name, target, fkColumnName, false, false); } public ToOne addToOneWithoutProperty(String name, Entity target, String fkColumnName, boolean notNull, boolean unique) { PropertyBuilder propertyBuilder = new PropertyBuilder(schema, this, null, name); if (notNull) { propertyBuilder.notNull(); } if (unique) { propertyBuilder.unique(); } propertyBuilder.dbName(fkColumnName); Property column = propertyBuilder.getProperty(); Property[] fkColumns = {column}; ToOne toOne = new ToOne(schema, this, target, fkColumns, false); toOne.setName(name); toOneRelations.add(toOne); return toOne; } protected void addIncomingToMany(ToMany toMany) { incomingToManyRelations.add(toMany); } public ContentProvider addContentProvider() { List entities = new ArrayList<>(); entities.add(this); ContentProvider contentProvider = new ContentProvider(schema, entities); contentProviders.add(contentProvider); return contentProvider; } /** Adds a new index to the entity. */ public Entity addIndex(Index index) { indexes.add(index); return this; } public Entity addImport(String additionalImport) { additionalImportsEntity.add(additionalImport); return this; } /** The entity is represented by a protocol buffers object. Requires some special actions like using builders. */ Entity useProtobuf() { protobuf = true; return this; } public boolean isProtobuf() { return protobuf; } public Schema getSchema() { return schema; } public String getDbName() { return dbName; } @Deprecated /** * @deprecated Use setDbName */ public void setTableName(String tableName) { setDbName(tableName); } public void setDbName(String dbName) { this.dbName = dbName; this.nonDefaultDbName = dbName != null; } public String getClassName() { return className; } public List getProperties() { return properties; } public List getPropertiesColumns() { return propertiesColumns; } public String getJavaPackage() { return javaPackage; } public void setJavaPackage(String javaPackage) { this.javaPackage = javaPackage; } public String getJavaPackageDao() { return javaPackageDao; } public void setJavaPackageDao(String javaPackageDao) { this.javaPackageDao = javaPackageDao; } public String getClassNameDao() { return classNameDao; } public void setClassNameDao(String classNameDao) { this.classNameDao = classNameDao; } public String getClassNameTest() { return classNameTest; } public void setClassNameTest(String classNameTest) { this.classNameTest = classNameTest; } public String getJavaPackageTest() { return javaPackageTest; } public void setJavaPackageTest(String javaPackageTest) { this.javaPackageTest = javaPackageTest; } /** Internal property used by templates, don't use during entity definition. */ public List getPropertiesPk() { return propertiesPk; } /** Internal property used by templates, don't use during entity definition. */ public List getPropertiesNonPk() { return propertiesNonPk; } /** Internal property used by templates, don't use during entity definition. */ public Property getPkProperty() { return pkProperty; } public List getIndexes() { return indexes; } /** Internal property used by templates, don't use during entity definition. */ public String getPkType() { return pkType; } public boolean isConstructors() { return constructors; } /** Flag to define if constructors should be generated. */ public void setConstructors(boolean constructors) { this.constructors = constructors; } public boolean isSkipGeneration() { return skipGeneration; } /** * Flag if the entity's code generation should be skipped. E.g. if you need to change the class after initial * generation. */ public void setSkipGeneration(boolean skipGeneration) { this.skipGeneration = skipGeneration; } @Deprecated /** * @deprecated Use setSkipCreationInDb */ public void setSkipTableCreation(boolean skipTableCreation) { setSkipCreationInDb(skipTableCreation); } /** Flag if CREATE & DROP TABLE scripts should be skipped in Dao. */ public void setSkipCreationInDb(boolean skipCreationInDb) { this.skipCreationInDb = skipCreationInDb; } public boolean isSkipCreationInDb() { return skipCreationInDb; } public boolean isSkipGenerationTest() { return skipGenerationTest; } public void setSkipGenerationTest(boolean skipGenerationTest) { this.skipGenerationTest = skipGenerationTest; } public List getToOneRelations() { return toOneRelations; } public List getToManyRelations() { return toManyRelations; } public List getIncomingToManyRelations() { return incomingToManyRelations; } /** * Entities with relations are active, but this method allows to make the entities active even if it does not have * relations. */ public void setActive(Boolean active) { this.active = active; } public Boolean getActive() { return active; } public Boolean getHasKeepSections() { return hasKeepSections; } public Collection getAdditionalImportsEntity() { return additionalImportsEntity; } public Collection getAdditionalImportsDao() { return additionalImportsDao; } public void setHasKeepSections(Boolean hasKeepSections) { this.hasKeepSections = hasKeepSections; } public List getInterfacesToImplement() { return interfacesToImplement; } public List getContentProviders() { return contentProviders; } public void implementsInterface(String... interfaces) { for (String interfaceToImplement : interfaces) { if (interfacesToImplement.contains(interfaceToImplement)) { throw new RuntimeException("Interface defined more than once: " + interfaceToImplement); } interfacesToImplement.add(interfaceToImplement); } } public void implementsSerializable() { interfacesToImplement.add("java.io.Serializable"); } public String getSuperclass() { return superclass; } public void setSuperclass(String classToExtend) { this.superclass = classToExtend; } public String getJavaDoc() { return javaDoc; } public void setJavaDoc(String javaDoc) { this.javaDoc = DaoUtil.checkConvertToJavaDoc(javaDoc, ""); } public String getCodeBeforeClass() { return codeBeforeClass; } public void setCodeBeforeClass(String codeBeforeClass) { this.codeBeforeClass = codeBeforeClass; } void init2ndPass() { init2ndPassNamesWithDefaults(); for (int i = 0; i < properties.size(); i++) { Property property = properties.get(i); property.setOrdinal(i); property.init2ndPass(); if (property.isPrimaryKey()) { propertiesPk.add(property); } else { propertiesNonPk.add(property); } } for (int i = 0; i < indexes.size(); i++) { final Index index = indexes.get(i); final int propertiesSize = index.getProperties().size(); if (propertiesSize == 1) { final Property property = index.getProperties().get(0); property.setIndex(index); } else if (propertiesSize > 1) { multiIndexes.add(index); } } if (propertiesPk.size() == 1) { pkProperty = propertiesPk.get(0); pkType = schema.mapToJavaTypeNullable(pkProperty.getPropertyType()); } else { pkType = "Void"; } propertiesColumns = new ArrayList<>(properties); for (ToOne toOne : toOneRelations) { toOne.init2ndPass(); Property[] fkProperties = toOne.getFkProperties(); for (Property fkProperty : fkProperties) { if (!propertiesColumns.contains(fkProperty)) { propertiesColumns.add(fkProperty); } } } for (ToManyBase toMany : toManyRelations) { toMany.init2ndPass(); // Source Properties may not be virtual, so we do not need the following code: // for (Property sourceProperty : toMany.getSourceProperties()) { // if (!propertiesColumns.contains(sourceProperty)) { // propertiesColumns.add(sourceProperty); // } // } } if (active == null) { active = schema.isUseActiveEntitiesByDefault(); } active |= !toOneRelations.isEmpty() || !toManyRelations.isEmpty(); if (hasKeepSections == null) { hasKeepSections = schema.isHasKeepSectionsByDefault(); } init2ndPassIndexNamesWithDefaults(); for (ContentProvider contentProvider : contentProviders) { contentProvider.init2ndPass(); } } protected void init2ndPassNamesWithDefaults() { if (dbName == null) { dbName = DaoUtil.dbName(className); nonDefaultDbName = false; } if (classNameDao == null) { classNameDao = className + "Dao"; } if (classNameTest == null) { classNameTest = className + "Test"; } if (javaPackage == null) { javaPackage = schema.getDefaultJavaPackage(); } if (javaPackageDao == null) { javaPackageDao = schema.getDefaultJavaPackageDao(); if (javaPackageDao == null) { javaPackageDao = javaPackage; } } if (javaPackageTest == null) { javaPackageTest = schema.getDefaultJavaPackageTest(); if (javaPackageTest == null) { javaPackageTest = javaPackage; } } } protected void init2ndPassIndexNamesWithDefaults() { for (int i = 0; i < indexes.size(); i++) { Index index = indexes.get(i); if (index.getName() == null) { String indexName = "IDX_" + getDbName(); List properties = index.getProperties(); for (int j = 0; j < properties.size(); j++) { Property property = properties.get(j); indexName += "_" + property.getDbName(); if ("DESC".equalsIgnoreCase(index.getPropertiesOrder().get(j))) { indexName += "_DESC"; } } // TODO can this get too long? how to shorten reliably without depending on the order (i) index.setDefaultName(indexName); } } } void init3rdPass() { for (Property property : properties) { property.init3ndPass(); } init3rdPassRelations(); init3rdPassAdditionalImports(); } private void init3rdPassRelations() { Set toOneNames = new HashSet<>(); for (ToOne toOne : toOneRelations) { toOne.init3ndPass(); if (!toOneNames.add(toOne.getName().toLowerCase())) { throw new RuntimeException("Duplicate name for " + toOne); } } Set toManyNames = new HashSet<>(); for (ToManyBase toMany : toManyRelations) { toMany.init3rdPass(); if (toMany instanceof ToMany) { Entity targetEntity = toMany.getTargetEntity(); for (Property targetProperty : ((ToMany) toMany).getTargetProperties()) { if (!targetEntity.propertiesColumns.contains(targetProperty)) { targetEntity.propertiesColumns.add(targetProperty); } } } if (!toManyNames.add(toMany.getName().toLowerCase())) { throw new RuntimeException("Duplicate name for " + toMany); } } } private void init3rdPassAdditionalImports() { if (active && !javaPackage.equals(javaPackageDao)) { additionalImportsEntity.add(javaPackageDao + "." + classNameDao); } for (ToOne toOne : toOneRelations) { Entity targetEntity = toOne.getTargetEntity(); checkAdditionalImportsEntityTargetEntity(targetEntity); // For deep loading checkAdditionalImportsDaoTargetEntity(targetEntity); } for (ToManyBase toMany : toManyRelations) { Entity targetEntity = toMany.getTargetEntity(); checkAdditionalImportsEntityTargetEntity(targetEntity); } for (ToManyBase incomingToMany : incomingToManyRelations) { if (incomingToMany instanceof ToManyWithJoinEntity) { final ToManyWithJoinEntity toManyWithJoinEntity = (ToManyWithJoinEntity) incomingToMany; final Entity joinEntity = toManyWithJoinEntity.getJoinEntity(); checkAdditionalImportsDaoTargetEntity(joinEntity); } } for (Property property : properties) { String customType = property.getCustomType(); if (customType != null) { String pack = DaoUtil.getPackageFromFullyQualified(customType); if (pack != null && !pack.equals(javaPackage)) { additionalImportsEntity.add(customType); } if (pack != null && !pack.equals(javaPackageDao)) { additionalImportsDao.add(customType); } } String converter = property.getConverter(); if (converter != null) { String pack = DaoUtil.getPackageFromFullyQualified(converter); if (pack != null && !pack.equals(javaPackageDao)) { additionalImportsDao.add(converter); } } } } private void checkAdditionalImportsEntityTargetEntity(Entity targetEntity) { if (!targetEntity.getJavaPackage().equals(javaPackage)) { additionalImportsEntity.add(targetEntity.getJavaPackage() + "." + targetEntity.getClassName()); } if (!targetEntity.getJavaPackageDao().equals(javaPackage)) { additionalImportsEntity.add(targetEntity.getJavaPackageDao() + "." + targetEntity.getClassNameDao()); } } private void checkAdditionalImportsDaoTargetEntity(Entity targetEntity) { if (!targetEntity.getJavaPackage().equals(javaPackageDao)) { additionalImportsDao.add(targetEntity.getJavaPackage() + "." + targetEntity.getClassName()); } } public void validatePropertyExists(Property property) { if (!properties.contains(property)) { throw new RuntimeException("Property " + property + " does not exist in " + this); } } public List getMultiIndexes() { return multiIndexes; } public boolean isNonDefaultDbName() { return nonDefaultDbName; } @Override public String toString() { return "Entity " + className + " (package: " + javaPackage + ")"; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy