/** * Copyright 2004-2016 Riccardo Solmi. All rights reserved. * This file is part of the Whole Platform. * * The Whole Platform is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The Whole Platform 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the Whole Platform. If not, see <http://www.gnu.org/licenses/>. */ package org.whole.lang.java.util; import java.util.Date; import java.util.HashMap; import java.util.Map; import org.whole.lang.builders.BuilderConstants; import org.whole.lang.builders.IBuilder; import org.whole.lang.builders.IBuilderOperation; import org.whole.lang.commons.builders.ICommonsBuilder; import org.whole.lang.commons.reflect.CommonsLanguageKit; import org.whole.lang.contexts.IBuilderContext; import org.whole.lang.contexts.IEntityContext; import org.whole.lang.java.builders.IJavaBuilder; import org.whole.lang.java.model.PrimitiveTypeEnum; import org.whole.lang.java.reflect.JavaLanguageKit; import org.whole.lang.model.EnumValue; import org.whole.lang.parsers.DataTypeParsers; import org.whole.lang.reflect.EntityDescriptor; import org.whole.lang.reflect.EntityDescriptorEnum; import org.whole.lang.reflect.FeatureDescriptor; import org.whole.lang.reflect.ILanguageKit; import org.whole.lang.reflect.ReflectionFactory; import org.whole.lang.templates.AbstractTemplateFactory; import org.whole.lang.templates.ITemplate; import org.whole.lang.util.DataTypeUtils; /** * @author Riccardo Solmi, Enrico Persiani */ public class JavaStoreProducerBuilder implements IBuilder { private static final int MAX_METHOD_STATEMENTS = 5000; private IJavaBuilder jb; private ICommonsBuilder cb; private Map<ILanguageKit, String> builderNameMap = new HashMap<ILanguageKit, String>(); private Map<ILanguageKit, String> edEnumNameMap = new HashMap<ILanguageKit, String>(); private static final String builderPrefix = "b"; private static final String edEnumPrefix = "e"; private String builderName = "b"; private String edEnumName = "e"; private int builderIndex = 0; private int methodStatements = 0; private int methodCount = 0; private Strategy STRATEGY_FOR_STATIC; private Strategy STRATEGY_FOR_DYNAMIC; private Strategy strategy; public JavaStoreProducerBuilder(IBuilderOperation targetOperation) { this(targetOperation, true, false); } public JavaStoreProducerBuilder(IBuilderOperation targetOperation, boolean specific, boolean force) { jb = (IJavaBuilder) targetOperation.wGetBuilder(JavaLanguageKit.URI); cb = (ICommonsBuilder) targetOperation.wGetBuilder(CommonsLanguageKit.URI); withStrategy(specific, force); } public IBuilder withStrategy(boolean specific, boolean force) { STRATEGY_FOR_STATIC = specific ? new SpecificStrategy() : new GenericStrategy(); STRATEGY_FOR_DYNAMIC = force ? STRATEGY_FOR_STATIC : null; return this; } public void buildStartCompilationUnit(String packageName, String className) { buildStartCompilationUnit(packageName, className, null); } public void buildStartCompilationUnit(String packageName, String className, String templateClassName) { jb.CompilationUnit_(); if (packageName == null || packageName.length()==0) cb.Resolver(); else { jb.PackageDeclaration_(); jb.Javadoc(); cb.Resolver(); jb.SimpleName(packageName); jb._PackageDeclaration(); } jb.ImportDeclarations_(); jb.ImportDeclaration_(); jb.QualifiedName(IBuilderOperation.class.getName()); jb.ImportModifier(false); jb.ImportModifier(false); jb._ImportDeclaration(); jb.ImportDeclaration_(); jb.QualifiedName(AbstractTemplateFactory.class.getName()); jb.ImportModifier(false); jb.ImportModifier(false); jb._ImportDeclaration(); jb._ImportDeclarations(); jb.TypeDeclarations_(1); jb.ClassDeclaration_(); jb.Javadoc(); jb.ExtendedModifiers_(1); jb.Modifier("public"); jb._ExtendedModifiers(); jb.SimpleName(className); jb.TypeParameters(); if (templateClassName != null) { jb.ParameterizedType_(); jb.SimpleType("AbstractTemplateFactory"); jb.Types_(1); jb.QualifiedType(templateClassName); jb._Types(); jb._ParameterizedType(); } else jb.SimpleType("AbstractTemplateFactory"); jb.Types(); jb.BodyDeclarations_(1); jb.MethodDeclaration_(); jb.Javadoc(); jb.ExtendedModifiers_(1); jb.Modifier("public"); jb._ExtendedModifiers(); jb.TypeParameters(); jb.PrimitiveType("void"); jb.SimpleName("apply"); jb.Parameters_(1); jb.SingleVariableDeclaration_(); jb.ExtendedModifiers(); jb.SimpleType("IBuilderOperation"); jb.Varargs(false); jb.SimpleName("op"); jb.ExtraDimensions(); jb._SingleVariableDeclaration(); jb._Parameters(); jb.ExtraDimensions(); jb.Types(); jb.Block_(); } public void buildEndCompilationUnit() { jb._Block(); jb._MethodDeclaration(); jb._BodyDeclarations(); jb._ClassDeclaration(); jb._TypeDeclarations(); jb._CompilationUnit(); } public void buildStartBlock() { jb.Block_(); } public void buildEndBlock() { jb._Block(); } protected void ensureMethodSizeLimit() { if (methodStatements++ == MAX_METHOD_STATEMENTS) { methodStatements = 0; String nextMethodName = "apply" + Integer.toString(methodCount++); // apply0(op); jb.ExpressionStatement_(); jb.MethodInvocation_(); cb.Resolver(); jb.Types(); jb.SimpleName(nextMethodName); jb.Arguments_(); jb.SimpleName("op"); jb._Arguments(); jb._MethodInvocation(); jb._ExpressionStatement(); // } jb._Block(); jb._MethodDeclaration(); // private void apply0(IBuilderOperation op) { jb.MethodDeclaration_(); jb.Javadoc(); jb.ExtendedModifiers_(1); jb.Modifier("private"); jb._ExtendedModifiers(); jb.TypeParameters(); jb.PrimitiveType("void"); jb.SimpleName(nextMethodName); jb.Parameters_(1); jb.SingleVariableDeclaration_(); jb.ExtendedModifiers(); jb.SimpleType("IBuilderOperation"); jb.Varargs(false); jb.SimpleName("op"); jb.ExtraDimensions(); jb._SingleVariableDeclaration(); jb._Parameters(); jb.ExtraDimensions(); jb.Types(); jb.Block_(); builderNameMap.clear(); edEnumNameMap.clear(); } } protected void ensureBuilder(EntityDescriptor<?> ed) { ensureMethodSizeLimit(); ILanguageKit languageKit = ed.getLanguageKit(); ILanguageKit builderLanguageKit = languageKit; if (languageKit.isDynamic()) { builderLanguageKit = ReflectionFactory.getLanguageKit(CommonsLanguageKit.URI); if (STRATEGY_FOR_DYNAMIC == null) STRATEGY_FOR_DYNAMIC = new SymbolicStrategy(); strategy = STRATEGY_FOR_DYNAMIC; } else strategy = STRATEGY_FOR_STATIC; builderName = builderNameMap.get(builderLanguageKit); if (builderName == null) { builderName = builderPrefix + builderIndex++; builderNameMap.put(builderLanguageKit, builderName); buildGetBuilder(builderLanguageKit); } if (languageKit.isDynamic()) { edEnumName = edEnumNameMap.get(languageKit); if (edEnumName == null) { edEnumName = edEnumPrefix + builderIndex++; edEnumNameMap.put(languageKit, edEnumName); buildGetEntityDescriptorEnum(languageKit); } } } protected void buildGetBuilder(ILanguageKit languageKit) { String builderType = BuilderConstants.builderType(languageKit); jb.VariableDeclarationStatement_(); jb.ExtendedModifiers(); jb.SimpleType(builderType); jb.VariableDeclarationFragments_(1); jb.VariableDeclarationFragment_(); jb.SimpleName(builderName); jb.ExtraDimensions(); jb.CastExpression_(); jb.SimpleType(builderType); jb.MethodInvocation_(); jb.SimpleName("op"); jb.Types(); jb.SimpleName("wGetBuilder"); jb.Arguments_(1); jb.QualifiedName(languageKit.getClass().getName()+".URI"); jb._Arguments(); jb._MethodInvocation(); jb._CastExpression(); jb._VariableDeclarationFragment(); jb._VariableDeclarationFragments(); jb._VariableDeclarationStatement(); } protected void buildGetEntityDescriptorEnum(ILanguageKit languageKit) { jb.VariableDeclarationStatement_(); jb.ExtendedModifiers(); jb.SimpleType(EntityDescriptorEnum.class.getName()); jb.VariableDeclarationFragments_(1); jb.VariableDeclarationFragment_(); jb.SimpleName(edEnumName); jb.ExtraDimensions(); jb.MethodInvocation_(); jb.MethodInvocation_(); jb.QualifiedName("org.whole.lang.reflect.ReflectionFactory"); jb.Types(); jb.SimpleName("getLanguageKit"); jb.Arguments_(1); jb.StringLiteral(languageKit.getURI()); jb._Arguments(); jb._MethodInvocation(); jb.Types(); jb.SimpleName("getEntityDescriptorEnum"); jb.Arguments(); jb._MethodInvocation(); jb._VariableDeclarationFragment(); jb._VariableDeclarationFragments(); jb._VariableDeclarationStatement(); } protected void buildDataEntity_(EntityDescriptor<?> entityDesc) { ensureBuilder(entityDesc); jb.ExpressionStatement_(); jb.MethodInvocation_(); jb.SimpleName(builderName); jb.Types(); strategy.buildDataEntity_(entityDesc); } protected void _buildDataEntity() { jb._Arguments(); jb._MethodInvocation(); jb._ExpressionStatement(); } public void wEntity(EntityDescriptor<?> entityDesc) { ensureBuilder(entityDesc); jb.ExpressionStatement_(); jb.MethodInvocation_(); jb.SimpleName(builderName); jb.Types(); strategy.buildEntity(entityDesc); jb._MethodInvocation(); jb._ExpressionStatement(); } public void wEntity_(EntityDescriptor<?> entityDesc) { ensureBuilder(entityDesc); jb.ExpressionStatement_(); jb.MethodInvocation_(); jb.SimpleName(builderName); jb.Types(); strategy.buildSimpleEntity_(entityDesc); jb._MethodInvocation(); jb._ExpressionStatement(); } public void wEntity_(EntityDescriptor<?> entityDesc, int initialCapacity) { ensureBuilder(entityDesc); jb.ExpressionStatement_(); jb.MethodInvocation_(); jb.SimpleName(builderName); jb.Types(); strategy.buildCompositeEntity_(entityDesc); jb.IntLiteral(initialCapacity); jb._Arguments(); jb._MethodInvocation(); jb._ExpressionStatement(); } public void _wEntity(EntityDescriptor<?> entityDesc) { ensureBuilder(entityDesc); jb.ExpressionStatement_(); jb.MethodInvocation_(); jb.SimpleName(builderName); jb.Types(); strategy._buildEntity(entityDesc); jb._MethodInvocation(); jb._ExpressionStatement(); } public void wEntity(EntityDescriptor<?> entityDesc, boolean value) { buildDataEntity_(entityDesc); jb.BooleanLiteral(value); _buildDataEntity(); } public void wEntity(EntityDescriptor<?> entityDesc, byte value) { buildDataEntity_(entityDesc); jb.CastExpression_(); jb.PrimitiveType(PrimitiveTypeEnum._byte); jb.ByteLiteral(value); jb._CastExpression(); _buildDataEntity(); } public void wEntity(EntityDescriptor<?> entityDesc, char value) { buildDataEntity_(entityDesc); jb.CharLiteral(value); _buildDataEntity(); } public void wEntity(EntityDescriptor<?> entityDesc, double value) { buildDataEntity_(entityDesc); boolean nan = Double.isNaN(value), infinite = Double.isInfinite(value); if (nan || infinite) { jb.FieldAccess_(); jb.SimpleName("Double"); jb.SimpleName(nan ? "NaN" : (Double.compare(value, 0) < 0 ? "NEGATIVE_INFINITY" : "POSITIVE_INFINITY")); jb._FieldAccess(); } else jb.DoubleLiteral(value); _buildDataEntity(); } public void wEntity(EntityDescriptor<?> entityDesc, float value) { buildDataEntity_(entityDesc); boolean nan = Float.isNaN(value), infinite = Float.isInfinite(value); if (nan || infinite) { jb.FieldAccess_(); jb.SimpleName("Float"); jb.SimpleName(nan ? "NaN" : (Float.compare(value, 0) < 0 ? "NEGATIVE_INFINITY" : "POSITIVE_INFINITY")); jb._FieldAccess(); } else jb.FloatLiteral(value); _buildDataEntity(); } public void wEntity(EntityDescriptor<?> entityDesc, int value) { buildDataEntity_(entityDesc); jb.IntLiteral(value); _buildDataEntity(); } public void wEntity(EntityDescriptor<?> entityDesc, long value) { buildDataEntity_(entityDesc); jb.LongLiteral(value); _buildDataEntity(); } public void wEntity(EntityDescriptor<?> entityDesc, short value) { buildDataEntity_(entityDesc); jb.CastExpression_(); jb.PrimitiveType(PrimitiveTypeEnum._short); jb.ShortLiteral(value); jb._CastExpression(); _buildDataEntity(); } public void wEntity(EntityDescriptor<?> entityDesc, String value) { buildDataEntity_(entityDesc); jb.StringLiteral(value); _buildDataEntity(); } public void wEntity(EntityDescriptor<?> entityDesc, Date value) { buildDataEntity_(entityDesc); jb.ClassInstanceCreation_(); cb.Resolver(); cb.Resolver(); jb.QualifiedType("java.util.Date"); jb.Arguments_(1); jb.LongLiteral(value.getTime()); jb._Arguments(); cb.Resolver(); jb._ClassInstanceCreation(); _buildDataEntity(); } public void wEntity(EntityDescriptor<?> entityDesc, EnumValue value) { buildDataEntity_(entityDesc); jb.StringLiteral(DataTypeUtils.getDataTypeParser(entityDesc, DataTypeParsers.PERSISTENCE) .unparseEnumValue(entityDesc, value)); _buildDataEntity(); } public void wEntity(EntityDescriptor<?> entityDesc, Object value) { buildDataEntity_(entityDesc); if (value == null) { jb.CastExpression_(); jb.SimpleType("Object"); jb.NullLiteral(); jb._CastExpression(); } else jb.StringLiteral(DataTypeUtils.getDataTypeParser(entityDesc, DataTypeParsers.PERSISTENCE) .unparseObject(entityDesc, value)); _buildDataEntity(); } public void wSetBuilderContext(IBuilderContext context) { } public void wSetEntityContext(IEntityContext context) { } public void wDefault() { // TODO throw new UnsupportedOperationException(); } public void wEntity() { // TODO throw new UnsupportedOperationException(); } public void wEntity_() { // TODO throw new UnsupportedOperationException(); } public void _wEntity() { // TODO throw new UnsupportedOperationException(); } public void wFeature(int index) { // TODO throw new UnsupportedOperationException(); } public void wFeature(FeatureDescriptor feature) { // TODO throw new UnsupportedOperationException(); } public void wFeature(ITemplate template) { // TODO throw new UnsupportedOperationException(); } protected interface Strategy { public void buildDataEntity_(EntityDescriptor<?> ed); public void buildEntity(EntityDescriptor<?> ed); public void buildSimpleEntity_(EntityDescriptor<?> ed); public void buildCompositeEntity_(EntityDescriptor<?> ed); public void _buildEntity(EntityDescriptor<?> ed); } protected class SpecificStrategy implements Strategy { public void buildDataEntity_(EntityDescriptor<?> ed) { jb.SimpleName(BuilderConstants.buildName(ed)); jb.Arguments_(1); } public void buildEntity(EntityDescriptor<?> ed) { jb.SimpleName(BuilderConstants.buildName(ed)); jb.Arguments_(0); jb._Arguments(); } public void buildSimpleEntity_(EntityDescriptor<?> ed) { jb.SimpleName(BuilderConstants.startBuildName(ed)); jb.Arguments_(0); jb._Arguments(); } public void buildCompositeEntity_(EntityDescriptor<?> ed) { jb.SimpleName(BuilderConstants.startBuildName(ed)); jb.Arguments_(1); } public void _buildEntity(EntityDescriptor<?> ed) { jb.SimpleName(BuilderConstants.endBuildName(ed)); jb.Arguments_(0); jb._Arguments(); } } protected abstract class AbstractStrategy implements Strategy { public void buildDataEntity_(EntityDescriptor<?> ed) { jb.SimpleName(BuilderConstants.buildName()); jb.Arguments_(2); buildTarget(ed); } public void buildEntity(EntityDescriptor<?> ed) { jb.SimpleName(BuilderConstants.buildName()); jb.Arguments_(1); buildTarget(ed); jb._Arguments(); } public void buildSimpleEntity_(EntityDescriptor<?> ed) { jb.SimpleName(BuilderConstants.startBuildName()); jb.Arguments_(1); buildTarget(ed); jb._Arguments(); } public void buildCompositeEntity_(EntityDescriptor<?> ed) { jb.SimpleName(BuilderConstants.startBuildName()); jb.Arguments_(2); buildTarget(ed); } public void _buildEntity(EntityDescriptor<?> ed) { jb.SimpleName(BuilderConstants.endBuildName()); jb.Arguments_(1); buildTarget(ed); jb._Arguments(); } protected abstract void buildTarget(EntityDescriptor<?> ed); } protected class GenericStrategy extends AbstractStrategy { protected final void buildTarget(EntityDescriptor<?> ed) { jb.FieldAccess_(); jb.SimpleName(ed.getEntityDescriptorEnum().getClass().getName()); jb.SimpleName(ed.getImplName()); jb._FieldAccess(); } } protected class SymbolicStrategy extends AbstractStrategy { protected final void buildTarget(EntityDescriptor<?> ed) { jb.MethodInvocation_(); jb.SimpleName(edEnumName); jb.Types(); jb.SimpleName("valueOf"); jb.Arguments_(1); jb.StringLiteral(ed.getName()); jb._Arguments(); jb._MethodInvocation(); } } }