/******************************************************************************* * Copyright (c) 2005, 2012 IBM Corporation and others. * 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: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.bpel.ui.util; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Vector; import javax.xml.namespace.QName; import org.eclipse.bpel.common.extension.model.ExtensionMap; import org.eclipse.bpel.common.ui.ImageUtils; import org.eclipse.bpel.common.ui.details.viewers.ComboViewer; import org.eclipse.bpel.common.ui.details.widgets.DecoratedLabel; import org.eclipse.bpel.common.ui.markers.ModelMarkerUtil; import org.eclipse.bpel.model.BPELFactory; import org.eclipse.bpel.model.BPELPackage; import org.eclipse.bpel.model.Catch; import org.eclipse.bpel.model.CompensateScope; import org.eclipse.bpel.model.CorrelationSet; import org.eclipse.bpel.model.CorrelationSets; import org.eclipse.bpel.model.Flow; import org.eclipse.bpel.model.ForEach; import org.eclipse.bpel.model.Invoke; import org.eclipse.bpel.model.OnEvent; import org.eclipse.bpel.model.PartnerLink; import org.eclipse.bpel.model.PartnerLinks; import org.eclipse.bpel.model.Process; import org.eclipse.bpel.model.Scope; import org.eclipse.bpel.model.Sequence; import org.eclipse.bpel.model.Variable; import org.eclipse.bpel.model.Variables; import org.eclipse.bpel.model.adapters.AdapterRegistry; import org.eclipse.bpel.model.messageproperties.MessagepropertiesPackage; import org.eclipse.bpel.model.messageproperties.PropertyAlias; import org.eclipse.bpel.model.partnerlinktype.PartnerlinktypePackage; import org.eclipse.bpel.model.util.BPELUtils; import org.eclipse.bpel.names.NCNameWordDetector; import org.eclipse.bpel.runtimes.IBPELModuleFacetConstants; import org.eclipse.bpel.ui.BPELEditor; import org.eclipse.bpel.ui.BPELUIPlugin; import org.eclipse.bpel.ui.IBPELUIConstants; import org.eclipse.bpel.ui.Messages; import org.eclipse.bpel.ui.Policy; import org.eclipse.bpel.ui.adapters.BPELUIAdapterFactory; import org.eclipse.bpel.ui.adapters.BPELUIExtensionAdapterFactory; import org.eclipse.bpel.ui.adapters.BPELUIMessagePropertiesAdapterFactory; import org.eclipse.bpel.ui.adapters.BPELUIPartnerLinkTypeAdapterFactory; import org.eclipse.bpel.ui.adapters.BPELUIWSDLAdapterFactory; import org.eclipse.bpel.ui.adapters.BPELUIWSILAdapterFactory; import org.eclipse.bpel.ui.adapters.BPELUIXSDAdapterFactory; import org.eclipse.bpel.ui.adapters.IContainer; import org.eclipse.bpel.ui.adapters.ILabeledElement; import org.eclipse.bpel.ui.adapters.INamedElement; import org.eclipse.bpel.ui.bpelactions.AbstractBPELAction; import org.eclipse.bpel.ui.dialogs.NamespaceMappingDialog; import org.eclipse.bpel.ui.editparts.BPELEditPart; import org.eclipse.bpel.ui.editparts.FlowEditPart; import org.eclipse.bpel.ui.editparts.InvokeEditPart; import org.eclipse.bpel.ui.editparts.LinkEditPart; import org.eclipse.bpel.ui.editparts.ScopeEditPart; import org.eclipse.bpel.ui.editparts.StartNodeEditPart; import org.eclipse.bpel.ui.editparts.borders.GradientBorder; import org.eclipse.bpel.ui.editparts.util.OverlayCompositeImageDescriptor; import org.eclipse.bpel.ui.extensions.ActionDescriptor; import org.eclipse.bpel.ui.extensions.BPELUIRegistry; import org.eclipse.bpel.ui.uiextensionmodel.ActivityExtension; import org.eclipse.bpel.ui.uiextensionmodel.UiextensionmodelPackage; import org.eclipse.bpel.validator.EmfModelQuery; import org.eclipse.bpel.wsil.model.inspection.InspectionPackage; 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.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.geometry.Rectangle; import org.eclipse.emf.common.notify.AdapterFactory; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.common.util.BasicEList; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.common.util.TreeIterator; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EPackage; 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.gef.AccessibleEditPart; import org.eclipse.gef.EditDomain; import org.eclipse.gef.EditPart; import org.eclipse.gef.EditPartViewer; import org.eclipse.gef.GraphicalEditPart; import org.eclipse.gef.GraphicalViewer; import org.eclipse.gef.Tool; import org.eclipse.jface.dialogs.IInputValidator; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.window.Window; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.accessibility.ACC; import org.eclipse.swt.accessibility.AccessibleControlEvent; import org.eclipse.swt.accessibility.AccessibleEvent; import org.eclipse.swt.custom.CLabel; import org.eclipse.swt.events.KeyAdapter; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseListener; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.events.PaintListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.ImageData; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableItem; import org.eclipse.swt.widgets.Widget; import org.eclipse.ui.PartInitException; import org.eclipse.ui.ide.IDE; import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetWidgetFactory; import org.eclipse.wst.common.componentcore.ComponentCore; import org.eclipse.wst.common.componentcore.ModuleCoreNature; import org.eclipse.wst.common.componentcore.resources.IVirtualComponent; import org.eclipse.wst.common.project.facet.core.IFacetedProject; import org.eclipse.wst.common.project.facet.core.IProjectFacet; import org.eclipse.wst.common.project.facet.core.IProjectFacetVersion; import org.eclipse.wst.common.project.facet.core.ProjectFacetsManager; import org.eclipse.wst.wsdl.Definition; import org.eclipse.wst.wsdl.Fault; import org.eclipse.wst.wsdl.Input; import org.eclipse.wst.wsdl.Message; import org.eclipse.wst.wsdl.Operation; import org.eclipse.wst.wsdl.Output; import org.eclipse.wst.wsdl.PortType; import org.eclipse.wst.wsdl.WSDLPackage; import org.eclipse.wst.wsdl.util.WSDLResourceImpl; import org.eclipse.xsd.XSDAttributeDeclaration; import org.eclipse.xsd.XSDElementDeclaration; import org.eclipse.xsd.XSDPackage; /** * BPELUtil is a place to put *static* helper methods for the BPEL editor. * * Note that helpers which have specifically to do with accessing model objects are * usually found in the ModelHelper class. */ public class BPELUtil { private static final Variable[] EMPTY_VARIABLE_ARRAY = new Variable[0]; private static final PartnerLink[] EMPTY_PARTNERLINK_ARRAY = new PartnerLink[0]; private static final CorrelationSet[] EMPTY_CORRELATIONSET_ARRAY = new CorrelationSet[0]; /** * This global variable stores the path of the last WSDL file selected with * a WorkbenchFileSelectionDialog. */ public static IPath lastWSDLFilePath = null; /** * Global variable storing the path of the last BPEL file selected */ public static IPath lastBPELFilePath = null; /** * Global variable storing the path of the last XSD file selected */ public static IPath lastXSDFilePath; static { AdapterRegistry.INSTANCE.registerAdapterFactory( BPELPackage.eINSTANCE, BPELUIAdapterFactory.getInstance()); AdapterRegistry.INSTANCE.registerAdapterFactory( WSDLPackage.eINSTANCE, BPELUIWSDLAdapterFactory.getInstance()); AdapterRegistry.INSTANCE.registerAdapterFactory( PartnerlinktypePackage.eINSTANCE, BPELUIPartnerLinkTypeAdapterFactory.getInstance()); AdapterRegistry.INSTANCE.registerAdapterFactory( XSDPackage.eINSTANCE, BPELUIXSDAdapterFactory.getInstance()); AdapterRegistry.INSTANCE.registerAdapterFactory( MessagepropertiesPackage.eINSTANCE, BPELUIMessagePropertiesAdapterFactory.getInstance()); AdapterRegistry.INSTANCE.registerAdapterFactory( UiextensionmodelPackage.eINSTANCE, BPELUIExtensionAdapterFactory.getInstance()); AdapterRegistry.INSTANCE.registerAdapterFactory( InspectionPackage.eINSTANCE, BPELUIWSILAdapterFactory.getInstance() ); } /** * Register adapter factory for the given EClass. * * @param key * @param factory */ public static void registerAdapterFactory(EClass key, AdapterFactory factory) { AdapterRegistry.INSTANCE.registerAdapterFactory(key,factory); } public static void registerAdapterFactory(EPackage key, AdapterFactory factory) { AdapterRegistry.INSTANCE.registerAdapterFactory(key, factory); } static Class<?> adapterInterface ( Object type ) { if (type instanceof Class) { return (Class) type; } if (type instanceof String) { try { return Class.forName((String)type); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } } throw new RuntimeException("Adapter type " + type + " is not understood."); //$NON-NLS-1$ //$NON-NLS-2$ } /** * @param <T> * @param target * @param clazz * @return the adapted interface or object */ public static <T extends Object> T adapt ( Object target, Class<T> clazz) { return AdapterRegistry.INSTANCE.adapt(target, clazz); } /** * This method tries the registered adapter factories one by one, returning * the first non-null result it gets. If none of the factories can adapt * the result, it returns null. * @param target target object * @param type type of the adapter to find * @return the adapter for the target. */ public static Object adapt (Object target, Object type) { return AdapterRegistry.INSTANCE.adapt(target, type); } /** * Create an adapter for the given target of the given type. * In addition, pass a context object to the adapter(s) of the target. * * The idea is that some adapters can be stateful and depend not only * on the objects that they wrap, but also on some other context that is needed * to completely and correctly implement the interface for which the adaptor is * needed. * * Adapters that are stateless, should ignore any notifications sent to them. * * @param target the target object * @param type the type it wants to adapt to * @param context the context object * * @return the adapter */ public static Object adapt (Object target, Object type, Object context) { return AdapterRegistry.INSTANCE.adapt(target, type,context); } /** * Returns the effective EClass for a custom activity (action). */ public static EClass getEClassFor(Object target) { if (target instanceof Invoke) { ActionDescriptor[] descriptors = BPELUIRegistry.getInstance().getActionDescriptors(); for( ActionDescriptor descriptor : descriptors ) { AbstractBPELAction action = descriptor.getAction(); if (action.isInstanceOf(target)) { return action.getModelType(); } } } if (!(target instanceof EObject)) { return null; } return ((EObject)target).eClass(); } public static boolean isCustomActivity(Object target) { if (target instanceof Invoke) { ActionDescriptor[] descriptors = BPELUIRegistry.getInstance().getActionDescriptors(); for( ActionDescriptor descriptor : descriptors ) { AbstractBPELAction action = descriptor.getAction(); if (action.getModelType() == BPELPackage.eINSTANCE.getInvoke()) continue; if (action.isInstanceOf(target)) { return true; } } } return false; } public static boolean isBPELAction(EClass target) { ActionDescriptor[] descriptors = BPELUIRegistry.getInstance().getActionDescriptors(); for( ActionDescriptor descriptor : descriptors ) { AbstractBPELAction action = descriptor.getAction(); if (action.getModelType() == target) { return true; } } return false; } /** * Creates a new instance of clazz using the EFactory of the EPackage clazz belongs to. */ public static EObject createEObject(EClass clazz) { return clazz.getEPackage().getEFactoryInstance().create(clazz); } // This is a hack to bundle the result of a cloneSubtree with enough state to undo/redo // the extension map changes it caused. public static class CloneResult { /** The result of the clone */ public EObject targetRoot; Map<EObject,EObject> targetMap; Map<EObject,EObject> targetMapAdditions = new HashMap<EObject,EObject>(); /** * Undo ... ? */ public void undo() { for (EObject next : this.targetMapAdditions.keySet()) { this.targetMap.remove(next); } } /** * Redo ... ? */ public void redo() { for (EObject key : this.targetMapAdditions.keySet()) { this.targetMap.put(key, this.targetMapAdditions.get(key)); } } } // This helper is used by the cloneSubtree() method. protected static void cloneSubtreeHelper (EObject source, Map<EObject,EObject> sourceMap, Map<EObject,EObject> targetMap, Map<EObject,EObject> copyMap, CloneResult result) { EObject targetObject = createEObject(source.eClass()); copyMap.put(source, targetObject); if (sourceMap != null && sourceMap.containsKey(source)) { EObject sourceExtension = sourceMap.get(source); EObject targetExtension = createEObject(sourceExtension.eClass()); copyMap.put(sourceExtension, targetExtension); for (TreeIterator<?> it2 = sourceExtension.eAllContents(); it2.hasNext(); ) { EObject source2 = (EObject)it2.next(); EObject target2 = createEObject(source2.eClass()); copyMap.put(source2, target2); } targetMap.put(targetObject, targetExtension); result.targetMapAdditions.put(targetObject, targetExtension); } } /** * Clones an EObject and all EObjects contained directly or indirectly within it. All * cloned objects possessing an extension in the sourceMap will also have their extensions * cloned into the targetMap. Containment references and other references to any of the * cloned object(s) will be fixed up to point into the target objects. Any references to * non-cloned objects will be copied as-is in the cloned objects. * * NOTE: This method relies on BPELUtil.createEObject() knowing how to create new instances * of the EClasses of all copied objects (i.e. objectFactories must contain the necessary * EFactory instances for everything copied by this method). * * @param source The root of the source subtree to clone. * @param sourceMap The extension map containing source extensions of cloned objects. * @param targetMap The extension map in which cloned extensions should be recorded. * @return a CloneResult containing the root of the target subtree, which can be used * for undo/redo. */ @SuppressWarnings("nls") public static CloneResult cloneSubtree (EObject source, Map<EObject,EObject> sourceMap, Map<EObject,EObject> targetMap) { HashMap<EObject,EObject> copyMap = new HashMap<EObject,EObject>(); CloneResult result = new CloneResult(); result.targetMap = targetMap; // (1) Create target objects for each EObject in the containment subtree of source. // If the source object has an extension in sourceMap, create copies of the extension // and its containment tree as well. // NOTE: we can NOT just recursively call cloneSubtree for the extension, it wouldn't // work with fixing up references. We have to iterate its eAllContents also here. cloneSubtreeHelper(source, sourceMap, targetMap, copyMap, result); for (TreeIterator<?> it = source.eAllContents(); it.hasNext(); ) { EObject sourceObject = (EObject)it.next(); cloneSubtreeHelper(sourceObject, sourceMap, targetMap, copyMap, result); } // (2) Copy the features from each cloned source object to the corresponding target // object. As we copy, we replace any references to cloned source objects with // references to the corresponding target objects--but references to non-cloned // objects are copied as-is. for (Map.Entry<EObject,EObject> entry : copyMap.entrySet() ) { EObject sourceObject = entry.getKey(); EObject targetObject = entry.getValue(); if (sourceObject.eClass() != targetObject.eClass()) { throw new IllegalStateException("Source and target objects are not of the same class after cloning."); } if (Policy.DEBUG) { System.out.println("copying a "+sourceObject.eClass().getName()); //$NON-NLS-1$ } for ( EStructuralFeature feature : sourceObject.eClass().getEAllStructuralFeatures()) { // special cases first. if (!feature.isChangeable()) { if (Policy.DEBUG) System.out.println(" *** skipping unchangeable feature "+feature); //$NON-NLS-1$ continue; } if (feature.isUnsettable() && !targetObject.eIsSet(feature)) { if (Policy.DEBUG) System.out.println(" unsetting feature "+feature.getName()); //$NON-NLS-1$ targetObject.eUnset(feature); continue; } Object value = sourceObject.eGet(feature); boolean treatAsReference = (feature instanceof EReference); if (treatAsReference) { if (feature.isMany()) { // list of references. EList<Object> newValues = new BasicEList<Object>(); if (Policy.DEBUG) System.out.println(" copying multi-reference feature "+feature.getName()+":"); //$NON-NLS-1$ //$NON-NLS-2$ for (Iterator<?> it3 = ((Collection)value).iterator(); it3.hasNext(); ) { Object oldValue = it3.next(); Object newValue = (oldValue==null ? null : copyMap.get(oldValue)); if (newValue == null) { newValue = oldValue; } if (Policy.DEBUG) System.out.println("+ (oldValue="+oldValue+" newValue="+newValue+")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ newValues.add(newValue); } targetObject.eSet(feature, newValues); } else { // single reference. Object newValue = (value==null? null : copyMap.get(value)); if (newValue == null) { newValue = value; } if (Policy.DEBUG) System.out.println(" copying reference feature "+feature.getName() //$NON-NLS-1$ +" (value="+value+" newValue="+newValue+")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ targetObject.eSet(feature, newValue); } } else { /** In case of a DOM Node and the "element" feature, we simply clone the result */ if (value instanceof org.w3c.dom.Node && "element".equals(feature.getName())) { org.w3c.dom.Node e = (org.w3c.dom.Node)value; value = e.cloneNode(true); } // non-reference attribute. just copy the value if (Policy.DEBUG) System.out.println(" copying attr feature "+feature.getName()+" (value="+value+")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ targetObject.eSet(feature, value); } } } result.targetRoot = copyMap.get(source); return result; } /** * Convenience formatting methods. */ public static String formatString(String format, String arg1) { return MessageFormat.format(format, new Object[] { arg1 }); } public static String formatString(String format, String arg1, String arg2) { return MessageFormat.format(format, new Object[] { arg1, arg2 }); } /** * strips out invalid characters to conform to QName specs. * If the resulting name is null, returns "bpel" as a valid QName * to guarantee that something valid is returned. * * TODO: This has to be a valid NCName ... * * @param str * * @return */ public static String generateValidName(String str) { StringBuilder result = new StringBuilder(""); //$NON-NLS-1$ if (str != null) { for(char ch : str.trim().toCharArray()) { int destLength = result.length(); if (((destLength == 0) && (Character.isLetter(ch) || ch == '_')) || ((destLength > 0) && Character.isJavaIdentifierPart(ch))) { result.append(ch); } } } if (result.length() == 0) result.append(IBPELUIConstants.EXTENSION_BPEL); return result.toString(); } /** * Helper that traverses the IContainer hierarchy of the given modelObject in depth * first fashion and applies the given visitor to each node. * * DO NOT USE THIS for anything that must see "all" model objects (including implicit * sequences, for example). Use TreeIterator modelObject.eAllContents() for that. */ public static void visitModelDepthFirst(Object modelObject, IModelVisitor visitor) { if (visitor.visit(modelObject)) { IContainer container = BPELUtil.adapt(modelObject, IContainer.class); if (container != null) { for (Iterator it = container.getChildren(modelObject).iterator(); it.hasNext(); ) { visitModelDepthFirst(it.next(), visitor); } } // TODO: Make this go away if (modelObject instanceof Flow) { // Hack: also visit the links of a flow! Flow flow = (Flow)modelObject; for (Iterator it = FlowLinkUtil.getFlowLinks(flow).iterator(); it.hasNext(); ) { visitModelDepthFirst(it.next(), visitor); } } } } private static class NameUnusedVisitor implements IModelVisitor { private boolean unused = true; private final String candidateName; private final Collection<EObject> ignoreObjects; NameUnusedVisitor(String candidateName, Collection<EObject> ignoreObjects) { this.candidateName = candidateName; if (ignoreObjects == null) ignoreObjects = Collections.emptySet(); this.ignoreObjects = ignoreObjects; } @Override public boolean visit(Object child) { if (!this.ignoreObjects.contains(child)) { INamedElement namedElement = BPELUtil.adapt(child, INamedElement.class); if (namedElement != null) { String name = namedElement.getName(child); if ((name != null) && (name.compareToIgnoreCase(this.candidateName) == 0)) this.unused = false; } } return true;//unused; } public boolean isUnused() { return this.unused; } } /** * checks if a name is available for use within the given process (i.e. if this name * were added within the modelRoot, would it be unique). */ public static boolean isNameUnused(EObject modelRoot, String candidateName, Collection ignoreObjects) { NameUnusedVisitor visitor = new NameUnusedVisitor(candidateName, ignoreObjects); for (TreeIterator<EObject> it = modelRoot.eAllContents(); it.hasNext(); ) { visitor.visit(it.next()); if (visitor.isUnused() == false) return false; } return true; } /** * return a mangled name (based on the given hint) which is unique in the given process. */ public static String getUniqueModelName(EObject context, String hint, Collection ignoreObjects) { return getUniqueModelName2(context, hint, ignoreObjects); } /** * return a mangled name (based on the given hint) which is unique in the given WSDL definition. */ public static String getUniqueModelName (Definition definition, String hint, Collection ignoreObjects) { return getUniqueModelName2(definition, hint, ignoreObjects); } protected static String getUniqueModelName2 (EObject modelRoot, String hint, Collection ignoreObjects) { // first try it exactly as hinted. String result = BPELUtil.generateValidName((hint==null)?"":hint.trim()); //$NON-NLS-1$ if (isNameUnused(modelRoot, result, ignoreObjects)) return result; // go back to the first non-digit int digitPos = result.length()-1; while (digitPos >= 0 && Character.isDigit(result.charAt(digitPos))) digitPos--; digitPos++; // move back to the digit String nameWithoutNum = result.substring(0, digitPos); // try increasing numbers until one is accepted. for (int num = 1; ; num++) { result = nameWithoutNum+String.valueOf(num); if (isNameUnused(modelRoot, result, ignoreObjects)) return result; } } public static String generateUniqueModelName (EObject context, String hint, EObject model) { if (hint == null || "".equals(hint)) { //$NON-NLS-1$ ILabeledElement element = BPELUtil.adapt(model, ILabeledElement.class); hint = (element != null) ? element.getTypeLabel(model) : ""; //$NON-NLS-1$ } return BPELUtil.getUniqueModelName(context, hint, Collections.singletonList(model)); } public static String getFilenameFromUri(String uri) { if (uri == null) return Messages.BPELUtil__unknown_URI__54; // Hack. Why aren't we just using URI objects? int idx = Math.max(uri.lastIndexOf("/"), uri.lastIndexOf("\\")); //$NON-NLS-1$ //$NON-NLS-2$ return (idx >= 0)? uri.substring(idx+1) : uri; } /** * Converts the first letter of the target String to upper case. * @param target * @return the name with the first letter uppercased. */ public static String upperCaseFirstLetter (String target) { if (target.length() < 1) { return target; } StringBuilder buf = new StringBuilder (target.length()); buf.append(target.substring(0, 1).toUpperCase()); buf.append(target.substring(1, target.length())); return buf.toString(); } /** * Converts the first letter of the target String to lower case. */ public static String lowerCaseFirstLetter(String target) { if (target.length() < 1) { return target; } StringBuffer buf = new StringBuffer(target.length()); buf.append(target.substring(0, 1).toLowerCase()); buf.append(target.substring(1, target.length())); return buf.toString(); } /** * Returns all of the PropertyAlias objects from WSDL files in the same ResourceSet as * the resource containing messageType, which are aliases for messageType. */ public static List<PropertyAlias> getPropertyAliasesForMessageType(Message messageType) { List<PropertyAlias> aliases = new ArrayList<PropertyAlias>(); Resource resource = messageType.eResource(); if (resource == null) { return aliases; } ResourceSet resourceSet = resource.getResourceSet(); for (Iterator<Resource> it = resourceSet.getResources().iterator(); it.hasNext(); ) { resource = it.next(); // TODO: this is a hack. Why is there no WSDLResource interface?? if (resource instanceof WSDLResourceImpl) { for (TreeIterator<EObject> treeIt = resource.getAllContents(); treeIt.hasNext(); ) { EObject object = treeIt.next(); if (object instanceof PropertyAlias) { PropertyAlias alias = (PropertyAlias)object; if (messageType.equals(alias.getMessageType())) aliases.add(alias); } } } } return aliases; } // Creates an implicit sequence with a name that is unique in the editor's process. // Note that an ActivityExtension is created and inserted in the extension map, // but the implicit sequence itself should be inserted in the model by the caller. public static Sequence createImplicitSequence (Process process, ExtensionMap extensionMap) { Sequence impSeq = BPELFactory.eINSTANCE.createSequence(); ModelHelper.createExtensionIfNecessary(extensionMap, impSeq); Collection ignoreObjects = Collections.singletonList(impSeq); if (ModelHelper.isSpecCompliant(process)) { impSeq.setName(getUniqueModelName(process, Messages.BPELUtil_Sequence_1, ignoreObjects)); } else { impSeq.setName(getUniqueModelName(process, Messages.BPELUtil_HiddenSequence_2, ignoreObjects)); ((ActivityExtension)ModelHelper.getExtension(impSeq)).setImplicit(true); } // TODO: also give sequence a unique ID marked as implicit! return impSeq; } public static TreeIterator nodeAndAllContents(final EObject node) { final TreeIterator<EObject> allContents = node.eAllContents(); return new TreeIterator() { boolean didNode = false; @Override public void prune() { // TODO: This won't work when calling on the first item. if (!this.didNode) throw new IllegalStateException(); allContents.prune(); } @Override public boolean hasNext() { if (this.didNode) return allContents.hasNext(); return node != null; } @Override public Object next() { if (this.didNode) return allContents.next(); this.didNode = true; return node; } @Override public void remove() { // This won't work when calling on the first item. if (!this.didNode) throw new IllegalStateException(); allContents.remove(); } }; } private static class RefreshActionVisitor implements IModelVisitor { private final GraphicalViewer viewer; public RefreshActionVisitor(GraphicalViewer viewer) { this.viewer = viewer; } @Override public boolean visit(Object child) { EditPart ep = (EditPart) this.viewer.getEditPartRegistry().get(child); if (ep != null && ep instanceof BPELEditPart) { IFigure fig = ((BPELEditPart)ep).getContentPane(); if (fig != null) { ((BPELEditPart)ep).regenerateVisuals(); ep.refresh(); } } if(ep instanceof LinkEditPart){ ep.refresh(); } return true;//unused; } } /** * refreshes all the editparts of the process. Useful for changing layouts etc */ public static void regenerateVisuals(Process process, GraphicalViewer viewer) { RefreshActionVisitor visitor = new RefreshActionVisitor(viewer); visitModelDepthFirst(process, visitor); return; } /** * The policy for whether a BPELEditPart's edges should be hilighted or not. This one defers * to the active tool if it is an IHilightControllingTool and says no otherwise. */ public static boolean shouldHilightEdges(EditDomain domain, EObject modelObject) { Tool tool = domain.getActiveTool(); if (tool instanceof IHilightControllingTool) { return ((IHilightControllingTool)tool).hilightModelTarget(modelObject); } return false; } /** * Used to determine the type of pattern to paint a container in the Process. * Because the nesting of containers is confusing, we want to draw nice gradients * to help the user. * 1 and 3 return values mean solid fill. * 0 and 2 mean gradient fills. */ public static int getRepaintFillType(IFigure fig) { int depth = 0; IFigure parent = fig.getParent(); while (parent != null) { if (parent != null && parent.getBorder() != null && parent.getBorder() instanceof GradientBorder) { depth++; } parent = parent.getParent(); } return depth % 4; } public static void sortFlowList(List<FlowEditPart> listOfFlowEditParts) { List<FlowEditPart> result = listOfFlowEditParts; int resultSize = result.size(); for (int i = 0; i<resultSize; i++) { for (int j = i+1; j<resultSize; j++) { Flow flow1 = (Flow)(result.get(i)).getModel(); Flow flow2 = (Flow)(result.get(j)).getModel(); Flow[] parents = FlowLinkUtil.getParentFlows(flow2); for( Flow parent : parents ) { if (parent == flow1) { // flow2 must be layed out before flow1 so its size will be known! FlowEditPart temp = result.get(i); result.set(i, result.get(j)); result.set(j, temp); } } } } } /** * Refresh the given ComboViewer, and also make sure selectedObject is selected in it. */ public static void refreshCombo(ComboViewer viewer, Object selectedObject) { viewer.refresh(); String s = ((ILabelProvider)viewer.getLabelProvider()).getText(selectedObject); viewer.getCombo().setText(s); } /** * Helper method to calculate the width of a button. * This is necessary for internationalization and accessibility. * Returned value is the calculated width or defaultSize, whichever * is larger. */ public static int calculateButtonWidth(Widget widget, int defaultSize){ GC gc; int width = 0; if (widget instanceof Button) { Button w = (Button)widget; gc = new GC(w); gc.setFont(w.getFont()); width = gc.textExtent(w.getText()).x + 17; gc.dispose(); return Math.max(width, defaultSize); } return defaultSize; } public static String getMaxLengthString(String strings[]) { int max = -1; int index = -1; for (int i = 0; i < strings.length; i++) { if (strings[i].length() > max) { max = strings[i].length(); index = i; } } if (index >= 0) return strings[index]; return ""; //$NON-NLS-1$ } /** * Helper method to calculate the width of a CLabel. * This is necessary for internationalization and accessibility. * * Returned value is the calculated width or defaultSize, whichever * is larger. */ public static int calculateLabelWidth(Widget widget, int defaultSize){ GC gc; int width = 0; if (widget instanceof CLabel) { CLabel w = (CLabel)widget; gc = new GC(w); gc.setFont(w.getFont()); width = gc.textExtent(w.getText()).x + 17; gc.dispose(); return Math.max(width, defaultSize); } if (widget instanceof DecoratedLabel) { DecoratedLabel w = (DecoratedLabel)widget; gc = new GC(w); gc.setFont(w.getFont()); width = gc.textExtent(w.getText()).x + 17; gc.dispose(); return Math.max(width, defaultSize); } if (widget instanceof Label) { Label w = (Label)widget; gc = new GC(w); gc.setFont(w.getFont()); width = gc.textExtent(w.getText()).x + 5; gc.dispose(); return Math.max(width, defaultSize); } return defaultSize; } public static IFile getFileFromURI(URI uri) { if (uri.isFile()) { return getFileFromDeviceURI(uri); } return getFileFromPlatformURI(uri); } public static IFile getFileFromDeviceURI(URI uri) { String device = uri.device(); Iterator pathIt = uri.segmentsList().iterator(); StringBuffer path = new StringBuffer(); while (pathIt.hasNext()) { path.append("/" + pathIt.next()); //$NON-NLS-1$ } return ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(new Path(device, path.toString())); } public static IFile getFileFromPlatformURI(URI uri) { String [] segs = uri.segments(); IPath path = null; // start at 1 to skip resource for (int i = 1; i< segs.length; i++) { if (path == null) { path = new Path(segs[i]); } else { path = path.append(segs[i]); } } return ResourcesPlugin.getWorkspace().getRoot().getFile(path); } /** * Function to return a platform URI from a standard hierarchital URI. * Normally we can use URI.createPlatformURI, but that function always assumes * that it is non-platform */ public static URI getPlatformURI(URI uri) { String str = uri.toString(); if (str.startsWith("platform:")) return uri; //$NON-NLS-1$ return URI.createPlatformResourceURI(uri.toString()); } /* external fault handler helpers */ public static boolean getShowFaultHandler(EditPart part) { if (part instanceof ScopeEditPart) return ((ScopeEditPart)part).getShowFaultHandler(); else if (part instanceof InvokeEditPart) return ((InvokeEditPart)part).getShowFaultHandler(); else if (part instanceof StartNodeEditPart) return ((StartNodeEditPart)part).getShowFaultHandler(); return false; } public static void setShowFaultHandler(EditPart part, boolean show) { if (part instanceof ScopeEditPart) ((ScopeEditPart)part).setShowFaultHandler(show); else if (part instanceof InvokeEditPart) ((InvokeEditPart)part).setShowFaultHandler(show); else if (part instanceof StartNodeEditPart) ((StartNodeEditPart)part).setShowFaultHandler(show); } /* external compensation handler helpers */ public static boolean getShowCompensationHandler(EditPart part) { if (part instanceof ScopeEditPart) return ((ScopeEditPart)part).getShowCompensationHandler(); else if (part instanceof InvokeEditPart) return ((InvokeEditPart)part).getShowCompensationHandler(); return false; } public static boolean getShowTerminationHandler(EditPart part) { if (part instanceof ScopeEditPart) return ((ScopeEditPart)part).getShowTerminationHandler(); return false; } public static void setShowCompensationHandler(EditPart part, boolean show) { if (part instanceof ScopeEditPart) ((ScopeEditPart)part).setShowCompensationHandler(show); else if (part instanceof InvokeEditPart) ((InvokeEditPart)part).setShowCompensationHandler(show); } public static void setShowTerminationHandler(EditPart part, boolean show) { if (part instanceof ScopeEditPart) ((ScopeEditPart)part).setShowTerminationHandler(show); } /* external event handler helpers */ public static boolean getShowEventHandler(EditPart part) { if (part instanceof ScopeEditPart) return ((ScopeEditPart)part).getShowEventHandler(); else if (part instanceof StartNodeEditPart) return ((StartNodeEditPart)part).getShowEventHandler(); return false; } public static void setShowEventHandler(EditPart part, boolean show) { if (part instanceof ScopeEditPart) ((ScopeEditPart)part).setShowEventHandler(show); else if (part instanceof StartNodeEditPart) ((StartNodeEditPart)part).setShowEventHandler(show); } /** * Returns the extension file of the given BPEL file. */ public static IFile getBPELEXFile(IFile bpelFile) { IPath path = bpelFile.getFullPath().removeFileExtension().addFileExtension(IBPELUIConstants.EXTENSION_MODEL_EXTENSIONS); return ResourcesPlugin.getWorkspace().getRoot().getFile(path); } /** * Returns the artifacts WSDL of the given BPEL file. */ public static IFile getArtifactsWSDLFile(IFile bpelFile) { IPath wsdlPath = bpelFile.getFullPath().removeFileExtension(); String fileName = wsdlPath.lastSegment() + "Artifacts"; //$NON-NLS-1$ wsdlPath = wsdlPath.removeLastSegments(1).append(fileName); wsdlPath = wsdlPath.addFileExtension(IBPELUIConstants.EXTENSION_WSDL); return ResourcesPlugin.getWorkspace().getRoot().getFile(wsdlPath); } public static Image getImage(IMarker marker) { Image img = ModelMarkerUtil.getImage(marker); ImageData background = null; if (img != null) { background = img.getImageData(); } if (background == null) { // Don't give up yet. If this is also a problem marker, we can find an image to // display... try { if (marker.isSubtypeOf(IMarker.PROBLEM)) { background = ImageUtils.getImage(marker).getImageData(); } } catch (CoreException e) { BPELUIPlugin.log(e); return null; } } if (background == null) return null; String uri = marker.getAttribute(IBPELUIConstants.MARKER_OVERLAYIMAGETOPLEFT, ""); //$NON-NLS-1$ ImageData topLeft = getImageData(uri); uri = marker.getAttribute(IBPELUIConstants.MARKER_OVERLAYIMAGETOPRIGHT, ""); //$NON-NLS-1$ ImageData topRight = getImageData(uri); uri = marker.getAttribute(IBPELUIConstants.MARKER_OVERLAYIMAGEBOTTOMLEFT, ""); //$NON-NLS-1$ ImageData bottomLeft = getImageData(uri); uri = marker.getAttribute(IBPELUIConstants.MARKER_OVERLAYIMAGEBOTTOMRIGHT, ""); //$NON-NLS-1$ ImageData bottomRight = getImageData(uri); OverlayCompositeImageDescriptor descriptor = new OverlayCompositeImageDescriptor(background, topLeft, topRight, bottomLeft, bottomRight); return descriptor.createImage(); } private static ImageData getImageData(String uri) { if (uri.length() == 0) return null; URL url = null; try { url = new URL(uri); } catch (MalformedURLException e) { return null; } ImageDescriptor desc = ImageDescriptor.createFromURL(url); return desc.getImageData(); } /** * Returns the EditPart which is responsible for the given IFigure. */ public static EditPart mapFigure2EditPart(EditPartViewer viewer, IFigure figure) { Map visualPartMap = viewer.getVisualPartMap(); EditPart part = null; while (part == null && figure != null) { part = (EditPart)visualPartMap.get(figure); figure = figure.getParent(); } return part; } /** * Reads the process from disk. */ public static Process getProcess(IResource bpelFile, ResourceSet resourceSet) throws IOException { URI uri = URI.createPlatformResourceURI(bpelFile.getFullPath().toString()); Resource processResource = resourceSet.getResource(uri, true); EList<EObject> contents = processResource.getContents(); if (!contents.isEmpty()) { return (Process) contents.get(0); } return null; } public static AccessibleEditPart getAccessibleEditPart(GraphicalEditPart part) { final GraphicalEditPart thisPart = part; return new AccessibleEditPart() { @Override public void getName(AccessibleEvent e) { String childType = null; String displayName = null; ILabeledElement labeledElement = BPELUtil.adapt(thisPart.getModel(), ILabeledElement.class); if (labeledElement != null) { childType = labeledElement.getTypeLabel(thisPart.getModel()); displayName = labeledElement.getLabel(thisPart.getModel()); if (childType != null && displayName.equals(childType)) { childType = null; } } else { e.result = null; return; } // return something reasonable (type followed by name if any) // or nothing at all StringBuffer concat = new StringBuffer(); if (childType != null && childType.length() > 0) concat.append(childType); if (concat.length() > 0) concat.append(" "); //$NON-NLS-1$ if (displayName != null && displayName.length() > 0) concat.append(displayName); if (concat.length() > 0) e.result = concat.toString(); else e.result = null; return; } @Override public void getChildCount(AccessibleControlEvent e) { List<EditPart> list = thisPart.getChildren(); int count = 0; for (EditPart part : list) { AccessibleEditPart access = (AccessibleEditPart)part.getAdapter(AccessibleEditPart.class); if (access == null) continue; count++; } e.detail = count; } @Override public void getChildren(AccessibleControlEvent e) { List<EditPart> list = thisPart.getChildren(); Vector<Integer> childList = new Vector<Integer>(); for (EditPart part : list) { AccessibleEditPart access = (AccessibleEditPart)part.getAdapter(AccessibleEditPart.class); if (access == null) continue; childList.add( Integer.valueOf( access.getAccessibleID())); } e.children = childList.toArray(); } @Override public void getLocation(AccessibleControlEvent e) { Rectangle bounds = thisPart.getFigure().getBounds().getCopy(); thisPart.getFigure().translateToAbsolute(bounds); org.eclipse.swt.graphics.Point p = new org.eclipse.swt.graphics.Point(0, 0); p = thisPart.getViewer().getControl().toDisplay(p); e.x = bounds.x + p.x; e.y = bounds.y + p.y; e.width = bounds.width; e.height = bounds.height; } /** * @see AccessibleEditPart#getState(AccessibleControlEvent) */ @Override public void getState(AccessibleControlEvent e) { e.detail = ACC.STATE_SELECTABLE | ACC.STATE_FOCUSABLE; if (thisPart.getSelected() != EditPart.SELECTED_NONE) e.detail |= ACC.STATE_SELECTED; if (thisPart.getViewer().getFocusEditPart() == thisPart) e.detail = ACC.STATE_FOCUSED; } }; } /** creates a table cursor that can be used to navigate tables for keyboard accessibility **/ public static TableCursor createTableCursor(final Table table, final TableViewer tableViewer) { // create a TableCursor to navigate around the table final TableCursor cursor = new TableCursor(table, SWT.NONE); cursor.addSelectionListener(new SelectionAdapter() { // when the TableEditor is over a cell, select the corresponding row in the table @Override public void widgetSelected(SelectionEvent e) { if (cursor.getRow() != null) table.setSelection(new TableItem[] {cursor.getRow()}); } // when the user hits "ENTER" in the TableCursor, pop up an editor @Override public void widgetDefaultSelected(SelectionEvent e) { TableItem row = cursor.getRow(); if (row != null) { int nRow = table.indexOf(row); int column = cursor.getColumn(); Object obj = tableViewer.getElementAt(nRow); tableViewer.editElement(obj, column); } } }); // Hide the TableCursor when the user hits the "CTRL" or "SHIFT" key. // This alows the user to select multiple items in the table. cursor.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { if ((e.keyCode == SWT.CTRL) || (e.keyCode == SWT.SHIFT) || (e.stateMask & SWT.CONTROL) != 0 || (e.stateMask & SWT.SHIFT) != 0) { cursor.setVisible(false); } } }); cursor.addMouseListener(new MouseListener() { @Override public void mouseDoubleClick(MouseEvent e) { } @Override public void mouseDown(MouseEvent e) { TableItem row = cursor.getRow(); if (row != null) { int nRow = table.indexOf(row); int column = cursor.getColumn(); Object obj = tableViewer.getElementAt(nRow); tableViewer.editElement(obj, column); } } @Override public void mouseUp(MouseEvent e) { } }); // Show the TableCursor when the user releases the "SHIFT" or "CTRL" key. // This signals the end of the multiple selection task. table.addKeyListener(new KeyAdapter() { @Override public void keyReleased(KeyEvent e) { if (e.keyCode == SWT.CONTROL && (e.stateMask & SWT.SHIFT) != 0) return; if (e.keyCode == SWT.SHIFT && (e.stateMask & SWT.CONTROL) != 0) return; if (e.keyCode != SWT.CONTROL && (e.stateMask & SWT.CONTROL) != 0) return; if (e.keyCode != SWT.SHIFT && (e.stateMask & SWT.SHIFT) != 0) return; if (table.getItemCount() == 0) return; TableItem[] selection = table.getSelection(); TableItem row = (selection.length == 0) ? table.getItem(table.getTopIndex()) : selection[0]; table.showItem(row); cursor.setSelection(row, 0); cursor.setVisible(true); cursor.setFocus(); } }); return cursor; } public static ResourceSet createResourceSetImpl() { // TODO: Extensibility return new ResourceSetImpl(); } static final NCNameWordDetector NCNAME_DETECTOR = new NCNameWordDetector (); /** * Returns a validator that checks that the new value is a valid NCName. */ public static IInputValidator getNCNameValidator() { return new IInputValidator() { @Override public String isValid (String newText) { if ( NCNAME_DETECTOR.isValid( newText ) == false ) { return Messages.BPELUtil_NCName; } // TODO ! temporary hack return null; } }; } public static void deleteNonContainmentRefs(EObject modelObject, Collection referents) { if (modelObject == null) return; for (EReference feature : modelObject.eClass().getEAllReferences()) { if (feature.isMany()) { EList<Object> list = (EList<Object>)modelObject.eGet(feature, true); for (Object referent : referents) { if (list.contains(referent)) list.remove(referent); // TODO: support non-changeable features! print a warning. } } else { Object oldValue = modelObject.eGet(feature, true); for (Object referent : referents) { if (oldValue == referent) { if (feature.isUnsettable()) { // this is okay, default is always null for EReferences. modelObject.eUnset(feature); } else { modelObject.eSet(feature, null); } break; } // TODO: support non-changeable features! print a warning. } } } } //@return: returns arraylist with all activities the compensate // can validly point to public static ArrayList getCompensableActivities(Object context){ final ArrayList returnObjects = new ArrayList(); if (context instanceof CompensateScope) { CompensateScope compensateScope = (CompensateScope) context; EObject enclosingContainer = compensateScope; if (compensateScope.eContainer() != null) { enclosingContainer = enclosingContainer.eContainer(); // Go to parent scope where compensate is contained while (!(enclosingContainer instanceof Scope) && (enclosingContainer.eContainer() != null)) { enclosingContainer = enclosingContainer.eContainer(); } } // Put all scopes and invokes within parent scope in arraylist visitModelDepthFirst(enclosingContainer, new IModelVisitor() { @Override public boolean visit(Object modelObject) { if (modelObject instanceof Scope) { returnObjects.add(modelObject); } else if (modelObject instanceof Invoke) { returnObjects.add(modelObject); } return true; } }); // https://issues.jboss.org/browse/JBIDE-8044 if (!returnObjects.isEmpty()) returnObjects.remove(0); //remove the scope containing the compensate return returnObjects; } throw new IllegalArgumentException(); } public static Object resolveXSDObject(Object xsdObject) { if (xsdObject instanceof XSDElementDeclaration) { XSDElementDeclaration resolvedElement = ((XSDElementDeclaration)xsdObject).getResolvedElementDeclaration(); if (resolvedElement != null) xsdObject = resolvedElement; } else if (xsdObject instanceof XSDAttributeDeclaration) { XSDAttributeDeclaration resolvedAttribute = ((XSDAttributeDeclaration)xsdObject).getResolvedAttributeDeclaration(); if (resolvedAttribute != null) xsdObject = resolvedAttribute; } return xsdObject; } public static String debugObject(Object object) { if (object == null) return "null"; //$NON-NLS-1$ if (object instanceof String) { return "\""+(String)object+"\""; } //$NON-NLS-1$ //$NON-NLS-2$ if (object.getClass().getName().startsWith("java.lang")) { //$NON-NLS-1$ return object.toString(); } if (object instanceof List) { StringBuffer b = new StringBuffer("("); //$NON-NLS-1$ for (Iterator it = ((List)object).iterator(); it.hasNext(); ) { b.append(debugObject(it.next())); if (it.hasNext()) b.append(", "); //$NON-NLS-1$ } b.append(")"); //$NON-NLS-1$ return b.toString(); } if (object instanceof QName) { QName qname = (QName)object; return "QName(\""+qname.getNamespaceURI()+"\", \""+qname.getLocalPart()+"\")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } StringBuffer b = new StringBuffer(shortClassName(object.getClass())); boolean proxy = (object instanceof EObject) && ((EObject)object).eIsProxy(); if (proxy) b.append("-proxy"); //$NON-NLS-1$ boolean isEObject = (object instanceof EObject); INamedElement namedElement = null; if (isEObject) { namedElement = BPELUtil.adapt(object, INamedElement.class); if (namedElement != null) { try { String s = namedElement.getName(object); b.append((s==null)? "<null>" : "<\""+s+"\">"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } catch (Exception e) { b.append("<???>"); //$NON-NLS-1$ } } } if (namedElement==null) { b.append("{"); b.append(String.valueOf(object.hashCode())); b.append("}"); //$NON-NLS-1$ //$NON-NLS-2$ } return b.toString(); } public static String debug(Notification n) { StringBuffer b = new StringBuffer(shortClassName(n.getClass())); b.append("("); //$NON-NLS-1$ b.append(debugObject(n.getNotifier())); b.append(", "); //$NON-NLS-1$ switch (n.getEventType()) { case Notification.SET-1: b.append("CREATE"); break; //$NON-NLS-1$ case Notification.SET: b.append("SET"); break; //$NON-NLS-1$ case Notification.UNSET: b.append("UNSET"); break; //$NON-NLS-1$ case Notification.ADD: b.append("ADD"); break; //$NON-NLS-1$ case Notification.REMOVE: b.append("REMOVE"); break; //$NON-NLS-1$ case Notification.ADD_MANY: b.append("ADD_MANY"); break; //$NON-NLS-1$ case Notification.MOVE: b.append("MOVE"); break; //$NON-NLS-1$ case Notification.REMOVING_ADAPTER: b.append("REMOVING_ADAPTER"); break; //$NON-NLS-1$ case Notification.RESOLVE: b.append("RESOLVE"); break; //$NON-NLS-1$ default: b.append("??? ("+String.valueOf(n.getEventType())+")"); //$NON-NLS-1$ //$NON-NLS-2$ } b.append(" "); //$NON-NLS-1$ EStructuralFeature feature = (EStructuralFeature)n.getFeature(); if (feature == null) b.append("???"); else b.append(feature.getName()); //$NON-NLS-1$ if (n.getPosition() >= 0) { b.append("["); //$NON-NLS-1$ b.append(String.valueOf(n.getPosition())); b.append("]"); //$NON-NLS-1$ } else { if (feature != null && feature.isMany()) b.append("{***}"); //$NON-NLS-1$ } b.append(": "); //$NON-NLS-1$ b.append(debugObject(n.getOldValue())); b.append(" --> "); //$NON-NLS-1$ b.append(debugObject(n.getNewValue())); b.append(")"); //$NON-NLS-1$ return b.toString(); } protected static String shortClassName(Class clazz) { StringBuffer b = new StringBuffer(clazz.getName()); for (int i = b.indexOf("."); i >= 0; i = b.indexOf(".")) b.delete(0,i+1); //$NON-NLS-1$ //$NON-NLS-2$ //if (b.indexOf("Impl") == b.length()-4) b.delete(b.length()-4, b.length())); return b.toString(); } /** * Creates a composite with a flat border around it. */ public static Composite createBorderComposite(Composite parent, TabbedPropertySheetWidgetFactory wf) { final Composite result = wf.createComposite(parent); FillLayout layout = new FillLayout(); final int margin = 1; layout.marginHeight = margin; layout.marginWidth = margin; result.setLayout(layout); result.addPaintListener(new PaintListener() { @Override public void paintControl(PaintEvent e) { org.eclipse.swt.graphics.Rectangle bounds = result.getBounds(); bounds.x = margin-1; bounds.y = margin-1; bounds.width = bounds.width - (margin*2) + 1; bounds.height = bounds.height - (margin*2) + 1; e.gc.drawRectangle(bounds); } }); return result; } static void addVariablesToMap(Map<String, Variable> targetMap, Variables vars, Variable refVar ) { if (vars == null) { return; } for(Variable v : vars.getChildren()) { // scoping for initialization (only visible from). if (v == refVar) { break; } if (v.getName() != null) { targetMap.put(v.getName(),v); } } } static void addVisibleVariables (Map<String,Variable> targetMap, EObject target, Variable refVariable ) { if (target == null) { return; } if (target instanceof Resource) { return; } if (target instanceof Process) { addVariablesToMap(targetMap, ((Process)target).getVariables(), refVariable ); return ; } // recursively add less local variables first addVisibleVariables(targetMap, target.eContainer(), refVariable ); if (target instanceof Scope) { addVariablesToMap(targetMap, ((Scope)target).getVariables(), refVariable ); } if (target instanceof Catch) { Variable v = ((Catch)target).getFaultVariable(); if (v != null && v.getName() != null) { targetMap.put(v.getName(), v); } } if (target instanceof OnEvent) { Variable v = ((OnEvent)target).getVariable(); if (v != null && v.getName() != null) { targetMap.put(v.getName(), v); } } if (target instanceof ForEach) { Variable v = ((ForEach)target).getCounterName(); if (v != null && v.getName() != null) { targetMap.put(v.getName(), v); } } } private static void addPartnerLinksToMap(Map<String, PartnerLink> targetMap, PartnerLinks plinks) { if (plinks == null) return; for (PartnerLink p : plinks.getChildren()) { if (p.getName() != null) targetMap.put(p.getName(), p); } } private static void addVisiblePartnerLinks(Map<String, PartnerLink> targetMap, EObject target) { if (target == null) return; if (target instanceof Resource) return; if (target instanceof Process) { addPartnerLinksToMap(targetMap, ((Process)target).getPartnerLinks()); } else { // recursively add less local partnerlinks first addVisiblePartnerLinks(targetMap, target.eContainer()); if (target instanceof Scope) { addPartnerLinksToMap(targetMap, ((Scope)target).getPartnerLinks()); } } } private static void addCorrelationSetsToMap(Map<String, CorrelationSet> targetMap, CorrelationSets csets) { if (csets == null) return; for( CorrelationSet c : csets.getChildren() ) { if (c.getName() != null) targetMap.put(c.getName(), c); } } private static void addVisibleCorrelationSets(Map<String, CorrelationSet> targetMap, EObject target) { if (target == null) return; if (target instanceof Resource) return; if (target instanceof Process) { addCorrelationSetsToMap(targetMap, ((Process)target).getCorrelationSets()); } else { // recursively add less local correlationsets first addVisibleCorrelationSets(targetMap, target.eContainer()); if (target instanceof Scope) { addCorrelationSetsToMap(targetMap, ((Scope)target).getCorrelationSets()); } } } /** * Look up the variables visible to a certain context activity (or the whole process). * Variables in BPEL follow lexical scoping rules (resolved OASIS issue 101). * * The returned variables are in no particular order. */ public static Variable[] getVisibleVariables (EObject target) { Map<String,Variable> name2Variable = new HashMap<String,Variable>(); addVisibleVariables(name2Variable, target, target instanceof Variable ? (Variable) target: null ); if (name2Variable.isEmpty()) { return EMPTY_VARIABLE_ARRAY; } Collection<Variable> variables = name2Variable.values(); if (variables.size() == 1) { return variables.toArray(EMPTY_VARIABLE_ARRAY); } ArrayList<Variable> list = new ArrayList<Variable>( variables ); Collections.sort(list, new Comparator<Variable>() { @Override public int compare(Variable o1, Variable o2) { return o1.getName().compareTo(o2.getName()); } }); return list.toArray(EMPTY_VARIABLE_ARRAY); } /** * Look up the PartnerLinks visible to a certain context activity (or the whole process). * When local PartnerLinks are added to the spec, they will follow lexical scoping rules * just like variables. * * The returned PartnerLinks are in no particular order. */ public static PartnerLink[] getVisiblePartnerLinks(EObject target) { Map<String, PartnerLink> name2PartnerLink = new HashMap<String, PartnerLink>(); addVisiblePartnerLinks(name2PartnerLink, target); if (name2PartnerLink.isEmpty()) return EMPTY_PARTNERLINK_ARRAY; PartnerLink[] result = new PartnerLink[name2PartnerLink.size()]; name2PartnerLink.values().toArray(result); return result; } /** * Look up the PartnerLinks visible to a certain context activity (or the whole process). * When local PartnerLinks are added to the spec, they will follow lexical scoping rules * just like variables. * * The returned PartnerLinks are in no particular order. */ public static CorrelationSet[] getVisibleCorrelationSets(EObject target) { Map<String, CorrelationSet> name2CorrelationSet = new HashMap<String, CorrelationSet>(); addVisibleCorrelationSets(name2CorrelationSet, target); if (name2CorrelationSet.isEmpty()) return EMPTY_CORRELATIONSET_ARRAY; CorrelationSet[] result = new CorrelationSet[name2CorrelationSet.size()]; name2CorrelationSet.values().toArray(result); return result; } /** * If the given message is used by an operation in the same definition, * returns the Operation that uses the given message. * Otherwise, returns null. */ public static Operation getOperationFromMessage(Message message) { if (message == null) return null; Definition def = message.getEnclosingDefinition(); if (def == null) return null; Iterator<PortType> ptIt = def.getEPortTypes().iterator(); while (ptIt.hasNext()) { PortType pt = ptIt.next(); Iterator<Operation> it = pt.getOperations().iterator(); while (it.hasNext()) { Operation op = it.next(); Input input = op.getEInput(); if (input != null) { if (input.getMessage().getQName().equals(message.getQName())) { return op; } } Output output = op.getEOutput(); if (output != null) { if (output.getMessage().getQName().equals(message.getQName())) { return op; } } Iterator<Fault> faultIterator = op.getEFaults().iterator(); while (faultIterator.hasNext()) { Fault fault = faultIterator.next(); Message faultMessage = fault.getEMessage(); if (faultMessage != null) { if (faultMessage.getQName() != null) { if (faultMessage.getQName().equals(message.getQName())) { return op; } } } } } } return null; } public static void openEditor(EObject modelObject, BPELEditor editor) { try { // https://issues.jboss.org/browse/JBIDE-8044 if (modelObject==null) { // https://issues.jboss.org/browse/JBIDE-8601 MessageDialog.openError(editor.getEditorSite().getShell(), Messages.BPELUtil__Error, Messages.BPELUtil_NoEditorForNullObject); return; } EObject resolvedObject = null; if (modelObject.eResource()==null) { // https://jira.jboss.org/browse/JBIDE-7351 // try to resolve proxies here, otherwise we don't know editor input if (modelObject.eIsProxy()) { resolvedObject = EmfModelQuery.resolveProxy(editor.getProcess(), modelObject); } } else resolvedObject = modelObject; if (resolvedObject==null) { // https://issues.jboss.org/browse/JBIDE-8601 MessageDialog.openError(editor.getEditorSite().getShell(), Messages.BPELUtil__Error, NLS.bind( Messages.BPELUtil_NoEditorForObject, (new Object[] { modelObject.getClass().getSimpleName() }))); return; } IFile file = BPELUtil.getFileFromURI(resolvedObject.eResource().getURI()); IDE.openEditor(editor.getSite().getWorkbenchWindow().getActivePage(), file); } catch (PartInitException ex) { BPELUIPlugin.log(ex, IStatus.WARNING); } } /** * Returns the BPEL file associated with the given process. */ public static IFile getBPELFile(Process process) { return getFileFromURI(process.eResource().getURI()); } public static String lookupOrCreateNamespacePrefix ( EObject context, String namespace, String prefix, Shell shell ) { String nsPrefix = BPELUtils.getNamespacePrefix(context, namespace); if (nsPrefix != null && nsPrefix.length() > 0) { return nsPrefix; } NamespaceMappingDialog dialog = new NamespaceMappingDialog (shell, context); dialog.setNamespace(namespace); if (prefix != null) { dialog.setPrefix(prefix); } if (dialog.open() == Window.CANCEL) { return nsPrefix; } nsPrefix = dialog.getPrefix(); BPELUtils.setNamespacePrefix(context, namespace, nsPrefix); return nsPrefix; } /** * Traverses the root object and returns all objects under it that are of the same * class or subclasses of "target". */ public static List<EObject> getAllEObjectsOfType(EObject root, EClass eClass) { List<EObject> allElems = new ArrayList<EObject>(); for (TreeIterator<EObject> iter = root.eAllContents(); iter.hasNext();) { EObject element = iter.next(); if (eClass.isSuperTypeOf(element.eClass()) || element.eClass() == eClass) { allElems.add(element); } } return allElems; } public static boolean isBPELProject(IProject project){ if (project == null) { return false; } if (ModuleCoreNature.isFlexibleProject(project)) { IFacetedProject fproj = null; try { fproj = ProjectFacetsManager.create(project); } catch (CoreException e) { return false; } if (fproj.hasProjectFacet(getBPELFacetVersion())) { return true; } } return false; } public static IProjectFacetVersion getBPELFacetVersion() { IProjectFacet bpelFacet = ProjectFacetsManager.getProjectFacet(IBPELModuleFacetConstants.BPEL20_PROJECT_FACET); IProjectFacetVersion bpelFacetVersion = bpelFacet.getVersion(IBPELModuleFacetConstants.BPEL20_MODULE_VERSION); return bpelFacetVersion; } public static org.eclipse.core.resources.IContainer getBPELContentFolder(IProject project) { org.eclipse.core.resources.IContainer bpelContent = null; if (BPELUtil.isBPELProject(project)) { IPath rootPath = getWebContentRootPath(project); if (rootPath != null && !rootPath.isEmpty()) { bpelContent = project.getFolder(rootPath); } } return bpelContent; } public static IPath getWebContentRootPath(IProject project) { IPath path = null; IVirtualComponent component = ComponentCore.createComponent(project); if (component != null && component.exists()) { path = component.getRootFolder().getProjectRelativePath(); } return path; } }