package org.eclipse.gmf.tooling.runtime.parsers; import java.lang.reflect.InvocationTargetException; import java.util.Collection; import java.util.HashMap; import java.util.Map; import org.eclipse.emf.common.notify.AdapterFactory; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EClassifier; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.util.QueryDelegate; import org.eclipse.emf.edit.provider.IItemLabelProvider; import org.eclipse.gmf.runtime.diagram.core.listener.NotificationListener; import org.eclipse.gmf.tooling.runtime.ocl.tracker.OclTracker.Registrator; import org.eclipse.ocl.ParserException; import org.eclipse.ocl.common.OCLConstants; import org.eclipse.ocl.ecore.EcoreEnvironmentFactory; import org.eclipse.ocl.ecore.OCL; import org.eclipse.ocl.ecore.OCL.Helper; import org.eclipse.ocl.ecore.OCLExpression; import org.eclipse.ocl.ecore.delegate.OCLQueryDelegateFactory; public class OclChoiceParser extends ChoiceParserBase { private static final String ITEM_PARAM_NAME = "_item"; private static final String FILTER_ID = "OCLChoiceParser"; private final OCL myOcl; private final OCLExpression myItemsOclExpression; private final QueryDelegate myShowOclQuery; private final AdapterFactory myAdapterFactory; private Tracker myTracker; public OclChoiceParser(EStructuralFeature feature, String itemsExpression, String showExpression, AdapterFactory adapterFactory) { super(feature); myAdapterFactory = adapterFactory; myOcl = OCL.newInstance(new EcoreEnvironmentFactory()); EClass contextClass = feature.getEContainingClass(); Helper helper = myOcl.createOCLHelper(); helper.setContext(contextClass); try { myItemsOclExpression = helper.createQuery(itemsExpression); } catch (ParserException e) { throw new RuntimeException(e); } if (showExpression == null) { myShowOclQuery = null; } else { Map<String, EClassifier> parameters = new HashMap<String, EClassifier>(); parameters.put(ITEM_PARAM_NAME, getFeature().getEType()); myShowOclQuery = new OCLQueryDelegateFactory(OCLConstants.OCL_DELEGATE_URI).createQueryDelegate(contextClass, parameters, showExpression); } myTracker = new Tracker(); } @SuppressWarnings("unchecked") @Override protected Collection<Object> getItems(EObject element) { return (Collection<Object>) myOcl.evaluate(element, myItemsOclExpression); } @Override protected String getEditChoice(EObject element, Object item) { Object result; if (item == null) { result = null; } else if (myShowOclQuery == null) { result = item; } else { Map<String, Object> arguments = new HashMap<String, Object>(); arguments.put(ITEM_PARAM_NAME, item); try { result = myShowOclQuery.execute(element, arguments); } catch (InvocationTargetException e) { throw new RuntimeException(e); } } if (result == null) { return getNullItemEditChoice(); } else if (result instanceof EObject) { EObject eResult = (EObject) result; myTracker.setTracked(eResult); return ((IItemLabelProvider) myAdapterFactory.adapt(eResult, IItemLabelProvider.class)).getText(eResult); } else { return result.toString(); } } protected String getNullItemEditChoice() { return ""; } @Override public boolean isAffectingEvent(Object event, int flags) { return myTracker.isAffectingEvent(event, flags) || super.isAffectingEvent(event, flags); } public void installListeners(NotificationListener listener, Registrator oclRegistrator) { myTracker.start(listener, oclRegistrator); } public void uninstallListeners() { myTracker.stop(); } private static class Tracker { private Registrator myOclRegistrator; private NotificationListener myListener; private EObject myTracked; private boolean myTracking = false; public void start(NotificationListener listener, Registrator oclRegistrator) { myOclRegistrator = oclRegistrator; myListener = listener; myTracking = true; registerListener(); } public void stop() { unregisterListener(); myTracking = false; } public void setTracked(EObject tracked) { if (tracked != myTracked) { unregisterListener(); myTracked = tracked; registerListener(); } } private void registerListener() { if (!myTracking || myTracked == null) { return; } myOclRegistrator.registerListener(FILTER_ID, myListener, myTracked); } private void unregisterListener() { if (!myTracking || myTracked == null) { return; } myOclRegistrator.unregisterListener(FILTER_ID); } public boolean isAffectingEvent(Object event, int flags) { if (event instanceof Notification) { Notification notification = (Notification) event; if (notification.getNotifier() == myTracked) { return true; } } return false; } } }