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

org.teamapps.universaldb.generator.PojoCodeGenerator Maven / Gradle / Ivy

/*-
 * ========================LICENSE_START=================================
 * UniversalDB
 * ---
 * Copyright (C) 2014 - 2024 TeamApps.org
 * ---
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * =========================LICENSE_END==================================
 */
package org.teamapps.universaldb.generator;

import org.teamapps.universaldb.model.*;
import org.teamapps.universaldb.pojo.template.PojoTemplate;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

public class PojoCodeGenerator {


	public static final String UDB_PREFIX = "Udb";
	public static final String QUERY_SUFFIX = "Query";

	private static String tabs(int count) {
		return "\t".repeat(count);
	}

	private static String withQuotes(String value) {
		return value != null ? "\"" + value + "\"" : "null";
	}

	private static String withQuotes(List values) {
		return values.stream().map(s -> "\"" + s + "\"").collect(Collectors.joining(", "));
	}

	private static String withBoolean(boolean value) {
		return value ? "true" : "false";
	}

	public void generateCode(DatabaseModel databaseModel, File basePath) throws IOException {
		String namespace = databaseModel.getNamespace();
		File baseDir = createBaseDir(basePath, namespace);
		createModelProviderClass(databaseModel, baseDir);

		File dbPojoDir = new File(baseDir, databaseModel.getName().toLowerCase());
		dbPojoDir.mkdir();
		String packageName = namespace + "." + databaseModel.getName().toLowerCase();

		for (EnumModel enumModel : databaseModel.getEnums()) {
			File dir = dbPojoDir;
			String classPackageName = packageName;
			if (enumModel.isRemoteEnum()) {
				classPackageName = enumModel.getRemoteDatabaseNamespace() + "." + enumModel.getRemoteDatabase().toLowerCase();
				dir = createBaseDir(basePath, classPackageName);
			}
			createEnum(enumModel, dir, classPackageName);
		}

		for (ViewModel viewModel : databaseModel.getViews()) {

		}

		for (TableModel table : databaseModel.getTables()) {
			File dir = dbPojoDir;
			String classPackageName = packageName;
			List remoteTableNamespaces = databaseModel.getRemoteTableNamespaces();
			if (table.isRemoteTable() && table.getRemoteDatabaseNamespace() != null) {
				classPackageName = table.getRemoteDatabaseNamespace() + "." + table.getRemoteDatabase().toLowerCase();
				dir = createBaseDir(basePath, classPackageName);
			}
			createTablePojo(table, dir, classPackageName, remoteTableNamespaces);
			createTableQueryPojo(table, dir, classPackageName, remoteTableNamespaces);
		}

	}

	public String createModelProviderCode(DatabaseModel model) throws IOException {
		PojoTemplate tpl = PojoTemplate.createModelProviderCodeTpl();
		createModelProviderClass(tpl, model);
		return tpl.writeTemplateCode();
	}

	public String createModelProviderClassCode(DatabaseModel model) throws IOException {
		PojoTemplate tpl = PojoTemplate.createModelProviderClass();
		createModelProviderClass(tpl, model);
		return tpl.writeTemplateCode();
	}

	public void createModelProviderClass(DatabaseModel model, File baseDir) throws IOException {
		PojoTemplate tpl = PojoTemplate.createModelProviderClass();
		String type = tpl.firstUpper(model.getModelClassName());
		createModelProviderClass(tpl, model);
		tpl.writeTemplate(type, baseDir);
	}

