Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 360940

Summary: [Import/Export] allow IMPORT to override package unit and nsURI
Product: [Modeling] EMF Reporter: Erdal Karaca <erdal.karaca.de>
Component: cdo.coreAssignee: Project Inbox <emf.cdo-inbox>
Status: NEW --- QA Contact:
Severity: enhancement    
Priority: P3 CC: alexandre.borgoltz, Carel.Bast, esteban.dugueperoux, laurent.redor, lu.xingxiao, stepper
Version: 4.13   
Target Milestone: ---   
Hardware: PC   
OS: Windows XP   
Whiteboard:
Attachments:
Description Flags
preliminary nsURI/package unit rewrite support none

Description Erdal Karaca CLA 2011-10-14 06:52:57 EDT
When importing an exported repository, I would like to apply new namespace URIs and their corresponding package units (meta models).
This will allow us to migrate models whose meta models are changed in a binary compatible way.
Comment 1 Erdal Karaca CLA 2011-10-18 03:59:07 EDT
First run: I am getting this exception:

java.lang.IllegalStateException: Unresolvable proxy: http://example.com/users-v1.0.ecore#//User
	at org.eclipse.emf.cdo.common.model.EMFUtil.safeResolve(EMFUtil.java:414)
	at org.eclipse.emf.cdo.common.model.EMFUtil.safeResolveAll(EMFUtil.java:435)
	at org.eclipse.emf.cdo.server.CDOServerImporter$FlushHandler.handleModels(CDOServerImporter.java:268)
	
This is the step when the new ecore file is loaded instead of the old one.
In the new ecore file (just copied from my workspace into another temprorary folder), I can see things like this:

<eStructuralFeatures xsi:type="ecore:EReference" name="creator" lowerBound="1"
        eType="ecore:EClass users-v1.0.ecore#//User"/>
        
The old package unit contains this:

<eStructuralFeatures xsi:type="ecore:EReference" name="creator" lowerBound="1"
        eType="ecore:EClass praesto-users-v1.0#//User"/>
        
So, when it is about to resolve the type, it cannot be found as the namespace is not correctly built.

Do you have any hints where to look for or what to do next?

I will attach the current patch/diff...
Comment 2 Erdal Karaca CLA 2011-10-18 04:01:11 EDT
Created attachment 205392 [details]
preliminary nsURI/package unit rewrite support
Comment 3 Erdal Karaca CLA 2011-10-18 04:03:13 EDT
Note to comment #1:
It should read (not anonymized completely):

"""
The old package unit contains this:

<eStructuralFeatures xsi:type="ecore:EReference" name="creator" lowerBound="1"
eType="ecore:EClass users-v1.0#//User"/>
"""
Comment 4 Erdal Karaca CLA 2011-10-18 04:55:04 EDT
I just opened the new package unit (modified ecore file) in a text editor and removed all ".ecore" occurences.
Then, I am
Comment 5 Erdal Karaca CLA 2011-10-18 04:55:39 EDT
Then, I am able to go one step further...
Comment 6 Erdal Karaca CLA 2011-10-18 05:04:03 EDT
The next question is: How to resolve proxies that are still referencing old types, i.e. types whose package URI has changed?
When loading the package unit that do not have changed, we must be able to dispatch proxy URIs.
Is that possible?
Comment 7 Eike Stepper CLA 2011-10-18 05:09:14 EDT
What do you mean by proxy? That term does not exist in CDO.
Comment 8 Erdal Karaca CLA 2011-10-18 05:16:09 EDT
Example:
Package A contains a Class C1 that has a reference to Class C2 in package B.
Now, I decide to change package B's URI.
When loading package unit A, it will fail since C1 is referencing  C2 which now has a new URI.

I just saw that the exception is caused due to org.eclipse.emf.ecore.util.EcoreUtil.resolve(EObject, ResourceSet) being called.
Inside this method:
URI proxyURI = ((InternalEObject)proxy).eProxyURI(); 

proxyURI contains the old URI...

Is that understandable?
Comment 9 Eike Stepper CLA 2011-10-18 05:23:23 EDT
Ah, you're referring to EReferences between EModelElements. You're right, EModelElements are EObjects, too. I thought you were referring to references between "normal" EObjects, which are really CDORevisions and have no proxy URIs ;-)

Next question: You say "When loading the package unit that do not have changed, we must be able to dispatch proxy URIs." What means "dispatch"? "Map to new URIs"?

