Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

VIATRA/Query/DeveloperDocumentation/Model connectors

For navigating from results of the QueryExplorer to an appropriate location in the editor which presents the particular model elements one must double-click the result in the QueryExplorer. If the presenting editor is not a default-EMF editor model connectors are needed. As an example consider textual models created with an editor generated with EMFText or Xtext. The following process demonstrates a model connector for EMFText-based textual models.

Provide an IAdapterFactory

The model connector concept is lightweight and seemlessly integrates as an adapter. Thus, you have to register a new IAdapterFactory which creates the connector. In the following snippet you see the part of the plugin.xml registering the adapter factory:

   <extension
        point="org.eclipse.core.runtime.adapters">
      <factory
           adaptableType="org.eclipse.ui.texteditor.ITextEditor"
           class="org.emftext.incquery.modelconnector.ModelConnectorAdapterFactoryForEMFTextEditors">
         <adapter
              type="org.eclipse.incquery.runtime.api.IModelConnector">
         </adapter>
      </factory>
   </extension>

The adaptableType property specifies the kind of editor being supported by this adapter factory (and thus it is supported by the model connector). Determine the adapter factory with the class property. The children adapter specifies the returning type of the adapter factory. This is the type which your editor is adapted to. In the case of IncQuery the type must always refer to org.eclipse.incquery.runtime.api.IModelConnector.

Next step is to implement the adapter factory:

  public class ModelConnectorAdapterFactoryForEMFTextEditors implements IAdapterFactory {
 
    @Override
    public Object getAdapter(Object adaptableObject, Class adapterType) {
        if(adapterType.equals(IModelConnector.class) && adaptableObject instanceof ITextEditor){
           if(EMFTextAccessProxy.isAccessibleWith(adaptableObject.getClass(), IEditor.class)){
             IEditor emftextEditor = (IEditor) EMFTextAccessProxy.get(adaptableObject, IEditor.class);
             return new EMFTextModelConnector((ITextEditor) adaptableObject, emftextEditor);
           }
        }
        return null;
    }
 
    @Override
    public Class[] getAdapterList() {
        return new Class[] { IModelConnector.class };
    }
  }

Implement IModelConnector

The last step is to provide the implementation of the IModelConnector interface. In the following you see the model connector which supports navigation to textual model elements in EMFText-based editors:

        public class EMFTextModelConnector extends EMFModelConnector {
 
        private IEditor emftextEditor;
        private ITextEditor textEditor;
 
        public EMFTextModelConnector(ITextEditor textEditor, IEditor emftextEditor) {
                super(textEditor);
                this.emftextEditor = emftextEditor;
                this.textEditor = textEditor;
        }
 
        @Override
        public Notifier getNotifier(IModelConnectorTypeEnum modelConnectorTypeEnum) {
                Notifier result = null;
                switch (modelConnectorTypeEnum) {
                case RESOURCE:
                    result = emftextEditor.getResource();
                    break;
 
                case RESOURCESET:
                    result = emftextEditor.getResource().getResourceSet();
 
                }
                return result;
        }
 
        @Override
        public void showLocation(Object[] locationObjects) {
                IResource emftextResource = emftextEditor.getResource();
                ILocationMap locationMap = emftextResource.getLocationMap();
                if (locationObjects.length > 0 && objectsAreEObjects(locationObjects)) {
                    // selects the first object in the array since text editors can only select one
                    EObject eObject = (EObject) locationObjects[0];
                    int start = locationMap.getCharStart(eObject);
                    int end = locationMap.getCharEnd(eObject);
                    textEditor.selectAndReveal(start, end - start + 1);
                }
        }
 
        private boolean objectsAreEObjects(Object[] locationObjects) {
                if(locationObjects == null){
                    return false;
                }
                for (Object object : locationObjects) {
                    if(!(object instanceof EObject)){
                        return false;
                    }
                }
                return true;
        }
    }

The above example can be found in the github repository for IncQuery addons: https://github.com/istvanrath/EMF-IncQuery-Addons/tree/master/emftext

Back to the top