	public void createModelProviderClass(PojoTemplate tpl, DatabaseModel model) throws IOException {
		tpl.setValue("package", model.getNamespace());
		String type = tpl.firstUpper(model.getModelClassName());
		StringBuilder sb = new StringBuilder();

		sb.append(tabs(2))
				.append("DatabaseModel model = new DatabaseModel(")
				.append(withQuotes(model.getName())).append(", ")
				.append(withQuotes(model.getTitle())).append(", ")
				.append(withQuotes(model.getNamespace())).append(", ")
				.append(withQuotes(model.getModelClassName())).append(");")
				.append(tpl.nl());
		sb.append(tabs(2)).append("model.setPojoBuildTime(").append(System.currentTimeMillis()).append("L);").append(tpl.nl());

		for (EnumModel enumModel : model.getEnums().stream().sorted(Comparator.comparing(EnumModel::getName)).toList()) {
			String enumCreateMethod = enumModel.isRemoteEnum() ? "createRemoteEnum" : "createEnum";
			sb.append(tabs(2))
					.append("EnumModel ").append(enumModel.getName()).append(" = ")
					.append("model.").append(enumCreateMethod).append("(")
					.append(withQuotes(enumModel.getName())).append(", ")
					.append(withQuotes(enumModel.getTitle())).append(", ")
					.append("Arrays.asList(").append(withQuotes(enumModel.getEnumNames())).append("), ")
					.append("Arrays.asList(").append(withQuotes(enumModel.getEnumTitles())).append(")");
			if (enumModel.isRemoteEnum()) {
				sb.append(withQuotes(enumModel.getRemoteDatabase())).append(", ");
				sb.append(withQuotes(enumModel.getRemoteDatabaseNamespace()));
			}
			sb.append(");").append(tpl.nl());
		}
		sb.append(tpl.nl());
		for (TableModel table : model.getLocalTables().stream().sorted(Comparator.comparing(TableModel::getName)).toList()) {
			sb.append(tabs(2))
					.append("TableModel ")
					.append(table.getName()).append(" = ")
					.append("model.createTable(")
					.append(withQuotes(table.getName())).append(", ")
					.append(withQuotes(table.getTitle())).append(", ")
					.append(withBoolean(table.isTrackModifications())).append(", ")
					.append(withBoolean(table.isVersioning())).append(", ")
					.append(withBoolean(table.isRecoverableRecords())).append(");")
					.append(tpl.nl());
		}

		sb.append("\n");
		for (TableModel table : model.getRemoteTables().stream().sorted(Comparator.comparing(TableModel::getName)).toList()) {
			sb.append(tabs(2))
					.append("TableModel ")
					.append(table.getName()).append(" = ")
					.append("model.createRemoteTable(")
					.append(withQuotes(table.getName())).append(", ")
					.append(withQuotes(table.getTitle())).append(", ")
					.append(withQuotes(table.getRemoteTableName())).append(", ")
					.append(withQuotes(table.getRemoteDatabase())).append(", ")
					.append(withQuotes(table.getRemoteDatabaseNamespace())).append(");")
					.append(tpl.nl());
		}

		for (TableModel table : model.getTables().stream().sorted(Comparator.comparing(TableModel::getName)).toList()) {
			sb.append(tpl.nl());
			for (FieldModel field : table.getFields().stream().filter(f -> !f.isMetaField()).toList()) {
				sb.append(tabs(2))
						.append(table.getName()).append(".")
						.append(getAddMethodName(field.getFieldType())).append("(")
						.append(withQuotes(field.getName())).append(", ")
						.append(withQuotes(field.getTitle()));
				if (field.getFieldType().isReference()) {
					ReferenceFieldModel referenceFieldModel = (ReferenceFieldModel) field;
					sb.append(", ")
							.append(referenceFieldModel.getReferencedTable().getName()).append(", ")
							.append(withBoolean(referenceFieldModel.isCascadeDelete()));
				} else if (field.getFieldType().isEnum()) {
					EnumFieldModel enumFieldModel = (EnumFieldModel) field;
					sb.append(", ")
							.append(enumFieldModel.getEnumModel().getName());
				} else if (field.getFieldType().isFile()) {
					FileFieldModel fileFieldModel = (FileFieldModel) field;
					sb.append(", ")
							.append(withBoolean(fileFieldModel.isIndexContent())).append(", ")
							.append(fileFieldModel.getMaxIndexContentLength()).append(", ")
							.append(withBoolean(fileFieldModel.isDetectLanguage()));
				}
				sb.append(");").append(tpl.nl());
			}
		}
		sb.append(tpl.nl());

		for (TableModel table : model.getTables().stream().sorted(Comparator.comparing(TableModel::getName)).toList()) {
			for (ReferenceFieldModel referenceField : table.getReferenceFields().stream().filter(rf -> rf.getReverseReferenceField() != null).toList()) {
				sb.append(tabs(2))
						.append("model.addReverseReferenceField(")
						.append(table.getName()).append(", ")
						.append(withQuotes(referenceField.getName())).append(", ")
						.append(referenceField.getReferencedTable().getName()).append(", ")
						.append(withQuotes(referenceField.getReverseReferenceField().getName()))
						.append(");").append(tpl.nl());
			}
		}

		tpl.setValue("type", type);
		tpl.setValue("model", sb.toString());
	}

