/******************************************************************************* * 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.xmleditor.editors; import java.util.Arrays; 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.runtime.CoreException; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EAnnotation; 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.jface.text.ITextViewer; import org.eclipse.jface.text.contentassist.CompletionProposal; import org.eclipse.jface.text.contentassist.ICompletionProposal; import org.eclipse.jface.text.contentassist.IContentAssistProcessor; import org.eclipse.jface.text.contentassist.IContextInformation; import org.eclipse.jface.text.contentassist.IContextInformationValidator; import org.eclipse.swt.graphics.Image; import org.eclipse.ui.IEditorDescriptor; import org.eclipse.ui.ISharedImages; import org.eclipse.ui.PlatformUI; import org.eclipse.wst.sse.core.StructuredModelManager; import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion; import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel; import ca.uwaterloo.gsd.fsml.codeAssist.FSMLCodeAssistUtil; 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.xmlMappingInterpreter.XMLMappingInterpreter; public class FSMLXMLContentAssistProcessor implements IContentAssistProcessor { @Override public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) { IFile currentFile = (IFile) PlatformUI.getWorkbench() .getActiveWorkbenchWindow().getActivePage().getActiveEditor() .getEditorInput().getAdapter(IFile.class); List<IFile> fsmlModelFiles = FSMLCodeAssistUtil.findModelFile( currentFile.getProject(), FSMLCodeAssistUtil.supportedFrameworks); Vector<ICompletionProposal> proposals = new Vector<ICompletionProposal>(); for (IFile fsmlModelFile : fsmlModelFiles) { if (fsmlModelFile == null || !fsmlModelFile.exists()) { System.err.println("no valid project found"); return new CompletionProposal[0]; } 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(); Queries.INSTANCE.reset(); // register Java mapping interpreter // register XML mapping interpreter XMLMappingInterpreter xmlMappingInterpreter = new XMLMappingInterpreter(); Queries.INSTANCE.registerCustomInterpreter(xmlMappingInterpreter); Queries.INSTANCE .initialize(currentFile.getProject(), assertedModel); // main method call IDOMModel modelForEdit; modelForEdit = (IDOMModel) StructuredModelManager .getModelManager() .getModelForEdit((IStructuredDocument) viewer.getDocument()); ; ((IStructuredDocument) viewer.getDocument()) .getAdapter(IFile.class); IndexedRegion indexedRegion = modelForEdit.getIndexedRegion(offset); Markers.INSTANCE.setProject(currentFile.getProject()); Vector<IMarker> markers = Markers.INSTANCE.getCoveringMarkers( currentFile, offset, indexedRegion.getLength()); HashMap<String, EObject> fsmlId2ModelEObject = new HashMap<String, EObject>(); FSMLEcoreUtil.createFsmlId2EObjectMap(assertedModel, fsmlId2ModelEObject); for (IMarker marker : markers) { EObject eObject; try { eObject = fsmlId2ModelEObject.get(marker .getAttribute(MarkerDescriptor.ATTRIBUTE_ID)); if (eObject != null) { int start = ((Integer)marker.getAttribute(MarkerDescriptor.ATTRIBUTE_CHAR_START)); int end = ((Integer)marker.getAttribute(MarkerDescriptor.ATTRIBUTE_CHAR_END)); xmlMappingInterpreter.associateContext(start, end,eObject); proposals.addAll(createProposals(assertedModel, resource, offset, indexedRegion.getLength(), eObject)); } } catch (CoreException e) { e.printStackTrace(); } } } return proposals.toArray(new FSMLXMLProposal[1]); } private Vector<ICompletionProposal> createProposals(Model model, Resource resource, int offset, int length, EObject eObject) { // content assist Vector<ICompletionProposal> proposals = new Vector<ICompletionProposal>(); EList<EStructuralFeature> allStructuralFeatures = eObject.eClass() .getEAllStructuralFeatures(); 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 = PlatformUI.getWorkbench().getSharedImages() .getImage(ISharedImages.IMG_TOOL_FORWARD); } for (EStructuralFeature structuralFeature : allStructuralFeatures) { String type = ""; if (structuralFeature instanceof EAttribute) { type = "EAttribute"; // calculate the number of instances so cardinality check can be // done later on int numInstances = 0; if ((eObject.eIsSet(structuralFeature)) && !eObject.eGet(structuralFeature).getClass().isArray()) { numInstances = 1; } else if (eObject.eIsSet(structuralFeature)) { numInstances = Arrays.asList(eObject.eGet(structuralFeature)).size(); } if (structuralFeature.getUpperBound() != -1 && numInstances + 1 > structuralFeature.getUpperBound()) { // skip this proposal if cardinaltiy constraint is not met // TODO: problem with feature group continue; } EAnnotation featureGroup = structuralFeature .getEAnnotation(FSMLEcoreUtil.FEATURE_GROUP); if (featureGroup != null) { // feature group if (false) { continue; } } // ASTRewrite rewrite = // ASTRewrite.create(coveringNode.getAST()); String projectName = resource.getURI().fileExtension(); projectName = projectName.substring(0, 1).toUpperCase() + projectName.substring(1); String proposalName = structuralFeature.getName(); if (proposalName.length() > 0) { proposalName = proposalName.toUpperCase().charAt(0) + proposalName.substring(1); // if we have more than one concrete class, we should use // the concreteClass name instead // going with the reference name for now to be consistent // with the metamodel in DSPD // proposalName = concreteClass.getName(); } ICompletionProposal linkedCorrectionProposal = new FSMLXMLProposal( "FSML: " + proposalName + "(" + eObject.eClass().getName() + ", " + projectName + "-Attribute)", eObject,null,structuralFeature,resource,proposalImage); proposals.add(linkedCorrectionProposal); } else if (structuralFeature instanceof EReference) { type = "EReference"; Collection<EClass> concreteClasses = FSMLEcoreUtil .getSubclassesOfEClass(((EReference) structuralFeature) .getEReferenceType(), true); for (EClass concreteClass : concreteClasses) { // calculate the number of instances so cardinality check // can be done later on EList<EObject> contents = eObject.eContents(); int numInstances = 0; for (EObject object : contents) { if (object.eClass().getName().equals( concreteClass.getName())) { numInstances++; } } if (structuralFeature.getUpperBound() != -1 && numInstances + 1 > structuralFeature .getUpperBound()) { // skip this proposal if cardinaltiy constraint is not // met // TODO: problem with feature group continue; } EAnnotation featureGroup = structuralFeature .getEAnnotation(FSMLEcoreUtil.FEATURE_GROUP); if (featureGroup != null) { // feature group if (false) { continue; } } // ASTRewrite rewrite = // ASTRewrite.create(coveringNode.getAST()); String projectName = resource.getURI().fileExtension(); projectName = projectName.substring(0, 1).toUpperCase() + projectName.substring(1); String proposalName = structuralFeature.getName(); if (proposalName.length() > 0) { proposalName = proposalName.toUpperCase().charAt(0) + proposalName.substring(1); // if we have more than one concrete class, we should // use the concreteClass name instead // going with the reference name for now to be // consistent with the metamodel in DSPD // proposalName = concreteClass.getName(); } ICompletionProposal linkedCorrectionProposal = new FSMLXMLProposal( "FSML: " + proposalName + "(" + eObject.eClass().getName() + ", " + projectName + ")", eObject,concreteClass,structuralFeature,resource,proposalImage); proposals.add(linkedCorrectionProposal); } } } // if (proposals.size()==1){ // FSMLProposal onlyProposal = (FSMLProposal)proposals.get(0); // try { // onlyProposal.performChange(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor(), // jc.getDocument()); // } catch (CoreException e) { // e.printStackTrace(); // } // proposals.clear(); // } return proposals; } @Override public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) { // TODO Auto-generated method stub return null; } @Override public char[] getCompletionProposalAutoActivationCharacters() { // TODO Auto-generated method stub return null; } @Override public char[] getContextInformationAutoActivationCharacters() { // TODO Auto-generated method stub return null; } @Override public IContextInformationValidator getContextInformationValidator() { // TODO Auto-generated method stub return null; } @Override public String getErrorMessage() { // TODO Auto-generated method stub return null; } }