Skip to content

Commit

Permalink
Generator: Introduce SqlAdapters
Browse files Browse the repository at this point in the history
  • Loading branch information
minborg committed Oct 3, 2016
1 parent 810a521 commit 08b958c
Show file tree
Hide file tree
Showing 9 changed files with 350 additions and 24 deletions.
Expand Up @@ -59,12 +59,14 @@ public final class StandardTranslatorKey {
public final static TranslatorKey<Table, Class>
ENTITY_IMPL = TranslatorKey.of("EntityImpl", Class.class),
MANAGER_IMPL = TranslatorKey.of("ManagerImpl", Class.class),
SQL_ADAPTER = TranslatorKey.of("SqlAdapter", Class.class),
GENERATED_ENTITY_IMPL = TranslatorKey.of("GeneratedEntityImpl", Class.class),
GENERATED_MANAGER_IMPL = TranslatorKey.of("GeneratedManagerImpl", Class.class);
GENERATED_MANAGER_IMPL = TranslatorKey.of("GeneratedManagerImpl", Class.class),
GENERATED_SQL_ADAPTER = TranslatorKey.of("GeneratedSqlAdapter", Class.class);

/**
* Returns a stream of the standard {@link TranslatorKey Translator Keys}
* that is used on a 'per project' basis.
* that is used on a per project basis.
*
* @return stream of standard project {@link TranslatorKey Translator Keys}
*/
Expand Down
Expand Up @@ -32,16 +32,18 @@
import com.speedment.generator.standard.lifecycle.GeneratedMetadataTranslator;
import com.speedment.generator.standard.manager.GeneratedManagerImplTranslator;
import com.speedment.generator.standard.manager.GeneratedManagerTranslator;
import com.speedment.generator.standard.manager.GeneratedSqlAdapterTranslator;
import com.speedment.generator.standard.manager.ManagerImplTranslator;
import com.speedment.generator.standard.manager.ManagerTranslator;
import com.speedment.generator.standard.manager.SqlAdapterTranslator;
import com.speedment.generator.translator.component.CodeGenerationComponent;
import com.speedment.runtime.config.Project;
import com.speedment.runtime.config.Table;

/**
*
* @author Emil Forslund
* @since 3.0.1
* @author Emil Forslund
* @since 3.0.1
*/
public final class StandardTranslatorComponent {

Expand All @@ -51,10 +53,12 @@ void installTranslators(@WithState(INITIALIZED) CodeGenerationComponent codeGen)
codeGen.put(Table.class, ENTITY_IMPL, EntityImplTranslator::new);
codeGen.put(Table.class, MANAGER, ManagerTranslator::new);
codeGen.put(Table.class, MANAGER_IMPL, ManagerImplTranslator::new);
codeGen.put(Table.class, SQL_ADAPTER, SqlAdapterTranslator::new);
codeGen.put(Table.class, GENERATED_ENTITY, GeneratedEntityTranslator::new);
codeGen.put(Table.class, GENERATED_ENTITY_IMPL, GeneratedEntityImplTranslator::new);
codeGen.put(Table.class, GENERATED_MANAGER, GeneratedManagerTranslator::new);
codeGen.put(Table.class, GENERATED_MANAGER_IMPL, GeneratedManagerImplTranslator::new);
codeGen.put(Table.class, GENERATED_SQL_ADAPTER, GeneratedSqlAdapterTranslator::new);
codeGen.put(Project.class, APPLICATION, ApplicationTranslator::new);
codeGen.put(Project.class, APPLICATION_IMPL, ApplicationImplTranslator::new);
codeGen.put(Project.class, APPLICATION_BUILDER, ApplicationBuilderTranslator::new);
Expand All @@ -63,4 +67,4 @@ void installTranslators(@WithState(INITIALIZED) CodeGenerationComponent codeGen)
codeGen.put(Project.class, GENERATED_APPLICATION_BUILDER, GeneratedApplicationBuilderTranslator::new);
codeGen.put(Project.class, GENERATED_METADATA, GeneratedMetadataTranslator::new);
}
}
}
Expand Up @@ -36,11 +36,8 @@

