/******************************************************************************* * 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.recommender; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Set; import java.util.Map.Entry; import org.eclipse.core.filebuffers.FileBuffers; import org.eclipse.core.internal.resources.Marker; 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.TreeIterator; import org.eclipse.emf.ecore.EObject; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.ISourceRange; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.dom.AST; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.ASTParser; import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jdt.core.dom.MethodDeclaration; import org.eclipse.jdt.internal.core.ResolvedSourceMethod; import org.eclipse.jdt.internal.corext.refactoring.structure.ASTNodeSearchUtil; import org.eclipse.jface.util.TransferDragSourceListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.StructuredViewer; import org.eclipse.swt.dnd.DragSourceAdapter; import org.eclipse.swt.dnd.DragSourceEvent; import org.eclipse.swt.dnd.Transfer; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.ImageData; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.ISharedImages; import org.eclipse.ui.IViewPart; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.part.MarkerTransfer; import ca.uwaterloo.gsd.fsml.core.MarkerDescriptor; import ca.uwaterloo.gsd.fsml.core.Markers; 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; public class FSMLCodeGenDragSourceListener extends DragSourceAdapter implements TransferDragSourceListener { private final StructuredViewer viewer; private final IProject project; private Marker marker; public FSMLCodeGenDragSourceListener(StructuredViewer viewer, IProject project) { this.viewer = viewer; this.project = project; } @Override public Transfer getTransfer() { return MarkerTransfer.getInstance(); // return PluginTransfer.getInstance(); } // public void dragSetData(DragSourceEvent event) { // //event.data = "showStatus(null);"; // // event.data = new PluginTransferData( "my_drop_action", new // // byte[]{(byte)1}); // event.detail = DND.DROP_MOVE; // // ResourceSet resourceSet = new ResourceSetImpl(); // EList<EObject> existingResourceModel = null; // // IFile implModelFile = ResourcesPlugin.getWorkspace().getRoot().getFile( // project.getFullPath().append(JavaImplVariantManager.modelName)); // URI implModelURI = URI.createPlatformResourceURI(implModelFile // .getFullPath().toString(), true); // // if (implModelFile.exists()) { // // existingResourceModel = resourceSet.getResource(implModelURI, true) // .getContents(); // // } // // HashMap<String, EObject> defaultsInImplModel = new HashMap<String, EObject>(); // // EList<EObject> implModelContents = existingResourceModel.get(0) // .eContents(); // EObject currentFeature = null; // for (int i = 0; i < implModelContents.size(); i++) { // currentFeature = implModelContents.get(i); // if (currentFeature.eClass().getName().startsWith( // JavaImplVariantManagerConstants.DEFAULT)) { // // check if the mapping is the same (eClass and // // eStructuralFeature) // String eClass = (String) currentFeature.eGet(currentFeature // .eClass().getEStructuralFeature( // JavaImplVariantManagerConstants.ECLASS)); // String eStructuralFeature = (String) currentFeature // .eGet(currentFeature // .eClass() // .getEStructuralFeature( // JavaImplVariantManagerConstants.ESTRUCTURALFEATURE)); // // EList<Variant> defaultVariants = ((EList) currentFeature // .eGet(JavaImplVariantManager // .getVariantReferenceForDefault(currentFeature // .eClass()))); // // String mappingType = currentFeature // .eClass() // .getName() // .replaceAll( // JavaImplVariantManagerConstants.DEFAULT // + JavaImplVariantManagerConstants.DELIMITER, // ""); // String hashMapKey = mappingType // + JavaImplVariantManagerConstants.DELIMITER + eClass // + JavaImplVariantManagerConstants.DELIMITER // + eStructuralFeature; // defaultsInImplModel.put(hashMapKey, currentFeature); // } // // } // EObject eObj = (EObject) ((IStructuredSelection) viewer.getSelection()) // .toArray()[0]; // EList<EAnnotation> annotations = eObj.eContainingFeature() // .getEAnnotations(); // // for (EAnnotation annotation : annotations) { // String hashMapKey = annotation // .getSource() // + JavaImplVariantManagerConstants.DELIMITER // + eObj.eContainer().eClass().getName() // + JavaImplVariantManagerConstants.DELIMITER // + eObj.eContainingFeature().getName(); // if (defaultsInImplModel.containsKey(hashMapKey)) { // EObject defaultMappingType = defaultsInImplModel.get(hashMapKey); // // EList defaultVariants=(EList)defaultMappingType.eGet(defaultMappingType.eClass().getEStructuralFeature(JavaImplVariantManagerConstants.VARIANT)); // if (defaultVariants.size()>0) { // String declaringMethodKey = (String)((EObject)defaultVariants.get(0)).eGet(((EObject)defaultVariants.get(0)).eClass().getEStructuralFeature(JavaImplVariantManagerConstants.METHOD_NAME)); // // //// IResource resource = iMember.getJavaProject().getResource(); //// JavaMarkerDescriptor markerDescriptor = createJavaMarkerDescriptor(resource, fullyQualifiedName, value, explanation); //// markerDescriptor.setCharStartCharEnd(iMember); //// //// //// BindingKeyResolver resolver = new BindingKeyResolver(declaringMethodKey); //// resolver.parse(); //// resolver.getCompilationUnitDeclaration(); // //// try { //// JavaCore.create(project).findType(Util.getDeclaringTypeSignature(declaringMethodKey)); //// } catch (JavaModelException e) { //// // TODO Auto-generated catch block //// e.printStackTrace(); //// } // // marker = (Marker)Markers.INSTANCE.getMarkers(FSMLEcoreUtil.getFSMLId((EObject)defaultVariants.get(0),null)).get(0); // event.data = new Marker[] { marker}; // // } // // } // } // } @Override public void dragStart(DragSourceEvent event) { // check whether the feature is in the last reconciled model - if not, // this listener will handle it EObject selectedEObject = (EObject) ((IStructuredSelection) viewer.getSelection()) .toArray()[0]; String parentKey = FSMLEcoreUtil.getFSMLId(selectedEObject, null); Model lastReconciledModel = ((ModelContainer) selectedEObject.eResource() .getResourceSet().getResources().get(0).getContents().get(0)) .getLastReconciledModel(); TreeIterator<EObject> allContents = lastReconciledModel.eAllContents(); boolean found = false; while (allContents.hasNext()) { if (parentKey.equals(FSMLEcoreUtil.getFSMLId(allContents.next(), null))) { found = true; break; } } if (!found) { event.doit = true; Image icon = PlatformUI.getWorkbench().getSharedImages().getImage( ISharedImages.IMG_TOOL_FORWARD); double zoom = 1d * 5; // scale to half of the size maintaining // aspect ratio ImageData iconImageData = icon.getImageData().scaledTo( (int) (icon.getBounds().width * zoom), (int) (icon.getBounds().height * zoom)); event.image = new Image(Display.getDefault(), iconImageData); } else { event.doit = false; } } @Override public void dragSetData(DragSourceEvent event) { // TODO Auto-generated method stub // super.dragFinished(event); // PackageExplorerPart view = (PackageExplorerPart)PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().findView("org.eclipse.jdt.ui.PackageExplorer"); // TreeViewer treeViewer = view.getTreeViewer(); // treeViewer.collapseAll(); // treeViewer.addFilter(new ViewerFilter() { // // @Override // public boolean select(Viewer viewer, Object parentElement, Object element) { // // TODO Auto-generated method stub // return true; // } // // }); ArrayList<IMarker> markers = new ArrayList<IMarker>(); List<String> methodLocationNamesForMarkers= new ArrayList<String>(); EObject selectedEObject = (EObject) ((IStructuredSelection) viewer.getSelection()) .toArray()[0]; Model assertedModel = ((ModelContainer)selectedEObject.eResource().getContents().get(0)).getAssertedModel(); TreeIterator<EObject> allContents = assertedModel.eAllContents(); HashMap<String, CompilationUnit> cuCache = new HashMap<String,CompilationUnit>(); HashMap<String, Integer> methodLocations = new HashMap<String, Integer>(); while (allContents.hasNext()){ EObject currentObject = allContents.next(); if (currentObject.eClass().equals(selectedEObject.eClass())){ List<IMarker> markersForCurrentObject = Markers.INSTANCE.getMarkers(FSMLEcoreUtil.getFSMLId(currentObject, null)); if (!markersForCurrentObject.isEmpty()){ markers.addAll(markersForCurrentObject); IResource resource =null; ICompilationUnit cu =null; int markerStartPos; int markerEndPos; for (int i=0;i<markersForCurrentObject.size();i++){ resource = markersForCurrentObject.get(i).getResource(); cu = JavaCore.createCompilationUnitFrom(FileBuffers.getWorkspaceFileAtLocation(resource.getFullPath()));; try { markerStartPos = ((Integer)markersForCurrentObject.get(i) .getAttribute(MarkerDescriptor.ATTRIBUTE_CHAR_START)) .intValue(); markerEndPos = ((Integer) markersForCurrentObject.get(i) .getAttribute(MarkerDescriptor.ATTRIBUTE_CHAR_END)) .intValue(); CompilationUnit astRoot =null; CompilationUnit cuInCache = cuCache.get(resource.getFullPath().toString()); if (cuInCache==null){ ASTParser parser = ASTParser.newParser(AST.JLS3); parser.setSource(cu); parser.setResolveBindings(true); parser.setBindingsRecovery(true); astRoot = (CompilationUnit) parser.createAST(null); cuCache.put(resource.getFullPath().toString(), astRoot); }else { astRoot =cuInCache; } ASTNode astNode = ASTNodeSearchUtil.getAstNode(astRoot, markerStartPos, markerEndPos-markerStartPos); while (astNode!=null && !(astNode instanceof MethodDeclaration)){ astNode = astNode.getParent(); } if (astNode!=null){ String methodKey = ((ResolvedSourceMethod)((MethodDeclaration)astNode).resolveBinding().getJavaElement()).getKey(); methodKey = methodKey.substring(methodKey.indexOf(";.")+2); if (methodLocations.get(methodKey)==null){ methodLocations.put(methodKey,1); } else { methodLocations.put(methodKey,methodLocations.get(methodKey)+1); } methodLocationNamesForMarkers.add(methodKey); } else { methodLocationNamesForMarkers.add("N/A"); } } catch (JavaModelException e) { e.printStackTrace(); } catch (CoreException e) { e.printStackTrace(); } } } } } Set<Entry<String, Integer>> entrySet = methodLocations.entrySet(); ArrayList<Entry<String,Integer>> sortedMethodLocations = new ArrayList<Entry<String,Integer>>(); sortedMethodLocations.addAll(entrySet); Collections.sort(sortedMethodLocations, new Comparator<Entry<String,Integer>>(){ @Override public int compare(Entry<String, Integer> o1, Entry<String, Integer> o2) { if (o1.getValue()>o2.getValue()){ return -1; }else if (o1.getValue()==o2.getValue()){ return 0; }else { return 1; } } } ); //find the context class EObject classEObject = selectedEObject; while (classEObject!=null && classEObject.eClass().getEAnnotation(JavaMappingInterpreter.CONTEXT_CLASS)==null){ classEObject = classEObject.eContainer(); } if (classEObject!=null){ List<IMarker> classEObjectMarker = Markers.INSTANCE.getMarkers(FSMLEcoreUtil.getFSMLId(classEObject, null)); if (classEObjectMarker.size()>0){ IResource resource = classEObjectMarker.get(0).getResource(); ICompilationUnit cu = JavaCore.createCompilationUnitFrom(FileBuffers.getWorkspaceFileAtLocation(resource.getFullPath()));; ASTParser parser = ASTParser.newParser(AST.JLS3); parser.setSource(cu); parser.setResolveBindings(true); parser.setBindingsRecovery(true); CompilationUnit astRoot = (CompilationUnit) parser.createAST(null); for (Entry<String, Integer> entry : sortedMethodLocations) { System.out.println (entry.getKey()+"\t("+entry.getValue()+")"); } for (Entry<String, Integer> entry : sortedMethodLocations) { String targetMethodKey = "L"+astRoot.getPackage().getName().toString().replaceAll("\\.", "\\/")+"/"+resource.getName().replaceAll(resource.getFileExtension(), "").replaceAll("\\.","")+";."+entry.getKey(); ASTNode targetMethod = astRoot.findDeclaringNode(targetMethodKey); if (targetMethod!=null){ try { ResolvedSourceMethod resolvedSourceMethod = ((ResolvedSourceMethod)((MethodDeclaration)targetMethod).resolveBinding().getJavaElement()); ISourceRange sourceRange = resolvedSourceMethod.getSourceRange(); int sourceStart= resolvedSourceMethod.getSource().indexOf("{")+2; IMarker codeLocationAssistMarker = resource.createMarker("fsml code location assist"); codeLocationAssistMarker.setAttribute(MarkerDescriptor.ATTRIBUTE_ID, targetMethodKey); codeLocationAssistMarker.setAttribute(MarkerDescriptor.ATTRIBUTE_CHAR_START, sourceRange.getOffset()+sourceStart); codeLocationAssistMarker.setAttribute(MarkerDescriptor.ATTRIBUTE_CHAR_END,sourceRange.getOffset()+sourceStart); event.data = new Marker[] { (Marker)codeLocationAssistMarker}; } catch (CoreException e) { e.printStackTrace(); } break; } } } } if (event.data ==null){ event.data = new Marker[] {}; } //TODO: create the most common method if can't find any target method?? try { IViewPart showView = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().showView("ca.uwaterloo.gsd.fsml.codeLocationAssist.featureInstancesCodeLocatorView"); if (showView!=null && showView instanceof FeatureInstancesCodeLocatorView){ ((FeatureInstancesCodeLocatorView)showView).showMarker(markers,methodLocationNamesForMarkers); } } catch (PartInitException e) { e.printStackTrace(); } } }