eclipse-sirius / sirius-emf-json

JSON-based EMF Resource implementation - part of Eclipse Sirius
https://eclipse.dev/sirius/sirius-web.html
Eclipse Public License 2.0
5 stars 10 forks source link

Do not assume Schema Locations are pointing to a Resource it can be an EObject #24

Closed adaussy closed 10 months ago

adaussy commented 10 months ago

The current implementation assume that the URI located in schemaLocation attribute points to a resource. It not always the case it could target directly a EPackage inside a Resource. It is especially the case when dealing with UML profile.

org.eclipse.sirius.emfjson.utils.GsonEObjectDeserializer.deserialize(JsonElement, Type, JsonDeserializationContext)

 @Override
    public List<EObject> deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext context) throws JsonParseException {
       ...

        // schema location
        JsonObject jsonSchemaLocation = jsonRoot.getAsJsonObject(IGsonConstants.SCHEMA_LOCATION);
        if (jsonSchemaLocation != null) {
            Set<Entry<String, JsonElement>> schemaLocationSet = jsonSchemaLocation.entrySet();
            for (Entry<String, JsonElement> entry : schemaLocationSet) {
                String schemaLocation = entry.getValue().getAsString();

                if (this.resourceSet != null && schemaLocation != null && schemaLocation.length() > 0) {
                    URI uri = URI.createURI(schemaLocation);
                    if (this.uriHandler != null) {
                        uri = this.uriHandler.resolve(uri);
                    }
                    // TODO: in condition, add a test for extendedMetaData (see line 2898 of
                    // XMLHandler.class)
                    uri = this.helper.resolve(uri, this.resourceURI);
                    Resource ePackageResource = this.resourceSet.getResource(uri, true);
                    TreeIterator<EObject> iterator = ePackageResource.getAllContents();
                    while (iterator.hasNext()) {
                        EObject eObject = iterator.next();
                        if (eObject instanceof EPackage) {
                            EPackage ePackage = (EPackage) eObject;
                            this.resourceSet.getPackageRegistry().put(ePackage.getNsURI(), ePackage);
                        }
                    }
                }
            }
        }

        ...
    }

I think we need to check if a fragment is present an if it is directly use resourceSet.getEObject(URI).

Here is a model than can be used to check.

DynamicProfileTypeTests.profile.uml.zip

xsi:schemaLocation="http://www.eclipse.org/uml2/schemas/Ecore/5 pathmap://UML_PROFILES/Ecore.profile.uml#_z1OFcHjqEdy8S4Cr8Rc_NA"