/*
* Copyright 2012 PRODYNA AG
*
* Licensed under the Eclipse Public License (EPL), Version 1.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.opensource.org/licenses/eclipse-1.0.php or
* http://www.nabucco.org/License.html
*
* 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 org.nabucco.framework.generator.compiler.transformation.java.datatype;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Statement;
import org.eclipse.jdt.internal.compiler.ast.SuperReference;
import org.nabucco.framework.generator.compiler.transformation.java.common.ast.JavaAstSupport;
import org.nabucco.framework.generator.compiler.transformation.java.common.ast.container.JavaAstContainter;
import org.nabucco.framework.generator.compiler.transformation.java.visitor.NabuccoToJavaVisitorContext;
import org.nabucco.framework.generator.compiler.transformation.java.visitor.NabuccoToJavaVisitorSupport;
import org.nabucco.framework.generator.compiler.visitor.NabuccoVisitorException;
import org.nabucco.framework.generator.parser.model.NabuccoModel;
import org.nabucco.framework.generator.parser.model.modifier.NabuccoModifierType;
import org.nabucco.framework.generator.parser.model.modifier.NabuccoModifierTypeMapper;
import org.nabucco.framework.generator.parser.model.multiplicity.NabuccoMultiplicityType;
import org.nabucco.framework.generator.parser.model.multiplicity.NabuccoMultiplicityTypeMapper;
import org.nabucco.framework.generator.parser.syntaxtree.DatatypeDeclaration;
import org.nabucco.framework.generator.parser.syntaxtree.DatatypeStatement;
import org.nabucco.framework.generator.parser.syntaxtree.NodeToken;
import org.nabucco.framework.mda.model.MdaModel;
import org.nabucco.framework.mda.model.java.JavaModel;
import org.nabucco.framework.mda.model.java.JavaModelException;
import org.nabucco.framework.mda.model.java.ast.element.JavaAstElementFactory;
import org.nabucco.framework.mda.model.java.ast.produce.JavaAstModelProducer;
/**
* NabuccoToJavaDatatypeRefIdVisitor
*
* @author Nicolas Moser, PRODYNA AG
*/
class NabuccoToJavaDatatypeRefIdVisitor extends NabuccoToJavaVisitorSupport {
/**
* Creates a new {@link NabuccoToJavaDatatypeRefIdVisitor} instance.
*
* @param visitorContext
* the visitor context
*/
public NabuccoToJavaDatatypeRefIdVisitor(NabuccoToJavaVisitorContext context) {
super(createContext(context));
}
/**
* Prepare the visitor context for the current traversion.
*
* @param context
* the existing context
*
* @return the new context
*/
private static NabuccoToJavaVisitorContext createContext(NabuccoToJavaVisitorContext context) {
context = new NabuccoToJavaVisitorContext(context);
context.setNabuccoExtension(null);
return context;
}
@Override
public void visit(DatatypeStatement nabuccoDatatype, MdaModel<JavaModel> target) {
super.visit(nabuccoDatatype, target);
this.createParentRefIds(target);
}
/**
* Create the reference IDs for the datatypes parent datatypes.
*
* @param target
* the java target
*/
private void createParentRefIds(MdaModel<JavaModel> target) {
NabuccoModel parent = super.getParent();
if (parent != null) {
super.getVisitorContext().setNabuccoExtension(null);
parent.getUnit().accept(this, target);
}
}
@Override
public void visit(DatatypeDeclaration nabuccoDatatype, MdaModel<JavaModel> target) {
// Transient fields must not have a ref id.
if (nabuccoDatatype.nodeOptional.present()) {
return;
}
NabuccoMultiplicityType multiplicity = NabuccoMultiplicityTypeMapper.getInstance().mapToMultiplicity(
nabuccoDatatype.nodeToken1.tokenImage);
if (!multiplicity.isMultiple()) {
this.createRefId(nabuccoDatatype);
this.createOverwritingSetter(nabuccoDatatype);
}
}
/**
* Checks whether a type is of another component and creates a reference ID.
*
* @param nabuccoDatatype
* the datatype declaration
*
*/
private void createRefId(DatatypeDeclaration nabuccoDatatype) {
String name = nabuccoDatatype.nodeToken2.tokenImage;
JavaAstContainter<FieldDeclaration> field = JavaAstSupport.createField(REF_ID_TYPE, name + REF_ID,
NabuccoModifierType.PRIVATE);
JavaAstContainter<MethodDeclaration> getter = JavaAstSupport.createGetter(field.getAstNode());
JavaAstContainter<MethodDeclaration> setter = JavaAstSupport.createSetter(field.getAstNode());
this.getVisitorContext().getContainerList().add(field);
this.getVisitorContext().getContainerList().add(getter);
this.getVisitorContext().getContainerList().add(setter);
}
/**
* Creates the overwriting setter which is setting the ref ID appropriate to the setters ID.
*
* @param nabuccoDatatype
* the datatype declaration
*/
private void createOverwritingSetter(DatatypeDeclaration nabuccoDatatype) {
String type = ((NodeToken) nabuccoDatatype.nodeChoice1.choice).tokenImage;
String name = nabuccoDatatype.nodeToken2.tokenImage;
NabuccoModifierType modifier = NabuccoModifierTypeMapper.getInstance().mapToModifier(
((NodeToken) nabuccoDatatype.nodeChoice.choice).tokenImage);
JavaAstContainter<FieldDeclaration> field = JavaAstSupport.createField(type, name, modifier);
JavaAstContainter<MethodDeclaration> setter = JavaAstSupport.createSetter(field.getAstNode());
setter.getImports().add(super.resolveImport(type));
this.getVisitorContext().getContainerList().add(setter);
try {
JavaAstModelProducer producer = JavaAstModelProducer.getInstance();
JavaAstElementFactory javaFactory = JavaAstElementFactory.getInstance();
MethodDeclaration method = setter.getAstNode();
String setterName = javaFactory.getJavaAstMethod().getMethodName(method);
SuperReference superReference = producer.createSuperReference();
List<Expression> arguments = new ArrayList<Expression>();
for (Argument argument : method.arguments) {
arguments.add(producer.createSingleNameReference(javaFactory.getJavaAstArgument().getName(argument)));
}
method.statements = new Statement[] { producer.createMessageSend(setterName, superReference, arguments) };
NabuccoToJavaDatatypeVisitorSupport.prepareSetterForRefId(setter);
} catch (JavaModelException me) {
throw new NabuccoVisitorException("Error creating Reference ID for " + name + ".", me);
}
}
/**
* Getter for the field and method container.
*
* @return the list of container
*/
List<JavaAstContainter<? extends ASTNode>> getContainerList() {
return this.getVisitorContext().getContainerList();
}
}