/*******************************************************************************
* Copyright (c) 2010 Michal Antkiewicz.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Michal Antkiewicz - initial API and implementation
******************************************************************************/
package ca.uwaterloo.gsd.fsml.javaMappingInterpreter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EAnnotation;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.Annotation;
import org.eclipse.jdt.core.dom.ClassInstanceCreation;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.NormalAnnotation;
import org.eclipse.jdt.core.dom.NullLiteral;
import org.eclipse.jdt.core.dom.PackageDeclaration;
import org.eclipse.jdt.core.dom.ReturnStatement;
import org.eclipse.jdt.core.dom.SuperMethodInvocation;
import org.eclipse.jdt.core.dom.Type;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
import org.eclipse.jdt.core.search.SearchMatch;
import org.eclipse.jdt.internal.core.DefaultWorkingCopyOwner;
import org.eclipse.jdt.internal.corext.refactoring.structure.ASTNodeSearchUtil;
import ca.uwaterloo.gsd.fsml.core.Cause;
import ca.uwaterloo.gsd.fsml.core.FSMLMappingException;
import ca.uwaterloo.gsd.fsml.core.FSMLMappingInterpreter;
import ca.uwaterloo.gsd.fsml.core.Markers;
import ca.uwaterloo.gsd.fsml.core.Queries;
import ca.uwaterloo.gsd.fsml.ecore.FSMLEcoreUtil;
import ca.uwaterloo.gsd.fsml.fsml.Model;
import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.analysis.ASTUtils;
import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.analysis.IAnalysisManagers;
import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.analysis.IHierarchicalCallGraphManager;
import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.analysis.IJavaASTManager;
import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.analysis.IJavaImplVariantManager;
import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.analysis.impl.AnalysisManagers;
import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.mappings.AnnotatedWithMapping;
import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.mappings.AnnotationAttributeMapping;
import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.mappings.ArgumentIsFieldMapping;
import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.mappings.ArgumentIsNewMapping;
import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.mappings.ArgumentIsThisMapping;
import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.mappings.ArgumentIsVariableMapping;
import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.mappings.ArgumentMapping;
import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.mappings.ArgumentValueMapping;
import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.mappings.AssignedWithNewMapping;
import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.mappings.AssignedWithNullMapping;
import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.mappings.CallsReceivedMapping;
import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.mappings.ExtendsClassMapping;
import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.mappings.FieldTypeAnnotatedWithMapping;
import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.mappings.HasFieldAnnotatedWithMapping;
import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.mappings.HasFieldTypedWithMapping;
import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.mappings.ImplementsInterfaceMapping;
import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.mappings.LocalVariableTypeAnnotatedWithMapping;
import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.mappings.MethodCallMapping;
import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.mappings.MethodCallsMapping;
import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.mappings.MethodNameMapping;
import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.mappings.MethodsMapping;
import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.mappings.NumberOfPublicMethodsMapping;
import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.mappings.PublicMethodsMapping;
import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.mappings.TypedWithMapping;
import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.mappings.TypesOfReturnedObjectsMapping;
import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.preferences.JavaPreferenceConstants;
import ca.uwaterloo.gsd.fsml.stats.Stats;
import ca.uwaterloo.gsd.fsml.sync.ClassSyncItem;
import ca.uwaterloo.gsd.fsml.sync.RA;
import ca.uwaterloo.gsd.fsml.sync.StructuralFeatureSyncItem;
/**
* @author Michal Antkiewicz <mantkiew@gsd.uwaterloo.ca>
*/
public class JavaMappingInterpreter extends FSMLMappingInterpreter {
/**
* constants for context annotations
*/
public static final String CONTEXT_ANNOTATION = "annotation";
public static final String CONTEXT_PROJECT = "project";
public static final String CONTEXT_FIELD = "field";
public static final String CONTEXT_LOCAL_VARIABLE = "localVariable";
public static final String CONTEXT_METHOD = "method";
public static final String CONTEXT_METHOD_CALL = "methodCall";
public static final String CONTEXT_CLASS = "class";
/**
* constants for query annotations
*/
public static final String QUERY_ATTRIBUTE = "attribute";
public static final String QUERY_ARGUMENT = "argument";
public static final String QUERY_METHOD_CALL = "methodCall";
public static final String QUERY_ARGUMENT_IS_FIELD = "argumentIsField";
public static final String QUERY_ARGUMENT_IS_VARIABLE = "argumentIsVariable";
public static final String QUERY_ARGUMENT_IS_NEW = "argumentIsNew";
public static final String QUERY_ARGUMENT_IS_THIS = "argumentIsThis";
public static final String QUERY_ARGUMENT_VALUE = "argumentValue";
public static final String QUERY_ARGUMENT_NAME = "argumentName";
public static final String QUERY_CALLS_RECEIVED = "callsReceived";
public static final String QUERY_ASSIGNED_WITH_NULL = "assignedWithNull";
public static final String QUERY_ASSIGNED_WITH_NEW = "assignedWithNew";
public static final String QUERY_TYPED_WITH = "typedWith";
public static final String QUERY_FIELD_TYPE = "fieldType";
public static final String QUERY_FIELD_NAME = "fieldName";
public static final String QUERY_FIELD_TYPE_ANNOTATED_WITH = "fieldTypeAnnotatedWith";
public static final String QUERY_LOCAL_VARIABLE_TYPE = "localVariableType";
public static final String QUERY_LOCAL_VARIABLE_NAME = "localVariableName";
public static final String QUERY_LOCAL_VARIABLE_TYPE_ANNOTATED_WITH = "localVariableTypeAnnotatedWith";
public static final String QUERY_TYPES_OF_RETURNED_OBJECTS = "typesOfReturnedObjects";
public static final String QUERY_RETURNS_OBJECT_OF_TYPE = "returnsObjectOfType";
public static final String QUERY_RETURN_TYPES = "returnTypes";
public static final String QUERY_METHODS = "methods";
public static final String QUERY_SIGNATURE = "signature";
public static final String QUERY_METHOD_NAME = "methodName";
public static final String QUERY_ANNOTATED_WITH = "annotatedWith";
public static final String QUERY_HAS_NO_ATTRIBUTE = "hasNoAttribute";
public static final String QUERY_HAS_FIELD_ANNOTATED_WITH = "hasFieldAnnotatedWith";
public static final String QUERY_HAS_FIELD_TYPED_WITH = "hasFieldTypedWith";
public static final String QUERY_IS_LOCAL = "isLocal";
public static final String QUERY_IMPLEMENTS_INTERFACE = "implementsInterface";
public static final String QUERY_EXTENDS_CLASS = "extendsClass";
public static final String QUERY_QUALIFIER = "qualifier";
public static final String QUERY_CLASS_NAME = "className";
public static final String QUERY_IS_CLASS = "isClass";
public static final String QUERY_IS_INTERFACE = "isInterface";
public static final String QUERY_FULLY_QUALIFIED_NAME = "fullyQualifiedName";
public static final String QUERY_PROJECT_NAME = "projectName";
public static final String QUERY_METHOD_CALLS = "methodCalls";
public static final String QUERY_NUMBER_OF_PUBLIC_METHODS = "numberOfPublicMethods";
public static final String QUERY_PUBLIC_METHODS = "publicMethods";
/**
* constants for annotation details
*/
public static final String DETAIL_SAME_AS = "sameAs";
public static final String DETAIL_RECEIVER = "receiver";
public static final String DETAIL_IN = "in";
public static final String DETAIL_ATTRIBUTE_NAME = "attributeName";
public static final String DETAIL_INHERITED = "inherited";
public static final String DETAIL_FEATURE_PATH = "featurePath";
public static final String DETAIL_INDEX = "index";
public static final String DETAIL_NAME = "name";
public static final String DETAIL_CONCRETE = "concrete";
public static final String DETAIL_ABSTRACT = "abstract";
public static final String DETAIL_LOCAL = "local";
public static final String DETAIL_FULLY_QUALIFIED_TYPE = "fullyQualifiedType";
public static final String DETAIL_FULLY_QUALIFIED_NAME = "fullyQualifiedName";
public static final String DETAIL_CLASS = "class";
public static final String DETAIL_POSITION = "position";
public static final String DETAIL_INITIALIZER = "initializer";
public static final String DETAIL_SIGNATURE = "signature";
public static final String DETAIL_LOCATION_SIG = "locationSig";
public static final String DETAIL_LOCATION_NAME = "locationName";
public static final String DETAIL_RECEIVER_EXPR = "receiverExpr";
public static final String DETAIL_ARGUMENT = "argument";
public static final String DETAIL_OF_METHOD_CALL = "ofMethodCall";
public static final String DETAIL_SAME_AS_ARG = "sameAsArg";
public static final String DETAIL_OF_CALL = "ofCall";
public static final String DETAIL_CALL = "call";
public static final String DETAIL_BEFORE = "before";
public static final String DETAIL_GIVEN_CALLBACK_SEQ = "givenCallbackSeq";
public static final String DETAIL_SUBTYPE_OF = "subtypeOf";
public static final String DETAIL_STATEMENT = "statement";
public static final String DETAIL_IFKEY = "ifkey";
/**
* Herman: Whether to perform variant analysis and create generator model for a project.
*/
public static boolean analyzeImplVariants (){
return JavaMappingInterpreterPlugin.getPlugin().getPreferenceStore().getBoolean(JavaPreferenceConstants.ANALYZE_IMPL_VARIANTS_ID);
}
/**
* A link to the owner being used in the interpreter
*/
public static final DefaultWorkingCopyOwner primaryWorkingCopyOwner = DefaultWorkingCopyOwner.PRIMARY;
protected IAnalysisManagers analysisManagers = null;
public String getDescription() {
return "Default FSML Java Mapping Interpreter";
}
@Override
public String[] getContextAnnotations() {
return new String[] { CONTEXT_CLASS, CONTEXT_METHOD_CALL, CONTEXT_METHOD, CONTEXT_FIELD,CONTEXT_LOCAL_VARIABLE, CONTEXT_PROJECT, JavaMappingInterpreter.CONTEXT_ANNOTATION };
}
@Override
public String[] getQueryAnnotations() {
return new String[] {
QUERY_PROJECT_NAME,
QUERY_FULLY_QUALIFIED_NAME, QUERY_CLASS_NAME, QUERY_QUALIFIER, QUERY_EXTENDS_CLASS, QUERY_IMPLEMENTS_INTERFACE, QUERY_IS_LOCAL, QUERY_ANNOTATED_WITH,
QUERY_IS_CLASS,QUERY_HAS_FIELD_ANNOTATED_WITH,QUERY_HAS_FIELD_TYPED_WITH,QUERY_NUMBER_OF_PUBLIC_METHODS,QUERY_PUBLIC_METHODS,
// method
QUERY_METHOD_NAME, QUERY_SIGNATURE, QUERY_METHODS, QUERY_RETURNS_OBJECT_OF_TYPE, QUERY_TYPES_OF_RETURNED_OBJECTS, QUERY_RETURN_TYPES, // + QUERY_ANNOTATED_WITH,
// field
QUERY_FIELD_NAME, QUERY_FIELD_TYPE, QUERY_TYPED_WITH, QUERY_ASSIGNED_WITH_NEW, QUERY_ASSIGNED_WITH_NULL, // + QUERY_ANNOTATED_WITH,
QUERY_METHOD_CALLS, QUERY_CALLS_RECEIVED,QUERY_FIELD_TYPE_ANNOTATED_WITH,
// method call argument
QUERY_ARGUMENT_NAME, QUERY_ARGUMENT_VALUE, QUERY_ARGUMENT_IS_THIS, QUERY_ARGUMENT_IS_NEW, QUERY_ARGUMENT_IS_VARIABLE, QUERY_ARGUMENT_IS_FIELD, QUERY_METHOD_CALL,
// argument i of method call m1 same object as argument j of method call m2
QUERY_ARGUMENT,
// annotations
QUERY_ATTRIBUTE, QUERY_HAS_NO_ATTRIBUTE,
//statements
QUERY_LOCAL_VARIABLE_TYPE_ANNOTATED_WITH, QUERY_LOCAL_VARIABLE_NAME,QUERY_LOCAL_VARIABLE_TYPE
};
}
public boolean createChildrenForQueryFeature(EObject element, EReference feature, EClass concreteChildType, EStructuralFeature queryFeature, IProgressMonitor progressMonitor) throws FSMLMappingException {
EAnnotation annotation = FSMLEcoreUtil.getEAnnotation(concreteChildType, CONTEXT_CLASS);
if (annotation != null) {
EAnnotation auxAnnotation = queryFeature.getEAnnotation(QUERY_IMPLEMENTS_INTERFACE);
if (auxAnnotation != null)
return new ImplementsInterfaceMapping(element, feature, queryFeature, auxAnnotation, concreteChildType, this, progressMonitor).performReverseEssential();
auxAnnotation = queryFeature.getEAnnotation(QUERY_EXTENDS_CLASS);
if (auxAnnotation != null)
return new ExtendsClassMapping(element, feature, queryFeature, auxAnnotation, concreteChildType, this, progressMonitor).performReverseEssential();
auxAnnotation = queryFeature.getEAnnotation(QUERY_ANNOTATED_WITH);
if (auxAnnotation != null)
return new AnnotatedWithMapping(element, feature, queryFeature, auxAnnotation, concreteChildType, this, progressMonitor).performReverseEssential();
auxAnnotation = queryFeature.getEAnnotation(QUERY_HAS_FIELD_ANNOTATED_WITH);
if (auxAnnotation != null)
return new HasFieldAnnotatedWithMapping(element, feature, queryFeature, auxAnnotation, concreteChildType, this, progressMonitor).performReverseEssential();
auxAnnotation = queryFeature.getEAnnotation(QUERY_HAS_FIELD_TYPED_WITH);
if (auxAnnotation != null)
return new HasFieldTypedWithMapping(element, feature, queryFeature, auxAnnotation, concreteChildType, this, progressMonitor).performReverseEssential();
}
annotation = FSMLEcoreUtil.getEAnnotation(concreteChildType, CONTEXT_METHOD);
if (annotation != null) {
EAnnotation auxAnnotation = queryFeature.getEAnnotation(QUERY_ANNOTATED_WITH);
if (auxAnnotation != null)
return new AnnotatedWithMapping(element, feature, queryFeature, auxAnnotation, concreteChildType, this, progressMonitor).performReverseEssential();
}
annotation = FSMLEcoreUtil.getEAnnotation(concreteChildType, CONTEXT_FIELD);
if (annotation != null) {
EAnnotation auxAnnotation = queryFeature.getEAnnotation(QUERY_TYPED_WITH);
if (auxAnnotation != null)
return new TypedWithMapping(element, feature, queryFeature, auxAnnotation, concreteChildType, this, progressMonitor).performReverseEssential();
auxAnnotation = queryFeature.getEAnnotation(QUERY_ANNOTATED_WITH);
if (auxAnnotation != null)
return new AnnotatedWithMapping(element, feature, queryFeature, auxAnnotation, concreteChildType, this, progressMonitor).performReverseEssential();
auxAnnotation = queryFeature.getEAnnotation(QUERY_FIELD_TYPE_ANNOTATED_WITH);
if (auxAnnotation != null)
return new FieldTypeAnnotatedWithMapping(element, feature, queryFeature, auxAnnotation, concreteChildType, this, progressMonitor).performReverseEssential();
}
annotation = FSMLEcoreUtil.getEAnnotation(concreteChildType, CONTEXT_LOCAL_VARIABLE);
if (annotation != null) {
EAnnotation auxAnnotation = queryFeature.getEAnnotation(QUERY_LOCAL_VARIABLE_TYPE_ANNOTATED_WITH);
if (auxAnnotation != null)
return new LocalVariableTypeAnnotatedWithMapping(element, feature, queryFeature, auxAnnotation, concreteChildType, this, progressMonitor).performReverseEssential();
}
return false;
}
public EStructuralFeature findQueryFeature(EClass eClass) {
EAnnotation annotation = FSMLEcoreUtil.getEAnnotation(eClass, CONTEXT_CLASS);
if (annotation != null) {
// retrieve essential implementsInterface or extendsClass annotation
EStructuralFeature queryFeature = FSMLEcoreUtil.findEStructuralFeatureWithAnnotations(eClass, new String[] { FSMLEcoreUtil.ESSENTIAL, QUERY_IMPLEMENTS_INTERFACE} );
if (queryFeature == null)
queryFeature = FSMLEcoreUtil.findEStructuralFeatureWithAnnotations(eClass, new String[] { FSMLEcoreUtil.ESSENTIAL, QUERY_EXTENDS_CLASS } );
if (queryFeature == null)
queryFeature = FSMLEcoreUtil.findEStructuralFeatureWithAnnotations(eClass, new String[] { FSMLEcoreUtil.ESSENTIAL, QUERY_ANNOTATED_WITH } );
if (queryFeature == null)
queryFeature = FSMLEcoreUtil.findEStructuralFeatureWithAnnotations(eClass, new String[] { FSMLEcoreUtil.ESSENTIAL, QUERY_HAS_FIELD_ANNOTATED_WITH } );
if (queryFeature == null)
queryFeature = FSMLEcoreUtil.findEStructuralFeatureWithAnnotations(eClass, new String[] { FSMLEcoreUtil.ESSENTIAL, QUERY_HAS_FIELD_TYPED_WITH } );
return queryFeature;
}
annotation = FSMLEcoreUtil.getEAnnotation(eClass, CONTEXT_LOCAL_VARIABLE);
if (annotation != null){
// retrieve essential typedWith annotation
return FSMLEcoreUtil.findEStructuralFeatureWithAnnotations(eClass, new String[] { FSMLEcoreUtil.ESSENTIAL, QUERY_LOCAL_VARIABLE_TYPE_ANNOTATED_WITH } );
}
annotation = FSMLEcoreUtil.getEAnnotation(eClass, CONTEXT_FIELD);
if (annotation != null){
// retrieve essential typedWith annotation
EStructuralFeature queryFeature = FSMLEcoreUtil.findEStructuralFeatureWithAnnotations(eClass, new String[] { FSMLEcoreUtil.ESSENTIAL, QUERY_TYPED_WITH } );
if (queryFeature == null)
queryFeature = FSMLEcoreUtil.findEStructuralFeatureWithAnnotations(eClass, new String[] { FSMLEcoreUtil.ESSENTIAL, QUERY_ANNOTATED_WITH } );
if (queryFeature == null)
queryFeature = FSMLEcoreUtil.findEStructuralFeatureWithAnnotations(eClass, new String[] { FSMLEcoreUtil.ESSENTIAL, QUERY_FIELD_TYPE_ANNOTATED_WITH } );
return queryFeature;
}
annotation = FSMLEcoreUtil.getEAnnotation(eClass, CONTEXT_METHOD);
if (annotation != null){
// retrieve essential typedWith annotation
return FSMLEcoreUtil.findEStructuralFeatureWithAnnotations(eClass, new String[] { FSMLEcoreUtil.ESSENTIAL, QUERY_ANNOTATED_WITH } );
}
return null;
}
@Override
public boolean forwardFeatureRepresentedAsClass(ClassSyncItem classSyncItem, IProgressMonitor progressMonitor) throws FSMLMappingException {
RA action = classSyncItem.getReconciliationAction();
EObject element = classSyncItem.getModel();
if (element == null)
element = classSyncItem.getCode();
EClass eClass = element.eClass();
EAnnotation annotation = FSMLEcoreUtil.getEAnnotation(eClass, CONTEXT_CLASS);
if (annotation != null) {
EAttribute nameFeature = (EAttribute) FSMLEcoreUtil.findEStructuralFeatureWithAnnotations(eClass, new String[] {QUERY_CLASS_NAME} );
EAttribute qualifierFeature = (EAttribute) FSMLEcoreUtil.findEStructuralFeatureWithAnnotations(eClass, new String[] {QUERY_QUALIFIER} );
EAttribute fqNameFeature = (EAttribute) FSMLEcoreUtil.findEStructuralFeatureWithAnnotations(eClass, new String[] {QUERY_FULLY_QUALIFIED_NAME} );
assert (fqNameFeature != null || (nameFeature != null && qualifierFeature != null));
String className = null;
String packageName = null;
if (fqNameFeature != null) {
String fqName = (String) element.eGet(fqNameFeature);
while (fqName==null || fqName.length()==0){
fqName = (String)FSMLEcoreUtil.getAttributeValueFromAttributeValueWizard(fqNameFeature);
if (fqName!=null && fqName.length()>0){
element.eSet(fqNameFeature, fqName);
break;
}
}
className = Signature.getSimpleName(fqName);
packageName = Signature.getQualifier(fqName);
}
else {
className = (String) element.eGet(nameFeature);
packageName = (String) element.eGet(qualifierFeature);
}
int index = className.indexOf('$');
if (index == -1) {
// top-level class
IType iType;
switch (action) {
case CODE_ADD:
iType = CodeTransforms.createCompilationUnit(project, className, packageName, progressMonitor);
contextManager.associateContext(element, iType);
break;
case CODE_REMOVE:
iType = (IType) contextManager.getContextIType(element, true);
CodeTransforms.removeIType(iType, progressMonitor);
contextManager.removeContext(element);
break;
}
}
else {
// nested class
String topLevelClassName = className.substring(0, index);
String nestedClassName = className.substring(index+1);
String fqName = (packageName != null && !packageName.isEmpty()) ? packageName + "." + topLevelClassName : topLevelClassName;
TypeDeclaration topLevelTypeDeclaration;
try {
IType topLevelIType = project.findType(fqName);
if (topLevelIType == null || !topLevelIType.exists()) {
// need to create the top-level class
topLevelIType = CodeTransforms.createCompilationUnit(project, topLevelClassName, packageName, progressMonitor);
}
CompilationUnit cu = javaAstManager.getCompilationUnit(topLevelIType);
topLevelTypeDeclaration = ASTUtils.getTypeDeclarationNode(topLevelIType, cu);
TypeDeclaration typeDeclaration;
switch (action) {
case CODE_ADD:
typeDeclaration = CodeTransforms.createNestedTypeDeclaration(project, cu, topLevelTypeDeclaration, nestedClassName, progressMonitor);
contextManager.associateContext(element, typeDeclaration);
break;
case CODE_REMOVE:
typeDeclaration = contextManager.getContextTypeDeclaration(element, true, progressMonitor);
CodeTransforms.commentOutASTNode(cu, typeDeclaration, eClass, null, progressMonitor);
contextManager.removeContext(element);
break;
}
} catch (JavaModelException e1) {
e1.printStackTrace();
}
}
return true;
}
annotation = FSMLEcoreUtil.getEAnnotation(eClass, CONTEXT_METHOD);
if (annotation != null) {
return new MethodsMapping(classSyncItem, annotation, this, progressMonitor).performForward();
}
annotation = FSMLEcoreUtil.getEAnnotation(eClass, CONTEXT_FIELD);
if (annotation != null) {
EAttribute nameFeature = (EAttribute) FSMLEcoreUtil.findEStructuralFeatureWithAnnotations(eClass, new String[] {QUERY_FIELD_NAME} );
String fieldName = (String) element.eGet(nameFeature);
while (fieldName==null||fieldName.length()==0){
fieldName = (String)FSMLEcoreUtil.getAttributeValueFromAttributeValueWizard(nameFeature);
if (fieldName!=null && fieldName.length()>0){
element.eSet(nameFeature, fieldName);
break;
}
}
String fieldType = null;
EAttribute typedWithFeature = (EAttribute) FSMLEcoreUtil.findEStructuralFeatureWithAnnotations(eClass, new String[] {QUERY_TYPED_WITH} );
if (typedWithFeature != null) {
EAnnotation typeAnnotation = typedWithFeature.getEAnnotation(QUERY_TYPED_WITH);
fieldType = (String) FSMLEcoreUtil.retrieveParameterValue(typeAnnotation, DETAIL_NAME, true);
}
else {
// try using fieldType value
EAttribute fieldTypeFeature = (EAttribute) FSMLEcoreUtil.findEStructuralFeatureWithAnnotations(eClass, new String[] {QUERY_FIELD_TYPE} );
if (fieldTypeFeature != null)
fieldType = (String) element.eGet(fieldTypeFeature);
}
if (fieldType != null && !fieldType.isEmpty()) {
EObject contextFeature = FSMLEcoreUtil.retrieveContextElement(classSyncItem, CONTEXT_CLASS);
TypeDeclaration contextTypeDeclaration = contextManager.getContextTypeDeclaration(contextFeature, true, progressMonitor);
VariableDeclarationFragment variableDeclarationFragment;
if (contextTypeDeclaration != null) {
switch (action) {
case CODE_ADD:
variableDeclarationFragment = CodeTransforms.createField(project, null, contextTypeDeclaration, "public", fieldName, fieldType, progressMonitor);
contextManager.associateContext(element, variableDeclarationFragment);
break;
case CODE_REMOVE:
variableDeclarationFragment = contextManager.getContextVariableDeclarationFragment(element, true, progressMonitor);
variableDeclarationFragment.delete();
break;
}
}
}
}
annotation = FSMLEcoreUtil.getEAnnotation(eClass, CONTEXT_METHOD_CALL);
if (annotation != null) {
}
return true;
}
public boolean reverseFeatureRepresentedAsAttribute(EObject element, EAttribute feature, IProgressMonitor progressMonitor) throws FSMLMappingException {
try {
EAnnotation annotation = feature.getEAnnotation(QUERY_EXTENDS_CLASS);
if (annotation != null)
return new ExtendsClassMapping(element, feature, annotation, null, this, progressMonitor).performReverse();
annotation = feature.getEAnnotation(QUERY_IMPLEMENTS_INTERFACE);
if (annotation != null)
return new ImplementsInterfaceMapping(element, feature, annotation, null, this, progressMonitor).performReverse();
annotation = feature.getEAnnotation(QUERY_ARGUMENT_VALUE);
if (annotation != null)
return new ArgumentValueMapping(element, feature, annotation, null, this, progressMonitor).performReverse();
annotation = feature.getEAnnotation(QUERY_RETURNS_OBJECT_OF_TYPE);
if (annotation != null)
return doReturnsObjectOfType_reverse(element, feature, annotation, progressMonitor);
annotation = feature.getEAnnotation(QUERY_TYPES_OF_RETURNED_OBJECTS);
if (annotation != null)
return new TypesOfReturnedObjectsMapping(element, feature, annotation, null, this, progressMonitor).performReverse();
annotation = feature.getEAnnotation(QUERY_RETURN_TYPES);
if (annotation != null)
return doReturnTypes_reverse(element, feature, annotation, null, progressMonitor);
annotation = feature.getEAnnotation(QUERY_METHODS);
if (annotation != null)
return new MethodsMapping(element, feature, annotation, null, this, progressMonitor).performReverse();
annotation = feature.getEAnnotation(JavaMappingInterpreter.QUERY_METHOD_CALLS);
if (annotation != null)
return new MethodCallsMapping(element, feature, annotation, null, this, progressMonitor).performReverse();
annotation = feature.getEAnnotation(QUERY_CALLS_RECEIVED);
if (annotation != null)
return new CallsReceivedMapping(element, feature, annotation, null, this, progressMonitor).performReverse();
annotation = feature.getEAnnotation(QUERY_TYPED_WITH);
if (annotation != null)
return new TypedWithMapping(element, feature, annotation, null, this, progressMonitor).performReverse();
annotation = feature.getEAnnotation(QUERY_ASSIGNED_WITH_NULL);
if (annotation != null)
return new AssignedWithNullMapping(element, feature, annotation, null, this, progressMonitor).performReverse();
annotation = feature.getEAnnotation(QUERY_ASSIGNED_WITH_NEW);
if (annotation != null)
return new AssignedWithNewMapping(element, feature, annotation, null, this, progressMonitor).performReverse();
annotation = feature.getEAnnotation(QUERY_METHOD_NAME);
if (annotation != null)
return new MethodNameMapping(element, feature, annotation, null, this, progressMonitor).performReverse();
annotation = feature.getEAnnotation(QUERY_METHOD_CALL);
if (annotation != null)
return new MethodCallMapping(element, feature, annotation, null, this, progressMonitor).performReverse();
annotation = feature.getEAnnotation(QUERY_ARGUMENT);
if (annotation != null)
return new ArgumentMapping(element, feature, annotation, null, this, progressMonitor).performReverse();
annotation = feature.getEAnnotation(QUERY_ARGUMENT_IS_THIS);
if (annotation != null)
return new ArgumentIsThisMapping(element, feature, annotation, null, this, progressMonitor).performReverse();
annotation = feature.getEAnnotation(QUERY_ARGUMENT_IS_NEW);
if (annotation != null)
return new ArgumentIsNewMapping(element, feature, annotation, null, this, progressMonitor).performReverse();
annotation = feature.getEAnnotation(QUERY_ARGUMENT_IS_VARIABLE);
if (annotation != null)
return new ArgumentIsVariableMapping(element, feature, annotation, null, this, progressMonitor).performReverse();
annotation = feature.getEAnnotation(QUERY_ARGUMENT_IS_FIELD);
if (annotation != null)
return new ArgumentIsFieldMapping(element, feature, annotation, null, this, progressMonitor).performReverse();
annotation = feature.getEAnnotation(QUERY_ANNOTATED_WITH);
if (annotation != null)
return new AnnotatedWithMapping(element, feature, annotation,null,this, progressMonitor).performReverse();
annotation = feature.getEAnnotation(QUERY_HAS_FIELD_ANNOTATED_WITH);
if (annotation != null)
return new HasFieldAnnotatedWithMapping(element, feature, annotation,null,this, progressMonitor).performReverse();
annotation = feature.getEAnnotation(QUERY_HAS_FIELD_TYPED_WITH);
if (annotation != null)
return new HasFieldTypedWithMapping(element, feature, annotation,null,this, progressMonitor).performReverse();
annotation = feature.getEAnnotation(QUERY_FIELD_TYPE_ANNOTATED_WITH);
if (annotation != null)
return new FieldTypeAnnotatedWithMapping(element, feature, annotation,null,this, progressMonitor).performReverse();
annotation = feature.getEAnnotation(QUERY_LOCAL_VARIABLE_TYPE_ANNOTATED_WITH);
if (annotation != null)
return new LocalVariableTypeAnnotatedWithMapping(element, feature, annotation,null,this, progressMonitor).performReverse();
annotation = feature.getEAnnotation(QUERY_ATTRIBUTE);
if (annotation != null)
return new AnnotationAttributeMapping(element, feature, annotation,null,this, progressMonitor).performReverse();
annotation = feature.getEAnnotation(QUERY_NUMBER_OF_PUBLIC_METHODS);
if (annotation != null)
return new NumberOfPublicMethodsMapping(element, feature, annotation,null,this, progressMonitor).performReverse();
annotation = feature.getEAnnotation(QUERY_PUBLIC_METHODS);
if (annotation != null)
return new PublicMethodsMapping(element, feature, annotation,null,this, progressMonitor).performReverse();
annotation = feature.getEAnnotation(QUERY_HAS_NO_ATTRIBUTE);
if (annotation != null)
return doHasNoAttribute_reverse(element, feature, annotation, progressMonitor);
annotation = feature.getEAnnotation(QUERY_FULLY_QUALIFIED_NAME);
if (annotation != null) {
IType auxClass = contextManager.getContextIType(element, true);
if (auxClass == null) {
// try context TypeDeclaration
TypeDeclaration typeDeclaration = contextManager.getContextTypeDeclaration(element, true, progressMonitor);
if (typeDeclaration != null) {
PackageDeclaration packageDeclaration = ((CompilationUnit) typeDeclaration.getRoot()).getPackage();
String qualifier = null;
if (packageDeclaration != null)
qualifier = packageDeclaration.getName().getFullyQualifiedName();
String name = typeDeclaration.getName().getFullyQualifiedName();
String fqName = qualifier != null && !"".equals(qualifier) ?
qualifier + "." + name :
name;
element.eSet(feature, fqName);
Stats.INSTANCE.logFeatureInstance(element, feature, annotation);
return true;
}
// there is not context!
return false;
}
element.eSet(feature, auxClass.getFullyQualifiedName());
Stats.INSTANCE.logFeatureInstance(element, feature, annotation);
return true;
}
annotation = feature.getEAnnotation(QUERY_CLASS_NAME);
if (annotation != null) {
IType auxClass = contextManager.getContextIType(element, true);
if (auxClass == null) {
// try context TypeDeclaration
TypeDeclaration typeDeclaration = contextManager.getContextTypeDeclaration(element, true, progressMonitor);
if (typeDeclaration != null) {
element.eSet(feature, typeDeclaration.getName().getIdentifier());
Stats.INSTANCE.logFeatureInstance(element, feature, annotation);
return true;
}
// there is not context!
return false;
}
element.eSet(feature, auxClass.getElementName());
Stats.INSTANCE.logFeatureInstance(element, feature, annotation);
return true;
}
annotation = feature.getEAnnotation(QUERY_QUALIFIER);
if (annotation != null) {
IType auxClass = contextManager.getContextIType(element, true);
if (auxClass == null) {
// try context TypeDeclaration
TypeDeclaration typeDeclaration = contextManager.getContextTypeDeclaration(element, true, progressMonitor);
if (typeDeclaration != null) {
CompilationUnit cu = (CompilationUnit) typeDeclaration.getRoot();
PackageDeclaration packageDeclaration = ((CompilationUnit) typeDeclaration.getRoot()).getPackage();
String qualifier = null;
if (packageDeclaration != null)
qualifier = packageDeclaration.getName().getFullyQualifiedName();
element.eSet(feature, qualifier);
Stats.INSTANCE.logFeatureInstance(element, feature, annotation);
return true;
}
// there is not context!
return false;
}
element.eSet(feature, auxClass.getPackageFragment().getElementName());
Stats.INSTANCE.logFeatureInstance(element, feature, annotation);
return true;
}
annotation = feature.getEAnnotation(QUERY_FIELD_NAME);
if (annotation != null) {
VariableDeclarationFragment variableDeclarationFragment = contextManager.getContextVariableDeclarationFragment(element, true, progressMonitor);
if (variableDeclarationFragment != null) {
element.eSet(feature, new String(variableDeclarationFragment.getName().getIdentifier()));
Stats.INSTANCE.logFeatureInstance(element, feature, annotation);
return true;
}
return false;
}
annotation = feature.getEAnnotation(QUERY_LOCAL_VARIABLE_NAME);
if (annotation != null) {
VariableDeclarationFragment variableDeclarationFragment = contextManager.getContextVariableDeclarationFragment(element, true, progressMonitor);
if (variableDeclarationFragment != null) {
element.eSet(feature, new String(variableDeclarationFragment.getName().getIdentifier()));
Stats.INSTANCE.logFeatureInstance(element, feature, annotation);
return true;
}
return false;
}
annotation = feature.getEAnnotation(QUERY_IS_CLASS);
if (annotation != null) {
IType auxClass =contextManager.getContextIType(element, true);
if (auxClass == null)
return false;
element.eSet(feature, auxClass.isClass());
return auxClass.isClass();
}
annotation = feature.getEAnnotation(QUERY_IS_INTERFACE);
if (annotation != null) {
IType auxClass =contextManager.getContextIType(element, true);
if (auxClass == null)
return false;
element.eSet(feature, auxClass.isInterface());
return auxClass.isClass();
}
annotation = feature.getEAnnotation(QUERY_PROJECT_NAME);
if (annotation != null && feature.getEAttributeType().getName().equals("EString")) {
IJavaProject contextProject = contextManager.getContextIJavaProject(element);
if (contextProject == null)
return false;
element.eSet(feature, new String(contextProject.getElementName()));
Stats.INSTANCE.logFeatureInstance(element, feature, annotation);
return true;
}
annotation = feature.getEAnnotation(QUERY_IS_LOCAL);
if (annotation != null) {
IType auxClass = (IType)contextManager.getContextIType(element, true);
if (auxClass == null)
return false;
String queriesProject = project.getHandleIdentifier();
String elementsProject = auxClass.getJavaProject().getHandleIdentifier();
boolean isLocal = !auxClass.isBinary() && elementsProject.equals(queriesProject);
element.eSet(feature, new Boolean(isLocal));
Stats.INSTANCE.logFeatureInstance(element, feature, annotation);
return true;
}
// unsupported mappings
annotation = feature.getEAnnotation(QUERY_SIGNATURE);
if (annotation != null)
throw new UnsupportedOperationException();
annotation = feature.getEAnnotation(QUERY_FIELD_TYPE);
if (annotation != null){
VariableDeclarationFragment variableDeclarationFragment = contextManager.getContextVariableDeclarationFragment(element, true, progressMonitor);
if (variableDeclarationFragment != null) {
Type fieldType = ((FieldDeclaration)variableDeclarationFragment.getParent()).getType();
String typeName = ASTUtils.getFullyQualifiedName(fieldType);
element.eSet(feature, typeName);
Stats.INSTANCE.logFeatureInstance(element, feature, annotation);
return true;
}
return false;
}
annotation = feature.getEAnnotation(QUERY_LOCAL_VARIABLE_TYPE);
if (annotation != null){
VariableDeclarationFragment variableDeclarationFragment = contextManager.getContextVariableDeclarationFragment(element, true, progressMonitor);
if (variableDeclarationFragment != null) {
Type fieldType = ((VariableDeclarationStatement)variableDeclarationFragment.getParent()).getType();
String typeName = ASTUtils.getFullyQualifiedName(fieldType);
element.eSet(feature, typeName);
Stats.INSTANCE.logFeatureInstance(element, feature, annotation);
return true;
}
return false;
}
annotation = feature.getEAnnotation(QUERY_ARGUMENT_NAME);
if (annotation != null)
throw new UnsupportedOperationException();
} catch (JavaModelException e) {
e.printStackTrace();
}
return false;
}
@Override
public boolean forwardFeatureRepresentedAsAttribute(StructuralFeatureSyncItem featureSyncItem, IProgressMonitor progressMonitor) {
EStructuralFeature feature = featureSyncItem.getStructuralFeature();
try {
EAnnotation annotation = feature.getEAnnotation(QUERY_EXTENDS_CLASS);
if (annotation != null)
return new ExtendsClassMapping(featureSyncItem, annotation, this, progressMonitor).performForward();
annotation = feature.getEAnnotation(QUERY_IMPLEMENTS_INTERFACE);
if (annotation != null)
return new ImplementsInterfaceMapping(featureSyncItem, annotation, this, progressMonitor).performForward();
annotation = feature.getEAnnotation(QUERY_METHODS);
if (annotation != null)
return new MethodsMapping(featureSyncItem, annotation, this, progressMonitor).performForward();
annotation = feature.getEAnnotation(JavaMappingInterpreter.QUERY_METHOD_CALLS);
if (annotation != null)
return new MethodCallsMapping(featureSyncItem, annotation, this, progressMonitor).performForward();
annotation = feature.getEAnnotation(QUERY_ARGUMENT_IS_THIS);
if (annotation != null)
return new ArgumentIsThisMapping(featureSyncItem, annotation, this, progressMonitor).performForward();
annotation = feature.getEAnnotation(QUERY_ARGUMENT_IS_NEW);
if (annotation != null)
return new ArgumentIsNewMapping(featureSyncItem, annotation, this, progressMonitor).performForward();
annotation = feature.getEAnnotation(QUERY_ARGUMENT_IS_FIELD);
if (annotation != null)
return new ArgumentIsFieldMapping(featureSyncItem, annotation, this, progressMonitor).performForward();
annotation = feature.getEAnnotation(QUERY_ARGUMENT_IS_VARIABLE);
if (annotation != null)
return new ArgumentIsVariableMapping(featureSyncItem, annotation, this, progressMonitor).performForward();
annotation = feature.getEAnnotation(QUERY_ASSIGNED_WITH_NULL);
if (annotation != null)
return new AssignedWithNullMapping(featureSyncItem, annotation, this, progressMonitor).performForward();
annotation = feature.getEAnnotation(QUERY_ASSIGNED_WITH_NEW);
if (annotation != null)
return new AssignedWithNewMapping(featureSyncItem, annotation, this, progressMonitor).performForward();
annotation = feature.getEAnnotation(QUERY_ARGUMENT_VALUE);
if (annotation != null)
return new ArgumentValueMapping(featureSyncItem, annotation, this, progressMonitor).performForward();
annotation = feature.getEAnnotation(QUERY_TYPES_OF_RETURNED_OBJECTS);
if (annotation != null)
return new TypesOfReturnedObjectsMapping(featureSyncItem, annotation, this, progressMonitor).performForward();
annotation = feature.getEAnnotation(QUERY_ARGUMENT);
if (annotation != null)
return new ArgumentMapping(featureSyncItem, annotation, this, progressMonitor).performForward();
return true;
} catch (FSMLMappingException e) {
e.printStackTrace();
}
return false;
}
public boolean reverseFeatureRepresentedAsReference(EObject element, EReference feature, EClass concreteChildType, IProgressMonitor progressMonitor) throws FSMLMappingException {
try {
EAnnotation annotation = feature.getEAnnotation(QUERY_EXTENDS_CLASS);
if (annotation != null)
return new ExtendsClassMapping(element, feature, annotation, concreteChildType, this, progressMonitor).performReverse();
annotation = feature.getEAnnotation(QUERY_IMPLEMENTS_INTERFACE);
if (annotation != null)
return new ImplementsInterfaceMapping(element, feature, annotation, concreteChildType, this, progressMonitor).performReverse();
annotation = feature.getEAnnotation(QUERY_ANNOTATED_WITH);
if (annotation != null)
return new AnnotatedWithMapping(element,feature,annotation, concreteChildType,this,progressMonitor).performReverse();
annotation = feature.getEAnnotation(QUERY_METHODS);
if (annotation != null)
return new MethodsMapping(element, feature, annotation, concreteChildType, this, progressMonitor).performReverse();
annotation = feature.getEAnnotation(QUERY_RETURN_TYPES);
if (annotation != null)
return doReturnTypes_reverse(element, feature, annotation, concreteChildType, progressMonitor);
annotation = feature.getEAnnotation(QUERY_TYPED_WITH);
if (annotation != null)
return new TypedWithMapping(element, feature, annotation, null, this, progressMonitor).performReverse();
annotation = feature.getEAnnotation(QUERY_ASSIGNED_WITH_NULL);
if (annotation != null)
return new AssignedWithNullMapping(element, feature, annotation, concreteChildType, this, progressMonitor).performReverse();
annotation = feature.getEAnnotation(QUERY_ASSIGNED_WITH_NEW);
if (annotation != null)
return new AssignedWithNewMapping(element, feature, annotation, concreteChildType, this, progressMonitor).performReverse();
annotation = feature.getEAnnotation(JavaMappingInterpreter.QUERY_METHOD_CALLS);
if (annotation != null)
return new MethodCallsMapping(element, feature, annotation, concreteChildType, this, progressMonitor).performReverse();
annotation = feature.getEAnnotation(QUERY_CALLS_RECEIVED);
if (annotation != null)
return new CallsReceivedMapping(element, feature, annotation, concreteChildType, this, progressMonitor).performReverse();
annotation = feature.getEAnnotation(QUERY_ARGUMENT);
if (annotation != null)
return new ArgumentMapping(element, feature, annotation, concreteChildType, this, progressMonitor).performReverse();
annotation = feature.getEAnnotation(QUERY_ARGUMENT_IS_THIS);
if (annotation != null)
return new ArgumentIsThisMapping(element, feature, annotation, concreteChildType, this, progressMonitor).performReverse();
annotation = feature.getEAnnotation(QUERY_ARGUMENT_IS_NEW);
if (annotation != null)
return new ArgumentIsNewMapping(element, feature, annotation, concreteChildType, this, progressMonitor).performReverse();
annotation = feature.getEAnnotation(QUERY_ARGUMENT_IS_VARIABLE);
if (annotation != null)
return new ArgumentIsVariableMapping(element, feature, annotation, concreteChildType, this, progressMonitor).performReverse();
annotation = feature.getEAnnotation(QUERY_ARGUMENT_IS_FIELD);
if (annotation != null)
return new ArgumentIsFieldMapping(element, feature, annotation, concreteChildType, this, progressMonitor).performReverse();
annotation = feature.getEAnnotation(QUERY_ATTRIBUTE);
if (annotation != null)
return new AnnotationAttributeMapping(element,feature,annotation,concreteChildType,this,progressMonitor).performReverse();
//return doAttributeRepresentedAsReference_reverse(element, feature, annotation, concreteChildType, progressMonitor);
annotation = feature.getEAnnotation(QUERY_IS_CLASS);
if (annotation != null) {
IType auxClass =contextManager.getContextIType(element, true);
if (auxClass == null || !auxClass.isClass())
return false;
EObject child = EcoreUtil.create(concreteChildType);
element.eSet(feature, child);
return reverseFeatureRepresentedAsClass(child, progressMonitor);
}
annotation = feature.getEAnnotation(QUERY_IS_INTERFACE);
if (annotation != null) {
IType auxClass =contextManager.getContextIType(element, true);
if (auxClass == null || !auxClass.isInterface())
return false;
EObject child = EcoreUtil.create(concreteChildType);
element.eSet(feature, child);
return reverseFeatureRepresentedAsClass(child, progressMonitor);
}
annotation = feature.getEAnnotation(QUERY_IS_LOCAL);
if (annotation != null) {
IType auxClass = (IType)contextManager.getContextIType(element, true);
if (auxClass == null)
return false;
String queriesProject = project.getHandleIdentifier();
String elementsProject = auxClass.getJavaProject().getHandleIdentifier();
boolean isLocal = !auxClass.isBinary() && elementsProject.equals(queriesProject);
if (!isLocal)
return false;
EObject child = EcoreUtil.create(concreteChildType);
element.eSet(feature, child);
return reverseFeatureRepresentedAsClass(child, progressMonitor);
}
// unsupported queries for references
annotation = feature.getEAnnotation(QUERY_METHOD_NAME);
if (annotation != null)
throw new UnsupportedOperationException();
annotation = feature.getEAnnotation(QUERY_SIGNATURE);
if (annotation != null)
throw new UnsupportedOperationException();
annotation = feature.getEAnnotation(QUERY_FIELD_NAME);
if (annotation != null)
throw new UnsupportedOperationException();
annotation = feature.getEAnnotation(QUERY_PROJECT_NAME);
if (annotation != null)
throw new UnsupportedOperationException();
annotation = feature.getEAnnotation(QUERY_FULLY_QUALIFIED_NAME);
if (annotation != null)
throw new UnsupportedOperationException();
annotation = feature.getEAnnotation(QUERY_CLASS_NAME);
if (annotation != null)
throw new UnsupportedOperationException();
annotation = feature.getEAnnotation(QUERY_QUALIFIER);
if (annotation != null)
throw new UnsupportedOperationException();
annotation = feature.getEAnnotation(QUERY_ARGUMENT_VALUE);
if (annotation != null)
throw new UnsupportedOperationException();
annotation = feature.getEAnnotation(QUERY_FIELD_TYPE);
if (annotation != null)
throw new UnsupportedOperationException();
annotation = feature.getEAnnotation(QUERY_ARGUMENT_NAME);
if (annotation != null)
throw new UnsupportedOperationException();
annotation = feature.getEAnnotation(QUERY_METHOD_CALL);
if (annotation != null)
throw new UnsupportedOperationException();
annotation = feature.getEAnnotation(QUERY_RETURNS_OBJECT_OF_TYPE);
if (annotation != null)
throw new UnsupportedOperationException();
annotation = feature.getEAnnotation(QUERY_TYPES_OF_RETURNED_OBJECTS);
if (annotation != null)
throw new UnsupportedOperationException();
} catch (JavaModelException e) {
e.printStackTrace();
}
return false;
}
@Override
public boolean forwardFeatureRepresentedAsReference(ClassSyncItem classSyncItem, IProgressMonitor progressMonitor) {
EObject element = classSyncItem.getModel() != null ? classSyncItem.getModel() : classSyncItem.getCode();
EReference feature = element.eContainmentFeature();
try {
EAnnotation annotation = feature.getEAnnotation(QUERY_EXTENDS_CLASS);
if (annotation != null)
return new ExtendsClassMapping(classSyncItem, annotation, this, progressMonitor).performForward();
annotation = feature.getEAnnotation(QUERY_IMPLEMENTS_INTERFACE);
if (annotation != null)
return new ImplementsInterfaceMapping(classSyncItem, annotation, this, progressMonitor).performForward();
annotation = feature.getEAnnotation(QUERY_METHODS);
if (annotation != null)
return new MethodsMapping(classSyncItem, annotation, this, progressMonitor).performForward();
annotation = feature.getEAnnotation(QUERY_METHOD_CALLS);
if (annotation != null)
return new MethodCallsMapping(classSyncItem, annotation, this, progressMonitor).performForward();
annotation = feature.getEAnnotation(QUERY_CALLS_RECEIVED);
if (annotation != null)
return new CallsReceivedMapping(classSyncItem, annotation, this, progressMonitor).performForward();
annotation = feature.getEAnnotation(QUERY_ARGUMENT_IS_THIS);
if (annotation != null)
return new ArgumentIsThisMapping(classSyncItem, annotation, this, progressMonitor).performForward();
annotation = feature.getEAnnotation(QUERY_ARGUMENT_IS_FIELD);
if (annotation != null)
return new ArgumentIsFieldMapping(classSyncItem, annotation, this, progressMonitor).performForward();
annotation = feature.getEAnnotation(QUERY_ASSIGNED_WITH_NEW);
if (annotation != null)
return new AssignedWithNewMapping(classSyncItem, annotation, this, progressMonitor).performForward();
annotation = feature.getEAnnotation(QUERY_ARGUMENT);
if (annotation != null)
return new ArgumentMapping(classSyncItem, annotation, this, progressMonitor).performForward();
/*annotation = feature.getEAnnotation("typedWith");
if (annotation != null)
return doTypedWith_forward(classSyncItem, annotation, progressMonitor);
annotation = feature.getEAnnotation("assignedWithNull");
if (annotation != null)
return doNullified_forward(classSyncItem, annotation, progressMonitor);
annotation = feature.getEAnnotation("assignedWithNew");
if (annotation != null)
return doInitializedWithConstructorCall_forward(classSyncItem, annotation, progressMonitor);
*/
} catch (FSMLMappingException e) {
e.printStackTrace();
}
return false;
}
@Override
public boolean canHandleContext(Class contextClass) {
return contextClass != null && (
TypeDeclaration.class.isAssignableFrom(contextClass) ||
MethodDeclaration.class.isAssignableFrom(contextClass) ||
VariableDeclarationFragment.class.isAssignableFrom(contextClass) ||
MethodInvocation.class.isAssignableFrom(contextClass) ||
ClassInstanceCreation.class.isAssignableFrom(contextClass) ||
Annotation.class.isAssignableFrom(contextClass) ||
IJavaProject.class.isAssignableFrom(contextClass)) ||
IType.class.isAssignableFrom(contextClass) ||
IMethod.class.isAssignableFrom(contextClass) ||
IField.class.isAssignableFrom(contextClass);
}
@Override
public boolean canForwardObjectUsingContextMapping(EClass eClass) {
EAnnotation annotation = FSMLEcoreUtil.getEAnnotation(eClass, CONTEXT_CLASS);
if (annotation != null)
return true;
annotation = FSMLEcoreUtil.getEAnnotation(eClass, CONTEXT_METHOD);
if (annotation != null)
return true;
annotation = FSMLEcoreUtil.getEAnnotation(eClass, CONTEXT_FIELD);
if (annotation != null)
return true;
/*annotation = FSMLEcoreUtil.getEAnnotation(eClass, CONTEXT_METHOD_CALL);
if (annotation != null)
return true;*/
// no context annotation, check the containment reference
return false;
}
@Override
public boolean canForwardObjectUsingQueryMapping(EReference eReference) {
EAnnotation annotation = FSMLEcoreUtil.getEAnnotation(eReference, QUERY_EXTENDS_CLASS);
if (annotation != null)
return true;
annotation = FSMLEcoreUtil.getEAnnotation(eReference, QUERY_IMPLEMENTS_INTERFACE);
if (annotation != null)
return true;
annotation = FSMLEcoreUtil.getEAnnotation(eReference, QUERY_METHOD_CALLS);
if (annotation != null)
return true;
annotation = FSMLEcoreUtil.getEAnnotation(eReference, QUERY_CALLS_RECEIVED);
if (annotation != null)
return true;
annotation = FSMLEcoreUtil.getEAnnotation(eReference, QUERY_ARGUMENT_IS_THIS);
if (annotation != null)
return true;
annotation = FSMLEcoreUtil.getEAnnotation(eReference, QUERY_ARGUMENT_IS_FIELD);
if (annotation != null)
return true;
annotation = FSMLEcoreUtil.getEAnnotation(eReference, QUERY_ASSIGNED_WITH_NULL);
if (annotation != null)
return true;
annotation = FSMLEcoreUtil.getEAnnotation(eReference, QUERY_ASSIGNED_WITH_NEW);
if (annotation != null)
return true;
annotation = FSMLEcoreUtil.getEAnnotation(eReference, QUERY_ARGUMENT);
if (annotation != null)
return true;
return false;
}
/**
* @param object
* @param javaElement
* This associates given model element with java element using appropriate feature2* hashmaps.
* Intended to be used by custom FSMLAnnotationInterpreters to set contexts supported by the default interpreter.
*/
public void associateContext(EObject element, Object context) {
contextManager.associateContext(element, context);
}
public void removeContext(EObject element) {
contextManager.removeContext(element);
}
public Object getContext(EObject element) {
return contextManager.getContext(element, new NullProgressMonitor());
}
@Override
public Object getContext(EObject element, Class contextClass, boolean required) {
return contextManager.getContext(element, contextClass, required, new NullProgressMonitor());
}
@Override
public boolean aliasContext(EObject source, EObject target) {
Object context = getContext(source);
if (context != null) {
associateContext(target, context);
return true;
}
return false;
}
// Java utilities
HashMap<String, ReturnStatement> returnsObjectOfTypeCache = new HashMap<String, ReturnStatement>();;
HashMap<String, Boolean> doesNotReturnObjectOfTypeCache = new HashMap<String, Boolean>();
@SuppressWarnings("restriction")
public ReturnStatement returnsObjectOfType(MethodDeclaration methodDeclaration, String fullyQualifiedName, IProgressMonitor progressMonitor) {
IMethod contextMethod = (IMethod) methodDeclaration.resolveBinding().getJavaElement();
// check cache first
String key = contextMethod.getKey() + "<-" + fullyQualifiedName;
Boolean returns = doesNotReturnObjectOfTypeCache.get(key);
if (returns != null)
// has been already checked so just return (it can be null)
return returnsObjectOfTypeCache.get(key);
final String requiredTypeName = fullyQualifiedName;
final ReturnStatement[] result = new ReturnStatement[1];
final SuperMethodInvocation[] superMethodInvocation = new SuperMethodInvocation[1];
final JavaMappingInterpreter jmi = this;
final IProgressMonitor monitor = progressMonitor;
result[0] = null;
superMethodInvocation[0] = null;
methodDeclaration.accept(new ASTVisitor() {
public boolean visit(ReturnStatement node) {
Expression expression = node.getExpression();
if (!(expression instanceof NullLiteral)) {
if (expression instanceof SuperMethodInvocation) {
superMethodInvocation[0] = (SuperMethodInvocation) expression;
}
else {
ITypeBinding typeBinding = expression.resolveTypeBinding();
if (typeBinding == null) {
superMethodInvocation[0] = null;
return true;
}
IType iType = (IType) typeBinding.getJavaElement();
try {
if (iType != null && (iType.getFullyQualifiedName().equals(requiredTypeName) ||
getAnalysisManagers().getTypeHierarchy().implementsOrExtendsType(iType, requiredTypeName)))
result[0] = node;
} catch (JavaModelException e) {
}
}
}
return true;
}
});
if (result[0] != null) {
doesNotReturnObjectOfTypeCache.put(key, false);
returnsObjectOfTypeCache.put(key, result[0]);
Stats.INSTANCE.logMessage("returnsObjectOfType: " + contextMethod.getKey() + " returns: " + fullyQualifiedName);
return result[0];
}
else if (superMethodInvocation[0] != null) {
// analyze super method
IMethodBinding superMethodBinding = superMethodInvocation[0].resolveMethodBinding();
if (superMethodBinding == null)
return null;
IMethod superMethod = (IMethod) superMethodBinding.getJavaElement();
CompilationUnit cu = javaAstManager.getCompilationUnit(superMethod);
MethodDeclaration superMethodDeclaration;
try {
superMethodDeclaration = ASTNodeSearchUtil.getMethodDeclarationNode(superMethod, cu);
return returnsObjectOfType(superMethodDeclaration, fullyQualifiedName, progressMonitor);
} catch (JavaModelException e) {
e.printStackTrace();
}
}
doesNotReturnObjectOfTypeCache.put(key, true);
return null;
}
/**
* annotations cache begin
*/
// iTypes used in extendsClass & implementsInterface annotations
public HashMap<String, IType> iTypes = new HashMap<String, IType>();
// iMethods used in calls method annotations
public HashMap<String, IMethod> iMethods = new HashMap<String, IMethod>();
// the project this interpreter operates on
protected IJavaProject project;
// cache for calls to a given method used by CallsReceivedMapping
public HashMap<IMethod, Collection<SearchMatch>> callsCache = new HashMap<IMethod, Collection<SearchMatch>>();
protected IJavaContextManager contextManager;
protected IJavaASTManager javaAstManager;
protected IJavaImplVariantManager javaImplVariantManager;
protected IHierarchicalCallGraphManager callGraphManager;
// search scope preferences
public boolean hierarchyScope;
public boolean hierarchyUnitsScope;
public boolean callGraphScope;
public boolean projectScope;
public boolean hierarchyScope() {
return JavaMappingInterpreterPlugin.getPlugin().getPreferenceStore().getString(JavaPreferenceConstants.METHOD_CALLS_SEARCH_SCOPE_ID).equals(
JavaPreferenceConstants.HIERARCHY_VALUE);
}
public boolean hierarchyUnitsScope() {
return JavaMappingInterpreterPlugin.getPlugin().getPreferenceStore().getString(JavaPreferenceConstants.METHOD_CALLS_SEARCH_SCOPE_ID).equals(
JavaPreferenceConstants.HIERARCHY_UNITS_VALUE);
}
public boolean callGraphScope() {
return JavaMappingInterpreterPlugin.getPlugin().getPreferenceStore().getString(JavaPreferenceConstants.METHOD_CALLS_SEARCH_SCOPE_ID).equals(
JavaPreferenceConstants.CALL_GRAPH_VALUE);
}
public boolean projectScope() {
return JavaMappingInterpreterPlugin.getPlugin().getPreferenceStore().getString(JavaPreferenceConstants.METHOD_CALLS_SEARCH_SCOPE_ID).equals(
JavaPreferenceConstants.PROJECT_VALUE);
}
public boolean initialize(IProject project, Model model) {
if (setProject(project)) {
getAnalysisManagers().init();
contextManager = this.getAnalysisManagers().getJavaContextManager();
javaAstManager = this.getAnalysisManagers().getJavaASTManager();
javaImplVariantManager = this.getAnalysisManagers().getJavaImplVariantManager();
callGraphManager = this.getAnalysisManagers().getHierarchicalCallGraphManager();
contextManager.associateContext(model, this.project);
try {
cacheJavaModelElementsUsedInAnnotations(model.eClass());
} catch (FSMLMappingException e) {
e.printStackTrace();
return false;
}
// read the preferences
// search scope
hierarchyScope = hierarchyScope();
hierarchyUnitsScope = hierarchyUnitsScope();
callGraphScope = callGraphScope();
projectScope = projectScope();
// Michal: need to configure the call graph manager with the methods found during the metamodel traversal
if (callGraphScope)
callGraphManager.setTargetMethods(iMethods.values());
return true;
}
return false;
}
@Override
public void terminate(IProgressMonitor progressMonitor) {
this.getAnalysisManagers().finish();
}
/**
* @param project
* @return true iff the project is a Java project
*/
public boolean setProject(IProject project) {
if (Queries.hasNature(project, JavaCore.NATURE_ID)) {
this.project = JavaCore.create(project);
Markers.INSTANCE.setProject(project);
return true;
}
this.project = null;
return false;
}
/**
* Traverses the metamodel and stores ITypes and IMethods used in annotations.
* @param metaClass
* @throws FSMLMappingException
*/
private void cacheJavaModelElementsUsedInAnnotations(EClass metaClass) throws FSMLMappingException {
Stats.INSTANCE.logMetamodelAnnotation(metaClass);
for (Object aux : metaClass.getEAllStructuralFeatures()) {
EStructuralFeature feature = (EStructuralFeature) aux;
Stats.INSTANCE.logMetamodelAnnotation(feature);
// iType annotations
EAnnotation annotation = feature.getEAnnotation(QUERY_EXTENDS_CLASS);
if (annotation == null)
annotation = feature.getEAnnotation(QUERY_IMPLEMENTS_INTERFACE);
if (annotation != null) {
String name = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_NAME, true);
try {
IType iType = project.findType(name);
if (iType != null && iType.exists()) {
iTypes.put(FSMLEcoreUtil.computeAnnotationKey(annotation), iType);
//Stats.INSTANCE.printMessage("iTypes: " + iType.getFullyQualifiedName());
}
} catch (JavaModelException e) {
e.printStackTrace();
}
}
// iMethod annotations
annotation = feature.getEAnnotation(JavaMappingInterpreter.QUERY_METHOD_CALLS);
if (annotation == null)
annotation = feature.getEAnnotation(QUERY_CALLS_RECEIVED);
if (annotation == null)
annotation = feature.getEAnnotation(QUERY_ASSIGNED_WITH_NEW);
if (annotation != null) {
String fieldType = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_SUBTYPE_OF, false);
if (fieldType != null)
continue;
String className = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_CLASS, true);
try {
IType iType = project.findType(className);
if (iType != null && iType.exists()) {
// Defaults to the class name, which will search for the constructor
String methodName = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_NAME, Signature.getSimpleName(className));
String signature = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, JavaMappingInterpreter.DETAIL_SIGNATURE, "()V");
String[] parameterTypeSignatures = Signature.getParameterTypes(signature);
IMethod iMethod = iType.getMethod(methodName, parameterTypeSignatures);
if (iMethod != null && !iMethod.exists()) {
// find a similar method directly in iType
for (IMethod auxMethod : iType.getMethods())
if (auxMethod.isSimilar(iMethod)) {
iMethod = auxMethod;
break;
}
}
if (iMethod != null && iMethod.exists()) {
String key = FSMLEcoreUtil.computeAnnotationKey(annotation);
iTypes.put(key, iType);
iMethods.put(key, iMethod);
//Stats.INSTANCE.printMessage("iMethods: " + iMethod.getElementName() + " " + iMethod.getSignature());
}
}
} catch (JavaModelException e) {
e.printStackTrace();
}
}
if (feature instanceof EReference) {
EReference reference = ((EReference)feature);
if (reference.isContainment()) {
EClassifier classifier = reference.getEType();
// TODO: make sure there are no cycles to prevent infinite recursion
if (classifier instanceof EClass && classifier != metaClass) {
for (Object subclass : FSMLEcoreUtil.getSubclassesOfEClass((EClass) classifier, true)) {
cacheJavaModelElementsUsedInAnnotations((EClass) subclass);
}
}
}
}
}
}
public static int ALL_TYPES = 0;
public static int SOURCE_ONLY = 1;
public static int BINARY_ONLY = 2;
/**
* @return true iff feature is present
* @throws FSMLMappingException
*/
public boolean doReturnsObjectOfType_reverse(EObject element, EAttribute feature, EAnnotation annotation, IProgressMonitor progressMonitor) throws JavaModelException, FSMLMappingException {
MethodDeclaration contextMethod = contextManager.getContextMethodDeclaration(element, true, progressMonitor);
if (feature.getEAttributeType().getName().equals("EBoolean")) {
// make sure feature is not there in case the default is true
element.eSet(feature, false);
String featurePath = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_FEATURE_PATH, false);
// navigate to the String feature that holds the fqName of the expected type
FSMLEcoreUtil.NavigationResult target = FSMLEcoreUtil.navigateToEObject(element, featurePath);
if (target.eObject == null) {
Stats.INSTANCE.logError(feature.getName() + " <returnsObjectOfType> cannot find targetElement! " + target.errorMessage);
return false;
}
if (target.eAttribute == null) {
Stats.INSTANCE.logError(feature.getName() + " <returnsObjectOfType> targetFeature is not an attribute! " + target.errorMessage);
return false;
}
if (!(target.eAttribute.getEAttributeType().getName().equals("EString"))) {
Stats.INSTANCE.logError(feature.getName() + " <returnsObjectOfType> targetFeature is not a String!");
return false;
}
String requiredTypeName = (String) target.eObject.eGet(target.eAttribute);
ReturnStatement returnStatement = returnsObjectOfType(contextMethod, requiredTypeName, progressMonitor);
boolean returnsType = returnStatement != null;
element.eSet(feature, new Boolean(returnsType));
if (returnsType) {
JavaMarkerDescriptor markerDescriptor = JavaMarkers.createMarkerDescriptor(contextMethod.resolveBinding().getJavaElement());
markerDescriptor.setAttributes(feature, returnStatement);
markerDescriptor.create(element);
Stats.INSTANCE.logFeatureInstance(element, feature, annotation);
return true;
}
}
return false;
}
/**
* Implements the reverse part of the "returnTypes" mapping.
*
* This mapping is currently implemented only for References. It will search the context class for return types of methods, excluding
* void methods and constructors. For each return type it will create a child with the reference type (or just a single one if the
* feature is not *). For each method it will create a marker in the parent feature.
*
* This mapping can be parameterized with the following annotation details:
* name : the name of the methods to search. Default uses all methods
* signature : the signature of methods to search. Default uses all methods
*
* @return true if the feature is present
*/
public boolean doReturnTypes_reverse(EObject element, EStructuralFeature feature, EAnnotation annotation, EClass concreteChildType, IProgressMonitor progressMonitor) throws JavaModelException, FSMLMappingException {
// References must have a child type
if (feature instanceof EReference && concreteChildType == null)
throw new FSMLMappingException(Cause.MISSING_CONCRETE_CHILD_TYPE, feature);
TypeDeclaration contextClass = contextManager.getContextTypeDeclaration(element, true, progressMonitor);
IJavaProject project = contextManager.getContextIJavaProject(element);
if (feature instanceof EReference) {
// Get the value of some parameters (if they don't exist, ignore and return everything)
String methodName = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_NAME, true);
String methodSignature = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, QUERY_SIGNATURE, "()V");
// Collect the return types
Map<TypeDeclaration, List<MethodDeclaration>> returnTypes = new HashMap<TypeDeclaration, List<MethodDeclaration>>();
for (MethodDeclaration method : contextClass.getMethods()) {
// filter by name
if (methodName != null && ! methodName.equals(method.getName().getIdentifier())) {
continue;
}
// filter by signature
if (methodSignature != null && ! methodSignature.equals(((IMethod)method.resolveBinding().getJavaElement()).getSignature())) {
continue;
}
// filter void types
if ("V".equals(method.resolveBinding().getReturnType().getKey())) {
continue;
}
// add the return type and method to the map/list
IType returnIType = (IType) method.getReturnType2().resolveBinding().getJavaElement();
CompilationUnit cu = javaAstManager.getCompilationUnit(returnIType);
TypeDeclaration returnTypeDeclaration = ASTNodeSearchUtil.getTypeDeclarationNode(returnIType, cu);
if (!returnTypes.containsKey(returnTypeDeclaration)) {
List<MethodDeclaration> methods = new ArrayList<MethodDeclaration>();
returnTypes.put(returnTypeDeclaration, methods);
}
returnTypes.get(returnTypeDeclaration).add(method);
}
for(TypeDeclaration typeDeclaration : returnTypes.keySet()) {
// Create a child for the return type
EObject child = EcoreUtil.create(concreteChildType);
if (feature.isMany()) {
((EList) element.eGet(feature)).add(child);
} else {
element.eSet(feature, child);
}
contextManager.associateContext(child, typeDeclaration);
// Recursively analyze the type
if (!reverseFeatureRepresentedAsClass(child, progressMonitor))
return false;
// Add one marker for each method that returns that type
for(MethodDeclaration method : returnTypes.get(typeDeclaration)) {
IJavaElement iMethod = method.resolveBinding().getJavaElement();
JavaMarkerDescriptor markerDescriptor = JavaMarkers.createMarkerDescriptor(iMethod);
markerDescriptor.setAttributes(feature, method);
// TODO - we are pointing the marker to the "method". We should search the AST for the return type
// node and point the marker to it.
markerDescriptor.setExplanation(typeDeclaration.getName().getFullyQualifiedName());
markerDescriptor.create(element);
}
// If not is many, we just analyzed the first type and now leave
if (! feature.isMany()) {
break;
}
}
return true;
}
return false;
}
/**
* @return true iff feature is present
* @throws FSMLMappingException
*/
public boolean doHasNoAttribute_reverse(EObject element, EAttribute feature, EAnnotation annotation, IProgressMonitor progressMonitor) throws JavaModelException, FSMLMappingException {
Annotation currentAnnotation = contextManager.getContextAnnotation(element, true, progressMonitor);
if (currentAnnotation.getNodeType() == ASTNode.NORMAL_ANNOTATION){
NormalAnnotation na = (NormalAnnotation) currentAnnotation;
if (na.values().isEmpty()){
element.eSet(feature, true);
}
else{
element.eSet(feature, false);
}
return true;
}
element.eSet(feature, currentAnnotation.getNodeType() == ASTNode.MARKER_ANNOTATION);
return true;
}
public IAnalysisManagers getAnalysisManagers() {
if (analysisManagers == null) {
analysisManagers = new AnalysisManagers(project);
}
return analysisManagers;
}
public IType findIType(String fullyQualifiedName) {
try {
return project.findType(fullyQualifiedName);
} catch (JavaModelException e) {
e.printStackTrace();
}
return null;
}
/*
public boolean doMethodCalls_reverse(EObject element, EStructuralFeature feature, EAnnotation annotation, EClass concreteChildType, IProgressMonitor progressMonitor) throws JavaModelException, FSMLMappingException {
if (feature instanceof EReference && concreteChildType == null)
throw new FSMLMappingException(Cause.MISSING_CONCRETE_CHILD_TYPE, feature);
String key = FSMLEcoreUtil.computeAnnotationKey(annotation);
// search for method calls in the context of a method or a class
EObject contextMethodElement = FSMLEcoreUtil.retrieveContextElement(element, CONTEXT_METHOD);
EObject contextClassElement = FSMLEcoreUtil.retrieveContextElement(element, CONTEXT_CLASS);
EObject contextElement = null;
IType contextType = null;
IMethod contextMethod = null;
if (contextMethodElement == null && contextClassElement != null) {
// only class
contextElement = contextClassElement;
contextType =contextManager.getContextIType(contextElement, true);
}
else if (contextMethodElement != null && contextClassElement == null) {
// only method
contextElement = contextMethodElement;
contextMethod = (IMethod) contextManager.getContextIMethod(contextElement, true);
}
else if (contextMethodElement != null && contextClassElement != null) {
// TODO: take the closest one. implement it properly
// for now assume that the method is closer
contextElement = contextMethodElement;
contextMethod = (IMethod) contextManager.getContextIMethod(contextElement, true);
}
if (contextElement != null) {
IType targetType = iTypes.get(key);
IMethod targetMethod = iMethods.get(key);
String scope = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_IN, false);
// default is SOURCE_HIERARCHY for types and NO_HIERARCHY for methods
int hierarchyConstant = contextType != null ? SOURCE_HIERARCHY : NO_HIERARCHY;
if (scope != null) {
if (scope.equals(CONTEXT_CLASS))
hierarchyConstant = NO_HIERARCHY;
}
String receiver = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_RECEIVER, false);
Collection<SearchMatch> result = callsMethod(contextType != null ? contextType : contextMethod, targetType, targetMethod, progressMonitor, hierarchyConstant);
for (SearchMatch match : result) {
IJavaElement iJavaElement = (IJavaElement) match.getElement();
iJavaElement = (IJavaElement) iJavaElement.getPrimaryElement();
CompilationUnit cu =contextManager.getCUforIJavaElement(iJavaElement, false, progressMonitor);
if (cu == null)
continue;
ASTNode astNode = ASTNodeSearchUtil.findNode(match, cu);
// for binary there may not be astNode!
if (astNode != null) {
if (astNode instanceof Name)
astNode = astNode.getParent();
if (astNode instanceof ExpressionStatement)
astNode = ((ExpressionStatement) astNode).getExpression();
if (astNode instanceof MethodDeclaration) {
Stats.INSTANCE.log("Method reference which is a method declaration found. Ignoring");
continue;
}
else if (astNode instanceof MethodRef) {
Stats.INSTANCE.log("Method reference in JavaDoc found. Ignoring");
continue;
}
else if (!(astNode instanceof MethodInvocation) && !(astNode instanceof ClassInstanceCreation)){
//ignore TagElements and MethodRefs
if (!(astNode instanceof TagElement) && !(astNode instanceof MethodRef) && !(astNode instanceof SuperMethodInvocation)) {
Stats.INSTANCE.log("Method reference which is either method invocation nor class instance creation found: " + astNode.getClass() + "\n");
}
}
}
else
Stats.INSTANCE.log(element.eClass().getName() + "::" + feature.getName() +" <callsMethod> ASTNode for match not found: " + match + "\n");
// check if expression is assignable to the required receiver
if (receiver != null) {
Expression expression = null;
if (astNode instanceof MethodInvocation)
expression = ((MethodInvocation) astNode).getExpression();
else if (astNode instanceof ClassInstanceCreation)
expression = ((ClassInstanceCreation) astNode).getExpression();
if (expression != null) {
while (expression instanceof ParenthesizedExpression)
expression = ((ParenthesizedExpression) expression).getExpression();
ITypeBinding typeBinding = expression.resolveTypeBinding();
if (typeBinding == null) {
continue;
}
IType iType = (IType) typeBinding.getJavaElement();
if (!implementsOrExtendsType(iType, receiver, false, progressMonitor))
continue;
else //analyze implementation variant
if (analyzeImplVariants) {
Stats.INSTANCE.log(element.eClass(), feature, annotation,"receiver is a "+expression.getClass().getSimpleName());
}
}
else {
// the receiver is 'this'
// locate the containing method declaration
IType containingType = findITypeContainingASTNode(astNode);
if (!implementsOrExtendsType(containingType, receiver, false, progressMonitor))
continue;
else //analyze implementation variant
if (analyzeImplVariants) {
Stats.INSTANCE.log(element.eClass(), feature, annotation,"receiver is this");
}
}
}
boolean featureOk = false;
// EReference
if (feature instanceof EReference) {
EObject child = EcoreUtil.create(concreteChildType);
if (astNode instanceof MethodInvocation) {
if (feature.isMany())
((EList)element.eGet(feature)).add(child);
else
element.eSet(feature, child);
contextManager.associateContext(child, astNode);
if (reverseFeatureRepresentedAsClass(child, progressMonitor)) {
Stats.INSTANCE.log(element.eClass(), feature, annotation);
if (analyzeImplVariants) {
MethodInvocation methodInvocation = (MethodInvocation) astNode;
//analyze the implementation variants
//find the method name
ASTNode currentNode=astNode;
while (currentNode.getNodeType()!=ASTNode.METHOD_DECLARATION) {
currentNode=currentNode.getParent();
}
List<Expression> args = methodInvocation.arguments();
for (Expression arg:args) {
Stats.INSTANCE.log(element.eClass(), feature, annotation, "Arguments: "+arg.getClass().getSimpleName());
}
String methodName = ((MethodDeclaration)currentNode).getName().toString();
if (hierarchyConstant==NO_HIERARCHY) {
Stats.INSTANCE.log(element.eClass(), feature, annotation, "inMethod: "+methodName+", atLocation: "+getStmtLocationInMethod(astNode));
} else { //we searched beyond the local file
//try to see if we still get the method call if we just search locally
Collection<SearchMatch> localResult =callsMethod(contextType != null ? contextType : contextMethod, targetType, targetMethod, progressMonitor, NO_HIERARCHY);
if (localResult.contains(match)) {
Stats.INSTANCE.log(element.eClass(), feature, annotation, "inMethod: "+methodName+", atLocation: "+getStmtLocationInMethod(astNode));
} else if (contextType != null) {
Stats.INSTANCE.log(element.eClass(), feature, annotation, "inheritsFrom: "+contextType.getSuperclassName());
}
}
}
featureOk = true;
}
// no need to create the marker, because the child is a method call context
}
else if (astNode instanceof ClassInstanceCreation) {
if (feature.isMany())
((EList)element.eGet(feature)).add(child);
else
element.eSet(feature, child);
ClassInstanceCreation classInstanceCreation = (ClassInstanceCreation) astNode;
contextManager.associateContext(child, classInstanceCreation);
if (reverseFeatureRepresentedAsClass(child, progressMonitor)) {
Stats.INSTANCE.log(element.eClass(), feature, annotation);
featureOk = true;
}
// no need to create the marker, because the child is a method call context
}
}
else {
if (feature.isMany())
((EList)element.eGet(feature)).add(true);
else
element.eSet(feature, true);
Stats.INSTANCE.log(element.eClass(), feature, annotation);
JavaMarkerDescriptor markerDescriptor = JavaMarkers.createMarkerDescriptor((IJavaElement) match.getElement());
markerDescriptor.setAttributes(feature, element.eClass().getName() + "::" + feature.getName(), match);
markerDescriptor.create(element);
}
// break iteration if a correct value has been set
if (!feature.isMany() && featureOk)
break;
}
}
if (feature.isMany()) {
if (!((EList)element.eGet(feature)).isEmpty())
return true;
}
else {
if (element.eGet(feature) != null)
return true;
}
return false;
}
*/
/*
public boolean doMethodCalls_forward(SyncItem syncItem, EAnnotation annotation, IProgressMonitor progressMonitor) throws JavaModelException, FSMLMappingException {
String detailName = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_NAME, true);
String detailLocationName = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, JavaMapping.DETAIL_LOCATION_NAME, true);
String detailLocationSig = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, JavaMapping.DETAIL_LOCATION_SIG, "()V");
String detailPosition = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_POSITION, false);
IMethod targetMethod = iMethods.get(FSMLEcoreUtil.computeAnnotationKey(annotation));
String[] parameterTypes = targetMethod.getParameterTypes();
// construct a call
String contents = detailName + CodeTransforms.constructDefaultCallParameters(parameterTypes) + ";";
int position = 0;
if (detailPosition == null || detailPosition.equals("before"))
position = CodeTransforms.BEFORE_ADVICE;
else if (detailPosition.equals("after"))
position = CodeTransforms.AFTER_ADVICE;
else
throw new FSMLMappingException(Cause.INCORRECT_VALUE, "for detail " + DETAIL_POSITION);
List<ASTNode> result = null;
// method calls can be create in the context method or a context class
EObject contextMethodElement = FSMLEcoreUtil.retrieveContextElement(syncItem, CONTEXT_METHOD);
if (contextMethodElement != null) {
MethodDeclaration methodDeclaration = contextManager.getContextMethodDeclaration(contextMethodElement, true, progressMonitor);
result = CodeTransforms.weaveAdvice(position, null, methodDeclaration, contents, progressMonitor);
}
// no context method, try context class
EObject contextClassElement = FSMLEcoreUtil.retrieveContextElement(syncItem, CONTEXT_CLASS);
if (contextClassElement != null) {
TypeDeclaration contextClass = contextManager.getContextTypeDeclaration(contextClassElement, true, progressMonitor);
MethodDeclaration methodDeclaration = findMethod(detailLocationName, detailLocationSig, contextClass, true, false, progressMonitor);
if (methodDeclaration == null)
// create the method
methodDeclaration = CodeTransforms.createMethod(project, null, contextClass, "public", detailLocationName, detailLocationSig, null, progressMonitor);
result = CodeTransforms.weaveAdvice(position, null, methodDeclaration, contents, progressMonitor);
}
// need to set up the call as a context and put the markers
if (result != null && !result.isEmpty()) {
// should be a single method call. However, in the future, different variants may
// require some preparation statements, e.g., variable declarations, and the call will
// the the last one
ASTNode astNode = result.get(result.size()-1);
if (astNode instanceof ExpressionStatement)
astNode = ((ExpressionStatement) astNode).getExpression();
if (astNode instanceof MethodInvocation) {
EObject element = FSMLEcoreUtil.retrieveContextElement(syncItem, CONTEXT_METHOD_CALL);
contextManager.associateContext(element, astNode);
}
}
return result != null;
}*/
/*
public boolean doExtendsClass_reverse(EObject element, EStructuralFeature feature, EAnnotation annotation, EClass concreteChildType, IProgressMonitor progressMonitor) throws JavaModelException, FSMLMappingException {
if (feature instanceof EReference && concreteChildType == null)
throw new FSMLMappingException(Cause.MISSING_CONCRETE_CHILD_TYPE, feature);
IType contextIType = contextManager.getContextIType(element, true);
if (contextIType == null || !contextIType.exists())
return false;
String requiredSuperTypeName = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_NAME, true);
if (implementsOrExtendsType(contextIType, requiredSuperTypeName, false, progressMonitor)) {
if (feature instanceof EAttribute)
element.eSet(feature, true);
else {
EObject child = EcoreUtil.create(concreteChildType);
element.eSet(feature, child);
if (!reverseFeatureRepresentedAsClass(child, progressMonitor))
return false;
}
Stats.INSTANCE.log(element.eClass(), feature, annotation);
if (analyzeImplVariants) {
//analyze implementation variants
String contextClassTypeSuperClass = contextIType.getSuperclassName();
if (contextClassTypeSuperClass.equals(requiredSuperTypeName)) {
Stats.INSTANCE.log(element.eClass(), feature, annotation,"directly");
} else {
Stats.INSTANCE.log(element.eClass(), feature, annotation,"indirectly: "+contextClassTypeSuperClass);
}
}
CompilationUnit cu = contextManager.getCUforIJavaElement(contextIType, false, progressMonitor);
if (cu == null)
return false;
TypeDeclaration typeDeclaration = ASTNodeSearchUtil.getTypeDeclarationNode(contextIType, cu);
if (typeDeclaration != null) {
Type superClassType = typeDeclaration.getSuperclassType();
if (superClassType != null) {
JavaMarkerDescriptor markerDescriptor = JavaMarkers.createMarkerDescriptor(contextIType);
markerDescriptor.setAttributes(feature, element.eClass().getName() + "::" + feature.getName(), superClassType);
markerDescriptor.create(element);
}
else
Stats.INSTANCE.log(element.eClass(), feature, "doExtendsClass_reverse: Cannot retrieve SuperType AST node & set the marker.");
}
else
Stats.INSTANCE.log(element.eClass(), feature, " doExtendsClass_reverse: Cannot retrieve TypeDeclaration AST node & set the marker.");
return true;
}
return false;
}*/
/*
public boolean doExtendsClass_forward(SyncItem syncItem, EAnnotation annotation, IProgressMonitor progressMonitor) throws JavaModelException, FSMLMappingException {
EObject contextClassElement = FSMLEcoreUtil.retrieveContextElement(syncItem, CONTEXT_CLASS);
TypeDeclaration contextClassDeclaration = contextManager.getContextTypeDeclaration(contextClassElement, true, progressMonitor);
if (contextClassDeclaration == null)
return false;
String requiredSuperType = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_NAME, true);
switch (syncItem.getReconciliationAction()) {
case CODE_ADD:
CodeTransforms.addExtendsDeclaration(null, contextClassDeclaration, requiredSuperType, progressMonitor);
break;
case CODE_REMOVE:
CodeTransforms.removeExtendsDeclaration(null, contextClassDeclaration, requiredSuperType, progressMonitor);
break;
}
return true;
}*/
/*
public boolean doCallsReceived_reverse(EObject element, EStructuralFeature feature, EAnnotation annotation, EClass concreteChildType, IProgressMonitor progressMonitor) throws JavaModelException, FSMLMappingException {
if (feature instanceof EReference && concreteChildType == null)
throw new FSMLMappingException(Cause.MISSING_CONCRETE_CHILD_TYPE, feature);
String key = FSMLEcoreUtil.computeAnnotationKey(annotation);
EObject aux = FSMLEcoreUtil.retrieveContextElement(element, CONTEXT_CLASS);
if (aux != null) {
IType contextType =contextManager.getContextIType(element, true);
String receiver = contextType.getFullyQualifiedName();
IMethod targetMethod = iMethods.get(key);
// check cache first
Collection<SearchMatch> result = callsCache.get(targetMethod);
if (result == null) {
result = callsMethod(targetMethod, progressMonitor, PROJECT);
callsCache.put(targetMethod, result);
}
for (SearchMatch match : result) {
// remove calls which are not received by the contextType
CompilationUnit cu =contextManager.getCUforIJavaElement(((IJavaElement) match.getElement()).getPrimaryElement(), false, progressMonitor);
if (cu == null)
continue;
ASTNode astNode = ASTNodeSearchUtil.findNode(match, cu);
// for binary there may not be astNode!
if (astNode != null) {
if (astNode instanceof Name)
astNode = astNode.getParent();
if (astNode instanceof ExpressionStatement)
astNode = ((ExpressionStatement) astNode).getExpression();
if (astNode instanceof MethodDeclaration) {
Stats.INSTANCE.log("Method reference which is a method declaration found. Ignoring");
continue;
}
else if (astNode instanceof MethodRef) {
Stats.INSTANCE.log("Method reference in JavaDoc found. Ignoring");
continue;
}
else {
//ignore TagElements and MethodRefs
if (!(astNode instanceof TagElement) && !(astNode instanceof MethodRef) && !(astNode instanceof SuperMethodInvocation))
Stats.INSTANCE.log("Method reference which is either method invocation nor class instance creation found: " + astNode.getClass() + "\n");
}
}
else
Stats.INSTANCE.log(element.eClass().getName() + "::" + feature.getName() +" <callsMethod> ASTNode for match not found: " + match + "\n");
// check if expression is assignable to the required receiver
IType auxType = null;
if (receiver != null) {
Expression expression = null;
if (astNode instanceof MethodInvocation)
expression = ((MethodInvocation) astNode).getExpression();
else if (astNode instanceof ClassInstanceCreation)
expression = ((ClassInstanceCreation) astNode).getExpression();
if (expression != null) {
ITypeBinding typeBinding = expression.resolveTypeBinding();
auxType = (IType) typeBinding.getJavaElement();
if (!implementsOrExtendsType(auxType, receiver, false, progressMonitor))
continue;
}
else {
// the receiver is 'this'
// locate the containing method declaration
auxType = findITypeContainingASTNode(astNode);
if (!implementsOrExtendsType(auxType, receiver, false, progressMonitor))
continue;
}
}
boolean featureOk = false;
// EReference
if (feature instanceof EReference) {
EObject child = EcoreUtil.create(concreteChildType);
if (astNode instanceof MethodInvocation) {
if (feature.isMany())
((EList)element.eGet(feature)).add(child);
else
element.eSet(feature, child);
MethodInvocation methodInvocation = (MethodInvocation) astNode;
contextManager.associateContext(child, methodInvocation);
if (reverseFeatureRepresentedAsClass(child, progressMonitor)) {
Stats.INSTANCE.log(element.eClass(), feature, annotation);
featureOk = true;
}
// no need to create the marker, because the child is a method call context
}
else if (astNode instanceof ClassInstanceCreation) {
if (feature.isMany())
((EList)element.eGet(feature)).add(child);
else
element.eSet(feature, child);
ClassInstanceCreation classInstanceCreation = (ClassInstanceCreation) astNode;
contextManager.associateContext(child, classInstanceCreation);
if (reverseFeatureRepresentedAsClass(child, progressMonitor))
Stats.INSTANCE.log(element.eClass(), feature, annotation);
// no need to create the marker, because the child is a method call context
}
}
// EAttribute
else {
if (feature.isMany())
((EList)element.eGet(feature)).add(true);
else
element.eSet(feature, true);
Stats.INSTANCE.log(element.eClass(), feature, annotation);
JavaMarkerDescriptor markerDescriptor = JavaMarkers.createMarkerDescriptor(auxType);
markerDescriptor.setAttributes(feature, element.eClass().getName() + "::" + feature.getName(), match);
markerDescriptor.create(element);
}
// break iteration if a correct value has been set
if (!feature.isMany() && featureOk)
break;
}
}
if (feature.isMany()) {
if (!((EList)element.eGet(feature)).isEmpty())
return true;
}
else {
if (element.eGet(feature) != null)
return true;
}
return false;
} */
/*public boolean doCallsReceived_forward(SyncItem syncItem, EAnnotation annotation, IProgressMonitor progressMonitor) throws JavaModelException, FSMLMappingException {
String detailName = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_NAME, true);
String detailLocationName = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, JavaMappingInterpreter.DETAIL_LOCATION_NAME, false);
String detailLocationSig = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, JavaMappingInterpreter.DETAIL_LOCATION_SIG, "()V");
String detailPosition = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_POSITION, false);
IMethod targetMethod = iMethods.get(FSMLEcoreUtil.computeAnnotationKey(annotation));
String[] parameterTypes = targetMethod.getParameterTypes();
// construct a call
String contents = detailName + CodeTransforms.constructDefaultCallParameters(parameterTypes) + ";";
int position = 0;
if (detailPosition == null || detailPosition.equals("before"))
position = CodeTransforms.BEFORE_ADVICE;
else if (detailPosition.equals("after"))
position = CodeTransforms.AFTER_ADVICE;
else
throw new FSMLMappingException(Cause.INCORRECT_VALUE, "for detail " + DETAIL_POSITION);
List<ASTNode> result = null;
// method calls can be create in the context method or a context class
EObject contextMethodElement = FSMLEcoreUtil.retrieveContextElement(syncItem, CONTEXT_METHOD);
if (contextMethodElement != null) {
MethodDeclaration contextMethod = contextManager.getContextMethodDeclaration(contextMethodElement, true, progressMonitor);
result = CodeTransforms.weaveAdvice(position, null, contextMethod, contents, progressMonitor);
}
else {
// no context method, try context class
EObject contextClassElement = FSMLEcoreUtil.retrieveContextElement(syncItem, CONTEXT_CLASS);
if (contextClassElement != null) {
TypeDeclaration contextClass = contextManager.getContextTypeDeclaration(contextClassElement, true, progressMonitor);
MethodDeclaration methodDeclaration = findMethod(detailLocationName, detailLocationSig, contextClass, true, false, progressMonitor);
if (methodDeclaration == null)
// create the method
methodDeclaration = CodeTransforms.createMethod(project, null, contextClass, "public", detailLocationName, detailLocationSig, null, progressMonitor);
result = CodeTransforms.weaveAdvice(position, null, methodDeclaration, contents, progressMonitor);
}
}
// need to set up the call as a context and put the markers
if (result != null && !result.isEmpty()) {
// should be a single method call. However, in the future, different variants may
// require some preparation statements, e.g., variable declarations, and the call will
// the the last one
ASTNode astNode = result.get(result.size()-1);
if (astNode instanceof ExpressionStatement)
astNode = ((ExpressionStatement) astNode).getExpression();
if (astNode instanceof MethodInvocation) {
EObject element = FSMLEcoreUtil.retrieveContextElement(syncItem, CONTEXT_METHOD_CALL);
contextManager.associateContext(element, astNode);
}
}
return result != null;
}*/
/*
public boolean doMethods_reverse(EObject element, EStructuralFeature feature, EAnnotation annotation, EClass concreteChildType, IProgressMonitor progressMonitor) throws JavaModelException, FSMLMappingException {
if (feature instanceof EReference && concreteChildType == null)
throw new FSMLMappingException(Cause.MISSING_CONCRETE_CHILD_TYPE, feature);
IType contextIType = contextManager.getContextIType(element, true);
if (contextIType == null || !contextIType.exists())
return false;
if (feature.getEType().getName().equals("EString")) {
// expect <signature> parameter
String methodSignature = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, JavaMappingInterpreter.DETAIL_SIGNATURE, "()V");
ArrayList<MarkerDescriptor> markerDescriptors = new ArrayList<MarkerDescriptor>();
boolean found = false;
for (IMethod iMethod : contextIType.getMethods()) {
if (iMethod.getSignature().equals(methodSignature)) {
Stats.INSTANCE.log(element.eClass(), feature, annotation);
if (analyzeImplVariants) {
//still need to analyze implementation variants here?
Stats.INSTANCE.log(element.eClass(), feature, annotation,"no variants...");
}
found = true;
String methodName = iMethod.getElementName();
if (feature.isMany()) {
((EList)element.eGet(feature)).add(methodName);
JavaMarkerDescriptor markerDescriptor = JavaMarkers.createMarkerDescriptor(iMethod);
markerDescriptor.setAttributes(feature, element.eClass().getName() + "::" + feature.getName() + "(" + methodName + ")", iMethod);
markerDescriptor.setElementAndValue(element, methodName);
markerDescriptors.add(markerDescriptor);
}
else {
element.eSet(feature, methodName);
JavaMarkerDescriptor markerDescriptor = JavaMarkers.createMarkerDescriptor(iMethod);
markerDescriptor.setAttributes(feature, element.eClass().getName() + "::" + feature.getName(), iMethod);
markerDescriptor.setElement(element);
markerDescriptors.add(markerDescriptor);
// ignore the rest of results!
break;
}
}
}
for (MarkerDescriptor descriptor : markerDescriptors)
descriptor.create();
return found;
}
else if (feature.getEType().getName().equals("EBoolean") || feature instanceof EReference) {
// expect <name, signature> parameters
String methodName = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_NAME, true);
String methodSignature = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, JavaMappingInterpreter.DETAIL_SIGNATURE, "()V");
String inherited = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_INHERITED, false);
if (!feature.isMany()) {
boolean includeInherited = inherited != null && inherited.equals("true");
// if there is no name for the method, search for a constructor, using the name of the context class.
if (methodName == null) {
methodName = contextIType.getElementName();
}
IMethod method = findMethod(methodName, methodSignature, contextIType, true, includeInherited, progressMonitor);
if (method != null && method.exists()) {
if (feature instanceof EAttribute)
element.eSet(feature, new Boolean(true));
else {
EObject child = EcoreUtil.create(concreteChildType);
element.eSet(feature, child);
CompilationUnit cu =contextManager.getCUforIJavaElement(method, false, progressMonitor);
MethodDeclaration methodDeclaration = (MethodDeclaration) cu.findDeclaringNode(method.getKey());
if (methodDeclaration == null)
return false;
contextManager.associateContext(child, methodDeclaration);
if (!reverseFeatureRepresentedAsClass(child, progressMonitor))
return false;
}
Stats.INSTANCE.log(element.eClass(), feature, annotation);
if (analyzeImplVariants) {
//analyze implementation variants
if (!includeInherited) {
Stats.INSTANCE.log(element.eClass(), feature, annotation,"implements (as required)");
} else {
IMethod localMethod = findMethod(methodName, methodSignature, contextIType, true, false, progressMonitor);
if (localMethod==null) {
Stats.INSTANCE.log(element.eClass(), feature, annotation,"inheritsFrom: "+contextIType.getSuperclassName());
} else {
//check if the method is in the super classes
IMethod ancestorMethods = findMethod(methodName, methodSignature, contextIType, false, true, progressMonitor);
if (ancestorMethods==null) {
Stats.INSTANCE.log(element.eClass(), feature, annotation,"implements");
} else {
Stats.INSTANCE.log(element.eClass(), feature, annotation,"overrides");
}
}
}
}
JavaMarkerDescriptor markerDescriptor = JavaMarkers.createMarkerDescriptor(method);
markerDescriptor.setAttributes(feature, element.eClass().getName() + "::" + feature.getName(), method);
markerDescriptor.create(element);
return true;
}
}
}
return false;
}
*/
/*
public boolean doMethods_forward(SyncItem syncItem, EAnnotation annotation, IProgressMonitor progressMonitor) throws JavaModelException, FSMLMappingException {
// contains the feature
EObject element = syncItem.getCode() != null ? syncItem.getCode() : syncItem.getModel();
// structural feature of an element
EStructuralFeature feature = null;
if (syncItem instanceof ClassSyncItem) {
// forwarding a containment reference
ClassSyncItem classSyncItem = (ClassSyncItem) syncItem;
feature = element.eContainmentFeature();
}
else if (syncItem instanceof StructuralFeatureSyncItem){
// forwarding an attribute
StructuralFeatureSyncItem featureSyncItem = (StructuralFeatureSyncItem) syncItem;
feature = featureSyncItem.getStructuralFeature();
ClassSyncItem classSyncItem = (ClassSyncItem) featureSyncItem.eContainer();
}
TypeDeclaration contextClass = contextManager.getContextTypeDeclaration(FSMLEcoreUtil.retrieveContextElement(syncItem, CONTEXT_CLASS), true, progressMonitor);
String methodName = null;
String methodSignature = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, JavaMappingInterpreter.DETAIL_SIGNATURE, "()V");
// Michal: the parameter does not have any effect. We create local methods only.
//String inherited = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_INHERITED);
if (feature.getEType().getName().equals("EString"))
methodName = (String) element.eGet(feature);
else if (feature.getEType().getName().equals("EBoolean") || feature instanceof EReference)
methodName = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_NAME, true);
// if there is no name for the method, create a constructor, using the name of the context class.
if (methodName == null)
methodName = contextClass.getName().getIdentifier();
// create the method
boolean result = false;
MethodDeclaration methodDeclaration;
switch (syncItem.getReconciliationAction()) {
case CODE_ADD:
methodDeclaration = CodeTransforms.createMethod(project, null, contextClass, "public", methodName, methodSignature, null, progressMonitor);
contextManager.associateContext(element, methodDeclaration);
result = true;
break;
case CODE_REMOVE:
methodDeclaration = contextManager.getContextMethodDeclaration(element, true, progressMonitor);
if (methodDeclaration != null)
CodeTransforms.commentOutASTNode(null, methodDeclaration, element.eClass(), feature, progressMonitor);
break;
}
// TODO: markers
return result;
}*/
/*
public boolean doImplementsInterface_reverse(EObject element, EStructuralFeature feature, EAnnotation annotation, EClass concreteChildType, IProgressMonitor progressMonitor) throws JavaModelException, FSMLMappingException {
if (feature instanceof EReference && concreteChildType == null)
throw new FSMLMappingException(Cause.MISSING_CONCRETE_CHILD_TYPE, feature);
IType iType = contextManager.getContextIType(element, true);
if (iType == null)
return false;
String requiredSuperType = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_NAME, true);
if (implementsOrExtendsType(iType, requiredSuperType, false, progressMonitor)) {
if (feature instanceof EAttribute)
element.eSet(feature, true);
else {
EObject child = EcoreUtil.create(concreteChildType);
element.eSet(feature, child);
if (!reverseFeatureRepresentedAsClass(child, progressMonitor))
return false;
}
Stats.INSTANCE.log(element.eClass(), feature, annotation);
if (analyzeImplVariants) {
//analyze implementation variants
String[] implementedInterfaces=iType.getSuperInterfaceNames();
boolean foundInterface = false;
for (String implementedInterface: implementedInterfaces) {
if (implementedInterface.equals(requiredSuperType)) {
foundInterface = true;
Stats.INSTANCE.log(element.eClass(), feature, annotation,"directly");
}
}
if (!foundInterface) {
Stats.INSTANCE.log(element.eClass(), feature, annotation,"indirectly: "+iType.getSuperclassName());
}
}
TypeDeclaration typeDeclaration = contextManager.getContextTypeDeclaration(element, true, progressMonitor);
if (typeDeclaration == null)
return false;
for (Object auxSuperType : typeDeclaration.superInterfaceTypes()) {
Type superInterface = (Type) auxSuperType;
ITypeBinding binding = superInterface.resolveBinding();
if (binding != null && binding.getQualifiedName().equals(requiredSuperType)) {
JavaMarkerDescriptor markerDescriptor = JavaMarkers.createMarkerDescriptor(iType);
markerDescriptor.setAttributes(feature, element.eClass().getName() + "::" + feature.getName(), superInterface);
markerDescriptor.create(element);
break;
}
}
return true;
}
return false;
}
*/
/* public boolean doImplementsInterface_forward(SyncItem syncItem, EAnnotation annotation, IProgressMonitor progressMonitor) throws JavaModelException, FSMLMappingException {
RA action = syncItem.getReconciliationAction();
TypeDeclaration contextClass = contextManager.getContextTypeDeclaration(FSMLEcoreUtil.retrieveContextElement(syncItem, CONTEXT_CLASS), true, progressMonitor);
String requiredSuperType = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_NAME, true);
switch (action) {
case CODE_ADD:
CodeTransforms.addInterfaceDeclaration(null, contextClass, requiredSuperType, progressMonitor);
break;
case CODE_REMOVE:
CodeTransforms.removeInterfaceDeclaration(null, contextClass, requiredSuperType, progressMonitor);
break;
}
return true;
}*/
/*
public boolean doArgumentIsField_reverse(EObject element, EStructuralFeature feature, EAnnotation annotation, EClass concreteChildType, IProgressMonitor progressMonitor) throws JavaModelException, FSMLMappingException {
if (feature instanceof EReference && concreteChildType == null)
throw new FSMLMappingException(Cause.MISSING_CONCRETE_CHILD_TYPE, feature);
// could be a method invocation or class instance creation
MethodInvocation methodInvocation = contextManager.getContextMethodInvocation(element, true, progressMonitor);
ClassInstanceCreation classInstanceCreation = contextManager.getContextClassInstanceCreation(element, true, progressMonitor);
// exactly one of them must be non-null
if((methodInvocation == null && classInstanceCreation == null) ||
(methodInvocation != null && classInstanceCreation != null))
throw new FSMLMappingException(Cause.MISSING_CONTEXT, feature);
String indexString = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_INDEX, true);
int index = Integer.valueOf(indexString) - 1;
ASTNode argument = null;
if (methodInvocation != null)
argument = (ASTNode) methodInvocation.arguments().get(index);
if (classInstanceCreation != null)
argument = (ASTNode) classInstanceCreation.arguments().get(index);
if (argument instanceof SimpleName) {
SimpleName simpleName = (SimpleName) argument;
IBinding binding = simpleName.resolveBinding();
if (binding.getKind() == IBinding.VARIABLE) {
IVariableBinding variableBinding = (IVariableBinding) binding;
if (variableBinding.isField()) {
Stats.INSTANCE.log(element.eClass().getName() + "::" + feature.getName() + " <argumentIsField> argument is a field");
if (feature instanceof EAttribute)
element.eSet(feature, true);
else {
EObject child = EcoreUtil.create(concreteChildType);
element.eSet(feature, child);
// check the sameAs constraint
String sameAs = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_SAME_AS, false);
if (sameAs != null && !sameAs.isEmpty()) {
NavigationResult navigationResult = FSMLEcoreUtil.navigateToEObject(element, sameAs);
VariableDeclarationFragment targetField = contextManager.getContextVariableDeclarationFragment(navigationResult.eObject, true, progressMonitor);
if (targetField == null || !targetField.resolveBinding().getKey().equals(variableBinding.getKey())) {
element.eUnset(feature);
return false;
}
}
IField field = (IField) variableBinding.getJavaElement();
CompilationUnit cu =contextManager.getCUforIJavaElement(field, false, progressMonitor);
VariableDeclarationFragment fieldDeclarationFragment = ASTNodeSearchUtil.getFieldDeclarationFragmentNode(field, cu);
if (fieldDeclarationFragment != null)
contextManager.associateContext(child, fieldDeclarationFragment);
if (!reverseFeatureRepresentedAsClass(child, progressMonitor))
return false;
}
Stats.INSTANCE.log(element.eClass(), feature, annotation);
IType iTypeOfArgument = findITypeContainingASTNode(argument);
if (iTypeOfArgument == null)
iTypeOfArgument = (IType) contextManager.getContextIType(element, true);
JavaMarkerDescriptor markerDescriptor = JavaMarkers.createMarkerDescriptor(iTypeOfArgument);
markerDescriptor.setAttributes(feature, element.eClass().getName() + "::" + feature.getName(), argument);
markerDescriptor.create(element);
return true;
}
}
}
return false;
}
public boolean doArgumentIsField_forward(SyncItem syncItem, EAnnotation annotation, IProgressMonitor progressMonitor) throws JavaModelException, FSMLMappingException {
String detailIndex = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_INDEX, true);
int index = 0;
if (detailIndex != null && !detailIndex.isEmpty()) {
try {
index = Integer.parseInt(detailIndex);
}
catch (NumberFormatException e) {
throw new FSMLMappingException(Cause.INCORRECT_VALUE, " of detail " + DETAIL_INDEX);
}
}
EObject element = syncItem.getModel();
MethodInvocation contextMethodInvocation = contextManager.getContextMethodInvocation(element, true, progressMonitor);
ClassInstanceCreation classInstanceCreation = contextManager.getContextClassInstanceCreation(element, true, progressMonitor);
String fieldName = null;
// field name comes from either
// 1) an attribute annotated with QUERY_FIELD_NAME or
// 2) from other feature annotated with CONTEXT_FIELD pointed to by DETAIL_SAME_AS parameter
EObject contextFieldElement = element;
String detailSameAs = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_SAME_AS, false);
if (detailSameAs != null) {
NavigationResult target = FSMLEcoreUtil.navigateToEObject(element, detailSameAs);
contextFieldElement = target.eObject;
if (target == null || target.eObject == null)
throw new FSMLMappingException(Cause.INCORRECT_VALUE, detailSameAs + " of " + DETAIL_SAME_AS);
}
// the field name is the value of the attribute annotated with QUERY_FIELD_NAME
EAnnotation contextFieldAnnotation = FSMLEcoreUtil.getEAnnotation(contextFieldElement.eClass(), CONTEXT_FIELD);
if (contextFieldAnnotation != null) {
// find an attribute annotated with QUERY_FIELD_NAME
EStructuralFeature fieldNameFeature = FSMLEcoreUtil.findEStructuralFeatureWithAnnotations(contextFieldElement.eClass(), new String[] { QUERY_FIELD_NAME });
if (fieldNameFeature == null)
throw new FSMLMappingException(Cause.MISSING_ATTRIBUTE, QUERY_FIELD_NAME);
if (fieldNameFeature instanceof EAttribute)
fieldName = (String) contextFieldElement.eGet(fieldNameFeature);
else
throw new FSMLMappingException(Cause.MAPPING_REQUIRES_ATTRIBUTE, fieldNameFeature);
}
else
throw new FSMLMappingException(Cause.REQUIRED_CONTEXT_MISSING, CONTEXT_FIELD);
switch (syncItem.getReconciliationAction()) {
case CODE_ADD:
if (contextMethodInvocation != null) {
Expression expression = CodeTransforms.replaceMethodCallArgument(null, contextMethodInvocation, index, fieldName, progressMonitor);
return expression != null;
}
if (classInstanceCreation != null) {
Expression expression = CodeTransforms.replaceMethodCallArgument(null, classInstanceCreation, index, fieldName, progressMonitor);
return expression != null;
}
case CODE_REMOVE:
if (contextMethodInvocation != null)
return CodeTransforms.replaceMethodCallArgument(null, contextMethodInvocation, index, "null", progressMonitor) != null;
if (classInstanceCreation != null)
return CodeTransforms.replaceMethodCallArgument(null, classInstanceCreation, index, "null", progressMonitor) != null;
}
return false;
}
*/
/*
public boolean doArgumentIsThis_reverse(EObject element, EStructuralFeature feature, EAnnotation annotation, EClass concreteChildType, IProgressMonitor progressMonitor) throws JavaModelException, FSMLMappingException {
if (feature instanceof EReference && concreteChildType == null)
throw new FSMLMappingException(Cause.MISSING_CONCRETE_CHILD_TYPE, feature);
// could be a method invocation or class instance creation
MethodInvocation methodInvocation = contextManager.getContextMethodInvocation(element, true, progressMonitor);
ClassInstanceCreation classInstanceCreation = contextManager.getContextClassInstanceCreation(element, true, progressMonitor);
// exactly one of them must be non-null
if ((methodInvocation == null && classInstanceCreation == null) ||
(methodInvocation != null && classInstanceCreation != null))
return false;
String indexString = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_INDEX, true);
int index = Integer.valueOf(indexString) - 1;
ASTNode argument = null;
if (methodInvocation != null)
argument = (ASTNode) methodInvocation.arguments().get(index);
if (classInstanceCreation != null)
argument = (ASTNode) classInstanceCreation.arguments().get(index);
if (argument instanceof ThisExpression)
Stats.INSTANCE.log(element.eClass().getName() + "::" + feature.getName() + " <argumentIsThis> argument is this expression");
else
return false;
if (feature instanceof EAttribute)
element.eSet(feature, true);
else {
EObject child = EcoreUtil.create(concreteChildType);
element.eSet(feature, child);
if (!reverseFeatureRepresentedAsClass(child, progressMonitor))
return false;
}
Stats.INSTANCE.log(element.eClass(), feature, annotation);
IType iTypeOfArgument = findITypeContainingASTNode(argument);
if (iTypeOfArgument == null)
iTypeOfArgument = (IType) contextManager.getContextIType(element, true);
JavaMarkerDescriptor markerDescriptor = JavaMarkers.createMarkerDescriptor(iTypeOfArgument);
markerDescriptor.setAttributes(feature, element.eClass().getName() + "::" + feature.getName(), argument);
markerDescriptor.create(element);
return true;
}
public boolean doArgumentIsThis_forward(SyncItem syncItem, EAnnotation annotation, IProgressMonitor progressMonitor) throws FSMLMappingException {
String detailIndex = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_INDEX, true);
int index = 0;
if (detailIndex != null && !detailIndex.isEmpty()) {
try {
index = Integer.parseInt(detailIndex);
}
catch (NumberFormatException e) {
throw new FSMLMappingException(Cause.INCORRECT_VALUE, " of detail " + DETAIL_INDEX);
}
}
EObject contextMethodInvocationElement = FSMLEcoreUtil.retrieveContextElement(syncItem, CONTEXT_METHOD_CALL);
MethodInvocation contextMethodInvocation = contextManager.getContextMethodInvocation(contextMethodInvocationElement, true, progressMonitor);
ClassInstanceCreation classInstanceCreation = contextManager.getContextClassInstanceCreation(contextMethodInvocationElement, true, progressMonitor);
switch (syncItem.getReconciliationAction()) {
case CODE_ADD:
if (contextMethodInvocation != null)
return CodeTransforms.replaceMethodCallArgument(null, contextMethodInvocation, index, "this", progressMonitor) != null;
if (classInstanceCreation != null)
return CodeTransforms.replaceMethodCallArgument(null, classInstanceCreation, index, "this", progressMonitor) != null;
case CODE_REMOVE:
if (contextMethodInvocation != null)
return CodeTransforms.replaceMethodCallArgument(null, contextMethodInvocation, index, "null", progressMonitor) != null;
if (classInstanceCreation != null)
return CodeTransforms.replaceMethodCallArgument(null, classInstanceCreation, index, "null", progressMonitor) != null;
}
return false;
}
*/
/*
public boolean doAssignedWithNull_reverse(EObject element, EStructuralFeature feature, EAnnotation annotation, EClass concreteChildType, IProgressMonitor progressMonitor) throws JavaModelException, FSMLMappingException {
if (feature instanceof EReference && concreteChildType == null)
throw new FSMLMappingException(Cause.MISSING_CONCRETE_CHILD_TYPE, feature);
EObject fieldFeature = FSMLEcoreUtil.retrieveContextElement(element, CONTEXT_FIELD);
EObject classFeature = FSMLEcoreUtil.retrieveContextElement(fieldFeature, CONTEXT_CLASS);
if (fieldFeature == null)
throw new FSMLMappingException(Cause.MISSING_CONTEXT, feature, CONTEXT_FIELD);
if (classFeature == null)
throw new FSMLMappingException(Cause.MISSING_CONTEXT, feature, CONTEXT_CLASS);
VariableDeclarationFragment variableDeclarationFragment = contextManager.getContextVariableDeclarationFragment(fieldFeature, true, progressMonitor);
IField auxField = (IField) variableDeclarationFragment.resolveBinding().getJavaElement();
if (variableDeclarationFragment != null) {
Collection<FieldReferenceMatch> result = writesToField(auxField, progressMonitor);
for (FieldReferenceMatch fieldReferenceMatch : result) {
Expression rhs = retrieveRHSFromMatch(fieldReferenceMatch, progressMonitor);
if (rhs instanceof NullLiteral) {
if (feature instanceof EAttribute)
element.eSet(feature, true);
else {
EObject child = EcoreUtil.create(concreteChildType);
element.eSet(feature, child);
if (!reverseFeatureRepresentedAsClass(child, progressMonitor))
return false;
}
Stats.INSTANCE.log(element.eClass(), feature, annotation);
JavaMarkerDescriptor descriptor = JavaMarkers.createMarkerDescriptor(auxField);
descriptor.setAttributes(feature, element.eClass().getName()+ "::" + feature.getName(), rhs.getParent());
descriptor.create(element);
return true;
}
}
}
return false;
}
public boolean doAssignedWithNull_forward(SyncItem syncItem, EAnnotation annotation, IProgressMonitor progressMonitor) throws JavaModelException, FSMLMappingException {
String detailLocationName = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, JavaMappingInterpreter.DETAIL_LOCATION_NAME, false);
String detailLocationSig = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, JavaMappingInterpreter.DETAIL_LOCATION_SIG, false);
if (detailLocationSig == null || detailLocationSig.isEmpty())
detailLocationSig = "()V";
String detailPosition = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_POSITION, false);
VariableDeclarationFragment targetField = contextManager.getContextVariableDeclarationFragment(FSMLEcoreUtil.retrieveContextElement(syncItem, CONTEXT_FIELD), true, progressMonitor);
// construct an assignment
String contents = targetField.getName().getIdentifier() + " = null;";
int position = 0;
if (detailPosition == null || detailPosition.equals("before"))
position = CodeTransforms.BEFORE_ADVICE;
else if (detailPosition.equals("after"))
position = CodeTransforms.AFTER_ADVICE;
else
throw new FSMLMappingException(Cause.INCORRECT_VALUE, "for detail " + DETAIL_POSITION);
// field assignment can be created in the context method or a context class
EObject contextMethodElement = FSMLEcoreUtil.retrieveContextElement(syncItem, CONTEXT_METHOD);
if (contextMethodElement != null) {
MethodDeclaration contextMethod = contextManager.getContextMethodDeclaration(contextMethodElement, true, progressMonitor);
CodeTransforms.weaveAdvice(position, null, contextMethod, contents, progressMonitor);
return true;
}
// no context method, try context class
EObject contextClassElement = FSMLEcoreUtil.retrieveContextElement(syncItem, CONTEXT_CLASS);
if (contextClassElement != null) {
TypeDeclaration contextClass = contextManager.getContextTypeDeclaration(contextClassElement, true, progressMonitor);
MethodDeclaration contextMethod = findMethod(detailLocationName, detailLocationSig, contextClass, true, false, progressMonitor);
if (contextMethod != null) {
CodeTransforms.weaveAdvice(position, null, contextMethod, contents, progressMonitor);
return true;
}
else {
// create the method
CodeTransforms.createMethod(project, null, contextClass, "public", detailLocationName, detailLocationSig, "\t" + contents, progressMonitor);
return true;
}
}
return false;
}
*/
/*
public boolean doAssignedWithNew_reverse(EObject element, EStructuralFeature feature, EAnnotation annotation, EClass concreteChildType, IProgressMonitor progressMonitor) throws JavaModelException, FSMLMappingException {
if (feature instanceof EReference && concreteChildType == null)
throw new FSMLMappingException(Cause.MISSING_CONCRETE_CHILD_TYPE, feature);
IField auxField = (IField) contextManager.getContextIField(element, true);
if (auxField == null)
return false;
VariableDeclarationFragment variableDeclarationFragment = contextManager.getContextVariableDeclarationFragment(element, true, progressMonitor);
if (variableDeclarationFragment != null) {
Expression initializer = variableDeclarationFragment.getInitializer();
if (initializer instanceof ClassInstanceCreation) {
// we assume that the code is correct
if (feature instanceof EAttribute)
element.eSet(feature, true);
else {
EObject child = EcoreUtil.create(concreteChildType);
element.eSet(feature, child);
contextManager.associateContext(child, initializer);
if (!reverseFeatureRepresentedAsClass(child, progressMonitor))
return false;
}
Stats.INSTANCE.log(element.eClass(), feature, annotation);
JavaMarkerDescriptor descriptor = JavaMarkers.createMarkerDescriptor(auxField);
descriptor.setAttributes(feature, element.eClass().getName() + "::" + feature.getName(), initializer);
descriptor.create(element);
return true;
}
Collection<FieldReferenceMatch> result = writesToField(auxField, progressMonitor);
for (FieldReferenceMatch fieldReferenceMatch : result) {
Expression rhs = retrieveRHSFromMatch(fieldReferenceMatch, progressMonitor);
if (rhs instanceof ClassInstanceCreation) {
ClassInstanceCreation cic = (ClassInstanceCreation) rhs;
Type instanceType = cic.getType();
String requiredClassName = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_CLASS, true);
String instanceTypeSignature = null;
if (instanceType instanceof QualifiedType) {
QualifiedType qtype = (QualifiedType) instanceType;
String qtypeName = qtype.getName().getFullyQualifiedName();
instanceTypeSignature = Signature.createTypeSignature(qtypeName, true);
}
else if (instanceType instanceof SimpleType) {
SimpleType stype = (SimpleType) instanceType;
String stypeName = stype.getName().getFullyQualifiedName();
instanceTypeSignature = Signature.createTypeSignature(stypeName, true);
}
if (compareTypeSignatures(requiredClassName, instanceTypeSignature)) {
if (feature instanceof EAttribute)
element.eSet(feature, true);
else {
EObject child = EcoreUtil.create(concreteChildType);
element.eSet(feature, child);
contextManager.associateContext(child, cic);
if (!reverseFeatureRepresentedAsClass(child, progressMonitor))
return false;
}
Stats.INSTANCE.log(element.eClass(), feature, annotation);
JavaMarkerDescriptor descriptor = JavaMarkers.createMarkerDescriptor(auxField);
descriptor.setAttributes(feature, element.eClass().getName() + "::" + feature.getName(), cic);
descriptor.create(element);
return true;
}
}
}
}
return false;
}
public boolean doAssignedWithNew_forward(SyncItem syncItem, EAnnotation annotation, IProgressMonitor progressMonitor) throws JavaModelException, FSMLMappingException {
// recognize the variant
// variant1: assignment in a method
String detailClass = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_CLASS, true);
String detailSignature = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, JavaMappingInterpreter.DETAIL_SIGNATURE, false);
String detailLocationName = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, JavaMappingInterpreter.DETAIL_LOCATION_NAME, false);
String detailLocationSig = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, JavaMappingInterpreter.DETAIL_LOCATION_SIG, false);
// default location signature
if (detailLocationSig == null || detailLocationSig.isEmpty())
detailLocationSig = "()V";
String detailPosition = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_POSITION, false);
// variant2: assignment in the field's initializer
String initializer = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_INITIALIZER, false);
// prepare class instance creation
String newExpression = "new " + Signature.getSimpleName(detailClass) + CodeTransforms.constructDefaultCallParameters(detailSignature);
// construct the new instance creation statement
IType instanceType = project.findType(detailClass);
if (instanceType.isInterface() || (instanceType.isClass() && Flags.isAbstract(instanceType.getFlags()))) {
// create annonymous subclass for interfaces and abstract classes
newExpression += " {\n\t }";
}
VariableDeclarationFragment targetField = contextManager.getContextVariableDeclarationFragment(FSMLEcoreUtil.retrieveContextElement(syncItem, CONTEXT_FIELD), true, progressMonitor);
if (initializer != null && initializer.equals("true")) {
//variant1
ClassInstanceCreation cic = (ClassInstanceCreation) CodeTransforms.setFieldsInitializer(null, targetField, newExpression, progressMonitor);
contextManager.associateContext(syncItem.getModel(), cic);
return true;
} else {
// variant2
// construct an assignment
if (detailLocationName == null)
throw new FSMLMappingException(Cause.MISSING_PARAMETER, JavaMappingInterpreter.DETAIL_LOCATION_NAME);
// construct a call
String contents = targetField.getName().getIdentifier() + " = " + newExpression + ";";
int position = 0;
if (detailPosition == null || detailPosition.equals("before"))
position = CodeTransforms.BEFORE_ADVICE;
else if (detailPosition.equals("after"))
position = CodeTransforms.AFTER_ADVICE;
else
throw new FSMLMappingException(Cause.INCORRECT_VALUE, "for detail " + DETAIL_POSITION);
// field assignment can be created in the context method or a context class
EObject contextMethodElement = FSMLEcoreUtil.retrieveContextElement(syncItem, CONTEXT_METHOD);
if (contextMethodElement != null) {
MethodDeclaration contextMethod = contextManager.getContextMethodDeclaration(contextMethodElement, true, progressMonitor);
List<ASTNode> result = CodeTransforms.weaveAdvice(position, null, contextMethod, contents, progressMonitor);
contextManager.associateContext(syncItem.getModel(), (ClassInstanceCreation) result.get(0));
return true;
}
else {
// no context method, try context class
EObject contextClassElement = FSMLEcoreUtil.retrieveContextElement(syncItem, CONTEXT_CLASS);
if (contextClassElement != null) {
TypeDeclaration contextClass = contextManager.getContextTypeDeclaration(contextClassElement, true, progressMonitor);
MethodDeclaration methodDeclaration = findMethod(detailLocationName, detailLocationSig, contextClass, true, false, progressMonitor);
if (methodDeclaration == null)
// create the method
methodDeclaration = CodeTransforms.createMethod(project, null, contextClass, "public", detailLocationName, detailLocationSig, null, progressMonitor);
List<ASTNode> result = CodeTransforms.weaveAdvice(position, null, methodDeclaration, contents, progressMonitor);
if (result.get(0) instanceof ExpressionStatement) {
ExpressionStatement expressionStatement = (ExpressionStatement) result.get(0);
Assignment assignment = (Assignment) expressionStatement.getExpression();
ClassInstanceCreation cic = (ClassInstanceCreation) assignment.getRightHandSide();
contextManager.associateContext(syncItem.getModel(), cic);
return true;
}
}
}
}
return false;
}
*/
/*
public boolean doArgumentIsNew_reverse(EObject element, EStructuralFeature feature, EAnnotation annotation, EClass concreteChildType, IProgressMonitor progressMonitor) throws JavaModelException, FSMLMappingException {
if (feature instanceof EReference && concreteChildType == null)
throw new FSMLMappingException(Cause.MISSING_CONCRETE_CHILD_TYPE, feature);
// could be a method invocation or class instance creation
MethodInvocation methodInvocation = contextManager.getContextMethodInvocation(element, true, progressMonitor);
ClassInstanceCreation classInstanceCreation = contextManager.getContextClassInstanceCreation(element, true, progressMonitor);
// exactly one of them must be non-null
assert(!(methodInvocation == null && classInstanceCreation == null) &&
!(methodInvocation != null && classInstanceCreation != null));
String indexString = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_INDEX, true);
int index = Integer.valueOf(indexString) - 1;
ASTNode argument = null;
if (methodInvocation != null)
argument = (ASTNode) methodInvocation.arguments().get(index);
if (classInstanceCreation != null)
argument = (ASTNode) classInstanceCreation.arguments().get(index);
if (argument instanceof ClassInstanceCreation)
Stats.INSTANCE.log(element.eClass().getName() + "::" + feature.getName() + " <argumentIsNew> argument is a class instance creation expression");
else
return false;
if (feature instanceof EAttribute)
element.eSet(feature, true);
else {
EObject child = EcoreUtil.create(concreteChildType);
element.eSet(feature, child);
ClassInstanceCreation argumentClassInstanceCreation = (ClassInstanceCreation) argument;
contextManager.associateContext(child, argumentClassInstanceCreation);
if (!reverseFeatureRepresentedAsClass(child, progressMonitor))
return false;
}
Stats.INSTANCE.log(element.eClass(), feature, annotation);
IType iTypeOfArgument = findITypeContainingASTNode(argument);
if (iTypeOfArgument == null)
iTypeOfArgument = (IType) contextManager.getContextIType(element, true);
JavaMarkerDescriptor markerDescriptor = JavaMarkers.createMarkerDescriptor(iTypeOfArgument);
markerDescriptor.setAttributes(feature, element.eClass().getName() + "::" + feature.getName(), argument);
markerDescriptor.create(element);
return true;
}*/
/*
public boolean doArgumentIsNew_forward(SyncItem syncItem, EAnnotation annotation, IProgressMonitor progressMonitor) throws JavaModelException, FSMLMappingException {
String detailIndex = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_INDEX, true);
int index = 0;
if (detailIndex != null && !detailIndex.isEmpty()) {
try {
index = Integer.parseInt(detailIndex);
}
catch (NumberFormatException e) {
throw new FSMLMappingException(Cause.INCORRECT_VALUE, " of detail " + DETAIL_INDEX);
}
}
String detailClass = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_CLASS, true);
String detailClassSimple = Signature.getSimpleName(detailClass);
String signature = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, JavaMappingInterpreter.DETAIL_SIGNATURE, "()V");
EObject contextMethodInvocationElement = FSMLEcoreUtil.retrieveContextElement(syncItem, CONTEXT_METHOD_CALL);
if (contextMethodInvocationElement == null)
throw new FSMLMappingException(Cause.MISSING_CONTEXT, CONTEXT_METHOD_CALL);
MethodInvocation contextMethodInvocation = contextManager.getContextMethodInvocation(contextMethodInvocationElement, true, progressMonitor);
ClassInstanceCreation classInstanceCreation = contextManager.getContextClassInstanceCreation(contextMethodInvocationElement, true, progressMonitor);
// construct the new instance creation statement
IType instanceType = project.findType(detailClass);
String newExpression = "new " + detailClassSimple + CodeTransforms.constructDefaultCallParameters(signature);
if (instanceType.isInterface() || (instanceType.isClass() && Flags.isAbstract(instanceType.getFlags()))) {
// create annonymous subclass for interfaces and abstract classes
newExpression += " {\n\t }";
}
switch (syncItem.getReconciliationAction()) {
case CODE_ADD:
if (contextMethodInvocation != null) {
Expression expression = CodeTransforms.replaceMethodCallArgument(null, contextMethodInvocation, index, newExpression, progressMonitor);
if (expression != null) {
CodeTransforms.organizeImports(contextMethodInvocation, detailClass);
return true;
}
}
if (classInstanceCreation != null) {
Expression expression = CodeTransforms.replaceMethodCallArgument(null, classInstanceCreation, index, newExpression, progressMonitor);
if (expression != null) {
CodeTransforms.organizeImports(classInstanceCreation, detailClass);
return true;
}
}
case CODE_REMOVE:
if (contextMethodInvocation != null)
return CodeTransforms.replaceMethodCallArgument(null, contextMethodInvocation, index, "null", progressMonitor) != null;
if (classInstanceCreation != null)
return CodeTransforms.replaceMethodCallArgument(null, classInstanceCreation, index, "null", progressMonitor) != null;
}
return false;
}*/
/*
public boolean doArgumentIsVariable_reverse(EObject element, EStructuralFeature feature, EAnnotation annotation, EClass concreteChildType, IProgressMonitor progressMonitor) throws JavaModelException, FSMLMappingException {
if (feature instanceof EReference && concreteChildType == null)
throw new FSMLMappingException(Cause.MISSING_CONCRETE_CHILD_TYPE, feature);
EObject methodCallFeature = FSMLEcoreUtil.retrieveContextElement(element, CONTEXT_METHOD_CALL);
if (methodCallFeature != null) {
// could be a method invocation or class instance creation
MethodInvocation methodInvocation = contextManager.getContextMethodInvocation(methodCallFeature, true, progressMonitor);
ClassInstanceCreation classInstanceCreation = contextManager.getContextClassInstanceCreation(methodCallFeature, true, progressMonitor);
// exactly one of them must be non-null
assert(!(methodInvocation == null && classInstanceCreation == null) &&
!(methodInvocation != null && classInstanceCreation != null));
String indexString = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_INDEX, true);
int index = Integer.valueOf(indexString) - 1;
ASTNode argument = null;
if (methodInvocation != null)
argument = (ASTNode) methodInvocation.arguments().get(index);
if (classInstanceCreation != null)
argument = (ASTNode) classInstanceCreation.arguments().get(index);
if (argument instanceof SimpleName) {
SimpleName simpleName = (SimpleName) argument;
IBinding binding = simpleName.resolveBinding();
if (binding.getKind() == IBinding.VARIABLE) {
IVariableBinding variableBinding = (IVariableBinding) binding;
if (!variableBinding.isField()) {
Stats.INSTANCE.log(element.eClass().getName() + "::" + feature.getName() + " <argumentIsVariable> argument is a variable");
if (feature instanceof EAttribute)
element.eSet(feature, simpleName.getIdentifier());
else {
EObject child = EcoreUtil.create(concreteChildType);
element.eSet(feature, child);
if (!reverseFeatureRepresentedAsClass(child, progressMonitor))
return false;
}
Stats.INSTANCE.log(element.eClass(), feature, annotation);
IType iTypeOfArgument = findITypeContainingASTNode(argument);
if (iTypeOfArgument == null)
iTypeOfArgument = (IType) contextManager.getContextIType(methodCallFeature, true);
JavaMarkerDescriptor markerDescriptor = JavaMarkers.createMarkerDescriptor(iTypeOfArgument);
markerDescriptor.setAttributes(feature, element.eClass().getName() + "::" + feature.getName(), argument);
markerDescriptor.create(element);
return true;
}
}
}
}
else
Stats.INSTANCE.log(element.eClass().getName() + "::" + feature.getName() + " <argumentIsNew> No context method call");
return false;
}*/
/*public boolean doArgumentIsVariable_forward(SyncItem syncItem, EAnnotation annotation, IProgressMonitor progressMonitor) throws JavaModelException, FSMLMappingException {
if (syncItem instanceof ClassSyncItem)
throw new FSMLMappingException(Cause.MAPPING_REQUIRES_ATTRIBUTE, syncItem.getModel().eContainingFeature());
StructuralFeatureSyncItem featureSyncItem = (StructuralFeatureSyncItem) syncItem;
EAttribute variableNameFeature = (EAttribute) featureSyncItem.getStructuralFeature();
String detailIndex = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_INDEX, true);
int index = 0;
if (detailIndex != null && !detailIndex.isEmpty()) {
try {
index = Integer.parseInt(detailIndex);
}
catch (NumberFormatException e) {
throw new FSMLMappingException(Cause.INCORRECT_VALUE, " of detail " + DETAIL_INDEX);
}
}
String detailType = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_CLASS, true);
IType instanceType = project.findType(detailType);
boolean annonymousSubclass = instanceType.isInterface() || (instanceType.isClass() && Flags.isAbstract(instanceType.getFlags()));
String detailSignature = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, JavaMappingInterpreter.DETAIL_SIGNATURE, "()V");
EObject element = syncItem.getModel();
MethodInvocation contextMethodInvocation = contextManager.getContextMethodInvocation(element, true, progressMonitor);
ClassInstanceCreation classInstanceCreation = contextManager.getContextClassInstanceCreation(element, true, progressMonitor);
String variableName = (String) element.eGet(variableNameFeature);
switch (syncItem.getReconciliationAction()) {
case CODE_ADD:
if (contextMethodInvocation != null) {
Expression expression = CodeTransforms.replaceMethodCallArgument(null, contextMethodInvocation, index, variableName, progressMonitor);
CodeTransforms.declareVariable(null, contextMethodInvocation, variableName, detailType, detailSignature, annonymousSubclass, progressMonitor);
return expression != null;
}
if (classInstanceCreation != null) {
Expression expression = CodeTransforms.replaceMethodCallArgument(null, classInstanceCreation, index, variableName, progressMonitor);
CodeTransforms.declareVariable(null, classInstanceCreation, variableName, detailType, detailSignature, annonymousSubclass, progressMonitor);
return expression != null;
}
break;
case CODE_REMOVE:
if (contextMethodInvocation != null)
return CodeTransforms.replaceMethodCallArgument(null, contextMethodInvocation, index, "null", progressMonitor) != null;
if (classInstanceCreation != null)
return CodeTransforms.replaceMethodCallArgument(null, classInstanceCreation, index, "null", progressMonitor) != null;
break;
}
return false;
}*/
/*
public boolean doArgumentValue_reverse(EObject element, EAttribute feature, EAnnotation annotation, IProgressMonitor progressMonitor) throws JavaModelException, FSMLMappingException {
EObject methodCallFeature = FSMLEcoreUtil.retrieveContextElement(element, CONTEXT_METHOD_CALL);
if (methodCallFeature != null) {
// could be a method invocation or class instance creation
MethodInvocation methodInvocation = contextManager.getContextMethodInvocation(methodCallFeature, true, progressMonitor);
ClassInstanceCreation classInstanceCreation = contextManager.getContextClassInstanceCreation(methodCallFeature, true, progressMonitor);
// exactly one of them must be non-null
assert(!(methodInvocation == null && classInstanceCreation == null) &&
!(methodInvocation != null && classInstanceCreation != null));
String indexString = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_INDEX, true);
int index = Integer.valueOf(indexString) - 1;
if (feature.getEAttributeType().getName().equals("EString")) {
ASTNode argument = null;
if (methodInvocation != null)
argument = (ASTNode) methodInvocation.arguments().get(index);
if (classInstanceCreation != null)
argument = (ASTNode) classInstanceCreation.arguments().get(index);
String value = null;
if (argument instanceof StringLiteral) {
value = ((StringLiteral) argument).getLiteralValue();
Stats.INSTANCE.log(element.eClass().getName() + "::" + feature.getName() + " <argumentValue>", "StringLiteral retrieved");
}
else if (argument instanceof TypeLiteral) {
TypeLiteral typeLiteral = (TypeLiteral) argument;
ITypeBinding binding = typeLiteral.getType().resolveBinding();
if (binding != null) {
value = binding.getQualifiedName();
Stats.INSTANCE.log(element.eClass().getName() + "::" + feature.getName() + " <argumentValue>","TypeLiteral retrieved (binding)");
}
else {
if (typeLiteral.getType().isQualifiedType()) {
QualifiedType qualifiedType = (QualifiedType) typeLiteral.getType();
value = qualifiedType.getQualifier() + "." + qualifiedType.getName();
Stats.INSTANCE.log(element.eClass().getName() + "::" + feature.getName() + " <argumentValue>","TypeLiteral retrieved (QualifiedType)");
}
else if (typeLiteral.getType().isSimpleType()) {
SimpleType simpleType = (SimpleType) typeLiteral.getType();
String simpleTypeName = simpleType.getName().getFullyQualifiedName();
// navigate to import declarations
ASTNode rootNode = argument.getRoot();
if (rootNode instanceof CompilationUnit) {
CompilationUnit cu = (CompilationUnit) rootNode;
for (Object aux : cu.imports()) {
ImportDeclaration id = (ImportDeclaration) aux;
QualifiedName importQualifiedName = (QualifiedName) id.getName();
SimpleName importLastName = importQualifiedName.getName();
if (importLastName.getIdentifier().equals(simpleTypeName)) {
value = importQualifiedName.getFullyQualifiedName();
Stats.INSTANCE.log(element.eClass().getName() + "::" + feature.getName() + " <argumentValue>","TypeLiteral retrieved. (ImportDeclaration)");
}
}
if (value == null) {
Stats.INSTANCE.log(element.eClass().getName() + "::" + feature.getName() + " <argumentValue>","TypeLiteral not retrieved. No binding. No QualifiedName. No ImportDeclaration.");
return false;
}
}
}
}
if (value != null)
Stats.INSTANCE.log("typedLiteral retrieved:" + value);
}
// handle both simple and qualified names
else if (argument instanceof Name) {
Object resolvedBinding = ((Name) argument).resolveBinding();
if (resolvedBinding instanceof IVariableBinding) {
IVariableBinding vb = (IVariableBinding) resolvedBinding;
Object auxValue = vb.getConstantValue();
if (auxValue instanceof String) {
value = (String) auxValue;
Stats.INSTANCE.log(element.eClass().getName() + "::" + feature.getName() + " <argumentValue>","Constant String retrieved");
}
else if (value == null) {
auxValue = vb.getVariableDeclaration().getConstantValue();
if (auxValue instanceof String) {
value = (String) auxValue;
Stats.INSTANCE.log(element.eClass().getName() + "::" + feature.getName() + " <argumentValue>","Constant String retrieved from VariableDeclaration");
}
}
}
}
else
Stats.INSTANCE.log(element.eClass().getName() + "::" + feature.getName() + " <argumentValue>","Argument not name nor literal");
if (value != null) {
// check equalTo constraint
EAnnotation equalToAnnotation = feature.getEAnnotation("valueEqualsTo");
if (equalToAnnotation != null) {
String featurePath = (String) FSMLEcoreUtil.retrieveParameterValue(equalToAnnotation, QUERY_ATTRIBUTE, true);
assert (featurePath != null);
// navigate to the String feature that holds the value this feature is expected to be equal to
FSMLEcoreUtil.NavigationResult target = FSMLEcoreUtil.navigateToEObject(element, featurePath);
// TODO: 'valueEqualsTo' constraint: handle all types
String targetValue = (String) target.eObject.eGet(target.eAttribute);
if (!value.equals(targetValue))
return false;
}
element.eSet(feature, value);
Stats.INSTANCE.log(element.eClass(), feature, annotation);
EObject contextClassElement = FSMLEcoreUtil.retrieveContextElement(methodCallFeature, CONTEXT_CLASS);
IType iTypeOfArgument = findITypeContainingASTNode(argument);
if (iTypeOfArgument == null) {
TypeDeclaration typeDeclaration = contextManager.getContextTypeDeclaration(contextClassElement, true, progressMonitor);
iTypeOfArgument = (IType) typeDeclaration.resolveBinding().getJavaElement();
}
JavaMarkerDescriptor markerDescriptor = JavaMarkers.createMarkerDescriptor(iTypeOfArgument);
markerDescriptor.setAttributes(feature, element.eClass().getName() + "::" + feature.getName(), argument);
markerDescriptor.create(element);
return true;
}
else
Stats.INSTANCE.log(element.eClass().getName() + "::" + feature.getName() + " <argumentValue>","Unable to retrieve value");
}
}
else
Stats.INSTANCE.log(element.eClass().getName() + "::" + feature.getName() + " <argumentValue>","No context method call");
return false;
}
public boolean doArgumentValue_forward(StructuralFeatureSyncItem syncItem, EAnnotation annotation, IProgressMonitor progressMonitor) throws FSMLMappingException {
String detailIndex = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_INDEX, true);
int index = 0;
if (detailIndex != null && !detailIndex.isEmpty()) {
try {
index = Integer.parseInt(detailIndex);
}
catch (NumberFormatException e) {
throw new FSMLMappingException(Cause.INCORRECT_VALUE, " of detail " + DETAIL_INDEX);
}
}
EObject contextMethodInvocationElement = FSMLEcoreUtil.retrieveContextElement(syncItem, CONTEXT_METHOD_CALL);
if (contextMethodInvocationElement == null)
throw new FSMLMappingException(Cause.MISSING_CONTEXT, CONTEXT_METHOD_CALL);
MethodInvocation contextMethodInvocation = contextManager.getContextMethodInvocation(contextMethodInvocationElement, true, progressMonitor);
switch (syncItem.getReconciliationAction()) {
case CODE_ADD:
EAttribute attribute = (EAttribute) syncItem.getStructuralFeature();
EObject element = syncItem.getModel();
// TODO: handle types other than String
String value = '"' + (String) element.eGet(attribute) + '"';
return CodeTransforms.replaceMethodCallArgument(null, contextMethodInvocation, index, value, progressMonitor) != null;
case CODE_REMOVE:
return CodeTransforms.replaceMethodCallArgument(null, contextMethodInvocation, index, "null", progressMonitor) != null;
}
return false;
}
*/
/*
public boolean doMethodName_reverse(EObject element, EAttribute feature, EAnnotation annotation, IProgressMonitor progressMonitor) throws JavaModelException, FSMLMappingException {
MethodDeclaration methodDeclaration = contextManager.getContextMethodDeclaration(element, true, progressMonitor);
IJavaElement method = methodDeclaration.resolveBinding().getJavaElement();
element.eSet(feature, method.getElementName());
Stats.INSTANCE.log(element.eClass(), feature, annotation);
JavaMarkerDescriptor markerDescriptor = JavaMarkers.createMarkerDescriptor(method);
//markerDescriptor.setAttributes(feature, element.eClass().getName() + "::" + feature.getName(), method);
markerDescriptor.create(element);
return true;
}
*/
/*
public boolean doTypesOfReturnedObjects_reverse(EObject element, EAttribute feature, EAnnotation annotation, IProgressMonitor progressMonitor) throws JavaModelException, FSMLMappingException {
MethodDeclaration contextMethod = contextManager.getContextMethodDeclaration(element, true, progressMonitor);
if (feature.getEAttributeType().getName().equals("EString")) {
// make sure feature is not there in case the default is true
element.eUnset(feature);
boolean returnNonTypesReturns = true;
ReturnStatement[] returnStatements = typesOfReturnedObjects(contextMethod, progressMonitor,returnNonTypesReturns);
ArrayList<MarkerDescriptor> markerDescriptors = new ArrayList<MarkerDescriptor>();
for (ReturnStatement statement : returnStatements) {
if (statement == null)
continue;
Expression expression = statement.getExpression();
if (expression == null)
continue;
if (returnNonTypesReturns) {
if (expression instanceof SuperMethodInvocation) {
Stats.INSTANCE.log(element.eClass(), feature, annotation,"super");
continue;
} else if (expression instanceof NullLiteral) {
Stats.INSTANCE.log(element.eClass(), feature, annotation,"null");
continue;
} else if (((IType)(expression.resolveTypeBinding().getJavaElement())).getFullyQualifiedName().equals("java.lang.Object")) {
continue;
}
}
ITypeBinding typeBinding = expression.resolveTypeBinding();
if (typeBinding == null)
continue;
IType iType = (IType) typeBinding.getJavaElement();
if (iType == null || !iType.exists())
continue;
String name = iType.getFullyQualifiedName();
if (feature.isMany()) {
((EList)element.eGet(feature)).add(name);
JavaMarkerDescriptor markerDescriptor = JavaMarkers.createMarkerDescriptor(contextMethod.resolveBinding().getJavaElement());
markerDescriptor.setAttributes(feature, element.eClass().getName() + "::" + feature.getName() + "(" + name + ")", statement);
markerDescriptor.setElementAndValue(element, name);
markerDescriptors.add(markerDescriptor);
}
else {
element.eSet(feature, name);
JavaMarkerDescriptor markerDescriptor = JavaMarkers.createMarkerDescriptor(contextMethod.resolveBinding().getJavaElement());
markerDescriptor.setAttributes(feature, element.eClass().getName() + "::" + feature.getName(), statement);
markerDescriptor.setElement(element);
markerDescriptors.add(markerDescriptor);
// ignore the rest of results!
break;
}
Stats.INSTANCE.log(element.eClass(), feature, annotation);
if (analyzeImplVariants) {
//analyze implementation variants
Expression stmtExpression = statement.getExpression();
while (stmtExpression instanceof ParenthesizedExpression) {
stmtExpression = ((ParenthesizedExpression)stmtExpression).getExpression();
}
if (stmtExpression instanceof ConditionalExpression) {
Expression elseExpression =((ConditionalExpression)stmtExpression).getElseExpression();
Expression thenExpression =((ConditionalExpression)stmtExpression).getThenExpression();
if (!(elseExpression instanceof InfixExpression) && !(elseExpression instanceof NullLiteral)) {
stmtExpression=((ConditionalExpression)stmtExpression).getElseExpression();
} else if(!(thenExpression instanceof InfixExpression) && !(thenExpression instanceof NullLiteral)) {
stmtExpression = ((ConditionalExpression)stmtExpression).getThenExpression();
} else {
Stats.INSTANCE.log(element.eClass(), feature, annotation,"failed to analyze ParenthesizedExpression or ConditionalExpression");
continue;
}
}
if (stmtExpression instanceof MethodInvocation) {
Stats.INSTANCE.log(element.eClass(), feature, annotation,"method of return type "+((MethodInvocation)stmtExpression).resolveMethodBinding().getReturnType().getName());
} else if (stmtExpression instanceof ThisExpression) {
Stats.INSTANCE.log(element.eClass(), feature, annotation,"this");
} else if (stmtExpression instanceof SimpleName) {
Stats.INSTANCE.log(element.eClass(),feature,annotation,"variable");
} else if (stmtExpression instanceof ClassInstanceCreation) {
if (((ClassInstanceCreation)stmtExpression).getAnonymousClassDeclaration()!=null) {
Stats.INSTANCE.log(element.eClass(),feature,annotation, "anon");
} else {
Stats.INSTANCE.log(element.eClass(),feature,annotation,"new");
}
} else {
Stats.INSTANCE.log(element.eClass(), feature, annotation,stmtExpression.getClass().getSimpleName());
}
}
}
for (MarkerDescriptor descriptor : markerDescriptors)
descriptor.create();
return returnStatements.length > 0;
}
return false;
}
*/
/*
public boolean doTypedWith_reverse(EObject element, EStructuralFeature feature, EAnnotation annotation, EClass concreteChildType, IProgressMonitor progressMonitor) throws JavaModelException, FSMLMappingException {
if (feature instanceof EReference && concreteChildType == null)
throw new FSMLMappingException(Cause.MISSING_CONCRETE_CHILD_TYPE, feature);
VariableDeclarationFragment variableDeclarationFragment = contextManager.getContextVariableDeclarationFragment(element, true, progressMonitor);
if (variableDeclarationFragment != null) {
String desiredType = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_NAME, true);
FieldDeclaration fieldDeclaration = (FieldDeclaration) variableDeclarationFragment.getParent();
String currentType = fieldDeclaration.getType().resolveBinding().getQualifiedName();
boolean typesEqual = desiredType.equals(currentType);
if (typesEqual) {
if (feature instanceof EAttribute)
element.eSet(feature, true);
else {
EObject child = EcoreUtil.create(concreteChildType);
element.eSet(feature, child);
if (!reverseFeatureRepresentedAsClass(child, progressMonitor))
return false;
}
Stats.INSTANCE.log(element.eClass(), feature, annotation);
IType iType = findITypeContainingASTNode(variableDeclarationFragment);
JavaMarkerDescriptor descriptor = JavaMarkers.createMarkerDescriptor(iType);
descriptor.setAttributes(feature, element.eClass().getName() + "::" + feature.getName(), fieldDeclaration.getType());
descriptor.create(element);
return true;
}
}
return false;
}
*/
/*
* public boolean doAnnotatedWith_reverse(EObject element, EAttribute feature, EAnnotation annotation, IProgressMonitor progressMonitor) throws JavaModelException, FSMLMappingException {
String fullAnnotationType = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_FULLY_QUALIFIED_TYPE, true);
String simpleAnnotationType = Signature.getSimpleName(fullAnnotationType);
BodyDeclaration bodyDeclaration = null;
if (FSMLEcoreUtil.getEAnnotation(element.eClass(),CONTEXT_CLASS) != null)
//we have a class
bodyDeclaration = contextManager.getContextTypeDeclaration(element, true, progressMonitor);
else if (FSMLEcoreUtil.getEAnnotation(element.eClass(),CONTEXT_METHOD) != null)
//we have a method
bodyDeclaration = contextManager.getContextMethodDeclaration(element, true, progressMonitor);
else if (FSMLEcoreUtil.getEAnnotation(element.eClass(),CONTEXT_FIELD) != null)
bodyDeclaration = (BodyDeclaration) contextManager.getContextVariableDeclarationFragment(element, true, progressMonitor).getParent();
else
return false;
boolean foundDesiredAnnotation = false;
for (Object modifier : bodyDeclaration.modifiers()) {
if (modifier instanceof Annotation){
String modifierType = ((Annotation)modifier).getTypeName().getFullyQualifiedName();
if (fullAnnotationType.equalsIgnoreCase(modifierType)
|| simpleAnnotationType.equalsIgnoreCase(modifierType)){
element.eSet(feature, new Boolean(true));
foundDesiredAnnotation = true;
break;
}
}
}
if (!foundDesiredAnnotation){
return false;
}
Stats.INSTANCE.log(element.eClass(), feature, annotation);
IJavaElement iJavaElement = findITypeContainingASTNode(bodyDeclaration);
JavaMarkerDescriptor markerDescriptor = JavaMarkers.createMarkerDescriptor(iJavaElement);
markerDescriptor.setAttributes(feature, element.eClass().getName() + "::" + feature.getName(), bodyDeclaration);
markerDescriptor.create(element);
return true;
/*
if (annotationFeature != null) {
String stringValue = null;
Annotation javaAnnotation = feature2Annotation.get(annotationFeature);
if (javaAnnotation.getNodeType() == ASTNode.NORMAL_ANNOTATION){
NormalAnnotation normalJavaAnnotation = (NormalAnnotation) javaAnnotation;
for (Object valueObject : normalJavaAnnotation.values()) {
MemberValuePair mvp = (MemberValuePair) valueObject;
if (mvp.getName().getFullyQualifiedName().equalsIgnoreCase(attributeName)){
//the name of the attribute is the desired one.
expressionValue = mvp.getValue();
Object objectValue = expressionValue.resolveConstantExpressionValue();
stringValue = objectValue.toString();
break;
}
}
}
}
*/
/*
* public boolean doAnnotatedWithReference_reverse(EObject element, EStructuralFeature feature, EAnnotation annotation, EClass concreteChildType, IProgressMonitor progressMonitor) throws JavaModelException, FSMLMappingException {
String fullAnnotationType = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_FULLY_QUALIFIED_TYPE, true);
String simpleAnnotationType = Signature.getSimpleName(fullAnnotationType);
BodyDeclaration bodyDeclaration = null;
if (FSMLEcoreUtil.getEAnnotation(element.eClass(),CONTEXT_CLASS) != null){
//we have a class
bodyDeclaration = contextManager.getContextTypeDeclaration(element, true, progressMonitor);
}
else if (FSMLEcoreUtil.getEAnnotation(element.eClass(),CONTEXT_METHOD) != null){
//we have a method
bodyDeclaration = contextManager.getContextMethodDeclaration(element, true, progressMonitor);
}
else if (FSMLEcoreUtil.getEAnnotation(element.eClass(),CONTEXT_FIELD) != null){
VariableDeclarationFragment variableDeclarationFragment = contextManager.getContextVariableDeclarationFragment(element, true, progressMonitor);
bodyDeclaration = (BodyDeclaration) variableDeclarationFragment.getParent();
}
else
return false;
boolean foundDesiredAnnotation = false;
EObject child = null;
Annotation foundAnnotation = null;
for (Object modifier : bodyDeclaration.modifiers()) {
if (modifier instanceof Annotation){
String modifierType = ((Annotation)modifier).getTypeName().getFullyQualifiedName();
if (fullAnnotationType.equalsIgnoreCase(modifierType)
|| simpleAnnotationType.equalsIgnoreCase(modifierType)){
//we've found the annotation
if (feature instanceof EAttribute)
element.eSet(feature, true);
else {
child = EcoreUtil.create(concreteChildType);
element.eSet(feature, child);
contextManager.associateContext(child, modifier);
if (!reverseFeatureRepresentedAsClass(child, progressMonitor)){
return false;
}
}
Stats.INSTANCE.log(element.eClass(), feature, annotation);
foundDesiredAnnotation = true;
foundAnnotation = (Annotation) modifier;
break;
}
}
}
if (!foundDesiredAnnotation){
return false;
}
Stats.INSTANCE.log(element.eClass(), feature, annotation);
if (child != null){
TypeDeclaration typeDeclaration = (TypeDeclaration) ((CompilationUnit) bodyDeclaration.getRoot()).types().get(0);
IType iTypeForBodyDeclaration = (IType) typeDeclaration.resolveBinding().getJavaElement();
JavaMarkerDescriptor markerDescriptor = JavaMarkers.createMarkerDescriptor(iTypeForBodyDeclaration);
markerDescriptor.setAttributes(null, child.eClass().getName(),foundAnnotation);
markerDescriptor.create(child);
return true;
}
else{
TypeDeclaration typeDeclaration = (TypeDeclaration) ((CompilationUnit) bodyDeclaration.getRoot()).types().get(0);
IType iTypeForBodyDeclaration = (IType) typeDeclaration.resolveBinding().getJavaElement();
JavaMarkerDescriptor markerDescriptor = JavaMarkers.createMarkerDescriptor(iTypeForBodyDeclaration);
markerDescriptor.setAttributes(feature, element.eClass().getName(),foundAnnotation);
markerDescriptor.create(element);
return true;
}
}
*/
/*
* public boolean doAttributeRepresentedAsAttribute_reverse(EObject element, EAttribute feature, EAnnotation annotation, IProgressMonitor progressMonitor) throws JavaModelException, FSMLMappingException {
String attributeName = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_ATTRIBUTE_NAME, true);
Annotation currentAnnotation = contextManager.getContextAnnotation(element, true, progressMonitor);
Expression expressionValue = null;
String stringValue = null;
if (currentAnnotation.getNodeType() == ASTNode.NORMAL_ANNOTATION){
NormalAnnotation normalJavaAnnotation = (NormalAnnotation) currentAnnotation;
for (Object valueObject : normalJavaAnnotation.values()) {
MemberValuePair mvp = (MemberValuePair) valueObject;
if (mvp.getName().getFullyQualifiedName().equalsIgnoreCase(attributeName)){
//the name of the attribute is the desired one.
expressionValue = mvp.getValue();
}
}
}
else if (currentAnnotation.getNodeType() == ASTNode.SINGLE_MEMBER_ANNOTATION){
SingleMemberAnnotation singleJavaAnnotation = (SingleMemberAnnotation) currentAnnotation;
expressionValue = singleJavaAnnotation.getValue();
if (expressionValue instanceof ArrayInitializer){
ArrayInitializer ai = (ArrayInitializer) expressionValue;
for (Object obj : ai.expressions()) {
Expression exp = (Expression) obj;
}
}
}
if (expressionValue != null){
if (expressionValue instanceof TypeLiteral){
TypeLiteral tl = (TypeLiteral) expressionValue;
String fullyQualifiedName = tl.resolveTypeBinding().getQualifiedName();
fullyQualifiedName = fullyQualifiedName.substring(fullyQualifiedName.indexOf('<')+1, fullyQualifiedName.indexOf('>'));
element.eSet(feature,fullyQualifiedName);
return true;
}
Object objectValue = expressionValue.resolveConstantExpressionValue();
if (objectValue != null){
stringValue = objectValue.toString();
}
if (stringValue != null){
element.eSet(feature,stringValue);
return true;
}
}
return false;
}
*/
/*
* public boolean doAttributeRepresentedAsReference_reverse(EObject element, EStructuralFeature feature, EAnnotation annotation, EClass concreteChildType, IProgressMonitor progressMonitor) throws JavaModelException, FSMLMappingException {
String attributeName = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_ATTRIBUTE_NAME, true);
Annotation currentAnnotation = contextManager.getContextAnnotation(element, true, progressMonitor);
Expression expressionValue = null;
String stringValue = null;
IType itype = null;
if (currentAnnotation.getNodeType() == ASTNode.NORMAL_ANNOTATION){
NormalAnnotation normalJavaAnnotation = (NormalAnnotation) currentAnnotation;
for (Object valueObject : normalJavaAnnotation.values()) {
MemberValuePair mvp = (MemberValuePair) valueObject;
if (mvp.getName().getFullyQualifiedName().equalsIgnoreCase(attributeName)){
//the name of the attribute is the desired one.
expressionValue = mvp.getValue();
if (expressionValue instanceof TypeLiteral){
TypeLiteral tl = (TypeLiteral) expressionValue;
String fullyQualifiedName = tl.resolveTypeBinding().getQualifiedName();
fullyQualifiedName = fullyQualifiedName.substring(fullyQualifiedName.indexOf('<')+1, fullyQualifiedName.indexOf('>'));
itype= project.findType(fullyQualifiedName);
EObject child = EcoreUtil.create(concreteChildType);
if (!feature.isMany()){
element.eSet(feature, child);
}
else {
EList list = (EList) element.eGet(feature);
list.add(child);
}
CompilationUnit cu =contextManager.getCUforIJavaElement(itype, false, progressMonitor);
TypeDeclaration typeDeclaration = ASTNodeSearchUtil.getTypeDeclarationNode(itype, cu);
contextManager.associateContext(child, typeDeclaration);
}
//TODO do for arrays and single markers.
}
}
}
Stats.INSTANCE.log(element.eClass(), feature, annotation);
//JavaMarkerDescriptor descriptor = JavaMarkers.createMarkerDescriptor(itype);
//descriptor.setAttributes(feature, element.eClass().getName() + "::" + feature.getName(), itype);
//descriptor.create(element);
return true;
}
*/
/*public boolean canCreateChildrenForDefaultQuery(EClass eClass) {
return FSMLEcoreUtil.getEAnnotation(eClass, CONTEXT_METHOD) != null ||
FSMLEcoreUtil.getEAnnotation(eClass, CONTEXT_ANNOTATION) != null;
}*/
/*public boolean createChildrenForDefaultQuery(EObject element, EReference feature, EClass concreteChildType, IProgressMonitor progressMonitor) throws FSMLMappingException {
EAnnotation annotation = FSMLEcoreUtil.getEAnnotation(concreteChildType, CONTEXT_METHOD);
if (annotation != null) {
// case 1: the method is statically specified
String methodName = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, QUERY_METHOD_NAME, false);
String methodSignature = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_SIGNATURE, false);
if (methodName != null && methodSignature != null) {
TypeDeclaration contextTypeDeclaration = contextManager.getContextTypeDeclaration(element, true, progressMonitor);
MethodDeclaration methodDeclaration = ASTUtils.findMethod(javaAstManager, methodName, methodSignature, contextTypeDeclaration, true,true, progressMonitor);
if (methodDeclaration != null) {
EObject child = EcoreUtil.create(concreteChildType);
if (feature.isMany())
((EList)element.eGet(feature)).add(child);
else
element.eSet(feature, child);
contextManager.associateContext(child, methodDeclaration);
if (reverseFeatureRepresentedAsClass(child, progressMonitor))
Stats.INSTANCE.log(element.eClass(), feature, annotation);
}
return true;
}
}
annotation = FSMLEcoreUtil.getEAnnotation(concreteChildType, JavaMappingInterpreter.CONTEXT_ANNOTATION);
if (annotation != null) {
String fullyQualifiedName = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, DETAIL_FULLY_QUALIFIED_TYPE, true);
String simpleAnnotationType = fullyQualifiedName.indexOf('.') != -1 ? fullyQualifiedName.substring(fullyQualifiedName.lastIndexOf('.')+1,fullyQualifiedName.length()): fullyQualifiedName;
VariableDeclarationFragment variableDeclarationFragment = contextManager.getContextVariableDeclarationFragment(element, true, progressMonitor);
BodyDeclaration bodyDeclaration = null;
if (variableDeclarationFragment != null)
bodyDeclaration = (BodyDeclaration) variableDeclarationFragment.getParent();
else {
bodyDeclaration = contextManager.getContextMethodDeclaration(element, true, progressMonitor);
if (bodyDeclaration == null)
bodyDeclaration = contextManager.getContextTypeDeclaration(element, true, progressMonitor);
}
if (bodyDeclaration == null)
return false;
Annotation foundAnnotation = null;
for (Object objectModifier : bodyDeclaration.modifiers()) {
IExtendedModifier modifier = (IExtendedModifier) objectModifier;
if (modifier instanceof Annotation){
Annotation currentAnnotation = (Annotation)modifier;
Name annotationNameObject = currentAnnotation.getTypeName();
if (annotationNameObject.isSimpleName()){
if (annotationNameObject.getFullyQualifiedName().equalsIgnoreCase(simpleAnnotationType)){
foundAnnotation = currentAnnotation;
break;
}
}
else {
QualifiedName qualifiedAnnotationName = (QualifiedName) annotationNameObject;
if (qualifiedAnnotationName.getName().getFullyQualifiedName().equalsIgnoreCase(fullyQualifiedName)){
foundAnnotation = currentAnnotation;
break;
}
}
}
}
if (foundAnnotation != null) {
EObject child = EcoreUtil.create(concreteChildType);
if (feature.isMany()){
((EList)element.eGet(feature)).add(child);
}
else{
element.eSet(feature, child);
}
contextManager.associateContext(child,foundAnnotation);
if (reverseFeatureRepresentedAsClass(child, progressMonitor))
Stats.INSTANCE.log(element.eClass(), feature, annotation);
}
return true;
}
return false;
}*/
}