/** * 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.gen; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Stack; import org.eclipse.jdt.core.dom.ArrayCreation; import org.eclipse.jdt.core.dom.ArrayInitializer; import org.eclipse.jdt.core.dom.Expression; import org.eclipse.jdt.core.dom.MethodDeclaration; import org.eclipse.jdt.core.dom.MethodInvocation; import org.whole.lang.builders.IBuilderOperation; import org.whole.lang.commons.model.SameStageFragment; import org.whole.lang.commons.model.StageDownFragment; import org.whole.lang.commons.model.StageUpFragment; import org.whole.lang.operations.AbstractOperation; import org.whole.lang.templates.AbstractTemplateFactory; import org.whole.lang.util.StringUtils; import org.whole.lang.util.UniqueIdGenerator; import org.whole.lang.visitors.IVisitor; /** * @author Riccardo Solmi */ public class JavaStoreBuilder extends CompilationUnitBuilder { public JavaStoreBuilder(JavaModelGenerator generator) { super(generator); cuList.remove(cu); } public void endStore(IVisitor v) { MethodInvocation callExp = newFactoryInvocation(v, "makeRootEntity"); callExp.arguments().add(getExpression()); builder().addStatement(builder().newReturnStatement(callExp)); } private final CompilationUnitBuilder builder() { return generator.getCurrentBuilder(); } public Expression getExpression() { return builder().exp; } public Expression setExpression(Expression exp) { return builder().exp = exp; } private UniqueIdGenerator uidGen = UniqueIdGenerator.newUniqueIdGenerator("e"); public String nextUniqueId() { return uidGen.next(); } private final int MAX_NESTING = 5; private int nestingSize = 0; public int initNestingSize() { int result = nestingSize; nestingSize = 1; return result; } private boolean checkNestingSize(int parentNestingSize) { if (nestingSize >= MAX_NESTING) { nestingSize = parentNestingSize; return true; } else { nestingSize += parentNestingSize; return false; } } public void addCodeBase(String name) { builder().addClassDeclaration(name, AbstractTemplateFactory.class.getName()); // public void apply(IBuilderOperation op) MethodDeclaration method = builder().newMethodDeclaration("void", "apply", builder().newSingleVariableDeclaration(IBuilderOperation.class.getName(), "op")); builder().addBodyDeclaration(method); } private Map factoryMap = new HashMap(); //IVisitor -> String factoryVar private int i=1; public String getFactoryVar(IVisitor v) { return (String)factoryMap.get(v); } public void addLanguageFactory(IVisitor visitor, String factoryName) { String factoryVar = "lf"+i++; factoryMap.put(visitor, factoryVar); //FIXME senza .impl addImportDeclaration(StringUtils.toPackageName(factoryName), true); builder().addImportDeclaration(StringUtils.toPackageName(factoryName), true); //FIXME potrei non essere in un blocco!! builder().addVariableDeclarationStatement(factoryName, factoryVar, builder().newFieldAccess(factoryName, "instance")); } public MethodInvocation newFactoryInvocation(IVisitor visitor, String method) { return builder().newMethodInvocation(getFactoryVar(visitor), method); } public ArrayCreation newArrayCreation(String type, ArrayInitializer initializer) { return builder().newArrayCreation(type, initializer); } //NB devono essere 3 addSubtree public Expression addSubtree(IVisitor visitor, SameStageFragment fragment, String type) { int parentNestingSize = initNestingSize(); IVisitor v = ((AbstractOperation) visitor.getOperation()).getVisitor(fragment.wGetRoot(), visitor.getOperation().getStage()); v.visit(fragment.wGetRoot()); MethodInvocation callExp2 = newFactoryInvocation(v, "makeRootEntity"); callExp2.arguments().add(getExpression()); MethodInvocation callExp = newFactoryInvocation(visitor, "create"+type); callExp.arguments().add(callExp2); return addSubtree(parentNestingSize, type, callExp); } public Expression addSubtree(IVisitor visitor, StageDownFragment fragment, String type) { int parentNestingSize = initNestingSize(); IVisitor v = ((AbstractOperation) visitor.getOperation()).getVisitor(fragment.wGetRoot(), 0); v.visit(fragment.wGetRoot()); MethodInvocation callExp2 = newFactoryInvocation(v, "makeRootEntity"); callExp2.arguments().add(getExpression()); MethodInvocation callExp = newFactoryInvocation(visitor, "create"+type); callExp.arguments().add(callExp2); return addSubtree(parentNestingSize, type, callExp); } public Expression addSubtree(IVisitor visitor, StageUpFragment fragment, String type) { int parentNestingSize = initNestingSize(); IVisitor v = ((AbstractOperation) visitor.getOperation()).getVisitor(fragment.wGetRoot(), 1); v.visit(fragment.wGetRoot()); MethodInvocation callExp2 = newFactoryInvocation(v, "makeRootEntity"); callExp2.arguments().add(getExpression()); MethodInvocation callExp = newFactoryInvocation(visitor, "create"+type); callExp.arguments().add(callExp2); return addSubtree(parentNestingSize, type, callExp); } public Expression addSubtree(int parentNestingSize, String type, MethodInvocation subtree) { if (nestingSize >= MAX_NESTING) { nestingSize = parentNestingSize; return setExpression(addSubtree(type, subtree)); } else { nestingSize += parentNestingSize; return setExpression(subtree); } } protected Expression addSubtree(String type, MethodInvocation subtree) { String tempEntity = nextUniqueId(); builder().addVariableDeclarationStatement(type, tempEntity, subtree); return ast.newSimpleName(tempEntity); } // TODO soluzione alternativa basata su stack private Stack/*<Expression>*/ argStack = new Stack(); public void pushLiteral(String text) { argStack.push(newLiteral(text)); } public void pushLiteral(boolean value) { argStack.push(newLiteral(value)); } public void pushLiteral(byte value) { argStack.push(newLiteral(value)); } public void pushLiteral(char value) { argStack.push(newLiteral(value)); } public void pushLiteral(double value) { argStack.push(newLiteral(value)); } public void pushLiteral(float value) { argStack.push(newLiteral(value)); } public void pushLiteral(int value) { argStack.push(newLiteral(value)); } public void pushLiteral(long value) { argStack.push(newLiteral(value)); } public void addSubtree(IVisitor visitor, int parentNestingSize, String type, int args) { MethodInvocation callExp = newFactoryInvocation(visitor, "create"+type); for (int i=0; i<args; i++) callExp.arguments().add(0, argStack.pop()); argStack.push(addSubtree(parentNestingSize, type, callExp)); } public void addSubtree(IVisitor visitor, int parentNestingSize, String compositeType, String componentType, int args) { MethodInvocation callExp = newFactoryInvocation(visitor, "create"+compositeType); ArrayInitializer initArrayExp = newArrayInitializer(); callExp.arguments().add(builder().newArrayCreation(componentType, initArrayExp)); List expressions = initArrayExp.expressions(); for (int i=0; i<args; i++) expressions.add(0, argStack.pop()); argStack.push(addSubtree(parentNestingSize, compositeType, callExp)); } }