Perhaps it's easier to understand if you first specify exactly *what* you're trying to achieve and then find out *how* to do that. What are the model changes you're planning to support and what will not be covered?
Comment 10 Erdal Karaca CLA 2011-10-18 05:32:42 EDT
As said in the forum post, this solution is only meant to be usable for simple meta model changes (binary compatibility).

This is to be achieved by "enhancing" the import functionality of cdo, i.e. when importing an exported repository:

- "dispatch", i.e. map old URIs to new URIs
- load new package units by specifying a new ecore file path

Note: This could all be done at xml file level, e.g. via xslt. But that would be specific to the xml export.
This solution will work for any import types.

The patch attached does already do this.
You can run the "enhanced import" this way:

cdo import repo1 path/to/file.xml http://myOldURI=http://myNewURI=mynewuri.ecore
Comment 11 Eike Stepper CLA 2011-10-18 05:45:51 EDT
I see. Regarding your previous question:

If you evolve one EPackage I'd expect all depending EPackages to evolve at the same pace. Changing something in an EPackage X must be followed by changing the nsURI to X'. If an EPackage Y depended on X and you're not going to drop it entirely you must also migrate Y to Y', even if it's only for the sake of the new references to X' (your "proxies", I guess).

Does that make sense?
Comment 12 Erdal Karaca CLA 2011-10-18 05:54:37 EDT
Yes, that makes sense!
When changing X to X': Shouldn't Y automatically be changed to Y' by the emf tooling? If yes, I do not see any changes made to Y.ecore in my workspace...

Then, I would have to replace all package units when importing:

cdo import repo1 path/to/file.xml http://X=http://X'=X'.ecore http://Y=http://Y'=Y'.ecore
Comment 13 Eike Stepper CLA 2011-10-18 06:04:58 EDT
> When changing X to X': Shouldn't Y automatically be changed to Y' by the emf
> tooling? If yes, I do not see any changes made to Y.ecore in my workspace...

I doubt it. In the best case (well, in fact it's the worst case, IMHO) Y would be serialized with the new references to X' but keep its old nsURI Y. I do not recall a magic in EMF that chooses a new nsURI for changed packages.

> Then, I would have to replace all package units when importing:
> 
> cdo import repo1 path/to/file.xml http://X=http://X'=X'.ecore
> http://Y=http://Y'=Y'.ecore

Yeah ;-)
Comment 14 Eike Stepper CLA 2011-10-18 06:07:20 EDT
> cdo import repo1 path/to/file.xml http://X=http://X'=X'.ecore
> http://Y=http://Y'=Y'.ecore

Keep in mind (IIRC) the equal sign "=" is allowed in normal nsURIs! Personally I would prefer a separate migration mappings file and a command line option like:

    -migrate "/path/to/mappings"
Comment 15 Erdal Karaca CLA 2011-10-18 06:55:28 EDT
What structure should the migration script have?
Simple properties file?
Maybe:

X=X'
Y=Y'
X'=X'.ecore
Y'=Y'.ecore

Afaik, you can escape specific chars in a properties file and use:

http\://example.com/model/version\=1.0=http://example.com/model/version\=2.0

