Contents

Overview

MoDisco moved from Modeling/GMT to Modeling/MDT (see this bug). As part of this migration, we should have renamed all Java packages from org.eclipse.gmt.modisco.* to org.eclipse.modisco.*.

Unfortunately, this means breaking every existing API, which is in contradiction with the API policy that was established for MoDisco. Among other things, this policy states that API cannot be broken without notifying adopters at least one year before that.

This means for MoDisco that we cannot just rename the Java packages, because we still have to support the API that existed in the org.eclipse.gmt.modisco.* namespace.

To reconcile these two contradicting requirements, we explored several solutions, which are presented below.

Possible solutions

duplicate

We could, before releasing a new version of MoDisco with the renamed packages, duplicate all the previously renamed plug-ins, and rename all packages (through an automated refactoring) from org.eclipse.modisco.* back to org.eclipse.gmt.modisco.*. And then distribute this as a "backward compatibility SDK".

The problem with this solution is for adopters that rely on plug-ins with the old namespace, but that want to start developing plug-ins for the latest version of MoDisco. This would be an all-or-nothing solution: either migrate everything to the latest version of MoDisco, or develop new projects with the old version.

delegate

Another solution would be to create a "backward compatibility SDK" (with GMT packages) that delegates to the latest version of MoDisco. The idea looks straightforward: every call to an API from the old version delegates to the corresponding API in the latest version.

This could be automated through a refactoring that would create proxies (in the GMT namespace) for each MoDisco API, that delegate to the corresponding methods with the same name, but in the org.eclipse.modisco namespace.

This would look like this:

New API (org.eclipse.modisco namespace)

Proxy implementation (org.eclipse.gmt.modisco namespace)

publicclass A {public A(){// do some initialization}publicvoid doStuff(){// do some stuff}}

A proxy knows its delegate, but a delegate doesn't know its proxy. But we need this information to be able to find the proxy that was associated with an element that is returned from a method. So, we have to keep this information somewhere. For example in a HashMap:

So far, so good. But in practice, we discovered that this is not always so simple, and there are many roadblocks that prevent this solution from working 100%. Moreover, even getting it to work only for common cases that can work is far from trivial, and requires a fair amount of work.