import static com.speedment.common.codegen.constant.DefaultAnnotationUsage.OVERRIDE;
import static com.speedment.common.codegen.internal.util.Formatting.*;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.joining;
import static com.speedment.generator.standard.manager.GeneratedManagerImplTranslator.ENTITY_CREATE_METHOD_NAME;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.joining;

/**
*
Expand Down Expand Up @@ -101,7 +98,7 @@ public interface ReadFromResultSet {
public static String[] generateNewEntityFromBody(ReadFromResultSet readFromResultSet, TranslatorSupport<Table> support, File file, Supplier<Stream<? extends Column>> columnsSupplier) {

final List<String> rows = new LinkedList<>();
rows.add("final " + support.entityName() + " entity = " + ENTITY_CREATE_METHOD_NAME + "();");
rows.add("final " + support.entityName() + " entity = manager." + ENTITY_CREATE_METHOD_NAME + "();");

final Stream.Builder<String> streamBuilder = Stream.builder();

Expand Down
Expand Up @@ -241,7 +241,7 @@ protected Class makeCodeGenModel(File file) {
// .add("return \"" + getSupport().tableOrThrow().getName() + "\";")
// )

.add(generateNewEntityFrom(getSupport(), file, table::columns))
//.add(generateNewEntityFrom(getSupport(), file, table::columns))
.add(generateNewEmptyEntity(getSupport(), file, table::columns))
.add(generateFields(getSupport(), file, FIELDS_METHOD, table::columns))
.add(generateFields(getSupport(), file, PRIMARY_KEYS_FIELDS_METHOD,
Expand Down Expand Up @@ -302,14 +302,14 @@ public Type getImplType() {
return getSupport().managerImplType();
}

private Method generateNewEntityFrom(TranslatorSupport<Table> support, File file, Supplier<Stream<? extends Column>> columnsSupplier) {
return Method.of(ENTITY_COPY_METHOD_NAME, support.entityType())
.protected_()
.add(SQLException.class)
.add(SpeedmentException.class)
.add(Field.of("resultSet", ResultSet.class))
.add(generateNewEntityFromBody(this::readFromResultSet, support, file, columnsSupplier));
}
// private Method generateNewEntityFrom(TranslatorSupport<Table> support, File file, Supplier<Stream<? extends Column>> columnsSupplier) {
// return Method.of(ENTITY_COPY_METHOD_NAME, support.entityType())
// .protected_()
// .add(SQLException.class)
// .add(SpeedmentException.class)
// .add(Field.of("resultSet", ResultSet.class))
// .add(generateNewEntityFromBody(this::readFromResultSet, support, file, columnsSupplier));
// }

private String readFromResultSet(File file, Column c, AtomicInteger position) {

Expand Down
@@ -0,0 +1,238 @@
/**
*
* Copyright (c) 2006-2016, Speedment, Inc. All Rights Reserved.
*
* 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.speedment.generator.standard.manager;

import com.speedment.common.codegen.constant.SimpleParameterizedType;
import com.speedment.common.codegen.model.AnnotationUsage;
import com.speedment.common.codegen.model.Class;
import com.speedment.common.codegen.model.Constructor;
import com.speedment.common.codegen.model.Field;
import com.speedment.common.codegen.model.File;
import com.speedment.common.codegen.model.Import;
import com.speedment.common.codegen.model.Method;
import com.speedment.common.injector.Injector;
import com.speedment.common.injector.annotation.Inject;
import com.speedment.generator.translator.AbstractEntityAndManagerTranslator;
import com.speedment.generator.translator.TranslatorSupport;
import com.speedment.runtime.core.component.DbmsHandlerComponent;
import com.speedment.runtime.core.component.ProjectComponent;
import com.speedment.runtime.core.component.resultset.ResultSetMapperComponent;
import com.speedment.runtime.core.component.resultset.ResultSetMapping;
import com.speedment.runtime.config.Column;
import com.speedment.runtime.config.Dbms;
import com.speedment.runtime.config.Table;
import com.speedment.runtime.core.internal.util.sql.ResultSetUtil;

import java.lang.reflect.Type;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;
import java.util.stream.Stream;

import com.speedment.common.codegen.internal.model.value.ReferenceValue;
import static com.speedment.common.codegen.internal.util.Formatting.indent;
import com.speedment.common.injector.State;
import com.speedment.common.injector.annotation.WithState;
import com.speedment.runtime.config.util.DocumentDbUtil;
import com.speedment.runtime.core.exception.SpeedmentException;
import static com.speedment.runtime.core.util.DatabaseUtil.dbmsTypeOf;
import static com.speedment.generator.standard.internal.util.ColumnUtil.usesOptional;
import static com.speedment.generator.standard.internal.util.GenerateMethodBodyUtil.generateNewEntityFromBody;
import com.speedment.generator.translator.component.TypeMapperComponent;
import com.speedment.runtime.config.Project;
import com.speedment.runtime.config.identifier.TableIdentifier;
import com.speedment.runtime.core.component.sql.SqlPersistenceComponent;
import com.speedment.runtime.core.component.sql.SqlStreamSupplierComponent;
import static java.util.stream.Collectors.joining;

/**
*
* @author Emil Forslund
*/
public final class GeneratedSqlAdapterTranslator extends AbstractEntityAndManagerTranslator<Class> {

public final static String ENTITY_COPY_METHOD_NAME = "entityCopy",
ENTITY_CREATE_METHOD_NAME = "entityCreate",
FIELDS_METHOD = "fields",
PRIMARY_KEYS_FIELDS_METHOD = "primaryKeyFields";

private @Inject
ResultSetMapperComponent resultSetMapperComponent;
private @Inject
DbmsHandlerComponent dbmsHandlerComponent;
private @Inject
TypeMapperComponent typeMappers;
private @Inject
Injector injector;

public GeneratedSqlAdapterTranslator(Table table) {
super(table, Class::of);
}

@Override
protected Class makeCodeGenModel(File file) {
file.add(Import.of(Project.class));
return newBuilder(file, getClassOrInterfaceName())
.forEveryTable((clazz, table) -> {
clazz
.public_()
.abstract_()
.add(Field.of("manager", getSupport().managerType()).add(inject()).private_())
.add(Method.of("createHelpers", void.class)
.add(Field.of("projectComponent", ProjectComponent.class).add(withStateInitialized(file)))
.add("final Project project = projectComponent.getProject();")
)
.add(Method.of("install", void.class)
.add("")
.add(Field.of("manager", getSupport().managerType()).add(withStateInitialized(file)))
.add(Field.of("streamSupplierComponent", SqlStreamSupplierComponent.class).add(withStateInitialized(file)))
.add(Field.of("persistenceComponent", SqlPersistenceComponent.class).add(withStateInitialized(file)))
.add("streamSupplierComponent.install(tableIdentifier, this::apply);")
.add("persistenceComponent.install(tableIdentifier);")
)
.add(Field.of("tableIdentifier", SimpleParameterizedType.create(TableIdentifier.class, getSupport().entityType())).private_().final_())
.add(Constructor.of().protected_()
// .add("this.tableIdentifier = "+TableIdentifier.class.getSimpleName()+".of(\\\"\" + getSupport().dbmsOrThrow().getName() + \"\\\");
.add("this.tableIdentifier = " + TableIdentifier.class.getSimpleName() + ".of("
+ Stream.of(getSupport().dbmsOrThrow().getName(), getSupport().schemaOrThrow().getName(), getSupport().tableOrThrow().getName())
.map(s -> "\"" + s + "\"").collect(joining(", "))
+ ");")
)
.add(generateNewEntityFrom(getSupport(), file, table::columns));
})
.build()
.call(i -> file.add(Import.of(getSupport().entityImplType())));
}

private Method generateApplyMethod(File file, Table table) {
return Method.of("apply", getSupport().entityType()).protected_()
.add("final " + getSupport().entityName() + " entity = manager.entityCreate();")
.add("try {")
.add(indent(fieldsss(table)))
.add("} catch (final SQLException sqle) {")
.add(indent("throw new SpeedmentException(sqle);"))
.add("}")
.add("return entity;");
}

private String[] fieldsss(Table table) {
throw new UnsupportedOperationException("Todo");
}

@Override
protected String getJavadocRepresentText() {
return "The generated Sql Adapter for a {@link "
+ getSupport().entityType().getTypeName() + "} entity.";
}

@Override
protected String getClassOrInterfaceName() {
return getSupport().generatedSqlAdapterName();
}

@Override
public boolean isInGeneratedPackage() {
return true;
}

public Type getImplType() {
return getSupport().managerImplType();
}

private Method generateNewEntityFrom(TranslatorSupport<Table> support, File file, Supplier<Stream<? extends Column>> columnsSupplier) {
return Method.of("apply", support.entityType())
.protected_()
.add(SQLException.class)
.add(SpeedmentException.class)
.add(Field.of("resultSet", ResultSet.class))
.add(generateNewEntityFromBody(this::readFromResultSet, support, file, columnsSupplier));
}

private String readFromResultSet(File file, Column c, AtomicInteger position) {

final TranslatorSupport<Table> support = new TranslatorSupport<>(injector, c.getParentOrThrow());
final Dbms dbms = c.getParentOrThrow().getParentOrThrow().getParentOrThrow();

final ResultSetMapping<?> mapping = resultSetMapperComponent.apply(
dbmsTypeOf(dbmsHandlerComponent, c.getParentOrThrow().getParentOrThrow().getParentOrThrow()),
c.findDatabaseType()
);

final boolean isIdentityMapper = !c.getTypeMapper().isPresent();

file.add(Import.of(DocumentDbUtil.class));

final StringBuilder sb = new StringBuilder();
if (!isIdentityMapper) {
sb
.append(typeMapperName(support, c))
.append(".toJavaType(DocumentDbUtil.referencedColumn(projectComponent.getProject(), ")
.append(support.entityName())
.append(".")
.append(support.namer().javaStaticFieldName(c.getJavaName()))
.append(".identifier()), getEntityClass(), ");
}
final String getterName = "get" + mapping.getResultSetMethodName(dbms);

final boolean isResultSetMethod = Stream.of(ResultSet.class.getMethods())
.map(java.lang.reflect.Method::getName)
.anyMatch(getterName::equals);

final boolean isResultSetMethodReturnsPrimitive = Stream.of(ResultSet.class.getMethods())
.filter(m -> m.getName().equals(getterName))
.anyMatch(m -> m.getReturnType().isPrimitive());

if (isResultSetMethod && !(usesOptional(c) && isResultSetMethodReturnsPrimitive)) {
sb
.append("resultSet.")
.append("get")
.append(mapping.getResultSetMethodName(dbms))
.append("(").append(position.getAndIncrement()).append(")");
} else {
file.add(Import.of(ResultSetUtil.class).static_().setStaticMember("*"));
sb
.append("get")
.append(mapping.getResultSetMethodName(dbms))
.append("(resultSet, ")
.append(position.getAndIncrement()).append(")");
}
if (!isIdentityMapper) {
sb.append(")");
}

return sb.toString();
}

private static String typeMapperName(TranslatorSupport<Table> support, Column col) {
return support.entityName() + "." + support.namer().javaStaticFieldName(col.getJavaName()) + ".typeMapper()";
}

private static boolean isPrimaryKey(Column column) {
return column.getParentOrThrow().findPrimaryKeyColumn(column.getName()).isPresent();
}

private AnnotationUsage withStateInitialized(File file) {
file.add(Import.of(State.class).static_().setStaticMember("INITIALIZED"));
return AnnotationUsage.of(WithState.class).set(new ReferenceValue("INITIALIZED"));
}

private AnnotationUsage inject() {
return AnnotationUsage.of(Inject.class);
}

}

0 comments on commit 08b958c

Please sign in to comment.