Import DaoGenerator from greenDAO

The jitpack.io build is facing issues. The code required for the code
generation is quite small, with a negligible build impact, so import it
directly to the repository from the fork and remove the dependency on
jitpack completely.

- Taken from https://codeberg.org/Freeyourgadget/greenDAO
- Original commit: 1998d7cd2d21f662c6044f6ccf3b3a251bbad341
This commit is contained in:
José Rebelo
2025-06-19 13:22:28 +01:00
parent 2961c38c04
commit e083eaa011
25 changed files with 3522 additions and 5 deletions
+8 -2
View File
@@ -7,8 +7,11 @@ plugins {
base.archivesName = 'gadgetbridge-daogenerator'
dependencies {
// https://github.com/Freeyourgadget/greenDAO/tree/fyg
implementation 'com.github.Freeyourgadget:greendao:1998d7cd2d21f662c6044f6ccf3b3a251bbad341'
// https://codeberg.org/Freeyourgadget/greenDao
//implementation 'com.github.Freeyourgadget:greendao:1998d7cd2d21f662c6044f6ccf3b3a251bbad341'
// As of 2025-06-19, this is bundled directly in the repository due to jitpack build issues
implementation 'org.freemarker:freemarker:2.3.23'
}
sourceSets {
@@ -16,6 +19,9 @@ sourceSets {
java {
srcDir 'src'
}
resources {
srcDir 'src-template'
}
}
}
@@ -0,0 +1,217 @@
package ${contentProvider.javaPackage};
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import de.greenrobot.dao.DaoLog;
import ${schema.defaultJavaPackageDao}.DaoSession;
import ${entity.javaPackageDao}.${entity.classNameDao};
/* Copy this code snippet into your AndroidManifest.xml inside the
<application> element:
<provider
android:name="${contentProvider.javaPackage}.${contentProvider.className}"
android:authorities="${contentProvider.authority}"/>
*/
public class ${contentProvider.className} extends ContentProvider {
public static final String AUTHORITY = "${contentProvider.authority}";
public static final String BASE_PATH = "${contentProvider.basePath}";
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + BASE_PATH);
public static final String CONTENT_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE
+ "/" + BASE_PATH;
public static final String CONTENT_ITEM_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE
+ "/" + BASE_PATH;
private static final String TABLENAME = ${entity.classNameDao}.TABLENAME;
private static final String PK = ${entity.classNameDao}.Properties.${entity.pkProperty.propertyName?cap_first}
.columnName;
<#assign counter = 0>
private static final int ${entity.className?upper_case}_DIR = ${counter};
private static final int ${entity.className?upper_case}_ID = ${counter+1};
private static final UriMatcher sURIMatcher;
static {
sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
sURIMatcher.addURI(AUTHORITY, BASE_PATH, ${entity.className?upper_case}_DIR);
sURIMatcher.addURI(AUTHORITY, BASE_PATH + "/#", ${entity.className?upper_case}_ID);
}
/**
* This must be set from outside, it's recommended to do this inside your Application object.
* Subject to change (static isn't nice).
*/
public static DaoSession daoSession;
@Override
public boolean onCreate() {
// if(daoSession == null) {
// throw new IllegalStateException("DaoSession must be set before content provider is created");
// }
DaoLog.d("Content Provider started: " + CONTENT_URI);
return true;
}
protected SQLiteDatabase getDatabase() {
if(daoSession == null) {
throw new IllegalStateException("DaoSession must be set during content provider is active");
}
return daoSession.getDatabase();
}
<#--
##########################################
########## Insert ##############
##########################################
-->
@Override
public Uri insert(Uri uri, ContentValues values) {
<#if contentProvider.isReadOnly()>
throw new UnsupportedOperationException("This content provider is readonly");
<#else>
int uriType = sURIMatcher.match(uri);
long id = 0;
String path = "";
switch (uriType) {
case ${entity.className?upper_case}_DIR:
id = getDatabase().insert(TABLENAME, null, values);
path = BASE_PATH + "/" + id;
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return Uri.parse(path);
</#if>
}
<#--
##########################################
########## Delete ##############
##########################################
-->
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
<#if contentProvider.isReadOnly()>
throw new UnsupportedOperationException("This content provider is readonly");
<#else>
int uriType = sURIMatcher.match(uri);
SQLiteDatabase db = getDatabase();
int rowsDeleted = 0;
String id;
switch (uriType) {
case ${entity.className?upper_case}_DIR:
rowsDeleted = db.delete(TABLENAME, selection, selectionArgs);
break;
case ${entity.className?upper_case}_ID:
id = uri.getLastPathSegment();
if (TextUtils.isEmpty(selection)) {
rowsDeleted = db.delete(TABLENAME, PK + "=" + id, null);
} else {
rowsDeleted = db.delete(TABLENAME, PK + "=" + id + " and "
+ selection, selectionArgs);
}
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return rowsDeleted;
</#if>
}
<#--
##########################################
########## Update ##############
##########################################
-->
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
<#if contentProvider.isReadOnly()>
throw new UnsupportedOperationException("This content provider is readonly");
<#else>
int uriType = sURIMatcher.match(uri);
SQLiteDatabase db = getDatabase();
int rowsUpdated = 0;
String id;
switch (uriType) {
case ${entity.className?upper_case}_DIR:
rowsUpdated = db.update(TABLENAME, values, selection, selectionArgs);
break;
case ${entity.className?upper_case}_ID:
id = uri.getLastPathSegment();
if (TextUtils.isEmpty(selection)) {
rowsUpdated = db.update(TABLENAME, values, PK + "=" + id, null);
} else {
rowsUpdated = db.update(TABLENAME, values, PK + "=" + id
+ " and " + selection, selectionArgs);
}
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return rowsUpdated;
</#if>
}
<#--
##########################################
########## Query ##############
##########################################
-->
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
int uriType = sURIMatcher.match(uri);
switch (uriType) {
case ${entity.className?upper_case}_DIR:
queryBuilder.setTables(TABLENAME);
break;
case ${entity.className?upper_case}_ID:
queryBuilder.setTables(TABLENAME);
queryBuilder.appendWhere(PK + "="
+ uri.getLastPathSegment());
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
SQLiteDatabase db = getDatabase();
Cursor cursor = queryBuilder.query(db, projection, selection,
selectionArgs, null, null, sortOrder);
cursor.setNotificationUri(getContext().getContentResolver(), uri);
return cursor;
}
<#--
##########################################
########## GetType ##############
##########################################
-->
@Override
public final String getType(Uri uri) {
switch (sURIMatcher.match(uri)) {
case ${entity.className?upper_case}_DIR:
return CONTENT_TYPE;
case ${entity.className?upper_case}_ID:
return CONTENT_ITEM_TYPE;
default :
throw new IllegalArgumentException("Unsupported URI: " + uri);
}
}
}
+129
View File
@@ -0,0 +1,129 @@
<#--
Copyright (C) 2011-2015 Markus Junginger, greenrobot (http://greenrobot.de)
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 <http://www.gnu.org/licenses/>.
-->
<#if entity.toOneRelations?has_content>
private String selectDeep;
protected String getSelectDeep() {
if (selectDeep == null) {
StringBuilder builder = new StringBuilder("SELECT ");
SqlUtils.appendColumns(builder, "T", getAllColumns());
builder.append(',');
<#list entity.toOneRelations as toOne>
SqlUtils.appendColumns(builder, "T${toOne_index}", daoSession.get${toOne.targetEntity.classNameDao}().getAllColumns());
<#if toOne_has_next>
builder.append(',');
</#if>
</#list>
builder.append(" FROM ${entity.tableName} T");
<#list entity.toOneRelations as toOne>
builder.append(" LEFT JOIN ${toOne.targetEntity.tableName} T${toOne_index}<#--
--> ON T.\"${toOne.fkProperties[0].columnName}\"=T${toOne_index}.\"${toOne.targetEntity.pkProperty.columnName}\"");
</#list>
builder.append(' ');
selectDeep = builder.toString();
}
return selectDeep;
}
protected ${entity.className} loadCurrentDeep(Cursor cursor, boolean lock) {
${entity.className} entity = loadCurrent(cursor, 0, lock);
int offset = getAllColumns().length;
<#list entity.toOneRelations as toOne>
${toOne.targetEntity.className} ${toOne.name} = loadCurrentOther(daoSession.get${toOne.targetEntity.classNameDao}(), cursor, offset);
<#if toOne.fkProperties[0].notNull> if(${toOne.name} != null) {
</#if> entity.set${toOne.name?cap_first}(${toOne.name});
<#if toOne.fkProperties[0].notNull>
}
</#if>
<#if toOne_has_next>
offset += daoSession.get${toOne.targetEntity.classNameDao}().getAllColumns().length;
</#if>
</#list>
return entity;
}
public ${entity.className} loadDeep(Long key) {
assertSinglePk();
if (key == null) {
return null;
}
StringBuilder builder = new StringBuilder(getSelectDeep());
builder.append("WHERE ");
SqlUtils.appendColumnsEqValue(builder, "T", getPkColumns());
String sql = builder.toString();
String[] keyArray = new String[] { key.toString() };
Cursor cursor = db.rawQuery(sql, keyArray);
try {
boolean available = cursor.moveToFirst();
if (!available) {
return null;
} else if (!cursor.isLast()) {
throw new IllegalStateException("Expected unique result, but count was " + cursor.getCount());
}
return loadCurrentDeep(cursor, true);
} finally {
cursor.close();
}
}
/** Reads all available rows from the given cursor and returns a list of new ImageTO objects. */
public List<${entity.className}> loadAllDeepFromCursor(Cursor cursor) {
int count = cursor.getCount();
List<${entity.className}> list = new ArrayList<${entity.className}>(count);
if (cursor.moveToFirst()) {
if (identityScope != null) {
identityScope.lock();
identityScope.reserveRoom(count);
}
try {
do {
list.add(loadCurrentDeep(cursor, false));
} while (cursor.moveToNext());
} finally {
if (identityScope != null) {
identityScope.unlock();
}
}
}
return list;
}
protected List<${entity.className}> loadDeepAllAndCloseCursor(Cursor cursor) {
try {
return loadAllDeepFromCursor(cursor);
} finally {
cursor.close();
}
}
/** A raw-style query where you can pass any WHERE clause and arguments. */
public List<${entity.className}> queryDeep(String where, String... selectionArg) {
Cursor cursor = db.rawQuery(getSelectDeep() + where, selectionArg);
return loadDeepAllAndCloseCursor(cursor);
}
</#if>
+101
View File
@@ -0,0 +1,101 @@
<#--
Copyright (C) 2011 Markus Junginger, greenrobot (http://greenrobot.de)
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 <http://www.gnu.org/licenses/>.
-->
package ${schema.defaultJavaPackageDao};
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import de.greenrobot.dao.AbstractDaoMaster;
import de.greenrobot.dao.identityscope.IdentityScopeType;
<#list schema.entities as entity>
import ${entity.javaPackageDao}.${entity.classNameDao};
</#list>
// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
/**
* Master of DAO (schema version ${schema.version?c}): knows all DAOs.
*/
public class DaoMaster extends AbstractDaoMaster {
public static final int SCHEMA_VERSION = ${schema.version?c};
/** Creates underlying database table using DAOs. */
public static void createAllTables(SQLiteDatabase db, boolean ifNotExists) {
<#list schema.entities as entity>
<#if !entity.skipTableCreation>
${entity.classNameDao}.createTable(db, ifNotExists);
</#if>
</#list>
}
/** Drops underlying database table using DAOs. */
public static void dropAllTables(SQLiteDatabase db, boolean ifExists) {
<#list schema.entities as entity>
<#if !entity.skipTableCreation>
${entity.classNameDao}.dropTable(db, ifExists);
</#if>
</#list>
}
public static abstract class OpenHelper extends SQLiteOpenHelper {
public OpenHelper(Context context, String name, CursorFactory factory) {
super(context, name, factory, SCHEMA_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
Log.i("greenDAO", "Creating tables for schema version " + SCHEMA_VERSION);
createAllTables(db, false);
}
}
/** WARNING: Drops all table on Upgrade! Use only during development. */
public static class DevOpenHelper extends OpenHelper {
public DevOpenHelper(Context context, String name, CursorFactory factory) {
super(context, name, factory);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by dropping all tables");
dropAllTables(db, true);
onCreate(db);
}
}
public DaoMaster(SQLiteDatabase db) {
super(db, SCHEMA_VERSION);
<#list schema.entities as entity>
registerDaoClass(${entity.classNameDao}.class);
</#list>
}
public DaoSession newSession() {
return new DaoSession(db, IdentityScopeType.Session, daoConfigMap);
}
public DaoSession newSession(IdentityScopeType type) {
return new DaoSession(db, type, daoConfigMap);
}
}
@@ -0,0 +1,87 @@
<#--
Copyright (C) 2011 Markus Junginger, greenrobot (http://greenrobot.de)
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 <http://www.gnu.org/licenses/>.
-->
package ${schema.defaultJavaPackageDao};
import android.database.sqlite.SQLiteDatabase;
import java.util.Map;
import de.greenrobot.dao.AbstractDao;
import de.greenrobot.dao.AbstractDaoSession;
import de.greenrobot.dao.identityscope.IdentityScopeType;
import de.greenrobot.dao.internal.DaoConfig;
<#list schema.entities as entity>
import ${entity.javaPackage}.${entity.className};
</#list>
<#list schema.entities as entity>
import ${entity.javaPackageDao}.${entity.classNameDao};
</#list>
// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
/**
* {@inheritDoc}
*
* @see de.greenrobot.dao.AbstractDaoSession
*/
public class DaoSession extends AbstractDaoSession {
<#list schema.entities as entity>
private final DaoConfig ${entity.classNameDao?uncap_first}Config;
</#list>
<#list schema.entities as entity>
private final ${entity.classNameDao} ${entity.classNameDao?uncap_first};
</#list>
public DaoSession(SQLiteDatabase db, IdentityScopeType type, Map<Class<? extends AbstractDao<?, ?>>, DaoConfig>
daoConfigMap) {
super(db);
<#list schema.entities as entity>
${entity.classNameDao?uncap_first}Config = daoConfigMap.get(${entity.classNameDao}.class).clone();
${entity.classNameDao?uncap_first}Config.initIdentityScope(type);
</#list>
<#list schema.entities as entity>
${entity.classNameDao?uncap_first} = new ${entity.classNameDao}<#--
-->(${entity.classNameDao?uncap_first}Config, this);
</#list>
<#list schema.entities as entity>
registerDao(${entity.className}.class, ${entity.classNameDao?uncap_first});
</#list>
}
public void clear() {
<#list schema.entities as entity>
${entity.classNameDao?uncap_first}Config.getIdentityScope().clear();
</#list>
}
<#list schema.entities as entity>
public ${entity.classNameDao} get${entity.classNameDao?cap_first}() {
return ${entity.classNameDao?uncap_first};
}
</#list>
}
@@ -0,0 +1,53 @@
<#--
Copyright (C) 2011 Markus Junginger, greenrobot (http://greenrobot.de)
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 <http://www.gnu.org/licenses/>.
-->
package ${entity.javaPackageTest};
<#assign isStringPK = entity.pkProperty?? && entity.pkProperty.propertyType == "String" />
<#if isStringPK>
import de.greenrobot.dao.test.AbstractDaoTestStringPk;
<#else>
import de.greenrobot.dao.test.AbstractDaoTestLongPk;
</#if>
import ${entity.javaPackage}.${entity.className};
import ${entity.javaPackageDao}.${entity.classNameDao};
public class ${entity.classNameTest} extends <#if
isStringPK>AbstractDaoTestStringPk<${entity.classNameDao}, ${entity.className}><#else>AbstractDaoTestLongPk<${entity.classNameDao}, ${entity.className}></#if> {
public ${entity.classNameTest}() {
super(${entity.classNameDao}.class);
}
@Override
protected ${entity.className} createEntity(<#if isStringPK>String<#else>Long</#if> key) {
${entity.className} entity = new ${entity.className}();
<#if entity.pkProperty??>
entity.set${entity.pkProperty.propertyName?cap_first}(key);
</#if>
<#list entity.properties as property>
<#if property.notNull>
entity.set${property.propertyName?cap_first}();
</#if>
</#list>
return entity;
}
}
+324
View File
@@ -0,0 +1,324 @@
<#--
Copyright (C) 2011-2015 Markus Junginger, greenrobot (http://greenrobot.de)
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 <http://www.gnu.org/licenses/>.
-->
<#assign toBindType = {"Boolean":"Long", "Byte":"Long", "Short":"Long", "Int":"Long", "Long":"Long", "Float":"Double", "Double":"Double", "String":"String", "ByteArray":"Blob", "Date": "Long" } />
<#assign toCursorType = {"Boolean":"Short", "Byte":"Short", "Short":"Short", "Int":"Int", "Long":"Long", "Float":"Float", "Double":"Double", "String":"String", "ByteArray":"Blob", "Date": "Long" } />
package ${entity.javaPackageDao};
import android.os.Build;
<#if entity.toOneRelations?has_content || entity.incomingToManyRelations?has_content>
import java.util.List;
</#if>
<#if entity.toOneRelations?has_content>
import java.util.ArrayList;
</#if>
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteStatement;
import de.greenrobot.dao.AbstractDao;
import de.greenrobot.dao.Property;
<#if entity.toOneRelations?has_content>
import de.greenrobot.dao.internal.SqlUtils;
</#if>
import de.greenrobot.dao.internal.DaoConfig;
<#if entity.incomingToManyRelations?has_content>
import de.greenrobot.dao.query.Query;
import de.greenrobot.dao.query.QueryBuilder;
</#if>
<#if entity.javaPackageDao != schema.defaultJavaPackageDao>
import ${schema.defaultJavaPackageDao}.DaoSession;
</#if>
<#if entity.additionalImportsDao?has_content>
<#list entity.additionalImportsDao as additionalImport>
import ${additionalImport};
</#list>
</#if>
import ${entity.javaPackage}.${entity.className};
<#if entity.protobuf>
import ${entity.javaPackage}.${entity.className}.Builder;
</#if>
// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
/**
* DAO for table "${entity.tableName}".
*/
public class ${entity.classNameDao} extends AbstractDao<${entity.className}, ${entity.pkType}> {
public static final String TABLENAME = "${entity.tableName}";
/**
* Properties of entity ${entity.className}.<br/>
* Can be used for QueryBuilder and for referencing column names.
*/
public static class Properties {
<#list entity.propertiesColumns as property>
public final static Property ${property.propertyName?cap_first} = new Property(${property_index}, ${property.javaType}.class, "${property.propertyName}", ${property.primaryKey?string}, "${property.columnName}");
</#list>
};
<#if entity.active>
private DaoSession daoSession;
</#if>
<#list entity.properties as property><#if property.customType?has_content><#--
--> private final ${property.converterClassName} ${property.propertyName}Converter = new ${property.converterClassName}();
</#if></#list>
<#list entity.incomingToManyRelations as toMany>
private Query<${toMany.targetEntity.className}> ${toMany.sourceEntity.className?uncap_first}_${toMany.name?cap_first}Query;
</#list>
public ${entity.classNameDao}(DaoConfig config) {
super(config);
}
public ${entity.classNameDao}(DaoConfig config, DaoSession daoSession) {
super(config, daoSession);
<#if entity.active>
this.daoSession = daoSession;
</#if>
}
<#if !entity.skipTableCreation>
/** Creates the underlying database table. */
public static void createTable(SQLiteDatabase db, boolean ifNotExists) {
String constraint = ifNotExists? "IF NOT EXISTS ": "";
db.execSQL("CREATE TABLE " + constraint + "\"${entity.tableName}\" (" + //
<#assign pks = []>
<#list entity.propertiesColumns as property>
<#if property.constraints??><#if property.constraints?contains("PRIMARY KEY")><#assign pks = pks + [property.columnName]></#if></#if>
</#list>
<#if pks?size gt 1>
<#list entity.propertiesColumns as property>
"\"${property.columnName}\" ${property.columnType}<#if property.constraints??> ${property.constraints?replace("PRIMARY KEY","")} </#if>," + // ${property_index}: ${property.propertyName}
</#list>
"PRIMARY KEY (" +
<#list pks as pk>
"\"${pk}\" <#if pk_has_next>," +<#else>) ON CONFLICT REPLACE)" + ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) ? " WITHOUT ROWID;" : ";")</#if>
</#list>
);
<#else>
<#list entity.propertiesColumns as property>
"\"${property.columnName}\" ${property.columnType}<#if property.constraints??> ${property.constraints} </#if><#if property_has_next>," +<#else>);");</#if> // ${property_index}: ${property.propertyName}
</#list>
</#if>
<#if entity.indexes?has_content >
// Add Indexes
<#list entity.indexes as index>
db.execSQL("CREATE <#if index.unique>UNIQUE </#if>INDEX " + constraint + "${index.name} ON ${entity.tableName}" +
" (<#list index.properties
as property>\"${property.columnName}\"<#if property_has_next>,</#if></#list>);");
</#list>
</#if>
}
/** Drops the underlying database table. */
public static void dropTable(SQLiteDatabase db, boolean ifExists) {
String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "\"${entity.tableName}\"";
db.execSQL(sql);
}
</#if>
/** @inheritdoc */
@Override
protected void bindValues(SQLiteStatement stmt, ${entity.className} entity) {
stmt.clearBindings();
<#list entity.properties as property>
<#if property.notNull || entity.protobuf>
<#if entity.protobuf>
if(entity.has${property.propertyName?cap_first}()) {
</#if> stmt.bind${toBindType[property.propertyType]}(${property_index + 1}, ${property.databaseValueExpressionNotNull});
<#if entity.protobuf>
}
</#if>
<#else> <#-- nullable, non-protobuff -->
${property.javaTypeInEntity} ${property.propertyName} = entity.get${property.propertyName?cap_first}();
if (${property.propertyName} != null) {
stmt.bind${toBindType[property.propertyType]}(${property_index + 1}, ${property.databaseValueExpression});
}
</#if>
</#list>
<#list entity.toOneRelations as toOne>
<#if !toOne.fkProperties?has_content>
${toOne.targetEntity.className} ${toOne.name} = entity.peak${toOne.name?cap_first}();
if(${toOne.name} != null) {
${toOne.targetEntity.pkProperty.javaType} ${toOne.name}__targetKey = ${toOne.name}.get${toOne.targetEntity.pkProperty.propertyName?cap_first}();
<#if !toOne.targetEntity.pkProperty.notNull>
if(${toOne.name}__targetKey != null) {
// TODO bind ${toOne.name}__targetKey
}
<#else>
// TODO bind ${toOne.name}__targetKey
</#if>
}
</#if>
</#list>
}
<#if entity.active>
@Override
protected void attachEntity(${entity.className} entity) {
super.attachEntity(entity);
entity.__setDaoSession(daoSession);
}
</#if>
/** @inheritdoc */
@Override
public ${entity.pkType} readKey(Cursor cursor, int offset) {
<#if entity.pkProperty??>
return <#if !entity.pkProperty.notNull>cursor.isNull(offset + ${entity.pkProperty.ordinal}) ? null : </#if><#if
entity.pkProperty.propertyType == "Byte">(byte) </#if><#if
entity.pkProperty.propertyType == "Date">new java.util.Date(</#if>cursor.get${toCursorType[entity.pkProperty.propertyType]}(offset + ${entity.pkProperty.ordinal})<#if
entity.pkProperty.propertyType == "Boolean"> != 0</#if><#if
entity.pkProperty.propertyType == "Date">)</#if>;
<#else>
return null;
</#if>
}
/** @inheritdoc */
@Override
public ${entity.className} readEntity(Cursor cursor, int offset) {
<#if entity.protobuf>
Builder builder = ${entity.className}.newBuilder();
<#list entity.properties as property>
<#if !property.notNull>
if (!cursor.isNull(offset + ${property_index})) {
</#if> builder.set${property.propertyName?cap_first}(cursor.get${toCursorType[property.propertyType]}(offset + ${property_index}));
<#if !property.notNull>
}
</#if>
</#list>
return builder.build();
<#elseif entity.constructors>
<#--
############################## readEntity non-protobuff, constructor ##############################
-->
${entity.className} entity = new ${entity.className}( //
<#list entity.properties as property>
<#if !property.notNull>cursor.isNull(offset + ${property_index}) ? null : </#if><#--
-->${property.getEntityValueExpression("cursor.get${toCursorType[property.propertyType]}(offset + ${property_index})")}<#--
--><#if property_has_next>,</#if> // ${property.propertyName}
</#list>
);
return entity;
<#else>
<#--
############################## readEntity non-protobuff, setters ##############################
-->
${entity.className} entity = new ${entity.className}();
readEntity(cursor, entity, offset);
return entity;
</#if>
}
/** @inheritdoc */
@Override
public void readEntity(Cursor cursor, ${entity.className} entity, int offset) {
<#if entity.protobuf>
throw new UnsupportedOperationException("Protobuf objects cannot be modified");
<#else>
<#list entity.properties as property>
entity.set${property.propertyName?cap_first}(<#if !property.notNull>cursor.isNull(offset + ${property_index}) ? null : </#if><#--
-->${property.getEntityValueExpression("cursor.get${toCursorType[property.propertyType]}(offset + ${property_index})")});
</#list>
</#if>
}
/** @inheritdoc */
@Override
protected ${entity.pkType} updateKeyAfterInsert(${entity.className} entity, long rowId) {
<#if entity.pkProperty??>
<#if entity.pkProperty.propertyType == "Long">
<#if !entity.protobuf>
entity.set${entity.pkProperty.propertyName?cap_first}(rowId);
</#if>
return rowId;
<#else>
return entity.get${entity.pkProperty.propertyName?cap_first}();
</#if>
<#else>
// Unsupported or missing PK type
return null;
</#if>
}
/** @inheritdoc */
@Override
public ${entity.pkType} getKey(${entity.className} entity) {
<#if entity.pkProperty??>
if(entity != null) {
return entity.get${entity.pkProperty.propertyName?cap_first}();
} else {
return null;
}
<#else>
return null;
</#if>
}
/** @inheritdoc */
@Override
protected boolean isEntityUpdateable() {
return ${(!entity.protobuf)?string};
}
<#list entity.incomingToManyRelations as toMany>
/** Internal query to resolve the "${toMany.name}" to-many relationship of ${toMany.sourceEntity.className}. */
public List<${toMany.targetEntity.className}> _query${toMany.sourceEntity.className?cap_first}_${toMany.name?cap_first}(<#--
--><#if toMany.targetProperties??><#list toMany.targetProperties as property><#--
-->${property.javaType} ${property.propertyName}<#if property_has_next>, </#if></#list><#else><#--
-->${toMany.sourceProperty.javaType} ${toMany.sourceProperty.propertyName}</#if>) {
synchronized (this) {
if (${toMany.sourceEntity.className?uncap_first}_${toMany.name?cap_first}Query == null) {
QueryBuilder<${toMany.targetEntity.className}> queryBuilder = queryBuilder();
<#if toMany.targetProperties??>
<#list toMany.targetProperties as property>
queryBuilder.where(Properties.${property.propertyName?cap_first}.eq(null));
</#list>
<#else>
queryBuilder.join(${toMany.joinEntity.className}.class, ${toMany.joinEntity.classNameDao}.Properties.${toMany.targetProperty.propertyName?cap_first})
.where(${toMany.joinEntity.classNameDao}.Properties.${toMany.sourceProperty.propertyName?cap_first}.eq(${toMany.sourceProperty.propertyName}));
</#if>
<#if toMany.order?has_content>
queryBuilder.orderRaw("${toMany.order}");
</#if>
${toMany.sourceEntity.className?uncap_first}_${toMany.name?cap_first}Query = queryBuilder.build();
}
}
Query<${toMany.targetEntity.className}> query = ${toMany.sourceEntity.className?uncap_first}_${toMany.name?cap_first}Query.forCurrentThread();
<#if toMany.targetProperties??>
<#list toMany.targetProperties as property>
query.setParameter(${property_index}, ${property.propertyName});
</#list>
<#else>
query.setParameter(0, ${toMany.sourceProperty.propertyName});
</#if>
return query.list();
}
</#list>
<#if entity.toOneRelations?has_content>
<#include "dao-deep.ftl">
</#if>
}
+287
View File
@@ -0,0 +1,287 @@
<#--
Copyright (C) 2011-2015 Markus Junginger, greenrobot (http://greenrobot.de)
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 <http://www.gnu.org/licenses/>.
-->
<#assign toBindType = {"Boolean":"Long", "Byte":"Long", "Short":"Long", "Int":"Long", "Long":"Long", "Float":"Double", "Double":"Double", "String":"String", "ByteArray":"Blob" }/>
<#assign toCursorType = {"Boolean":"Short", "Byte":"Short", "Short":"Short", "Int":"Int", "Long":"Long", "Float":"Float", "Double":"Double", "String":"String", "ByteArray":"Blob" }/>
<#assign complexTypes = ["String", "ByteArray", "Date"]/>
package ${entity.javaPackage};
<#if entity.toManyRelations?has_content>
import java.util.List;
</#if>
<#if entity.active>
import ${schema.defaultJavaPackageDao}.DaoSession;
import de.greenrobot.dao.DaoException;
</#if>
<#if entity.additionalImportsEntity?has_content>
<#list entity.additionalImportsEntity as additionalImport>
import ${additionalImport};
</#list>
</#if>
<#if entity.hasKeepSections>
// THIS CODE IS GENERATED BY greenDAO, EDIT ONLY INSIDE THE "KEEP"-SECTIONS
// KEEP INCLUDES - put your custom includes here
<#if keepIncludes?has_content>${keepIncludes!}</#if>// KEEP INCLUDES END
<#else>
// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT. Enable "keep" sections if you want to edit.
</#if>
<#if entity.javaDoc ??>
${entity.javaDoc}
<#else>
/**
* Entity mapped to table "${entity.tableName}".
*/
</#if>
<#if entity.codeBeforeClass ??>
${entity.codeBeforeClass}
</#if>
public class ${entity.className}<#if
entity.superclass?has_content> extends ${entity.superclass} </#if><#if
entity.interfacesToImplement?has_content> implements <#list entity.interfacesToImplement
as ifc>${ifc}<#if ifc_has_next>, </#if></#list></#if> {
<#list entity.properties as property>
<#if property.notNull && complexTypes?seq_contains(property.propertyType)>
/** Not-null value. */
</#if>
<#if property.javaDocField ??>
${property.javaDocField}
</#if>
<#if property.codeBeforeField ??>
${property.codeBeforeField}
</#if>
private ${property.javaTypeInEntity} ${property.propertyName};
</#list>
<#if entity.active>
/** Used to resolve relations */
private transient DaoSession daoSession;
/** Used for active entity operations. */
private transient ${entity.classNameDao} myDao;
<#list entity.toOneRelations as toOne>
private ${toOne.targetEntity.className} ${toOne.name};
<#if toOne.useFkProperty>
private ${toOne.resolvedKeyJavaType[0]} ${toOne.name}__resolvedKey;
<#else>
private boolean ${toOne.name}__refreshed;
</#if>
</#list>
<#list entity.toManyRelations as toMany>
private List<${toMany.targetEntity.className}> ${toMany.name};
</#list>
</#if>
<#if entity.hasKeepSections>
// KEEP FIELDS - put your custom fields here
${keepFields!} // KEEP FIELDS END
</#if>
<#if entity.constructors>
public ${entity.className}() {
}
<#if entity.propertiesPk?has_content && entity.propertiesPk?size != entity.properties?size>
public ${entity.className}(<#list entity.propertiesPk as
property>${property.javaType} ${property.propertyName}<#if property_has_next>, </#if></#list>) {
<#list entity.propertiesPk as property>
this.${property.propertyName} = ${property.propertyName};
</#list>
}
</#if>
public ${entity.className}(<#list entity.properties as
property>${property.javaTypeInEntity} ${property.propertyName}<#if property_has_next>, </#if></#list>) {
<#list entity.properties as property>
this.${property.propertyName} = ${property.propertyName};
</#list>
}
</#if>
<#if entity.active>
/** called by internal mechanisms, do not call yourself. */
public void __setDaoSession(DaoSession daoSession) {
this.daoSession = daoSession;
myDao = daoSession != null ? daoSession.get${entity.classNameDao?cap_first}() : null;
}
</#if>
<#list entity.properties as property>
<#if property.notNull && complexTypes?seq_contains(property.propertyType)>
/** Not-null value. */
</#if>
<#if property.javaDocGetter ??>
${property.javaDocGetter}
</#if>
<#if property.codeBeforeGetter ??>
${property.codeBeforeGetter}
</#if>
public ${property.javaTypeInEntity} get${property.propertyName?cap_first}() {
return ${property.propertyName};
}
<#if property.notNull && complexTypes?seq_contains(property.propertyType)>
/** Not-null value; ensure this value is available before it is saved to the database. */
</#if>
<#if property.javaDocSetter ??>
${property.javaDocSetter}
</#if>
<#if property.codeBeforeSetter ??>
${property.codeBeforeSetter}
</#if>
public void set${property.propertyName?cap_first}(${property.javaTypeInEntity} ${property.propertyName}) {
this.${property.propertyName} = ${property.propertyName};
}
</#list>
<#--
##########################################
########## To-One Relations ##############
##########################################
-->
<#list entity.toOneRelations as toOne>
/** To-one relationship, resolved on first access. */
public ${toOne.targetEntity.className} get${toOne.name?cap_first}() {
<#if toOne.useFkProperty>
${toOne.fkProperties[0].javaType} __key = this.${toOne.fkProperties[0].propertyName};
if (${toOne.name}__resolvedKey == null || <#--
--><#if toOne.resolvedKeyUseEquals[0]>!${toOne.name}__resolvedKey.equals(__key)<#--
--><#else>!${toOne.name}__resolvedKey.equals(__key)</#if>) {
if (daoSession == null) {
throw new DaoException("Entity is detached from DAO context");
}
${toOne.targetEntity.classNameDao} targetDao = daoSession.get${toOne.targetEntity.classNameDao?cap_first}();
${toOne.targetEntity.className} ${toOne.name}New = targetDao.load(__key);
synchronized (this) {
${toOne.name} = ${toOne.name}New;
${toOne.name}__resolvedKey = __key;
}
}
<#else>
if (${toOne.name} != null || !${toOne.name}__refreshed) {
if (daoSession == null) {
throw new DaoException("Entity is detached from DAO context");
}
${toOne.targetEntity.classNameDao} targetDao = daoSession.get${toOne.targetEntity.classNameDao?cap_first}();
targetDao.refresh(${toOne.name});
${toOne.name}__refreshed = true;
}
</#if>
return ${toOne.name};
}
<#if !toOne.useFkProperty>
/** To-one relationship, returned entity is not refreshed and may carry only the PK property. */
public ${toOne.targetEntity.className} peak${toOne.name?cap_first}() {
return ${toOne.name};
}
</#if>
public void set${toOne.name?cap_first}(${toOne.targetEntity.className} ${toOne.name}) {
<#if toOne.fkProperties[0].notNull>
if (${toOne.name} == null) {
throw new DaoException("To-one property '${toOne.fkProperties[0].propertyName}' has not-null constraint; cannot set to-one to null");
}
</#if>
synchronized (this) {
this.${toOne.name} = ${toOne.name};
<#if toOne.useFkProperty>
${toOne.fkProperties[0].propertyName} = <#if !toOne.fkProperties[0].notNull>${toOne.name} == null ? null : </#if>${toOne.name}.get${toOne.targetEntity.pkProperty.propertyName?cap_first}();
${toOne.name}__resolvedKey = ${toOne.fkProperties[0].propertyName};
<#else>
${toOne.name}__refreshed = true;
</#if>
}
}
</#list>
<#--
##########################################
########## To-Many Relations #############
##########################################
-->
<#list entity.toManyRelations as toMany>
/** To-many relationship, resolved on first access (and after reset). Changes to to-many relations are not persisted, make changes to the target entity. */
public List<${toMany.targetEntity.className}> get${toMany.name?cap_first}() {
if (${toMany.name} == null) {
if (daoSession == null) {
throw new DaoException("Entity is detached from DAO context");
}
${toMany.targetEntity.classNameDao} targetDao = daoSession.get${toMany.targetEntity.classNameDao?cap_first}();
List<${toMany.targetEntity.className}> ${toMany.name}New = targetDao._query${toMany.sourceEntity.className?cap_first}_${toMany.name?cap_first}(<#--
--><#if toMany.sourceProperties??><#list toMany.sourceProperties as property>${property.propertyName}<#if property_has_next>, </#if></#list><#else><#--
-->${entity.pkProperty.propertyName}</#if>);
synchronized (this) {<#-- Check if another thread was faster, we cannot lock while doing the query to prevent deadlocks -->
if(${toMany.name} == null) {
${toMany.name} = ${toMany.name}New;
}
}
}
return ${toMany.name};
}
/** Resets a to-many relationship, making the next get call to query for a fresh result. */
public synchronized void reset${toMany.name?cap_first}() {
${toMany.name} = null;
}
</#list>
<#--
##########################################
########## Active entity operations ######
##########################################
-->
<#if entity.active>
/** Convenient call for {@link AbstractDao#delete(Object)}. Entity must attached to an entity context. */
public void delete() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.delete(this);
}
/** Convenient call for {@link AbstractDao#update(Object)}. Entity must attached to an entity context. */
public void update() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.update(this);
}
/** Convenient call for {@link AbstractDao#refresh(Object)}. Entity must attached to an entity context. */
public void refresh() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.refresh(this);
}
</#if>
<#if entity.hasKeepSections>
// KEEP METHODS - put your custom methods here
${keepMethods!} // KEEP METHODS END
</#if>
}
@@ -0,0 +1,79 @@
package de.greenrobot.daogenerator;
import java.util.List;
public class ContentProvider {
private final List<Entity> entities;
private String authority;
private String basePath;
private String className;
private String javaPackage;
private boolean readOnly;
private Schema schema;
public ContentProvider(Schema schema, List<Entity> entities) {
this.schema = schema;
this.entities = entities;
}
public String getAuthority() {
return authority;
}
public void setAuthority(String authority) {
this.authority = authority;
}
public String getBasePath() {
return basePath;
}
public void setBasePath(String basePath) {
this.basePath = basePath;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public String getJavaPackage() {
return javaPackage;
}
public void setJavaPackage(String javaPackage) {
this.javaPackage = javaPackage;
}
public boolean isReadOnly() {
return readOnly;
}
public void readOnly() {
this.readOnly = true;
}
public List<Entity> getEntities() {
return entities;
}
public void init2ndPass() {
if (authority == null) {
authority = schema.getDefaultJavaPackage() + ".provider";
}
if (basePath == null) {
basePath = "";
}
if (className == null) {
className = entities.get(0).getClassName() + "ContentProvider";
}
if (javaPackage == null) {
javaPackage = schema.getDefaultJavaPackage();
}
}
}
@@ -0,0 +1,205 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package de.greenrobot.daogenerator;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import freemarker.template.Configuration;
import freemarker.template.Template;
/**
* Once you have your model created, use this class to generate entities and DAOs.
*
* @author Markus
*/
public class DaoGenerator {
private Pattern patternKeepIncludes;
private Pattern patternKeepFields;
private Pattern patternKeepMethods;
private Template templateDao;
private Template templateDaoMaster;
private Template templateDaoSession;
private Template templateEntity;
private Template templateDaoUnitTest;
private Template templateContentProvider;
public DaoGenerator() throws IOException {
System.out.println("greenDAO Generator");
System.out.println("Copyright 2011-2016 Markus Junginger, greenrobot.de. Licensed under GPL V3.");
System.out.println("This program comes with ABSOLUTELY NO WARRANTY");
patternKeepIncludes = compilePattern("INCLUDES");
patternKeepFields = compilePattern("FIELDS");
patternKeepMethods = compilePattern("METHODS");
Configuration config = new Configuration(Configuration.VERSION_2_3_23);
config.setClassForTemplateLoading(this.getClass(), "/");
templateDao = config.getTemplate("dao.ftl");
templateDaoMaster = config.getTemplate("dao-master.ftl");
templateDaoSession = config.getTemplate("dao-session.ftl");
templateEntity = config.getTemplate("entity.ftl");
templateDaoUnitTest = config.getTemplate("dao-unit-test.ftl");
templateContentProvider = config.getTemplate("content-provider.ftl");
}
private Pattern compilePattern(String sectionName) {
int flags = Pattern.DOTALL | Pattern.MULTILINE;
return Pattern.compile(".*^\\s*?//\\s*?KEEP " + sectionName + ".*?\n(.*?)^\\s*// KEEP " + sectionName
+ " END.*?\n", flags);
}
/** Generates all entities and DAOs for the given schema. */
public void generateAll(Schema schema, String outDir) throws Exception {
generateAll(schema, outDir, null, null);
}
/** Generates all entities and DAOs for the given schema. */
public void generateAll(Schema schema, String outDir, String outDirEntity, String outDirTest) throws Exception {
long start = System.currentTimeMillis();
File outDirFile = toFileForceExists(outDir);
File outDirEntityFile = outDirEntity != null? toFileForceExists(outDirEntity): outDirFile;
File outDirTestFile = outDirTest != null ? toFileForceExists(outDirTest) : null;
schema.init2ndPass();
schema.init3rdPass();
System.out.println("Processing schema version " + schema.getVersion() + "...");
List<Entity> entities = schema.getEntities();
for (Entity entity : entities) {
generate(templateDao, outDirFile, entity.getJavaPackageDao(), entity.getClassNameDao(), schema, entity);
if (!entity.isProtobuf() && !entity.isSkipGeneration()) {
generate(templateEntity, outDirEntityFile, entity.getJavaPackage(), entity.getClassName(), schema, entity);
}
if (outDirTestFile != null && !entity.isSkipGenerationTest()) {
String javaPackageTest = entity.getJavaPackageTest();
String classNameTest = entity.getClassNameTest();
File javaFilename = toJavaFilename(outDirTestFile, javaPackageTest, classNameTest);
if (!javaFilename.exists()) {
generate(templateDaoUnitTest, outDirTestFile, javaPackageTest, classNameTest, schema, entity);
} else {
System.out.println("Skipped " + javaFilename.getCanonicalPath());
}
}
for (ContentProvider contentProvider : entity.getContentProviders()) {
Map<String, Object> additionalObjectsForTemplate = new HashMap<String, Object>();
additionalObjectsForTemplate.put("contentProvider", contentProvider);
generate(templateContentProvider, outDirFile, entity.getJavaPackage(), entity.getClassName()
+ "ContentProvider", schema, entity, additionalObjectsForTemplate);
}
}
generate(templateDaoMaster, outDirFile, schema.getDefaultJavaPackageDao(), "DaoMaster", schema, null);
generate(templateDaoSession, outDirFile, schema.getDefaultJavaPackageDao(), "DaoSession", schema, null);
long time = System.currentTimeMillis() - start;
System.out.println("Processed " + entities.size() + " entities in " + time + "ms");
}
protected File toFileForceExists(String filename) throws IOException {
File file = new File(filename);
if (!file.exists()) {
throw new IOException(filename
+ " does not exist. This check is to prevent accidental file generation into a wrong path.");
}
return file;
}
private void generate(Template template, File outDirFile, String javaPackage, String javaClassName, Schema schema,
Entity entity) throws Exception {
generate(template, outDirFile, javaPackage, javaClassName, schema, entity, null);
}
private void generate(Template template, File outDirFile, String javaPackage, String javaClassName, Schema schema,
Entity entity, Map<String, Object> additionalObjectsForTemplate) throws Exception {
Map<String, Object> root = new HashMap<String, Object>();
root.put("schema", schema);
root.put("entity", entity);
if (additionalObjectsForTemplate != null) {
root.putAll(additionalObjectsForTemplate);
}
try {
File file = toJavaFilename(outDirFile, javaPackage, javaClassName);
file.getParentFile().mkdirs();
if (entity != null && entity.getHasKeepSections()) {
checkKeepSections(file, root);
}
Writer writer = new FileWriter(file);
try {
template.process(root, writer);
writer.flush();
System.out.println("Written " + file.getCanonicalPath());
} finally {
writer.close();
}
} catch (Exception ex) {
System.err.println("Data map for template: " + root);
System.err.println("Error while generating " + javaPackage + "." + javaClassName + " ("
+ outDirFile.getCanonicalPath() + ")");
throw ex;
}
}
private void checkKeepSections(File file, Map<String, Object> root) {
if (file.exists()) {
try {
String contents = new String(DaoUtil.readAllBytes(file));
Matcher matcher;
matcher = patternKeepIncludes.matcher(contents);
if (matcher.matches()) {
root.put("keepIncludes", matcher.group(1));
}
matcher = patternKeepFields.matcher(contents);
if (matcher.matches()) {
root.put("keepFields", matcher.group(1));
}
matcher = patternKeepMethods.matcher(contents);
if (matcher.matches()) {
root.put("keepMethods", matcher.group(1));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
protected File toJavaFilename(File outDirFile, String javaPackage, String javaClassName) {
String packageSubPath = javaPackage.replace('.', '/');
File packagePath = new File(outDirFile, packageSubPath);
File file = new File(packagePath, javaClassName + ".java");
return file;
}
}
@@ -0,0 +1,114 @@
/*
* Copyright (C) 2011-2015 Markus Junginger, greenrobot (http://greenrobot.de)
*
* 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 <http://www.gnu.org/licenses/>.
*/
package de.greenrobot.daogenerator;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/** Internal API */
public class DaoUtil {
public static String dbName(String javaName) {
StringBuilder builder = new StringBuilder(javaName);
for (int i = 1; i < builder.length(); i++) {
boolean lastWasUpper = Character.isUpperCase(builder.charAt(i - 1));
boolean isUpper = Character.isUpperCase(builder.charAt(i));
if (isUpper && !lastWasUpper) {
builder.insert(i, '_');
i++;
}
}
return builder.toString().toUpperCase();
}
public static String getClassnameFromFullyQualified(String clazz) {
int index = clazz.lastIndexOf('.');
if (index != -1) {
return clazz.substring(index + 1);
} else {
return clazz;
}
}
public static String capFirst(String string) {
return Character.toUpperCase(string.charAt(0)) + (string.length() > 1 ? string.substring(1) : "");
}
public static String getPackageFromFullyQualified(String clazz) {
int index = clazz.lastIndexOf('.');
if (index != -1) {
return clazz.substring(0, index);
} else {
return null;
}
}
public static byte[] readAllBytes(InputStream in) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
copyAllBytes(in, out);
return out.toByteArray();
}
public static byte[] readAllBytes(File file) throws IOException {
FileInputStream is = new FileInputStream(file);
try {
return DaoUtil.readAllBytes(is);
} finally {
is.close();
}
}
public static byte[] readAllBytes(String filename) throws IOException {
FileInputStream is = new FileInputStream(filename);
try {
return DaoUtil.readAllBytes(is);
} finally {
is.close();
}
}
/**
* Copies all available data from in to out without closing any stream.
*
* @return number of bytes copied
*/
public static int copyAllBytes(InputStream in, OutputStream out) throws IOException {
int byteCount = 0;
byte[] buffer = new byte[4096];
while (true) {
int read = in.read(buffer);
if (read == -1) {
break;
}
out.write(buffer, 0, read);
byteCount += read;
}
return byteCount;
}
public static String checkConvertToJavaDoc(String javaDoc, String indent) {
if (javaDoc != null && !javaDoc.trim().startsWith("/**")) {
javaDoc = javaDoc.replace("\n", "\n" + indent + " * ");
javaDoc = indent + "/**\n" + indent + " * " + javaDoc + "\n" + indent + " */";
}
return javaDoc;
}
}
@@ -0,0 +1,688 @@
/*
* Copyright (C) 2011-2015 Markus Junginger, greenrobot (http://greenrobot.de)
*
* 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 <http://www.gnu.org/licenses/>.
*/
package de.greenrobot.daogenerator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import de.greenrobot.daogenerator.Property.PropertyBuilder;
/**
* 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). <br/>
* <br/> Use the various addXXX methods to add entity properties, indexes, and relations to other entities (addToOne,
* addToMany).<br/> <br/> There are further configuration possibilities: <ul> <li>{@link
* Entity#implementsInterface(String...)} and {@link #implementsSerializable()} to specify interfaces the entity will
* implement</li> <li>{@link #setSuperclass(String)} to specify a class of which the entity will extend from</li>
* <li>Various setXXX methods</li> </ul>
*
* @see <a href="http://greendao-orm.com/documentation/modelling-entities/">Modelling Entities (Documentation page)</a>
* @see <a href="http://greendao-orm.com/documentation/relations/">Relations (Documentation page)</a>
*/
public class Entity {
private final Schema schema;
private final String className;
private final List<Property> properties;
private List<Property> propertiesColumns;
private final List<Property> propertiesPk;
private final List<Property> propertiesNonPk;
private final Set<String> propertyNames;
private final List<Index> indexes;
private final List<ToOne> toOneRelations;
private final List<ToManyBase> toManyRelations;
private final List<ToManyBase> incomingToManyRelations;
private final Collection<String> additionalImportsEntity;
private final Collection<String> additionalImportsDao;
private final List<String> interfacesToImplement;
private final List<ContentProvider> contentProviders;
private String tableName;
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 skipTableCreation;
private Boolean active;
private Boolean hasKeepSections;
Entity(Schema schema, String className) {
this.schema = schema;
this.className = className;
properties = new ArrayList<Property>();
propertiesPk = new ArrayList<Property>();
propertiesNonPk = new ArrayList<Property>();
propertyNames = new HashSet<String>();
indexes = new ArrayList<Index>();
toOneRelations = new ArrayList<ToOne>();
toManyRelations = new ArrayList<ToManyBase>();
incomingToManyRelations = new ArrayList<ToManyBase>();
additionalImportsEntity = new TreeSet<String>();
additionalImportsDao = new TreeSet<String>();
interfacesToImplement = new ArrayList<String>();
contentProviders = new ArrayList<ContentProvider>();
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 Property.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.columnName("_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.columnName(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<Entity> entities = new ArrayList<Entity>();
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 getTableName() {
return tableName;
}
public void setTableName(String tableName) {
this.tableName = tableName;
}
public String getClassName() {
return className;
}
public List<Property> getProperties() {
return properties;
}
public List<Property> 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<Property> getPropertiesPk() {
return propertiesPk;
}
/** Internal property used by templates, don't use during entity definition. */
public List<Property> getPropertiesNonPk() {
return propertiesNonPk;
}
/** Internal property used by templates, don't use during entity definition. */
public Property getPkProperty() {
return pkProperty;
}
public List<Index> getIndexes() {
return indexes;
}
/** Internal property used by templates, don't use during entity definition. */
public String getPkType() {
return pkType;
}
public boolean isConstructors() {
return constructors;
}
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;
}
/** Flag if CREATE & DROP TABLE scripts should be skipped in Dao. */
public void setSkipTableCreation(boolean skipTableCreation) {
this.skipTableCreation = skipTableCreation;
}
public boolean isSkipTableCreation() {
return skipTableCreation;
}
public boolean isSkipGenerationTest() {
return skipGenerationTest;
}
public void setSkipGenerationTest(boolean skipGenerationTest) {
this.skipGenerationTest = skipGenerationTest;
}
public List<ToOne> getToOneRelations() {
return toOneRelations;
}
public List<ToManyBase> getToManyRelations() {
return toManyRelations;
}
public List<ToManyBase> 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<String> getAdditionalImportsEntity() {
return additionalImportsEntity;
}
public Collection<String> getAdditionalImportsDao() {
return additionalImportsDao;
}
public void setHasKeepSections(Boolean hasKeepSections) {
this.hasKeepSections = hasKeepSections;
}
public List<String> getInterfacesToImplement() {
return interfacesToImplement;
}
public List<ContentProvider> 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);
}
}
if (propertiesPk.size() == 1) {
pkProperty = propertiesPk.get(0);
pkType = schema.mapToJavaTypeNullable(pkProperty.getPropertyType());
} else {
pkType = "Void";
}
propertiesColumns = new ArrayList<Property>(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 (tableName == null) {
tableName = DaoUtil.dbName(className);
}
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_" + getTableName();
List<Property> properties = index.getProperties();
for (int j = 0; j < properties.size(); j++) {
Property property = properties.get(j);
indexName += "_" + property.getColumnName();
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.setName(indexName);
}
}
}
void init3rdPass() {
for (Property property : properties) {
property.init3ndPass();
}
init3rdPassRelations();
init3rdPassAdditionalImports();
}
private void init3rdPassRelations() {
Set<String> toOneNames = new HashSet<String>();
for (ToOne toOne : toOneRelations) {
toOne.init3ndPass();
if (!toOneNames.add(toOne.getName().toLowerCase())) {
throw new RuntimeException("Duplicate name for " + toOne);
}
}
Set<String> toManyNames = new HashSet<String>();
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
if (!targetEntity.getJavaPackage().equals(javaPackageDao)) {
additionalImportsDao.add(targetEntity.getJavaPackage() + "." + targetEntity.getClassName());
}
}
for (ToManyBase toMany : toManyRelations) {
Entity targetEntity = toMany.getTargetEntity();
checkAdditionalImportsEntityTargetEntity(targetEntity);
}
for (Property property : properties) {
String customType = property.getCustomType();
if (customType != null) {
String pack = DaoUtil.getPackageFromFullyQualified(customType);
if (!pack.equals(javaPackage)) {
additionalImportsEntity.add(customType);
}
if (!pack.equals(javaPackageDao)) {
additionalImportsDao.add(customType);
}
}
String converter = property.getConverter();
if (converter != null) {
String pack = DaoUtil.getPackageFromFullyQualified(converter);
if (!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());
}
}
public void validatePropertyExists(Property property) {
if (!properties.contains(property)) {
throw new RuntimeException("Property " + property + " does not exist in " + this);
}
}
@Override
public String toString() {
return "Entity " + className + " (package: " + javaPackage + ")";
}
}
@@ -0,0 +1,43 @@
/*
* Copyright (C) 2011 Markus Junginger, greenrobot (http://greenrobot.de)
*
* 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 <http://www.gnu.org/licenses/>.
*/
package de.greenrobot.daogenerator;
public class Index extends PropertyOrderList {
private String name;
private boolean unique;
public String getName() {
return name;
}
public Index setName(String name) {
this.name = name;
return this;
}
public Index makeUnique() {
unique = true;
return this;
}
public boolean isUnique() {
return unique;
}
}
@@ -0,0 +1,421 @@
/*
* Copyright (C) 2011-2015 Markus Junginger, greenrobot (http://greenrobot.de)
*
* 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 <http://www.gnu.org/licenses/>.
*/
package de.greenrobot.daogenerator;
/** Model class for an entity's property: a Java property mapped to a data base column. */
public class Property {
public static class PropertyBuilder {
private final Property property;
public PropertyBuilder(Schema schema, Entity entity, PropertyType propertyType, String propertyName) {
property = new Property(schema, entity, propertyType, propertyName);
}
public PropertyBuilder columnName(String columnName) {
property.columnName = columnName;
return this;
}
public PropertyBuilder columnType(String columnType) {
property.columnType = columnType;
return this;
}
public PropertyBuilder primaryKey() {
property.primaryKey = true;
return this;
}
public PropertyBuilder primaryKeyAsc() {
property.primaryKey = true;
property.pkAsc = true;
return this;
}
public PropertyBuilder primaryKeyDesc() {
property.primaryKey = true;
property.pkDesc = true;
return this;
}
public PropertyBuilder autoincrement() {
if (!property.primaryKey || property.propertyType != PropertyType.Long) {
throw new RuntimeException(
"AUTOINCREMENT is only available to primary key properties of type long/Long");
}
property.pkAutoincrement = true;
return this;
}
public PropertyBuilder unique() {
property.unique = true;
return this;
}
public PropertyBuilder notNull() {
property.notNull = true;
return this;
}
public PropertyBuilder index() {
Index index = new Index();
index.addProperty(property);
property.entity.addIndex(index);
return this;
}
public PropertyBuilder indexAsc(String indexNameOrNull, boolean isUnique) {
Index index = new Index();
index.addPropertyAsc(property);
if (isUnique) {
index.makeUnique();
}
index.setName(indexNameOrNull);
property.entity.addIndex(index);
return this;
}
public PropertyBuilder indexDesc(String indexNameOrNull, boolean isUnique) {
Index index = new Index();
index.addPropertyDesc(property);
if (isUnique) {
index.makeUnique();
}
index.setName(indexNameOrNull);
property.entity.addIndex(index);
return this;
}
public PropertyBuilder customType(String customType, String converter) {
property.customType = customType;
property.customTypeClassName = DaoUtil.getClassnameFromFullyQualified(customType);
property.converter = converter;
property.converterClassName = DaoUtil.getClassnameFromFullyQualified(converter);
return this;
}
public PropertyBuilder codeBeforeField(String code) {
property.codeBeforeField = code;
return this;
}
public PropertyBuilder codeBeforeGetter(String code) {
property.codeBeforeGetter = code;
return this;
}
public PropertyBuilder codeBeforeSetter(String code) {
property.codeBeforeSetter = code;
return this;
}
public PropertyBuilder codeBeforeGetterAndSetter(String code) {
property.codeBeforeGetter = code;
property.codeBeforeSetter = code;
return this;
}
public PropertyBuilder javaDocField(String javaDoc) {
property.javaDocField = checkConvertToJavaDoc(javaDoc);
return this;
}
private String checkConvertToJavaDoc(String javaDoc) {
return DaoUtil.checkConvertToJavaDoc(javaDoc, " ");
}
public PropertyBuilder javaDocGetter(String javaDoc) {
property.javaDocGetter = checkConvertToJavaDoc(javaDoc);
return this;
}
public PropertyBuilder javaDocSetter(String javaDoc) {
property.javaDocSetter = checkConvertToJavaDoc(javaDoc);
return this;
}
public PropertyBuilder javaDocGetterAndSetter(String javaDoc) {
javaDoc = checkConvertToJavaDoc(javaDoc);
property.javaDocGetter = javaDoc;
property.javaDocSetter = javaDoc;
return this;
}
public Property getProperty() {
return property;
}
}
private final Schema schema;
private final Entity entity;
private PropertyType propertyType;
private final String propertyName;
private String columnName;
private String columnType;
private String customType;
private String customTypeClassName;
private String converter;
private String converterClassName;
private String codeBeforeField;
private String codeBeforeGetter;
private String codeBeforeSetter;
private String javaDocField;
private String javaDocGetter;
private String javaDocSetter;
private boolean primaryKey;
private boolean pkAsc;
private boolean pkDesc;
private boolean pkAutoincrement;
private boolean unique;
private boolean notNull;
/** Initialized in 2nd pass */
private String constraints;
private int ordinal;
private String javaType;
public Property(Schema schema, Entity entity, PropertyType propertyType, String propertyName) {
this.schema = schema;
this.entity = entity;
this.propertyName = propertyName;
this.propertyType = propertyType;
}
public String getPropertyName() {
return propertyName;
}
public PropertyType getPropertyType() {
return propertyType;
}
public void setPropertyType(PropertyType propertyType) {
this.propertyType = propertyType;
}
public String getColumnName() {
return columnName;
}
public String getColumnType() {
return columnType;
}
public boolean isPrimaryKey() {
return primaryKey;
}
public boolean isAutoincrement() {
return pkAutoincrement;
}
public String getConstraints() {
return constraints;
}
public boolean isUnique() {
return unique;
}
public boolean isNotNull() {
return notNull;
}
public String getJavaType() {
return javaType;
}
public String getJavaTypeInEntity() {
if (customTypeClassName != null) {
return customTypeClassName;
} else {
return javaType;
}
}
public int getOrdinal() {
return ordinal;
}
void setOrdinal(int ordinal) {
this.ordinal = ordinal;
}
public String getCustomType() {
return customType;
}
public String getCustomTypeClassName() {
return customTypeClassName;
}
public String getConverter() {
return converter;
}
public String getConverterClassName() {
return converterClassName;
}
public String getCodeBeforeField() {
return codeBeforeField;
}
public String getCodeBeforeGetter() {
return codeBeforeGetter;
}
public String getCodeBeforeSetter() {
return codeBeforeSetter;
}
public String getJavaDocField() {
return javaDocField;
}
public String getJavaDocGetter() {
return javaDocGetter;
}
public String getJavaDocSetter() {
return javaDocSetter;
}
public String getDatabaseValueExpression() {
return getDatabaseValueExpression(propertyName);
}
public String getDatabaseValueExpressionNotNull() {
return getDatabaseValueExpression("entity.get" + DaoUtil.capFirst(propertyName) + "()");
}
// Got too messy in template:
// <#if property.customType?has_content>${property.propertyName}Converter.convertToDatabaseValue(</#if><#--
// -->entity.get${property.propertyName?cap_first}()<#if property.customType?has_content>)</#if><#if
// property.propertyType == "Boolean"> ? 1l: 0l</#if><#if property.propertyType == "Date">.getTime()</#if>
public String getDatabaseValueExpression(String entityValue) {
StringBuilder builder = new StringBuilder();
if (customType != null) {
builder.append(propertyName).append("Converter.convertToDatabaseValue(");
}
builder.append(entityValue);
if (customType != null) {
builder.append(')');
}
if (propertyType == PropertyType.Boolean) {
builder.append(" ? 1L: 0L");
} else if (propertyType == PropertyType.Date) {
builder.append(".getTime()");
}
return builder.toString();
}
// Got too messy in template:
// <#if property.propertyType == "Byte">(byte) </#if>
// <#if property.propertyType == "Date">new java.util.Date(</#if>
// cursor.get${toCursorType[property.propertyType]}(offset + ${property_index})
// <#if property.propertyType == "Boolean"> != 0</#if>
// <#if property.propertyType == "Date">)</#if>
public String getEntityValueExpression(String databaseValue) {
StringBuilder builder = new StringBuilder();
if (customType != null) {
builder.append(propertyName).append("Converter.convertToEntityProperty(");
}
if (propertyType == PropertyType.Byte) {
builder.append("(byte) ");
} else if (propertyType == PropertyType.Date) {
builder.append("new java.util.Date(");
}
builder.append(databaseValue);
if (propertyType == PropertyType.Boolean) {
builder.append(" != 0");
} else if (propertyType == PropertyType.Date) {
builder.append(")");
}
if (customType != null) {
builder.append(')');
}
return builder.toString();
}
public Entity getEntity() {
return entity;
}
void init2ndPass() {
initConstraint();
if (columnType == null) {
columnType = schema.mapToDbType(propertyType);
}
if (columnName == null) {
columnName = DaoUtil.dbName(propertyName);
}
if (notNull) {
javaType = schema.mapToJavaTypeNotNull(propertyType);
} else {
javaType = schema.mapToJavaTypeNullable(propertyType);
}
}
private void initConstraint() {
StringBuilder constraintBuilder = new StringBuilder();
if (primaryKey) {
constraintBuilder.append("PRIMARY KEY");
if (pkAsc) {
constraintBuilder.append(" ASC");
}
if (pkDesc) {
constraintBuilder.append(" DESC");
}
if (pkAutoincrement) {
constraintBuilder.append(" AUTOINCREMENT");
}
}
// Always have String PKs NOT NULL because SQLite is pretty strange in this respect:
// One could insert multiple rows with NULL PKs
if (notNull || (primaryKey && propertyType == PropertyType.String)) {
constraintBuilder.append(" NOT NULL");
}
if (unique) {
constraintBuilder.append(" UNIQUE");
}
String newContraints = constraintBuilder.toString().trim();
if (constraintBuilder.length() > 0) {
constraints = newContraints;
}
}
void init3ndPass() {
// Nothing to do so far
}
@Override
public String toString() {
return "Property " + propertyName + " of " + entity.getClassName();
}
}
@@ -0,0 +1,86 @@
/*
* Copyright (C) 2011-2015 Markus Junginger, greenrobot (http://greenrobot.de)
*
* 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 <http://www.gnu.org/licenses/>.
*/
package de.greenrobot.daogenerator;
import java.util.ArrayList;
import java.util.List;
public class PropertyOrderList {
private List<Property> properties;
private List<String> propertiesOrder;
public PropertyOrderList() {
properties = new ArrayList<Property>();
propertiesOrder = new ArrayList<String>();
}
public void addProperty(Property property) {
properties.add(property);
propertiesOrder.add(null);
}
public void addPropertyAsc(Property property) {
properties.add(property);
propertiesOrder.add("ASC");
}
public void addPropertyDesc(Property property) {
properties.add(property);
propertiesOrder.add("DESC");
}
public void addOrderRaw(String order) {
properties.add(null);
propertiesOrder.add(order);
}
public List<Property> getProperties() {
return properties;
}
List<String> getPropertiesOrder() {
return propertiesOrder;
}
public String getCommaSeparatedString(String tablePrefixOrNull) {
StringBuilder builder = new StringBuilder();
int size = properties.size();
for (int i = 0; i < size; i++) {
Property property = properties.get(i);
String order = propertiesOrder.get(i);
if (property != null) {
if(tablePrefixOrNull != null) {
builder.append(tablePrefixOrNull).append('.');
}
builder.append('\'').append(property.getColumnName()).append('\'').append(' ');
}
if (order != null) {
builder.append(order);
}
if (i < size - 1) {
builder.append(',');
}
}
return builder.toString();
}
public boolean isEmpty() {
return properties.isEmpty();
}
}
@@ -0,0 +1,27 @@
/*
* Copyright (C) 2011 Markus Junginger, greenrobot (http://greenrobot.de)
*
* 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 <http://www.gnu.org/licenses/>.
*/
package de.greenrobot.daogenerator;
/**
* Currently available types for properties.
*
* @author Markus
*/
public enum PropertyType {
Byte, Short, Int, Long, Boolean, Float, Double, String, ByteArray, Date
}
@@ -0,0 +1,51 @@
/*
* Copyright (C) 2011 Markus Junginger, greenrobot (http://greenrobot.de)
*
* 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 <http://www.gnu.org/licenses/>.
*/
package de.greenrobot.daogenerator;
import java.util.ArrayList;
import java.util.List;
/** NOT IMPLEMENTED YET. Check back later. */
public class Query {
@SuppressWarnings("unused")
private String name;
private List<QueryParam> parameters;
@SuppressWarnings("unused")
private boolean distinct;
public Query(String name) {
this.name = name;
parameters= new ArrayList<QueryParam>();
}
public QueryParam addEqualsParam(Property column) {
return addParam(column, "=");
}
public QueryParam addParam(Property column, String operator) {
QueryParam queryParam = new QueryParam(column, operator);
parameters.add(queryParam);
return queryParam;
}
public void distinct() {
distinct = true;
}
}
@@ -0,0 +1,38 @@
/*
* Copyright (C) 2011 Markus Junginger, greenrobot (http://greenrobot.de)
*
* 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 <http://www.gnu.org/licenses/>.
*/
package de.greenrobot.daogenerator;
/** NOT IMPLEMENTED YET. Check back later. */
public class QueryParam {
private Property column;
private String operator;
public QueryParam(Property column, String operator) {
this.column = column;
this.operator = operator;
}
public Property getColumn() {
return column;
}
public String getOperator() {
return operator;
}
}
@@ -0,0 +1,189 @@
/*
* Copyright (C) 2011-2015 Markus Junginger, greenrobot (http://greenrobot.de)
*
* 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 <http://www.gnu.org/licenses/>.
*/
package de.greenrobot.daogenerator;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* The "root" model class to which you can add entities to.
*
* @see <a href="http://greendao-orm.com/documentation/modelling-entities/">Modelling Entities (Documentation page)</a>
*/
public class Schema {
private final int version;
private final String defaultJavaPackage;
private String defaultJavaPackageDao;
private String defaultJavaPackageTest;
private final List<Entity> entities;
private Map<PropertyType, String> propertyToDbType;
private Map<PropertyType, String> propertyToJavaTypeNotNull;
private Map<PropertyType, String> propertyToJavaTypeNullable;
private boolean hasKeepSectionsByDefault;
private boolean useActiveEntitiesByDefault;
public Schema(int version, String defaultJavaPackage) {
this.version = version;
this.defaultJavaPackage = defaultJavaPackage;
this.entities = new ArrayList<Entity>();
initTypeMappings();
}
public void enableKeepSectionsByDefault() {
hasKeepSectionsByDefault = true;
}
public void enableActiveEntitiesByDefault() {
useActiveEntitiesByDefault = true;
}
private void initTypeMappings() {
propertyToDbType = new HashMap<PropertyType, String>();
propertyToDbType.put(PropertyType.Boolean, "INTEGER");
propertyToDbType.put(PropertyType.Byte, "INTEGER");
propertyToDbType.put(PropertyType.Short, "INTEGER");
propertyToDbType.put(PropertyType.Int, "INTEGER");
propertyToDbType.put(PropertyType.Long, "INTEGER");
propertyToDbType.put(PropertyType.Float, "REAL");
propertyToDbType.put(PropertyType.Double, "REAL");
propertyToDbType.put(PropertyType.String, "TEXT");
propertyToDbType.put(PropertyType.ByteArray, "BLOB");
propertyToDbType.put(PropertyType.Date, "INTEGER");
propertyToJavaTypeNotNull = new HashMap<PropertyType, String>();
propertyToJavaTypeNotNull.put(PropertyType.Boolean, "boolean");
propertyToJavaTypeNotNull.put(PropertyType.Byte, "byte");
propertyToJavaTypeNotNull.put(PropertyType.Short, "short");
propertyToJavaTypeNotNull.put(PropertyType.Int, "int");
propertyToJavaTypeNotNull.put(PropertyType.Long, "long");
propertyToJavaTypeNotNull.put(PropertyType.Float, "float");
propertyToJavaTypeNotNull.put(PropertyType.Double, "double");
propertyToJavaTypeNotNull.put(PropertyType.String, "String");
propertyToJavaTypeNotNull.put(PropertyType.ByteArray, "byte[]");
propertyToJavaTypeNotNull.put(PropertyType.Date, "java.util.Date");
propertyToJavaTypeNullable = new HashMap<PropertyType, String>();
propertyToJavaTypeNullable.put(PropertyType.Boolean, "Boolean");
propertyToJavaTypeNullable.put(PropertyType.Byte, "Byte");
propertyToJavaTypeNullable.put(PropertyType.Short, "Short");
propertyToJavaTypeNullable.put(PropertyType.Int, "Integer");
propertyToJavaTypeNullable.put(PropertyType.Long, "Long");
propertyToJavaTypeNullable.put(PropertyType.Float, "Float");
propertyToJavaTypeNullable.put(PropertyType.Double, "Double");
propertyToJavaTypeNullable.put(PropertyType.String, "String");
propertyToJavaTypeNullable.put(PropertyType.ByteArray, "byte[]");
propertyToJavaTypeNullable.put(PropertyType.Date, "java.util.Date");
}
/**
* Adds a new entity to the schema. There can be multiple entities per table, but only one may be the primary entity
* per table to create table scripts, etc.
*/
public Entity addEntity(String className) {
Entity entity = new Entity(this, className);
entities.add(entity);
return entity;
}
/**
* Adds a new protocol buffers entity to the schema. There can be multiple entities per table, but only one may be
* the primary entity per table to create table scripts, etc.
*/
public Entity addProtobufEntity(String className) {
Entity entity = addEntity(className);
entity.useProtobuf();
return entity;
}
public String mapToDbType(PropertyType propertyType) {
return mapType(propertyToDbType, propertyType);
}
public String mapToJavaTypeNullable(PropertyType propertyType) {
return mapType(propertyToJavaTypeNullable, propertyType);
}
public String mapToJavaTypeNotNull(PropertyType propertyType) {
return mapType(propertyToJavaTypeNotNull, propertyType);
}
private String mapType(Map<PropertyType, String> map, PropertyType propertyType) {
String dbType = map.get(propertyType);
if (dbType == null) {
throw new IllegalStateException("No mapping for " + propertyType);
}
return dbType;
}
public int getVersion() {
return version;
}
public String getDefaultJavaPackage() {
return defaultJavaPackage;
}
public String getDefaultJavaPackageDao() {
return defaultJavaPackageDao;
}
public void setDefaultJavaPackageDao(String defaultJavaPackageDao) {
this.defaultJavaPackageDao = defaultJavaPackageDao;
}
public String getDefaultJavaPackageTest() {
return defaultJavaPackageTest;
}
public void setDefaultJavaPackageTest(String defaultJavaPackageTest) {
this.defaultJavaPackageTest = defaultJavaPackageTest;
}
public List<Entity> getEntities() {
return entities;
}
public boolean isHasKeepSectionsByDefault() {
return hasKeepSectionsByDefault;
}
public boolean isUseActiveEntitiesByDefault() {
return useActiveEntitiesByDefault;
}
void init2ndPass() {
if (defaultJavaPackageDao == null) {
defaultJavaPackageDao = defaultJavaPackage;
}
if (defaultJavaPackageTest == null) {
defaultJavaPackageTest = defaultJavaPackageDao;
}
for (Entity entity : entities) {
entity.init2ndPass();
}
}
void init3rdPass() {
for (Entity entity : entities) {
entity.init3rdPass();
}
}
}
@@ -0,0 +1,81 @@
/*
* Copyright (C) 2011-2015 Markus Junginger, greenrobot (http://greenrobot.de)
*
* 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 <http://www.gnu.org/licenses/>.
*/
package de.greenrobot.daogenerator;
import java.util.List;
/** To-many relationship from a source entity to many target entities. */
public class ToMany extends ToManyBase {
@SuppressWarnings("unused")
private Property[] sourceProperties;
private final Property[] targetProperties;
public ToMany(Schema schema, Entity sourceEntity, Property[] sourceProperties, Entity targetEntity,
Property[] targetProperties) {
super(schema, sourceEntity, targetEntity);
this.sourceProperties = sourceProperties;
this.targetProperties = targetProperties;
}
public Property[] getSourceProperties() {
return sourceProperties;
}
public void setSourceProperties(Property[] sourceProperties) {
this.sourceProperties = sourceProperties;
}
public Property[] getTargetProperties() {
return targetProperties;
}
void init2ndPass() {
super.init2ndPass();
if (sourceProperties == null) {
List<Property> pks = sourceEntity.getPropertiesPk();
if (pks.isEmpty()) {
throw new RuntimeException("Source entity has no primary key, but we need it for " + this);
}
sourceProperties = new Property[pks.size()];
sourceProperties = pks.toArray(sourceProperties);
}
int count = sourceProperties.length;
if (count != targetProperties.length) {
throw new RuntimeException("Source properties do not match target properties: " + this);
}
for (int i = 0; i < count; i++) {
Property sourceProperty = sourceProperties[i];
Property targetProperty = targetProperties[i];
PropertyType sourceType = sourceProperty.getPropertyType();
PropertyType targetType = targetProperty.getPropertyType();
if (sourceType == null || targetType == null) {
throw new RuntimeException("Property type uninitialized");
}
if (sourceType != targetType) {
System.err.println("Warning to-one property type does not match target key type: " + this);
}
}
}
void init3rdPass() {
super.init3rdPass();
}
}
@@ -0,0 +1,99 @@
/*
* Copyright (C) 2011-2015 Markus Junginger, greenrobot (http://greenrobot.de)
*
* 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 <http://www.gnu.org/licenses/>.
*/
package de.greenrobot.daogenerator;
/** Base class for to-many relationship from source entities to target entities. */
public abstract class ToManyBase {
@SuppressWarnings("unused")
private final Schema schema;
private String name;
protected final Entity sourceEntity;
protected final Entity targetEntity;
private final PropertyOrderList propertyOrderList;
public ToManyBase(Schema schema, Entity sourceEntity, Entity targetEntity) {
this.schema = schema;
this.sourceEntity = sourceEntity;
this.targetEntity = targetEntity;
propertyOrderList = new PropertyOrderList();
}
public Entity getSourceEntity() {
return sourceEntity;
}
public Entity getTargetEntity() {
return targetEntity;
}
public String getName() {
return name;
}
/**
* Sets the name of the relation, which is used as the property name in the entity (the source entity owning the
* to-many relationship).
*/
public void setName(String name) {
this.name = name;
}
/** Property of target entity used for ascending order. */
public void orderAsc(Property... properties) {
for (Property property : properties) {
targetEntity.validatePropertyExists(property);
propertyOrderList.addPropertyAsc(property);
}
}
/** Property of target entity used for descending order. */
public void orderDesc(Property... properties) {
for (Property property : properties) {
targetEntity.validatePropertyExists(property);
propertyOrderList.addPropertyDesc(property);
}
}
public String getOrder() {
if (propertyOrderList.isEmpty()) {
return null;
} else {
// Table prefix must match default of QueryBuilder in DaoCore
return propertyOrderList.getCommaSeparatedString("T");
}
}
void init2ndPass() {
if (name == null) {
char[] nameCharArray = targetEntity.getClassName().toCharArray();
nameCharArray[0] = Character.toLowerCase(nameCharArray[0]);
name = new String(nameCharArray) + "List";
}
}
void init3rdPass() {
}
@Override
public String toString() {
String sourceName = sourceEntity != null ? sourceEntity.getClassName() : null;
String targetName = targetEntity != null ? targetEntity.getClassName() : null;
return "ToMany '" + name + "' from " + sourceName + " to " + targetName;
}
}
@@ -0,0 +1,60 @@
/*
* Copyright (C) 2011-2015 Markus Junginger, greenrobot (http://greenrobot.de)
*
* 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 <http://www.gnu.org/licenses/>.
*/
package de.greenrobot.daogenerator;
import java.util.List;
/** To-many relationship to many target entities using a join entity (aka JOIN table). */
public class ToManyWithJoinEntity extends ToManyBase {
private final Entity joinEntity;
private final Property sourceProperty;
private final Property targetProperty;
public ToManyWithJoinEntity(Schema schema, Entity sourceEntity, Entity targetEntity, Entity joinEntity,
Property sourceProperty, Property targetProperty) {
super(schema, sourceEntity, targetEntity);
this.joinEntity = joinEntity;
this.sourceProperty = sourceProperty;
this.targetProperty = targetProperty;
}
public Entity getJoinEntity() {
return joinEntity;
}
public Property getSourceProperty() {
return sourceProperty;
}
public Property getTargetProperty() {
return targetProperty;
}
void init3rdPass() {
super.init3rdPass();
List<Property> pks = sourceEntity.getPropertiesPk();
if (pks.isEmpty()) {
throw new RuntimeException("Source entity has no primary key, but we need it for " + this);
}
List<Property> pks2 = targetEntity.getPropertiesPk();
if (pks2.isEmpty()) {
throw new RuntimeException("Target entity has no primary key, but we need it for " + this);
}
}
}
@@ -0,0 +1,134 @@
/*
* Copyright (C) 2011 Markus Junginger, greenrobot (http://greenrobot.de)
*
* 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 <http://www.gnu.org/licenses/>.
*/
package de.greenrobot.daogenerator;
/** To-one relationship from a source entity to one (or zero) target entity. */
public class ToOne {
private final Schema schema;
private final Entity sourceEntity;
private final Entity targetEntity;
private final Property[] fkProperties;
private final String[] resolvedKeyJavaType;
private final boolean[] resolvedKeyUseEquals;
private String name;
private final boolean useFkProperty;
public ToOne(Schema schema, Entity sourceEntity, Entity targetEntity, Property[] fkProperties, boolean useFkProperty) {
this.schema = schema;
this.sourceEntity = sourceEntity;
this.targetEntity = targetEntity;
this.fkProperties = fkProperties;
this.useFkProperty = useFkProperty;
resolvedKeyJavaType = new String[fkProperties.length];
resolvedKeyUseEquals = new boolean[fkProperties.length];
}
public Entity getSourceEntity() {
return sourceEntity;
}
public Entity getTargetEntity() {
return targetEntity;
}
public Property[] getFkProperties() {
return fkProperties;
}
public String[] getResolvedKeyJavaType() {
return resolvedKeyJavaType;
}
public boolean[] getResolvedKeyUseEquals() {
return resolvedKeyUseEquals;
}
public String getName() {
return name;
}
/**
* Sets the name of the relation, which is used as the property name in the entity (the source entity owning the
* to-many relationship).
*/
public void setName(String name) {
this.name = name;
}
public boolean isUseFkProperty() {
return useFkProperty;
}
void init2ndPass() {
if (name == null) {
char[] nameCharArray = targetEntity.getClassName().toCharArray();
nameCharArray[0] = Character.toLowerCase(nameCharArray[0]);
name = new String(nameCharArray);
}
}
/** Constructs fkColumns. Depends on 2nd pass of target key properties. */
void init3ndPass() {
Property targetPkProperty = targetEntity.getPkProperty();
if (fkProperties.length != 1 || targetPkProperty == null) {
throw new RuntimeException("Currently only single FK columns are supported: " + this);
}
Property property = fkProperties[0];
PropertyType propertyType = property.getPropertyType();
if (propertyType == null) {
propertyType = targetPkProperty.getPropertyType();
property.setPropertyType(propertyType);
// Property is not a regular property with primitive getters/setters, so let it catch up
property.init2ndPass();
property.init3ndPass();
} else if (propertyType != targetPkProperty.getPropertyType()) {
System.err.println("Warning to-one property type does not match target key type: " + this);
}
resolvedKeyJavaType[0] = schema.mapToJavaTypeNullable(propertyType);
resolvedKeyUseEquals[0] = checkUseEquals(propertyType);
}
protected boolean checkUseEquals(PropertyType propertyType) {
boolean useEquals;
switch (propertyType) {
case Byte:
case Short:
case Int:
case Long:
case Boolean:
case Float:
useEquals = true;
break;
default:
useEquals = false;
break;
}
return useEquals;
}
@Override
public String toString() {
String sourceName = sourceEntity != null ? sourceEntity.getClassName() : null;
String targetName = targetEntity != null ? targetEntity.getClassName() : null;
return "ToOne '" + name + "' from " + sourceName + " to " + targetName;
}
}
+1
View File
@@ -26,6 +26,7 @@ vendor's servers.
* Files in app/src/main/java/org/bouncycastle are taken from the [Bouncy Castle](https://www.bouncycastle.org/java.html) project, licensed under the MIT license by The Legion of the Bouncy Castle Inc.
* Files in app/src/main/java/com/android/nQuant are taken from the [nQuant.android](https://github.com/mcychan/nQuant.android/) project, licensed under the Apache license by Miller Cy Chan
* Files in app/src/main/java/org/concentus are taken from the [Concentus](https://github.com/lostromb/concentus) project, licensed under the BSD-3 license by various holding parties
* Files in GBDaoGenerator/src/de/greenrobot are taken from the [greenDAO](https://codeberg.org/Freeyourgadget/greenDAO) project (Gadgetbridge's fork), licensed under the GPLv3 by Markus Junginger, greenrobot
## Download
-3
View File
@@ -20,9 +20,6 @@ buildscript {
allprojects {
repositories {
mavenCentral()
maven {
url = 'https://jitpack.io'
}
google()
}
}