/******************************************************************************* * 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.mappings; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.emf.ecore.EAnnotation; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.jdt.core.Flags; import org.eclipse.jdt.core.IMethod; import org.eclipse.jdt.core.IType; 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.ClassInstanceCreation; import org.eclipse.jdt.core.dom.Expression; import ca.uwaterloo.gsd.fsml.core.Cause; import ca.uwaterloo.gsd.fsml.core.FSMLMappingException; import ca.uwaterloo.gsd.fsml.core.Mode; import ca.uwaterloo.gsd.fsml.core.Parameter; import ca.uwaterloo.gsd.fsml.ecore.FSMLEcoreUtil; import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.CodeTransforms; import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.JavaMappingInterpreter; import ca.uwaterloo.gsd.fsml.stats.Stats; import ca.uwaterloo.gsd.fsml.sync.SyncItem; public class ArgumentIsNewMapping extends ArgumentIs_Mapping { public ArgumentIsNewMapping(EObject element, EStructuralFeature feature, EAnnotation annotation, EClass concreteChildType, JavaMappingInterpreter interpreter, IProgressMonitor progressMonitor) throws FSMLMappingException { super(element, feature, annotation, concreteChildType, interpreter, progressMonitor); } public ArgumentIsNewMapping(SyncItem syncItem, EAnnotation annotation, JavaMappingInterpreter interpreter, IProgressMonitor progressMonitor) throws FSMLMappingException { super(syncItem, annotation, interpreter, progressMonitor); } @Parameter(name=JavaMappingInterpreter.DETAIL_SAME_AS, mode=Mode.NONE) public String detailSameAs; @Override protected boolean forward() throws FSMLMappingException { String detailClass = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, JavaMappingInterpreter.DETAIL_CLASS, true); String detailClassSimple = Signature.getSimpleName(detailClass); String signature = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, JavaMappingInterpreter.DETAIL_SIGNATURE, "()V"); EObject contextMethodInvocationElement = FSMLEcoreUtil.retrieveContextElement(syncItem, JavaMappingInterpreter.CONTEXT_METHOD_CALL); if (contextMethodInvocationElement == null) throw new FSMLMappingException(Cause.MISSING_CONTEXT, JavaMappingInterpreter.CONTEXT_METHOD_CALL); // construct the new instance creation statement IType instanceType; try { instanceType = contextIJavaProject.findType(detailClass); String newExpression = "new " + detailClassSimple + CodeTransforms.constructDefaultCallParameters(signature); if (instanceType.isInterface() || (instanceType.isClass() && Flags.isAbstract(instanceType.getFlags()))) { // create anonymous subclass for interfaces and abstract classes newExpression += " {\n\t"; IMethod[] instanceMethods = instanceType.getMethods(); StringBuffer contents = new StringBuffer(); /* Michal: temporarily disable * for (IMethod method : instanceMethods) { if (!method.isConstructor() && (instanceType.isInterface() || Flags.isAbstract(method.getFlags()))) { // if this is an interface, provide empty stub of methods // if this is an abstract class, ONLY provide empty stubs for abstract methods String visibility = ""; if (Flags.isPublic(method.getFlags())) { visibility = "public"; } else if (Flags.isProtected(method.getFlags())) { visibility = "protected"; } contents.append(CodeTransforms.createMethodString(contextIJavaProject, (CompilationUnit)(contextMethodInvocation == null ? contextClassInstanceCreation : contextMethodInvocation).getRoot(), null, visibility, method.getElementName(), method.getSignature(), null, progressMonitor)); contents.append("\n"); } } */ contents.append("}"); newExpression += contents.toString(); } 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 (contextClassInstanceCreation != null) { Expression expression = CodeTransforms.replaceMethodCallArgument(null, contextClassInstanceCreation, index, newExpression, progressMonitor); if (expression != null) { CodeTransforms.organizeImports(contextClassInstanceCreation, detailClass); return true; } } case CODE_REMOVE: if (contextMethodInvocation != null) return CodeTransforms.replaceMethodCallArgument(null, contextMethodInvocation, index, "null", progressMonitor) != null; if (contextClassInstanceCreation != null) return CodeTransforms.replaceMethodCallArgument(null, contextClassInstanceCreation, index, "null", progressMonitor) != null; } } catch (JavaModelException e) { throw new FSMLMappingException(Cause.INCORRECT_VALUE, feature); } return false; } @Override protected boolean reverse() throws 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 // exactly one of them must be non-null assert(!(contextMethodInvocation == null && contextClassInstanceCreation == null) && !(contextMethodInvocation != null && contextClassInstanceCreation != null)); String indexString = (String) FSMLEcoreUtil.retrieveParameterValue(annotation, JavaMappingInterpreter.DETAIL_INDEX, true); int index = Integer.valueOf(indexString) - 1; ASTNode argument = null; if (contextMethodInvocation != null) argument = (ASTNode) contextMethodInvocation.arguments().get(index); if (contextClassInstanceCreation != null) argument = (ASTNode) contextClassInstanceCreation.arguments().get(index); if (argument instanceof ClassInstanceCreation) Stats.INSTANCE.logMessage(element.eClass().getName() + "::" + feature.getName() + " <argumentIsNew> argument is a class instance creation expression"); else return setFeature(false); return setFeatureContextAndMarker(true, argument, argument, null); } }