	private String getAddMethodName(FieldType type) {
		return switch (type) {
			case BOOLEAN -> "addBoolean";
			case SHORT -> "addShort";
			case INT -> "addInteger";
			case LONG -> "addLong";
			case FLOAT -> "addFloat";
			case DOUBLE -> "addDouble";
			case TEXT -> "addText";
			case TRANSLATABLE_TEXT -> "addTranslatableText";
			case FILE -> "addFile";
			case SINGLE_REFERENCE -> "addReference";
			case MULTI_REFERENCE -> "addMultiReference";
			case TIMESTAMP -> "addTimestamp";
			case DATE -> "addDate";
			case TIME -> "addTime";
			case DATE_TIME -> "addDateTime";
			case LOCAL_DATE -> "addLocalDate";
			case ENUM -> "addEnum";
			case BINARY -> "addByteArray";
			case CURRENCY -> "addCurrency";
			case DYNAMIC_CURRENCY -> "addDynamicCurrency";
		};
	}

	private void createEnum(EnumModel enumModel, File dbPojoDir, String packageName) throws IOException {
		PojoTemplate enumTpl = PojoTemplate.createEnum();
		String enumType = enumTpl.firstUpper(enumModel.getName());
		enumTpl.setValue("package", packageName);
		enumTpl.setValue("type", enumType);
		List enumValues = new ArrayList<>();
		for (int i = 0; i < enumModel.getEnumNames().size(); i++) {
			String enumValue = enumModel.getEnumNames().get(i);
			String enumTitle = enumModel.getEnumTitles().get(i);
			enumValues.add("\t" + enumTpl.createConstantName(enumValue) + "(\"" + enumTitle + "\"),");
		}
		enumTpl.setValue("enumValues", enumValues.stream().collect(Collectors.joining("\n")));
		enumTpl.writeTemplate(enumType, dbPojoDir);
	}

