diff --git a/org.emoflon.core.dependencies/.settings/org.eclipse.jdt.core.prefs b/org.emoflon.core.dependencies/.settings/org.eclipse.jdt.core.prefs index d4540a53..3a79233b 100644 --- a/org.emoflon.core.dependencies/.settings/org.eclipse.jdt.core.prefs +++ b/org.emoflon.core.dependencies/.settings/org.eclipse.jdt.core.prefs @@ -1,10 +1,10 @@ eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 -org.eclipse.jdt.core.compiler.compliance=17 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=21 +org.eclipse.jdt.core.compiler.compliance=21 org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning org.eclipse.jdt.core.compiler.release=enabled -org.eclipse.jdt.core.compiler.source=17 +org.eclipse.jdt.core.compiler.source=21 diff --git a/org.emoflon.smartemf.dependencies/.classpath b/org.emoflon.smartemf.dependencies/.classpath index 1d64234c..6d4a7d88 100644 --- a/org.emoflon.smartemf.dependencies/.classpath +++ b/org.emoflon.smartemf.dependencies/.classpath @@ -1,6 +1,6 @@ - + diff --git a/org.emoflon.smartemf.dependencies/.settings/org.eclipse.jdt.core.prefs b/org.emoflon.smartemf.dependencies/.settings/org.eclipse.jdt.core.prefs index c05cfdd9..23fa13b1 100644 --- a/org.emoflon.smartemf.dependencies/.settings/org.eclipse.jdt.core.prefs +++ b/org.emoflon.smartemf.dependencies/.settings/org.eclipse.jdt.core.prefs @@ -1,9 +1,9 @@ eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.targetPlatform=15 -org.eclipse.jdt.core.compiler.compliance=15 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=21 +org.eclipse.jdt.core.compiler.compliance=21 org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning org.eclipse.jdt.core.compiler.release=enabled -org.eclipse.jdt.core.compiler.source=15 +org.eclipse.jdt.core.compiler.source=21 diff --git a/org.emoflon.smartemf.dependencies/META-INF/MANIFEST.MF b/org.emoflon.smartemf.dependencies/META-INF/MANIFEST.MF index 9cc0eb7f..d288ae76 100644 --- a/org.emoflon.smartemf.dependencies/META-INF/MANIFEST.MF +++ b/org.emoflon.smartemf.dependencies/META-INF/MANIFEST.MF @@ -51,5 +51,5 @@ Export-Package: org.jdom2, org.jdom2.xpath.jaxen, org.jdom2.xpath.util Require-Bundle: org.junit -Bundle-RequiredExecutionEnvironment: JavaSE-15 +Bundle-RequiredExecutionEnvironment: JavaSE-21 Automatic-Module-Name: org.emoflon.smartemf.dependencies diff --git a/org.emoflon.smartemf/src/org/emoflon/smartemf/SmartEMFGenerator.java b/org.emoflon.smartemf/src/org/emoflon/smartemf/SmartEMFGenerator.java index b2ef40ab..c32b3af6 100644 --- a/org.emoflon.smartemf/src/org/emoflon/smartemf/SmartEMFGenerator.java +++ b/org.emoflon.smartemf/src/org/emoflon/smartemf/SmartEMFGenerator.java @@ -24,38 +24,38 @@ /** * Class which generates the code */ -public class SmartEMFGenerator{ +public class SmartEMFGenerator { + + /** ########################Attributes######################## */ - /**########################Attributes########################*/ - private String path; private Collection templates; private GenModel genModel; - /**########################Constructor########################*/ + /** ########################Constructor######################## */ /** * constructs a new EMFGenerator object + * * @param ePackage to build from * @param genmodel to build with - * @param path to the original Ecore of the corresponding project - */ + * @param path to the original Ecore of the corresponding project + */ public SmartEMFGenerator(IProject project, EPackage ePackage, GenModel genmodel) { String projectPath = project.getLocation().makeAbsolute().toString(); - + // if modeldirectory contains project name -> don't duplicate it - if(genmodel.getModelDirectory().contains(project.getName())) { + if (genmodel.getModelDirectory().contains(project.getName())) { File f = new File(projectPath); path = f.getParentFile().getAbsolutePath() + "/" + genmodel.getModelDirectory() + "/"; - } - else { - path = projectPath + "/" + genmodel.getModelDirectory()+ "/"; + } else { + path = projectPath + "/" + genmodel.getModelDirectory() + "/"; } templates = new LinkedList<>(); this.genModel = genmodel; - - for(GenPackage genPkg : getGenPackages(genmodel)){ + + for (GenPackage genPkg : getGenPackages(genmodel)) { initTemplates(genPkg); } } @@ -67,65 +67,65 @@ private void initTemplates(GenPackage genPkg) { initFactoryImplementation(genPkg); initSmartEMFInterfaces(genPkg); initSmartEMFImplementations(genPkg); - - for(GenPackage subPkg : genPkg.getSubGenPackages()) { + + for (GenPackage subPkg : genPkg.getSubGenPackages()) { initTemplates(subPkg); } } - + private Collection getGenPackages(GenModel genmodel) { Collection visited = new HashSet<>(); Collection unvisited = new HashSet<>(); unvisited.addAll(genmodel.getGenPackages()); - while(!unvisited.isEmpty()) { + while (!unvisited.isEmpty()) { GenPackage next = unvisited.iterator().next(); visited.add(next); unvisited.remove(next); - + unvisited.addAll(next.getSubGenPackages()); } return visited; } - + private void initPackageInterface(GenPackage genPkg) { PackageInterfaceTemplate creator = new PackageInterfaceTemplate(genPkg, path); templates.add(creator); - - for(org.eclipse.emf.ecore.EEnum eenum : TemplateUtil.getEEnums(genPkg)){ + + for (org.eclipse.emf.ecore.EEnum eenum : TemplateUtil.getEEnums(genPkg)) { EEnumTemplate eenum_creator = new EEnumTemplate(genPkg, eenum, path); templates.add(eenum_creator); } } - + private void initPackageImplementation(GenPackage genPkg) { PackageImplTemplate creator = new PackageImplTemplate(genPkg, path); templates.add(creator); } - + private void initFactoryInterface(GenPackage genPkg) { FactoryInterfaceTemplate creator = new FactoryInterfaceTemplate(genPkg, path); templates.add(creator); } - + private void initFactoryImplementation(GenPackage genPkg) { FactoryImplTemplate creator = new FactoryImplTemplate(genPkg, path); templates.add(creator); } - + private void initSmartEMFInterfaces(GenPackage genPkg) { - for(EClassifier classifier : genPkg.getEcorePackage().getEClassifiers()){ - if(classifier instanceof EClass eClass) { + for (EClassifier classifier : genPkg.getEcorePackage().getEClassifiers()) { + if (classifier instanceof EClass eClass) { SmartEMFInterfaceTemplate interfaceTemplate = new SmartEMFInterfaceTemplate(genPkg, eClass, path); - templates.add(interfaceTemplate); + templates.add(interfaceTemplate); } } - + } - + private void initSmartEMFImplementations(GenPackage genPkg) { - for(EClassifier classifier : genPkg.getEcorePackage().getEClassifiers()){ - if(classifier instanceof EClass eClass) { - if(eClass.isInterface()) { + for (EClassifier classifier : genPkg.getEcorePackage().getEClassifiers()) { + if (classifier instanceof EClass eClass) { + if (eClass.isInterface()) { continue; } SmartEMFObjectTemplate implTemplate = new SmartEMFObjectTemplate(genPkg, eClass, path); diff --git a/org.emoflon.smartemf/src/org/emoflon/smartemf/persistence/AdapterList.java b/org.emoflon.smartemf/src/org/emoflon/smartemf/persistence/AdapterList.java index 2d9d2fe7..33390deb 100644 --- a/org.emoflon.smartemf/src/org/emoflon/smartemf/persistence/AdapterList.java +++ b/org.emoflon.smartemf/src/org/emoflon/smartemf/persistence/AdapterList.java @@ -13,11 +13,11 @@ public class AdapterList implements EList { private Collection adapters = new LinkedHashSet<>(); private SmartEMFResource resource; - + public AdapterList(SmartEMFResource resource) { this.resource = resource; } - + @Override public int size() { return adapters.size(); @@ -50,7 +50,7 @@ public T[] toArray(T[] a) { @Override public boolean add(Adapter e) { - if(!adapters.contains(e)) { + if (!adapters.contains(e)) { boolean result = adapters.add(e); resource.adapterAdded(e); return result; @@ -76,7 +76,7 @@ public boolean containsAll(Collection c) { @Override public boolean addAll(Collection c) { boolean changed = false; - for(Adapter a : c) { + for (Adapter a : c) { changed = changed || add(a); } return changed; @@ -90,10 +90,10 @@ public boolean addAll(int index, Collection c) { @Override public boolean removeAll(Collection c) { boolean changed = false; - for(Object a : c) { + for (Object a : c) { boolean success = remove(a); changed = changed || success; - if(success) + if (success) resource.sendRemoveAdapterMessages((Adapter) a); } return changed; diff --git a/org.emoflon.smartemf/src/org/emoflon/smartemf/persistence/JDOMXmiUnparser.java b/org.emoflon.smartemf/src/org/emoflon/smartemf/persistence/JDOMXmiUnparser.java index 1f268271..bb609140 100644 --- a/org.emoflon.smartemf/src/org/emoflon/smartemf/persistence/JDOMXmiUnparser.java +++ b/org.emoflon.smartemf/src/org/emoflon/smartemf/persistence/JDOMXmiUnparser.java @@ -26,305 +26,316 @@ public class JDOMXmiUnparser { - Map metamodel2NS = new HashMap<> (); - Map object2ID = new HashMap<>(); - Map>> waitingCrossRefs = new HashMap<>(); - - public void modelToJDOMTree(final Resource resource, final Document domTree) throws IOException { - // Create tree by traversing model - if(resource.getContents().size()> 1 || resource.getContents().size()< 1) { - Element root = new Element(XmiParserUtil.XMI_ROOT_NODE, XmiParserUtil.XMI_NS, XmiParserUtil.XMI_URI); - domTree.setRootElement(root); - - int idx = 0; - for(EObject container : resource.getContents()) { - root.getChildren().add(createDOMTree(container, container, null, "/"+idx, 0, false)); - idx++; - } - } else { - EObject container = resource.getContents().get(0); - domTree.setRootElement(createDOMTree(container, container, null, "/", 0, false)); + Map metamodel2NS = new HashMap<>(); + Map object2ID = new HashMap<>(); + Map>> waitingCrossRefs = new HashMap<>(); + + public void modelToJDOMTree(final Resource resource, final Document domTree) throws IOException { + // Create tree by traversing model + if (resource.getContents().size() > 1 || resource.getContents().size() < 1) { + Element root = new Element(XmiParserUtil.XMI_ROOT_NODE, XmiParserUtil.XMI_NS, XmiParserUtil.XMI_URI); + domTree.setRootElement(root); + + int idx = 0; + for (EObject container : resource.getContents()) { + root.getChildren().add(createDOMTree(container, container, null, "/" + idx, 0, false)); + idx++; } - - // Resolve unresolved Cross-Refs -> These are HRefs to foreign models - for(EObject href : waitingCrossRefs.keySet()) { - if(href.eResource() == resource) { - throw new IOException("Cross-reference to "+href+" could not be resolved during saving."); - } - - // Explore and index foreign model - if(!object2ID.containsKey(href)) { - indexForeignResource(href.eResource()); + } else { + EObject container = resource.getContents().get(0); + domTree.setRootElement(createDOMTree(container, container, null, "/", 0, false)); + } + + // Resolve unresolved Cross-Refs -> These are HRefs to foreign models + for (EObject href : waitingCrossRefs.keySet()) { + if (href.eResource() == resource) { + throw new IOException("Cross-reference to " + href + " could not be resolved during saving."); + } + + // Explore and index foreign model + if (!object2ID.containsKey(href)) { + indexForeignResource(href.eResource()); + } + + String foreignID = object2ID.get(href); + waitingCrossRefs.get(href).forEach(waiting -> waiting.accept(foreignID)); + } + + // Add default xmi namespaces and version attribute + if (resource.getContents().size() <= 1) { + Namespace xmiNS = Namespace.getNamespace(XmiParserUtil.XMI_NS, XmiParserUtil.XMI_URI); + domTree.getRootElement().addNamespaceDeclaration(xmiNS); + } + + Namespace xsiNS = Namespace.getNamespace(XmiParserUtil.XSI_NS, XmiParserUtil.XSI_URI); + domTree.getRootElement().addNamespaceDeclaration(xsiNS); + + for (EPackage pkg : metamodel2NS.keySet()) { + domTree.getRootElement().addNamespaceDeclaration(metamodel2NS.get(pkg)); + } + + domTree.getRootElement().getAttributes().add(new Attribute(XmiParserUtil.XMI_VERSION_ATR, + XmiParserUtil.XMI_VERSION, Namespace.getNamespace(XmiParserUtil.XMI_NS, XmiParserUtil.XMI_URI))); + } + + @SuppressWarnings("unchecked") + protected Element createDOMTree(EObject root, EObject currentEObject, EReference containment, String id, int idx, + boolean useSimple) throws IOException { + EClass currentClass = currentEObject.eClass(); + EPackage metamodel = currentClass.getEPackage(); + + Namespace ns = null; + if (!metamodel2NS.containsKey(metamodel)) { + ns = Namespace.getNamespace(metamodel.getName(), metamodel.getNsURI()); + metamodel2NS.put(metamodel, ns); + } else { + ns = metamodel2NS.get(metamodel); + } + + String currentId = id; + Element current = null; + if (containment != null) { + current = new Element(containment.getName()); + EPackage rootMetamodel = root.eClass().getEPackage(); + if (metamodel != rootMetamodel) { + current.getAttributes() + .add(new Attribute(XmiParserUtil.XSI_TYPE, + metamodel2NS.get(metamodel).getPrefix() + ":" + currentClass.getName(), + Namespace.getNamespace(XmiParserUtil.XSI_NS, XmiParserUtil.XSI_URI))); + } else { + // If the current object is a sub-type of the edge type then this must be + // defined in the xmi model + if (!containment.getEType().equals(currentEObject.eClass())) { + current.getAttributes() + .add(new Attribute(XmiParserUtil.XSI_TYPE, ns.getPrefix() + ":" + currentClass.getName(), + Namespace.getNamespace(XmiParserUtil.XSI_NS, XmiParserUtil.XSI_URI))); } - - String foreignID = object2ID.get(href); - waitingCrossRefs.get(href).forEach(waiting -> waiting.accept(foreignID)); } - - // Add default xmi namespaces and version attribute - if(resource.getContents().size() <= 1) { - Namespace xmiNS = Namespace.getNamespace(XmiParserUtil.XMI_NS, XmiParserUtil.XMI_URI); - domTree.getRootElement().addNamespaceDeclaration(xmiNS); + + // This a workaround for a useless/annoying xml simplification that occurs when + // a child list is exactly of size 1, then the index is omitted. + if (useSimple) { + currentId = id + "/@" + containment.getName(); + } else { + currentId = id + "/@" + containment.getName() + "." + idx; } - - Namespace xsiNS = Namespace.getNamespace(XmiParserUtil.XSI_NS, XmiParserUtil.XSI_URI); - domTree.getRootElement().addNamespaceDeclaration(xsiNS); - - for(EPackage pkg : metamodel2NS.keySet()) { - domTree.getRootElement().addNamespaceDeclaration(metamodel2NS.get(pkg)); + + } else { + current = new Element(currentClass.getName(), ns); + } + + object2ID.put(currentEObject, currentId); + if (waitingCrossRefs.containsKey(currentEObject)) { + for (Consumer consumer : waitingCrossRefs.get(currentEObject)) { + consumer.accept(currentId); } - - domTree.getRootElement().getAttributes().add(new Attribute(XmiParserUtil.XMI_VERSION_ATR, XmiParserUtil.XMI_VERSION, Namespace.getNamespace(XmiParserUtil.XMI_NS, XmiParserUtil.XMI_URI))); + waitingCrossRefs.remove(currentEObject); } - - @SuppressWarnings("unchecked") - protected Element createDOMTree(EObject root, EObject currentEObject, EReference containment, String id, int idx, boolean useSimple) throws IOException { - EClass currentClass = currentEObject.eClass(); - EPackage metamodel = currentClass.getEPackage(); - - Namespace ns = null; - if(!metamodel2NS.containsKey(metamodel)) { - ns = Namespace.getNamespace(metamodel.getName(), metamodel.getNsURI()); - metamodel2NS.put(metamodel, ns); + + // Containments + for (EReference containmentRef : currentClass.getEAllContainments()) { + List containees = new LinkedList<>(); + if (containmentRef.isMany()) { + containees.addAll((Collection) currentEObject.eGet(containmentRef)); } else { - ns = metamodel2NS.get(metamodel); + EObject containee = (EObject) currentEObject.eGet(containmentRef); + if (containee != null) + containees.add(containee); } - - String currentId = id; - Element current = null; - if(containment != null) { - current = new Element(containment.getName()); - EPackage rootMetamodel = root.eClass().getEPackage(); - if(metamodel != rootMetamodel) { - current.getAttributes().add(new Attribute(XmiParserUtil.XSI_TYPE, metamodel2NS.get(metamodel).getPrefix()+":"+currentClass.getName(), - Namespace.getNamespace(XmiParserUtil.XSI_NS, XmiParserUtil.XSI_URI))); - } else { - // If the current object is a sub-type of the edge type then this must be defined in the xmi model - if(!containment.getEType().equals(currentEObject.eClass())) { - current.getAttributes().add(new Attribute(XmiParserUtil.XSI_TYPE, ns.getPrefix()+":"+currentClass.getName(), - Namespace.getNamespace(XmiParserUtil.XSI_NS, XmiParserUtil.XSI_URI))); + int idIDX = 0; + for (EObject containee : containees) { + current.getChildren().add( + createDOMTree(root, containee, containmentRef, currentId, idIDX, !containmentRef.isMany())); + idIDX++; + } + } + + // Crossrefs + for (EReference crossRef : currentClass.getEAllReferences().stream().filter(ref -> !ref.isContainment()) + .filter(ref -> { + if (!(metamodel instanceof SmartPackage)) { + return true; + } else { + SmartPackage smartMetamodel = (SmartPackage) metamodel; + return !smartMetamodel.isDynamicEStructuralFeature(currentClass, ref); } - } - - // This a workaround for a useless/annoying xml simplification that occurs when a child list is exactly of size 1, then the index is omitted. - if(useSimple) { - currentId = id + "/@" + containment.getName(); - } else { - currentId = id + "/@" + containment.getName() + "." + idx; - } - + }).collect(Collectors.toList())) { + + LinkedList refs = new LinkedList<>(); + if (crossRef.isMany()) { + refs.addAll((Collection) currentEObject.eGet(crossRef)); } else { - current = new Element(currentClass.getName(), ns); - } - - object2ID.put(currentEObject, currentId); - if(waitingCrossRefs.containsKey(currentEObject)) { - for(Consumer consumer : waitingCrossRefs.get(currentEObject)) { - consumer.accept(currentId); - } - waitingCrossRefs.remove(currentEObject); + EObject currentRef = (EObject) currentEObject.eGet(crossRef); + if (currentRef != null) + refs.add(currentRef); } - - // Containments - for(EReference containmentRef : currentClass.getEAllContainments()) { - List containees = new LinkedList<>(); - if(containmentRef.isMany()) { - containees.addAll((Collection) currentEObject.eGet(containmentRef)); - } else { - EObject containee = (EObject) currentEObject.eGet(containmentRef); - if(containee != null) - containees.add(containee); - } - int idIDX = 0; - for(EObject containee : containees) { - current.getChildren().add(createDOMTree(root, containee, containmentRef, currentId, idIDX, !containmentRef.isMany())); - idIDX++; - } - } - - // Crossrefs - for(EReference crossRef : currentClass.getEAllReferences().stream() - .filter(ref -> !ref.isContainment()) - .filter(ref -> { - if(!(metamodel instanceof SmartPackage)) { - return true; - } else { - SmartPackage smartMetamodel = (SmartPackage) metamodel; - return !smartMetamodel.isDynamicEStructuralFeature(currentClass, ref); - } - }).collect(Collectors.toList())) { - - LinkedList refs = new LinkedList<>(); - if(crossRef.isMany()) { - refs.addAll((Collection) currentEObject.eGet(crossRef)); + if (refs.isEmpty()) + continue; + + Attribute refAtr = new Attribute(crossRef.getName(), ""); + PendingXMLCrossReference pendingCrossRefs = new PendingXMLCrossReference(current, refAtr, refs.size()); + if (refs.size() < 2) { + EObject refObj = refs.get(0); + // Ignore dangling references + if (refObj.eResource() == null) + continue; + + if (object2ID.containsKey(refObj)) { + pendingCrossRefs.insertID(object2ID.get(refObj), 0); } else { - EObject currentRef = (EObject) currentEObject.eGet(crossRef); - if(currentRef != null) - refs.add(currentRef); + // Remember this crossRef and wait for traversal + Set> otherPendingRefs = waitingCrossRefs.get(refObj); + if (otherPendingRefs == null) { + otherPendingRefs = new LinkedHashSet<>(); + waitingCrossRefs.put(refObj, otherPendingRefs); + } + + if (refObj.eResource() == currentEObject.eResource()) { + otherPendingRefs.add((crossRefID) -> { + pendingCrossRefs.insertID(crossRefID, 0); + if (pendingCrossRefs.isCompleted()) { + pendingCrossRefs.writeBack(); + } + }); + } else { + // this is reference to a foreign element -> href! + otherPendingRefs.add((crossRefID) -> { + pendingCrossRefs.insertID(crossRefID, 0); + EPackage otherMetamodel = refObj.eClass().getEPackage(); + if (!metamodel2NS.containsKey(otherMetamodel)) { + Namespace otherNS = Namespace.getNamespace(otherMetamodel.getName(), + otherMetamodel.getNsURI()); + metamodel2NS.put(otherMetamodel, otherNS); + } + if (otherMetamodel != metamodel) { + pendingCrossRefs.elementIsHref(true, 0, crossRef.getName(), + metamodel2NS.get(otherMetamodel).getPrefix() + ":" + refObj.eClass().getName()); + } else { + pendingCrossRefs.elementIsHref(true, 0, crossRef.getName(), null); + } + + if (pendingCrossRefs.isCompleted()) { + pendingCrossRefs.writeBack(); + } + }); + } + } - if(refs.isEmpty()) - continue; - - - Attribute refAtr = new Attribute(crossRef.getName(), ""); - PendingXMLCrossReference pendingCrossRefs = new PendingXMLCrossReference(current, refAtr, refs.size()); - if(refs.size()<2) { - EObject refObj = refs.get(0); - //Ignore dangling references - if(refObj.eResource() == null) + + } else if (refs.size() > 1) { + int crossRefIdx = 0; + for (EObject ref : refs) { + // Ignore dangling references + if (ref.eResource() == null) continue; - - if(object2ID.containsKey(refObj)) { - pendingCrossRefs.insertID(object2ID.get(refObj), 0); + + if (object2ID.containsKey(ref)) { + pendingCrossRefs.insertID(object2ID.get(ref), crossRefIdx); } else { // Remember this crossRef and wait for traversal - Set> otherPendingRefs = waitingCrossRefs.get(refObj); - if(otherPendingRefs == null) { + Set> otherPendingRefs = waitingCrossRefs.get(ref); + if (otherPendingRefs == null) { otherPendingRefs = new LinkedHashSet<>(); - waitingCrossRefs.put(refObj, otherPendingRefs); + waitingCrossRefs.put(ref, otherPendingRefs); } - - if(refObj.eResource() == currentEObject.eResource()) { + final int currentIdx = crossRefIdx; + + if (ref.eResource() == currentEObject.eResource()) { otherPendingRefs.add((crossRefID) -> { - pendingCrossRefs.insertID(crossRefID, 0); - if(pendingCrossRefs.isCompleted()) { + pendingCrossRefs.insertID(crossRefID, currentIdx); + if (pendingCrossRefs.isCompleted()) { pendingCrossRefs.writeBack(); } }); } else { // this is reference to a foreign element -> href! otherPendingRefs.add((crossRefID) -> { - pendingCrossRefs.insertID(crossRefID, 0); - EPackage otherMetamodel = refObj.eClass().getEPackage(); - if(!metamodel2NS.containsKey(otherMetamodel)) { - Namespace otherNS = Namespace.getNamespace(otherMetamodel.getName(), otherMetamodel.getNsURI()); + pendingCrossRefs.insertID(crossRefID, currentIdx); + EPackage otherMetamodel = ref.eClass().getEPackage(); + if (!metamodel2NS.containsKey(otherMetamodel)) { + Namespace otherNS = Namespace.getNamespace(otherMetamodel.getName(), + otherMetamodel.getNsURI()); metamodel2NS.put(otherMetamodel, otherNS); } - if(otherMetamodel != metamodel) { - pendingCrossRefs.elementIsHref(true, 0, crossRef.getName(), metamodel2NS.get(otherMetamodel).getPrefix()+":"+refObj.eClass().getName()); + if (otherMetamodel != metamodel) { + pendingCrossRefs.elementIsHref(true, currentIdx, crossRef.getName(), + metamodel2NS.get(otherMetamodel).getPrefix() + ":" + + ref.eClass().getName()); } else { - pendingCrossRefs.elementIsHref(true, 0, crossRef.getName(), null); + pendingCrossRefs.elementIsHref(true, currentIdx, crossRef.getName(), null); } - - if(pendingCrossRefs.isCompleted()) { + + if (pendingCrossRefs.isCompleted()) { pendingCrossRefs.writeBack(); } }); } - - } - - - } else if(refs.size()>1) { - int crossRefIdx = 0; - for(EObject ref : refs) { - //Ignore dangling references - if(ref.eResource() == null) - continue; - - if(object2ID.containsKey(ref)) { - pendingCrossRefs.insertID(object2ID.get(ref), crossRefIdx); - } else { - // Remember this crossRef and wait for traversal - Set> otherPendingRefs = waitingCrossRefs.get(ref); - if(otherPendingRefs == null) { - otherPendingRefs = new LinkedHashSet<>(); - waitingCrossRefs.put(ref, otherPendingRefs); - } - final int currentIdx = crossRefIdx; - - if(ref.eResource() == currentEObject.eResource()) { - otherPendingRefs.add((crossRefID) -> { - pendingCrossRefs.insertID(crossRefID, currentIdx); - if(pendingCrossRefs.isCompleted()) { - pendingCrossRefs.writeBack(); - } - }); - } else { - // this is reference to a foreign element -> href! - otherPendingRefs.add((crossRefID) -> { - pendingCrossRefs.insertID(crossRefID, currentIdx); - EPackage otherMetamodel = ref.eClass().getEPackage(); - if(!metamodel2NS.containsKey(otherMetamodel)) { - Namespace otherNS = Namespace.getNamespace(otherMetamodel.getName(), otherMetamodel.getNsURI()); - metamodel2NS.put(otherMetamodel, otherNS); - } - if(otherMetamodel != metamodel) { - pendingCrossRefs.elementIsHref(true, currentIdx, crossRef.getName(), metamodel2NS.get(otherMetamodel).getPrefix()+":"+ref.eClass().getName()); - } else { - pendingCrossRefs.elementIsHref(true, currentIdx, crossRef.getName(), null); - } - - if(pendingCrossRefs.isCompleted()) { - pendingCrossRefs.writeBack(); - } - }); - } - - } - crossRefIdx++; + } - + crossRefIdx++; } - - if(pendingCrossRefs.isCompleted()) - pendingCrossRefs.writeBack(); - + } - - // Attributes - for(EAttribute attribute : currentClass.getEAllAttributes()) { - String value = XmiParserUtil.valueToString(attribute, currentEObject.eGet(attribute)); - if(value == null) - continue; - - Attribute refAtr = new Attribute(attribute.getName(), value); - current.getAttributes().add(refAtr); + + if (pendingCrossRefs.isCompleted()) + pendingCrossRefs.writeBack(); + + } + + // Attributes + for (EAttribute attribute : currentClass.getEAllAttributes()) { + String value = XmiParserUtil.valueToString(attribute, currentEObject.eGet(attribute)); + if (value == null) + continue; + + Attribute refAtr = new Attribute(attribute.getName(), value); + current.getAttributes().add(refAtr); + } + return current; + } + + protected void indexForeignResource(final Resource resource) { + if (resource.getContents().size() < 2) { + indexForeignModel(resource.getContents().get(0), null, resource.getURI().toString() + "#/", 0, false); + } else { + int idx = 0; + for (EObject container : resource.getContents()) { + indexForeignModel(container, null, resource.getURI().toString() + "#/" + idx++, 0, false); } - return current; } - - protected void indexForeignResource(final Resource resource) { - if(resource.getContents().size() < 2) { - indexForeignModel(resource.getContents().get(0), null, resource.getURI().toString()+"#/", 0, false); + + } + + @SuppressWarnings("unchecked") + protected void indexForeignModel(final EObject root, final EReference containment, final String id, int idx, + boolean useSimple) { + EClass rootClass = root.eClass(); + String rootId = id; + if (containment != null) { + if (useSimple) { + rootId = id + "/@" + containment.getName(); } else { - int idx = 0; - for(EObject container : resource.getContents()) { - indexForeignModel(container, null, resource.getURI().toString()+"#/"+idx++, 0, false); - } + rootId = id + "/@" + containment.getName() + "." + idx; } - } - - @SuppressWarnings("unchecked") - protected void indexForeignModel(final EObject root, final EReference containment, final String id, int idx, boolean useSimple) { - EClass rootClass = root.eClass(); - String rootId = id; - if(containment != null) { - if(useSimple) { - rootId = id + "/@" + containment.getName(); - } else { - rootId = id + "/@" + containment.getName() + "." + idx; - } + object2ID.put(root, rootId); + + // Containments + for (EReference containmentRef : rootClass.getEAllContainments()) { + List containees = new LinkedList<>(); + if (containmentRef.isMany()) { + containees.addAll((Collection) root.eGet(containmentRef)); + } else { + EObject containee = (EObject) root.eGet(containmentRef); + if (containee != null) + containees.add(containee); } - object2ID.put(root, rootId); - - // Containments - for(EReference containmentRef : rootClass.getEAllContainments()) { - List containees = new LinkedList<>(); - if(containmentRef.isMany()) { - containees.addAll((Collection) root.eGet(containmentRef)); - } else { - EObject containee = (EObject) root.eGet(containmentRef); - if(containee != null) - containees.add(containee); - } - int idIDX = 0; - for(EObject containee : containees) { - indexForeignModel(containee, containmentRef, rootId, idIDX, !containmentRef.isMany()); - idIDX++; - } + int idIDX = 0; + for (EObject containee : containees) { + indexForeignModel(containee, containmentRef, rootId, idIDX, !containmentRef.isMany()); + idIDX++; } } + } } \ No newline at end of file diff --git a/org.emoflon.smartemf/src/org/emoflon/smartemf/persistence/PendingEMFCrossReference.java b/org.emoflon.smartemf/src/org/emoflon/smartemf/persistence/PendingEMFCrossReference.java index bd2f9cad..ab39c79d 100644 --- a/org.emoflon.smartemf/src/org/emoflon/smartemf/persistence/PendingEMFCrossReference.java +++ b/org.emoflon.smartemf/src/org/emoflon/smartemf/persistence/PendingEMFCrossReference.java @@ -11,25 +11,25 @@ public class PendingEMFCrossReference { final private EReference reference; final private EObject[] crossRefs; private int insertedObjects = 0; - + public PendingEMFCrossReference(final EObject node, final EReference reference, int numOfRefs) { this.node = node; this.reference = reference; crossRefs = new EObject[numOfRefs]; } - + public void insertObject(final EObject ref, int idx) { crossRefs[idx] = ref; insertedObjects++; } - + public boolean isCompleted() { return insertedObjects == crossRefs.length; } - + @SuppressWarnings("unchecked") public void writeBack() { - if(reference.isMany()) { + if (reference.isMany()) { List refs = (List) node.eGet(reference); refs.addAll(Arrays.asList(crossRefs)); } else { diff --git a/org.emoflon.smartemf/src/org/emoflon/smartemf/persistence/PendingXMLCrossReference.java b/org.emoflon.smartemf/src/org/emoflon/smartemf/persistence/PendingXMLCrossReference.java index 398f4a3b..ead40353 100644 --- a/org.emoflon.smartemf/src/org/emoflon/smartemf/persistence/PendingXMLCrossReference.java +++ b/org.emoflon.smartemf/src/org/emoflon/smartemf/persistence/PendingXMLCrossReference.java @@ -15,40 +15,41 @@ class PendingXMLCrossReference { final Map idx2name = new HashMap<>(); final Map idx2Type = new HashMap<>(); private int insertedIds = 0; - + public PendingXMLCrossReference(final Element element, final Attribute attribute, int numOfIds) { this.element = element; this.attribute = attribute; ids = new String[numOfIds]; isHref = new boolean[numOfIds]; } - + public void insertID(final String id, int idx) { ids[idx] = id; insertedIds++; } - + public void elementIsHref(boolean isHref, int idx, final String name, final String type) { this.isHref[idx] = isHref; idx2name.put(idx, name); - if(type != null) + if (type != null) idx2Type.put(idx, type); } - + public boolean isCompleted() { return insertedIds == ids.length; } - - public void writeBack() { + + public void writeBack() { StringBuilder sb = new StringBuilder(); - for(int i = 0; i eAdapters() { @Override /** - * returns whether message should be delivered, which is redirected to the containing resource + * returns whether message should be delivered, which is redirected to the + * containing resource */ public boolean eDeliver() { return eResource().eDeliver(); @@ -160,7 +161,8 @@ protected Object eDynamicGet(EStructuralFeature feature) { return null; } } else { - throw new RuntimeException("Feature <" + feature + "> is not present in objects of EClass <" + staticClass + ">"); + throw new RuntimeException( + "Feature <" + feature + "> is not present in objects of EClass <" + staticClass + ">"); } } } @@ -169,7 +171,8 @@ protected void eDynamicSet(EStructuralFeature feature, Object value) { Object oldValue = null; if (feature2Value.containsKey(feature)) { if (feature.isMany()) { - throw new RuntimeException("Feature <" + feature + "> represents a collection. Set can not be used on collection type attributes."); + throw new RuntimeException("Feature <" + feature + + "> represents a collection. Set can not be used on collection type attributes."); } else { oldValue = feature2Value.replace(feature, value); } @@ -177,13 +180,14 @@ protected void eDynamicSet(EStructuralFeature feature, Object value) { } else { if (staticPackage.isDynamicEStructuralFeature(staticClass, feature)) { if (feature.isMany()) { - throw new RuntimeException( - "Feature <" + feature + "> represents a collection. Set can not be used on collection type attributes."); + throw new RuntimeException("Feature <" + feature + + "> represents a collection. Set can not be used on collection type attributes."); } else { feature2Value.put(feature, value); } } else { - throw new RuntimeException("Feature <" + feature + "> is not present in objects of EClass <" + staticClass + ">"); + throw new RuntimeException( + "Feature <" + feature + "> is not present in objects of EClass <" + staticClass + ">"); } } @@ -236,7 +240,8 @@ protected void eDynamicUnset(EStructuralFeature feature) { feature2Value.put(feature, null); } } else { - throw new RuntimeException("Feature <" + feature + "> is not present in objects of EClass <" + staticClass + ">"); + throw new RuntimeException( + "Feature <" + feature + "> is not present in objects of EClass <" + staticClass + ">"); } } @@ -245,7 +250,8 @@ protected void eDynamicUnset(EStructuralFeature feature) { @SuppressWarnings("unchecked") protected void eDynamicInverseAdd(Object otherEnd, EStructuralFeature feature) { if (feature.isMany()) { - SmartCollection> list = (SmartCollection>) eGet(feature); + SmartCollection> list = (SmartCollection>) eGet( + feature); if (list.addInternal(otherEnd, false) == NotifyStatus.SUCCESS_NO_NOTIFICATION) { // sendNotification(SmartEMFNotification.createAddNotification(this, feature, otherEnd, -1)); } @@ -257,7 +263,8 @@ protected void eDynamicInverseAdd(Object otherEnd, EStructuralFeature feature) { @SuppressWarnings("unchecked") protected void eDynamicInverseRemove(Object otherEnd, EStructuralFeature feature) { if (feature.isMany()) { - SmartCollection> list = (SmartCollection>) eGet(feature); + SmartCollection> list = (SmartCollection>) eGet( + feature); list.removeInternal(otherEnd, false, true); } else { eUnset(feature); @@ -268,9 +275,9 @@ protected void eDynamicInverseRemove(Object otherEnd, EStructuralFeature feature public boolean eIsSet(EStructuralFeature feature) { Object obj = eGet(feature); if (feature.isMany()) { - if(obj instanceof Collection col) + if (obj instanceof Collection col) return !col.isEmpty(); - if(obj instanceof Map map) + if (obj instanceof Map map) return !map.isEmpty(); else throw new RuntimeException("Feature " + feature.getName() + " is neither a map nor a collection."); @@ -301,13 +308,14 @@ public EStructuralFeature eContainingFeature() { * @return status of execution and if a REMOVE notification was sent or not */ public NotifyStatus resetContainment() { - // if there is no eContainer, then this element is only contained within the resource and should be + // if there is no eContainer, then this element is only contained within the + // resource and should be // removed if (eContainer == null && resource != null) { resource.getContents().remove(this); } - setResource(null, true); + var setResourceState = setResource(null, true); if (eContainingFeature == null) return NotifyStatus.SUCCESS_NO_NOTIFICATION; @@ -317,14 +325,17 @@ public NotifyStatus resetContainment() { eContainer = null; eContainingFeature = null; - if(oldFeature.isMany()) { - if(((Collection) oldContainer.eGet(oldFeature)).remove(this)) { + if (oldFeature.isMany()) { + if(setResourceState == NotifyStatus.SUCCESS_NOTIFICATION_SEND) { + ((SmartCollection) oldContainer.eGet(oldFeature)).removeInternal(this, true, false); + return NotifyStatus.SUCCESS_NOTIFICATION_SEND; + } + if (((Collection) oldContainer.eGet(oldFeature)).remove(this)) { return NotifyStatus.SUCCESS_NOTIFICATION_SEND; } else { return NotifyStatus.FAILURE_NO_NOTIFICATION; } - } - else { + } else { oldContainer.eUnset(oldFeature); } @@ -343,29 +354,31 @@ public NotifyStatus setContainment(EObject eContainer, EStructuralFeature featur NotifyStatus status = NotifyStatus.FAILURE_NO_NOTIFICATION; // clean up old containment - // we don't use resetContainment here to optimize the number of generated notifications + // we don't use resetContainment here to optimize the number of generated + // notifications if (this.eContainer != null) { if (eContainingFeature.isMany()) { // remove quietly if element is only moved within the same resource - if(eContainer != null && resource != null && resource.equals(eContainer.eResource())) - ((SmartCollection) this.eContainer.eGet(eContainingFeature)).removeWithoutContainerResetting(this); + if (eContainer != null && resource != null && resource.equals(eContainer.eResource())) + ((SmartCollection) this.eContainer.eGet(eContainingFeature)) + .removeWithoutContainerResetting(this); else - ((SmartCollection) this.eContainer.eGet(eContainingFeature)).remove(this); + ((SmartCollection) this.eContainer.eGet(eContainingFeature)).remove(this); } else { // remove quietly if element is only moved within the same resource - if(eContainer != null && resource != null && resource.equals(eContainer.eResource())) { + if (eContainer != null && resource != null && resource.equals(eContainer.eResource())) { Resource.Internal tmp = resource; resource = null; ((SmartObject) this.eContainer).eUnset(eContainingFeature); resource = tmp; - } - else { + } else { ((SmartObject) this.eContainer).eUnset(eContainingFeature); } } status = NotifyStatus.SUCCESS_NOTIFICATION_SEND; } else { - // if there is no eContainer, then this element is only contained within the resource and should be + // if there is no eContainer, then this element is only contained within the + // resource and should be // removed before setting the new eContainer if (resource != null) { resource.getContents().remove(this); @@ -416,7 +429,7 @@ public void sendRemoveAdapterNotificationsRecursively(Adapter adapter) { setResourceOfContainments((o) -> o.sendRemoveAdapterNotificationsRecursively(adapter)); } - + public void setResourceWithoutChecks(Internal resource) { this.resource = resource; } @@ -430,7 +443,8 @@ public NotifyStatus setResource(Resource resource, boolean sendNotification) { return NotifyStatus.SUCCESS_NO_NOTIFICATION; // send remove messages to old adapters - // TODO lfritsche: should we optimize this and only do this if the adapters of both resources + // TODO lfritsche: should we optimize this and only do this if the adapters of + // both resources // differ? sendRemoveAdapterNotification(this); @@ -441,22 +455,26 @@ public NotifyStatus setResource(Resource resource, boolean sendNotification) { NotifyStatus status = NotifyStatus.SUCCESS_NO_NOTIFICATION; if (resource != null) { if (sendNotification) { - // if container is null, then this element is a root element within a resource and notifications are + // if container is null, then this element is a root element within a resource + // and notifications are // handled there if (eContainer() == null) { sendNotification(SmartEMFNotification.createAddNotification(resource, null, this, -1)); status = NotifyStatus.SUCCESS_NOTIFICATION_SEND; } else if (eContainingFeature().isMany()) { - sendNotification(SmartEMFNotification.createAddNotification(eContainer(), eContainingFeature(), this, -1)); + sendNotification( + SmartEMFNotification.createAddNotification(eContainer(), eContainingFeature(), this, -1)); status = NotifyStatus.SUCCESS_NOTIFICATION_SEND; } else { - sendNotification(SmartEMFNotification.createSetNotification(eContainer(), eContainingFeature(), null, this, -1)); + sendNotification(SmartEMFNotification.createSetNotification(eContainer(), eContainingFeature(), + null, this, -1)); status = NotifyStatus.SUCCESS_NOTIFICATION_SEND; } } - // if cascading is activated, we recursively generate add messages; else just this once + // if cascading is activated, we recursively generate add messages; else just + // this once SmartEMFResource smartResource = smartResource(); if (smartResource != null && smartResource.getCascade()) setResourceCall = (o) -> o.setResource(resource, true); @@ -478,10 +496,11 @@ public void setResourceSilently(Resource resource) { return; // send remove messages to old adapters - // TODO lfritsche: should we optimize this and only do this if the adapters of both resources + // TODO lfritsche: should we optimize this and only do this if the adapters of + // both resources // differ? sendRemoveAdapterNotification(this); - + this.resource = (Internal) resource; setResourceOfContainmentsSilently(resource); @@ -575,7 +594,8 @@ public NotificationChain eSetResource(Internal resource, NotificationChain notif } @Override - public NotificationChain eInverseAdd(InternalEObject otherEnd, int featureID, Class baseClass, NotificationChain notifications) { + public NotificationChain eInverseAdd(InternalEObject otherEnd, int featureID, Class baseClass, + NotificationChain notifications) { return new NotificationChainImpl(); } @@ -584,13 +604,15 @@ public NotificationChain eInverseAdd(InternalEObject otherEnd, int featureID, Cl public abstract void eInverseRemove(Object otherEnd, EStructuralFeature feature); @Override - public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, Class baseClass, NotificationChain notifications) { + public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, Class baseClass, + NotificationChain notifications) { throw new UnsupportedOperationException("Unsupported by SmartEMF"); } @Override - public NotificationChain eBasicSetContainer(InternalEObject newContainer, int newContainerFeatureID, NotificationChain notifications) { + public NotificationChain eBasicSetContainer(InternalEObject newContainer, int newContainerFeatureID, + NotificationChain notifications) { throw new UnsupportedOperationException("Unsupported by SmartEMF"); } diff --git a/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/SmartPackage.java b/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/SmartPackage.java index d7195ae2..1b060c74 100644 --- a/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/SmartPackage.java +++ b/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/SmartPackage.java @@ -8,15 +8,16 @@ import org.eclipse.emf.ecore.EStructuralFeature; public interface SmartPackage extends EPackage { - + public EStructuralFeature insertNewFeature(final EClass eClass, final EStructuralFeature eFeature); - + public boolean isDynamicEStructuralFeature(final EClass eClass, final EStructuralFeature eFeature); - + public boolean hasDynamicEStructuralFeatures(final EClass eClass); - + public Collection getDynamicEStructuralFeatures(final EClass eClass); - - public void registerDynamicFeatureUpdateCallback(final EClass eClass, final BiConsumer callback); + + public void registerDynamicFeatureUpdateCallback(final EClass eClass, + final BiConsumer callback); } diff --git a/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/SmartPackageImpl.java b/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/SmartPackageImpl.java index 8d51e55a..7d43e6a0 100644 --- a/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/SmartPackageImpl.java +++ b/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/SmartPackageImpl.java @@ -18,113 +18,117 @@ import org.eclipse.emf.ecore.impl.EReferenceImpl; public abstract class SmartPackageImpl extends EPackageImpl implements SmartPackage { - + private Map> dynamicFeatures = new HashMap<>(); private Map> subClassesInPackage = new HashMap<>(); private Map>> foreignSubClassCallbacks = new HashMap<>(); - public SmartPackageImpl(final String nsUri, final EFactory factory) { super(nsUri, factory); } - + @Override public EStructuralFeature insertNewFeature(final EClass eClass, final EStructuralFeature eFeature) { - if(!eContents().parallelStream().filter(obj -> (obj instanceof EClass)).filter(ecls -> eClass.equals(ecls)).findAny().isPresent()) { - throw new RuntimeException("EClass <"+eClass+"> is not present in the package <"+this+">"); + if (!eContents().parallelStream().filter(obj -> (obj instanceof EClass)).filter(ecls -> eClass.equals(ecls)) + .findAny().isPresent()) { + throw new RuntimeException("EClass <" + eClass + "> is not present in the package <" + this + ">"); } - - if(eFeature instanceof EReference) { - EReferenceImpl createdERef = (EReferenceImpl)ecoreFactory.createEReference(); + + if (eFeature instanceof EReference) { + EReferenceImpl createdERef = (EReferenceImpl) ecoreFactory.createEReference(); createdERef.setFeatureID(eClass.getEStructuralFeatures().size()); eClass.getEStructuralFeatures().add(createdERef); - - initEReference(createdERef, eFeature.getEType(), ((EReference) eFeature).getEOpposite(), eFeature.getName(), eFeature.getDefaultValueLiteral(), - eFeature.getLowerBound(), eFeature.getUpperBound(), eClass.getInstanceClass(), eFeature.isTransient(), eFeature.isVolatile(), eFeature.isChangeable(), - ((EReference) eFeature).isContainment(), ((EReference) eFeature).isResolveProxies(), eFeature.isUnsettable(), eFeature.isUnique(), eFeature.isDerived(), - eFeature.isOrdered()); - + + initEReference(createdERef, eFeature.getEType(), ((EReference) eFeature).getEOpposite(), eFeature.getName(), + eFeature.getDefaultValueLiteral(), eFeature.getLowerBound(), eFeature.getUpperBound(), + eClass.getInstanceClass(), eFeature.isTransient(), eFeature.isVolatile(), eFeature.isChangeable(), + ((EReference) eFeature).isContainment(), ((EReference) eFeature).isResolveProxies(), + eFeature.isUnsettable(), eFeature.isUnique(), eFeature.isDerived(), eFeature.isOrdered()); + insertClass2Feature(eClass, createdERef); getSubClassesInPackage(eClass).forEach(subClass -> { insertClass2Feature(subClass, createdERef); }); - - if(foreignSubClassCallbacks.containsKey(eClass)) { + + if (foreignSubClassCallbacks.containsKey(eClass)) { foreignSubClassCallbacks.get(eClass).forEach(callback -> callback.accept(eClass, createdERef)); } - + return createdERef; - } else if(eFeature instanceof EAttribute) { - EAttributeImpl createdEAtr = (EAttributeImpl)ecoreFactory.createEAttribute(); + } else if (eFeature instanceof EAttribute) { + EAttributeImpl createdEAtr = (EAttributeImpl) ecoreFactory.createEAttribute(); createdEAtr.setFeatureID(eClass.getEStructuralFeatures().size()); eClass.getEStructuralFeatures().add(createdEAtr); - - initEAttribute(createdEAtr, ((EAttribute)eFeature).getEType(), eFeature.getName(), eFeature.getDefaultValueLiteral(), eFeature.getLowerBound(), eFeature.getUpperBound(), - eClass.getInstanceClass(), createdEAtr.isTransient(), createdEAtr.isVolatile(), createdEAtr.isChangeable(), createdEAtr.isUnsettable(), createdEAtr.isID(), createdEAtr.isUnique(), + + initEAttribute(createdEAtr, ((EAttribute) eFeature).getEType(), eFeature.getName(), + eFeature.getDefaultValueLiteral(), eFeature.getLowerBound(), eFeature.getUpperBound(), + eClass.getInstanceClass(), createdEAtr.isTransient(), createdEAtr.isVolatile(), + createdEAtr.isChangeable(), createdEAtr.isUnsettable(), createdEAtr.isID(), createdEAtr.isUnique(), createdEAtr.isDerived(), createdEAtr.isOrdered()); - + insertClass2Feature(eClass, createdEAtr); getSubClassesInPackage(eClass).forEach(subClass -> { insertClass2Feature(subClass, createdEAtr); }); - - if(foreignSubClassCallbacks.containsKey(eClass)) { + + if (foreignSubClassCallbacks.containsKey(eClass)) { foreignSubClassCallbacks.get(eClass).forEach(callback -> callback.accept(eClass, createdEAtr)); } - + return createdEAtr; } else { - throw new RuntimeException("Unsupported EStructuralFeature type: "+eFeature); + throw new RuntimeException("Unsupported EStructuralFeature type: " + eFeature); } } - + @Override public boolean isDynamicEStructuralFeature(final EClass eClass, final EStructuralFeature eFeature) { - if(!dynamicFeatures.containsKey(eClass)) + if (!dynamicFeatures.containsKey(eClass)) return false; - + return dynamicFeatures.get(eClass).contains(eFeature); - + } - + @Override public boolean hasDynamicEStructuralFeatures(final EClass eClass) { - if(!dynamicFeatures.containsKey(eClass)) + if (!dynamicFeatures.containsKey(eClass)) return false; - + return true; } - + @Override public Collection getDynamicEStructuralFeatures(final EClass eClass) { - if(!dynamicFeatures.containsKey(eClass)) + if (!dynamicFeatures.containsKey(eClass)) return new HashSet<>(); - + return dynamicFeatures.get(eClass); } - + @Override - public void registerDynamicFeatureUpdateCallback(final EClass eClass, final BiConsumer callback) { + public void registerDynamicFeatureUpdateCallback(final EClass eClass, + final BiConsumer callback) { Set> currentCallbacks = foreignSubClassCallbacks.get(eClass); - if(currentCallbacks == null) { + if (currentCallbacks == null) { currentCallbacks = new HashSet<>(); foreignSubClassCallbacks.put(eClass, currentCallbacks); } currentCallbacks.add(callback); } - + protected void injectExternalReferences() { // Insert own features Collection externalRefs = getExternalUnidirectionalReferences(); - for(EReference ref : externalRefs) { - if(! (ref.getEType().getEPackage() instanceof SmartPackage)) + for (EReference ref : externalRefs) { + if (!(ref.getEType().getEPackage() instanceof SmartPackage)) continue; - - SmartPackage foreignPackage = (SmartPackage)ref.getEType().getEPackage(); - - EReferenceImpl inverse = (EReferenceImpl)ecoreFactory.createEReference(); - inverse.setName(ref.getName()+"_inverseTo_"+getName()); + + SmartPackage foreignPackage = (SmartPackage) ref.getEType().getEPackage(); + + EReferenceImpl inverse = (EReferenceImpl) ecoreFactory.createEReference(); + inverse.setName(ref.getName() + "_inverseTo_" + getName()); inverse.setEType(ref.getEContainingClass()); inverse.setEOpposite(ref); inverse.setLowerBound(0); @@ -138,19 +142,19 @@ protected void injectExternalReferences() { inverse.setUnique(ref.isUnique()); inverse.setDerived(ref.isDerived()); inverse.setOrdered(ref.isOrdered()); - + EReference trueInverse = (EReference) foreignPackage.insertNewFeature((EClass) ref.getEType(), inverse); ref.setEOpposite(trueInverse); } } - + protected void injectDynamicOpposites() { // Insert own features Collection internalRefs = getInternalUnidirectionalReferences(); - for(EReference ref : internalRefs) { - - EReferenceImpl inverse = (EReferenceImpl)ecoreFactory.createEReference(); - inverse.setName(ref.getName()+"_inverseTo_"+getName()); + for (EReference ref : internalRefs) { + + EReferenceImpl inverse = (EReferenceImpl) ecoreFactory.createEReference(); + inverse.setName(ref.getName() + "_inverseTo_" + getName()); inverse.setEType(ref.getEContainingClass()); inverse.setEOpposite(ref); inverse.setLowerBound(0); @@ -164,103 +168,92 @@ protected void injectDynamicOpposites() { inverse.setUnique(ref.isUnique()); inverse.setDerived(ref.isDerived()); inverse.setOrdered(ref.isOrdered()); - + EReference trueInverse = (EReference) insertNewFeature((EClass) ref.getEType(), inverse); ref.setEOpposite(trueInverse); } } - + protected void fetchDynamicEStructuralFeaturesOfSuperTypes() { // Update dynamic feature collection with dynamic features from super classes - Set ownClasses = eContents().parallelStream() - .filter(obj->(obj instanceof EClass)) - .map(ecls -> (EClass)ecls) - .collect(Collectors.toSet()); - - for(EClass ownClass : ownClasses) { - for(EClass foreignSuperClass : ownClass.getEAllSuperTypes().stream() - .filter(ecls -> (ecls instanceof EClass)) - .map(ecls -> (EClass)ecls) - .filter(ecls -> ecls.eContainer()!=this && (ecls.eContainer() instanceof SmartPackage)) + Set ownClasses = eContents().parallelStream().filter(obj -> (obj instanceof EClass)) + .map(ecls -> (EClass) ecls).collect(Collectors.toSet()); + + for (EClass ownClass : ownClasses) { + for (EClass foreignSuperClass : ownClass.getEAllSuperTypes().stream() + .filter(ecls -> (ecls instanceof EClass)).map(ecls -> (EClass) ecls) + .filter(ecls -> ecls.eContainer() != this && (ecls.eContainer() instanceof SmartPackage)) .collect(Collectors.toSet())) { - SmartPackage otherPkg = (SmartPackage)foreignSuperClass.eContainer(); - // Register a callback -> super classes might be subject to change during runtime + SmartPackage otherPkg = (SmartPackage) foreignSuperClass.eContainer(); + // Register a callback -> super classes might be subject to change during + // runtime otherPkg.registerDynamicFeatureUpdateCallback(foreignSuperClass, this::insertFeatureOfSuperType); - - if(!otherPkg.hasDynamicEStructuralFeatures(foreignSuperClass)) + + if (!otherPkg.hasDynamicEStructuralFeatures(foreignSuperClass)) continue; - - otherPkg.getDynamicEStructuralFeatures(foreignSuperClass).forEach(feature -> insertClass2Feature(ownClass, feature)); + + otherPkg.getDynamicEStructuralFeatures(foreignSuperClass) + .forEach(feature -> insertClass2Feature(ownClass, feature)); } } } - + protected Collection getExternalUnidirectionalReferences() { - Set ownClasses = eContents().parallelStream().filter(obj->(obj instanceof EClass)).map(ecls -> (EClass)ecls).collect(Collectors.toSet()); + Set ownClasses = eContents().parallelStream().filter(obj -> (obj instanceof EClass)) + .map(ecls -> (EClass) ecls).collect(Collectors.toSet()); // Find all references that point to EClasses not defined in this package. - return eContents().parallelStream() - .filter(obj->(obj instanceof EClass)) - .map(ecls -> (EClass)ecls) - .flatMap(ecls -> ecls.getEAllStructuralFeatures().parallelStream()) - .filter(ref -> (ref instanceof EReference)) - .map(ref -> (EReference) ref) - .filter(ref -> ref.getEOpposite() == null) - .filter(ref -> !ownClasses.contains(ref.getEType())) - .filter(ref -> !ref.isContainment()) - .collect(Collectors.toSet()); + return eContents().parallelStream().filter(obj -> (obj instanceof EClass)).map(ecls -> (EClass) ecls) + .flatMap(ecls -> ecls.getEAllStructuralFeatures().parallelStream()) + .filter(ref -> (ref instanceof EReference)).map(ref -> (EReference) ref) + .filter(ref -> ref.getEOpposite() == null).filter(ref -> !ownClasses.contains(ref.getEType())) + .filter(ref -> !ref.isContainment()).collect(Collectors.toSet()); } - + protected Collection getInternalUnidirectionalReferences() { - Set ownClasses = eContents().parallelStream().filter(obj->(obj instanceof EClass)).map(ecls -> (EClass)ecls).collect(Collectors.toSet()); + Set ownClasses = eContents().parallelStream().filter(obj -> (obj instanceof EClass)) + .map(ecls -> (EClass) ecls).collect(Collectors.toSet()); // Find all references that point to EClasses defined in this package. - return eContents().parallelStream() - .filter(obj->(obj instanceof EClass)) - .map(ecls -> (EClass)ecls) - .flatMap(ecls -> ecls.getEAllStructuralFeatures().parallelStream()) - .filter(ref -> (ref instanceof EReference)) - .map(ref -> (EReference) ref) - .filter(ref -> ref.getEOpposite() == null) - .filter(ref -> ownClasses.contains(ref.getEType())) - .filter(ref -> !ref.isContainment()) - .collect(Collectors.toSet()); + return eContents().parallelStream().filter(obj -> (obj instanceof EClass)).map(ecls -> (EClass) ecls) + .flatMap(ecls -> ecls.getEAllStructuralFeatures().parallelStream()) + .filter(ref -> (ref instanceof EReference)).map(ref -> (EReference) ref) + .filter(ref -> ref.getEOpposite() == null).filter(ref -> ownClasses.contains(ref.getEType())) + .filter(ref -> !ref.isContainment()).collect(Collectors.toSet()); } - + private void insertClass2Feature(final EClass eClass, final EStructuralFeature eFeature) { Set currentFeatures = dynamicFeatures.get(eClass); - if(currentFeatures == null) { + if (currentFeatures == null) { currentFeatures = new HashSet<>(); dynamicFeatures.put(eClass, currentFeatures); } currentFeatures.add(eFeature); } - + private void insertFeatureOfSuperType(final EClass superClass, final EStructuralFeature eFeature) { - Set subClasses = eContents().parallelStream() - .filter(obj->(obj instanceof EClass)) - .map(ecls -> (EClass)ecls) - .filter(ecls -> ecls.getEAllSuperTypes().contains(superClass)) + Set subClasses = eContents().parallelStream().filter(obj -> (obj instanceof EClass)) + .map(ecls -> (EClass) ecls).filter(ecls -> ecls.getEAllSuperTypes().contains(superClass)) .collect(Collectors.toSet()); - - for(EClass subClass : subClasses) { + + for (EClass subClass : subClasses) { insertClass2Feature(subClass, eFeature); } - + } - + protected Set getSubClassesInPackage(final EClass eClass) { - if(subClassesInPackage.containsKey(eClass)) + if (subClassesInPackage.containsKey(eClass)) return subClassesInPackage.get(eClass); - + Set subClasses = new HashSet<>(); subClassesInPackage.put(eClass, subClasses); - - for(EClass someClass : eContents().stream().filter(obj->(obj instanceof EClass)).map(ecls -> (EClass)ecls).filter(ecls -> ecls != eClass).collect(Collectors.toSet())) { - if(someClass.getEAllSuperTypes().contains(eClass)) { + + for (EClass someClass : eContents().stream().filter(obj -> (obj instanceof EClass)).map(ecls -> (EClass) ecls) + .filter(ecls -> ecls != eClass).collect(Collectors.toSet())) { + if (someClass.getEAllSuperTypes().contains(eClass)) { subClasses.add(someClass); } } return subClasses; } - } diff --git a/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/collections/DefaultSmartEList.java b/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/collections/DefaultSmartEList.java index 4d538926..fb186f81 100644 --- a/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/collections/DefaultSmartEList.java +++ b/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/collections/DefaultSmartEList.java @@ -20,15 +20,15 @@ public final class DefaultSmartEList extends LinkedList implements EList, InternalEList { private EStructuralFeature feature = null; - + public DefaultSmartEList() { - + } - + public DefaultSmartEList(EStructuralFeature feature) { this.feature = feature; } - + /** * */ @@ -38,42 +38,42 @@ public DefaultSmartEList(EStructuralFeature feature) { public boolean add(T e) { return super.add(e); } - + @Override public void add(int index, T element) { super.add(index, element); } - + @Override public boolean addAll(Collection c) { return super.addAll(c); } - + @Override public boolean addAll(int index, Collection c) { return super.addAll(index, c); } - + @Override public void clear() { super.clear(); } - + @Override public T remove(int index) { return super.remove(index); } - + @Override public boolean remove(Object o) { return super.remove(o); } - + @Override public boolean removeAll(Collection c) { return super.removeAll(c); } - + @Override public T basicGet(int index) { return get(index); @@ -83,7 +83,7 @@ public T basicGet(int index) { public List basicList() { return this; } - + @Override public Iterator iterator() { return basicIterator(); @@ -93,7 +93,7 @@ public Iterator iterator() { public Iterator basicIterator() { Iterator listIterator = super.iterator(); Iterator featureIterator = new EContentsEList.FeatureIterator() { - + @Override public boolean hasNext() { return listIterator.hasNext(); diff --git a/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/collections/LinkedSmartESet.java b/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/collections/LinkedSmartESet.java index 8a02f2af..c1d34e05 100644 --- a/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/collections/LinkedSmartESet.java +++ b/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/collections/LinkedSmartESet.java @@ -22,7 +22,7 @@ public LinkedSmartESet(EObject eContainer, EReference feature) { protected void initializeCollection(EObject eContainer, EReference feature) { elements = new LinkedHashSet(); } - + @Override public T basicGet(int index) { return get(index); @@ -105,17 +105,19 @@ public ReplacingIterator replacingIterator() { @Override public void replace(T element) { if (iteratorIndex <= 0) - throw new NoSuchElementException("There is no last element to replace! Please call method next(), first!"); + throw new NoSuchElementException( + "There is no last element to replace! Please call method next(), first!"); elements.remove(copiedElements[iteratorIndex - 1]); - // since this SmartCollection behaves like a set, we do not have to insert the new element at the + // since this SmartCollection behaves like a set, we do not have to insert the + // new element at the // same position as the removed one elements.add(element); } }; } - + // Unsupported EList operations - + @Override public void move(int newPosition, T object) { throw new UnsupportedOperationException("Not supported for Sets"); @@ -161,7 +163,7 @@ public ListIterator listIterator(int index) { public List subList(int fromIndex, int toIndex) { throw new UnsupportedOperationException("Not supported for Sets"); } - + @Override public NotificationChain basicRemove(Object object, NotificationChain notifications) { throw new UnsupportedOperationException("Not supported for SmartESets"); @@ -171,7 +173,7 @@ public NotificationChain basicRemove(Object object, NotificationChain notificati public NotificationChain basicAdd(T object, NotificationChain notifications) { throw new UnsupportedOperationException("Not supported for SmartESets"); } - + @Override public T setUnique(int index, T object) { throw new UnsupportedOperationException("Not supported for SmartESets"); diff --git a/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/collections/ResourceContentSmartEList.java b/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/collections/ResourceContentSmartEList.java index b7a8f875..a25198e6 100644 --- a/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/collections/ResourceContentSmartEList.java +++ b/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/collections/ResourceContentSmartEList.java @@ -102,10 +102,10 @@ private void resetContainment(T e, boolean removeRecursively) { if (oldContainer != null) { if (e.eContainingFeature().isMany()) { Object getResult = oldContainer.eGet(e.eContainingFeature()); -// if(removeRecursively) - ((SmartCollection) getResult).remove(e); -// else -// ((SmartCollection) getResult).removeWithoutContainerResetting(e); + if (removeRecursively) + ((SmartCollection) getResult).remove(e); + else + ((SmartCollection) getResult).removeWithoutContainerResetting(e); } else { if (removeRecursively) { oldContainer.eUnset(e.eContainingFeature()); diff --git a/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/collections/SmartCollection.java b/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/collections/SmartCollection.java index a0c0e455..ae0fdd42 100644 --- a/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/collections/SmartCollection.java +++ b/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/collections/SmartCollection.java @@ -28,7 +28,7 @@ public SmartCollection(EObject eContainer, EReference feature, boolean sendNotif this(eContainer, feature); this.sendNotifications = sendNotifications; } - + public SmartCollection(EObject eContainer, EReference feature) { this.eContainer = eContainer; this.feature = feature; @@ -123,7 +123,8 @@ public boolean addAll(Collection c) { status = addStatus; } - // if feature is containment then set resource should have sent this notification already + // if feature is containment then set resource should have sent this + // notification already if (!feature.isContainment()) sendNotification(SmartEMFNotification.createAddManyNotification(eContainer, feature, newList, 0)); @@ -140,7 +141,6 @@ public NotifyStatus removeWithoutContainerResetting(Object o) { return NotifyStatus.SUCCESS_NOTIFICATION_SEND; } - /** * Returns status of execution and if a REMOVE notification was sent or not */ @@ -238,12 +238,13 @@ public boolean retainAll(Collection c) { } protected void sendNotification(Notification n) { - // if the feature is a containment, then notifications are handled when setting the resource + // if the feature is a containment, then notifications are handled when setting + // the resource // if(feature.isContainment()) // return; - if(!sendNotifications) + if (!sendNotifications) return; - + Resource r = eContainer.eResource(); if (r != null) { for (Adapter a : r.eAdapters()) { diff --git a/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/collections/SmartEList.java b/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/collections/SmartEList.java index 3524ba0b..77ff8ee6 100644 --- a/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/collections/SmartEList.java +++ b/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/collections/SmartEList.java @@ -198,7 +198,8 @@ public ReplacingIterator replacingIterator() { @Override public void replace(T element) { if (iteratorIndex <= 0) - throw new NoSuchElementException("There is no last element to replace! Please call method next(), first!"); + throw new NoSuchElementException( + "There is no last element to replace! Please call method next(), first!"); elements.set(iteratorIndex - 1, element); } diff --git a/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/collections/SmartESet.java b/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/collections/SmartESet.java index 8919231e..28026c01 100644 --- a/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/collections/SmartESet.java +++ b/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/collections/SmartESet.java @@ -16,9 +16,9 @@ public class SmartESet extends SmartCollection> { public SmartESet(EObject eContainer, EReference feature, boolean sendNotifications) { - super(eContainer, feature, sendNotifications); + super(eContainer, feature, sendNotifications); } - + public SmartESet(EObject eContainer, EReference feature) { super(eContainer, feature); } @@ -170,9 +170,11 @@ public ReplacingIterator replacingIterator() { @Override public void replace(T element) { if (iteratorIndex <= 0) - throw new NoSuchElementException("There is no last element to replace! Please call method next(), first!"); + throw new NoSuchElementException( + "There is no last element to replace! Please call method next(), first!"); elements.remove(copiedElements[iteratorIndex - 1]); - // since this SmartCollection behaves like a set, we do not have to insert the new element at the + // since this SmartCollection behaves like a set, we do not have to insert the + // new element at the // same position as the removed one elements.add(element); } diff --git a/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/notification/NotificationList.java b/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/notification/NotificationList.java index a226b995..ed7bbc61 100644 --- a/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/notification/NotificationList.java +++ b/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/notification/NotificationList.java @@ -7,7 +7,9 @@ import org.eclipse.emf.common.notify.Notifier; /** - * This class implements the {@link NotificationChain} interface. It is used to collect notifications without immediately merging them. + * This class implements the {@link NotificationChain} interface. It is used to + * collect notifications without immediately merging them. + * * @author paulschiffner */ public class NotificationList extends LinkedList implements NotificationChain { @@ -20,18 +22,18 @@ public NotificationList(Iterable notifications) { add(n); } } - + public NotificationList(Notification... notifications) { super(); for (Notification n : notifications) { add(n); } } - + @Override public void dispatch() { for (Notification n : this) { - Notifier notifier = (Notifier)(n.getNotifier()); + Notifier notifier = (Notifier) (n.getNotifier()); notifier.eNotify(n); } } diff --git a/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/notification/NotifyStatus.java b/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/notification/NotifyStatus.java index bc4bc282..9a3f2b76 100644 --- a/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/notification/NotifyStatus.java +++ b/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/notification/NotifyStatus.java @@ -3,8 +3,8 @@ public enum NotifyStatus { SUCCESS_NO_NOTIFICATION, - + SUCCESS_NOTIFICATION_SEND, - + FAILURE_NO_NOTIFICATION } diff --git a/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/notification/SmartContentAdapter.java b/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/notification/SmartContentAdapter.java index 41b7490e..ee2b873e 100644 --- a/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/notification/SmartContentAdapter.java +++ b/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/notification/SmartContentAdapter.java @@ -8,17 +8,15 @@ import org.eclipse.emf.ecore.util.EContentAdapter; public class SmartContentAdapter extends EContentAdapter { - + @Override - protected void unsetTarget(Resource target) - { - basicUnsetTarget(target); - List contents = target.getContents(); - for (EObject e : contents) - { - Notifier notifier = e; - removeAdapter(notifier, true, false); - } - } + protected void unsetTarget(Resource target) { + basicUnsetTarget(target); + List contents = target.getContents(); + for (EObject e : contents) { + Notifier notifier = e; + removeAdapter(notifier, true, false); + } + } } diff --git a/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/notification/SmartEMFCrossReferenceAdapter.java b/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/notification/SmartEMFCrossReferenceAdapter.java index 429f71e6..f8623fc9 100644 --- a/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/notification/SmartEMFCrossReferenceAdapter.java +++ b/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/notification/SmartEMFCrossReferenceAdapter.java @@ -30,1152 +30,922 @@ import org.eclipse.emf.ecore.util.InternalEList; import org.eclipse.emf.ecore.util.EContentsEList.FeatureIterator; - /** - * This reference adapter is mostly a copy of the original ECrossReferenceAdapter but without expensive get calls to the underlying resource + * This reference adapter is mostly a copy of the original + * ECrossReferenceAdapter but without expensive get calls to the underlying + * resource + * * @author Lars * */ -public class SmartEMFCrossReferenceAdapter implements Adapter.Internal -{ - /** - * Returns the first {@link ECrossReferenceAdapter} in the notifier's {@link Notifier#eAdapters() adapter list}, - * or null, if there isn't one. - * @param notifier the object to search. - * @return the first ECrossReferenceAdapter in the notifier's adapter list. - */ - public static ECrossReferenceAdapter getCrossReferenceAdapter(Notifier notifier) - { - List adapters = notifier.eAdapters(); - for (int i = 0, size = adapters.size(); i < size; ++i) - { - Object adapter = adapters.get(i); - if (adapter instanceof ECrossReferenceAdapter) - { - return (ECrossReferenceAdapter)adapter; - } - } - return null; - } - - protected Set unloadedResources = new HashSet(); - protected Map unloadedEObjects = new HashMap(); - - protected class InverseCrossReferencer extends EcoreUtil.CrossReferencer - { - private static final long serialVersionUID = 1L; - - protected Map> proxyMap; - - /** - * @since 2.10 - */ - protected EContentsEList.FeatureFilter crossReferenceFilter; - - protected InverseCrossReferencer() - { - super((Collection)null); - - crossReferenceFilter = createCrossReferenceFilter(); - } - - /** - * @since 2.10 - */ - protected EContentsEList.FeatureFilter createCrossReferenceFilter() - { - return new EContentsEList.FeatureFilter() - { - public boolean isIncluded(EStructuralFeature eStructuralFeature) - { - return FeatureMapUtil.isFeatureMap(eStructuralFeature) || SmartEMFCrossReferenceAdapter.this.isIncluded((EReference)eStructuralFeature); - } - }; - } - - @Override - protected EContentsEList.FeatureIterator getCrossReferences(EObject eObject) - { - InternalEList eCrossReferences = (InternalEList)eObject.eCrossReferences(); - - final EContentsEList.FeatureIterator underlyingIterator = (FeatureIterator)(resolve() ? eCrossReferences.iterator() : eCrossReferences.basicIterator()); - - if (underlyingIterator instanceof EContentsEList.Filterable) - { - // Simply filter the model-provided iterator to skip the references that we don't need to index - ((EContentsEList.Filterable)underlyingIterator).filter(crossReferenceFilter); - return underlyingIterator; - } - - // Otherwise, we'll post-filter the iterator, ourselves, but this does mean that we may compute derived features unnecessarily - return new EContentsEList.FeatureIterator() - { - private boolean prepared; - - private EObject preparedNext; - - private EStructuralFeature preparedFeature; - - private EStructuralFeature feature; - - public boolean hasNext() - { - if (!prepared) - { - while (underlyingIterator.hasNext()) - { - preparedNext = underlyingIterator.next(); - preparedFeature = underlyingIterator.feature(); - if (crossReferenceFilter.isIncluded(preparedFeature)) - { - prepared = true; - break; - } - } - } - - return prepared; - } - - public EObject next() - { - if (!prepared && !hasNext()) - { - throw new NoSuchElementException(); - } - - feature = preparedFeature; - prepared = false; - return preparedNext; - } - - public void remove() - { - // Must not attempt to remove cross-references in indexing them - throw new UnsupportedOperationException(); - } - - public EStructuralFeature feature() - { - return feature; - } - }; - } - - @Override - protected boolean crossReference(EObject eObject, EReference eReference, EObject crossReferencedEObject) - { - return isIncluded(eReference); - } - - @Override - protected Collection newCollection() - { - return - new BasicEList() - { - private static final long serialVersionUID = 1L; - - private static final int THRESHOLD = 100; - - private Map map; - - @Override - protected Object[] newData(int capacity) - { - return new EStructuralFeature.Setting [capacity]; - } - - @Override - protected void didAdd(int index, EStructuralFeature.Setting setting) - { - if (map != null) - { - EObject eObject = setting.getEObject(); - EStructuralFeature eStructuralFeature = setting.getEStructuralFeature(); - Object object = map.get(eObject); - if (object == null) - { - map.put(eObject, eStructuralFeature); - } - else if (object instanceof Object[]) - { - Object[] oldFeatures = (Object[])object; - Object[] newFeatures = new Object[oldFeatures.length + 1]; - System.arraycopy(oldFeatures, 0, newFeatures, 0, oldFeatures.length); - newFeatures[oldFeatures.length] = eStructuralFeature; - map.put(eObject, newFeatures); - } - else - { - Object[] newFeatures = new Object[2]; - newFeatures[0] = object; - newFeatures[1] = eStructuralFeature; - map.put(eObject, newFeatures); - } - } - } - - @Override - protected void didRemove(int index, EStructuralFeature.Setting setting) - { - if (map != null) - { - if (size < THRESHOLD / 2) - { - map = null; - } - else - { - EObject eObject = setting.getEObject(); - Object object = map.get(eObject); - if (object instanceof Object[]) - { - Object[] oldFeatures = (Object[])object; - EStructuralFeature eStructuralFeature = setting.getEStructuralFeature(); - if (oldFeatures.length == 2) - { - map.put(eObject, oldFeatures[0] == eStructuralFeature ? oldFeatures[1] : oldFeatures[0]); - } - else - { - Object[] newFeatures = new Object [oldFeatures.length - 1]; - for (int i = 0; i < oldFeatures.length; ++i) - { - Object oldFeature = oldFeatures[i]; - if (oldFeature == eStructuralFeature) - { - System.arraycopy(oldFeatures, i + 1, newFeatures, i, oldFeatures.length - i - 1); - break; - } - else - { - newFeatures[i] = oldFeatures[i]; - } - } - map.put(eObject, newFeatures); - } - } - else - { - map.remove(eObject); - } - } - } - } - - @Override - public boolean add(EStructuralFeature.Setting setting) - { - if (size > 0 && (!settingTargets || SmartEMFCrossReferenceAdapter.this.resolve())) - { - EObject eObject = setting.getEObject(); - if (size > THRESHOLD) - { - if (map == null) - { - map = new HashMap(); - EStructuralFeature.Setting[] settingData = (EStructuralFeature.Setting[])data; - for (int i = 0; i < size; ++i) - { - didAdd(i, settingData[i]); - } - } - - Object object = map.get(eObject); - if (object != null) - { - EStructuralFeature eStructuralFeature = setting.getEStructuralFeature(); - if (object == eStructuralFeature) - { - return false; - } - else if (object instanceof Object[]) - { - Object[] features = (Object[])object; - for (int i = 0; i < features.length; ++i) - { - if (features[i] == eStructuralFeature) - { - return false; - } - } - } - } - } - else - { - EStructuralFeature eStructuralFeature = setting.getEStructuralFeature(); - EStructuralFeature.Setting[] settingData = (EStructuralFeature.Setting[])data; - for (int i = 0; i < size; ++i) - { - EStructuralFeature.Setting containedSetting = settingData[i]; - if (containedSetting.getEObject() == eObject && containedSetting.getEStructuralFeature() == eStructuralFeature) - { - return false; - } - } - } - } - addUnique(setting); - return true; - } - }; - } - - public void add(EObject eObject) - { - handleCrossReference(eObject); - if (!resolve()) - { - addProxy(eObject, eObject); - } - } - - @Override - protected void add(InternalEObject eObject, EReference eReference, EObject crossReferencedEObject) - { - super.add(eObject, eReference, crossReferencedEObject); - if (!resolve()) - { - addProxy(crossReferencedEObject, eObject); - } - } - - public void add(EObject eObject, EReference eReference, EObject crossReferencedEObject) - { - add((InternalEObject)eObject, eReference, crossReferencedEObject); - } - - protected void addProxy(EObject proxy, EObject context) - { - if (proxy.eIsProxy()) - { - if (proxyMap == null) - { - proxyMap = new HashMap>(); - } - URI uri = normalizeURI(((InternalEObject)proxy).eProxyURI(), context); - List proxies = proxyMap.get(uri); - if (proxies == null) - { - proxyMap.put(uri, proxies = new BasicEList.FastCompare()); - } - proxies.add(proxy); - } - } - - public Object remove(EObject eObject) - { - if (!resolve()) - { - removeProxy(eObject, eObject); - } - return super.remove(eObject); - } - - public void remove(EObject eObject, EReference eReference, EObject crossReferencedEObject) - { - if (!resolve()) - { - removeProxy(crossReferencedEObject, eObject); - } - BasicEList collection = (BasicEList)get(crossReferencedEObject); - if (collection != null) - { - EStructuralFeature.Setting [] settingData = (EStructuralFeature.Setting[])collection.data(); - for (int i = 0, size = collection.size(); i < size; ++i) - { - EStructuralFeature.Setting setting = settingData[i]; - if (setting.getEObject() == eObject && setting.getEStructuralFeature() == eReference) - { - if (collection.size() == 1) - { - super.remove(crossReferencedEObject); - } - else - { - collection.remove(i); - } - break; - } - } - } - } - - protected void removeProxy(EObject proxy, EObject context) - { - if (proxyMap != null && proxy.eIsProxy()) - { - URI uri = normalizeURI(((InternalEObject)proxy).eProxyURI(), context); - List proxies = proxyMap.get(uri); - if (proxies != null) - { - proxies.remove(proxy); - if (proxies.isEmpty()) - { - proxyMap.remove(uri); - } - } - } - } - - protected List removeProxies(URI uri) - { - return proxyMap != null ? proxyMap.remove(uri) : null; - } - - protected URI normalizeURI(URI uri, EObject objectContext) - { - // This should be the same as the logic in ResourceImpl.getEObject(String). - // - String fragment = uri.fragment(); - if (fragment != null) - { - int length = fragment.length(); - if (length > 0 && fragment.charAt(0) != '/' && fragment.charAt(length - 1) == '?') - { - int index = fragment.lastIndexOf('?', length - 2); - if (index > 0) - { - uri = uri.trimFragment().appendFragment(fragment.substring(0, index)); - } - } - } - Resource resourceContext = objectContext.eResource(); - if (resourceContext != null) - { - ResourceSet resourceSetContext = resourceContext.getResourceSet(); - if (resourceSetContext != null) - { - return resourceSetContext.getURIConverter().normalize(uri); - } - } - return uri; - } - - @Override - protected boolean resolve() - { - return SmartEMFCrossReferenceAdapter.this.resolve(); - } - } - - protected InverseCrossReferencer inverseCrossReferencer; - - protected boolean settingTargets; - - /** - * Indicates whether the adapter is currently being attached {@link #useRecursion() iteratively}. - * - * @see #useRecursion() - * @see #setTarget(EObject) - * @see #unsetTarget(EObject) - * @since 2.14 - */ - protected boolean iterating; - - public SmartEMFCrossReferenceAdapter() - { - inverseCrossReferencer = createInverseCrossReferencer(); - } - - /** - * Returns whether the process of attaching this adapter should be done recursively or iteratively; - * the default is to return {@code true} for recursion. - * - * @since 2.14 - * @return whether the process of attaching this adapter should be done recursively or iteratively. - */ - protected boolean useRecursion() - { - return true; - } - - public Collection getNonNavigableInverseReferences(EObject eObject) - { - return getNonNavigableInverseReferences(eObject, !resolve()); - } - - public Collection getNonNavigableInverseReferences(EObject eObject, boolean resolve) - { - if (resolve) - { - resolveAll(eObject); - } - - Collection result = inverseCrossReferencer.get(eObject); - if (result == null) - { - result = Collections.emptyList(); - } - return result; - } - - public Collection getInverseReferences(EObject eObject) - { - return getInverseReferences(eObject, !resolve()); - } - - public Collection getInverseReferences(EObject eObject, boolean resolve) - { - Collection result = new ArrayList(); - - if (resolve) - { - resolveAll(eObject); - } - - EObject eContainer = resolve ? eObject.eContainer() : ((InternalEObject)eObject).eInternalContainer(); - if (eContainer != null) - { - result.add(((InternalEObject)eContainer).eSetting(eObject.eContainmentFeature())); - } - - Collection nonNavigableInverseReferences = inverseCrossReferencer.get(eObject); - if (nonNavigableInverseReferences != null) - { - result.addAll(nonNavigableInverseReferences); - } - - for (EReference eReference : eObject.eClass().getEAllReferences()) - { - EReference eOpposite = eReference.getEOpposite(); - if (eOpposite != null && !eReference.isContainer() && eObject.eIsSet(eReference)) - { - if (eReference.isMany()) - { - Object collection = eObject.eGet(eReference); - for (@SuppressWarnings("unchecked") Iterator j = - resolve ? - ((Collection)collection).iterator() : - ((InternalEList)collection).basicIterator(); - j.hasNext(); ) - { - InternalEObject referencingEObject = (InternalEObject)j.next(); - result.add(referencingEObject.eSetting(eOpposite)); - } - } - else - { - result.add(((InternalEObject)eObject.eGet(eReference, resolve)).eSetting(eOpposite)); - } - } - } - - return result; - } - - /** - * @since 2.17 - */ - public Collection getInverseReferences(EObject eObject, EReference eReference, boolean resolve) - { - Collection result = new ArrayList(); - - if (resolve) - { - resolveAll(eObject); - } - - if (eReference.isContainment()) - { - EReference containmentFeature = eObject.eContainmentFeature(); - if (eReference == containmentFeature) - { - EObject eContainer = resolve ? eObject.eContainer() : ((InternalEObject)eObject).eInternalContainer(); - if (eContainer != null) - { - result.add(((InternalEObject)eContainer).eSetting(containmentFeature)); - } - } - } - else - { - EReference eOpposite = eReference.getEOpposite(); - if (eOpposite == null) - { - Collection nonNavigableInverseReferences = inverseCrossReferencer.get(eObject); - if (nonNavigableInverseReferences != null) - { - for (EStructuralFeature.Setting setting : nonNavigableInverseReferences) - { - if (eReference == setting.getEStructuralFeature()) - { - result.add(setting); - } - } - } - } - else - { - int featureID = eObject.eClass().getFeatureID(eOpposite); - if (featureID != -1) - { - InternalEObject internalEObject = (InternalEObject)eObject; - if (internalEObject.eIsSet(featureID)) - { - Object value = internalEObject.eGet(featureID, resolve, true); - if (eOpposite.isMany()) - { - for (@SuppressWarnings("unchecked") - Iterator j = resolve ? ((Collection)value).iterator() : ((InternalEList)value).basicIterator(); j.hasNext();) - { - InternalEObject referencingEObject = (InternalEObject)j.next(); - result.add(referencingEObject.eSetting(eReference)); - } - } - else - { - result.add(((InternalEObject)value).eSetting(eReference)); - } - } - } - } - } - - return result; - } - - protected void resolveAll(EObject eObject) - { - if (!eObject.eIsProxy()) - { - Resource resource = eObject.eResource(); - if (resource != null) - { - URI uri = resource.getURI(); - if (uri != null) - { - ResourceSet resourceSet = resource.getResourceSet(); - if (resourceSet != null) - { - uri = resourceSet.getURIConverter().normalize(uri); - } - uri = uri.appendFragment(resource.getURIFragment(eObject)); - } - else - { - uri = URI.createHierarchicalURI(null, null, resource.getURIFragment(eObject)); - } - List proxies = inverseCrossReferencer.removeProxies(uri); - if (proxies != null) - { - for (int i = 0, size = proxies.size(); i < size; ++i) - { - EObject proxy = proxies.get(i); - for (EStructuralFeature.Setting setting : getInverseReferences(proxy, false)) - { - resolveProxy(resource, eObject, proxy, setting); - } - } - } - } - } - } - - protected void resolveProxy(Resource resource, EObject eObject, EObject proxy, EStructuralFeature.Setting setting) - { - Object value = setting.get(true); - if (setting.getEStructuralFeature().isMany()) - { - InternalEList list = (InternalEList)value; - List basicList = list.basicList(); - int index = basicList.indexOf(proxy); - if (index != -1) - { - list.get(index); - } - } - } - - protected boolean isIncluded(EReference eReference) - { - return eReference.getEOpposite() == null && !eReference.isDerived(); - } - - protected InverseCrossReferencer createInverseCrossReferencer() - { - return new InverseCrossReferencer(); - } - - /** - * Handles a notification by calling {@link #selfAdapt selfAdapter}. - */ - public void notifyChanged(Notification notification) - { - selfAdapt(notification); - } - - /** - * Handles a notification by calling {@link #handleContainment handleContainment} - * for any containment-based notification. - */ - protected void selfAdapt(Notification notification) - { - Object notifier = notification.getNotifier(); - if (notifier instanceof EObject) - { - Object feature = notification.getFeature(); - if (feature instanceof EReference) - { - EReference reference = (EReference)feature; - if (reference.isContainment()) - { - handleContainment(notification); - } - else if (isIncluded(reference)) - { - handleCrossReference(reference, notification); - } - } - } - else if (notifier instanceof Resource) - { - switch (notification.getFeatureID(Resource.class)) - { - case Resource.RESOURCE__CONTENTS: - { - if (!unloadedResources.contains(notifier)) - { - switch (notification.getEventType()) - { - case Notification.REMOVE: - { - Resource resource = (Resource)notifier; - if (!resource.isLoaded()) - { - EObject eObject = (EObject)notification.getOldValue(); - unloadedEObjects.put(eObject, resource); - for (Iterator i = EcoreUtil.getAllProperContents(eObject, false); i.hasNext(); ) - { - unloadedEObjects.put(i.next(), resource); - } - } - break; - } - case Notification.REMOVE_MANY: - { - Resource resource = (Resource)notifier; - if (!resource.isLoaded()) - { - @SuppressWarnings("unchecked") - List eObjects = (List)notification.getOldValue(); - for (Iterator i = EcoreUtil.getAllProperContents(eObjects, false); i.hasNext(); ) - { - unloadedEObjects.put(i.next(), resource); - } - } - break; - } - default: - { - handleContainment(notification); - break; - } - } - } - break; - } - case Resource.RESOURCE__IS_LOADED: - { - if (notification.getNewBooleanValue()) - { - unloadedResources.remove(notifier); - for (Notifier child : ((Resource)notifier).getContents()) - { - addAdapter(child); - } - } - else - { - unloadedResources.add((Resource)notifier); - for (Iterator> i = unloadedEObjects.entrySet().iterator(); i.hasNext(); ) - { - Map.Entry entry = i.next(); - if (entry.getValue() == notifier) - { - i.remove(); - if (!resolve()) - { - EObject eObject = entry.getKey(); - Collection settings = inverseCrossReferencer.get(eObject); - if (settings != null) - { - for (EStructuralFeature.Setting setting : settings) - { - inverseCrossReferencer.addProxy(eObject, setting.getEObject()); - } - } - } - } - } - } - break; - } - } - } - else if (notifier instanceof ResourceSet) - { - if (notification.getFeatureID(ResourceSet.class) == ResourceSet.RESOURCE_SET__RESOURCES) - { - handleContainment(notification); - } - } - } - - /** - * Handles a containment change by adding and removing the adapter as appropriate. - */ - protected void handleContainment(Notification notification) - { - switch (notification.getEventType()) - { - case Notification.RESOLVE: - { - Notifier oldValue = (Notifier)notification.getOldValue(); - removeAdapter(oldValue); - Notifier newValue = (Notifier)notification.getNewValue(); - addAdapter(newValue); - break; - } - case Notification.UNSET: - { - Object newValue = notification.getNewValue(); - if (newValue != null && newValue != Boolean.TRUE && newValue != Boolean.FALSE) - { - addAdapter((Notifier)newValue); - } - break; - } - case Notification.SET: - { - Notifier newValue = (Notifier)notification.getNewValue(); - if (newValue != null) - { - addAdapter(newValue); - } - break; - } - case Notification.ADD: - { - Notifier newValue = (Notifier)notification.getNewValue(); - if (newValue != null) - { - addAdapter(newValue); - } - break; - } - case Notification.ADD_MANY: - { - for (Object newValue : (Collection)notification.getNewValue()) - { - addAdapter((Notifier)newValue); - } - break; - } - } - } - - /** - * Handles a cross reference change by adding and removing the adapter as appropriate. - */ - protected void handleCrossReference(EReference reference, Notification notification) - { - switch (notification.getEventType()) - { - case Notification.RESOLVE: - case Notification.SET: - case Notification.UNSET: - { - EObject notifier = (EObject)notification.getNotifier(); - EReference feature = (EReference)notification.getFeature(); - if (!feature.isMany() || notification.getPosition() != Notification.NO_INDEX) - { - EObject oldValue = (EObject)notification.getOldValue(); - if (oldValue != null) - { - inverseCrossReferencer.remove(notifier, feature, oldValue); - } - EObject newValue = (EObject)notification.getNewValue(); - if (newValue != null) - { - inverseCrossReferencer.add(notifier, feature, newValue); - } - } - break; - } - case Notification.ADD: - { - EObject newValue = (EObject)notification.getNewValue(); - if (newValue != null) - { - inverseCrossReferencer.add((EObject)notification.getNotifier(), (EReference)notification.getFeature(), newValue); - } - break; - } - case Notification.ADD_MANY: - { - EObject notifier = (EObject)notification.getNotifier(); - EReference feature = (EReference)notification.getFeature(); - for (Object newValue : (Collection)notification.getNewValue()) - { - inverseCrossReferencer.add(notifier, feature, (EObject)newValue); - } - break; - } - case Notification.REMOVE: - { - EObject oldValue = (EObject)notification.getOldValue(); - if (oldValue != null) - { - inverseCrossReferencer.remove((EObject)notification.getNotifier(), (EReference)notification.getFeature(), oldValue); - } - break; - } - case Notification.REMOVE_MANY: - { - EObject notifier = (EObject)notification.getNotifier(); - EReference feature = (EReference)notification.getFeature(); - for (Object oldValue : (Collection)notification.getOldValue()) - { - inverseCrossReferencer.remove(notifier, feature, (EObject)oldValue); - } - break; - } - } - } - - /** - * Handles installation of the adapter - * by adding the adapter to each of the directly contained objects. - */ - public void setTarget(Notifier target) - { - if (target instanceof EObject) - { - setTarget((EObject)target); - } - else if (target instanceof Resource) - { - setTarget((Resource)target); - } - else if (target instanceof ResourceSet) - { - setTarget((ResourceSet)target); - } - } - - /** - * Handles installation of the adapter on an EObject - * by adding the adapter to each of the directly contained objects. - */ - protected void setTarget(EObject target) - { - inverseCrossReferencer.add(target); - - if (useRecursion()) - { - for (@SuppressWarnings("unchecked") Iterator i = - resolve() ? - target.eContents().iterator() : - (Iterator)((InternalEList)target.eContents()).basicIterator(); - i.hasNext(); ) - { - Notifier notifier = i.next(); - addAdapter(notifier); - } - } - else if (!iterating) - { - iterating = true; - for (TreeIterator i = EcoreUtil.getAllContents(target, resolve()); i.hasNext(); ) - { - EObject eObject = i.next(); - if (eObject.eAdapters().contains(this)) - { - i.prune(); - } - else - { - addAdapter(eObject); - } - } - iterating = false; - } - } - - /** - * Handles installation of the adapter on a Resource - * by adding the adapter to each of the directly contained objects. - */ - protected void setTarget(Resource target) - { - if (!target.isLoaded()) - { - unloadedResources.add(target); - } - List contents = target.getContents(); - for (EObject e : contents) - { - Notifier notifier = e; - addAdapter(notifier); - } - } - - /** - * Handles installation of the adapter on a ResourceSet - * by adding the adapter to each of the directly contained objects. - */ - protected void setTarget(ResourceSet target) - { - List resources = target.getResources(); - for (Resource e : resources) - { - Notifier notifier = e; - addAdapter(notifier); - } - } - - /** - * Handles undoing the installation of the adapter - * by removing the adapter to each of the directly contained objects. - */ - public void unsetTarget(Notifier target) - { - if (target instanceof EObject) - { - unsetTarget((EObject)target); - } - else if (target instanceof Resource) - { - unsetTarget((Resource)target); - } - else if (target instanceof ResourceSet) - { - unsetTarget((ResourceSet)target); - } - } - - /** - * Handles undoing the installation of the adapter from an EObject - * by removing the adapter to each of the directly contained objects. - */ - protected void unsetTarget(EObject target) - { - for (EContentsEList.FeatureIterator i = inverseCrossReferencer.getCrossReferences(target); i.hasNext(); ) - { - EObject crossReferencedEObject = i.next(); - inverseCrossReferencer.remove(target, (EReference)i.feature(), crossReferencedEObject); - } - - if (useRecursion()) - { - for (@SuppressWarnings("unchecked") Iterator i = - resolve() ? - (Iterator)(Iterator)target.eContents().iterator() : - (Iterator)((InternalEList)target.eContents()).basicIterator(); - i.hasNext(); ) - { - // Don't remove the adapter if the object is in a different resource - // and that resource (and hence all its contents) are being cross referenced. - // - InternalEObject internalEObject = i.next(); - Resource eDirectResource = internalEObject.eDirectResource(); - if (eDirectResource == null || !eDirectResource.eAdapters().contains(this)) - { - removeAdapter(internalEObject); - } - } - } - else if (!iterating) - { - iterating = true; - for (TreeIterator i = EcoreUtil.getAllContents(target, resolve()); i.hasNext(); ) - { - // Don't remove the adapter if the object is in a different resource - // and that resource (and hence all its contents) are being cross referenced. - // - InternalEObject internalEObject = i.next(); - Resource eDirectResource = internalEObject.eDirectResource(); - if (eDirectResource == null || !eDirectResource.eAdapters().contains(this)) - { - removeAdapter(internalEObject); - } - } - iterating = false; - } - } - - /** - * Handles undoing the installation of the adapter from a Resource - * by removing the adapter to each of the directly contained objects. - */ - protected void unsetTarget(Resource target) - { - List contents = target.getContents(); - for (EObject e : contents) - { - Notifier notifier = e; - removeAdapter(notifier); - } - unloadedResources.remove(target); - } - - /** - * Handles undoing the installation of the adapter from a ResourceSet - * by removing the adapter to each of the directly contained objects. - */ - protected void unsetTarget(ResourceSet target) - { - List resources = target.getResources(); - for (Resource e : resources) - { - Notifier notifier = e; - removeAdapter(notifier); - } - } - - protected void addAdapter(Notifier notifier) - { - List eAdapters = notifier.eAdapters(); - if (!eAdapters.contains(this)) - { - boolean oldSettingTargets = settingTargets; - try - { - settingTargets = true; - eAdapters.add(this); - } - finally - { - settingTargets = oldSettingTargets; - } - } - } - - protected void removeAdapter(Notifier notifier) - { - notifier.eAdapters().remove(this); - } - - public void dump() - { - EcoreUtil.CrossReferencer.print(System.out, inverseCrossReferencer); - } - - public Notifier getTarget() - { - return null; - } - - public boolean isAdapterForType(Object type) - { - return false; - } - - protected boolean resolve() - { - return true; - } +public class SmartEMFCrossReferenceAdapter implements Adapter.Internal { + /** + * Returns the first {@link ECrossReferenceAdapter} in the notifier's + * {@link Notifier#eAdapters() adapter list}, or null, if there + * isn't one. + * + * @param notifier the object to search. + * @return the first ECrossReferenceAdapter in the notifier's adapter list. + */ + public static ECrossReferenceAdapter getCrossReferenceAdapter(Notifier notifier) { + List adapters = notifier.eAdapters(); + for (int i = 0, size = adapters.size(); i < size; ++i) { + Object adapter = adapters.get(i); + if (adapter instanceof ECrossReferenceAdapter) { + return (ECrossReferenceAdapter) adapter; + } + } + return null; + } + + protected Set unloadedResources = new HashSet(); + protected Map unloadedEObjects = new HashMap(); + + protected class InverseCrossReferencer extends EcoreUtil.CrossReferencer { + private static final long serialVersionUID = 1L; + + protected Map> proxyMap; + + /** + * @since 2.10 + */ + protected EContentsEList.FeatureFilter crossReferenceFilter; + + protected InverseCrossReferencer() { + super((Collection) null); + + crossReferenceFilter = createCrossReferenceFilter(); + } + + /** + * @since 2.10 + */ + protected EContentsEList.FeatureFilter createCrossReferenceFilter() { + return new EContentsEList.FeatureFilter() { + public boolean isIncluded(EStructuralFeature eStructuralFeature) { + return FeatureMapUtil.isFeatureMap(eStructuralFeature) + || SmartEMFCrossReferenceAdapter.this.isIncluded((EReference) eStructuralFeature); + } + }; + } + + @Override + protected EContentsEList.FeatureIterator getCrossReferences(EObject eObject) { + InternalEList eCrossReferences = (InternalEList) eObject.eCrossReferences(); + + final EContentsEList.FeatureIterator underlyingIterator = (FeatureIterator) (resolve() + ? eCrossReferences.iterator() + : eCrossReferences.basicIterator()); + + if (underlyingIterator instanceof EContentsEList.Filterable) { + // Simply filter the model-provided iterator to skip the references that we + // don't need to index + ((EContentsEList.Filterable) underlyingIterator).filter(crossReferenceFilter); + return underlyingIterator; + } + + // Otherwise, we'll post-filter the iterator, ourselves, but this does mean that + // we may compute derived features unnecessarily + return new EContentsEList.FeatureIterator() { + private boolean prepared; + + private EObject preparedNext; + + private EStructuralFeature preparedFeature; + + private EStructuralFeature feature; + + public boolean hasNext() { + if (!prepared) { + while (underlyingIterator.hasNext()) { + preparedNext = underlyingIterator.next(); + preparedFeature = underlyingIterator.feature(); + if (crossReferenceFilter.isIncluded(preparedFeature)) { + prepared = true; + break; + } + } + } + + return prepared; + } + + public EObject next() { + if (!prepared && !hasNext()) { + throw new NoSuchElementException(); + } + + feature = preparedFeature; + prepared = false; + return preparedNext; + } + + public void remove() { + // Must not attempt to remove cross-references in indexing them + throw new UnsupportedOperationException(); + } + + public EStructuralFeature feature() { + return feature; + } + }; + } + + @Override + protected boolean crossReference(EObject eObject, EReference eReference, EObject crossReferencedEObject) { + return isIncluded(eReference); + } + + @Override + protected Collection newCollection() { + return new BasicEList() { + private static final long serialVersionUID = 1L; + + private static final int THRESHOLD = 100; + + private Map map; + + @Override + protected Object[] newData(int capacity) { + return new EStructuralFeature.Setting[capacity]; + } + + @Override + protected void didAdd(int index, EStructuralFeature.Setting setting) { + if (map != null) { + EObject eObject = setting.getEObject(); + EStructuralFeature eStructuralFeature = setting.getEStructuralFeature(); + Object object = map.get(eObject); + if (object == null) { + map.put(eObject, eStructuralFeature); + } else if (object instanceof Object[]) { + Object[] oldFeatures = (Object[]) object; + Object[] newFeatures = new Object[oldFeatures.length + 1]; + System.arraycopy(oldFeatures, 0, newFeatures, 0, oldFeatures.length); + newFeatures[oldFeatures.length] = eStructuralFeature; + map.put(eObject, newFeatures); + } else { + Object[] newFeatures = new Object[2]; + newFeatures[0] = object; + newFeatures[1] = eStructuralFeature; + map.put(eObject, newFeatures); + } + } + } + + @Override + protected void didRemove(int index, EStructuralFeature.Setting setting) { + if (map != null) { + if (size < THRESHOLD / 2) { + map = null; + } else { + EObject eObject = setting.getEObject(); + Object object = map.get(eObject); + if (object instanceof Object[]) { + Object[] oldFeatures = (Object[]) object; + EStructuralFeature eStructuralFeature = setting.getEStructuralFeature(); + if (oldFeatures.length == 2) { + map.put(eObject, + oldFeatures[0] == eStructuralFeature ? oldFeatures[1] : oldFeatures[0]); + } else { + Object[] newFeatures = new Object[oldFeatures.length - 1]; + for (int i = 0; i < oldFeatures.length; ++i) { + Object oldFeature = oldFeatures[i]; + if (oldFeature == eStructuralFeature) { + System.arraycopy(oldFeatures, i + 1, newFeatures, i, + oldFeatures.length - i - 1); + break; + } else { + newFeatures[i] = oldFeatures[i]; + } + } + map.put(eObject, newFeatures); + } + } else { + map.remove(eObject); + } + } + } + } + + @Override + public boolean add(EStructuralFeature.Setting setting) { + if (size > 0 && (!settingTargets || SmartEMFCrossReferenceAdapter.this.resolve())) { + EObject eObject = setting.getEObject(); + if (size > THRESHOLD) { + if (map == null) { + map = new HashMap(); + EStructuralFeature.Setting[] settingData = (EStructuralFeature.Setting[]) data; + for (int i = 0; i < size; ++i) { + didAdd(i, settingData[i]); + } + } + + Object object = map.get(eObject); + if (object != null) { + EStructuralFeature eStructuralFeature = setting.getEStructuralFeature(); + if (object == eStructuralFeature) { + return false; + } else if (object instanceof Object[]) { + Object[] features = (Object[]) object; + for (int i = 0; i < features.length; ++i) { + if (features[i] == eStructuralFeature) { + return false; + } + } + } + } + } else { + EStructuralFeature eStructuralFeature = setting.getEStructuralFeature(); + EStructuralFeature.Setting[] settingData = (EStructuralFeature.Setting[]) data; + for (int i = 0; i < size; ++i) { + EStructuralFeature.Setting containedSetting = settingData[i]; + if (containedSetting.getEObject() == eObject + && containedSetting.getEStructuralFeature() == eStructuralFeature) { + return false; + } + } + } + } + addUnique(setting); + return true; + } + }; + } + + public void add(EObject eObject) { + handleCrossReference(eObject); + if (!resolve()) { + addProxy(eObject, eObject); + } + } + + @Override + protected void add(InternalEObject eObject, EReference eReference, EObject crossReferencedEObject) { + super.add(eObject, eReference, crossReferencedEObject); + if (!resolve()) { + addProxy(crossReferencedEObject, eObject); + } + } + + public void add(EObject eObject, EReference eReference, EObject crossReferencedEObject) { + add((InternalEObject) eObject, eReference, crossReferencedEObject); + } + + protected void addProxy(EObject proxy, EObject context) { + if (proxy.eIsProxy()) { + if (proxyMap == null) { + proxyMap = new HashMap>(); + } + URI uri = normalizeURI(((InternalEObject) proxy).eProxyURI(), context); + List proxies = proxyMap.get(uri); + if (proxies == null) { + proxyMap.put(uri, proxies = new BasicEList.FastCompare()); + } + proxies.add(proxy); + } + } + + public Object remove(EObject eObject) { + if (!resolve()) { + removeProxy(eObject, eObject); + } + return super.remove(eObject); + } + + public void remove(EObject eObject, EReference eReference, EObject crossReferencedEObject) { + if (!resolve()) { + removeProxy(crossReferencedEObject, eObject); + } + BasicEList collection = (BasicEList) get( + crossReferencedEObject); + if (collection != null) { + EStructuralFeature.Setting[] settingData = (EStructuralFeature.Setting[]) collection.data(); + for (int i = 0, size = collection.size(); i < size; ++i) { + EStructuralFeature.Setting setting = settingData[i]; + if (setting.getEObject() == eObject && setting.getEStructuralFeature() == eReference) { + if (collection.size() == 1) { + super.remove(crossReferencedEObject); + } else { + collection.remove(i); + } + break; + } + } + } + } + + protected void removeProxy(EObject proxy, EObject context) { + if (proxyMap != null && proxy.eIsProxy()) { + URI uri = normalizeURI(((InternalEObject) proxy).eProxyURI(), context); + List proxies = proxyMap.get(uri); + if (proxies != null) { + proxies.remove(proxy); + if (proxies.isEmpty()) { + proxyMap.remove(uri); + } + } + } + } + + protected List removeProxies(URI uri) { + return proxyMap != null ? proxyMap.remove(uri) : null; + } + + protected URI normalizeURI(URI uri, EObject objectContext) { + // This should be the same as the logic in ResourceImpl.getEObject(String). + // + String fragment = uri.fragment(); + if (fragment != null) { + int length = fragment.length(); + if (length > 0 && fragment.charAt(0) != '/' && fragment.charAt(length - 1) == '?') { + int index = fragment.lastIndexOf('?', length - 2); + if (index > 0) { + uri = uri.trimFragment().appendFragment(fragment.substring(0, index)); + } + } + } + Resource resourceContext = objectContext.eResource(); + if (resourceContext != null) { + ResourceSet resourceSetContext = resourceContext.getResourceSet(); + if (resourceSetContext != null) { + return resourceSetContext.getURIConverter().normalize(uri); + } + } + return uri; + } + + @Override + protected boolean resolve() { + return SmartEMFCrossReferenceAdapter.this.resolve(); + } + } + + protected InverseCrossReferencer inverseCrossReferencer; + + protected boolean settingTargets; + + /** + * Indicates whether the adapter is currently being attached + * {@link #useRecursion() iteratively}. + * + * @see #useRecursion() + * @see #setTarget(EObject) + * @see #unsetTarget(EObject) + * @since 2.14 + */ + protected boolean iterating; + + public SmartEMFCrossReferenceAdapter() { + inverseCrossReferencer = createInverseCrossReferencer(); + } + + /** + * Returns whether the process of attaching this adapter should be done + * recursively or iteratively; the default is to return {@code true} for + * recursion. + * + * @since 2.14 + * @return whether the process of attaching this adapter should be done + * recursively or iteratively. + */ + protected boolean useRecursion() { + return true; + } + + public Collection getNonNavigableInverseReferences(EObject eObject) { + return getNonNavigableInverseReferences(eObject, !resolve()); + } + + public Collection getNonNavigableInverseReferences(EObject eObject, boolean resolve) { + if (resolve) { + resolveAll(eObject); + } + + Collection result = inverseCrossReferencer.get(eObject); + if (result == null) { + result = Collections.emptyList(); + } + return result; + } + + public Collection getInverseReferences(EObject eObject) { + return getInverseReferences(eObject, !resolve()); + } + + public Collection getInverseReferences(EObject eObject, boolean resolve) { + Collection result = new ArrayList(); + + if (resolve) { + resolveAll(eObject); + } + + EObject eContainer = resolve ? eObject.eContainer() : ((InternalEObject) eObject).eInternalContainer(); + if (eContainer != null) { + result.add(((InternalEObject) eContainer).eSetting(eObject.eContainmentFeature())); + } + + Collection nonNavigableInverseReferences = inverseCrossReferencer.get(eObject); + if (nonNavigableInverseReferences != null) { + result.addAll(nonNavigableInverseReferences); + } + + for (EReference eReference : eObject.eClass().getEAllReferences()) { + EReference eOpposite = eReference.getEOpposite(); + if (eOpposite != null && !eReference.isContainer() && eObject.eIsSet(eReference)) { + if (eReference.isMany()) { + Object collection = eObject.eGet(eReference); + for (@SuppressWarnings("unchecked") + Iterator j = resolve ? ((Collection) collection).iterator() + : ((InternalEList) collection).basicIterator(); j.hasNext();) { + InternalEObject referencingEObject = (InternalEObject) j.next(); + result.add(referencingEObject.eSetting(eOpposite)); + } + } else { + result.add(((InternalEObject) eObject.eGet(eReference, resolve)).eSetting(eOpposite)); + } + } + } + + return result; + } + + /** + * @since 2.17 + */ + public Collection getInverseReferences(EObject eObject, EReference eReference, + boolean resolve) { + Collection result = new ArrayList(); + + if (resolve) { + resolveAll(eObject); + } + + if (eReference.isContainment()) { + EReference containmentFeature = eObject.eContainmentFeature(); + if (eReference == containmentFeature) { + EObject eContainer = resolve ? eObject.eContainer() : ((InternalEObject) eObject).eInternalContainer(); + if (eContainer != null) { + result.add(((InternalEObject) eContainer).eSetting(containmentFeature)); + } + } + } else { + EReference eOpposite = eReference.getEOpposite(); + if (eOpposite == null) { + Collection nonNavigableInverseReferences = inverseCrossReferencer + .get(eObject); + if (nonNavigableInverseReferences != null) { + for (EStructuralFeature.Setting setting : nonNavigableInverseReferences) { + if (eReference == setting.getEStructuralFeature()) { + result.add(setting); + } + } + } + } else { + int featureID = eObject.eClass().getFeatureID(eOpposite); + if (featureID != -1) { + InternalEObject internalEObject = (InternalEObject) eObject; + if (internalEObject.eIsSet(featureID)) { + Object value = internalEObject.eGet(featureID, resolve, true); + if (eOpposite.isMany()) { + for (@SuppressWarnings("unchecked") + Iterator j = resolve ? ((Collection) value).iterator() + : ((InternalEList) value).basicIterator(); j.hasNext();) { + InternalEObject referencingEObject = (InternalEObject) j.next(); + result.add(referencingEObject.eSetting(eReference)); + } + } else { + result.add(((InternalEObject) value).eSetting(eReference)); + } + } + } + } + } + + return result; + } + + protected void resolveAll(EObject eObject) { + if (!eObject.eIsProxy()) { + Resource resource = eObject.eResource(); + if (resource != null) { + URI uri = resource.getURI(); + if (uri != null) { + ResourceSet resourceSet = resource.getResourceSet(); + if (resourceSet != null) { + uri = resourceSet.getURIConverter().normalize(uri); + } + uri = uri.appendFragment(resource.getURIFragment(eObject)); + } else { + uri = URI.createHierarchicalURI(null, null, resource.getURIFragment(eObject)); + } + List proxies = inverseCrossReferencer.removeProxies(uri); + if (proxies != null) { + for (int i = 0, size = proxies.size(); i < size; ++i) { + EObject proxy = proxies.get(i); + for (EStructuralFeature.Setting setting : getInverseReferences(proxy, false)) { + resolveProxy(resource, eObject, proxy, setting); + } + } + } + } + } + } + + protected void resolveProxy(Resource resource, EObject eObject, EObject proxy, EStructuralFeature.Setting setting) { + Object value = setting.get(true); + if (setting.getEStructuralFeature().isMany()) { + InternalEList list = (InternalEList) value; + List basicList = list.basicList(); + int index = basicList.indexOf(proxy); + if (index != -1) { + list.get(index); + } + } + } + + protected boolean isIncluded(EReference eReference) { + return eReference.getEOpposite() == null && !eReference.isDerived(); + } + + protected InverseCrossReferencer createInverseCrossReferencer() { + return new InverseCrossReferencer(); + } + + /** + * Handles a notification by calling {@link #selfAdapt selfAdapter}. + */ + public void notifyChanged(Notification notification) { + selfAdapt(notification); + } + + /** + * Handles a notification by calling {@link #handleContainment + * handleContainment} for any containment-based notification. + */ + protected void selfAdapt(Notification notification) { + Object notifier = notification.getNotifier(); + if (notifier instanceof EObject) { + Object feature = notification.getFeature(); + if (feature instanceof EReference) { + EReference reference = (EReference) feature; + if (reference.isContainment()) { + handleContainment(notification); + } else if (isIncluded(reference)) { + handleCrossReference(reference, notification); + } + } + } else if (notifier instanceof Resource) { + switch (notification.getFeatureID(Resource.class)) { + case Resource.RESOURCE__CONTENTS: { + if (!unloadedResources.contains(notifier)) { + switch (notification.getEventType()) { + case Notification.REMOVE: { + Resource resource = (Resource) notifier; + if (!resource.isLoaded()) { + EObject eObject = (EObject) notification.getOldValue(); + unloadedEObjects.put(eObject, resource); + for (Iterator i = EcoreUtil.getAllProperContents(eObject, false); i.hasNext();) { + unloadedEObjects.put(i.next(), resource); + } + } + break; + } + case Notification.REMOVE_MANY: { + Resource resource = (Resource) notifier; + if (!resource.isLoaded()) { + @SuppressWarnings("unchecked") + List eObjects = (List) notification.getOldValue(); + for (Iterator i = EcoreUtil.getAllProperContents(eObjects, false); i.hasNext();) { + unloadedEObjects.put(i.next(), resource); + } + } + break; + } + default: { + handleContainment(notification); + break; + } + } + } + break; + } + case Resource.RESOURCE__IS_LOADED: { + if (notification.getNewBooleanValue()) { + unloadedResources.remove(notifier); + for (Notifier child : ((Resource) notifier).getContents()) { + addAdapter(child); + } + } else { + unloadedResources.add((Resource) notifier); + for (Iterator> i = unloadedEObjects.entrySet().iterator(); i + .hasNext();) { + Map.Entry entry = i.next(); + if (entry.getValue() == notifier) { + i.remove(); + if (!resolve()) { + EObject eObject = entry.getKey(); + Collection settings = inverseCrossReferencer.get(eObject); + if (settings != null) { + for (EStructuralFeature.Setting setting : settings) { + inverseCrossReferencer.addProxy(eObject, setting.getEObject()); + } + } + } + } + } + } + break; + } + } + } else if (notifier instanceof ResourceSet) { + if (notification.getFeatureID(ResourceSet.class) == ResourceSet.RESOURCE_SET__RESOURCES) { + handleContainment(notification); + } + } + } + + /** + * Handles a containment change by adding and removing the adapter as + * appropriate. + */ + protected void handleContainment(Notification notification) { + switch (notification.getEventType()) { + case Notification.RESOLVE: { + Notifier oldValue = (Notifier) notification.getOldValue(); + removeAdapter(oldValue); + Notifier newValue = (Notifier) notification.getNewValue(); + addAdapter(newValue); + break; + } + case Notification.UNSET: { + Object newValue = notification.getNewValue(); + if (newValue != null && newValue != Boolean.TRUE && newValue != Boolean.FALSE) { + addAdapter((Notifier) newValue); + } + break; + } + case Notification.SET: { + Notifier newValue = (Notifier) notification.getNewValue(); + if (newValue != null) { + addAdapter(newValue); + } + break; + } + case Notification.ADD: { + Notifier newValue = (Notifier) notification.getNewValue(); + if (newValue != null) { + addAdapter(newValue); + } + break; + } + case Notification.ADD_MANY: { + for (Object newValue : (Collection) notification.getNewValue()) { + addAdapter((Notifier) newValue); + } + break; + } + } + } + + /** + * Handles a cross reference change by adding and removing the adapter as + * appropriate. + */ + protected void handleCrossReference(EReference reference, Notification notification) { + switch (notification.getEventType()) { + case Notification.RESOLVE: + case Notification.SET: + case Notification.UNSET: { + EObject notifier = (EObject) notification.getNotifier(); + EReference feature = (EReference) notification.getFeature(); + if (!feature.isMany() || notification.getPosition() != Notification.NO_INDEX) { + EObject oldValue = (EObject) notification.getOldValue(); + if (oldValue != null) { + inverseCrossReferencer.remove(notifier, feature, oldValue); + } + EObject newValue = (EObject) notification.getNewValue(); + if (newValue != null) { + inverseCrossReferencer.add(notifier, feature, newValue); + } + } + break; + } + case Notification.ADD: { + EObject newValue = (EObject) notification.getNewValue(); + if (newValue != null) { + inverseCrossReferencer.add((EObject) notification.getNotifier(), (EReference) notification.getFeature(), + newValue); + } + break; + } + case Notification.ADD_MANY: { + EObject notifier = (EObject) notification.getNotifier(); + EReference feature = (EReference) notification.getFeature(); + for (Object newValue : (Collection) notification.getNewValue()) { + inverseCrossReferencer.add(notifier, feature, (EObject) newValue); + } + break; + } + case Notification.REMOVE: { + EObject oldValue = (EObject) notification.getOldValue(); + if (oldValue != null) { + inverseCrossReferencer.remove((EObject) notification.getNotifier(), + (EReference) notification.getFeature(), oldValue); + } + break; + } + case Notification.REMOVE_MANY: { + EObject notifier = (EObject) notification.getNotifier(); + EReference feature = (EReference) notification.getFeature(); + for (Object oldValue : (Collection) notification.getOldValue()) { + inverseCrossReferencer.remove(notifier, feature, (EObject) oldValue); + } + break; + } + } + } + + /** + * Handles installation of the adapter by adding the adapter to each of the + * directly contained objects. + */ + public void setTarget(Notifier target) { + if (target instanceof EObject) { + setTarget((EObject) target); + } else if (target instanceof Resource) { + setTarget((Resource) target); + } else if (target instanceof ResourceSet) { + setTarget((ResourceSet) target); + } + } + + /** + * Handles installation of the adapter on an EObject by adding the adapter to + * each of the directly contained objects. + */ + protected void setTarget(EObject target) { + inverseCrossReferencer.add(target); + + if (useRecursion()) { + for (@SuppressWarnings("unchecked") + Iterator i = resolve() ? target.eContents().iterator() + : (Iterator) ((InternalEList) target.eContents()).basicIterator(); i.hasNext();) { + Notifier notifier = i.next(); + addAdapter(notifier); + } + } else if (!iterating) { + iterating = true; + for (TreeIterator i = EcoreUtil.getAllContents(target, resolve()); i.hasNext();) { + EObject eObject = i.next(); + if (eObject.eAdapters().contains(this)) { + i.prune(); + } else { + addAdapter(eObject); + } + } + iterating = false; + } + } + + /** + * Handles installation of the adapter on a Resource by adding the adapter to + * each of the directly contained objects. + */ + protected void setTarget(Resource target) { + if (!target.isLoaded()) { + unloadedResources.add(target); + } + List contents = target.getContents(); + for (EObject e : contents) { + Notifier notifier = e; + addAdapter(notifier); + } + } + + /** + * Handles installation of the adapter on a ResourceSet by adding the adapter to + * each of the directly contained objects. + */ + protected void setTarget(ResourceSet target) { + List resources = target.getResources(); + for (Resource e : resources) { + Notifier notifier = e; + addAdapter(notifier); + } + } + + /** + * Handles undoing the installation of the adapter by removing the adapter to + * each of the directly contained objects. + */ + public void unsetTarget(Notifier target) { + if (target instanceof EObject) { + unsetTarget((EObject) target); + } else if (target instanceof Resource) { + unsetTarget((Resource) target); + } else if (target instanceof ResourceSet) { + unsetTarget((ResourceSet) target); + } + } + + /** + * Handles undoing the installation of the adapter from an EObject by removing + * the adapter to each of the directly contained objects. + */ + protected void unsetTarget(EObject target) { + for (EContentsEList.FeatureIterator i = inverseCrossReferencer.getCrossReferences(target); i + .hasNext();) { + EObject crossReferencedEObject = i.next(); + inverseCrossReferencer.remove(target, (EReference) i.feature(), crossReferencedEObject); + } + + if (useRecursion()) { + for (@SuppressWarnings("unchecked") + Iterator i = resolve() + ? (Iterator) (Iterator) target.eContents().iterator() + : (Iterator) ((InternalEList) target.eContents()).basicIterator(); i + .hasNext();) { + // Don't remove the adapter if the object is in a different resource + // and that resource (and hence all its contents) are being cross referenced. + // + InternalEObject internalEObject = i.next(); + Resource eDirectResource = internalEObject.eDirectResource(); + if (eDirectResource == null || !eDirectResource.eAdapters().contains(this)) { + removeAdapter(internalEObject); + } + } + } else if (!iterating) { + iterating = true; + for (TreeIterator i = EcoreUtil.getAllContents(target, resolve()); i.hasNext();) { + // Don't remove the adapter if the object is in a different resource + // and that resource (and hence all its contents) are being cross referenced. + // + InternalEObject internalEObject = i.next(); + Resource eDirectResource = internalEObject.eDirectResource(); + if (eDirectResource == null || !eDirectResource.eAdapters().contains(this)) { + removeAdapter(internalEObject); + } + } + iterating = false; + } + } + + /** + * Handles undoing the installation of the adapter from a Resource by removing + * the adapter to each of the directly contained objects. + */ + protected void unsetTarget(Resource target) { + List contents = target.getContents(); + for (EObject e : contents) { + Notifier notifier = e; + removeAdapter(notifier); + } + unloadedResources.remove(target); + } + + /** + * Handles undoing the installation of the adapter from a ResourceSet by + * removing the adapter to each of the directly contained objects. + */ + protected void unsetTarget(ResourceSet target) { + List resources = target.getResources(); + for (Resource e : resources) { + Notifier notifier = e; + removeAdapter(notifier); + } + } + + protected void addAdapter(Notifier notifier) { + List eAdapters = notifier.eAdapters(); + if (!eAdapters.contains(this)) { + boolean oldSettingTargets = settingTargets; + try { + settingTargets = true; + eAdapters.add(this); + } finally { + settingTargets = oldSettingTargets; + } + } + } + + protected void removeAdapter(Notifier notifier) { + notifier.eAdapters().remove(this); + } + + public void dump() { + EcoreUtil.CrossReferencer.print(System.out, inverseCrossReferencer); + } + + public Notifier getTarget() { + return null; + } + + public boolean isAdapterForType(Object type) { + return false; + } + + protected boolean resolve() { + return true; + } } \ No newline at end of file diff --git a/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/notification/SmartEMFNotification.java b/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/notification/SmartEMFNotification.java index 24db58b7..0afa0dee 100644 --- a/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/notification/SmartEMFNotification.java +++ b/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/notification/SmartEMFNotification.java @@ -13,7 +13,8 @@ public final class SmartEMFNotification implements Notification { private Object newValue; private int position; - private SmartEMFNotification(int eventType, Object notifier, EStructuralFeature feature, Object oldValue, Object newValue, int position) { + private SmartEMFNotification(int eventType, Object notifier, EStructuralFeature feature, Object oldValue, + Object newValue, int position) { this.eventType = eventType; this.notifier = notifier; this.feature = feature; @@ -22,35 +23,43 @@ private SmartEMFNotification(int eventType, Object notifier, EStructuralFeature this.position = position; } - public static Notification createAddNotification(Object notifier, EStructuralFeature feature, Object newValue, int index) { + public static Notification createAddNotification(Object notifier, EStructuralFeature feature, Object newValue, + int index) { return new SmartEMFNotification(ADD, notifier, feature, null, newValue, index); } - public static Notification createAddManyNotification(Object notifier, EStructuralFeature feature, Object newValue, int index) { + public static Notification createAddManyNotification(Object notifier, EStructuralFeature feature, Object newValue, + int index) { return new SmartEMFNotification(ADD_MANY, notifier, feature, null, newValue, index); } - public static Notification createSetNotification(Object notifier, EStructuralFeature feature, Object oldValue, Object newValue, int index) { + public static Notification createSetNotification(Object notifier, EStructuralFeature feature, Object oldValue, + Object newValue, int index) { return new SmartEMFNotification(SET, notifier, feature, oldValue, newValue, index); } - public static Notification createUnSetNotification(Object notifier, EStructuralFeature feature, Object oldValue, int index) { + public static Notification createUnSetNotification(Object notifier, EStructuralFeature feature, Object oldValue, + int index) { return new SmartEMFNotification(UNSET, notifier, feature, oldValue, null, index); } - public static Notification createRemoveNotification(Object notifier, EStructuralFeature feature, Object oldValue, int index) { + public static Notification createRemoveNotification(Object notifier, EStructuralFeature feature, Object oldValue, + int index) { return new SmartEMFNotification(REMOVE, notifier, feature, oldValue, null, index); } - public static Notification createRemoveManyNotification(Object notifier, EStructuralFeature feature, Object oldValue, int index) { + public static Notification createRemoveManyNotification(Object notifier, EStructuralFeature feature, + Object oldValue, int index) { return new SmartEMFNotification(REMOVE_MANY, notifier, feature, oldValue, null, index); } - public static Notification createRemovingAdapterNotification(Object notifier, EStructuralFeature feature, Object oldValue, int index) { + public static Notification createRemovingAdapterNotification(Object notifier, EStructuralFeature feature, + Object oldValue, int index) { return new SmartEMFNotification(REMOVING_ADAPTER, notifier, feature, oldValue, null, index); } - public static Notification createMoveNotification(Object notifier, EStructuralFeature feature, Object value, int oldIndex, int newIndex) { + public static Notification createMoveNotification(Object notifier, EStructuralFeature feature, Object value, + int oldIndex, int newIndex) { return new SmartEMFNotification(MOVE, notifier, feature, oldIndex, value, newIndex); } @@ -140,7 +149,8 @@ public int getPosition() { @Override /** - * Returns whether the notification can be and has been merged with this one.
+ * Returns whether the notification can be and has been merged with this one. + *
* Notifications can be merged when all these conditions are met: *
    *
  • They have the same notifier
  • @@ -153,10 +163,12 @@ public int getPosition() { *
* * - * null is treated as a "nothing new happened" notification and will always be merged; the - * result of this merging is the unmodified old notification. + * null is treated as a "nothing new happened" notification and will + * always be merged; the result of this merging is the unmodified old + * notification. * - * @param notification a notification that happened after this one (if order is relevant) + * @param notification a notification that happened after this one (if order is + * relevant) * @return whether the notification can be and has been merged with this one. */ public boolean merge(Notification notification) { diff --git a/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/util/SmartEMFUtil.java b/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/util/SmartEMFUtil.java index 29828224..08a8cdd1 100644 --- a/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/util/SmartEMFUtil.java +++ b/org.emoflon.smartemf/src/org/emoflon/smartemf/runtime/util/SmartEMFUtil.java @@ -26,7 +26,8 @@ public class SmartEMFUtil { public static void deleteNode(EObject node, boolean recursive) { - // reset containment is only called for this element (and not recursively) like in EMF + // reset containment is only called for this element (and not recursively) like + // in EMF deleteNode_internal(node, recursive); ((SmartObject) node).resetContainment(); } @@ -93,7 +94,8 @@ private static void resolveAll(EObject eObject) { @SuppressWarnings("unchecked") private static void resolveCrossReferences(EObject eObject) { - // for all but SmartEMF objects we assume the references are resolved by iterating over them + // for all but SmartEMF objects we assume the references are resolved by + // iterating over them if (eObject instanceof SmartObject) { for (EReference reference : eObject.eClass().getEAllReferences()) { if (reference.isContainment()) @@ -124,7 +126,8 @@ private static void resolveCrossReferences(EObject eObject) { } private static void resolveProxyContainer(EObject eObject) { - // for all but SmartEMF objects we assume the container is resolved by calling EObject#eContainer + // for all but SmartEMF objects we assume the container is resolved by calling + // EObject#eContainer EObject eContainer = eObject.eContainer(); if (eContainer != null && eContainer instanceof SmartObject && eContainer.eIsProxy()) { EObject resolved = EcoreUtil.resolve(eContainer, eObject); diff --git a/org.emoflon.smartemf/src/org/emoflon/smartemf/templates/CodeTemplate.java b/org.emoflon.smartemf/src/org/emoflon/smartemf/templates/CodeTemplate.java index 59872f44..d89d38c4 100644 --- a/org.emoflon.smartemf/src/org/emoflon/smartemf/templates/CodeTemplate.java +++ b/org.emoflon.smartemf/src/org/emoflon/smartemf/templates/CodeTemplate.java @@ -3,5 +3,5 @@ public interface CodeTemplate { public void createCode(); - + } diff --git a/org.emoflon.smartemf/src/org/emoflon/smartemf/templates/util/CodeFormattingUtil.java b/org.emoflon.smartemf/src/org/emoflon/smartemf/templates/util/CodeFormattingUtil.java index c5cdd675..6581d1f9 100644 --- a/org.emoflon.smartemf/src/org/emoflon/smartemf/templates/util/CodeFormattingUtil.java +++ b/org.emoflon.smartemf/src/org/emoflon/smartemf/templates/util/CodeFormattingUtil.java @@ -13,9 +13,9 @@ public class CodeFormattingUtil { public static String format(String code) { CodeFormatter codeFormatter = ToolFactory.createCodeFormatter(null); TextEdit textEdit = codeFormatter.format(CodeFormatter.K_UNKNOWN, code, 0, code.length(), 0, null); - if(textEdit == null) + if (textEdit == null) return code; - + IDocument doc = new Document(code); try { textEdit.apply(doc); diff --git a/org.emoflon.smartemf/src/org/emoflon/smartemf/templates/util/JarExtractor.java b/org.emoflon.smartemf/src/org/emoflon/smartemf/templates/util/JarExtractor.java index 468c40d6..09c00937 100644 --- a/org.emoflon.smartemf/src/org/emoflon/smartemf/templates/util/JarExtractor.java +++ b/org.emoflon.smartemf/src/org/emoflon/smartemf/templates/util/JarExtractor.java @@ -25,108 +25,108 @@ import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl; public class JarExtractor { - + private Map name2genModelFiles = new HashMap<>(); - private Map name2ecoreModelFiles = new HashMap<>(); - - private String tempPath; - private String path; - - public JarExtractor(String tempPath, String path) { - this.tempPath = tempPath; - this.path = path; - - GenModelPackage.eINSTANCE.getName(); - EcorePackage.eINSTANCE.getName(); - } + private Map name2ecoreModelFiles = new HashMap<>(); + + private String tempPath; + private String path; + + public JarExtractor(String tempPath, String path) { + this.tempPath = tempPath; + this.path = path; + + GenModelPackage.eINSTANCE.getName(); + EcorePackage.eINSTANCE.getName(); + } public Collection extractGenModels() throws IOException { File tmpFolder = new File(tempPath); tmpFolder.mkdirs(); Collection genModels = new LinkedList<>(); - + // read jar file and extract files readJarFile(path); - + // add all genmodels - for(String fileName : name2genModelFiles.keySet()) { - GenModel gen = getGenModel(name2genModelFiles.get(fileName)); + for (String fileName : name2genModelFiles.keySet()) { + GenModel gen = getGenModel(name2genModelFiles.get(fileName)); genModels.add(gen); } - + // clean up all created files name2genModelFiles.values().forEach(File::delete); name2ecoreModelFiles.values().forEach(File::delete); - + tmpFolder.delete(); - + return genModels; } - + public String readJarFile(String jarFilePath) { - try { - ZipFile zipFile = new ZipFile(jarFilePath); - Enumeration e = zipFile.entries(); - - while (e.hasMoreElements()) { - ZipEntry entry = (ZipEntry) e.nextElement(); - // if the entry is not directory and matches relative file then extract it - if (!entry.isDirectory()) { - BufferedInputStream bis = new BufferedInputStream(zipFile.getInputStream(entry)); - - // Read the file - String entryName = entry.getName(); - if(entryName.endsWith(".genmodel") || entryName.endsWith(".ecore")) { - File jarFile = new File(entryName); - - String fullFileName = jarFile.getName(); - String[] fileNameSplit = fullFileName.split("[.]"); - String fileName = fileNameSplit[0]; - String extensionName = fileNameSplit[1]; - - File newFile = new File(tempPath+File.separator+fullFileName); - newFile.createNewFile(); - copyInputStreamToFile(bis, newFile); - - if(extensionName.equals("genmodel")) { - name2genModelFiles.put(fileName, newFile); - } - if(extensionName.equals("ecore")) { - name2ecoreModelFiles.put(fileName, newFile); - } - } - bis.close(); - } else { - continue; - } - } - } catch (IOException e) { - e.printStackTrace(); - } - return null; + try { + ZipFile zipFile = new ZipFile(jarFilePath); + Enumeration e = zipFile.entries(); + + while (e.hasMoreElements()) { + ZipEntry entry = (ZipEntry) e.nextElement(); + // if the entry is not directory and matches relative file then extract it + if (!entry.isDirectory()) { + BufferedInputStream bis = new BufferedInputStream(zipFile.getInputStream(entry)); + + // Read the file + String entryName = entry.getName(); + if (entryName.endsWith(".genmodel") || entryName.endsWith(".ecore")) { + File jarFile = new File(entryName); + + String fullFileName = jarFile.getName(); + String[] fileNameSplit = fullFileName.split("[.]"); + String fileName = fileNameSplit[0]; + String extensionName = fileNameSplit[1]; + + File newFile = new File(tempPath + File.separator + fullFileName); + newFile.createNewFile(); + copyInputStreamToFile(bis, newFile); + + if (extensionName.equals("genmodel")) { + name2genModelFiles.put(fileName, newFile); + } + if (extensionName.equals("ecore")) { + name2ecoreModelFiles.put(fileName, newFile); + } + } + bis.close(); + } else { + continue; + } + } + } catch (IOException e) { + e.printStackTrace(); + } + return null; } - + public static GenModel getGenModel(File genModelFile) throws IOException { ResourceSet rs = new ResourceSetImpl(); rs.getResourceFactoryRegistry().getExtensionToFactoryMap().put("genmodel", new XMIResourceFactoryImpl()); rs.getResourceFactoryRegistry().getExtensionToFactoryMap().put("ecore", new XMIResourceFactoryImpl()); - Resource createResource = rs.createResource(URI.createFileURI(genModelFile.getAbsolutePath())); - createResource.load(null); - if(createResource.getContents().get(0) instanceof GenModel gen) { - // tricking emf into loading the ecore - GenPackage genPackage = gen.getGenPackages().get(0); - genPackage.getEcorePackage(); - return gen; - } - throw new RuntimeException("Genmodel not found in " + genModelFile.getAbsolutePath()); + Resource createResource = rs.createResource(URI.createFileURI(genModelFile.getAbsolutePath())); + createResource.load(null); + if (createResource.getContents().get(0) instanceof GenModel gen) { + // tricking emf into loading the ecore + GenPackage genPackage = gen.getGenPackages().get(0); + genPackage.getEcorePackage(); + return gen; + } + throw new RuntimeException("Genmodel not found in " + genModelFile.getAbsolutePath()); } - - public static void copyInputStreamToFile(InputStream input, File file) { - try (OutputStream output = new FileOutputStream(file)) { - input.transferTo(output); - } catch (IOException ioException) { - ioException.printStackTrace(); - } + + public static void copyInputStreamToFile(InputStream input, File file) { + try (OutputStream output = new FileOutputStream(file)) { + input.transferTo(output); + } catch (IOException ioException) { + ioException.printStackTrace(); + } } } diff --git a/org.emoflon.smartemf/src/org/emoflon/smartemf/templates/util/Keywords.java b/org.emoflon.smartemf/src/org/emoflon/smartemf/templates/util/Keywords.java index 8292298b..6ad495ba 100644 --- a/org.emoflon.smartemf/src/org/emoflon/smartemf/templates/util/Keywords.java +++ b/org.emoflon.smartemf/src/org/emoflon/smartemf/templates/util/Keywords.java @@ -7,13 +7,15 @@ public class Keywords { /** * The list of invalid parameter names. */ - final public static String[] keywords = new String[] {"class", "rule", "clone", "equals", "finalize", - "getClass", "hashCode", "notify", "notifyAll", "toString", "wait", - "abstract", "assert", "boolean", "break", "byte", "case", "catch", "char", "class", "const", "continue", "default", "do", "double", "EAttribute", "EBoolean", "EDataType", - "EClass", "EClassifier", "EDouble", "EFloat", "EInt", "else", "enum", "EPackage", "EReference", "EString", "extends", "final", "finally", "float", "for", "goto", "if", - "implements", "import", "instanceof", "int", "interface", "long", "native", "new", "package", "private", "protected", "public", "return", "short", "static", - "strictfp", "super", "switch", "synchronized", "this", "throw", "throws", "transient", "try", "void", "volatile", "while"}; - + final public static String[] keywords = new String[] { "class", "rule", "clone", "equals", "finalize", "getClass", + "hashCode", "notify", "notifyAll", "toString", "wait", "abstract", "assert", "boolean", "break", "byte", + "case", "catch", "char", "class", "const", "continue", "default", "do", "double", "EAttribute", "EBoolean", + "EDataType", "EClass", "EClassifier", "EDouble", "EFloat", "EInt", "else", "enum", "EPackage", "EReference", + "EString", "extends", "final", "finally", "float", "for", "goto", "if", "implements", "import", + "instanceof", "int", "interface", "long", "native", "new", "package", "private", "protected", "public", + "return", "short", "static", "strictfp", "super", "switch", "synchronized", "this", "throw", "throws", + "transient", "try", "void", "volatile", "while" }; + final public static HashSet blacklist = new HashSet<>(Arrays.asList(keywords)); - + } diff --git a/org.emoflon.smartemf/src/org/emoflon/smartemf/templates/util/TemplateUtil.xtend b/org.emoflon.smartemf/src/org/emoflon/smartemf/templates/util/TemplateUtil.xtend index daa7d8c9..0af2ff77 100644 --- a/org.emoflon.smartemf/src/org/emoflon/smartemf/templates/util/TemplateUtil.xtend +++ b/org.emoflon.smartemf/src/org/emoflon/smartemf/templates/util/TemplateUtil.xtend @@ -132,7 +132,9 @@ class TemplateUtil { for(genpkg : genModel.genPackages) { val pkgURI = genpkg.NSURI val genModelURI = pkgURI.replace(".ecore", ".genmodel") - val resourceURI = genModelURI.replace("platform:/", "platform:/resource/") + var resourceURI = genModelURI + if(!resourceURI.contains("platform:/resource/")) + resourceURI = resourceURI.replace("platform:/", "platform:/resource/") uriStringToGenModelMap.put(resourceURI, genModel) } } diff --git a/org.moflon.core.feature/feature.xml b/org.moflon.core.feature/feature.xml index d3b083ce..12d06299 100644 --- a/org.moflon.core.feature/feature.xml +++ b/org.moflon.core.feature/feature.xml @@ -107,20 +107,6 @@ See here for more details on EPL: https://www.eclipse.org/org/documents/epl-v10. version="0.0.0" unpack="false"/> - - - - - - - - - - - - diff --git a/org.moflon.core.ui.autosetup/.gitignore b/org.moflon.core.ui.autosetup/.gitignore deleted file mode 100644 index aec0be45..00000000 --- a/org.moflon.core.ui.autosetup/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/bin/ -/target/ -/.settings/ \ No newline at end of file diff --git a/org.moflon.core.ui.autosetup/.project b/org.moflon.core.ui.autosetup/.project deleted file mode 100644 index 3ce22c75..00000000 --- a/org.moflon.core.ui.autosetup/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - org.moflon.core.ui.autosetup - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.pde.PluginNature - org.eclipse.jdt.core.javanature - - diff --git a/org.moflon.core.ui.autosetup/META-INF/MANIFEST.MF b/org.moflon.core.ui.autosetup/META-INF/MANIFEST.MF deleted file mode 100644 index 325495f8..00000000 --- a/org.moflon.core.ui.autosetup/META-INF/MANIFEST.MF +++ /dev/null @@ -1,20 +0,0 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: eMoflon::Core Workspace auto-setup components -Bundle-SymbolicName: org.moflon.core.ui.autosetup;singleton:=true -Bundle-Version: 1.0.0.qualifier -Bundle-RequiredExecutionEnvironment: JavaSE-21 -Require-Bundle: org.eclipse.equinox.registry;bundle-version="[3.0.0,4.0.0)", - org.eclipse.team.ui;bundle-version="[3.0.0,4.0.0)", - org.eclipse.ui.workbench;bundle-version="[3.0.0,4.0.0)", - org.eclipse.jface;bundle-version="[3.0.0,4.0.0)", - org.eclipse.debug.core;bundle-version="[3.0.0,4.0.0)", - org.emoflon.core.dependencies;bundle-version="1.0.0", - org.moflon.core.build;bundle-version="[1.0.0,2.0.0)", - org.moflon.core.utilities;bundle-version="[3.0.0,4.0.0)", - org.moflon.core.ui;bundle-version="[1.0.0,2.0.0)" -Export-Package: org.moflon.core.ui.autosetup, - org.moflon.core.ui.autosetup.handbook, - org.moflon.core.ui.autosetup.handler -Automatic-Module-Name: org.moflon.core.ui.autosetup -Bundle-Vendor: eMoflon developers diff --git a/org.moflon.core.ui.autosetup/build.properties b/org.moflon.core.ui.autosetup/build.properties deleted file mode 100644 index c305a810..00000000 --- a/org.moflon.core.ui.autosetup/build.properties +++ /dev/null @@ -1,12 +0,0 @@ -source.. = src/ -output.. = bin/ -bin.includes = META-INF/,\ - .,\ - resources/,\ - plugin.xml,\ - src/,\ - schema/,\ - build.properties,\ - .project,\ - .gitignore,\ - .classpath diff --git a/org.moflon.core.ui.autosetup/plugin.xml b/org.moflon.core.ui.autosetup/plugin.xml deleted file mode 100644 index 91118849..00000000 --- a/org.moflon.core.ui.autosetup/plugin.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/org.moflon.core.ui.autosetup/resources/icons/junitmoflon.png b/org.moflon.core.ui.autosetup/resources/icons/junitmoflon.png deleted file mode 100644 index 8e811264..00000000 Binary files a/org.moflon.core.ui.autosetup/resources/icons/junitmoflon.png and /dev/null differ diff --git a/org.moflon.core.ui.autosetup/schema/RegisterPsfUrlExtension.exsd b/org.moflon.core.ui.autosetup/schema/RegisterPsfUrlExtension.exsd deleted file mode 100644 index 1d9c98e7..00000000 --- a/org.moflon.core.ui.autosetup/schema/RegisterPsfUrlExtension.exsd +++ /dev/null @@ -1,102 +0,0 @@ - - - - - - - - - Use this to register extensions that can contribute URL entries for built-in PSFs in the eMoflon::Core 'cloud' menu. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [Enter the first release in which this extension point appears.] - - - - - - - - - [Enter extension point usage example here.] - - - - - - - - - [Enter API information here.] - - - - - - - - - [Enter information about supplied implementation of this extension point.] - - - - - diff --git a/org.moflon.core.ui.autosetup/src/org/moflon/core/ui/autosetup/CloseProjectsJob.java b/org.moflon.core.ui.autosetup/src/org/moflon/core/ui/autosetup/CloseProjectsJob.java deleted file mode 100644 index 1833f8eb..00000000 --- a/org.moflon.core.ui.autosetup/src/org/moflon/core/ui/autosetup/CloseProjectsJob.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.moflon.core.ui.autosetup; - -import java.util.List; - -import org.eclipse.core.resources.IProject; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.core.runtime.SubMonitor; -import org.eclipse.core.runtime.jobs.Job; -import org.moflon.core.utilities.ProgressMonitorUtil; -import org.moflon.core.utilities.WorkspaceHelper; - -/** - * This {@link Job} closes the list of preconfigured projects (see - * {@link CloseProjectsJob#CloseProjectsJob(String, List)}) upon - * {@link #run(IProgressMonitor)} - * - * @author Roland Kluge - Initial implementation - */ -public final class CloseProjectsJob extends Job { - private final List projects; - - public CloseProjectsJob(String name, List projects) { - super(name); - this.projects = projects; - } - - @Override - protected IStatus run(final IProgressMonitor monitor) { - final SubMonitor closingMonitor = SubMonitor.convert(monitor, "Closing projects", projects.size()); - try { - for (final IProject project : projects) { - project.close(closingMonitor.split(1)); - ProgressMonitorUtil.checkCancellation(closingMonitor); - } - } catch (final CoreException e) { - return new Status(IStatus.ERROR, WorkspaceHelper.getPluginId(getClass()), e.getMessage(), e); - } finally { - SubMonitor.done(monitor); - } - - return Status.OK_STATUS; - } -} \ No newline at end of file diff --git a/org.moflon.core.ui.autosetup/src/org/moflon/core/ui/autosetup/ExploreEMoflonProjectsJob.java b/org.moflon.core.ui.autosetup/src/org/moflon/core/ui/autosetup/ExploreEMoflonProjectsJob.java deleted file mode 100644 index e27aa051..00000000 --- a/org.moflon.core.ui.autosetup/src/org/moflon/core/ui/autosetup/ExploreEMoflonProjectsJob.java +++ /dev/null @@ -1,183 +0,0 @@ -package org.moflon.core.ui.autosetup; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.LinkedList; -import java.util.List; -import java.util.stream.Collectors; - -import org.apache.log4j.Logger; -import org.eclipse.core.resources.IBuildConfiguration; -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.IResourceVisitor; -import org.eclipse.core.resources.ResourcesPlugin; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.MultiStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.core.runtime.SubMonitor; -import org.eclipse.core.runtime.jobs.Job; -import org.eclipse.debug.core.DebugPlugin; -import org.eclipse.debug.core.ILaunchConfiguration; -import org.eclipse.debug.core.ILaunchConfigurationType; -import org.eclipse.debug.core.ILaunchManager; -import org.gervarro.eclipse.workspace.util.WorkspaceTaskJob; -import org.moflon.core.build.BuildUtilities; -import org.moflon.core.build.ProjectBuilderTask; -import org.moflon.core.utilities.LogUtils; -import org.moflon.core.utilities.ProgressMonitorUtil; -import org.moflon.core.utilities.WorkspaceHelper; - -final class ExploreEMoflonProjectsJob extends Job { - private static final Logger logger = Logger.getLogger(ExploreEMoflonProjectsJob.class); - - private static final String LAUNCH_EXT = ".launch"; - private static final CharSequence AUTO_TESTSUITE = "TestSuite"; - - private final List jobs; - - private WorkspaceInstaller workspaceInstaller; - - ExploreEMoflonProjectsJob(String name, List jobs, String label, WorkspaceInstaller workspaceInstaller) { - super(name); - this.jobs = jobs; - this.workspaceInstaller = workspaceInstaller; - } - - @Override - protected final IStatus run(final IProgressMonitor monitor) { - final IProject[] graphicalMoflonProjects = workspaceInstaller.getProjectsToBuild(); - final List mweProjects = getProjectsWithMweWorkflows(); - if (mweProjects.size() > 0) { - try { - final ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager(); - final ILaunchConfigurationType type = manager - .getLaunchConfigurationType("org.eclipse.emf.mwe2.launch.Mwe2LaunchConfigurationType"); - final ILaunchConfiguration[] configurations = manager.getLaunchConfigurations(type); - if (configurations.length > 0) { - // (1) Closing projects with textual syntax (without workspace lock) - jobs.add(new CloseProjectsJob("Closing projects", mweProjects)); - // (2) Building projects with graphical syntax (with workspace lock) - prepareIncrementalProjectBuilderJob(jobs, graphicalMoflonProjects); - // (3) Launching MWE2 workflows to generate Xtext metamodels (without workspace - // lock) - final Job mweWorkflowLauncher = new LaunchConfigurationRunnerJob("Launching MWE2 workflows", - configurations); - mweWorkflowLauncher.setRule(ResourcesPlugin.getWorkspace().getRoot()); - jobs.add(mweWorkflowLauncher); - - // (4) Opening projects with textual syntax (without workspace lock) - jobs.add(new OpenProjectsJob("Opening projects", mweProjects)); - // (5) Building projects with textual syntax (with workspace lock) - prepareIncrementalProjectBuilderJob(jobs, mweProjects); - } else { - // Building projects (with workspace lock) - prepareIncrementalProjectBuilderJob(jobs, graphicalMoflonProjects); - prepareIncrementalProjectBuilderJob(jobs, mweProjects); - } - } catch (final CoreException e) { - // Building projects with graphical syntax (with workspace lock) - prepareIncrementalProjectBuilderJob(jobs, graphicalMoflonProjects); - } - } else { - // Building projects with graphical syntax (with workspace lock) - prepareIncrementalProjectBuilderJob(jobs, graphicalMoflonProjects); - } - - enqueueJUnitTestJob(jobs); - return Status.OK_STATUS; - } - - /** - * Searches for all projects that contain JUnit test configurations and enqueues - * a job that invokes all of these configurations into the given list of jobs - * - * @param jobs - * the job list - */ - private void enqueueJUnitTestJob(final List jobs) { - final List launchConfigurations = new LinkedList(); - for (final IProject testProjectCandidate : getAllOpenProjectsInWorkspace()) { - try { - final List selectedLaunchConfigurations = Arrays.asList(testProjectCandidate.members()).stream()// - .filter(m -> m instanceof IFile) // - .map(m -> (IFile) m.getAdapter(IFile.class))// - .filter(f -> f.getName().endsWith(LAUNCH_EXT) && f.getName().contains(AUTO_TESTSUITE))// - .collect(Collectors.toList()); - launchConfigurations.addAll(selectedLaunchConfigurations); - } catch (final CoreException e) { - LogUtils.error(logger, e); - } - } - if (!launchConfigurations.isEmpty()) { - final Job testConfigurationJob = new Job("Launching test configurations") { - - @Override - protected IStatus run(final IProgressMonitor monitor) { - final MultiStatus result = new MultiStatus(WorkspaceHelper.getPluginId(getClass()), IStatus.OK, - "Test configurations executed succesfully", null); - final ILaunchManager mgr = DebugPlugin.getDefault().getLaunchManager(); - final SubMonitor subMonitor = SubMonitor.convert(monitor, launchConfigurations.size()); - for (final IFile file : launchConfigurations) { - final ILaunchConfiguration config = mgr.getLaunchConfiguration(file); - final LaunchInvocationTask launchInvocationTask = new LaunchInvocationTask(config); - result.add(launchInvocationTask.run(subMonitor.split(1))); - ProgressMonitorUtil.checkCancellation(subMonitor); - } - return result; - } - }; - testConfigurationJob.setRule(ResourcesPlugin.getWorkspace().getRoot()); - jobs.add(testConfigurationJob); - } - } - - private List getAllOpenProjectsInWorkspace() { - return WorkspaceHelper.getAllProjectsInWorkspace().stream().filter(p -> p.isAccessible()) - .collect(Collectors.toList()); - } - - private List getProjectsWithMweWorkflows() { - return getAllOpenProjectsInWorkspace().stream().filter(p -> containsMwe2Files(p)).collect(Collectors.toList()); - } - - private boolean containsMwe2Files(final IProject project) { - final List mwe2Resources = new ArrayList<>(); - try { - project.accept(new IResourceVisitor() { - - @Override - public boolean visit(IResource resource) throws CoreException { - // Quit after first identified resource - if (!mwe2Resources.isEmpty()) - return false; - - if (resource.getName().endsWith("." + WorkspaceHelper.MWE2_FILE_EXTENSION)) - mwe2Resources.add(resource); - - return true; - } - }); - return !mwe2Resources.isEmpty(); - } catch (final CoreException e) { - return false; - } - } - - private final void prepareIncrementalProjectBuilderJob(final List jobs, final Collection projects) { - projects.toArray(new IProject[projects.size()]); - } - - private final void prepareIncrementalProjectBuilderJob(final List jobs, final IProject[] projects) { - final IBuildConfiguration[] buildConfigurations = BuildUtilities - .getDefaultBuildConfigurations(Arrays.asList(projects)); - if (buildConfigurations.length > 0) { - final ProjectBuilderTask builder = new ProjectBuilderTask(buildConfigurations); - jobs.add(new WorkspaceTaskJob(builder)); - } - } -} \ No newline at end of file diff --git a/org.moflon.core.ui.autosetup/src/org/moflon/core/ui/autosetup/LaunchConfigurationRunnerJob.java b/org.moflon.core.ui.autosetup/src/org/moflon/core/ui/autosetup/LaunchConfigurationRunnerJob.java deleted file mode 100644 index 9c5c0aac..00000000 --- a/org.moflon.core.ui.autosetup/src/org/moflon/core/ui/autosetup/LaunchConfigurationRunnerJob.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.moflon.core.ui.autosetup; - -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.core.runtime.SubMonitor; -import org.eclipse.core.runtime.jobs.Job; -import org.eclipse.debug.core.ILaunchConfiguration; -import org.moflon.core.utilities.ProgressMonitorUtil; - -/** - * This {@link Job} invokes the preconfigured set of - * {@link ILaunchConfiguration}s upon {@link #run(IProgressMonitor)} - * - * @author Roland Kluge - Initial implementation - */ -public final class LaunchConfigurationRunnerJob extends Job { - private final ILaunchConfiguration[] configurations; - - public LaunchConfigurationRunnerJob(String name, ILaunchConfiguration[] configurations) { - super(name); - this.configurations = configurations; - } - - @Override - public IStatus run(final IProgressMonitor monitor) { - final SubMonitor mweWorkflowExecutionMonitor = SubMonitor.convert(monitor, "Executing MWE2 workflows", - configurations.length); - try { - for (int i = 0; i < configurations.length; i++) { - final ILaunchConfiguration config = configurations[i]; - final LaunchInvocationTask launchInvocationTask = new LaunchInvocationTask(config); - launchInvocationTask.run(mweWorkflowExecutionMonitor.split(1)); - ProgressMonitorUtil.checkCancellation(mweWorkflowExecutionMonitor); - } - } finally { - SubMonitor.done(monitor); - } - return Status.OK_STATUS; - } -} \ No newline at end of file diff --git a/org.moflon.core.ui.autosetup/src/org/moflon/core/ui/autosetup/LaunchInvocationTask.java b/org.moflon.core.ui.autosetup/src/org/moflon/core/ui/autosetup/LaunchInvocationTask.java deleted file mode 100644 index 72e05c99..00000000 --- a/org.moflon.core.ui.autosetup/src/org/moflon/core/ui/autosetup/LaunchInvocationTask.java +++ /dev/null @@ -1,63 +0,0 @@ -package org.moflon.core.ui.autosetup; - -import org.apache.log4j.Logger; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.OperationCanceledException; -import org.eclipse.core.runtime.Status; -import org.eclipse.debug.core.DebugException; -import org.eclipse.debug.core.ILaunch; -import org.eclipse.debug.core.ILaunchConfiguration; -import org.eclipse.debug.core.ILaunchManager; -import org.gervarro.eclipse.task.ITask; -import org.moflon.core.utilities.LogUtils; -import org.moflon.core.utilities.WorkspaceHelper; - -public class LaunchInvocationTask implements ITask { - private static final Logger logger = Logger.getLogger(LaunchInvocationTask.class); - private final ILaunchConfiguration launchConfiguration; - - public LaunchInvocationTask(final ILaunchConfiguration launchConfiguration) { - this.launchConfiguration = launchConfiguration; - } - - @Override - public IStatus run(final IProgressMonitor monitor) { - try { - final ILaunch launch = launchConfiguration.launch(ILaunchManager.RUN_MODE, monitor, true); - while (!launch.isTerminated()) { - try { - Thread.sleep(10000); - if (monitor.isCanceled()) { - terminateProcess(launch); - } - } catch (final InterruptedException e) { - terminateProcess(launch); - } - } - return Status.OK_STATUS; - } catch (final CoreException e) { - return new Status(IStatus.ERROR, WorkspaceHelper.getPluginId(getClass()), IStatus.ERROR, - "Unable to launch " + launchConfiguration.getName(), e); - } - } - - private final void terminateProcess(final ILaunch launch) { - if (launch.canTerminate()) { - try { - launch.terminate(); - } catch (final DebugException e) { - LogUtils.warn(logger, "Unable to terminate %s", launchConfiguration.getName()); - } - } else { - LogUtils.warn(logger, "Unable to terminate %s", launchConfiguration.getName()); - } - throw new OperationCanceledException(); - } - - @Override - public final String getTaskName() { - return "Launching configuration " + launchConfiguration.getName(); - } -} diff --git a/org.moflon.core.ui.autosetup/src/org/moflon/core/ui/autosetup/OpenProjectsJob.java b/org.moflon.core.ui.autosetup/src/org/moflon/core/ui/autosetup/OpenProjectsJob.java deleted file mode 100644 index e904d53b..00000000 --- a/org.moflon.core.ui.autosetup/src/org/moflon/core/ui/autosetup/OpenProjectsJob.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.moflon.core.ui.autosetup; - -import java.util.List; - -import org.eclipse.core.resources.IProject; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.core.runtime.SubMonitor; -import org.eclipse.core.runtime.jobs.Job; -import org.moflon.core.utilities.ProgressMonitorUtil; -import org.moflon.core.utilities.WorkspaceHelper; - -/** - * This {@link Job} opens the list of preconfigured projects (see - * {@link CloseProjectsJob#CloseProjectsJob(String, List)}) upon - * {@link #run(IProgressMonitor)} - * - * @author Roland Kluge - Initial implementation - */ -public final class OpenProjectsJob extends Job { - private final List projects; - - public OpenProjectsJob(final String name, final List projects) { - super(name); - this.projects = projects; - } - - @Override - protected IStatus run(IProgressMonitor monitor) { - final SubMonitor openingMonitor = SubMonitor.convert(monitor, "Opening projects", projects.size()); - try { - for (final IProject project : projects) { - project.open(openingMonitor.split(1)); - ProgressMonitorUtil.checkCancellation(openingMonitor); - } - } catch (final CoreException e) { - return new Status(IStatus.ERROR, WorkspaceHelper.getPluginId(getClass()), e.getMessage(), e); - } finally { - SubMonitor.done(monitor); - } - return Status.OK_STATUS; - } -} \ No newline at end of file diff --git a/org.moflon.core.ui.autosetup/src/org/moflon/core/ui/autosetup/PsfFileUtils.java b/org.moflon.core.ui.autosetup/src/org/moflon/core/ui/autosetup/PsfFileUtils.java deleted file mode 100644 index 2097fe11..00000000 --- a/org.moflon.core.ui.autosetup/src/org/moflon/core/ui/autosetup/PsfFileUtils.java +++ /dev/null @@ -1,118 +0,0 @@ -package org.moflon.core.ui.autosetup; - -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.URL; -import java.net.URLConnection; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.Optional; - -import org.apache.log4j.Logger; -import org.eclipse.core.resources.ResourcesPlugin; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.NullProgressMonitor; -import org.moflon.core.utilities.ExceptionUtil; -import org.moflon.core.utilities.UtilityClassNotInstantiableException; -import org.moflon.core.utilities.XMLUtils; -import org.w3c.dom.Document; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -/** - * Utility class for working with PSF files. - */ -public final class PsfFileUtils { - - private static Logger logger = Logger.getLogger(PsfFileUtils.class); - - private PsfFileUtils() { - throw new UtilityClassNotInstantiableException(); - } - - public static String joinPsfFile(Collection files) throws IOException, CoreException { - if (files == null || files.isEmpty()) - throw new IllegalArgumentException("Illegal input (empty or null): " + files); - - final Iterator iter = files.iterator(); - final File file1 = iter.next(); - if (files.size() == 1) { - return Files.readString(file1.toPath()); - } - - final Document document1 = XMLUtils.parseXmlDocument(file1); - final Node root1 = document1.getChildNodes().item(0); - while (iter.hasNext()) { - final File file2 = iter.next(); - final Document document2 = XMLUtils.parseXmlDocument(file2); - final Node root2 = document2.getChildNodes().item(0); - final NodeList childNodes2 = root2.getChildNodes(); - for (int i = 0; i < childNodes2.getLength(); ++i) { - final Node childNode2 = childNodes2.item(i); - final Node clonedChildNode2 = childNode2.cloneNode(true); - document1.adoptNode(clonedChildNode2); // Update/set metadata appropriately for new document - root1.appendChild(clonedChildNode2); // Insert at appropriate place in new document - } - } - - final String joinedPsfFiles = XMLUtils.formatXmlString(document1, new NullProgressMonitor()); - return joinedPsfFiles; - - } - - public static List extractPsfFileContents(final List absolutePathsToPSF) throws IOException { - final List psfContents = new ArrayList<>(); - for (final String absolutePathToPSF : absolutePathsToPSF) { - psfContents.add(Files.readString(Path.of(absolutePathToPSF))); - } - return psfContents; - } - - public static Optional extractPsfFileContent(final URL url) { - try { - URLConnection connection = url.openConnection(); - connection.setReadTimeout(60 * 1000); - String enc = connection.getContentEncoding(); - if (enc == null) - enc = ResourcesPlugin.getEncoding(); - return Optional.of(read(connection.getInputStream(), enc)); - } catch (Exception e) { - logger.error(ExceptionUtil.displayExceptionAsString(e)); - // Fail silently but return empty optional - } - - return Optional.empty(); - } - - public static String read(InputStream is, String encoding) throws IOException { - if (is == null) - throw new IOException("Stream is null"); - - BufferedReader reader = null; - try { - StringBuffer buffer = new StringBuffer(); - char[] part = new char[2048]; - int read = 0; - reader = new BufferedReader(new InputStreamReader(is, encoding)); - while ((read = reader.read(part)) != -1) - buffer.append(part, 0, read); - - return buffer.toString(); - } finally { - if (reader != null) { - try { - reader.close(); - } catch (IOException ex) { - // silently ignored - } - } - } - } -} diff --git a/org.moflon.core.ui.autosetup/src/org/moflon/core/ui/autosetup/WorkspaceInstaller.java b/org.moflon.core.ui.autosetup/src/org/moflon/core/ui/autosetup/WorkspaceInstaller.java deleted file mode 100644 index b008d581..00000000 --- a/org.moflon.core.ui.autosetup/src/org/moflon/core/ui/autosetup/WorkspaceInstaller.java +++ /dev/null @@ -1,210 +0,0 @@ -package org.moflon.core.ui.autosetup; - -import java.io.File; -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.net.URL; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.regex.Pattern; -import java.util.stream.Collectors; - -import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.ResourcesPlugin; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.NullProgressMonitor; -import org.eclipse.core.runtime.OperationCanceledException; -import org.eclipse.core.runtime.Status; -import org.eclipse.core.runtime.jobs.IJobChangeEvent; -import org.eclipse.core.runtime.jobs.ISchedulingRule; -import org.eclipse.core.runtime.jobs.Job; -import org.eclipse.jdt.internal.core.JavaModelManager; -import org.eclipse.team.internal.ui.wizards.ImportProjectSetOperation; -import org.eclipse.team.ui.TeamOperation; -import org.eclipse.ui.IWorkingSet; -import org.gervarro.eclipse.workspace.util.WorkspaceTask; -import org.gervarro.eclipse.workspace.util.WorkspaceTaskJob; -import org.moflon.core.build.TaskUtilities; -import org.moflon.core.utilities.ExceptionUtil; -import org.moflon.core.utilities.LogUtils; - -@SuppressWarnings("restriction") -public class WorkspaceInstaller { - protected static final Logger logger = Logger.getLogger(WorkspaceInstaller.class); - - private static final String MASTER_BRANCH = "master"; - - public void installPsfFiles(final List psfFiles) { - final String label = joinBasenames(psfFiles); - installPsfFiles(psfFiles, label); - } - - public void installPsfFiles(final List psfFiles, final String label) { - installPsfFiles(psfFiles, label, MASTER_BRANCH); - } - - public void installPsfFiles(final List psfFiles, final String label, final String customBranch) { - try { - prepareWorkspace(); - - // We extract the contents beforehand because the following action may delete - // them if we load PSF files - // directly from the workspace - final String psfContent; - if (customBranch == null || MASTER_BRANCH.equals(customBranch)) { - psfContent = PsfFileUtils.joinPsfFile(psfFiles); - } else { - psfContent = PsfFileUtils.joinPsfFile(psfFiles).replaceAll(Pattern.quote("," + MASTER_BRANCH + ","), - "," + customBranch + ","); - } - - final int numberOfProjects = StringUtils.countMatches(psfContent, " 1 ? null : psfFiles.get(0).getAbsolutePath(), // - label).run(); - } catch (final InterruptedException e) { - // Operation cancelled by the user on the GUI - throw new OperationCanceledException(); - } catch (final InvocationTargetException | IOException e) { - LogUtils.error(logger, e); - return; - } catch (final CoreException e) { - final String message = "Sorry, I was unable to check out the projects in the PSF file.\n"// - + " If you did not explicitly cancel then please check the following (most probable first):\n"// - + " (1) Ensure that the Git repositories appearing in the error message below are clean or do not exist (Window/Perspective/Open Perspective/Other.../Git)\n" // - + " (2) If possible, start with an empty, fresh workspace. Although the PSF import offers to delete the projects this may fail, especially on Windows.\n"// - + " (3) Are you sure you have access to all the projects (if they do not support anonymous access)?\n"// - + " (4) The PSF file might be outdated - please check for an update of the test plugin\n"// - + " (5) If it's quite late in the night, our server might be down performing a back-up - try again in a few hours.\n"// - + " (6) If none of these helped, write us a mail to contact@emoflon.org :)\n" // - + "\n" // - + "Exception of type " + e.getClass().getName() + ", Message: " - + ExceptionUtil.displayExceptionAsString(e); - logger.error(message); - return; - } - } - - private TeamOperation createImportProjectSetOperation(String psfContent, String urlString, String label) { - return new ImportProjectSetOperation(null, psfContent, urlString, new IWorkingSet[0]) { - - @Override - public String getJobName() { - return "Checking out projects"; - } - - @Override - public ISchedulingRule getSchedulingRule() { - return ResourcesPlugin.getWorkspace().getRoot(); - } - - @Override - public void done(final IJobChangeEvent event) { - if (event.getResult().isOK()) { - final WorkspaceTask buildConfiguratorTask = new WorkspaceTask() { - - @Override - public void run(IProgressMonitor monitor) throws CoreException { - performBuildAndTest(label); - } - - @Override - public String getTaskName() { - return "Configuring build and test process"; - } - - @Override - public ISchedulingRule getRule() { - return ResourcesPlugin.getWorkspace().getRoot(); - } - }; - new WorkspaceTaskJob(buildConfiguratorTask).schedule(); - } - } - - }; - } - - private final void performBuildAndTest(final String label) { - final List jobs = new ArrayList(); - - enqueuePreprocessingJobs(jobs); - - final Job moflonProjectExplorerJob = new ExploreEMoflonProjectsJob("Exploring eMoflon projects", jobs, label, - this); - moflonProjectExplorerJob.setRule(ResourcesPlugin.getWorkspace().getRoot()); - jobs.add(moflonProjectExplorerJob); - jobs.add(new Job("Good bye.") { - @Override - protected IStatus run(IProgressMonitor monitor) { - logger.info("Code generation jobs completed successfully."); - return Status.OK_STATUS; - } - }); - - try { - TaskUtilities.processJobQueueInBackground(jobs); - logger.info("Code generation jobs scheduled."); - } catch (final CoreException e) { - LogUtils.error(logger, e); - } - logger.info( - "End of automatic workspace configuration reached. Please wait for the code generation jobs to finish. Bye bye."); - } - - /** - * Adds jobs to the queue that shall be invoked prior to building the projects - * in the workspace - * - * @param jobs - * the job queue - */ - protected void enqueuePreprocessingJobs(final List jobs) { - // Nothing to do here - } - - /** - * The list of projects to be built - * - * @return all projects in the workspace - */ - protected IProject[] getProjectsToBuild() { - return ResourcesPlugin.getWorkspace().getRoot().getProjects(); - } - - // This is required to avoid NPEs when checking out plugin projects (a problem - // with JDT) - private static void prepareWorkspace() { - try { - JavaModelManager.getExternalManager().createExternalFoldersProject(new NullProgressMonitor()); - } catch (final CoreException e) { - LogUtils.error(logger, e); - } - - } - - private static String joinBasenames(final List files) { - return files.stream().map(f -> f.getName()).collect(Collectors.joining(", ")); - } - - public void installPsfFile(URL url, String label) { - Optional psfContent = PsfFileUtils.extractPsfFileContent(url); - psfContent.ifPresent(psf -> { - try { - createImportProjectSetOperation(psf, url.toString(), label).run(); - } catch (Exception e) { - logger.error(ExceptionUtil.displayExceptionAsString(e)); - } - }); - } -} diff --git a/org.moflon.core.ui.autosetup/src/org/moflon/core/ui/autosetup/handbook/RegisterPsfUrlForHandbookPart1.java b/org.moflon.core.ui.autosetup/src/org/moflon/core/ui/autosetup/handbook/RegisterPsfUrlForHandbookPart1.java deleted file mode 100644 index 2873946d..00000000 --- a/org.moflon.core.ui.autosetup/src/org/moflon/core/ui/autosetup/handbook/RegisterPsfUrlForHandbookPart1.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.moflon.core.ui.autosetup.handbook; - -public class RegisterPsfUrlForHandbookPart1 extends SokobanHandbookPsfUrlRegistration { - - public RegisterPsfUrlForHandbookPart1() { - super(1, "https://raw.githubusercontent.com/eMoflon/emoflon-ibex-examples/master/sokoban/version1/projectSet.psf"); - } - -} diff --git a/org.moflon.core.ui.autosetup/src/org/moflon/core/ui/autosetup/handbook/SokobanHandbookPsfUrlRegistration.java b/org.moflon.core.ui.autosetup/src/org/moflon/core/ui/autosetup/handbook/SokobanHandbookPsfUrlRegistration.java deleted file mode 100644 index 6cdc6e19..00000000 --- a/org.moflon.core.ui.autosetup/src/org/moflon/core/ui/autosetup/handbook/SokobanHandbookPsfUrlRegistration.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.moflon.core.ui.autosetup.handbook; - -import java.net.MalformedURLException; -import java.net.URL; - -import org.moflon.core.ui.autosetup.handler.RegisterPsfUrlExtension; - -public abstract class SokobanHandbookPsfUrlRegistration implements RegisterPsfUrlExtension { - protected static final String PREFIX = "I. Sokoban Example: "; - private String label; - private String url; - - public SokobanHandbookPsfUrlRegistration(int part, String url) { - this(PREFIX + part, url); - } - - public SokobanHandbookPsfUrlRegistration(String label, String url) { - this.url = url; - this.label = label; - } - - @Override - public String getLabel() { - return label; - } - - @Override - public URL getUrl() { - try { - return new URL(url); - } catch (MalformedURLException e) { - throw new IllegalStateException(e); - } - } -} diff --git a/org.moflon.core.ui.autosetup/src/org/moflon/core/ui/autosetup/handler/InstallPsfFileHandler.java b/org.moflon.core.ui.autosetup/src/org/moflon/core/ui/autosetup/handler/InstallPsfFileHandler.java deleted file mode 100644 index a797513b..00000000 --- a/org.moflon.core.ui.autosetup/src/org/moflon/core/ui/autosetup/handler/InstallPsfFileHandler.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.moflon.core.ui.autosetup.handler; - -import java.io.File; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; - -import org.eclipse.core.commands.ExecutionEvent; -import org.eclipse.core.commands.ExecutionException; -import org.eclipse.swt.SWT; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.FileDialog; -import org.moflon.core.ui.AbstractCommandHandler; -import org.moflon.core.ui.autosetup.WorkspaceInstaller; - -public class InstallPsfFileHandler extends AbstractCommandHandler { - - @Override - public Object execute(final ExecutionEvent event) throws ExecutionException { - final FileDialog dialog = new FileDialog(Display.getDefault().getActiveShell(), SWT.MULTI); - dialog.setFilterExtensions(new String[] { "*.psf", "*.PSF" }); - dialog.setText("Choose your PSF file(s)"); - - String open = dialog.open(); - if (open != null) { - final String parentPath = dialog.getFilterPath(); - final List selectedFileNames = Arrays.asList(dialog.getFileNames()); - final List psfFiles = selectedFileNames.stream().map(s -> new File(new File(parentPath), s)) - .collect(Collectors.toList()); - - new WorkspaceInstaller().installPsfFiles(psfFiles); - } - return null; - } - -} diff --git a/org.moflon.core.ui.autosetup/src/org/moflon/core/ui/autosetup/handler/PopulatePsfUrlMenu.java b/org.moflon.core.ui.autosetup/src/org/moflon/core/ui/autosetup/handler/PopulatePsfUrlMenu.java deleted file mode 100644 index ae28a951..00000000 --- a/org.moflon.core.ui.autosetup/src/org/moflon/core/ui/autosetup/handler/PopulatePsfUrlMenu.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.moflon.core.ui.autosetup.handler; - -import java.util.Collection; - -import org.apache.log4j.Logger; -import org.eclipse.jface.action.ContributionItem; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.widgets.Menu; -import org.eclipse.swt.widgets.MenuItem; -import org.eclipse.ui.menus.ExtensionContributionFactory; -import org.eclipse.ui.menus.IContributionRoot; -import org.eclipse.ui.services.IServiceLocator; -import org.moflon.core.ui.autosetup.WorkspaceInstaller; -import org.moflon.core.utilities.ExtensionsUtil; - -public class PopulatePsfUrlMenu extends ExtensionContributionFactory { - private Logger logger = Logger.getLogger(PopulatePsfUrlMenu.class); - - private static final String URI_PREF_EXTENSION_ID = "org.moflon.core.ui.autosetup.RegisterPsfUrlExtension"; - - private static Collection registerPsfUrlExtensions = ExtensionsUtil - .collectExtensions(URI_PREF_EXTENSION_ID, "class", RegisterPsfUrlExtension.class); - - @Override - public void createContributionItems(IServiceLocator serviceLocator, IContributionRoot additions) { - registerPsfUrlExtensions.stream()// - .sorted((r1, r2) -> r1.getLabel().compareTo(r2.getLabel()))// - .forEach(ext -> { - additions.addContributionItem(new ContributionItem() { - @Override - public void fill(Menu menu, int index) { - logger.debug("Inserting " + ext.getLabel() + " at " + index); - MenuItem mi = new MenuItem(menu, SWT.DEFAULT, menu.getItemCount()); - mi.setText(ext.getLabel()); - mi.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - logger.info(ext.getLabel() + " selected!"); - logger.info(ext.getUrl() + " is going to be imported."); - new WorkspaceInstaller().installPsfFile(ext.getUrl(), ext.getLabel()); - } - }); - } - }, null); - }); - } -} diff --git a/org.moflon.core.ui.autosetup/src/org/moflon/core/ui/autosetup/handler/RegisterPsfUrlExtension.java b/org.moflon.core.ui.autosetup/src/org/moflon/core/ui/autosetup/handler/RegisterPsfUrlExtension.java deleted file mode 100644 index d29382b0..00000000 --- a/org.moflon.core.ui.autosetup/src/org/moflon/core/ui/autosetup/handler/RegisterPsfUrlExtension.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.moflon.core.ui.autosetup.handler; - -import java.net.URL; - -public interface RegisterPsfUrlExtension { - /** - * Get the label to be displayed in the menu. - * - * @return A string represented the label to be displayed for the PSF in the - * menu. - */ - String getLabel(); - - /** - * Get the URL to be displayed in the menu. - * - * @return The URL to the PSF to be imported when the entry is selected. - */ - URL getUrl(); -} diff --git a/org.moflon.core.ui.packageregistration/.classpath b/org.moflon.core.ui.packageregistration/.classpath deleted file mode 100644 index 375961e4..00000000 --- a/org.moflon.core.ui.packageregistration/.classpath +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/org.moflon.core.ui.packageregistration/.gitignore b/org.moflon.core.ui.packageregistration/.gitignore deleted file mode 100644 index 3d1f6cf4..00000000 --- a/org.moflon.core.ui.packageregistration/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/.settings/ -/bin -/target \ No newline at end of file diff --git a/org.moflon.core.ui.packageregistration/.project b/org.moflon.core.ui.packageregistration/.project deleted file mode 100644 index f2fa45b9..00000000 --- a/org.moflon.core.ui.packageregistration/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - org.moflon.core.ui.packageregistration - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.pde.PluginNature - org.eclipse.jdt.core.javanature - - diff --git a/org.moflon.core.ui.packageregistration/META-INF/MANIFEST.MF b/org.moflon.core.ui.packageregistration/META-INF/MANIFEST.MF deleted file mode 100644 index 652b4604..00000000 --- a/org.moflon.core.ui.packageregistration/META-INF/MANIFEST.MF +++ /dev/null @@ -1,17 +0,0 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: eMoflon::Core components for registering Ecore files -Bundle-SymbolicName: org.moflon.core.ui.packageregistration;singleton:=true -Bundle-Version: 1.0.1.qualifier -Bundle-RequiredExecutionEnvironment: JavaSE-21 -Require-Bundle: org.eclipse.emf.ecore;bundle-version="2.11.0", - org.eclipse.core.resources, - org.eclipse.equinox.registry, - org.apache.log4j, - org.eclipse.jface, - org.eclipse.ui.workbench, - org.eclipse.emf.ecore.xmi, - org.moflon.core.ui -Bundle-Vendor: eMoflon developers -Automatic-Module-Name: org.moflon.core.ui.packageregistration -Export-Package: org.moflon.core.ui.packageregistration diff --git a/org.moflon.core.ui.packageregistration/build.properties b/org.moflon.core.ui.packageregistration/build.properties deleted file mode 100644 index 79785aca..00000000 --- a/org.moflon.core.ui.packageregistration/build.properties +++ /dev/null @@ -1,6 +0,0 @@ -source.. = src/ -output.. = bin/ -bin.includes = META-INF/,\ - .,\ - icons/,\ - plugin.xml diff --git a/org.moflon.core.ui.packageregistration/icons/register.png b/org.moflon.core.ui.packageregistration/icons/register.png deleted file mode 100644 index bd198799..00000000 Binary files a/org.moflon.core.ui.packageregistration/icons/register.png and /dev/null differ diff --git a/org.moflon.core.ui.packageregistration/plugin.xml b/org.moflon.core.ui.packageregistration/plugin.xml deleted file mode 100644 index 40ebaf89..00000000 --- a/org.moflon.core.ui.packageregistration/plugin.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/org.moflon.core.ui.packageregistration/src/org/moflon/core/ui/packageregistration/EmfRegistryManager.java b/org.moflon.core.ui.packageregistration/src/org/moflon/core/ui/packageregistration/EmfRegistryManager.java deleted file mode 100644 index d281179e..00000000 --- a/org.moflon.core.ui.packageregistration/src/org/moflon/core/ui/packageregistration/EmfRegistryManager.java +++ /dev/null @@ -1,166 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2008 The University of York. - * 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: - * Dimitrios Kolovos - initial API and implementation - ******************************************************************************/ -package org.moflon.core.ui.packageregistration; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.eclipse.emf.common.util.URI; -import org.eclipse.emf.ecore.EDataType; -import org.eclipse.emf.ecore.EEnum; -import org.eclipse.emf.ecore.EObject; -import org.eclipse.emf.ecore.EPackage; -import org.eclipse.emf.ecore.EcorePackage; -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.emf.ecore.xmi.impl.XMIResourceFactoryImpl; - -/** - * This class allows to register and manage EMF metamodels - * - * @author Roland Kluge - Initial implementation - * - */ -public class EmfRegistryManager { - private static EmfRegistryManager instance = null; - - private HashMap> managedMetamodels = new HashMap<>(); - - public static EmfRegistryManager getInstance() { - if (instance == null) { - instance = new EmfRegistryManager(); - } - return instance; - } - - public void registerMetamodel(String fileName) throws Exception { - List ePackages = register(URI.createPlatformResourceURI(fileName, true), EPackage.Registry.INSTANCE); - managedMetamodels.put(fileName, ePackages); - } - - // The following methods are taken from org.eclipse.epsilon.emc.emf.EmfUtil - - public static List register(URI uri, EPackage.Registry registry) throws Exception { - return register(uri, registry, true); - } - - /** - * Register all the packages in the metamodel specified by the uri in the - * registry. - * - * @param uri - * The URI of the metamodel - * @param registry - * The registry in which the metamodel's packages are registered - * @param useUriForResource - * If True, the URI of the resource created for the metamodel would - * be overwritten with the URI of the last EPackage in the metamodel. - * @return A list of the EPackages registered. - * @throws Exception - * If there is an error accessing the resources. - */ - public static List register(URI uri, EPackage.Registry registry, boolean useUriForResource) - throws Exception { - - List ePackages = new ArrayList(); - - initialiseResourceFactoryRegistry(); - - ResourceSet resourceSet = new ResourceSetImpl(); - resourceSet.getPackageRegistry().put(EcorePackage.eINSTANCE.getNsURI(), EcorePackage.eINSTANCE); - - Resource metamodel = resourceSet.createResource(uri); - metamodel.load(Collections.EMPTY_MAP); - - setDataTypesInstanceClasses(metamodel); - - Iterator it = metamodel.getAllContents(); - while (it.hasNext()) { - Object next = it.next(); - if (next instanceof EPackage) { - EPackage p = (EPackage) next; - - adjustNsAndPrefix(metamodel, p, useUriForResource); - registry.put(p.getNsURI(), p); - ePackages.add(p); - } - } - - return ePackages; - - } - - private static void initialiseResourceFactoryRegistry() { - final Map etfm = Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap(); - - if (!etfm.containsKey("*")) { - etfm.put("*", new XMIResourceFactoryImpl()); - } - - } - - private static void adjustNsAndPrefix(Resource metamodel, EPackage p, boolean useUriForResource) { - if (p.getNsURI() == null || p.getNsURI().trim().length() == 0) { - if (p.getESuperPackage() == null) { - p.setNsURI(p.getName()); - } else { - p.setNsURI(p.getESuperPackage().getNsURI() + "/" + p.getName()); - } - } - - if (p.getNsPrefix() == null || p.getNsPrefix().trim().length() == 0) { - if (p.getESuperPackage() != null) { - if (p.getESuperPackage().getNsPrefix() != null) { - p.setNsPrefix(p.getESuperPackage().getNsPrefix() + "." + p.getName()); - } else { - p.setNsPrefix(p.getName()); - } - } - } - - if (p.getNsPrefix() == null) - p.setNsPrefix(p.getName()); - if (useUriForResource) - metamodel.setURI(URI.createURI(p.getNsURI())); - } - - protected static void setDataTypesInstanceClasses(Resource metamodel) { - Iterator it = metamodel.getAllContents(); - while (it.hasNext()) { - EObject eObject = (EObject) it.next(); - if (eObject instanceof EEnum) { - // ((EEnum) eObject).setInstanceClassName("java.lang.Integer"); - } else if (eObject instanceof EDataType) { - EDataType eDataType = (EDataType) eObject; - String instanceClass = ""; - if (eDataType.getName().equals("String")) { - instanceClass = "java.lang.String"; - } else if (eDataType.getName().equals("Boolean")) { - instanceClass = "java.lang.Boolean"; - } else if (eDataType.getName().equals("Integer")) { - instanceClass = "java.lang.Integer"; - } else if (eDataType.getName().equals("Float")) { - instanceClass = "java.lang.Float"; - } else if (eDataType.getName().equals("Double")) { - instanceClass = "java.lang.Double"; - } - if (instanceClass.trim().length() > 0) { - eDataType.setInstanceClassName(instanceClass); - } - } - } - } -} diff --git a/org.moflon.core.ui.packageregistration/src/org/moflon/core/ui/packageregistration/RegisterMetamodelHandler.java b/org.moflon.core.ui.packageregistration/src/org/moflon/core/ui/packageregistration/RegisterMetamodelHandler.java deleted file mode 100644 index 7fa7eb1c..00000000 --- a/org.moflon.core.ui.packageregistration/src/org/moflon/core/ui/packageregistration/RegisterMetamodelHandler.java +++ /dev/null @@ -1,66 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2008 The University of York. - * 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: - * Dimitrios Kolovos - initial API and implementation - ******************************************************************************/ -package org.moflon.core.ui.packageregistration; - -import java.util.Iterator; - -import org.eclipse.core.commands.ExecutionEvent; -import org.eclipse.core.commands.ExecutionException; -import org.eclipse.core.resources.IFile; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.ui.handlers.HandlerUtil; -import org.moflon.core.ui.AbstractCommandHandler; - -/** - * This class provides the front-end capabilities for registering an EMF model. - * - * @author Dimitrios Kolovos - initial API and implementation - * @author Roland Kluge - Adjustment to eMoflon::Core - */ -public class RegisterMetamodelHandler extends AbstractCommandHandler { - - /** - * Invokes {@link #registerMetamodelInFile(IFile)} for each {@link IFile} in the selection - * @param event the event to handle - * @param {@link AbstractCommandHandler#DEFAULT_HANDLER_RESULT} - */ - @Override - public Object execute(final ExecutionEvent event) throws ExecutionException { - final ISelection selection = HandlerUtil.getCurrentSelectionChecked(event); - - if (selection instanceof IStructuredSelection) { - final IStructuredSelection structuredSelection = (IStructuredSelection) selection; - final Iterator it = structuredSelection.iterator(); - while (it.hasNext()) { - final IFile file = (IFile) it.next(); - registerMetamodelInFile(file); - } - } - - return AbstractCommandHandler.DEFAULT_HANDLER_RESULT; - } - - /** - * Uses {@link EmfRegistryManager} to register the given {@link IFile} - * @param file the file to register - */ - private void registerMetamodelInFile(final IFile file) { - final String fileName = file.getFullPath().toOSString(); - try { - EmfRegistryManager.getInstance().registerMetamodel(fileName); - logger.info("Metamodel " + fileName + " registered successfully"); - } catch (final Exception ex) { - logger.error("Metamodel " + fileName + " could not be registered", ex); - } - } - -} diff --git a/org.moflon.core.ui/.settings/org.eclipse.jdt.core.prefs b/org.moflon.core.ui/.settings/org.eclipse.jdt.core.prefs index d4540a53..3a79233b 100644 --- a/org.moflon.core.ui/.settings/org.eclipse.jdt.core.prefs +++ b/org.moflon.core.ui/.settings/org.eclipse.jdt.core.prefs @@ -1,10 +1,10 @@ eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 -org.eclipse.jdt.core.compiler.compliance=17 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=21 +org.eclipse.jdt.core.compiler.compliance=21 org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning org.eclipse.jdt.core.compiler.release=enabled -org.eclipse.jdt.core.compiler.source=17 +org.eclipse.jdt.core.compiler.source=21 diff --git a/org.moflon.core.ui/src/org/moflon/core/ui/MoflonConsole.java b/org.moflon.core.ui/src/org/moflon/core/ui/MoflonConsole.java index 6217c7f6..7347b3d9 100644 --- a/org.moflon.core.ui/src/org/moflon/core/ui/MoflonConsole.java +++ b/org.moflon.core.ui/src/org/moflon/core/ui/MoflonConsole.java @@ -5,12 +5,14 @@ import java.io.IOException; import java.net.URL; import java.util.Properties; +import java.util.function.Supplier; import org.apache.log4j.Level; import org.apache.log4j.PatternLayout; import org.apache.log4j.WriterAppender; import org.apache.log4j.spi.LoggingEvent; import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.console.ConsolePlugin; import org.eclipse.ui.console.IConsole; @@ -24,11 +26,17 @@ public class MoflonConsole extends WriterAppender { private static final String PATTERN_KEY = "log4j.appender." + MOFLON_CONSOLE + ".layout.ConversionPattern"; private static final String DEFAULT_PATTERN = "%5p [%c{2}::%L]: %m"; + private static final Color WHITE = new Color(Display.getDefault(), 255, 255, 255); + private static final Color BLACK = new Color(Display.getDefault(), 0, 0, 0); + private static final Color RED = new Color(Display.getDefault(), 255, 0, 0); + private static final Color BRIGHT_RED = new Color(Display.getDefault(), 252, 63, 63); private static final Color BLUE = new Color(Display.getDefault(), 0, 0, 128); + private static final Color LIGHT_BLUE = new Color(Display.getDefault(), 85, 85, 230); private static final Color YELLOW = new Color(Display.getDefault(), 239, 155, 15); + private static final Color BRIGHT_YELLOW = new Color(Display.getDefault(), 245, 191, 100); public MoflonConsole(final URL configFile) { Properties properties = new Properties(); @@ -60,45 +68,41 @@ private static MessageConsole findConsole(final String name) { /** * Prints a message on the MoflonConsole. * - * @param message - * The message to print. + * @param message The message to print. */ private static void printMessage(final String message) { - printMessage(message, null); + printMessage(message, () -> (calcBGLuminance() > 0.5) ? BLACK : WHITE); } /** * Prints a message in red on the MoflonConsole. * - * @param message - * The message to print. + * @param message The message to print. */ private static void printErrorMessage(final String message) { - printMessage(message, RED); + printMessage(message, () -> (calcBGLuminance() < 0.5) ? BRIGHT_RED : RED); } /** * Prints a message in blue on the MoflonConsole. * - * @param message - * The message to print. + * @param message The message to print. */ private static void printInfoMessage(final String message) { - printMessage(message, BLUE); + printMessage(message, () -> (calcBGLuminance() < 0.5) ? LIGHT_BLUE : BLUE); } /** * Prints a message on the MoflonConsole. * - * @param message - * The message to print. + * @param message The message to print. */ - private static synchronized void printMessage(final String message, final Color color) { + private static synchronized void printMessage(final String message, final Supplier color) { Display device = Display.getDefault(); device.asyncExec(new Runnable() { @Override public void run() { - _printMessage(message, color); + _printMessage(message, color.get()); } }); } @@ -147,6 +151,18 @@ else if (event.getLevel().equals(Level.INFO)) } private void printWarningMessage(final String message) { - printMessage(message, YELLOW); + printMessage(message, () -> (calcBGLuminance() < 0.5) ? BRIGHT_YELLOW : YELLOW); + } + + public static double calcBGLuminance() { + if (ConsolePlugin.getStandardDisplay().getActiveShell() == null) + return 0.0; + + Color col = ConsolePlugin.getStandardDisplay().getActiveShell().getBackground(); + if (col == null) + return 0.0; + + RGB rgb = col.getRGB(); + return (0.299 * rgb.red + 0.587 * rgb.green + 0.114 * rgb.blue) / 255; } } diff --git a/org.moflon.git.ui/.classpath b/org.moflon.git.ui/.classpath deleted file mode 100644 index 375961e4..00000000 --- a/org.moflon.git.ui/.classpath +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/org.moflon.git.ui/.gitignore b/org.moflon.git.ui/.gitignore deleted file mode 100644 index ae3c1726..00000000 --- a/org.moflon.git.ui/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/bin/ diff --git a/org.moflon.git.ui/.project b/org.moflon.git.ui/.project deleted file mode 100644 index 310025bc..00000000 --- a/org.moflon.git.ui/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - org.moflon.git.ui - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.pde.PluginNature - org.eclipse.jdt.core.javanature - - diff --git a/org.moflon.git.ui/.settings/org.eclipse.jdt.core.prefs b/org.moflon.git.ui/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index d4540a53..00000000 --- a/org.moflon.git.ui/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,10 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 -org.eclipse.jdt.core.compiler.compliance=17 -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning -org.eclipse.jdt.core.compiler.release=enabled -org.eclipse.jdt.core.compiler.source=17 diff --git a/org.moflon.git.ui/META-INF/MANIFEST.MF b/org.moflon.git.ui/META-INF/MANIFEST.MF deleted file mode 100644 index 1d5b8d25..00000000 --- a/org.moflon.git.ui/META-INF/MANIFEST.MF +++ /dev/null @@ -1,17 +0,0 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: eMoflon::Core Git tooling -Bundle-SymbolicName: org.moflon.git.ui;singleton:=true -Bundle-Version: 1.0.0.qualifier -Bundle-RequiredExecutionEnvironment: JavaSE-21 -Require-Bundle: org.eclipse.equinox.registry;bundle-version="3.6.100", - org.eclipse.ui.workbench;bundle-version="3.0.0", - org.eclipse.jface;bundle-version="3.0.0", - org.eclipse.jgit;bundle-version="4.0.0", - org.emoflon.core.dependencies;bundle-version="1.0.0", - org.moflon.core.ui;bundle-version="1.0.0", - org.moflon.core.utilities;bundle-version="3.0.0" -Bundle-Vendor: eMoflon developers -Automatic-Module-Name: org.moflon.git.ui -Export-Package: org.moflon.git, - org.moflon.git.ui.handler diff --git a/org.moflon.git.ui/build.properties b/org.moflon.git.ui/build.properties deleted file mode 100644 index 99a3f50c..00000000 --- a/org.moflon.git.ui/build.properties +++ /dev/null @@ -1,6 +0,0 @@ -source.. = src/ -output.. = bin/ -bin.includes = META-INF/,\ - .,\ - plugin.xml,\ - src/ diff --git a/org.moflon.git.ui/plugin.xml b/org.moflon.git.ui/plugin.xml deleted file mode 100644 index ba656d78..00000000 --- a/org.moflon.git.ui/plugin.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/org.moflon.git.ui/src/org/moflon/git/GitHelper.java b/org.moflon.git.ui/src/org/moflon/git/GitHelper.java deleted file mode 100644 index ce510430..00000000 --- a/org.moflon.git.ui/src/org/moflon/git/GitHelper.java +++ /dev/null @@ -1,161 +0,0 @@ -package org.moflon.git; - -import java.io.File; -import java.io.IOException; - -import org.apache.log4j.Logger; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.runtime.IPath; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.MultiStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.core.runtime.SubMonitor; -import org.eclipse.jgit.api.CleanCommand; -import org.eclipse.jgit.api.Git; -import org.eclipse.jgit.api.ResetCommand; -import org.eclipse.jgit.api.ResetCommand.ResetType; -import org.eclipse.jgit.lib.Repository; -import org.eclipse.jgit.storage.file.FileRepositoryBuilder; -import org.moflon.core.utilities.LogUtils; -import org.moflon.core.utilities.ProgressMonitorUtil; -import org.moflon.core.utilities.UtilityClassNotInstantiableException; -import org.moflon.core.utilities.WorkspaceHelper;; - -/** - * Utility methods for working with Git - * - * @author Lars Fritsche - Initial implementation - * @author Roland Kluge - * - */ -public final class GitHelper { - private static final Logger logger = Logger.getLogger(GitHelper.class); - - private static final String GIT_FOLDER = "/.git"; - - /** - * Disabled constructor - */ - private GitHelper() { - throw new UtilityClassNotInstantiableException(); - } - - /** - * @param project - * the project to check - * @return true if the project is contained in a Git repository - */ - public static boolean isInGitRepository(final IProject project) { - return findGitRepositoryRoot(project) != null; - } - - /** - * Resets and cleans the given Git repository - * - * The repository should exist - * - * The effect of this method is equal to - * git reset --hard && git clean -fxd - * - * @param rep - * the repository to reset and clean - * @param monitor - * the monitor to be used - * @return the success or failure status - */ - public static IStatus resetAndCleanGitRepository(final Repository rep, final IProgressMonitor monitor) { - final SubMonitor subMon = SubMonitor.convert(monitor, "Resetting Git repository " + rep, 2); - final Git git = new Git(rep); - try { - final ResetCommand resetCmd = git.reset(); - resetCmd.setMode(ResetType.HARD); - - final CleanCommand cleanCmd = git.clean(); - cleanCmd.setCleanDirectories(true); - cleanCmd.setIgnore(false); - - try { - logger.debug("Resetting " + rep); - resetCmd.call(); - } catch (final Exception e) { - return new Status(IStatus.ERROR, WorkspaceHelper.getPluginId(GitHelper.class), - String.format("Failed to reset %s", rep), e); - } - subMon.worked(1); - ProgressMonitorUtil.checkCancellation(subMon); - - try { - logger.debug("Cleaning " + rep); - cleanCmd.call(); - } catch (final Exception e) { - return new Status(IStatus.ERROR, WorkspaceHelper.getPluginId(GitHelper.class), - String.format("Failed to clean %s", rep), e); - } - subMon.worked(1); - ProgressMonitorUtil.checkCancellation(subMon); - - LogUtils.info(logger, "Resetting and cleaning of %s successful", rep); - } finally { - git.close(); - } - - return Status.OK_STATUS; - } - - /** - * Retrieves the Git repository containing the given project. - * - * @param project - * the project - * @param multiStatus - * used to report problems - * @return the repository or null if the project is not inside a - * Git repository - */ - public static Repository findGitRepository(final IProject project, final MultiStatus multiStatus) { - final IPath pathToRepository = findGitRepositoryRoot(project); - - if (pathToRepository == null) { - multiStatus.add(new Status(IStatus.ERROR, WorkspaceHelper.getPluginId(GitHelper.class), - String.format("Not a git repository: %s", project.getLocation().makeAbsolute()))); - return null; - } - - final File gitFolder = new File(pathToRepository + GIT_FOLDER); - - try { - final Repository rep = FileRepositoryBuilder.create(gitFolder); - return rep; - } catch (final IOException e) { - multiStatus.add(new Status(IStatus.ERROR, WorkspaceHelper.getPluginId(GitHelper.class), - String.format("Exception while opening git repository in %s", gitFolder), e)); - return null; - } - } - - /** - * Finds the folder containing the Git metadata folder .git in the parents of - * the given project - * - * @param project - * the project - * @return the folder or null if no such folder exists - */ - private static IPath findGitRepositoryRoot(final IProject project) { - IPath pathToRepository = project.getLocation().makeAbsolute(); - { - File gitFolder = null; - do { - gitFolder = new File(pathToRepository + GIT_FOLDER); - - if (gitFolder.exists()) { - return pathToRepository; - } - - pathToRepository = pathToRepository.removeLastSegments(1); - } while (!pathToRepository.isRoot()); - } - return null; - } -} diff --git a/org.moflon.git.ui/src/org/moflon/git/ui/handler/GitResetProjectHandler.java b/org.moflon.git.ui/src/org/moflon/git/ui/handler/GitResetProjectHandler.java deleted file mode 100644 index 9187d1aa..00000000 --- a/org.moflon.git.ui/src/org/moflon/git/ui/handler/GitResetProjectHandler.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.moflon.git.ui.handler; - -import java.util.Collection; - -import org.eclipse.core.commands.ExecutionEvent; -import org.eclipse.core.commands.ExecutionException; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.ResourcesPlugin; -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.ui.handlers.HandlerUtil; -import org.gervarro.eclipse.workspace.util.IWorkspaceTask; -import org.gervarro.eclipse.workspace.util.WorkspaceTaskJob; -import org.moflon.core.ui.AbstractCommandHandler; - -public class GitResetProjectHandler extends AbstractCommandHandler { - @Override - public Object execute(final ExecutionEvent event) throws ExecutionException { - final ISelection selection = HandlerUtil.getCurrentSelectionChecked(event); - if (!(selection instanceof IStructuredSelection)) - return AbstractCommandHandler.DEFAULT_HANDLER_RESULT; - - final IStructuredSelection structuredSelection = (IStructuredSelection) selection; - - final Collection projects = AbstractCommandHandler.getProjectsFromSelection(structuredSelection); - - if (projects.size() == 0) { - MessageDialog.openInformation(null, "Selection must contain a project", - "You need at least one selection within your workspace to find the repository."); - return AbstractCommandHandler.DEFAULT_HANDLER_RESULT; - } - - if (!showWarningDialog()) - return null; - - final IWorkspaceTask task = new GitResetTask(projects); - final WorkspaceTaskJob job = new WorkspaceTaskJob(task); - job.setUser(true); - job.setRule(ResourcesPlugin.getWorkspace().getRoot()); - job.schedule(); - - return AbstractCommandHandler.DEFAULT_HANDLER_RESULT; - } - - private static boolean showWarningDialog() { - final boolean userHasConfirmed = MessageDialog.openConfirm(null, "Confirm reset", - "This will undo all changes and reset the project to HEAD. Proceed?"); - return userHasConfirmed; - } -} diff --git a/org.moflon.git.ui/src/org/moflon/git/ui/handler/GitResetTask.java b/org.moflon.git.ui/src/org/moflon/git/ui/handler/GitResetTask.java deleted file mode 100644 index 729e6c1f..00000000 --- a/org.moflon.git.ui/src/org/moflon/git/ui/handler/GitResetTask.java +++ /dev/null @@ -1,93 +0,0 @@ -package org.moflon.git.ui.handler; - -import java.util.Collection; -import java.util.Set; -import java.util.stream.Collectors; - -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.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.MultiStatus; -import org.eclipse.core.runtime.SubMonitor; -import org.eclipse.core.runtime.jobs.ISchedulingRule; -import org.eclipse.jgit.lib.Repository; -import org.gervarro.eclipse.workspace.util.IWorkspaceTask; -import org.moflon.core.utilities.ProgressMonitorUtil; -import org.moflon.core.utilities.WorkspaceHelper; -import org.moflon.git.GitHelper; - -class GitResetTask implements IWorkspaceTask { - private final Collection projects; - - GitResetTask(Collection projects) { - this.projects = projects; - } - - @Override - public String getTaskName() { - return "Reset and clean Git repositories"; - } - - public ISchedulingRule getRule() { - return ResourcesPlugin.getWorkspace().getRoot(); - } - - @Override - public void run(final IProgressMonitor monitor) throws CoreException { - final SubMonitor subMon = SubMonitor.convert(monitor, "Resetting and cleaning Git repositories", - 2 * this.projects.size()); - final MultiStatus status = new MultiStatus(WorkspaceHelper.getPluginId(getClass()), 0, - "Problems during resetting and cleaning", null); - - final Set repositories = collectRepositories(status); - if (status.matches(IStatus.ERROR)) { - throw new CoreException(status); - } - - resetAndCleanRepositories(repositories, status, subMon.split(this.projects.size())); - if (status.matches(IStatus.ERROR)) { - throw new CoreException(status); - } - - for (final IProject project : this.projects) { - project.refreshLocal(IResource.DEPTH_INFINITE, subMon.split(1)); - } - } - - /** - * Resets and cleans all of the listed repositories - * - * @param repositories - * the repositories - * @param status - * used for collecting problems - * @param monitor - * the progress monitor - */ - private void resetAndCleanRepositories(final Set repositories, final MultiStatus status, - final IProgressMonitor monitor) { - final SubMonitor subMon = SubMonitor.convert(monitor, "Resetting and cleaning Git repositories", - repositories.size()); - for (final Repository repository : repositories) { - final IStatus resetStatus = GitHelper.resetAndCleanGitRepository(repository, subMon); - subMon.worked(1); - status.add(resetStatus); - ProgressMonitorUtil.checkCancellation(subMon); - } - } - - /** - * Retrieves the set of repositories that contain the configured projects - * - * @param status - * used for collection problems - * @return the list of repositories - */ - private Set collectRepositories(final MultiStatus status) { - return this.projects.stream().filter(GitHelper::isInGitRepository) - .map(project -> GitHelper.findGitRepository(project, status)).collect(Collectors.toSet()); - } -} \ No newline at end of file