Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEd Merks2023-02-07 10:16:25 +0000
committerEd Merks2023-02-07 10:16:25 +0000
commit7d4f2b1cd6ae959f92a7f0ff9ac7d064bd1eb9f4 (patch)
tree82ef4e3f50cc01c326ff73ce8615c0e5ff8e0108
parentfaa3067e60f4381a3f0cd31e4fd74b92d3afa3d4 (diff)
downloadorg.eclipse.emf-7d4f2b1cd6ae959f92a7f0ff9ac7d064bd1eb9f4.tar.gz
org.eclipse.emf-7d4f2b1cd6ae959f92a7f0ff9ac7d064bd1eb9f4.tar.xz
org.eclipse.emf-7d4f2b1cd6ae959f92a7f0ff9ac7d064bd1eb9f4.zip
[581496] Provide improved support for locating models for reflective
editing
-rw-r--r--plugins/org.eclipse.emf.ecore.editor/src/org/eclipse/emf/ecore/presentation/EcoreEditor.java149
1 files changed, 146 insertions, 3 deletions
diff --git a/plugins/org.eclipse.emf.ecore.editor/src/org/eclipse/emf/ecore/presentation/EcoreEditor.java b/plugins/org.eclipse.emf.ecore.editor/src/org/eclipse/emf/ecore/presentation/EcoreEditor.java
index 9228fd6b9..0d1f919fb 100644
--- a/plugins/org.eclipse.emf.ecore.editor/src/org/eclipse/emf/ecore/presentation/EcoreEditor.java
+++ b/plugins/org.eclipse.emf.ecore.editor/src/org/eclipse/emf/ecore/presentation/EcoreEditor.java
@@ -121,6 +121,8 @@ import org.eclipse.emf.common.ui.viewer.IViewerProvider;
import org.eclipse.emf.common.util.BasicDiagnostic;
import org.eclipse.emf.common.util.Diagnostic;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.common.util.UniqueEList;
@@ -130,10 +132,14 @@ import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.ETypeParameter;
+import org.eclipse.emf.ecore.EcorePackage;
+import org.eclipse.emf.ecore.impl.EPackageRegistryImpl;
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.util.EContentAdapter;
import org.eclipse.emf.ecore.util.EcoreUtil;
@@ -900,6 +906,7 @@ public class EcoreEditor
{
resourceToReadOnlyMap = new HashMap<Resource, Boolean>();
}
+
@Override
public boolean isReadOnly(Resource resource)
{
@@ -918,6 +925,17 @@ public class EcoreEditor
"genmodel".equals(uri.fileExtension()) ||
uri.isPlatformResource() && !resourceSet.getURIConverter().normalize(uri).isPlatformResource() ||
uri.isPlatformPlugin();
+ if (!result)
+ {
+ for (Object value : resourceSet.getPackageRegistry().values())
+ {
+ if (value instanceof EObject && ((EObject)value).eResource() == resource)
+ {
+ result = true;
+ break;
+ }
+ }
+ }
if (resourceToReadOnlyMap != null)
{
resourceToReadOnlyMap.put(resource, result);
@@ -1195,13 +1213,15 @@ public class EcoreEditor
boolean isReflective = getActionBarContributor() instanceof EcoreActionBarContributor.Reflective;
final ResourceSet resourceSet = editingDomain.getResourceSet();
- final EPackage.Registry packageRegistry = resourceSet.getPackageRegistry();
resourceSet.getURIConverter().getURIMap().putAll(EcorePlugin.computePlatformURIMap(true));
resourceSet.getLoadOptions().put(XMLResource.OPTION_DEFER_IDREF_RESOLUTION, Boolean.TRUE);
if (isReflective)
- {
+ {
+ final EPackage.Registry packageRegistry = new DynamicLoadingEPackageRegistryImpl(resourceSet);
+ resourceSet.setPackageRegistry(packageRegistry);
+
// If we're in the reflective editor, set up an option to handle missing packages.
//
final EPackage genModelEPackage = packageRegistry.getEPackage("http://www.eclipse.org/emf/2002/GenModel");
@@ -1277,7 +1297,7 @@ public class EcoreEditor
if (!resourceSet.getResources().isEmpty())
{
Resource resource = resourceSet.getResources().get(0);
- if (isReflective && resource instanceof XMLResource)
+ if (isReflective && resource instanceof XMLResource && EcoreUtil.getObjectByType(resource.getContents(), EcorePackage.Literals.EPACKAGE) == null)
{
((XMLResource)resource).getDefaultSaveOptions().put(XMLResource.OPTION_LINE_WIDTH, 10);
}
@@ -2132,4 +2152,127 @@ public class EcoreEditor
{
return false;
}
+
+ /**
+ * A package registry implementation that locates and loads registered models based on references via the model's nsURI.
+ */
+ private static class DynamicLoadingEPackageRegistryImpl extends EPackageRegistryImpl
+ {
+ private static final long serialVersionUID = 1L;
+
+ private final Map<String, EPackage> ePackageNsURItoEPackageMap = new HashMap<String, EPackage>();
+
+ private final EList<Resource> editorResources;
+
+ private final ResourceSet modelResourceSet;
+
+ private Map<String, URI> ePackageNsURItoGenModelLocationMap;
+
+ public DynamicLoadingEPackageRegistryImpl(ResourceSet editorResourceSet)
+ {
+ super(EPackage.Registry.INSTANCE);
+ editorResources = editorResourceSet.getResources();
+ modelResourceSet = new ResourceSetImpl();
+ modelResourceSet.getURIConverter().getURIMap().putAll(editorResourceSet.getURIConverter().getURIMap());
+ }
+
+ @Override
+ public EPackage getEPackage(String nsURI)
+ {
+ EPackage ePackage = super.getEPackage(nsURI);
+ if (ePackage == null)
+ {
+ ePackage = ePackageNsURItoEPackageMap.get(nsURI);
+ }
+
+ if (ePackage == null)
+ {
+ if (ePackageNsURItoGenModelLocationMap == null)
+ {
+ ePackageNsURItoGenModelLocationMap = EcorePlugin.getEPackageNsURIToGenModelLocationMap(true);
+ }
+
+ URI location = ePackageNsURItoGenModelLocationMap.get(nsURI);
+ if (location != null)
+ {
+ EList<Resource> modelResources = modelResourceSet.getResources();
+ if (modelResources.isEmpty())
+ {
+ // To support Xcore resources, we need a resource with a URI that helps determine the containing project.
+ //
+ modelResourceSet.createResource(editorResources.get(0).getURI());
+ }
+
+ try
+ {
+ // Load the model location in this separate model resource set and resolve all proxies to ensure that any referenced Ecore models are loaded.
+ Resource modelResource = modelResourceSet.getResource(location, true);
+ EcoreUtil.resolveAll(modelResource);
+
+ // Look for an EPackage in all the resources.
+ //
+ EPackage.Registry packageRegistry = modelResourceSet.getPackageRegistry();
+ for (Resource resource : modelResources)
+ {
+ for (TreeIterator<?> i = new EcoreUtil.ContentTreeIterator<Object>(resource.getContents())
+ {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ protected Iterator<? extends EObject> getEObjectChildren(EObject eObject)
+ {
+ return eObject instanceof EPackage ? ((EPackage)eObject).getESubpackages().iterator() : Collections.<EObject> emptyList().iterator();
+ }
+ };i.hasNext();)
+ {
+ Object content = i.next();
+ if (content instanceof EPackage)
+ {
+ // Register the nsUR of each EPackage in the model resource set's package registry, and in our ePackageNsURItoEPackageMap,
+ // but only if it's not already registered there.
+ //
+ EPackage candidate = (EPackage)content;
+ String candidateNsURI = candidate.getNsURI();
+ if (super.getEPackage(candidateNsURI) == null)
+ {
+ put(candidateNsURI, candidate);
+ packageRegistry.put(candidateNsURI, candidate);
+ ePackageNsURItoEPackageMap.put(candidateNsURI, candidate);
+
+ // Also register the resource's actual URI in the package registry and change the resource's URI to the nsURI.
+ // This ensures that the resource can still be found via the original URI and even if the resource is moved to the editor's resource set.
+ //
+ Resource candidateResource = candidate.eResource();
+ if (candidateResource != null)
+ {
+ packageRegistry.put(candidateResource.getURI().toString(), candidate);
+ candidateResource.setURI(URI.createURI(candidateNsURI));
+ }
+ }
+ }
+ }
+ }
+
+ ePackage = ePackageNsURItoEPackageMap.get(nsURI);
+ if (ePackage != null)
+ {
+ Resource ePackageResource = ePackage.eResource();
+ if (ePackageResource != null && !editorResources.contains(ePackageResource))
+ {
+ // Move the resource to the editor's resource set so that it's visible.
+ //
+ editorResources.add(ePackageResource);
+ }
+ }
+ }
+ catch (RuntimeException exception)
+ {
+ EcoreEditorPlugin.INSTANCE.log(exception);
+ }
+ }
+ }
+
+ return ePackage;
+ }
+ }
}

Back to the top