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

com.abubusoft.kripton.processor.sqlite.BindM2MBuilder Maven / Gradle / Ivy

There is a newer version: 8.2.0-rc.4
Show newest version
/*******************************************************************************
 * Copyright 2015, 2017 Francesco Benincasa ([email protected]).
 *
 * 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.
 *******************************************************************************/
/**
 * 
 */
package com.abubusoft.kripton.processor.sqlite;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.annotation.processing.Filer;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;

import com.abubusoft.kripton.android.ColumnType;
import com.abubusoft.kripton.android.annotation.BindSqlColumn;
import com.abubusoft.kripton.android.annotation.BindDao;
import com.abubusoft.kripton.android.annotation.BindDaoMany2Many;
import com.abubusoft.kripton.android.annotation.BindGeneratedDao;
import com.abubusoft.kripton.android.annotation.BindSqlDelete;
import com.abubusoft.kripton.android.annotation.BindSqlInsert;
import com.abubusoft.kripton.android.annotation.BindSqlParam;
import com.abubusoft.kripton.android.annotation.BindSqlSelect;
import com.abubusoft.kripton.android.annotation.BindSqlType;
import com.abubusoft.kripton.android.sqlite.ForeignKeyAction;
import com.abubusoft.kripton.common.CaseFormat;
import com.abubusoft.kripton.common.Converter;
import com.abubusoft.kripton.common.One;
import com.abubusoft.kripton.common.Pair;
import com.abubusoft.kripton.processor.BaseProcessor;
import com.abubusoft.kripton.processor.bind.JavaWriterHelper;
import com.abubusoft.kripton.processor.bind.model.many2many.M2MEntity;
import com.abubusoft.kripton.processor.bind.model.many2many.M2MModel;
import com.abubusoft.kripton.processor.core.AnnotationAttributeType;
import com.abubusoft.kripton.processor.core.reflect.AnnotationUtility.MethodFoundListener;
import com.abubusoft.kripton.processor.core.reflect.TypeUtility;
import com.abubusoft.kripton.processor.element.GeneratedTypeElement;
import com.abubusoft.kripton.processor.sqlite.core.JavadocUtility;
import com.abubusoft.kripton.processor.sqlite.model.SQLProperty;
import com.abubusoft.kripton.processor.utils.AnnotationProcessorUtilis;
import com.squareup.javapoet.AnnotationSpec;
import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.TypeSpec;

/**
 * The Class BindM2MBuilder.
 *
 * @author Francesco Benincasa ([email protected])
 */
public class BindM2MBuilder extends AbstractBuilder {

	/** The Constant PREFIX. */
	public static final String PREFIX = "Bind";

	/** The Constant SUFFIX. */
	public static final String SUFFIX = "Cursor";

	/** The entity result. */
	private static Set entityResult = new HashSet();
	
	/** The dao result. */
	private static Set daoResult = new HashSet();

	/**
	 * Instantiates a new bind M 2 M builder.
	 *
	 * @param filer the filer
	 */
	public BindM2MBuilder(Filer filer) {
		super(BaseProcessor.elementUtils, filer, null);
	}

	/**
	 * Generate.
	 *
	 * @param filer the filer
	 * @param model the model
	 * @return the pair
	 * @throws Exception the exception
	 */
	public static Pair, Set> generate(Filer filer, M2MModel model) throws Exception {
		entityResult.clear();
		daoResult.clear();
		BindM2MBuilder visitor = new BindM2MBuilder(filer);

		for (M2MEntity item : model.getEntities()) {
			visitor.generate(item);
		}

		Pair, Set> result = new Pair<>();
		result.value0 = entityResult;
		result.value1 = daoResult;

		return result;
	}

	/**
	 * Generate.
	 *
	 * @param entity the entity
	 * @throws Exception the exception
	 */
	public void generate(M2MEntity entity) throws Exception {
		generateEntity(entity);
		generateDaoPart(entity);
	}

