osate / osate2

Open Source AADL2 Tool Environment
http://osate.org
Eclipse Public License 2.0
36 stars 8 forks source link

Property sets and packages cannot be contributed in standalone mode #1388

Closed lwrage closed 5 years ago

lwrage commented 6 years ago

AADL model units are currently contributed via an extension point. We need a registry that can be populated programmatically to operate in standalone mode. child of #1538

Etienne13 commented 5 years ago

FYI, you can do standalone application using the current mechanism (via extension point) if your standalone application is an osgi application (this is what we did to do non regression tests in RAMSES)

lwrage commented 5 years ago

@Etienne13 Do you have any documentation that shows how to create such an osgi application?

AaronGreenhouse commented 5 years ago

Based on current work on #1387 I copied the revised AnnexRegistry to this branch (1388_stand_alone_property_sets), and created another test program LoadDeclarativeModelAndContributedProperties.

I'm using the test model

package test
public
    annex fake {** fake **}; 

    data d
        properties
            Source_language => (Java, C);
    end d;
end test;

When I load it the verifier is unable to resolve the name of the property Source_Language or of the enumeration elements Java and C:

Loading...

Validating...
Couldn't resolve reference to property definition 'Source_language'. Property set name may be missing.
Couldn't resolve reference to Property Constant, Property Definition, Enumeration or Unit literal 'Java'. For classifier references use classifier( <ref> ).
Couldn't resolve reference to Property Constant, Property Definition, Enumeration or Unit literal 'C'. For classifier references use classifier( <ref> ).
Packge test has duplicates /SEI/Tools/Eclipses/osate2_2018-12-develop-2019-02-13/ws/LoadDeclarativeModelAndContributedProperities/aadl_files/test.aadl

Traversing...
*** aadl_files/test.aadl ***
org.osate.aadl2.impl.AadlPackageImpl@31142d58 (name: test)
org.osate.aadl2.impl.PublicPackageSectionImpl@e38f0b7 (name: null) (noAnnexes: false, noProperties: false)
org.osate.aadl2.impl.DataTypeImpl@1192b58e (name: d) (noPrototypes: false, noAnnexes: false, noProperties: false) (derivedModes: false, noFlows: false, noModes: false) (noFeatures: false)
org.osate.aadl2.impl.PropertyAssociationImpl@4f8d86e4 (append: false, constant: false)
org.osate.aadl2.impl.ModalPropertyValueImpl@25f723b0 (name: null)
org.osate.aadl2.impl.ListValueImpl@4aa11206
org.osate.aadl2.impl.NamedValueImpl@40d60f2
org.osate.aadl2.impl.NamedValueImpl@6d8796c1
org.osate.aadl2.impl.DefaultAnnexLibraryImpl@784223e9 (name: fake) (sourceText: {** fake **})
org.osate.aadl2.impl.DefaultAnnexLibraryImpl@7316523a (name: fake) (sourceText:  fake )
-- -- -- -- -- -- -- --

This is the problem that we need to fix: Having the contributed property sets installed and loaded.

AaronGreenhouse commented 5 years ago

Need to update PluginSupportUtil.getContributedAadl() the same that I updated AnnexRegistry. Probably should even merge the two fixes to make sure the extension registry is only created once.

AaronGreenhouse commented 5 years ago

I'm not entirely sure how the contributed aadl is loaded and "linked" in OSATE. But I think what I want to do here is provide a mechanism for getting the list of contributed aadl from the plugin.xml files and then adding them to the ResourceSet that is used by the stand-alone program.

AaronGreenhouse commented 5 years ago

See org.osate.testsupport.TestResourceSetHelper.initialize() for loading of contributed resources. Pay attention to the URI mapping business.

As with #1387, supporting registration of contributions from the manifest files and through direct registration via method calls.

AaronGreenhouse commented 5 years ago

