/******************************************************************************* * 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 java.util.Collection; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EAnnotation; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.jdt.core.IField; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.Expression; import org.eclipse.jdt.core.dom.MethodDeclaration; import org.eclipse.jdt.core.dom.NullLiteral; import org.eclipse.jdt.core.dom.TypeDeclaration; import org.eclipse.jdt.core.dom.VariableDeclarationFragment; import org.eclipse.jdt.core.search.FieldReferenceMatch; import org.eclipse.jdt.internal.core.ResolvedSourceMethod; import ca.uwaterloo.gsd.fsml.core.Cause; import ca.uwaterloo.gsd.fsml.core.Context; 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.javaMappingInterpreter.CodeQueries; import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.CodeTransforms; import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.JavaMappingInterpreter; import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.analysis.ASTUtils; import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.analysis.JavaModelUtils; import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.analysis.impl.JavaImplVariantManagerConstants; import ca.uwaterloo.gsd.fsml.stats.Stats; import ca.uwaterloo.gsd.fsml.sync.SyncItem; public class AssignedWithNullMapping extends JavaMapping { public AssignedWithNullMapping(EObject element, EStructuralFeature feature, EAnnotation annotation, EClass concreteChildType, JavaMappingInterpreter interpreter, IProgressMonitor progressMonitor) throws FSMLMappingException { super(element, feature, annotation, concreteChildType, interpreter, progressMonitor); } public AssignedWithNullMapping(SyncItem syncItem, EAnnotation annotation, JavaMappingInterpreter interpreter, IProgressMonitor progressMonitor) throws FSMLMappingException { super(syncItem, annotation, interpreter, progressMonitor); // exactly one of them must be non-null if ((contextMethodDeclaration == null && contextTypeDeclaration == null) || (contextMethodDeclaration != null && contextTypeDeclaration != null)) throw new FSMLMappingException(Cause.MISSING_CONTEXT, "MethodDeclaration XOR TypeDeclaration"); if (detailPosition == null || detailPosition.equals("before")) position = CodeTransforms.BEFORE_ADVICE; else if (detailPosition.equals("after")) position = CodeTransforms.AFTER_ADVICE; else { try { position = Integer.parseInt(detailPosition); } catch (Exception e){ throw new FSMLMappingException(Cause.INCORRECT_VALUE, "for detail " + JavaMappingInterpreter.DETAIL_POSITION); } } } @Context(mode=Mode.REVERSE) public IField contextIField; @Context(mode=Mode.FORWARD) public VariableDeclarationFragment contextVariableDeclarationFragment; @Context(mode=Mode.FORWARD, excludes="contextMethodDeclaration") public TypeDeclaration contextTypeDeclaration; @Context(mode=Mode.FORWARD, excludes="contextTypeDeclaration") public MethodDeclaration contextMethodDeclaration; @Parameter(name=JavaMappingInterpreter.DETAIL_LOCATION_NAME, mode=Mode.FORWARD, required=true) public String locationName; @Parameter(name=JavaMappingInterpreter.DETAIL_LOCATION_SIG, mode=Mode.FORWARD, defaultValue="()V") public String locationSig; @Parameter(name=JavaMappingInterpreter.DETAIL_POSITION, mode=Mode.FORWARD, defaultValue="after") public String detailPosition; int position = 0; @Override protected boolean forward() throws FSMLMappingException { // construct an assignment String contents = contextVariableDeclarationFragment.getName().getIdentifier() + " = null;"; // field assignment can be created in the context method or a context class if (contextMethodDeclaration != null) { CodeTransforms.weaveAdvice(position, null, contextMethodDeclaration, contents, progressMonitor); return true; } // no context method, try context class if (contextTypeDeclaration != null) { MethodDeclaration contextMethod = ASTUtils.findMethod(javaAstManager, locationName, locationSig, contextTypeDeclaration, true, false, progressMonitor); if (contextMethod != null) { CodeTransforms.weaveAdvice(position, null, contextMethod, contents, progressMonitor); return true; } else { // create the method CodeTransforms.createMethod(contextIJavaProject, null, contextTypeDeclaration, "public", locationName, locationSig, "\t" + contents, progressMonitor); return true; } } return false; } @Override protected boolean reverse() throws FSMLMappingException { if (contextIField != null) { Collection<FieldReferenceMatch> result; try { result = JavaModelUtils.writesToField(contextIJavaProject, contextIField, progressMonitor); for (FieldReferenceMatch fieldReferenceMatch : result) { Expression rhs = CodeQueries.retrieveRHSFromMatch(javaAstManager, fieldReferenceMatch, progressMonitor); if (rhs instanceof NullLiteral){ if (javaInterpreter.analyzeImplVariants()){ EClass targetClass = javaImplVariantManager.getVariantEClass(JavaImplVariantManagerConstants.VARIANT+ JavaImplVariantManagerConstants.DELIMITER+ annotation.getSource() + JavaImplVariantManagerConstants.DELIMITER + JavaImplVariantManagerConstants.IN_METHOD); EObject child = EcoreUtil.create(targetClass); ((EList) javaImplVariantManager.getModel().eGet(javaImplVariantManager.getVariantsReference())).add(child); child.eSet(targetClass.getEStructuralFeature(JavaImplVariantManagerConstants.METHOD_NAME), ((ResolvedSourceMethod)fieldReferenceMatch.getElement()).getElementName() ); child.eSet(targetClass.getEStructuralFeature(JavaImplVariantManagerConstants.ECLASS), element.eClass().getName()); child.eSet(targetClass.getEStructuralFeature(JavaImplVariantManagerConstants.ESTRUCTURALFEATURE), feature.getName()); Stats.INSTANCE.logImplVariant(element.eClass(), feature, annotation,"InMethod: "+((ResolvedSourceMethod)fieldReferenceMatch.getElement()).getElementName()); } return setFeatureContextAndMarker(true, null, rhs.getParent(), null); } else { // see if it is a variable with null value if (rhs.getNodeType() == ASTNode.SIMPLE_NAME) // TODO: ; } } } catch (JavaModelException e) { e.printStackTrace(); } } return setFeature(false); } }