/**
*
* Copyright (c) 2006-2017, 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.plugins.enums.internal;
import com.speedment.common.codegen.constant.SimpleType;
import com.speedment.common.codegen.model.*;
import com.speedment.common.codegen.model.Enum;
import com.speedment.common.injector.Injector;
import com.speedment.generator.core.exception.SpeedmentGeneratorException;
import com.speedment.generator.translator.JavaClassTranslator;
import com.speedment.generator.translator.Translator;
import com.speedment.generator.translator.TranslatorDecorator;
import com.speedment.generator.translator.namer.JavaLanguageNamer;
import com.speedment.plugins.enums.StringToEnumTypeMapper;
import com.speedment.runtime.config.Column;
import com.speedment.runtime.config.Table;
import com.speedment.runtime.config.trait.HasEnabled;
import com.speedment.runtime.core.util.OptionalUtil;
import com.speedment.runtime.field.ReferenceField;
import com.speedment.runtime.typemapper.TypeMapper;
import java.lang.reflect.Type;
import java.util.List;
import static com.speedment.common.codegen.constant.DefaultAnnotationUsage.OVERRIDE;
import static com.speedment.common.codegen.constant.DefaultType.WILDCARD;
import static com.speedment.common.codegen.constant.DefaultType.classOf;
import static com.speedment.common.codegen.model.Value.*;
import static com.speedment.common.codegen.util.Formatting.indent;
import static com.speedment.common.codegen.util.Formatting.shortName;
import static com.speedment.generator.standard.internal.util.ColumnUtil.usesOptional;
import static com.speedment.runtime.config.util.DocumentDbUtil.isUnique;
import static java.util.Objects.requireNonNull;
/**
*
* @author Emil Forslund
* @author Simon Jonasson
* @since 1.0.0
*/
public final class GeneratedEntityDecorator
implements TranslatorDecorator<Table, Interface> {
public final static String
FROM_DATABASE_METHOD = "fromDatabase",
TO_DATABASE_METHOD = "toDatabase",
DATABASE_NAME_FIELD = "databaseName";
private final Injector injector;
public GeneratedEntityDecorator(Injector injector) {
this.injector = requireNonNull(injector);
}
@Override
public void apply(JavaClassTranslator<Table, Interface> translator) {
translator.onMake((file, builder) -> {
builder.forEveryTable(Translator.Phase.POST_MAKE, (intrf, table) -> {
file.getImports().removeIf(i -> i.getType().equals(StringToEnumTypeMapper.class));
table.columns()
.filter(HasEnabled::test)
.filter(col -> col.getTypeMapper()
.filter(StringToEnumTypeMapper.class.getName()::equals)
.isPresent()
).forEachOrdered(col -> {
final JavaLanguageNamer namer = translator.getSupport().namer();
final String colEnumName = EnumGeneratorUtil.enumNameOf(col, injector);
final List<String> constants = EnumGeneratorUtil.enumConstantsOf(col);
final Type enumType = new GeneratedEnumType(colEnumName, constants);
final Enum colEnum = Enum.of(shortName(colEnumName))
.add(Field.of(DATABASE_NAME_FIELD, String.class).private_().final_());
// Generate enum constants
constants.forEach(constant -> {
final String javaName = namer.javaStaticFieldName(constant);
colEnum.add(EnumConstant.of(javaName).add(Value.ofText(constant)));
});
// Generate constructor
colEnum.add(Constructor.of()
.add(Field.of(DATABASE_NAME_FIELD, String.class))
.add("this." + DATABASE_NAME_FIELD + " = " + DATABASE_NAME_FIELD + ";")
);
// Generate fromDatabase()-method
final Method fromDatabase = Method.of(FROM_DATABASE_METHOD, enumType)
.public_().static_()
.add(Field.of(DATABASE_NAME_FIELD, String.class))
.add("switch (" + DATABASE_NAME_FIELD + ") {");
constants.stream()
.map(s -> indent("case \"" + s + "\" : return " + namer.javaStaticFieldName(s) + ";"))
.forEachOrdered(fromDatabase::add);
fromDatabase
.add(indent("default : throw new UnsupportedOperationException("))
.add(indent("\"Unknown enum constant '\" + " + DATABASE_NAME_FIELD + " + \"'.\"", 2))
.add(indent(");"))
.add("}");
colEnum.add(fromDatabase);
// Generate toDatabase()-method
colEnum.add(Method.of(TO_DATABASE_METHOD, String.class)
.public_().add("return " + DATABASE_NAME_FIELD + ";")
);
// Add it to the interface.
intrf.add(colEnum);
// Rewrite the static field to use a inlined type mapper
// instead.
final String fieldName = namer.javaStaticFieldName(col.getJavaName());
final Field field = intrf.getFields().stream()
.filter(f -> f.getName().equals(fieldName))
.findFirst().orElseThrow(() -> new SpeedmentGeneratorException(
"Expected a static field with name '" +
fieldName + "' to be generated."
));
if (usesOptional(col)) {
file.add(Import.of(OptionalUtil.class));
}
final String enumShortName = shortName(colEnumName);
final String enumVarName = namer.javaVariableName(enumShortName);
field.set(ofInvocation(ReferenceField.class, "create",
ofReference("Identifier." + fieldName),
ofReference(
usesOptional(col)
? "o -> " + OptionalUtil.class.getSimpleName() + ".unwrap(o.get" + translator.getSupport().typeName(col) + "()),"
: translator.getSupport().entityName() + "::get" + translator.getSupport().typeName(col)
),
ofReference(
translator.getSupport().entityName() + "::set" +
translator.getSupport().typeName(col)
),
ofAnonymous(TypeMapper.class)
.add(String.class)
.add(SimpleType.create(colEnumName))
.add(Method.of("getLabel", String.class)
.public_().add(OVERRIDE)
.add("return \"String to " + enumShortName + " Mapper\";")
)
.add(Method.of("getJavaType", Type.class)
.public_().add(OVERRIDE)
.add(Field.of("column", Column.class))
.add("return " + enumShortName + ".class;")
)
.add(Method.of("toJavaType", enumType)
.public_().add(OVERRIDE)
.add(Field.of("column", Column.class))
.add(Field.of("clazz", classOf(WILDCARD)))
.add(Field.of("str", String.class))
.add("return str == null ? null : " + enumShortName + "." + FROM_DATABASE_METHOD + "(str);")
)
.add(Method.of("toDatabaseType", String.class)
.public_().add(OVERRIDE)
.add(Field.of(enumVarName, enumType))
.add("return " + enumVarName + " == null ? null : " + enumVarName + "." + TO_DATABASE_METHOD + "();")
),
ofBoolean(isUnique(col))
));
});
});
});
}
}