This is not working in any kind of straightforward way. I have modified the LoadDeclarativeModel example from Issue #1387 to add some property sets to the resource set and to add them to the URI map as is done in org.osate.testsupport.TestResourceSetHelper.initialize().

        final URI psURI1 = URI.createPlatformPluginURI(
                "org.osate.workspace/resources/properties/Predeclared_Property_Sets/Programming_Properties.aadl",
                false);

        final URI psURI2 = URI.createPlatformPluginURI(
                "org.osate.workspace/resources/properties/Predeclared_Property_Sets/AADL_Project.aadl",
                false);

        final List<Resource> resources = new ArrayList<>();

        final Map<URI, URI> uriMap = rs.getURIConverter().getURIMap();
        resources.add(rs.getResource(psURI1, true));
        uriMap.put(psURI1, URI.createPlatformResourceURI(psURI1.path().substring(7), false));
        resources.add(rs.getResource(psURI2, true));
        uriMap.put(psURI2, URI.createPlatformResourceURI(psURI2.path().substring(7), false));

References are not being resolved between the property sets or the example that uses them:

...aadl_files/test.aadl
Couldn't resolve reference to property definition 'Source_language'. Property set name may be missing.
Couldn't resolve reference to Property Constant, Property Definition, Enumeration or Unit literal 'Java'. For classifier references use classifier( <ref> ).
Couldn't resolve reference to Property Constant, Property Definition, Enumeration or Unit literal 'C'. For classifier references use classifier( <ref> ).

Futhermore, all kinds of weird messages are output regarding the property sets:

Validating...
...platform:/plugin/org.osate.workspace/resources/properties/Predeclared_Property_Sets/Programming_Properties.aadl
1    [main] INFO  t.linking.impl.ImportedNamesAdapter  - getElements should be called with a QualifiedName during linking.
11   [main] INFO  t.linking.impl.ImportedNamesAdapter  - getElements should be called with a QualifiedName during linking.
17   [main] INFO  t.linking.impl.ImportedNamesAdapter  - getElements should be called with a QualifiedName during linking.
18   [main] INFO  t.linking.impl.ImportedNamesAdapter  - getElements should be called with a QualifiedName during linking.
19   [main] INFO  t.linking.impl.ImportedNamesAdapter  - getElements should be called with a QualifiedName during linking.
19   [main] INFO  t.linking.impl.ImportedNamesAdapter  - getElements should be called with a QualifiedName during linking.
20   [main] INFO  t.linking.impl.ImportedNamesAdapter  - getElements should be called with a QualifiedName during linking.
20   [main] INFO  t.linking.impl.ImportedNamesAdapter  - getElements should be called with a QualifiedName during linking.
21   [main] INFO  t.linking.impl.ImportedNamesAdapter  - getElements should be called with a QualifiedName during linking.
...

It is highly possible that the URI map we are creating is wrong. But it's unclear what it should be.

If you load the property sets from the local directory as a regular .aadl file, things do work correctly.

lwrage commented 5 years ago

I have a version that works, at least it seems to resolve all references.

lwrage commented 5 years ago

We still need a way to get the list of predeclared property sets in standalone mode.

AaronGreenhouse commented 5 years ago

Working on an example that reads the contributed resources from the plugin.xml extensions.

To run this kind of example you need to put the jars that contain the contributed resources on the classpath (this should be obvious), but you also need the jar for org.osate.pluginsupport

java -cp ".\runit.jar;.\org.osate.contribution.sei_1.0.0.v20190228-2050.jar;.\org.osat
e.workspace_1.0.0.v20180511-1311.jar;.\org.osate.pluginsupport_1.0.0.v20190403-1541.jar" org.osate.standalone.emf.LoadDeclarativeModelAndContributedProperties_extensions
AaronGreenhouse commented 5 years ago