	/**
	 * Generate dao part.
	 *
	 * @param entity the entity
	 * @throws IOException Signals that an I/O exception has occurred.
	 */
	private void generateDaoPart(M2MEntity entity) throws IOException {
		String daoClassName = entity.daoName.simpleName();

		String daoPackageName = entity.daoName.packageName();
		String entityPackageName=entity.getPackageName();
		String generatedDaoClassName = "Generated" + daoClassName;

		AnnotationProcessorUtilis.infoOnGeneratedClasses(BindDaoMany2Many.class, daoPackageName, generatedDaoClassName);
		//@formatter:off
		classBuilder = TypeSpec.interfaceBuilder(generatedDaoClassName)
				.addModifiers(Modifier.PUBLIC)				
				.addAnnotation(AnnotationSpec.builder(BindDao.class)
						.addMember("value", "$T.class",TypeUtility.className(entityPackageName, entity.name)).build())
				.addAnnotation(AnnotationSpec.builder(BindGeneratedDao.class)
						.addMember("dao", "$T.class",entity.daoName).build())
				.addAnnotation(AnnotationSpec.builder(BindDaoMany2Many.class)											
						.addMember("entity1", "$T.class",entity.entity1Name)
						.addMember("entity2", "$T.class",entity.entity2Name)
						.build())
				.addSuperinterface(entity.daoName);		
		//@formatter:on

		JavadocUtility.generateJavadocGeneratedBy(classBuilder);

		if (entity.generateMethods) {
			generateSelects(entity, entityPackageName);
			generateDeletes(entity, entityPackageName);
			generateInsert(entity, entityPackageName);
		}

		TypeSpec typeSpec = classBuilder.build();

		JavaWriterHelper.writeJava2File(filer, daoPackageName, typeSpec);

		GeneratedTypeElement daoPartElement = new GeneratedTypeElement(daoPackageName, classBuilder.build(), null, null);
		daoResult.add(daoPartElement);
	}

	/**
	 * Generate selects.
	 *
	 * @param entity the entity
	 * @param packageName the package name
	 */
	private void generateSelects(M2MEntity entity, String packageName) {
		String idPart = CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, entity.idName);

		String methodName = "";
		String workId = "";

		methodName = "selectBy" + idPart;
		if (!isMethodAlreadyDefined(entity, methodName)) {
			//@formatter:off
			MethodSpec methodSpec = MethodSpec.methodBuilder(methodName)
					.addModifiers(Modifier.PUBLIC)
					.addModifiers(Modifier.ABSTRACT)
					.addAnnotation(AnnotationSpec.builder(BindSqlSelect.class).addMember("where", "$S",entity.idName+"=${"+entity.idName+"}").build())
					.addParameter(ParameterSpec.builder(Long.TYPE, entity.idName)
							.addAnnotation(AnnotationSpec.builder(BindSqlParam.class).addMember("value", "$S",entity.idName).build()).build())
					.returns(TypeUtility.className(packageName, entity.name))				
					.build(); 
			//@formatter:on
			classBuilder.addMethod(methodSpec);
		}