	private void createTablePojo(TableModel table, File dbPojoDir, String packageName, List importNamespaces) throws IOException {
		PojoTemplate tpl = table.isRemoteTable() ? PojoTemplate.createEntityViewInterface() : PojoTemplate.createEntityInterface();
		PojoTemplate udbTpl = table.isRemoteTable() ? PojoTemplate.createUdbEntityView() : PojoTemplate.createUdbEntity();
		String type = tpl.firstUpper(table.getName());
		String udbType = UDB_PREFIX + type;
		String query = type + QUERY_SUFFIX;
		String udbQuery = UDB_PREFIX + query;
		String imports = importNamespaces.stream().map(s -> "import " + s + ".*;").collect(Collectors.joining("\n"));
		tpl.setValue("package", packageName);
		tpl.setValue("type", type);
		tpl.setValue("udbType", udbType);
		tpl.setValue("query", query);
		tpl.setValue("udbQuery", udbQuery);
		tpl.setValue("imports", imports);

		udbTpl.setValue("package", packageName);
		udbTpl.setValue("type", type);
		udbTpl.setValue("udbType", udbType);
		udbTpl.setValue("imports", imports);

		List staticFieldNames = new ArrayList<>();
		List staticFields = new ArrayList<>();
		List staticFieldSetters = new ArrayList<>();
		staticFields.add("\t" + "protected static TableIndex table;");
		staticFields.add("\t" + "protected static UniversalDB universalDB;");

		for (FieldModel fieldModel : table.getFields()) {
			String staticFieldName = "FIELD_" + tpl.createConstantName(fieldModel.getName());
			staticFieldNames.add("\t" + "final static String " + staticFieldName + " = \"" + fieldModel.getName() + "\";");
			staticFields.add("\t" + "protected static " + tpl.getIndexTypeName(fieldModel.getFieldType()) + " " + fieldModel.getName() + ";");
			staticFieldSetters.add("\t\t" + fieldModel.getName() + " = (" + tpl.getIndexTypeName(fieldModel.getFieldType()) + ") tableIndex.getFieldIndex(" + staticFieldName + ");");

			int version = 0;
			boolean loop1 = true;
			boolean loop2 = true;
			boolean loop3 = true;
			boolean loop4 = true;
			while (loop1 || loop2 || loop3 || loop4) {
				version++;
				loop1 = tpl.addInterfaceGetMethod(fieldModel, version);
				if (!table.isRemoteTable()) {
					loop2 = tpl.addInterfaceSetMethod(fieldModel, table, version);
				} else {
					loop2 = false;
				}
				loop3 = udbTpl.addUdbEntityGetMethod(fieldModel, version);
				if (!table.isRemoteTable()) {
					loop4 = udbTpl.addUdbEntitySetMethod(fieldModel, table, version);
				} else {
					loop4 = false;
				}
			}
		}

		tpl.setValue("staticFieldNames", staticFieldNames.stream().collect(Collectors.joining("\n")));
		udbTpl.setValue("staticFields", staticFields.stream().collect(Collectors.joining("\n")));
		udbTpl.setValue("staticFieldSetters", staticFieldSetters.stream().collect(Collectors.joining("\n")));

		tpl.writeTemplate(type, dbPojoDir);
		udbTpl.writeTemplate(udbType, dbPojoDir);
	}

	private void createTableQueryPojo(TableModel table, File dbPojoDir, String packageName, List importNamespaces) throws IOException {
		PojoTemplate tpl = PojoTemplate.createQueryInterface();
		PojoTemplate udbTpl = PojoTemplate.createUdbQuery();
		String type = tpl.firstUpper(table.getName());
		String udbType = UDB_PREFIX + type;
		String query = type + QUERY_SUFFIX;
		String udbQuery = UDB_PREFIX + query;
		String imports = importNamespaces.stream().map(s -> "import " + s + ".*;").collect(Collectors.joining("\n"));
		tpl.setValue("package", packageName);
		tpl.setValue("type", type);
		tpl.setValue("udbType", udbType);
		tpl.setValue("query", query);
		tpl.setValue("udbQuery", udbQuery);
		tpl.setValue("imports", imports);

		udbTpl.setValue("package", packageName);
		udbTpl.setValue("type", type);
		udbTpl.setValue("udbType", udbType);
		udbTpl.setValue("query", query);
		udbTpl.setValue("udbQuery", udbQuery);
		udbTpl.setValue("imports", imports);

		for (FieldModel fieldModel : table.getFields()) {
			tpl.addSubQueryInterfaceMethod(fieldModel, query);
			tpl.addQueryInterfaceMethod(fieldModel, query, false);
			tpl.addQueryInterfaceMethod(fieldModel, query, true);
			udbTpl.addUdbSubQueryMethod(fieldModel, query, type);
			udbTpl.addUdbQueryMethod(fieldModel, query, type, false);
			udbTpl.addUdbQueryMethod(fieldModel, query, type, true);
		}

		tpl.writeTemplate(query, dbPojoDir);
		udbTpl.writeTemplate(udbQuery, dbPojoDir);
	}

	private File createBaseDir(File basePath, String nameSpace) {
		nameSpace = nameSpace.toLowerCase();
		String[] parts = nameSpace.split("\\.");
		basePath.mkdir();
		File path = basePath;
		for (String part : parts) {
			path = new File(path, part);
			path.mkdir();
		}
		System.out.println("name-space:" + nameSpace + ", path:" + path.getPath());
		return path;
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy