/*******************************************************************************
* Copyright (c) 2010 Herman Lee.
* 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:
* Herman Lee - initial API and implementation
******************************************************************************/
package ca.uwaterloo.gsd.fsml.quickFix;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Vector;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EAttribute;
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.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
import org.eclipse.jdt.ui.text.java.JavaContentAssistInvocationContext;
import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.IEditorDescriptor;
import org.eclipse.ui.IMarkerResolution;
import org.eclipse.ui.PlatformUI;
import ca.uwaterloo.gsd.fsml.codeAssist.FSMLCodeAssistUtil;
import ca.uwaterloo.gsd.fsml.contentassist.FSMLJavaContentCompleteProcessor;
import ca.uwaterloo.gsd.fsml.contentassist.FSMLJavaProposal;
import ca.uwaterloo.gsd.fsml.core.MarkerDescriptor;
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.fsml.ModelContainer;
import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.JavaMappingInterpreter;
import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.JavaMarkers;
import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.analysis.JavaModelUtils;
import ca.uwaterloo.gsd.fsml.xmlMappingInterpreter.XMLMappingInterpreter;
public class FSMLProblemMarkersQuickFix implements IMarkerResolution {
private String label;
private String errorMsg;
public FSMLProblemMarkersQuickFix(String label, String errorMsg) {
this.label = label;
this.errorMsg = errorMsg;
}
@Override
public String getLabel() {
return label;
}
@Override
public void run(IMarker problemMarker) {
// MessageDialog.openInformation(null, "QuickFix Demo",
// "This quick-fix is not yet implemented");
IProject currentProject = problemMarker.getResource().getProject();
Markers.INSTANCE.setProject(currentProject);
List<IFile> modelFiles = FSMLCodeAssistUtil.findModelFile(currentProject);
for (IFile fsmlModelFile : modelFiles) {
EList<EObject> fsmlModel = null;
ResourceSet resourceSet = new ResourceSetImpl();
URI fsmlModelURI = URI.createPlatformResourceURI(
fsmlModelFile.getFullPath().toString(), true);
Resource resource = resourceSet.getResource(
fsmlModelURI, true);
fsmlModel = resource.getContents();
Model assertedModel = ((ModelContainer) fsmlModel.get(0))
.getAssertedModel();
HashMap<String, EObject> fsmlId2ModelEObject = new HashMap<String,EObject>();
FSMLEcoreUtil.createFsmlId2EObjectMap(assertedModel, fsmlId2ModelEObject);
ICompilationUnit compilationUnit = getCompilationUnit(problemMarker);
int markerStartPos;
int markerEndPos;
try {
markerStartPos = ((Integer) problemMarker
.getAttribute(MarkerDescriptor.ATTRIBUTE_CHAR_START))
.intValue();
markerEndPos = ((Integer) problemMarker
.getAttribute(MarkerDescriptor.ATTRIBUTE_CHAR_END))
.intValue();
ASTNode coveringNode = FSMLCodeAssistUtil.getCoveringNode(compilationUnit, markerStartPos, 0);
Queries.INSTANCE.reset();
JavaMappingInterpreter javaMappingInterpreter = new JavaMappingInterpreter();
Queries.INSTANCE.registerCustomInterpreter(javaMappingInterpreter);
//register XML mapping interpreter
XMLMappingInterpreter xmlMappingInterpreter = new XMLMappingInterpreter();
Queries.INSTANCE.registerCustomInterpreter(xmlMappingInterpreter);
Queries.INSTANCE.initialize(currentProject,assertedModel);
javaMappingInterpreter.getAnalysisManagers().getJavaASTManager().setCompilationUnit(
JavaModelUtils.getTypeRoot(((CompilationUnit)coveringNode.getRoot()).getJavaElement()),(CompilationUnit)coveringNode.getRoot());
ASTRewrite rewrite = ASTRewrite.create(coveringNode.getAST());
String featureName=null;
boolean isFeatureGroup = false;
if (errorMsg.contains("'inv_featureGroupConstraint' invariant is violated on ")){
//this diagnostic message is of the format
//"The 'inv_*' invariant is violated on '*'
errorMsg = errorMsg.replaceAll("'inv_featureGroupConstraint' invariant is violated on ", "");
isFeatureGroup = true;
}else if (errorMsg.contains("feature") && errorMsg.contains("must be")){
//this diagnostic message is of the format
//"The * feature 'featureName' of 'project name' must be *
int beginning = errorMsg.indexOf("'");
featureName = errorMsg.substring(beginning+1,errorMsg.substring(beginning+1).indexOf("'")+beginning+1);
}
Vector<IMarker> markers = JavaMarkers.getMarkersCoveredByNode(coveringNode);
Image proposalImage=null;
if (resource.getURI().path()!=null){
IEditorDescriptor modelEditor = PlatformUI.getWorkbench().getEditorRegistry().getDefaultEditor(
resource.getURI().path());
if (modelEditor!=null){
proposalImage= modelEditor.getImageDescriptor().createImage();
}
}
if (proposalImage ==null){
proposalImage = FSMLJavaContentCompleteProcessor.IMG_TOOL_FORWARD;
}
for (IMarker coveringNodeMarker : markers) {
Object id = coveringNodeMarker.getAttribute(MarkerDescriptor.ATTRIBUTE_ID);
EObject currentEObject = fsmlId2ModelEObject.get(id);
if (currentEObject==null){
continue;
} else {
//associate context
Queries.INSTANCE.removeContext(currentEObject);
ASTNode astNode = coveringNode;
while (astNode!=null){
if (astNode instanceof MethodDeclaration){
MethodDeclaration methodDeclaration = (MethodDeclaration)astNode;
//FSMLEcoreUtil.parameterValuesFromRecommenderSystem.put(JavaMappingInterpreter.DETAIL_LOCATION_NAME, methodDeclaration.getName().getIdentifier());
IMethod iMethod = (IMethod) methodDeclaration.resolveBinding().getJavaElement();
String key = iMethod.getKey();
String auxSignature = key.substring(key.indexOf('('));
auxSignature = auxSignature.replace('/', '.');
//FSMLEcoreUtil.parameterValuesFromRecommenderSystem.put(JavaMappingInterpreter.DETAIL_LOCATION_SIG, auxSignature);
}
astNode = astNode.getParent();
}
}
}
for (IMarker coveringNodeMarker : markers) {
Object id = coveringNodeMarker.getAttribute(MarkerDescriptor.ATTRIBUTE_ID);
EObject currentEObject = fsmlId2ModelEObject.get(id);
if (currentEObject==null){
continue;
}
EStructuralFeature structuralFeature = currentEObject.eClass().getEStructuralFeature(featureName);
if (structuralFeature==null && !isFeatureGroup){
continue;
}
FSMLJavaProposal proposal =null;
if (isFeatureGroup){
proposal = new FSMLJavaProposal(errorMsg,compilationUnit,rewrite,2,
proposalImage,currentEObject,currentEObject.eClass(),null,coveringNode,markerStartPos,resource,null);
}else if (structuralFeature instanceof EAttribute){
proposal = new FSMLJavaProposal(errorMsg,compilationUnit,rewrite,2,
proposalImage,currentEObject,null,structuralFeature,coveringNode,markerStartPos,resource,null);
}else if (structuralFeature instanceof EReference){
Collection<EClass> concreteClasses = FSMLEcoreUtil
.getSubclassesOfEClass(
((EReference) structuralFeature)
.getEReferenceType(), true);
for (EClass concreteClass : concreteClasses) {
proposal = new FSMLJavaProposal(errorMsg,compilationUnit,rewrite,2,
proposalImage,currentEObject,concreteClass,structuralFeature,coveringNode,markerStartPos, resource,null);
}
}
proposal.apply(new JavaContentAssistInvocationContext(compilationUnit).getDocument());
break; //we are done since we have applied the only relevant proposal
}
} catch (CoreException e) {
e.printStackTrace();
}
}
}
private ICompilationUnit getCompilationUnit(IMarker marker) {
IResource res = marker.getResource();
if (res instanceof IFile && res.isAccessible()) {
IJavaElement element = JavaCore.create((IFile) res);
if (element instanceof ICompilationUnit)
return (ICompilationUnit) element;
}
return null;
}
}