Had to tweak AnnexRegistry (more so than from the tweaks for #1387). It was not enough to check whether the extension registry is null. Need also to check the extension point itself. If neither is present just install the default registry handler.

AaronGreenhouse commented 5 years ago

Not sure how to set up the URI map when loading the contributed resources from extensions automatically. I tried using the scheme from TestResourceSetHelper but that doesn't seem to work.

AaronGreenhouse commented 5 years ago

When loading contributed resources from the extension registry, the URIs should be converted to classpath:/ URIs. I added a method to PluginSupportUtil to get them in this format.

AaronGreenhouse commented 5 years ago

Summary of the important points here:

For the cross-references to work between the models, we must pretend that the file are organized as a project. For example, here we create a project "foo" that is in the directory aadl_files of the current directory:

// URI mapping for loading files this defines the "workspace" needed to resolve relative references
String wsRoot = Paths.get(".").toAbsolutePath().normalize().toString();
EcorePlugin.getPlatformResourceMap().put("foo", URI.createFileURI(wsRoot + "/aadl_files/"));

The upshot of this is that when we load the files we refer to them as being in foo and not in aadl_files. So for example, if the names are being passed on the command line, they should be named foo/test.aadl even though they are located in aadl_files/test.aadl.

(In the future, there should probably be some library methods to make this process more transparent to the user of the program, but right now we don't have enough experience with how this is going to work in practice.)

As with annexes, there are two ways to proceed with finding the contributed resources.

  1. They can searched for in the plug-ins, or
  2. They can explicitly loaded by the application

To get the list of contributed resources from the plug-ins on the classpath, use

EcorePlugin.ExtensionProcessor.process(null);
final List<URI> contributed = PluginSupportUtil.getContributedAadlAsClasspath();

This is the same process() method as for annexes. It only needs to be called once for the entire program to make sure that all the plugin.xml files are read and processed. The method call PluginSupportUtil.getContributedAadlAsClasspath() gets the URIs to all the contributed resources as classpath:/ URIs. You just add them to the resource set as you any other resource:

        for (final URI uri : contributed) {
            rs.getResource(uri, true);
        }

When executing the program you need to make sure the plug-in jar files containing the contributed resources you need are on the classpath. You also need to have the the jar for org.osate.pluginsupport on the classpath because it contains the scheme for the contributed aadl extension.

Searching all the plug-ins on the classpath can be slow, so it may be better to simply name the needed contributed resources directly. To do this you just create your own classpath:/ URIs. For example, if you need the resources AADL_Project.aadl and Programming_Properties.aadl you would use code like the following:

final String jar = "classpath:/";
final String path = "resources/properties/Predeclared_Property_Sets/";

final URI psURI1 = URI.createURI(jar + path + "AADL_Project.aadl");
final URI psURI2 = URI.createURI(jar + path + "Programming_Properties.aadl");

rs.getResource(psURI1, true);
rs.getResource(psURI2, true);

Note that you need to know the location of the contributed resource within the jar file.

Again, at runtime you need to make sure that the plugin jar file containing the contributed resources is on the classpath.

When directly loading the contributed resource, you must also set up the URI mappings to map the plug-in to the jar file. This is necessary so that names in instance models can be resolved correctly. (The URI map is set up by the process() method when loading information from the plugin.xml files.)

// set up URI mappings for reference resolution
final Map<URI, URI> uriMap = rs.getURIConverter().getURIMap();
// mapped URIs end in '/' => prefix mapping
uriMap.put(URI.createPlatformPluginURI("/org.osate.workspace/", false), URI.createURI(jar));

Here jar still refers to "classpath:/" as above. Here we map org.osate.workspace because that is the plug-in that contains the contributed resources we are using. If we were using contributed resources from other plug-ins we would have to map those plug-ins as well.

(Again, should any one ever write a real program that uses this stuff we should probably create some library methods to help out with this process.)

AaronGreenhouse commented 5 years ago

Copied the above to the OSATE2 wiki: https://github.com/osate/osate2/wiki/Using-contributed-resources-in-stand-alone-applications