Home » Modeling » ATL » Model injection of a registered XML/XSD model
Model injection of a registered XML/XSD model [message #1271242] |
Fri, 14 March 2014 12:08  |
Eclipse User |
|
|
|
Hello,
I am trying to programatically run an ATL transformation where one of the injected models is defined by XML/XSD, but it seems the model is not correctly injected by ATL.
If I define and load an EMF plugin that has the corresponding XSD2Ecore mapping, the transformation goes fine. However I want to run the transformation without the plugin available, i.e programatically mimic what the EMF plugin is doing.
From what I understand so far, these are my steps :
- Build the EPackage from the XSD using XSDEcoreBuilder
- Register the package in the model factory registry
- Use that model factory to create ReferenceModel, Model and injections
Although registrations/injections seem to go fine, the ATL transformation launcher raises an exception about missing class in the reference model.
Remarks before I enter into the code:
- the XSDEcoreBuilder changes class names by adding Type to each of them (e.g. MyClass->MyClassType) so I use those modified names in the transformation (though I'd prefer not to). I have tried old names and it doesn't change the behaviour.
- After registrations, I can programatically load the XML resource and navigate into it using EMF without problems. I find the expected classes. I looked at how ATL implements the injections (IInjector) and tried to mimic it in my "manual" EMF loading to see if I could reproduce the ATL error but it works fine.
- I tried to use the global registry instead of the factory local one without success.
- I know there is a potential workaround: directly passing the EMF loaded resource to ATL, but I would like to avoid that if possible.
Attached is a set of sample files for checking/testing: a sample ATL A2B, sample XML/XSD (A: inputs), sample XMI/Ecore (B: outputs), java code for testing.
Below is the java code for the tests, then the debug output and the ATL launch error:
Code:
public class TestATLXML {
public static void main(String[] args) {
try {
IPath inputMMPath = new Path("files/A.xsd");
IPath inputMPath = new Path("files/A-XSD.xml");
String inputMMName = "A";
IPath outputMMPath = new Path("files/B.ecore");
IPath outputMPath = new Path("files/B-XSD.xmi");
String outputMMName = "B";
IPath asmPath = new Path("files/A2B.asm");
//Initializations
ILauncher transformationLauncher = new EMFVMLauncher();
EMFModelFactory modelFactory = new EMFModelFactory();
IInjector injector = new EMFInjector();
IExtractor extractor = new EMFExtractor();
transformationLauncher.initialize(new HashMap<String,Object>());
// input
registerXSD(modelFactory,inputMMPath);
testEMFLoad(modelFactory, inputMPath);
IReferenceModel inputMM = modelFactory.newReferenceModel();
injector.inject(inputMM, URI.createFileURI(inputMMPath.toString()).toString());
IModel inputM = modelFactory.newModel(inputMM);
injector.inject(inputM, URI.createFileURI(inputMPath.toString()).toString());
transformationLauncher.addInModel(inputM, "IN", inputMMName);
// output
IReferenceModel outputMM = modelFactory.newReferenceModel();
injector.inject(outputMM, URI.createFileURI(outputMMPath.toString()).toString());
IModel outputM = modelFactory.newModel(outputMM);
transformationLauncher.addOutModel(outputM, "OUT", outputMMName);
// transformation
transformationLauncher.launch(ILauncher.RUN_MODE, new NullProgressMonitor(), new HashMap<String,Object>(),
new FileInputStream(asmPath.toOSString()));
// extract results
extractor.extract(outputM, URI.createFileURI(outputMPath.toString()).toString());
}
catch (ATLCoreException e) {
e.printStackTrace();
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
catch (ATLExecutionException e) {
e.printStackTrace();
}
}
private static void registerXSD(EMFModelFactory modelFactory, IPath XSD) throws IOException {
//local registry
ResourceSet resourceSet = modelFactory.getResourceSet();
resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put( "xsd",
new XSDResourceFactoryImpl());
resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put( "xml",
new XMLResourceFactoryImpl());
// global registry
//ResourceSet resourceSet = new ResourceSetImpl();
//Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().put("xsd",
//new XMLResourceFactoryImpl());
//Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().put("xml",
//new XMLResourceFactoryImpl());
XSDEcoreBuilder xsdEcoreBuilder = new XSDEcoreBuilder();
Collection<EObject> loaded = xsdEcoreBuilder.generate(URI.createFileURI(XSD.toOSString()));
for (Object loadedObject : loaded) {
if (loadedObject instanceof EPackage) {
//Resource.Factory.Registry.INSTANCE.
resourceSet.getPackageRegistry().put(((EPackage) loadedObject).getNsURI(), (EPackage) loadedObject);
// for xml with missing namespace and schema location
resourceSet.getPackageRegistry().put(null, (EPackage) loadedObject);
System.out.println("registerXSD: an EPackage in the input: " + ((EPackage) loadedObject).getNsURI());
} else {
final String typeInfo = (loadedObject == null)?
"N/A" : loadedObject.getClass().getName();
System.out.println("registerXSD: A non-EPackage in the input: " + typeInfo);
}
}
}
private static void testEMFLoad(EMFModelFactory modelFactory, IPath XML) {
// get factory resource set
ResourceSet resourceSet = modelFactory.getResourceSet();
// Not sure how these loading options should be set
Map options = resourceSet.getLoadOptions();
final ExtendedMetaData extendedMetaData = new BasicExtendedMetaData(resourceSet.getPackageRegistry());
options.put(XMLResource.OPTION_EXTENDED_META_DATA, extendedMetaData);
options.put(XMLResource.OPTION_RECORD_UNKNOWN_FEATURE, Boolean.TRUE);
// get resource
Resource resource = resourceSet.getResource(URI.createFileURI(XML.toOSString()), true);
// get & output root element name
EObject object = (EObject) resource.getContents().get(0);
System.out.println(object.eClass().toString());
// get & output root's first contained element
System.out.println(object.eContents().get(0).toString());
}
}
Output:
registerXSD: an EPackage in the input: files/A.xsd
org.eclipse.emf.ecore.impl.EClassImpl@aa8837c (name: DocumentRoot) (instanceClassName: null) (abstract: false, interface: false)
org.eclipse.emf.ecore.impl.DynamicEObjectImpl@5606b5d8 (eClass: org.eclipse.emf.ecore.impl.EClassImpl@69d2bdc3 (name: AType) (instanceClassName: null) (abstract: false, interface: false))
org.eclipse.m2m.atl.engine.emfvm.VMException: Cannot find class AType in reference model A
at __matchA2B#2(A2B.atl)
local variables: self=A2B : ASMModule
at __matcher__#1(A2B.atl)
local variables: self=A2B : ASMModule
at main#22(A2B.atl)
local variables: self=A2B : ASMModule
That'(s about it. I know I'm missing something but I can't find it. Any help appreciated.
Regards,
Mathias
|
|
|
Re: Model injection of a registered XML/XSD model [message #1274421 is a reply to message #1271242] |
Fri, 21 March 2014 08:49  |
Eclipse User |
|
|
|
Hello,
As a follow-up, I have tried the following workaround but the result is the same :
1) loading the resource "manually" using EMF
2) passing this resource URI to the ATL injector
As of now, my only option (considering the XSD2Ecore plugin is not available) is to first generate & serialize the corresponding XMI/ECORE with EMF and using these as transformation source.
Any ideas on what is wrong with my preferred approach ?
Regards,
|
|
|
Goto Forum:
Current Time: Thu Jul 10 02:21:58 EDT 2025
Powered by FUDForum. Page generated in 0.03169 seconds
|