/*
* 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.view.browsersupport;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.ast.Assignment;
import org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess;
import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.FieldReference;
import org.eclipse.jdt.internal.compiler.ast.ImportReference;
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
import org.eclipse.jdt.internal.compiler.ast.MessageSend;
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
import org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
import org.eclipse.jdt.internal.compiler.ast.Statement;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.nabucco.framework.generator.compiler.constants.NabuccoJavaTemplateConstants;
import org.nabucco.framework.generator.compiler.transformation.common.annotation.NabuccoAnnotation;
import org.nabucco.framework.generator.compiler.transformation.java.constants.ViewConstants;
import org.nabucco.framework.generator.compiler.transformation.util.NabuccoTransformationUtility;
import org.nabucco.framework.mda.model.java.JavaCompilationUnit;
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.element.method.JavaAstMethodSignature;
import org.nabucco.framework.mda.model.java.ast.produce.JavaAstModelProducer;
import org.nabucco.framework.mda.template.java.JavaTemplateException;
import org.nabucco.framework.mda.template.java.extract.JavaAstExtractorFactory;
import org.nabucco.framework.mda.template.java.extract.JavaAstStatementExtractor;
/**
* BrowserElementSupport
*
* @author Stefanie Feld, PRODYNA AG
*/
public class BrowserElementSupport implements ViewConstants {
/**
* Selects and modifies the method getValues and adds ifStatements for each basetype.
*
* @deprecated not needed anymore since the view model changed.
* @param datatypeName
* the name of the datatype in the view.
* @param viewName
* the name of the view.
* @param annotationDeclarationList
* the list of all mapped field annotation declarations.
* @param type
* the type declaration.
* @param helperUnit
* the java compilation unit for the helperTemplate.
* @throws JavaModelException
* if an error occurred transforming the model.
* @throws JavaTemplateException
* if an error occurred loading the template.
*/
@Deprecated
public static void addGetValuesStatements(String datatypeName, String viewName,
List<NabuccoAnnotation> annotationDeclarationList, TypeDeclaration type, JavaCompilationUnit helperUnit)
throws JavaModelException, JavaTemplateException {
JavaAstElementFactory javaFactory = JavaAstElementFactory.getInstance();
// select getValues()
JavaAstMethodSignature signature = new JavaAstMethodSignature(GET_VALUES);
MethodDeclaration getValues = (MethodDeclaration) javaFactory.getJavaAstType().getMethod(type, signature);
// count how many statements are from the datatype
int length = 0;
for (NabuccoAnnotation annotationDeclaration : annotationDeclarationList) {
if (annotationDeclaration.getValue().split(FIELD_SEPARATOR)[0].matches(datatypeName)) {
length++;
}
}
// copy the statements from getValues and add an if statement for each basetype property
Statement[] statement = getValues.statements;
int position = statement.length;
int size = position + length;
Statement[] newStatement = Arrays.copyOf(statement, size);
// the original method has two statements
// the first statement of the copy has to be the first of the original
// the last statement of the copy has to be the second of the original
// new statements are added between
newStatement[size - 1] = statement[1];
position--;
for (NabuccoAnnotation annotationDeclaration : annotationDeclarationList) {
if (annotationDeclaration.getValue().split(FIELD_SEPARATOR)[0].matches(datatypeName)) {
// load the template
TypeDeclaration helperType = helperUnit
.getType(NabuccoJavaTemplateConstants.BROWSER_VIEW_HELPER_TEMPLATE);
// select helper method getValues
JavaAstMethodSignature helperSignature = new JavaAstMethodSignature(GET_VALUES);
MethodDeclaration getValuesHelper = (MethodDeclaration) javaFactory.getJavaAstType().getMethod(
helperType, helperSignature);
JavaAstStatementExtractor statementExtractor = JavaAstExtractorFactory.getInstance()
.getStatementExtractor();
MessageSend messageSendStatement = (MessageSend) statementExtractor.extractStatement(
getValuesHelper.statements[0], getValuesHelper.scope);
modifyGetValuesStatement(viewName, annotationDeclaration, messageSendStatement);
// add the statement to the list of statements
newStatement[position] = messageSendStatement;
position++;
}
}
getValues.statements = newStatement;
}
/**
* Modifies the given statement for a property.
*
* @param viewName
* the name of the view.
* @param annotationDeclaration
* the mapped field of the property.
* @param messageSendStatement
* the statement to modify.
* @throws JavaModelException
* if an error occurred transforming the model.
*/
private static void modifyGetValuesStatement(String viewName, NabuccoAnnotation annotationDeclaration,
MessageSend messageSendStatement) throws JavaModelException {
JavaAstModelProducer jamp = JavaAstModelProducer.getInstance();
String property = PROPERTY;
String getProperty = GET;
if (annotationDeclaration.getValue() != null) {
for (int i = 0; i < annotationDeclaration.getValue().split(FIELD_SEPARATOR).length; i++) {
String actual = annotationDeclaration.getValue().split(FIELD_SEPARATOR)[i];
property = property + UNDERSCORE + actual.toUpperCase();
getProperty = getProperty + NabuccoTransformationUtility.firstToUpper(actual);
}
}
// change first argument
QualifiedNameReference firstArgument = jamp.createQualifiedNameReference(viewName + MODEL, property);
messageSendStatement.arguments[0] = firstArgument;
// change second argument
MessageSend secondArgument = (MessageSend) messageSendStatement.arguments[1];
SingleNameReference receiver = (SingleNameReference) secondArgument.receiver;
secondArgument = jamp.createMessageSend(getProperty, receiver, null);
messageSendStatement.arguments[1] = secondArgument;
}
/**
* Adds the import of a given String to the javaAstUnit.
*
* @param importString
* the String with the import.
* @param unit
* the java compilation unit where all imports are added to.
* @throws JavaModelException
* if an error occurred transforming the model.
*/
public static void addImport(String importString, JavaCompilationUnit unit) throws JavaModelException {
JavaAstElementFactory javaFactory = JavaAstElementFactory.getInstance();
ImportReference importReference = JavaAstModelProducer.getInstance().createImportReference(importString);
javaFactory.getJavaAstUnit().addImport(unit.getUnitDeclaration(), importReference);
}
/**
* Changes the constructor.
*
* @param datatypeName
* the name of the datatype in the view.
* @param datatype
* the name of the datatype type.
* @param name
* the name of the constructor.
* @param type
* the type declaration.
* @throws JavaModelException
* if an error occurred transforming the model.
*/
public static void changeConstructor(String viewName, String datatypeName, String datatype, String name,
TypeDeclaration type) throws JavaModelException {
JavaAstModelProducer jamp = JavaAstModelProducer.getInstance();
JavaAstElementFactory javaFactory = JavaAstElementFactory.getInstance();
// select the constructor
JavaAstMethodSignature signature = new JavaAstMethodSignature(name, DATATYPE);
ConstructorDeclaration constructor = javaFactory.getJavaAstType().getConstructor(type, signature);
Argument parameter = constructor.arguments[0];
// change type of parameter
TypeReference typeReference = jamp.createTypeReference(datatype, false);
parameter.type = typeReference;
// change argument of first statement
LocalDeclaration firstStatement = (LocalDeclaration) constructor.statements[0];
MessageSend initialization = (MessageSend) firstStatement.initialization;
ClassLiteralAccess browserElement = jamp.createClassLiteralAccess(datatype + EDIT_VIEW_BROWSER_ELEMENT);
initialization.arguments[0] = browserElement;
// change second statement
Assignment secondStatement = (Assignment) constructor.statements[1];
MessageSend secondStatementExpression = (MessageSend) secondStatement.expression;
ClassLiteralAccess browserElementHandler = jamp.createClassLiteralAccess(datatype
+ EDIT_VIEW_BROWSER_ELEMENT_HANDLER);
secondStatementExpression.arguments[0] = browserElementHandler;
// change third statement
Assignment thirdStatement = (Assignment) constructor.statements[2];
TypeReference viewModelReference = jamp.createTypeReference(viewName + MODEL, false);
AllocationExpression allocationExpression = jamp.createAllocationExpression(viewModelReference, null);
thirdStatement.expression = allocationExpression;
// change fourth statement
SingleNameReference viewModel = jamp.createSingleNameReference(VIEW_MODEL_FIELD);
SingleNameReference datatypeReference = jamp.createSingleNameReference(DATATYPE_FIELD);
List<Expression> arguments = new ArrayList<Expression>();
arguments.add(datatypeReference);
MessageSend fourthStatement = jamp.createMessageSend(
PREFIX_SETTER + NabuccoTransformationUtility.firstToUpper(datatypeName), viewModel, arguments);
constructor.statements[3] = fourthStatement;
}
/**
* Changes the method getViewModel().
*
* @param datatype
* the name of the datatype.
* @param type
* the type declaration.
* @throws JavaModelException
* if an error occurred transforming the model.
*/
public static void changeGetViewModel(String viewName, TypeDeclaration type) throws JavaModelException {
JavaAstModelProducer jamp = JavaAstModelProducer.getInstance();
JavaAstElementFactory javaFactory = JavaAstElementFactory.getInstance();
// select method getViewModel()
JavaAstMethodSignature signature = new JavaAstMethodSignature(GET_VIEW_MODEL);
MethodDeclaration getViewModel = (MethodDeclaration) javaFactory.getJavaAstType().getMethod(type, signature);
// change returnType
TypeReference typeReference = jamp.createTypeReference(viewName + MODEL, false);
getViewModel.returnType = typeReference;
}
/**
* Changes the method setViewModel().
*
* @param datatype
* the name of the datatype.
* @param type
* the type declaration.
* @throws JavaModelException
* if an error occurred transforming the model.
*/
public static void changeSetViewModel(String viewName, TypeDeclaration type) throws JavaModelException {
JavaAstModelProducer jamp = JavaAstModelProducer.getInstance();
JavaAstElementFactory javaFactory = JavaAstElementFactory.getInstance();
// select method getViewModel()
JavaAstMethodSignature signature = new JavaAstMethodSignature(SET_VIEW_MODEL, EDIT_VIEW_MODEL);
MethodDeclaration getViewModel = (MethodDeclaration) javaFactory.getJavaAstType().getMethod(type, signature);
// change type of argument
TypeReference typeReference = jamp.createTypeReference(viewName + MODEL, false);
getViewModel.arguments[0].type = typeReference;
}
/**
* Changes the setter.
*
* @param datatype
* the name of the datatype.
* @param type
* the type declaration.
* @throws JavaModelException
* if an error occurred transforming the model.
*/
public static void changeSetter(String datatype, TypeDeclaration type) throws JavaModelException {
JavaAstModelProducer jamp = JavaAstModelProducer.getInstance();
JavaAstElementFactory javaFactory = JavaAstElementFactory.getInstance();
String datatypeName = NabuccoTransformationUtility.firstToLower(datatype);
// select method setDatatype()
JavaAstMethodSignature signature = new JavaAstMethodSignature(PREFIX_SETTER + DATATYPE, DATATYPE);
MethodDeclaration setter = (MethodDeclaration) javaFactory.getJavaAstType().getMethod(type, signature);
// change name
setter.selector = (PREFIX_SETTER + datatype).toCharArray();
// change the name of the argument
setter.arguments[0].name = datatypeName.toCharArray();
// change the type of the argument
TypeReference typeReference = jamp.createTypeReference(datatype, false);
setter.arguments[0].type = typeReference;
// change first statement
SingleNameReference nameReference = jamp.createSingleNameReference(datatypeName);
FieldReference fieldReference = jamp.createFieldThisReference(datatypeName);
Assignment statement = (Assignment) setter.statements[0];
statement.expression = nameReference;
statement.lhs = fieldReference;
}
/**
* Changes the getter.
*
* @param datatype
* the name of the datatype.
* @param type
* the type declaration.
* @throws JavaModelException
* if an error occurred transforming the model.
*/
public static void changeGetter(String datatype, TypeDeclaration type) throws JavaModelException {
JavaAstModelProducer jamp = JavaAstModelProducer.getInstance();
JavaAstElementFactory javaFactory = JavaAstElementFactory.getInstance();
String datatypeName = NabuccoTransformationUtility.firstToLower(datatype);
// select method getDatatype()
JavaAstMethodSignature signature = new JavaAstMethodSignature(GET + DATATYPE);
MethodDeclaration getter = (MethodDeclaration) javaFactory.getJavaAstType().getMethod(type, signature);
// change returnType
TypeReference typeReference = jamp.createTypeReference(datatype, false);
getter.returnType = typeReference;
// change name
getter.selector = (GET + datatype).toCharArray();
// change the expression of the return statement
SingleNameReference nameReference = jamp.createSingleNameReference(datatypeName);
ReturnStatement returnStatement = (ReturnStatement) getter.statements[0];
returnStatement.expression = nameReference;
}
/**
* Changes the local field view model.
*
* @param type
* the type declaration.
* @throws JavaModelException
* if an error occurred transforming the model.
*/
public static void changeFieldViewModel(String viewName, TypeDeclaration type) throws JavaModelException {
JavaAstModelProducer jamp = JavaAstModelProducer.getInstance();
JavaAstElementFactory javaFactory = JavaAstElementFactory.getInstance();
// select field datatype
FieldDeclaration datatypeField = javaFactory.getJavaAstType().getField(type, VIEW_MODEL_FIELD);
// change type
TypeReference reference = jamp.createTypeReference(viewName + MODEL, false);
datatypeField.type = reference;
}
/**
* Changes the local field browser handler.
*
* @param datatype
* the name of the datatype.
* @param type
* the type declaration.
* @throws JavaModelException
* if an error occurred transforming the model.
*/
public static void changeFieldBrowserHandler(String datatype, TypeDeclaration type) throws JavaModelException {
JavaAstModelProducer jamp = JavaAstModelProducer.getInstance();
JavaAstElementFactory javaFactory = JavaAstElementFactory.getInstance();
// select field datatype
FieldDeclaration datatypeField = javaFactory.getJavaAstType().getField(type, BROWSER_HANDLER_FIELD);
// change type
TypeReference reference = jamp.createTypeReference(datatype + EDIT_VIEW_BROWSER_ELEMENT_HANDLER, false);
datatypeField.type = reference;
}
}