/*******************************************************************************
* 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.List;
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.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.TypeDeclaration;
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.ecore.FSMLEcoreUtil;
import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.CodeTransforms;
import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.JavaMappingInterpreter;
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 ExtendsClassMapping extends JavaMapping {
/**
* Constructor used in reverse engineering.
* @param element
* @param feature
* @param annotation
* @param concreteChildType
* @param interpreter
* @param progressMonitor
* @throws FSMLMappingException
*/
public ExtendsClassMapping(EObject element, EStructuralFeature feature, EAnnotation annotation, EClass concreteChildType, JavaMappingInterpreter interpreter, IProgressMonitor progressMonitor) throws FSMLMappingException {
super(element, feature, annotation, concreteChildType, interpreter, progressMonitor);
}
public ExtendsClassMapping(EObject element, EStructuralFeature feature, EStructuralFeature essentialFeature, EAnnotation annotation, EClass concreteChildType, JavaMappingInterpreter interpreter, IProgressMonitor progressMonitor) throws FSMLMappingException {
super(element, feature, essentialFeature, annotation, concreteChildType, interpreter, progressMonitor);
}
public ExtendsClassMapping(SyncItem syncItem, EAnnotation annotation, JavaMappingInterpreter interpreter, IProgressMonitor progressMonitor) throws FSMLMappingException {
super(syncItem, annotation, interpreter, progressMonitor);
}
@Context(mode=Mode.REVERSE, required=true)
public IType contextIType;
@Context(mode=Mode.FORWARD_AND_REVERSE)
public TypeDeclaration contextTypeDeclaration;
@Parameter(name=JavaMappingInterpreter.DETAIL_NAME, mode=Mode.ALL, required=true)
public String detailName;
@Parameter(name=JavaMappingInterpreter.DETAIL_LOCAL, mode=Mode.REVERSE_ESSENTIAL, defaultValue="false")
public String detailLocal;
@Parameter(name=JavaMappingInterpreter.DETAIL_CONCRETE, mode=Mode.REVERSE_ESSENTIAL, defaultValue="false")
public String detailConcrete;
@Parameter(name=JavaMappingInterpreter.DETAIL_ABSTRACT, mode=Mode.REVERSE_ESSENTIAL, defaultValue="false")
public String detailAbstract;
@Override
protected boolean forward() {
switch (syncItem.getReconciliationAction()) {
case CODE_ADD:
CodeTransforms.addExtendsDeclaration(contextIJavaProject, null, contextTypeDeclaration, detailName, progressMonitor);
break;
case CODE_REMOVE:
CodeTransforms.removeExtendsDeclaration(null, contextTypeDeclaration, detailName, progressMonitor);
break;
}
return true;
}
@Override
protected boolean reverse() throws FSMLMappingException {
try {
if (typeHierarchy.implementsOrExtendsType(contextIType, detailName)) {
boolean result = setFeatureContextAndMarker(
true,
null,
contextTypeDeclaration != null ?
contextTypeDeclaration.getSuperclassType() :
null,
null
);
if (result && javaInterpreter.analyzeImplVariants()) {
//analyze implementation variants
IType superClass = typeHierarchy.getSuperclass(contextIType);
String contextClassTypeSuperClass = superClass.getFullyQualifiedName();
if (contextClassTypeSuperClass.equals(detailName)) {
Stats.INSTANCE.logImplVariant(element.eClass(), feature, annotation,"directly");
EClass targetClass = javaImplVariantManager.getVariantEClass(JavaImplVariantManagerConstants.VARIANT+
JavaImplVariantManagerConstants.DELIMITER+
annotation.getSource() + JavaImplVariantManagerConstants.DELIMITER
+ JavaImplVariantManagerConstants.DIRECTLY);
EObject child = EcoreUtil.create(targetClass);
((EList) javaImplVariantManager.getModel().eGet(javaImplVariantManager.getVariantsReference())).add(child);
child.eSet(targetClass.getEStructuralFeature(JavaImplVariantManagerConstants.ECLASS), element.eClass().getName());
child.eSet(targetClass.getEStructuralFeature(JavaImplVariantManagerConstants.ESTRUCTURALFEATURE), feature.getName());
} else {
EClass targetClass = javaImplVariantManager.getVariantEClass(JavaImplVariantManagerConstants.VARIANT+
JavaImplVariantManagerConstants.DELIMITER+
annotation.getSource() + JavaImplVariantManagerConstants.DELIMITER
+ JavaImplVariantManagerConstants.INDIRECTLY);
EObject child = EcoreUtil.create(targetClass);
((EList) javaImplVariantManager.getModel().eGet(javaImplVariantManager.getVariantsReference())).add(child);
child.eSet(targetClass.getEStructuralFeature(JavaImplVariantManagerConstants.CLASS_NAME), contextClassTypeSuperClass);
child.eSet(targetClass.getEStructuralFeature(JavaImplVariantManagerConstants.ECLASS), element.eClass().getName());
child.eSet(targetClass.getEStructuralFeature(JavaImplVariantManagerConstants.ESTRUCTURALFEATURE), feature.getName());
Stats.INSTANCE.logImplVariant(element.eClass(), feature, annotation,"indirectly: "+contextClassTypeSuperClass);
}
}
return result;
}
} catch (JavaModelException e) {
e.printStackTrace();
}
return setFeature(false);
}
@Override
protected boolean reverseEssential() throws FSMLMappingException {
boolean localOnly = "true".equals(detailLocal);
boolean concreteOnly = "true".equals(detailConcrete);
boolean abstractOnly = "true".equals(detailAbstract);
try {
IType iType = contextIJavaProject.findType(detailName);
List<IType> subtypes = JavaModelUtils.getSubtypesOfType(iType, contextIJavaProject, localOnly, concreteOnly, abstractOnly, progressMonitor);
for (IType type : subtypes) {
setFeatureContextAndMarker(true, type, type, null);
}
return FSMLEcoreUtil.isFeaturePresent(element, feature);
} catch (JavaModelException e) {
e.printStackTrace();
}
return false;
}
}