/*
* 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.visitor.util.spp;
import java.util.Arrays;
import java.util.Collections;
import java.util.StringTokenizer;
import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.FieldReference;
import org.eclipse.jdt.internal.compiler.ast.MessageSend;
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
import org.eclipse.jdt.internal.compiler.ast.Statement;
import org.eclipse.jdt.internal.compiler.ast.ThisReference;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.nabucco.framework.generator.compiler.transformation.util.NabuccoTransformationUtility;
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;
/**
* StructuredPropertyPathElementFactory
*
* @author Silas Schwarz PRODYNA AG
*/
public class StructuredPropertyPathViewModelElementFactory {
private static StructuredPropertyPathViewModelElementFactory instance;
/**
* @return Returns the instance.
*/
public static StructuredPropertyPathViewModelElementFactory getInstance() {
if (instance == null) {
instance = new StructuredPropertyPathViewModelElementFactory();
}
return instance;
}
private StructuredPropertyPathViewModelElementFactory() {
}
/**
* Creates a getter method for a given {@link StructuredPropertyPath} root element and a
* absolute name. This method checks several conditions in order to determinate how the method
* should look like. taken in to account are the element type
* {@link StructuredPropertyPathEntryType} the multiplicity and location in the path (special
* treatment for cases such as the parent is a set)
*
* @param root
* the root element of the {@link StructuredPropertyPath}
* @param name
* the absolute mapped property name
* @return a getter methods
* @throws JavaModelException
*/
public MethodDeclaration createGetter(StructuredPropertyPathEntry root, String name) throws JavaModelException {
String orginalPath = name;
StructuredPropertyPathEntry entry = root.getEntry(name);
JavaAstModelProducer modelProducer = JavaAstModelProducer.getInstance();
JavaAstElementFactory elementFactory = JavaAstElementFactory.getInstance();
name = OperationType.GETTER.format(convertToMethodName(name));
MethodDeclaration methodDeclaration = modelProducer.createMethodDeclaration(name, null, false);
switch (entry.getEntryType()) {
case BASETYPE: {
elementFactory.getJavaAstMethod().setReturnType(methodDeclaration,
modelProducer.createTypeReference("String", false));
if (!isParentSet(root, orginalPath)) {
methodDeclaration.statements = new Statement[] { modelProducer
.createReturnStatement(CommonOperationSupport.createNullSaveGetterChain(
modelProducer.createThisReference(), orginalPath.concat(".value"))) };
} else {
methodDeclaration.statements = new Statement[] { modelProducer.createReturnStatement(modelProducer
.createFieldThisReference(convertToMethodName(orginalPath))) };
}
break;
}
case ENUMERATION: {
elementFactory.getJavaAstMethod().setReturnType(methodDeclaration,
modelProducer.createTypeReference("String", false));
MessageSend getterChain = CommonOperationSupport.createGetterChain(modelProducer.createThisReference(),
orginalPath);
getterChain = modelProducer.createMessageSend("name", getterChain, Collections.<Expression> emptyList());
methodDeclaration.statements = new Statement[] { modelProducer.createReturnStatement(CommonOperationSupport
.getNullChecks(getterChain, OperationType.GETTER)) };
break;
}
case DATATYPE: {
if (entry.isMultiple()) {
TypeReference parameterizedTypeReference = modelProducer.createParameterizedTypeReference("Set", false,
Arrays.asList(new TypeReference[] { entry.getTypeReference() }));
elementFactory.getJavaAstMethod().setReturnType(methodDeclaration, parameterizedTypeReference);
} else {
elementFactory.getJavaAstMethod().setReturnType(methodDeclaration, entry.getTypeReference());
if (isRootEntry(root, orginalPath)) {
methodDeclaration.statements = new Statement[] { modelProducer.createReturnStatement(modelProducer
.createFieldThisReference(orginalPath)) };
} // no else case only getter for rooted datatypes
}
break;
}
case ROOT:
default: {
throw new IllegalStateException("unreachable access in create getter for structured property support");
}
}
return methodDeclaration;
}
/**
* Creates a setter method for a given {@link StructuredPropertyPath} root element and a
* absolute name. This method checks several conditions in order to determinate how the method
* should look like. taken in to account are the element type
* {@link StructuredPropertyPathEntryType} the multiplicity and location in the path (special
* treatment for cases such as the parent is a set)
*
* @param root
* the root element of the {@link StructuredPropertyPath}
* @param name
* the absolute mapped property name
* @return a setter methods
* @throws JavaModelException
*/
public MethodDeclaration createSetter(StructuredPropertyPathEntry root, String name) throws JavaModelException {
String orginalPath = name;
StructuredPropertyPathEntry entry = root.getEntry(name);
JavaAstModelProducer modelProducer = JavaAstModelProducer.getInstance();
JavaAstElementFactory elementFactory = JavaAstElementFactory.getInstance();
String propertyName = NabuccoTransformationUtility.firstToLower(convertToMethodName(name));
name = OperationType.SETTER.format(propertyName);
MethodDeclaration methodDeclaration = modelProducer.createMethodDeclaration(name, null, false);
switch (entry.getEntryType()) {
case BASETYPE: {
if (isParentSet(root, orginalPath)) {
elementFactory.getJavaAstMethod().addArgument(methodDeclaration,
modelProducer.createArgument(propertyName, modelProducer.createTypeReference("String", false)));
ThisReference thisReference = modelProducer.createThisReference();
FieldReference fieldReference = modelProducer.createFieldThisReference(propertyName);
SingleNameReference parameterReference = modelProducer.createSingleNameReference(propertyName);
methodDeclaration.statements = new Statement[] { modelProducer
.createMessageSend("updateProperty", thisReference, Arrays.asList(new Expression[] {
fieldReference,
modelProducer.createAssignment(fieldReference, modelProducer
.createConditionalExpression(
CommonOperationSupport.createNullCheck(parameterReference),
parameterReference, CommonOperationSupport.getEmptyStringLiteral())) })) };
} else {
}
break;
}
case DATATYPE: {
if (entry.isMultiple()) {
} else {
elementFactory.getJavaAstMethod().addArgument(
methodDeclaration,
modelProducer.createArgument(propertyName,
modelProducer.createTypeReference(entry.getTypeReference().toString(), false)));
}
break;
}
case ENUMERATION: {
break;
}
case ROOT:
break;
default: {
}
}
return methodDeclaration;
}
/**
* @param root
* @param orginalPath
* @return
*/
private boolean isParentSet(StructuredPropertyPathEntry root, String orginalPath) {
int index = orginalPath.lastIndexOf(StructuredPropertyPathEntry.SEPARATOR);
if (index > 0) {
return root.getEntry(orginalPath.substring(0, index)).isMultiple();
}
return false;
}
private String convertToMethodName(String path) {
StringTokenizer st = new StringTokenizer(path, StructuredPropertyPathEntry.SEPARATOR.toString());
path = "";
while (st.hasMoreTokens()) {
path = path.concat(NabuccoTransformationUtility.firstToUpper(st.nextToken()));
}
return path;
}
private boolean isRootEntry(StructuredPropertyPathEntry root, String path) {
return !(path.split("\\" + StructuredPropertyPathEntry.SEPARATOR.toString()).length > 1);
}
}