| /******************************************************************************* |
| * Copyright (c) 2013, 2016 THALES GLOBAL SERVICES 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: |
| * Obeo - initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.emf.ecoretools.design.service; |
| |
| import java.io.IOException; |
| import java.io.OutputStream; |
| import java.io.PrintWriter; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Set; |
| |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.emf.codegen.ecore.genmodel.GenClass; |
| import org.eclipse.emf.codegen.ecore.genmodel.GenDelegationKind; |
| import org.eclipse.emf.codegen.ecore.genmodel.GenModel; |
| import org.eclipse.emf.common.EMFPlugin; |
| import org.eclipse.emf.common.command.Command; |
| import org.eclipse.emf.common.util.Diagnostic; |
| 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.EClassifier; |
| import org.eclipse.emf.ecore.EEnum; |
| import org.eclipse.emf.ecore.EEnumLiteral; |
| import org.eclipse.emf.ecore.EModelElement; |
| import org.eclipse.emf.ecore.ENamedElement; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.EOperation; |
| import org.eclipse.emf.ecore.EPackage; |
| import org.eclipse.emf.ecore.EParameter; |
| import org.eclipse.emf.ecore.EReference; |
| import org.eclipse.emf.ecore.EStructuralFeature; |
| import org.eclipse.emf.ecore.ETypeParameter; |
| import org.eclipse.emf.ecore.EcorePackage; |
| import org.eclipse.emf.ecore.impl.EStringToStringMapEntryImpl; |
| import org.eclipse.emf.ecore.resource.Resource; |
| import org.eclipse.emf.ecore.resource.URIConverter; |
| import org.eclipse.emf.ecore.util.Diagnostician; |
| import org.eclipse.emf.ecore.util.EcoreUtil; |
| import org.eclipse.emf.edit.EMFEditPlugin; |
| import org.eclipse.emf.edit.command.AddCommand; |
| import org.eclipse.emf.transaction.RecordingCommand; |
| import org.eclipse.emf.transaction.TransactionalEditingDomain; |
| import org.eclipse.sirius.business.api.session.Session; |
| import org.eclipse.sirius.business.api.session.SessionManager; |
| import org.eclipse.sirius.diagram.DDiagram; |
| import org.eclipse.sirius.diagram.DDiagramElement; |
| import org.eclipse.sirius.diagram.DEdge; |
| import org.eclipse.sirius.diagram.DNodeContainer; |
| import org.eclipse.sirius.diagram.DNodeList; |
| import org.eclipse.sirius.diagram.DSemanticDiagram; |
| import org.eclipse.sirius.diagram.EdgeArrows; |
| import org.eclipse.sirius.diagram.EdgeTarget; |
| import org.eclipse.sirius.diagram.business.api.query.DDiagramQuery; |
| import org.eclipse.sirius.diagram.business.internal.helper.task.operations.CreateViewTask; |
| import org.eclipse.sirius.diagram.business.internal.query.DDiagramInternalQuery; |
| import org.eclipse.sirius.diagram.description.AbstractNodeMapping; |
| import org.eclipse.sirius.diagram.description.DiagramElementMapping; |
| import org.eclipse.sirius.diagram.description.tool.CreateView; |
| import org.eclipse.sirius.diagram.description.tool.ToolFactory; |
| import org.eclipse.sirius.ecore.extender.business.api.accessor.ModelAccessor; |
| import org.eclipse.sirius.ecore.extender.business.api.accessor.exception.FeatureNotFoundException; |
| import org.eclipse.sirius.ecore.extender.business.api.accessor.exception.MetaClassNotFoundException; |
| import org.eclipse.sirius.ext.emf.AllContents; |
| import org.eclipse.sirius.tools.api.command.CommandContext; |
| import org.eclipse.sirius.viewpoint.DRepresentation; |
| import org.eclipse.sirius.viewpoint.DSemanticDecorator; |
| import org.eclipse.sirius.viewpoint.FontFormat; |
| |
| import com.google.common.base.Ascii; |
| import com.google.common.base.CharMatcher; |
| import com.google.common.base.Function; |
| import com.google.common.base.Optional; |
| import com.google.common.base.Predicate; |
| import com.google.common.base.Splitter; |
| import com.google.common.collect.Iterables; |
| import com.google.common.collect.Iterators; |
| import com.google.common.collect.Lists; |
| import com.google.common.collect.Ordering; |
| import com.google.common.collect.Sets; |
| |
| /** |
| * Generic Ecore services usable from a VSM. |
| */ |
| public class DesignServices extends EReferenceServices { |
| private static final String CLASS_DIAGRAM_CLASS_MAPPINGID = "EC EClass"; |
| |
| /** |
| * Returns all the root objects of all the resources in the same |
| * resource-set as the specified object. |
| * |
| * @param any |
| * an EObject. |
| * @return all the root objects in the same resource-set as <code>any</code> |
| * or an empty collection if <code>any</code> is not inside a |
| * resource-set. |
| */ |
| public List<EObject> allRoots(EObject any) { |
| Resource res = any.eResource(); |
| if (res != null && res.getResourceSet() != null) { |
| List<EObject> roots = new ArrayList<EObject>(); |
| for (Resource childRes : res.getResourceSet().getResources()) { |
| roots.addAll(childRes.getContents()); |
| } |
| return roots; |
| } else { |
| return Collections.emptyList(); |
| } |
| } |
| |
| public Set<EPackage> rootEPackages(EObject any) { |
| return Sets.newLinkedHashSet(Iterables.filter(allRoots(any), EPackage.class)); |
| } |
| |
| public Boolean isEOperation(EObject any) { |
| return any instanceof EOperation; |
| } |
| |
| public Boolean isEStructuralFeature(EObject any) { |
| return any instanceof EStructuralFeature; |
| } |
| |
| public Boolean isEPackage(EObject any) { |
| return any instanceof EPackage; |
| } |
| |
| public Boolean isEClass(EObject any) { |
| return any instanceof EClass; |
| } |
| |
| public Boolean isEEnum(EObject any) { |
| return any instanceof EEnum; |
| } |
| |
| protected static final String GEN_MODEL_PACKAGE_NS_URI = "http://www.eclipse.org/emf/2002/GenModel"; |
| |
| protected static final String ECORE_PACKAGE_NS_URI = "http://www.eclipse.org/emf/2002/Ecore"; |
| |
| public EObject markForAutosize(EObject any) { |
| if (any != null) { |
| any.eAdapters().add(AutosizeTrigger.AUTO_SIZE_MARKER); |
| } |
| return any; |
| } |
| |
| public EObject eContainerEContainer(EObject any) { |
| if (any.eContainer() != null) |
| return any.eContainer().eContainer(); |
| return null; |
| } |
| |
| public Set<EStringToStringMapEntryImpl> getVisibleDocAnnotations(EObject self, DSemanticDiagram diag) { |
| // [diagram.getDisplayedEModelElements().oclAsType(ecore::EModelElement).eAnnotations.details->select(key |
| // = 'documentation')/] |
| Set<EStringToStringMapEntryImpl> result = Sets.newLinkedHashSet(); |
| for (EModelElement displayed : getDisplayedEModelElements(diag)) { |
| if (!(displayed instanceof EAttribute) && !(displayed instanceof EEnumLiteral) |
| && !(displayed instanceof EOperation)) { |
| EAnnotation eAnnot = displayed.getEAnnotation(GEN_MODEL_PACKAGE_NS_URI); |
| if (eAnnot != null) { |
| for (EStringToStringMapEntryImpl mapEntry : Iterables.filter(eAnnot.getDetails(), |
| EStringToStringMapEntryImpl.class)) { |
| if ("documentation".equals(mapEntry.getKey())) { |
| result.add(mapEntry); |
| } |
| } |
| } |
| } |
| |
| } |
| return result; |
| } |
| |
| public Set<EStringToStringMapEntryImpl> getVisibleConstraintsAnnotations(EObject self, |
| DSemanticDiagram diag) { |
| Set<EStringToStringMapEntryImpl> result = Sets.newLinkedHashSet(); |
| for (EModelElement displayed : getDisplayedEModelElements(diag)) { |
| if (!(displayed instanceof EAttribute) && !(displayed instanceof EEnumLiteral) |
| && !(displayed instanceof EOperation)) { |
| EAnnotation eAnnot = displayed.getEAnnotation(ECORE_PACKAGE_NS_URI); |
| if (eAnnot != null) { |
| for (EStringToStringMapEntryImpl mapEntry : Iterables.filter(eAnnot.getDetails(), |
| EStringToStringMapEntryImpl.class)) { |
| if ("constraints".equals(mapEntry.getKey())) { |
| result.add(mapEntry); |
| } |
| } |
| } |
| } |
| |
| } |
| return result; |
| } |
| |
| public boolean hasNoClassifier(DSemanticDiagram diagram) { |
| Iterator<DSemanticDecorator> it = Iterators.filter(diagram.getOwnedDiagramElements().iterator(), |
| DSemanticDecorator.class); |
| while (it.hasNext()) { |
| DSemanticDecorator dec = it.next(); |
| if (dec.getTarget() instanceof EClassifier) |
| return true; |
| } |
| return false; |
| } |
| |
| public Set<EReference> getNonDisplayedEReferences(EClass self, DSemanticDiagram diag) { |
| Set<EReference> result = Sets.newLinkedHashSet(); |
| Set<EClass> displayedEClasses = null; |
| for (EReference eReference : self.getEAllReferences()) { |
| if (eReference.getEType() != null) { |
| if (displayedEClasses == null) { |
| displayedEClasses = getDisplayedEClasses(diag); |
| } |
| /* |
| * if the target of the EReference is not visible, we *have* to |
| * display it as a node except if it iis from a supertype which |
| * is visible itself, then the reference will be already |
| * displayed. but if the reference is owned by a super type and |
| * this supertype is not visible, even if the target is visible, |
| * then we have to display it as a node to! |
| */ |
| boolean targetTypeIsVisible = displayedEClasses.contains(eReference.getEType()); |
| boolean referenceIsInherited = eReference.getEContainingClass() != self; |
| boolean referenceHostIsVisible = displayedEClasses.contains(eReference.getEContainingClass()); |
| if (!referenceIsInherited && !targetTypeIsVisible) { |
| result.add(eReference); |
| } |
| if (referenceIsInherited && (!referenceHostIsVisible)) { |
| result.add(eReference); |
| } |
| } |
| } |
| return result; |
| } |
| |
| public Set<EClass> getDisplayedEClasses(DSemanticDiagram diagram) { |
| Set<EClass> result = Sets.newLinkedHashSet(); |
| Iterator<DNodeList> it = Iterators.filter(new DDiagramInternalQuery(diagram).getContainers().iterator(), |
| DNodeList.class); |
| while (it.hasNext()) { |
| DNodeList dec = it.next(); |
| if (dec.getTarget() instanceof EClass && dec.isVisible()) { |
| result.add((EClass) dec.getTarget()); |
| } |
| } |
| return result; |
| } |
| |
| public Set<EClassifier> getDisplayedEClassifiers(DSemanticDiagram diagram) { |
| Set<EClassifier> result = Sets.newLinkedHashSet(); |
| Iterator<DNodeList> it = Iterators.filter(new DDiagramInternalQuery(diagram).getContainers().iterator(), |
| DNodeList.class); |
| while (it.hasNext()) { |
| DNodeList dec = it.next(); |
| if (dec.getTarget() instanceof EClassifier && dec.isVisible()) { |
| result.add((EClassifier) dec.getTarget()); |
| } |
| } |
| return result; |
| } |
| |
| private Set<EClass> getInternalEClasses(DSemanticDiagram diagram) { |
| Set<EClass> result = Sets.newLinkedHashSet(); |
| Iterator<DNodeList> it = Iterators.filter(new DDiagramInternalQuery(diagram).getContainers().iterator(), |
| DNodeList.class); |
| while (it.hasNext()) { |
| DNodeList dec = it.next(); |
| if (dec.getTarget() instanceof EClass) { |
| if (dec.getActualMapping() != null |
| && CLASS_DIAGRAM_CLASS_MAPPINGID.equals(dec.getActualMapping().getName())) { |
| result.add((EClass) dec.getTarget()); |
| } |
| } |
| } |
| return result; |
| } |
| |
| public Set<EClass> getDirectSuperTypesOrMostSpecificVisibleOnes(EClass self, DSemanticDiagram diagram) { |
| Set<EClass> result = Sets.newLinkedHashSet(); |
| Set<EClass> displayed = getDisplayedEClasses(diagram); |
| for (EClass directSuperType : self.getESuperTypes()) { |
| if (displayed.contains(directSuperType)) { |
| result.add(directSuperType); |
| } else { |
| Set<EClass> mostSpecificDisplayed = findMostSpecificAndVisible(directSuperType.getESuperTypes(), |
| displayed); |
| if (mostSpecificDisplayed != null) { |
| result.addAll(mostSpecificDisplayed); |
| } |
| } |
| } |
| return result; |
| } |
| |
| private Set<EClass> findMostSpecificAndVisible(Collection<EClass> superTypes, Set<EClass> displayed) { |
| Set<EClass> result = Sets.newLinkedHashSet(); |
| for (EClass eClass : superTypes) { |
| if (displayed.contains(eClass)) { |
| result.add(eClass); |
| } else { |
| result.addAll(findMostSpecificAndVisible(eClass.getESuperTypes(), displayed)); |
| } |
| } |
| return result; |
| } |
| |
| public Set<EClass> getExternalEClasses(EPackage root, DSemanticDiagram diagram) { |
| |
| Set<EClass> related = Sets.newLinkedHashSet(); |
| Set<EClass> eClasses = getInternalEClasses(diagram); |
| RelatedElementsSwitch relations = new RelatedElementsSwitch(); |
| for (EClass eClass : eClasses) { |
| for (EClass other : Iterables.filter(relations.getRelatedElements(eClass), EClass.class)) { |
| related.add(other); |
| } |
| } |
| |
| return Sets.difference(related, eClasses); |
| } |
| |
| public Set<EReference> getEReferencesToDisplay(EPackage root, DSemanticDiagram diagram) { |
| // [diagram.getDisplayedEClasses().oclAsType(ecore::EClass).eAllReferences->flatten()/] |
| Collection<EClass> eClasses = getDisplayedEClasses(diagram); |
| Set<EReference> eRefs = Sets.newLinkedHashSet(); |
| for (EClass clazz : eClasses) { |
| eRefs.addAll(clazz.getEAllReferences()); |
| } |
| return eRefs; |
| } |
| |
| public Boolean targetIsInterface(EClass clazz, EObject view) { |
| if (view instanceof DEdge) { |
| EdgeTarget target = ((DEdge) view).getTargetNode(); |
| if (target instanceof DSemanticDecorator && ((DSemanticDecorator) target).getTarget() instanceof EClass) { |
| return ((EClass) ((DSemanticDecorator) target).getTarget()).isInterface(); |
| } |
| } |
| return false; |
| } |
| |
| public List<EReference> getEOppositeSemanticElements(EReference ref) { |
| Set<EReference> allRefs = Sets.newLinkedHashSet(); |
| allRefs.add(ref); |
| if (ref.getEOpposite() != null) |
| allRefs.add(ref.getEOpposite()); |
| return Ordering.natural().onResultOf(new Function<EReference, String>() { |
| |
| public String apply(EReference input) { |
| return input.getName(); |
| } |
| }).sortedCopy(allRefs); |
| } |
| |
| public Set<EModelElement> getDisplayedEModelElements(DSemanticDiagram diagram) { |
| Set<EModelElement> modelelements = Sets.newLinkedHashSet(); |
| Iterator<DSemanticDecorator> it = Iterators.filter(Iterators.concat(Iterators.singletonIterator(diagram), |
| new DDiagramQuery(diagram).getAllDiagramElements().iterator()), DSemanticDecorator.class); |
| while (it.hasNext()) { |
| DSemanticDecorator dec = it.next(); |
| if (dec.getTarget() instanceof EModelElement) |
| modelelements.add((EModelElement) dec.getTarget()); |
| } |
| return modelelements; |
| } |
| |
| public List<EObject> getValidsForDiagram(final EObject element, final DSemanticDecorator containerView) { |
| Predicate<EObject> validForClassDiagram = new Predicate<EObject>() { |
| |
| public boolean apply(EObject input) { |
| return input instanceof EPackage || input instanceof EClassifier; |
| } |
| }; |
| return allValidSessionElements(element, validForClassDiagram); |
| } |
| |
| public Set<EObject> getRelated(EObject firstView, List<EObject> allSelectedViews, DDiagram diag) { |
| Set<EObject> relateds = Sets.newLinkedHashSet(); |
| for (DSemanticDecorator decorator : Iterables.filter(allSelectedViews, DSemanticDecorator.class)) { |
| relateds.addAll(new RelatedElementsSwitch().getRelatedElements(decorator.getTarget())); |
| } |
| return relateds; |
| } |
| |
| public Set<EObject> getRelated(EObject firstView, EObject aView, DDiagram diag) { |
| return getRelated(firstView, Lists.newArrayList(aView), diag); |
| } |
| |
| private List<EObject> allValidSessionElements(EObject cur, Predicate<EObject> validForClassDiagram) { |
| Session found = SessionManager.INSTANCE.getSession(cur); |
| List<EObject> result = Lists.newArrayList(); |
| if (found != null) { |
| for (Resource res : found.getSemanticResources()) { |
| if (res.getURI().isPlatformResource() || res.getURI().isPlatformPlugin()) { |
| Iterators.addAll(result, Iterators.filter(res.getAllContents(), validForClassDiagram)); |
| } |
| } |
| } |
| return result; |
| } |
| |
| /** |
| * Gets the containing resource name, or null. |
| * |
| * @param current |
| * is the object |
| * @return the resource |
| */ |
| public String eResourceName(final EObject current) { |
| if (current != null && current.eResource() != null) { |
| return current.eResource().getURI().lastSegment(); |
| } else { |
| return null; |
| } |
| } |
| |
| /** |
| * Replace spaces by camel case value. |
| * |
| * @param any |
| * @param from |
| * @return |
| */ |
| public String toCamelCase(EObject any, String from) { |
| if (from != null) { |
| StringBuffer buffer = new StringBuffer(from.length()); |
| for (String word : Splitter.on(CharMatcher.WHITESPACE).trimResults().split(from)) { |
| buffer.append(toU1Case(word)); |
| } |
| return buffer.toString(); |
| } |
| return from; |
| } |
| |
| private String toU1Case(String word) { |
| if (word != null && word.length() > 0) { |
| return new StringBuilder(word.length()).append(Ascii.toUpperCase(word.charAt(0))).append(word.substring(1)) |
| .toString(); |
| } |
| return word; |
| } |
| |
| /** |
| * Computes the label of an EAttribute. |
| */ |
| public String render(EAttribute attr) { |
| return new EAttributeServices().render(attr); |
| } |
| |
| /** |
| * Performs a "direct edit" operation on an EAttribute. |
| */ |
| public EStructuralFeature performEdit(EAttribute attr, String editString) { |
| return new EAttributeServices().performEdit(attr, editString); |
| } |
| |
| /** |
| * Performs a "direct edit" operation on an EAttribute. |
| */ |
| public EStructuralFeature performEditAsAttribute(EStructuralFeature attr, String editString) { |
| return new EAttributeServices().performEdit(attr, editString); |
| } |
| |
| /** |
| * Computes the label of an EOperation. |
| */ |
| public String render(EOperation op) { |
| return new EOperationServices().render(op); |
| } |
| |
| public String renderTooltip(EObject current) { |
| String result = ""; |
| Optional<Diagnostic> diag = DiagnosticAttachment.get(current); |
| if (diag.isPresent()) { |
| result += prettyMessage(diag.get()); |
| } |
| return result; |
| } |
| |
| private String prettyMessage(Diagnostic diag) { |
| String result = ""; |
| for (Diagnostic child : diag.getChildren()) { |
| String message = child.getMessage(); |
| /* |
| * we remove any substring which could be the toString of some data |
| * and replace it with something which will not change on subsequent |
| * executions. |
| */ |
| for (EObject data : Iterables.filter(child.getData(), EObject.class)) { |
| String instanceVariableString = data.getClass().getName() + "@" + Integer.toHexString(data.hashCode()); |
| message = message.replace(instanceVariableString, data.eClass().getName()); |
| } |
| |
| result += "\n" + severityLabel(child.getSeverity()) + " : " + message; |
| result += prettyMessage(child); |
| } |
| return result; |
| } |
| |
| private String severityLabel(int severity) { |
| switch (severity) { |
| case Diagnostic.ERROR: |
| return "ERROR"; |
| case Diagnostic.CANCEL: |
| return "CANCEL"; |
| case Diagnostic.INFO: |
| return "INFO"; |
| case Diagnostic.WARNING: |
| return "WARNING"; |
| case Diagnostic.OK: |
| return "OK"; |
| |
| } |
| return "UNKNOWN"; |
| } |
| |
| /** |
| * Computes the tooltip of an EOperation. |
| * |
| * @param op |
| * the operation to get the tooltip from |
| * @return the tooltip of the given EOperation. |
| */ |
| public String renderEOperationTooltip(EOperation op) { |
| String validationTooltip = renderTooltip(op); |
| String operationSignature = new EOperationServices().renderEOperationTooltip(op); |
| if (validationTooltip != null && validationTooltip.length() > 0) { |
| return validationTooltip + "\n" + operationSignature; |
| } else { |
| return operationSignature; |
| } |
| } |
| |
| /** |
| * Performs a "direct edit" operation on an EOperation. |
| */ |
| public EOperation performEdit(EOperation op, String editString) { |
| return new EOperationServices().performEdit(op, editString); |
| } |
| |
| public List<ENamedElement> getAllAssociatedElements(EOperation op) { |
| return new EOperationServices().getAllAssociatedElements(op); |
| } |
| |
| /** |
| * Computes the label of an EReference. |
| */ |
| @Override |
| public String render(EReference ref) { |
| return new EReferenceServices().render(ref); |
| } |
| |
| /** |
| * Computes the label of an EReference. |
| */ |
| @Override |
| public String renderAsNode(EReference ref) { |
| return new EReferenceServices().renderAsNode(ref); |
| } |
| |
| public String renderEOpposite(EReference ref) { |
| if (ref.getEOpposite() != null) { |
| return new EReferenceServices().render(ref.getEOpposite()); |
| } |
| return ""; |
| } |
| |
| /** |
| * Performs a "direct edit" operation on an EReference. |
| */ |
| @Override |
| public EReference performEdit(EReference ref, String editString) { |
| return new EReferenceServices().performEdit(ref, editString); |
| } |
| |
| /** |
| * Finds a type matching the specified name (case-insensitive) in the same |
| * resource-set as obj, or inside Ecore itself if none could be found. |
| * |
| * @param obj |
| * the object defining the context in which to look. |
| * @param name |
| * the name of the type to look for (case-insensitive). Only |
| * basic type names are supported (no qualified names). |
| * Whitespace before or after the name is ignored. |
| * @return the first type found in the resource set or Ecore itself which |
| * matches the specified name. |
| */ |
| public EClassifier findTypeByName(EObject obj, String name) { |
| EClassifier result = findTypeByName(allRoots(obj), name); |
| if (result == null) { |
| result = findTypeByNameFrom(EcorePackage.eINSTANCE, name); |
| } |
| return result; |
| } |
| |
| /** |
| * Returns the root container; it may be this object itself |
| * |
| * @param eObject |
| * the object to get the root container for. |
| * @return the root container. |
| */ |
| public EObject getRootContainer(EObject eObject) { |
| return EcoreUtil.getRootContainer(eObject); |
| } |
| |
| private EClassifier findTypeByName(Iterable<EObject> roots, String name) { |
| for (EObject root : roots) { |
| EClassifier result = findTypeByNameFrom(root, name); |
| if (result != null) { |
| return result; |
| } |
| } |
| return null; |
| } |
| |
| private EClassifier findTypeByNameFrom(EObject root, String name) { |
| if (root instanceof EClassifier && nameMatches((EClassifier) root, name)) { |
| return (EClassifier) root; |
| } |
| for (EObject obj : AllContents.of(root)) { |
| if (obj instanceof EClassifier && nameMatches((EClassifier) obj, name)) { |
| return (EClassifier) obj; |
| } |
| } |
| return null; |
| } |
| |
| private boolean nameMatches(EClassifier type, String name) { |
| if (type != null && type.getName() != null && name != null) { |
| return type.getName().trim().equalsIgnoreCase(name.trim()); |
| } else { |
| return false; |
| } |
| } |
| |
| public Boolean hasError(EObject eObj) { |
| if (eObj instanceof EClass || eObj instanceof EStructuralFeature) { |
| DiagnosticAttachment attachment = DiagnosticAttachment.getAttachment(eObj); |
| if (attachment == null) { |
| Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eObj); |
| attachment = DiagnosticAttachment.getOrCreate(eObj, diagnostic); |
| } |
| Diagnostic diag = attachment.getDiagnostic(); |
| if (diag != null) { |
| return diag.getSeverity() == Diagnostic.ERROR; |
| } |
| } |
| return false; |
| } |
| |
| public Boolean isEDataType(EObject eObj) { |
| return eObj.eClass() == EcorePackage.eINSTANCE.getEDataType(); |
| } |
| |
| public Boolean isDDiagram(EObject any, EObject view) { |
| return view instanceof DDiagram; |
| } |
| |
| public List<EObject> eOperationSemanticElements(EOperation eOp) { |
| List result = Lists.newArrayList(Ordering.natural().onResultOf(new Function<EParameter, String>() { |
| |
| public String apply(EParameter arg0) { |
| return arg0.getName(); |
| } |
| }).sortedCopy(eOp.getEParameters())); |
| result.add(0, eOp); |
| return result; |
| } |
| |
| public Boolean viewContainerNotSemanticContainer(EObject self, DSemanticDiagram diag, |
| DSemanticDecorator containerView) { |
| return containerView.getTarget() != self.eContainer(); |
| } |
| |
| public Boolean noEOpposite(EReference ref) { |
| return ref.getEOpposite() == null; |
| } |
| |
| public boolean hasNoDocAnnotation(EObject eObj) { |
| // Error[eAnnotations.details->select(key = 'documentation')->size() = |
| // 0/] |
| if (eObj instanceof EModelElement) { |
| return EcoreUtil.getDocumentation((EModelElement) eObj) == null; |
| } |
| return true; |
| } |
| |
| public EdgeArrows arrowsFillDiamond(EObject any) { |
| return EdgeArrows.FILL_DIAMOND_LITERAL; |
| } |
| |
| public FontFormat fontFormatBold(EObject any) { |
| return FontFormat.BOLD_LITERAL; |
| } |
| |
| public void reconnectESuperTypeSource(EObject element, EObject target, EObject source, EObject otherEnd, |
| EObject edgeView, EObject sourceView) { |
| if (edgeView instanceof DEdge && ((DEdge) edgeView).getSourceNode() instanceof DSemanticDecorator |
| && ((DEdge) edgeView).getTargetNode() instanceof DSemanticDecorator) { |
| EObject newSource = ((DSemanticDecorator) ((DEdge) edgeView).getSourceNode()).getTarget(); |
| EObject newTarget = ((DSemanticDecorator) ((DEdge) edgeView).getTargetNode()).getTarget(); |
| |
| /* |
| * reconnect source: |
| */ |
| if (newSource instanceof EClass && newTarget instanceof EClass && source instanceof EClass) { |
| ((EClass) source).getESuperTypes().remove(newTarget); |
| ((EClass) newSource).getESuperTypes().add((EClass) newTarget); |
| |
| } |
| } |
| |
| } |
| |
| public void reconnectESuperTypeTarget(EObject element, EObject target, EObject source, EObject otherEnd, |
| EObject edgeView, EObject sourceView) { |
| if (edgeView instanceof DEdge && ((DEdge) edgeView).getSourceNode() instanceof DSemanticDecorator |
| && ((DEdge) edgeView).getTargetNode() instanceof DSemanticDecorator) { |
| EObject newTarget = ((DSemanticDecorator) ((DEdge) edgeView).getTargetNode()).getTarget(); |
| |
| /* |
| * reconnect target: |
| */ |
| if (newTarget instanceof EClass && target instanceof EClass && element instanceof EClass) { |
| ((EClass) element).getESuperTypes().remove(newTarget); |
| ((EClass) element).getESuperTypes().add((EClass) target); |
| |
| } |
| } |
| |
| } |
| |
| public void reconnectEReferenceSource(EObject element, EObject newValue) { |
| if (newValue instanceof EClass && element instanceof EReference) { |
| |
| EReference eRef = (EReference) element; |
| EClass srcClass = (EClass) newValue; |
| |
| if (eRef.eContainer() != srcClass) { |
| srcClass.getEStructuralFeatures().add(eRef); |
| } |
| |
| } |
| } |
| |
| public void reconnectEReferenceTarget(EObject element, EObject newValue) { |
| if (newValue != null && element instanceof EReference) { |
| |
| EReference eRef = (EReference) element; |
| |
| if (newValue instanceof EClass) { |
| EClass targetClass = (EClass) newValue; |
| if (eRef.getEType() != newValue) { |
| eRef.setEType(targetClass); |
| } |
| } else if (newValue instanceof ETypeParameter) { |
| if (eRef.getEType() != newValue) { |
| EGenericsServices.setETypeWithGenerics(eRef, newValue); |
| } |
| } |
| |
| } |
| } |
| |
| /** |
| * Create view. |
| * |
| * @param semanticElement |
| * Semantic element |
| * @param containerView |
| * Container view |
| * @param session |
| * Session |
| * @param containerViewVariable |
| * Name of the container view variable |
| */ |
| private void createView(final EObject semanticElement, final DSemanticDecorator containerView, |
| final Session session, final String containerViewVariable) { |
| // Get all available mappings applicable for the copiedElement in the |
| // current container |
| List<DiagramElementMapping> semanticElementMappings = getMappings(semanticElement, containerView, session); |
| |
| // Build a createView tool |
| final CreateView createViewOp = ToolFactory.eINSTANCE.createCreateView(); |
| for (DiagramElementMapping copiedElementMapping : semanticElementMappings) { |
| final DiagramElementMapping tmpCopiedElementMapping = copiedElementMapping; |
| createViewOp.setMapping(tmpCopiedElementMapping); |
| final String containerViewExpression = "var:" + containerViewVariable; |
| createViewOp.setContainerViewExpression(containerViewExpression); |
| |
| session.getTransactionalEditingDomain().getCommandStack() |
| .execute(new RecordingCommand(session.getTransactionalEditingDomain()) { |
| |
| @SuppressWarnings("restriction") |
| @Override |
| protected void doExecute() { |
| try { |
| // Get the command context |
| DRepresentation representation = null; |
| if (containerView instanceof DRepresentation) { |
| representation = (DRepresentation) containerView; |
| } else if (containerView instanceof DDiagramElement) { |
| representation = ((DDiagramElement) containerView).getParentDiagram(); |
| } |
| |
| final CommandContext context = new CommandContext(semanticElement, representation); |
| |
| // Execute the create view task |
| new CreateViewTask(context, session.getModelAccessor(), createViewOp, |
| session.getInterpreter()).execute(); |
| } catch (MetaClassNotFoundException e) { |
| EcoreToolsDesignPlugin.INSTANCE.log(e); |
| } catch (FeatureNotFoundException e) { |
| EcoreToolsDesignPlugin.INSTANCE.log(e); |
| } |
| } |
| }); |
| } |
| } |
| |
| /** |
| * Paste a semantic element and create the corresponding view in the given |
| * container |
| * |
| * @param container |
| * Semantic container |
| * @param semanticElement |
| * Element to paste |
| * @param containerView |
| * Container view |
| */ |
| public void paste(final EObject container, final EObject semanticElement, final DSemanticDecorator elementView, |
| final DSemanticDecorator containerView) { |
| // Paste the semantic element from the clipboard to the selected |
| // container |
| final Session session = SessionManager.INSTANCE.getSession(container); |
| TransactionalEditingDomain domain = session.getTransactionalEditingDomain(); |
| // The feature is set to null because the domain will deduce it |
| Command cmd = AddCommand.create(domain, container, null, semanticElement); |
| if (cmd.canExecute()) { |
| cmd.execute(); |
| } |
| // Create the view for the pasted element |
| createView(semanticElement, containerView, session, "containerView"); |
| } |
| |
| /** |
| * Get mappings available for a semantic element and a given container view. |
| * |
| * @param semanticElement |
| * Semantic element |
| * @param containerView |
| * Container view |
| * @param session |
| * Session |
| * @return List of mappings which could not be null |
| */ |
| @SuppressWarnings("restriction") |
| private List<DiagramElementMapping> getMappings(final EObject semanticElement, |
| final DSemanticDecorator containerView, Session session) { |
| ModelAccessor modelAccessor = session.getModelAccessor(); |
| List<DiagramElementMapping> mappings = new ArrayList<DiagramElementMapping>(); |
| |
| if (containerView instanceof DSemanticDiagram) { |
| |
| for (DiagramElementMapping mapping : (((DSemanticDiagram) containerView).getDescription() |
| .getAllContainerMappings())) { |
| String domainClass = ((AbstractNodeMapping) mapping).getDomainClass(); |
| if (modelAccessor.eInstanceOf(semanticElement, domainClass) && !mapping.isCreateElements()) { |
| mappings.add(mapping); |
| } |
| } |
| for (DiagramElementMapping mapping : (((DSemanticDiagram) containerView).getDescription() |
| .getAllNodeMappings())) { |
| String domainClass = ((AbstractNodeMapping) mapping).getDomainClass(); |
| if (modelAccessor.eInstanceOf(semanticElement, domainClass) && !mapping.isCreateElements()) { |
| mappings.add(mapping); |
| } |
| } |
| } else if (containerView instanceof DNodeContainer) { |
| for (DiagramElementMapping mapping : (((DNodeContainer) containerView).getActualMapping() |
| .getAllContainerMappings())) { |
| String domainClass = ((AbstractNodeMapping) mapping).getDomainClass(); |
| if (modelAccessor.eInstanceOf(semanticElement, domainClass) && !mapping.isCreateElements()) { |
| mappings.add(mapping); |
| } |
| } |
| for (DiagramElementMapping mapping : (((DNodeContainer) containerView).getActualMapping() |
| .getAllNodeMappings())) { |
| String domainClass = ((AbstractNodeMapping) mapping).getDomainClass(); |
| if (modelAccessor.eInstanceOf(semanticElement, domainClass) && !mapping.isCreateElements()) { |
| mappings.add(mapping); |
| } |
| } |
| } |
| return mappings; |
| } |
| |
| public String getClassesTableName(EObject cur) { |
| // [(if (oclIsKindOf(ecore::EStructuralFeature) and |
| // oclAsType(ecore::EStructuralFeature).derived) then '/' else '' endif) |
| // + name/] |
| if (cur instanceof EStructuralFeature) { |
| if (((EStructuralFeature) cur).isDerived()) { |
| return "/" + ((EStructuralFeature) cur).getName(); |
| } |
| } |
| if (cur instanceof ENamedElement) { |
| return ((ENamedElement) cur).getName(); |
| } |
| return cur.eClass().getName(); |
| } |
| |
| public boolean hasCDOBundle(EObject cur) { |
| return Platform.getBundle("org.eclipse.emf.cdo") != null; |
| } |
| |
| public EObject enableCDOGen(EObject cur, Set<GenModel> genmodels) throws IOException { |
| for (GenModel genModel : genmodels) { |
| if (isNotFromPluginsOrRegistry(genModel)) { |
| genModel.getModelPluginVariables().add("CDO=org.eclipse.emf.cdo"); |
| genModel.setRootExtendsInterface("org.eclipse.emf.cdo.CDOObject"); |
| genModel.setRootExtendsClass("org.eclipse.emf.internal.cdo.CDOObjectImpl"); |
| genModel.setFeatureDelegation(GenDelegationKind.REFLECTIVE_LITERAL); |
| genModel.setProviderRootExtendsClass("org.eclipse.emf.cdo.edit.CDOItemProviderAdapter"); |
| |
| if (genModel.eResource().getURI().isPlatformResource()) { |
| URI cdoMFURI = getCDOMFUri(genModel); |
| if (!URIConverter.INSTANCE.exists(cdoMFURI, Collections.EMPTY_MAP)) { |
| try (OutputStream out = URIConverter.INSTANCE.createOutputStream(cdoMFURI, |
| Collections.EMPTY_MAP)) { |
| new PrintWriter(out).write("This is a marker file for bundles with CDO native models."); |
| } |
| } |
| |
| } |
| |
| } |
| } |
| return cur; |
| } |
| |
| private boolean isNotFromPluginsOrRegistry(GenModel genModel) { |
| return genModel.eResource() != null && genModel.eResource().getURI() != null |
| && !genModel.eResource().getURI().isPlatformPlugin(); |
| } |
| |
| private URI getCDOMFUri(GenModel genModel) { |
| return URI.createPlatformResourceURI(genModel.eResource().getURI().segment(1), true).appendSegment("META-INF") |
| .appendSegment("CDO.MF"); |
| } |
| |
| public EObject disableCDOGen(EObject cur, Set<GenModel> genmodels) throws IOException { |
| for (GenModel genModel : genmodels) { |
| if (isNotFromPluginsOrRegistry(genModel)) { |
| genModel.getModelPluginVariables().remove("CDO=org.eclipse.emf.cdo"); |
| genModel.setRootExtendsInterface("org.eclipse.emf.ecore.EObject"); |
| genModel.setRootExtendsClass("org.eclipse.emf.ecore.impl.MinimalEObjectImpl$Container"); |
| genModel.setFeatureDelegation(GenDelegationKind.NONE_LITERAL); |
| genModel.setProviderRootExtendsClass(null); |
| |
| if (genModel.eResource().getURI().isPlatformResource()) { |
| URI cdoMFURI = getCDOMFUri(genModel); |
| if (URIConverter.INSTANCE.exists(cdoMFURI, Collections.EMPTY_MAP)) { |
| URIConverter.INSTANCE.delete(cdoMFURI, Collections.EMPTY_MAP); |
| } |
| |
| } |
| } |
| } |
| return cur; |
| } |
| |
| public String getEClassItemIconPath(GenClass cur) throws IOException { |
| String r = "/org.eclipse.emf.ecoretools.design/icons/full/obj16/empty.gif"; |
| if (cur != null && EMFPlugin.IS_RESOURCES_BUNDLE_AVAILABLE) { |
| String icon = cur.getItemIconFileName(); |
| IFile f = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(icon)); |
| if (f.exists() && f.isAccessible()) { |
| r = icon; |
| } |
| } |
| return r; |
| } |
| |
| } |