Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » XMI and cross references (xtext links) problem
XMI and cross references (xtext links) problem [message #1109140] Sun, 15 September 2013 00:35 Go to next message
Alan DW is currently offline Alan DWFriend
Messages: 108
Registered: March 2012
Senior Member
Hello everyone,

I'm developing an eclipse plug-in which uses Xtext. The instance model should be serialized to XMI and sent to a remote server for further processing. However, if I try to serialize the model right away, it contains local file references and "xtext links" such as this one:

xtextLink_::0.0.0::1::/15

My problem is very much related to this thread:

http://www.eclipse.org/forums/index.php/t/251191/

but in contrast to Ioana, I cannot use StandaloneSetup because I'm running the code inside an Eclipse application. I already tried to use both "EcoreUtil#resolveAll(model)" and "EcoreUtil#resolveAll(modelResource)" before serializing to XMI - both worked without throwing errors, but neither got rid of the xtext links, which give me a lot of headache on the remote server. Basically I want to achieve the same thing as Ioana, just from inside Eclipse instead of a standalone Java application.


Any hints on what I might be missing or doing wrong?


Thanks,


Alan
Re: XMI and cross references (xtext links) problem [message #1109331 is a reply to message #1109140] Sun, 15 September 2013 08:01 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 6546
Registered: July 2009
Senior Member
Hi,

can you share reproducable code
(grammar, sample model, handler, plugin.xml ...)
Re: XMI and cross references (xtext links) problem [message #1109371 is a reply to message #1109331] Sun, 15 September 2013 09:30 Go to previous messageGo to next message
Alan DW is currently offline Alan DWFriend
Messages: 108
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:



  1. Scan a given Eclipse Project in the workspace for DSL files (by file extension)
  2. Load the contained EObjects, resolving cross-file-references and maintaining referential integrity
  3. Create a single ArchFile container which holds all of the fragments
  4. Serialize that ArchFile to XMI
  5. 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 #1109392 is a reply to message #1109371] Sun, 15 September 2013 10:12 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 6546
Registered: July 2009
Senior Member
Hi,

i guess the problem is: if the source and the target resource set is not the same the system cannot keeps track
of the references.

unfortuately you did not share code that i can simply run so i cannot try myself.

btw to load existing resources simply call:

resourceset.getResource.

~Christian
Re: XMI and cross references (xtext links) problem [message #1109395 is a reply to message #1109392] Sun, 15 September 2013 10:16 Go to previous messageGo to next message
Alan DW is currently offline Alan DWFriend
Messages: 108
Registered: March 2012
Senior Member
Hi,

I'm currently preparing a small sample plug-in with the full required source for you. Please give me a couple of minutes for that.

Thanks,


Alan
Re: XMI and cross references (xtext links) problem [message #1109402 is a reply to message #1109395] Sun, 15 September 2013 10:33 Go to previous messageGo to next message
Alan DW is currently offline Alan DWFriend
Messages: 108
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 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 6546
Registered: July 2009
Senior Member
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;
		}
	}

}
Re: XMI and cross references (xtext links) problem [message #1109554 is a reply to message #1109441] Sun, 15 September 2013 16:13 Go to previous messageGo to next message
Alan DW is currently offline Alan DWFriend
Messages: 108
Registered: March 2012
Senior Member
Hi Christian,

thanks *a lot* for your help. Your code provided a lot of insights for me - just had a look at the Xtext homepage documentation page, loads of stuff have changed since I've last visited it.

Regarding your unit test version: for me, it still returns xtextlinks in the XMI... all I have changed from your code was adapting it to my DSL. Is it working for you in the way you posted it?


Thanks,

Alan
Re: XMI and cross references (xtext links) problem [message #1109557 is a reply to message #1109554] Sun, 15 September 2013 16:20 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 6546
Registered: July 2009
Senior Member
Yes no Xtext links can you please share a complete zip once more (
incl. Ui project)

--
Need training, onsite consulting or any other kind of help for Xtext?
Go visit http://xtext.itemis.com or send a mail to xtext at itemis dot de
Re: XMI and cross references (xtext links) problem [message #1109565 is a reply to message #1109557] Sun, 15 September 2013 16:35 Go to previous messageGo to next message
Alan DW is currently offline Alan DWFriend
Messages: 108
Registered: March 2012
Senior Member
Sure, here it is Smile
I've created a second Test in the same location as the first one, called "ArchTest2", which closely follows your implementation. I tried to make sure not to overloook anything, I hope I did not, that would be embarassing Embarrassed

Sorry I can't attach it to this post, as it exceeds the maximum file size (2MB) by a small amount.

You can get it here from my dropbox: https://www.dropbox.com/s/htuyelyxwz68wu8/ArchJUnitTest.zip

I hope the link is working for you. Sorry for the inconvenience.
Re: XMI and cross references (xtext links) problem [message #1109574 is a reply to message #1109565] Sun, 15 September 2013 16:53 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 6546
Registered: July 2009
Senior Member
HI,

you have still the wrong utils.WorkspaceUtils.getModelElements(Set<IFile>, ResourceSet)
Re: XMI and cross references (xtext links) problem [message #1109589 is a reply to message #1109574] Sun, 15 September 2013 17:26 Go to previous messageGo to next message
Alan DW is currently offline Alan DWFriend
Messages: 108
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 #1109593 is a reply to message #1109589] Sun, 15 September 2013 17:32 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 6546
Registered: July 2009
Senior Member
hmm if i take this method to your code the test passes. and text xtext version might not be a problem but i can only test with 2.4.3
Re: XMI and cross references (xtext links) problem [message #1109596 is a reply to message #1109593] Sun, 15 September 2013 17:36 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 6546
Registered: July 2009
Senior Member
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>
Re: XMI and cross references (xtext links) problem [message #1109602 is a reply to message #1109596] Sun, 15 September 2013 17:48 Go to previous messageGo to next message
Alan DW is currently offline Alan DWFriend
Messages: 108
Registered: March 2012
Senior Member
But how can this be? I'm using that very same code! Btw, I get the same XMI if I use the StandaloneSetup ^_^'

What on earth is going on here? It's always creepy if the same code does different things on different machines, but this is just plain crazy xD

I'll try updating to Xtext 2.4.3. Maybe it helps.

And thanks for your patience Smile
Re: XMI and cross references (xtext links) problem [message #1111748 is a reply to message #1109602] Wed, 18 September 2013 17:24 Go to previous messageGo to next message
Alan DW is currently offline Alan DWFriend
Messages: 108
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 #1111778 is a reply to message #1111748] Wed, 18 September 2013 18:25 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 6546
Registered: July 2009
Senior Member
HI,

calling standalone setups in eclipse will disturb registries.
and your test ist still green.
i use full eclipse from http://www.eclipse.org/Xtext/download.html (on mac)
Re: XMI and cross references (xtext links) problem [message #1111888 is a reply to message #1111778] Wed, 18 September 2013 21:49 Go to previous messageGo to next message
Alan DW is currently offline Alan DWFriend
Messages: 108
Registered: March 2012
Senior Member
Hi,

I use the same Eclipse (just for another OS). I just tried it on Linux (64bit), and it is the same problem as on Windows. Is it possible that we have encountered an Xtext bug here, since we are both running the same code?


Alan
Re: XMI and cross references (xtext links) problem [message #1111916 is a reply to message #1111888] Wed, 18 September 2013 22:51 Go to previous messageGo to next message
Alan DW is currently offline Alan DWFriend
Messages: 108
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


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 #1112090 is a reply to message #1111916] Thu, 19 September 2013 05:38 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 6546
Registered: July 2009
Senior Member
Hnmm 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

--
Need training, onsite consulting or any other kind of help for Xtext?
Go visit http://xtext.itemis.com or send a mail to xtext at itemis dot de
Re: XMI and cross references (xtext links) problem [message #1112226 is a reply to message #1112090] Thu, 19 September 2013 09:20 Go to previous message
Alan DW is currently offline Alan DWFriend
Messages: 108
Registered: March 2012
Senior Member
Christian Dietrich wrote on Thu, 19 September 2013 01:38
Hnmm 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 Shocked

	@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 Wink


Thanks a LOT!


Alan
Previous Topic:5 Minute Tutorial doesnt work
Next Topic:Utilize Errors/Warnings to add ControlDecorators to SWT widgets
Goto Forum:
  


Current Time: Fri Dec 19 10:15:59 GMT 2014

Powered by FUDForum. Page generated in 0.02428 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software