What do you think about comment #1? Do you have a solution? How did you manage to put the ecore files as package units into the repository?
Comment 16 Eike Stepper CLA 2011-10-18 11:56:37 EDT
(In reply to comment #15)
> What do you think about comment #1? Do you have a solution? How did you manage
> to put the ecore files as package units into the repository?

With this code:

      PackageLoader loader = new PackageLoader()
      {
        public EPackage[] loadPackages(CDOPackageUnit packageUnit)
        {
          String id = packageUnit.getID();
          String data = models.get(id);

          EPackage ePackage = EMFUtil.createEPackage(id, data.getBytes(), false, resourceSet, true);
          return EMFUtil.getAllPackages(ePackage);
        }
      };

      packageRegistry.putPackageUnits(array, CDOPackageUnit.State.PROXY);
      for (InternalCDOPackageUnit packageUnit : array)
      {
        packageUnit.load(loader, false);
      }
Comment 17 Eike Stepper CLA 2011-10-18 12:09:52 EDT
(In reply to comment #15)
> What structure should the migration script have?
> Simple properties file?

I clarified that nsURIs may contain "=" characters, but spaces wouldn't work very well (although they're not explicitely excluded by the spec, according to Ed).

What about an own format like:

  X -> X'
  Y -> Y'
Comment 18 Erdal Karaca CLA 2011-10-18 13:59:55 EDT
(In reply to comment #17)
> (In reply to comment #15)
> > What structure should the migration script have?
> > Simple properties file?
> 
> I clarified that nsURIs may contain "=" characters, but spaces wouldn't work
> very well (although they're not explicitely excluded by the spec, according to
> Ed).
> 
> What about an own format like:
> 
>   X -> X'
>   Y -> Y'

Actually, that would be the start of a domain specific language (DSL) that we would have to maintain/extend by time...
I tried with the plain old properties format and it works very well as long as we have such simple requirements.

Or do we really want a specific 'migration file format'?
Comment 19 Erdal Karaca CLA 2011-10-18 14:03:48 EDT
(In reply to comment #16)
> (In reply to comment #15)
> > What do you think about comment #1? Do you have a solution? How did you manage
> > to put the ecore files as package units into the repository?
> 
> With this code:
> 
>       PackageLoader loader = new PackageLoader()
>       {
>         public EPackage[] loadPackages(CDOPackageUnit packageUnit)
>         {
>           String id = packageUnit.getID();
>           String data = models.get(id);
> 
>           EPackage ePackage = EMFUtil.createEPackage(id, data.getBytes(),
> false, resourceSet, true);
>           return EMFUtil.getAllPackages(ePackage);
>         }
>       };
> 
>       packageRegistry.putPackageUnits(array, CDOPackageUnit.State.PROXY);
>       for (InternalCDOPackageUnit packageUnit : array)
>       {
>         packageUnit.load(loader, false);
>       }


E.g. my ecore files in the workspaces have embedded ecore file names when cross references are involved.
In the datastore, those file references are not present...
Does that have to do with URI conversion? I will try the code once I am back at my development machine...
Comment 20 Eike Stepper CLA 2011-10-18 16:06:24 EDT
(In reply to comment #18)
> Or do we really want a specific 'migration file format'?

Not necessarily now ;-)

The format aspect is probably less costly than the execution semantics implied by a full-fledged model migration DSL.
Comment 21 Eike Stepper CLA 2011-10-18 16:14:50 EDT
(In reply to comment #19)
> E.g. my ecore files in the workspaces have embedded ecore file names when cross
> references are involved.
> In the datastore, those file references are not present...

Because obviously they would make sense in a non-local environment.

> Does that have to do with URI conversion? I will try the code once I am back at
> my development machine...

I must admit that I've never fully understood the subtleness of references to unregistered packages. For a distributed system we definitely need keys that make sense everywhere.
Comment 22 Alexandre Borgoltz CLA 2011-11-21 14:35:21 EST
Erdal, did you finally reach your goal (migrating a CDO-hosted model to a newer version of the metamodel)?
Comment 23 Erdal Karaca CLA 2011-11-21 14:47:23 EST
(In reply to comment #22)
> Erdal, did you finally reach your goal (migrating a CDO-hosted model to a newer
> version of the metamodel)?

Unfortunately, not fully, as I am stuck with those embedded ecore meta model file names used when cross references occur...
One workaround would be to remove the package units from the xml repository export and load it "manually" into the repository by registering your new meta models with the package registry (once you create your session). Then, import the (modified) repository file again.

One other thing I still have to try out is: load the xml file into an xml database (e.g. basex), then use xquery to manipulate or "migrate" the "model" and export it again.
Comment 24 Eike Stepper CLA 2012-08-14 22:58:11 EDT
Moving all open issues to 4.2. Open bugs can be ported to 4.1 maintenance after they've been fixed in master.
Comment 25 Eike Stepper CLA 2013-06-27 04:09:25 EDT
Moving all outstanding enhancements to 4.3
Comment 26 Eike Stepper CLA 2014-08-19 09:29:22 EDT
Moving all open enhancement requests to 4.4
Comment 27 Eike Stepper CLA 2014-08-19 09:38:13 EDT
Moving all open enhancement requests to 4.4
Comment 28 Eike Stepper CLA 2015-07-14 02:22:29 EDT
Moving all open bugzillas to 4.5.
Comment 29 Eike Stepper CLA 2016-07-31 01:05:24 EDT
Moving all unaddressed bugzillas to 4.6.
Comment 30 Eike Stepper CLA 2017-12-28 01:14:22 EST
Moving all open bugs to 4.7
Comment 31 Eike Stepper CLA 2019-11-08 02:16:31 EST
Moving all unresolved issues to version 4.8-
Comment 32 Eike Stepper CLA 2019-12-13 12:46:27 EST
Moving all unresolved issues to version 4.9
Comment 33 Eike Stepper CLA 2020-12-11 10:36:42 EST
Moving to 4.13.