		methodName = entity.entity1Name.simpleName() + CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, entity.idName);
		workId = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, methodName);
		methodName = "selectBy" + methodName;
		if (!isMethodAlreadyDefined(entity, methodName)) {
			//@formatter:off
			MethodSpec methodSpec = MethodSpec.methodBuilder(methodName)
					.addModifiers(Modifier.PUBLIC)
					.addModifiers(Modifier.ABSTRACT)
					.addAnnotation(AnnotationSpec.builder(BindSqlSelect.class).addMember("where", "$S",workId+"=${"+workId+"}").build())
					.addParameter(ParameterSpec.builder(Long.TYPE, workId)
							.addAnnotation(AnnotationSpec.builder(BindSqlParam.class).addMember("value", "$S",workId).build()).build())
					.returns(TypeUtility.parameterizedTypeName(TypeUtility.className(List.class), TypeUtility.className(packageName, entity.name)))				
					.build();
			//@formatter:on
			classBuilder.addMethod(methodSpec);
		}

		methodName = entity.entity2Name.simpleName() + CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, entity.idName);
		workId = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, methodName);
		methodName = "selectBy" + methodName;
		if (!isMethodAlreadyDefined(entity, methodName)) {

			//@formatter:off
			MethodSpec methodSpec = MethodSpec.methodBuilder(methodName)
					.addModifiers(Modifier.PUBLIC)
					.addModifiers(Modifier.ABSTRACT)
					.addAnnotation(AnnotationSpec.builder(BindSqlSelect.class).addMember("where", "$S",workId+"=${"+workId+"}").build())
					.addParameter(ParameterSpec.builder(Long.TYPE, workId)
							.addAnnotation(AnnotationSpec.builder(BindSqlParam.class).addMember("value", "$S",workId).build()).build())
					.returns(TypeUtility.parameterizedTypeName(TypeUtility.className(List.class), TypeUtility.className(packageName, entity.name)))				
					.build();
			//@formatter:on
			classBuilder.addMethod(methodSpec);
		}
	}

	/**
	 * analyze DAO definition to check if method is already defined.
	 *
	 * @param entity the entity
	 * @param methodName the method name
	 * @return true, if is method already defined
	 */
	private boolean isMethodAlreadyDefined(M2MEntity entity, final String methodName) {

		final One found = new One(false);
		SqlBuilderHelper.forEachMethods(entity.daoElement, new MethodFoundListener() {

			@Override
			public void onMethod(ExecutableElement executableMethod) {
				if (executableMethod.getSimpleName().toString().equals(methodName)) {
					found.value0 = true;
				}

			}
		});

		return found.value0;
	}

	/**
	 * Generate deletes.
	 *
	 * @param entity the entity
	 * @param packageName the package name
	 */
	private void generateDeletes(M2MEntity entity, String packageName) {
		String idPart = CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, entity.idName);

		String methodName = "";
		String workId = "";

		methodName = "deleteBy" + idPart;
		if (!isMethodAlreadyDefined(entity, methodName)) {
		//@formatter:off
		MethodSpec methodSpec = MethodSpec.methodBuilder(methodName)
				.addModifiers(Modifier.PUBLIC)
				.addModifiers(Modifier.ABSTRACT)
				.addAnnotation(AnnotationSpec.builder(BindSqlDelete.class).addMember("where", "$S",entity.idName+"=${"+entity.idName+"}").build())
				.addParameter(ParameterSpec.builder(Long.TYPE, entity.idName)
						.addAnnotation(AnnotationSpec.builder(BindSqlParam.class).addMember("value", "$S",entity.idName).build()).build())
				.returns(Integer.TYPE)				
				.build(); 
		//@formatter:on
			classBuilder.addMethod(methodSpec);
		}

		methodName = entity.entity1Name.simpleName() + CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, entity.idName);
		workId = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, methodName);
		methodName = "deleteBy" + methodName;
		if (!isMethodAlreadyDefined(entity, methodName)) {

			//@formatter:off
			MethodSpec methodSpec = MethodSpec.methodBuilder(methodName)
					.addModifiers(Modifier.PUBLIC)
					.addModifiers(Modifier.ABSTRACT)
					.addAnnotation(AnnotationSpec.builder(BindSqlDelete.class).addMember("where", "$S",workId+"=${"+workId+"}").build())
					.addParameter(ParameterSpec.builder(Long.TYPE, workId)
							.addAnnotation(AnnotationSpec.builder(BindSqlParam.class).addMember("value", "$S",workId).build()).build())
					.returns(Integer.TYPE)				
					.build();
			//@formatter:on
			classBuilder.addMethod(methodSpec);
		}

		methodName = entity.entity2Name.simpleName() + CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, entity.idName);
		workId = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, methodName);
		methodName = "deleteBy" + methodName;
		if (!isMethodAlreadyDefined(entity, methodName)) {
			//@formatter:off
			MethodSpec methodSpec = MethodSpec.methodBuilder(methodName)
					.addModifiers(Modifier.PUBLIC)
					.addModifiers(Modifier.ABSTRACT)
					.addAnnotation(AnnotationSpec.builder(BindSqlDelete.class).addMember("where", "$S",workId+"=${"+workId+"}").build())
					.addParameter(ParameterSpec.builder(Long.TYPE, workId)
							.addAnnotation(AnnotationSpec.builder(BindSqlParam.class).addMember("value", "$S",workId).build()).build())
					.returns(Integer.TYPE)				
					.build();
			//@formatter:on
			classBuilder.addMethod(methodSpec);
		}
	}

	/**
	 * Generate insert.
	 *
	 * @param entity the entity
	 * @param packageName the package name
	 */
	private void generateInsert(M2MEntity entity, String packageName) {
		if (!isMethodAlreadyDefined(entity, "insert")) {
		//@formatter:off
		MethodSpec methodSpec = MethodSpec.methodBuilder("insert")
				.addModifiers(Modifier.PUBLIC)
				.addModifiers(Modifier.ABSTRACT)
				.addAnnotation(AnnotationSpec.builder(BindSqlInsert.class).build())
				.addParameter(ParameterSpec.builder(TypeUtility.className(packageName, entity.name), "bean")
						.addAnnotation(AnnotationSpec.builder(BindSqlParam.class).addMember("value", "$S","bean").build()).build())
				.returns(Integer.TYPE)				
				.build(); 
		//@formatter:on
			classBuilder.addMethod(methodSpec);
		}
	}

	/**
	 * Generate entity.
	 *
	 * @param entity the entity
	 * @throws IOException Signals that an I/O exception has occurred.
	 */
	private void generateEntity(M2MEntity entity) throws IOException {
		if (!entity.needToCreate)
			return;

		String tableName = entity.tableName;
		String entityClassName = entity.name;

		AnnotationProcessorUtilis.infoOnGeneratedClasses(BindDaoMany2Many.class, entity.getPackageName(), entityClassName);
		//@formatter:off
		classBuilder = TypeSpec.classBuilder(entityClassName)
				.addModifiers(Modifier.PUBLIC)				
				.addAnnotation(AnnotationSpec.builder(BindSqlType.class).addMember("name", "$S",tableName).build());
		//@formatter:on

		// javadoc for class
		classBuilder.addJavadoc("

"); classBuilder.addJavadoc("\nGenerated entity implementation for $L\n", entity.name); classBuilder.addJavadoc("

\n"); JavadocUtility.generateJavadocGeneratedBy(classBuilder); // classBuilder.addJavadoc(" @see $T\n", // TypeUtility.className(entity.getElement().getQualifiedName().toString())); { //@formatter:off FieldSpec fieldSpec = FieldSpec.builder(Long.TYPE, entity.idName, Modifier.PUBLIC) .addJavadoc("Primary key\n") .addAnnotation(AnnotationSpec.builder(BindSqlColumn.class) .addMember("columnType","$T.$L", ColumnType.class, ColumnType.PRIMARY_KEY).build()) .build(); //@formatter:on classBuilder.addField(fieldSpec); } Converter converterFK = CaseFormat.LOWER_CAMEL.converterTo(CaseFormat.UPPER_CAMEL); Converter converterFieldName = CaseFormat.UPPER_CAMEL.converterTo(CaseFormat.LOWER_CAMEL); Converter converterField2ColumnName = CaseFormat.LOWER_CAMEL.converterTo(CaseFormat.LOWER_UNDERSCORE); String fkPrefix = converterFK.convert(entity.idName); String fk1Name = converterField2ColumnName.convert(entity.entity1Name.simpleName() + fkPrefix); String fk2Name = converterField2ColumnName.convert(entity.entity2Name.simpleName() + fkPrefix); String field1Name = converterFieldName.convert(entity.entity1Name.simpleName() + fkPrefix); String field2Name = converterFieldName.convert(entity.entity2Name.simpleName() + fkPrefix); { //@formatter:off FieldSpec fieldSpec = FieldSpec.builder(Long.TYPE, field1Name, Modifier.PUBLIC) .addJavadoc("Foreign key to $T model class\n", entity.entity1Name) .addAnnotation(AnnotationSpec.builder(BindSqlColumn.class) .addMember(AnnotationAttributeType.PARENT_ENTITY.getValue(),"$T.class", entity.entity1Name) .addMember(AnnotationAttributeType.ON_DELETE.getValue(),"$T.$L", ForeignKeyAction.class, ForeignKeyAction.CASCADE).build()) .build(); //@formatter:on classBuilder.addField(fieldSpec); } { //@formatter:off FieldSpec fieldSpec = FieldSpec.builder(Long.TYPE, field2Name, Modifier.PUBLIC) .addJavadoc("Foreign key to $T model class\n", entity.entity2Name) .addAnnotation(AnnotationSpec.builder(BindSqlColumn.class) .addMember(AnnotationAttributeType.PARENT_ENTITY.getValue(),"$T.class", entity.entity2Name) .addMember(AnnotationAttributeType.ON_DELETE.getValue(),"$T.$L", ForeignKeyAction.class, ForeignKeyAction.CASCADE).build()) .build(); //@formatter:on classBuilder.addField(fieldSpec); } TypeSpec typeSpec = classBuilder.build(); JavaWriterHelper.writeJava2File(filer, entity.getPackageName(), typeSpec); List properties = new ArrayList(); { SQLProperty property = new SQLProperty(entity.idName, entity.getClassName()); property.columnType = ColumnType.PRIMARY_KEY; property.columnName = entity.idName; property.setNullable(false); property.setPrimaryKey(true); property.foreignParentClassName = null; properties.add(property); } { SQLProperty property = new SQLProperty(field1Name, entity.getClassName()); property.columnType = ColumnType.INDEXED; property.columnName = fk1Name; property.setNullable(false); property.setPrimaryKey(false); property.onDeleteAction = ForeignKeyAction.CASCADE; property.foreignParentClassName = entity.entity1Name.toString(); properties.add(property); } { SQLProperty property = new SQLProperty(field2Name, entity.getClassName()); property.columnType = ColumnType.INDEXED; property.columnName = fk2Name; property.setNullable(false); property.setPrimaryKey(false); property.onDeleteAction = ForeignKeyAction.CASCADE; property.foreignParentClassName = entity.entity2Name.toString(); properties.add(property); } GeneratedTypeElement entityElement = new GeneratedTypeElement(entity.getPackageName(), classBuilder.build(), tableName, fk1Name + ", " + fk2Name); entityElement.properties = properties; entityResult.add(entityElement); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy