Home » Modeling » TMF (Xtext) » XMI and cross references (xtext links) problem
| |
Re: XMI and cross references (xtext links) problem [message #1109371 is a reply to message #1109331] |
Sun, 15 September 2013 09:30 |
Alan DW Messages: 119 Registered: March 2012 |
Senior Member |
|
|
Hi Christian,
thank you for your support, it is much appreciated. I have attached the XText source file in question to this message, along with a (toy) example model. Basically it is about modeling the IT landscape (architecture) of a company and a quite straight-forward DSL. However, the use case is a little complex, so I'll try to explain as good as I can.
The most important part is at the top of the file:
/** An ArchFile is the (syntactically invisible) top-level element in each file. */
ArchFile:
(fragments += Fragment)*
;
/** A Fragment is basically everything that may be contained in an ArchFile. */
Fragment:
OrganizationalComponent | Location | Person | HardwareComponent | SoftwareComponent | Service
;
So, each DSL instance file has an invisible top-level container, which may hold any number of fragments, as listed in the grammar. And of course, multiple DSL instance files can - and will - cross reference each other in the same project.
Now, my eclipse-plug-in is supposed to:
- Scan a given Eclipse Project in the workspace for DSL files (by file extension)
- Load the contained EObjects, resolving cross-file-references and maintaining referential integrity
- Create a single ArchFile container which holds all of the fragments
- Serialize that ArchFile to XMI
- Send the generated XMI to a web-server
After scanning the project for DSL files, here is my code for loading the DSL files. I suspect the error to be in this code.
/**
* Returns all model elements in the project.<br>
* This method will also resolve cross-references between Xtext DSL files.
*
* @return The set of all model elements in the project.
*/
public Set<EObject> getModelElements() {
ResourceSet projectResourceSet = new ResourceSetImpl();
// this.dslFiles is a set of thin wrappers around eclipse IFiles.
for (DSLFileWrapper dslFile : this.dslFiles) {
try {
projectResourceSet.createResource(dslFile.getFileURI()).load(null);
} catch (IOException e) {
Logger.logError(e);
}
}
// resolve all cross-references in the resource set
EcoreUtil.resolveAll(projectResourceSet);
Set<EObject> modelElements = new HashSet<EObject>();
Logger.log("Gathering model elements from " + projectResourceSet.getResources().size() + " resource(s)");
for (Resource resource : projectResourceSet.getResources()) {
Logger.log("Found " + resource.getContents().size() + " root element(s) in resource "
+ resource.getURI().toString());
modelElements.addAll(resource.getContents());
}
return modelElements;
}
Afterwards, the common root model element is built. The following snippet is Xtend code. It receives the output of the previous Java snippet as input:
public override EObject buildModel(Collection<EObject> individualElements) {
val ArchFile model = ArchDSLFactory::eINSTANCE.createArchFile();
for(EObject element : individualElements){
if(element instanceof Fragment){
model.fragments.add(element as Fragment);
}else if(element instanceof ArchFile){
model.fragments.addAll((element as ArchFile).fragments);
}
}
return model;
}
And finally, for sending the assembled model to the Webserver, it is converted to XMI (Java code again):
/**
* Converts the given {@link EObject} model into its XMI representation.
*
* @param model
* The model to convert
* @return The XMI string representation of the given model
*/
public static String serializeEObjectToXMI(final EObject model) {
ResourceSet resourceSet = new ResourceSetImpl();
resourceSet.getResourceFactoryRegistry().getProtocolToFactoryMap().put("xmi", new XMIResourceFactoryImpl());
Resource resource = resourceSet.createResource(org.eclipse.emf.common.util.URI.createFileURI("temp/model.xmi"));
EcoreUtil.resolveAll(resource);
if (model != null) {
resource.getContents().add(model);
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
resource.save(baos, null);
} catch (IOException ioe) {
Logger.logError(ioe);
}
String modelXMI = baos.toString();
try {
baos.close();
} catch (IOException ioe) {
}
if (model != null) {
resource.getContents().remove(model);
}
try {
resource.delete(null);
} catch (IOException e) {
Logger.logError(e);
}
return modelXMI;
}
However, at the very end of this (lengthy) procedure, I still find xtext links to be contained in the output XMI, which refer to local file URIs - and my remote server is of course unable to resolve those.
Sorry for the lengthy post, but the matter is complex...
Thanks again for your help!
Alan
[Updated on: Sun, 15 September 2013 09:32] Report message to a moderator
|
|
| | |
Re: XMI and cross references (xtext links) problem [message #1109402 is a reply to message #1109395] |
Sun, 15 September 2013 10:33 |
Alan DW Messages: 119 Registered: March 2012 |
Senior Member |
|
|
Hi Christian,
I've prepared the fully executable test plug-in and attached it to this message. Just import the two projects in your workspace (one is the Xtext DSL) and run the JUnit test case provided in ArchPlugin/src/tests/ArchTest.java as JUnit Plug-In Test. Before you do that, make sure that your JUnit workspace contains the "ArchitectureTest" project I've sent to you earlier, as the test will look for it.
Now, there ARE a couple of *very* strange things going on. First off, I could not get the test to run without calling the "StandaloneSetup" of my DSL, because the resource.load(null) method would throw an exception otherwise. I don't have that in my main project, though.
The second very strange thing is that with the StandaloneSetup, the XMI generation actually works as expected and does not contain xtextlinks any more (which is great!).
Can you shed some light on what the StandaloneSetup actually does? It has always been kind of a spell to me.
Thanks,
Alan
EDIT: The exception that I was getting in the JUnit test has turned out to be nothing else than a plain old PermGenSpace error. Turning up the max perm gen space fixed it. I have verified that the ONLY real difference between my main project and the small JUnit test provided here is the presence of the StandaloneSetup. Indeed, if that line is removed from the JUnit plug-in test, the resulting XMI will contain the xtext links again.
Still, for some reason I don't know yet, I can't get it to work in my main project in the same way as it works in the test project, even with calling StandaloneSetup...
[Updated on: Sun, 15 September 2013 11:33] Report message to a moderator
|
|
|
Re: XMI and cross references (xtext links) problem [message #1109441 is a reply to message #1109402] |
Sun, 15 September 2013 11:55 |
|
Hi,
calling standalonesetups in eclipse is bad. use the ui injector provider instead.
second you are missing the ui project.
and you did not what i told you
with a normal xtext project you can do something like:
grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.common.Terminals
generate myDsl "http://www.xtext.org/example/mydsl/MyDsl"
Model:
greetings+=Greeting*;
Greeting:
'Hello' name=ID ('from' from=[Greeting])? '!';
package org.xtext.example.mydsl.tests;
import static org.junit.Assert.assertTrue;
import java.util.Set;
import javax.inject.Inject;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.xtext.junit4.InjectWith;
import org.eclipse.xtext.junit4.XtextRunner;
import org.eclipse.xtext.ui.resource.IResourceSetProvider;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.xtext.example.mydsl.MyDslUiInjectorProvider;
@RunWith(XtextRunner.class)
@InjectWith(MyDslUiInjectorProvider.class)
public class SampleTest {
@Inject
IResourceSetProvider resourceSetProvider;
@Test
public void testIt() {
IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
IProject project = workspaceRoot.getProject("ArchitectureTest");
assertTrue(project.exists());
ResourceSet resourceSet = resourceSetProvider.get(project);
System.out.println("ArchitectureTest project found.");
Set<IFile> dslFiles = WorkspaceUtils.getAllDSLFilesInFolder(project.getLocation(), ".mydsl");
System.out.println("Found " + dslFiles.size() + " DSL files.");
Set<EObject> modelElements = WorkspaceUtils.getModelElements(dslFiles, resourceSet);
System.out.println("Read " + modelElements.size() + " model root elements.");
EObject modelRoot = ModelBuilder.build(modelElements);
System.out.println("Built root model.");
String XMI = XMIUtils.serializeEObjectToXMI(modelRoot, resourceSet);
System.out.println("The serialized model XMI contents");
System.out.println();
System.out.println();
System.out.println(XMI);
// this should hold, but it doesn't
assertTrue(XMI.contains("xtextLink") == false);
}
}
package org.xtext.example.mydsl.tests;
import java.util.Set;
import org.eclipse.emf.ecore.EObject;
import org.xtext.example.mydsl.myDsl.Greeting;
import org.xtext.example.mydsl.myDsl.Model;
import org.xtext.example.mydsl.myDsl.MyDslFactory;
public class ModelBuilder {
public static EObject build(final Set<EObject> elements) {
Model root = MyDslFactory.eINSTANCE.createModel();
for (EObject element : elements) {
if (element instanceof Model) {
root.getGreetings().addAll(((Model) element).getGreetings());
} else {
System.out.println("Could not determine type of eobject '" + element.toString() + "'!");
}
}
return root;
}
}
package org.xtext.example.mydsl.tests;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.util.EcoreUtil;
public class WorkspaceUtils {
/**
* Returns the set of all TxtureFiles contained within the given workspace folder that have the given file
* extension.
*
* @param folder
* The folder to search in
* @param fileExtension
* The file extension of the DSL files to look for
* @return The set of TxtureFiles generated from the encountered DSL files
*/
public static Set<IFile> getAllDSLFilesInFolder(final IPath folder, final String fileExtension) {
Set<IFile> resultSet = new HashSet<IFile>();
IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
Set<IResource> resources = new HashSet<IResource>();
getAllTxtureFilesInFolderRec(resources, folder, workspaceRoot, fileExtension);
for (IResource resource : resources) {
IFile file = (IFile) resource;
resultSet.add(file);
}
return resultSet;
}
private static void getAllTxtureFilesInFolderRec(final Set<IResource> resources, final IPath path,
final IWorkspaceRoot root, final String fileExtension) {
IContainer container = root.getContainerForLocation(path);
try {
IResource[] containedResources = container.members();
for (IResource member : containedResources) {
if (member.getName().endsWith(fileExtension)) {
// we've found a file resource that ends with ".move",
// so we add it to our list
resources.add(member);
} else if (member.getType() == IResource.FOLDER) {
// we've found a folder. We need to check its contents for
// ".move" files.
IPath folderPath = member.getLocation();
getAllTxtureFilesInFolderRec(resources, folderPath, root, fileExtension);
}
}
} catch (CoreException e) {
e.printStackTrace();
}
}
/**
* Returns all model elements in the project.<br>
* This method will also resolve cross-references between Xtext DSL files.
*
* @return The set of all model elements in the project.
*/
public static Set<EObject> getModelElements(final Set<IFile> sourceFiles, ResourceSet projectResourceSet) {
for (IFile dslFile : sourceFiles) {
try {
Resource resource = projectResourceSet.getResource(URI.createPlatformResourceURI(dslFile.getFullPath().toString(), true), true);
resource.load(null);
} catch (IOException e) {
e.printStackTrace();
}
}
// resolve all cross-references in the resource set
EcoreUtil.resolveAll(projectResourceSet);
Set<EObject> modelElements = new HashSet<EObject>();
System.out
.println("Gathering model elements from " + projectResourceSet.getResources().size() + " resource(s)");
for (Resource resource : projectResourceSet.getResources()) {
System.out.println("Found " + resource.getContents().size() + " root element(s) in resource "
+ resource.getURI().toString());
modelElements.addAll(resource.getContents());
}
return modelElements;
}
}
package org.xtext.example.mydsl.tests;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;
public class XMIUtils {
/**
* Converts the given {@link EObject} model into its XMI representation.
*
* @param model
* The model to convert
* @return The XMI string representation of the given model
*/
public static String serializeEObjectToXMI(final EObject model, ResourceSet rs) {
Resource resource = rs.createResource(org.eclipse.emf.common.util.URI.createFileURI("temp/model.xmi"));
EcoreUtil.resolveAll(resource);
if (model != null) {
resource.getContents().add(model);
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
resource.save(baos, null);
} catch (IOException ioe) {
ioe.printStackTrace();
}
String modelXMI = baos.toString();
try {
baos.close();
} catch (IOException ioe) {
}
if (model != null) {
resource.getContents().remove(model);
}
try {
resource.delete(null);
} catch (IOException e) {
e.printStackTrace();
}
return modelXMI;
}
/**
* Converts the given String (containing XMI data) to its {@link EObject} representation.
*
* @param xmiContents
* The string containing the XMI to convert
* @return The EObject representation of the XMI data
*/
public static EObject deserializeXMIString(final String xmiContents) {
File tempFile = createTempFile("ModelData", ".xmi", xmiContents);
if (tempFile == null) {
return null;
}
EObject model = deserializeFromXMIFile(tempFile, true);
return model;
}
/**
* Reads the contents of the given XMI file and constructs the contained EObject model.
*
* @param xmiFile
* The file to deserialize
* @return The EObject representation of the XMI contents.
*/
public static EObject deserializeFromXMIFile(final File xmiFile) {
return deserializeFromXMIFile(xmiFile, false);
}
/**
* Reads the contents of the given XMI file and constructs the contained EObject model.
*
* @param xmiFile
* The file to deserialize
* @param deleteResource
* If this is set to <code>true</code>, the resulting EObject will be removed from XMIResource and the
* resource (including the file itself) will be deleted after deserializing the EObject model from it.
* @return The EObject representation of the XMI contents.
*/
public static EObject deserializeFromXMIFile(final File xmiFile, final boolean deleteResource) {
ResourceSet resourceSet = new ResourceSetImpl();
Resource resource = resourceSet.createResource(URI.createFileURI(xmiFile.getAbsolutePath()));
try {
resource.load(null);
} catch (IOException e) {
e.printStackTrace();
return null;
}
EObject model = null;
if (resource.getContents() != null && resource.getContents().size() > 0) {
EcoreUtil.resolveAll(resource);
model = resource.getContents().get(0);
}
if (deleteResource) {
resource.getContents().remove(model);
try {
resource.delete(null);
} catch (IOException e) {
e.printStackTrace();
}
}
return model;
}
/**
* Creates a temporary file with the given name prefix, the given name suffix and the given file contents.
*
* @param namePrefix
* The prefix of the name of the temporary file
* @param nameSuffix
* The suffix of the name of the temporary file
* @param contents
* The contents of the temporary file
* @return The temporary file, as specified, or <code>null</code> if an error occured
*/
public static File createTempFile(final String namePrefix, final String nameSuffix, final String contents) {
File tempFile = null;
FileWriter writer = null;
BufferedWriter bWriter = null;
boolean writtenSuccessfully = false;
try {
tempFile = File.createTempFile(namePrefix, nameSuffix);
writer = new FileWriter(tempFile);
bWriter = new BufferedWriter(writer);
bWriter.write(contents);
bWriter.flush();
writtenSuccessfully = true;
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
if (bWriter != null) {
try {
bWriter.close();
} catch (IOException ioe) {
}
}
if (writer != null) {
try {
writer.close();
} catch (IOException ioe) {
}
}
}
if (!writtenSuccessfully) {
return null;
} else {
return tempFile;
}
}
}
Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Day Job: https://www.everest-systems.com
|
|
| | | | |
Re: XMI and cross references (xtext links) problem [message #1109589 is a reply to message #1109574] |
Sun, 15 September 2013 17:26 |
Alan DW Messages: 119 Registered: March 2012 |
Senior Member |
|
|
Hi,
I must have missed that change. Changed it to:
/**
* Returns all model elements in the project.<br>
* This method will also resolve cross-references between Xtext DSL files.
*
* @return The set of all model elements in the project.
*/
public static Set<EObject> getModelElements(final Set<IFile> sourceFiles, final ResourceSet projectResourceSet) {
for (IFile dslFile : sourceFiles) {
try {
Resource resource = projectResourceSet.getResource(
URI.createPlatformResourceURI(dslFile.getFullPath().toString(), true), true);
resource.load(null);
} catch (IOException e) {
e.printStackTrace();
}
}
// resolve all cross-references in the resource set
EcoreUtil.resolveAll(projectResourceSet);
Set<EObject> modelElements = new HashSet<EObject>();
System.out
.println("Gathering model elements from " + projectResourceSet.getResources().size() + " resource(s)");
for (Resource resource : projectResourceSet.getResources()) {
System.out.println("Found " + resource.getContents().size() + " root element(s) in resource "
+ resource.getURI().toString());
modelElements.addAll(resource.getContents());
}
return modelElements;
}
I just copy-pasted (!) your code (all of it, except for package and import declarations) and only changed the file ending from "mydsl" to "arch", still getting xtextlinks in the output XMI O.o Sorry, I'm really not trying to act dumb, in fact I'm desperately trying to get it to work since... 3am this night with hardly any sleep in between ^^'
Is it possible that the eclipse version, xtext version, emf version or other environment setting can cause this behaviour? I'm running Juno SR1 with Xtext 2.4.1 and EMF SDK v2.9.1.
|
|
| |
Re: XMI and cross references (xtext links) problem [message #1109596 is a reply to message #1109593] |
Sun, 15 September 2013 17:36 |
|
Here is the xmi
?xml version="1.0" encoding="ASCII"?>
<archDSL:ArchFile xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:archDSL="http://www.qe.at/txture/ArchDSL">
<fragments xsi:type="archDSL:Building" name="Unknown" address="unknown"/>
<fragments xsi:type="archDSL:Server" name="GoogleQueryServer" owningCompany="//@fragments.9">
<services xsi:type="archDSL:SoftwareService" name="Search" software="//@fragments.7"/>
</fragments>
<fragments xsi:type="archDSL:Building" name="Redmond" address="Somewhere in Redmond"/>
<fragments xsi:type="archDSL:Company" name="IBM"/>
<fragments xsi:type="archDSL:Company" name="Microsoft" ceo="//@fragments.5" headquarters="//@fragments.2"/>
<fragments xsi:type="archDSL:Person" name="BillGates" firstName="Bill" lastName="Gates" mailAddress="bill.gates@microsoft.com"/>
<fragments xsi:type="archDSL:Company" name="Canonical"/>
<fragments xsi:type="archDSL:Application" name="GoogleSearch" vendor="//@fragments.9" productName="Google Search"/>
<fragments xsi:type="archDSL:Company" name="Apache"/>
<fragments xsi:type="archDSL:Company" name="Google"/>
<fragments xsi:type="archDSL:Person" name="Unknown" firstName="Unknown" lastName="Unknown" mailAddress="unknown"/>
<fragments xsi:type="archDSL:Application" name="EclipseJuno" vendor="//@fragments.3" productName="Eclipse Juno" version="4.2"/>
<fragments xsi:type="archDSL:Building" name="WallStreet66" address="66 Wall-Street, NY">
<rooms name="Room5A"/>
<rooms name="Room3B"/>
</fragments>
<fragments xsi:type="archDSL:OperatingSystem" name="WindowsXP" vendor="//@fragments.4" productName="Windows XP" version="3.1.2"/>
<fragments xsi:type="archDSL:Server" name="MyMailServer" owningCompany="//@fragments.19" location="//@fragments.12/@rooms.0">
<systemSpecs operatingSystem="//@fragments.18" cpu="Intel Core2Duo" vendor="//@fragments.4" deviceName="Some Server">
<ram amount="256.0" unit="MB"/>
<hdd amount="5.0" unit="GB"/>
</systemSpecs>
<serverTypes>internal</serverTypes>
<services xsi:type="archDSL:SoftwareService" name="tomcat" portID="8080" software="//@fragments.16"/>
<services xsi:type="archDSL:SoftwareService" name="eclipse" url="http://192.168.0.1/myEclipse?runRemoteWorkbench" visibility="private" software="//@fragments.11"/>
<services xsi:type="archDSL:ProxyService" name="search" portID="5555" proxyTarget="//@fragments.1/@services.0"/>
</fragments>
<fragments xsi:type="archDSL:OperatingSystem" name="Ubuntu13_04" vendor="//@fragments.6" productName="Ubuntu" version="13.04"/>
<fragments xsi:type="archDSL:Application" name="Tomcat" vendor="//@fragments.8" productName="Tomcat" version="1.0.0"/>
<fragments xsi:type="archDSL:Person" name="JohnDoe" firstName="John" lastName="Doe" mailAddress="johnDoe@someCompany.com"/>
<fragments xsi:type="archDSL:OperatingSystem" name="Windows7" vendor="//@fragments.4" productName="Windows 7" version="1.0.0"/>
<fragments xsi:type="archDSL:Company" name="MyCompany" ceo="//@fragments.17" cio="//@fragments.17" headquarters="//@fragments.12"/>
</archDSL:ArchFile>
Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Day Job: https://www.everest-systems.com
|
|
| |
Re: XMI and cross references (xtext links) problem [message #1111748 is a reply to message #1109602] |
Wed, 18 September 2013 17:24 |
Alan DW Messages: 119 Registered: March 2012 |
Senior Member |
|
|
Hi,
after a couple of days, a good read in the EMF Bible about resources and a lot of experimenting, I'm still stuck with this issue.
I've downloaded the Eclipse Distribution (Win x64) from the Xtext site that comes bundled with Xtext 2.4.3, created a new workspace, created the language from scratch (copy-pasting the grammar) and copy-pasted your Code into my project.
Then I ran the Unit Test which you executed successfully - and it failed miserably as it has always done for me. It is still detecting xtextlinks in my output XMI.
So just to verify that I haven't gone totally crazy, I have re-packaged the test classes and attached them to this post. If anyone has an Eclipse instance with the latest version of Xtext, please run the unit Test provided in "TestProject/main/SampleTest.java" and make sure that the (also included) "ArchitectureTest" project is in your JUnit workspace and please tell me if it works for you or not.
SIDE NOTE: I've done quite a few experiments to find out just what the difference between using and not using the StandaloneSetup actually *is*. The EPackage registration seems equivalent. The only one that I could detect is that with the StandaloneSetup, the following code:
IResourceServiceProvider.Registry.INSTANCE.getExtensionToFactoryMap().get("mydsl")
will return an instance of "IResourceServiceProvider", where as without the standalone setup involved, it will return a "ResourceServiceProviderDescriptor", which most likely is just an indirection to the actual service provider to achieve lazy loading (not sure, though).
I tried to figure out what the StandaloneSetup does and from what I can tell by looking at the generated code without knowing too much about Google Guice, is that all the [DSL]StandaloneSetup.doSetup() actually *does* is create an Injector (which gets discarded afterwards if not stored by the setup caller) and to execute this:
public void register(Injector injector) {
if (!EPackage.Registry.INSTANCE.containsKey("http://www.xtext.org/example/mydsl/MyDsl")) {
EPackage.Registry.INSTANCE.put("http://www.xtext.org/example/mydsl/MyDsl", org.xtext.example.mydsl.myDsl.MyDslPackage.eINSTANCE);
}
org.eclipse.xtext.resource.IResourceFactory resourceFactory = injector.getInstance(org.eclipse.xtext.resource.IResourceFactory.class);
org.eclipse.xtext.resource.IResourceServiceProvider serviceProvider = injector.getInstance(org.eclipse.xtext.resource.IResourceServiceProvider.class);
Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().put("mydsl", resourceFactory);
org.eclipse.xtext.resource.IResourceServiceProvider.Registry.INSTANCE.getExtensionToFactoryMap().put("mydsl", serviceProvider);
}
... and to be quite honest, I don't see how this code could end up doing any harm to the Eclipse application. To me, all that it does is to make a failing unit test pass perfectly. But maybe I'm greatly mistaken here.
I really don't like be so obtrusive about this issue (deeply sorry for that), but my entire master thesis really *does* depend on exactly this crucial step and I'm totally stumped - no idea what else I could try.
Thanks,
Alan
[Updated on: Wed, 18 September 2013 17:28] Report message to a moderator
|
|
| | |
Re: XMI and cross references (xtext links) problem [message #1111916 is a reply to message #1111888] |
Wed, 18 September 2013 22:51 |
Alan DW Messages: 119 Registered: March 2012 |
Senior Member |
|
|
Hi,
I just realized something. I think I can explain now why it works for you but it does not work for me.
I was just assembling a minimal working example (with a much simpler DSL) to file a bug report. Then I ran the test for the first time and (much to my surprise) it worked, no StandaloneSetup involved. But then I ran it for a second time (same code, same test project), and then it failed. It turned out that every successive JUnit test run after the first fails. Apparently, Eclipse can't manage to properly shut down the workspace in the JUnit test and has some metadata remaining that conflicts with the EMF resources.
If I clean the workspace completely (including metadata) and re-create the test project, the test runs green again, but only once. Afterwards it fails (output from the Xtext logger):
ERROR org.eclipse.xtext.linking.lazy.LazyLinkingResource - resolution of uriFragment 'xtextLink_::0.0.0::1::/6' failed.
Also, when shutting down the workbench (upon JUnit test termination) I get a lot of these guys here:
[Worker-0] ERROR org.eclipse.emf.ecore.xcore.ui.XcoreExecutableExtensionFactory - com.google.inject.ProvisionException: Guice provision errors:
1) Error in custom provider, java.lang.IllegalStateException: The bundle has not been started!
Full stack trace of this error:
Toggle Spoiler at org.eclipse.xtext.service.MethodBasedModule.configure(MethodBasedModule.java:73)
while locating org.eclipse.xtext.ui.resource.IStorage2UriMapper
for field at org.eclipse.xtext.ui.editor.WorkspaceEncodingProvider.storage2UriMapper(Unknown Source)
at org.eclipse.xtext.ui.editor.WorkspaceEncodingProvider.class(Unknown Source)
while locating org.eclipse.xtext.ui.editor.WorkspaceEncodingProvider
while locating org.eclipse.xtext.parser.IEncodingProvider annotated with @org.eclipse.xtext.service.DispatchingProvider$Ui()
for field at org.eclipse.xtext.service.DispatchingProvider.uiBinding(Unknown Source)
while locating org.eclipse.xtext.service.DefaultRuntimeModule$IEncodingProviderDispatcher
while locating org.eclipse.xtext.parser.IEncodingProvider
for field at org.eclipse.xtext.resource.impl.DefaultResourceServiceProvider.encodingProvider(Unknown Source)
while locating org.eclipse.xtext.resource.impl.DefaultResourceServiceProvider
while locating org.eclipse.xtext.resource.IResourceServiceProvider
for field at org.eclipse.xtext.builder.BuilderParticipant.resourceServiceProvider(Unknown Source)
while locating org.eclipse.emf.ecore.xcore.ui.builder.XcoreBuildParticipant
while locating org.eclipse.xtext.builder.IXtextBuilderParticipant
Caused by: java.lang.IllegalStateException: The bundle has not been started!
at org.eclipse.xtext.ui.shared.Access$InternalProvider.get(Access.java:39)
at com.google.inject.internal.InternalFactoryToProviderAdapter.get(InternalFactoryToProviderAdapter.java:40)
at com.google.inject.internal.SingleFieldInjector.inject(SingleFieldInjector.java:53)
at com.google.inject.internal.MembersInjectorImpl.injectMembers(MembersInjectorImpl.java:110)
at com.google.inject.internal.ConstructorInjector.construct(ConstructorInjector.java:94)
at com.google.inject.internal.ConstructorBindingImpl$Factory.get(ConstructorBindingImpl.java:254)
at com.google.inject.internal.ProviderToInternalFactoryAdapter$1.call(ProviderToInternalFactoryAdapter.java:46)
at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1031)
at com.google.inject.internal.ProviderToInternalFactoryAdapter.get(ProviderToInternalFactoryAdapter.java:40)
at com.google.inject.Scopes$1$1.get(Scopes.java:65)
at com.google.inject.internal.InternalFactoryToProviderAdapter.get(InternalFactoryToProviderAdapter.java:40)
at com.google.inject.internal.FactoryProxy.get(FactoryProxy.java:54)
at com.google.inject.internal.SingleFieldInjector.inject(SingleFieldInjector.java:53)
at com.google.inject.internal.MembersInjectorImpl.injectMembers(MembersInjectorImpl.java:110)
at com.google.inject.internal.ConstructorInjector.construct(ConstructorInjector.java:94)
at com.google.inject.internal.ConstructorBindingImpl$Factory.get(ConstructorBindingImpl.java:254)
at com.google.inject.internal.BoundProviderFactory.get(BoundProviderFactory.java:53)
at com.google.inject.internal.SingleFieldInjector.inject(SingleFieldInjector.java:53)
at com.google.inject.internal.MembersInjectorImpl.injectMembers(MembersInjectorImpl.java:110)
at com.google.inject.internal.ConstructorInjector.construct(ConstructorInjector.java:94)
at com.google.inject.internal.ConstructorBindingImpl$Factory.get(ConstructorBindingImpl.java:254)
at com.google.inject.internal.InjectorImpl$3.get(InjectorImpl.java:737)
at com.google.inject.internal.SingleFieldInjector.inject(SingleFieldInjector.java:53)
at com.google.inject.internal.MembersInjectorImpl.injectMembers(MembersInjectorImpl.java:110)
at com.google.inject.internal.ConstructorInjector.construct(ConstructorInjector.java:94)
at com.google.inject.internal.ConstructorBindingImpl$Factory.get(ConstructorBindingImpl.java:254)
at com.google.inject.internal.FactoryProxy.get(FactoryProxy.java:54)
at com.google.inject.internal.InjectorImpl$4$1.call(InjectorImpl.java:978)
at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1024)
at com.google.inject.internal.InjectorImpl$4.get(InjectorImpl.java:974)
at com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1013)
at org.eclipse.xtext.ui.guice.AbstractGuiceAwareExecutableExtensionFactory.create(AbstractGuiceAwareExecutableExtensionFactory.java:50)
at org.eclipse.core.internal.registry.ConfigurationElement.createExecutableExtension(ConfigurationElement.java:262)
at org.eclipse.core.internal.registry.ConfigurationElementHandle.createExecutableExtension(ConfigurationElementHandle.java:55)
at org.eclipse.xtext.builder.impl.RegistryBuilderParticipant$BuilderParticipantReader.readElement(RegistryBuilderParticipant.java:102)
at org.eclipse.emf.ecore.plugin.RegistryReader.internalReadElement(RegistryReader.java:117)
at org.eclipse.emf.ecore.plugin.RegistryReader.readRegistry(RegistryReader.java:87)
at org.eclipse.xtext.builder.impl.RegistryBuilderParticipant.initParticipants(RegistryBuilderParticipant.java:80)
at org.eclipse.xtext.builder.impl.RegistryBuilderParticipant.getParticipants(RegistryBuilderParticipant.java:67)
at org.eclipse.xtext.builder.impl.RegistryBuilderParticipant.build(RegistryBuilderParticipant.java:52)
at org.eclipse.xtext.builder.impl.XtextBuilder.doBuild(XtextBuilder.java:186)
at org.eclipse.xtext.builder.impl.XtextBuilder.fullBuild(XtextBuilder.java:210)
at org.eclipse.xtext.builder.impl.XtextBuilder.build(XtextBuilder.java:89)
at org.eclipse.core.internal.events.BuildManager$2.run(BuildManager.java:726)
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:199)
at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:321)
at org.eclipse.core.internal.events.BuildManager.build(BuildManager.java:396)
at org.eclipse.core.internal.resources.Project$1.run(Project.java:618)
at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2345)
at org.eclipse.core.internal.resources.Project.internalBuild(Project.java:597)
at org.eclipse.core.internal.resources.Project.build(Project.java:124)
at org.eclipse.xtext.builder.impl.BuildScheduler$BuildJob.run(BuildScheduler.java:164)
at org.eclipse.core.internal.jobs.Worker.run(Worker.java:53)
I think "has not been started" is to say "has terminated prematurely" here.
EDIT: Waiting for the job manager to finish all its jobs in a tear-down method gets rid of this error. However, the overall problem of the test working only once still remains.
This is definitly weird, and not expected behaviour. Now I'm not sure if:
- My JUnit test code is wrong, not shutting down the workbench correctly or
- There is a bug in the eclipse platform and/or JUnit framework integration or
- There is a bug in Xtext and its metadata handling
In any case, something is fishy here.
EDIT: Another thing just came to my mind. By adding the EObjects parsed from the DSL files to a common root model and putting this common root model into an XMIResource, aren't we effectively relocating all of the EObjects to new resources, since the new root object has a containment reference to its newly assigned children? I need to check that.
[Updated on: Wed, 18 September 2013 23:15] Report message to a moderator
|
|
| |
Re: XMI and cross references (xtext links) problem [message #1112226 is a reply to message #1112090] |
Thu, 19 September 2013 09:20 |
Alan DW Messages: 119 Registered: March 2012 |
Senior Member |
|
|
Christian Dietrich wrote on Thu, 19 September 2013 01:38Hnmm strange. Did you try to do a clean build on the model project in
the beginning of the test. I thing you may need a built workspace
I-don't-believe-it!
Guess what: that simple thing totally did the trick
@Before
public void setUp() {
IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
IProject project = workspaceRoot.getProject("ArchitectureTest");
Assert.assertTrue(project.exists());
try {
project.build(IncrementalProjectBuilder.CLEAN_BUILD,
new NullProgressMonitor());
} catch (CoreException e) {
e.printStackTrace();
}
}
After almost a week of sleepless nights and headache because of this, the solution turns out to be so so simple -.- However, it does not *really* make all that much sense to me because I did nothing to "break" an existing workspace build, now did I? Well, maybe this is some Eclipse-specific thing. Either way, it works!
Thank you, Christian, for seeing this through with me. I don't know what I would have done without your help. It is much appreciated. If you want to, I can add you to the "acknowledgements" section of my master thesis once it's all done
Thanks a LOT!
Alan
|
|
|
Goto Forum:
Current Time: Sun Nov 10 19:46:14 GMT 2024
Powered by FUDForum. Page generated in 0.06445 seconds
|