Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » cross-file reference and link in xtext
cross-file reference and link in xtext [message #1716632] Mon, 07 December 2015 02:10 Go to next message
Dongho Yang is currently offline Dongho YangFriend
Messages: 10
Registered: August 2015
Junior Member
I created a new DSL by using xtext as follows. (Actually I will access the DSL on RCP application.)
grammar org.xtext.example.mydsl.MyDsl with      org.eclipse.xtext.common.Terminals

generate myDsl "...www.xtext.org/example/mydsl/MyDsl"


Configuration:
components+=(Component)*;

Component:
'Component' name=ID
'{'
(('display' display=STRING) &
('dependency' dependency=[Component|ID])?)
'}'
 ;
I have two files: sample1.mydsl

 Component comp1 {
     display "comp1"
     children comp2
 }
sampl2.mydsl

 Component comp2 {
      display "comp2"
 }


On RCP Application, I will compose a tree view with the Configuration model. But when I get comp2 object from getChildren() method of comp1 object, sometimes I couldn't get the comp2 object exactly.
I loaded the model data as below:

    private List<ConfigurationItem> itemList;

    void loadData() {
    project =               ResourcesPlugin.getWorkspace().getRoot().getProject("test");

    XtextResourceSet resourceSet = (XtextResourceSet) injector
        .getInstance(XtextResourceSetProvider.class)
        .get(project);
    resourceSet.addLoadOption(XtextResource.OPTION_RESOLVE_ALL, Boolean.TRUE);

    IFile[] samples = findFiles(resources);

    List<Resource> resourceList = new ArrayList<Resource>();
    for (IFile sample : samples) {
        Resource resourceSample = resourceSet.getResource(
                URI.createURI(sample.getLocationURI().toString(), true), true);
        resourceList.add(resourceSample);
    }

    for (Resource resource : resourceList) {
        System.out.println("resource = " + resource.toString());
        try {
            resource.load(null);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        EcoreUtil.resolveAll(resource);
    }

    // add all to configuration item list
    for (Resource rc : resourceList) {
        Configuration config = (Configuration) rc.getContents().get(0);
        itemList.addAll(config.getConfigurationItems().toArray(new ConfigurationItem[config.getConfigurationItems().size()]));
    }
}


test code

for (ConfigurationItem item : itemList) {
   if (item.getName().equals("comp1") {
      Component[] comps = item.getChildren();
      for (Component comp : comps) {
         if (comp != null) {
             System.out.println("comp display : " + comp.getDisplay());
         }
      }
  }
}

result
comp display : null


I expected the result to be "comp display : comp2".

But Sometimes the result is "comp display : comp2"

and sometimes the result is "comp display : null"

I think it is because of the lazy linking of xtext.

How can always I get correct result -> "comp display : comp2"?

I Hope someone can help me solve it. Thanks.


[Updated on: Mon, 07 December 2015 03:39]

Report message to a moderator

Re: cross-file reference and link in xtext [message #1716637 is a reply to message #1716632] Mon, 07 December 2015 05:35 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14669
Registered: July 2009
Senior Member
Do you at some point call yourdslstandalonesetup from your code. You should never do that in an eclipse environment http://koehnlein.blogspot.de/2012/11/xtext-tip-how-do-i-get-guice-injector.html?m=1

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: cross-file reference and link in xtext [message #1716638 is a reply to message #1716637] Mon, 07 December 2015 05:39 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14669
Registered: July 2009
Senior Member
And in eclipse you should load the resources by their platform resource uri

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: cross-file reference and link in xtext [message #1716639 is a reply to message #1716638] Mon, 07 December 2015 05:52 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14669
Registered: July 2009
Senior Member
And you should call the resolve after the for loop

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: cross-file reference and link in xtext [message #1716640 is a reply to message #1716637] Mon, 07 December 2015 06:03 Go to previous messageGo to next message
Dongho Yang is currently offline Dongho YangFriend
Messages: 10
Registered: August 2015
Junior Member
Hi Christian,

Because I use xtext models in RCP Application, I don't use the mydslstandalone. Instead, I created a injector as below and used it when it load models.
final private static Injector injector = ConfigDSLActivator.getInstance().getInjector("com.xxx.kcdsl.ConfigDSL");

public void loadData() {
XtextResourceSet resourceSet = (XtextResourceSet) injector
			    .getInstance(XtextResourceSetProvider.class)
			    .get(project);
		resourceSet.addLoadOption(XtextResource.OPTION_RESOLVE_ALL, Boolean.TRUE);
		
}



I don't know what i did wrong.

[Updated on: Mon, 07 December 2015 06:12]

Report message to a moderator

Re: cross-file reference and link in xtext [message #1716642 is a reply to message #1716640] Mon, 07 December 2015 06:11 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14669
Registered: July 2009
Senior Member
Yes then move the resolveall(resourceset) after the load loop

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: cross-file reference and link in xtext [message #1716643 is a reply to message #1716642] Mon, 07 December 2015 06:37 Go to previous messageGo to next message
Dongho Yang is currently offline Dongho YangFriend
Messages: 10
Registered: August 2015
Junior Member
Thanx Christian.
As you said, I Modified codes as below.


	                IFile[] samples = findFiles(resources);
	
			List<Resource> resourceList = new ArrayList<Resource>();
			for (IFile sample : samples) {
				Resource resourceSample = resourceSet.getResource(
						URI.createURI(sample.getLocationURI().toString(), true), true);
				resourceList.add(resourceSample);
			}
			
			for (Resource resource : resourceList) {
				try {
					resource.load(null);
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			
			EcoreUtil.resolveAll(resourceSet);
			// add all to configuration item list
			for (Resource rc : resourceList) {
				Configuration config = (Configuration) rc.getContents().get(0);
				itemList.addAll(config.getConfigurationItems().toArray(new ConfigurationItem[config.getConfigurationItems().size()]));
			}
			



but The test code still returns "comp display : null".

[Updated on: Mon, 07 December 2015 06:39]

Report message to a moderator

Re: cross-file reference and link in xtext [message #1716644 is a reply to message #1716643] Mon, 07 December 2015 06:55 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14669
Registered: July 2009
Senior Member
Can you please share a complete reproduceable example

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: cross-file reference and link in xtext [message #1716647 is a reply to message #1716644] Mon, 07 December 2015 07:56 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14669
Registered: July 2009
Senior Member
P.S: and use URI.createPlatformResourceURI(iFile.getFullPath().toString(), true) as decribed here https://wiki.eclipse.org/EMF/FAQ#How_do_I_map_between_an_EMF_Resource_and_an_Eclipse_IFile.3F

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: cross-file reference and link in xtext [message #1716664 is a reply to message #1716647] Mon, 07 December 2015 10:58 Go to previous messageGo to next message
Dongho Yang is currently offline Dongho YangFriend
Messages: 10
Registered: August 2015
Junior Member
Dear Christian.
Thanx. Still returns "comp display : null" message. It seems to be a problem with resolving cross-file reference. but I can't solve the problem.

[Updated on: Mon, 07 December 2015 10:59]

Report message to a moderator

Re: cross-file reference and link in xtext [message #1716665 is a reply to message #1716664] Mon, 07 December 2015 11:25 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14669
Registered: July 2009
Senior Member
As i sais.i need your code to analyze

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: cross-file reference and link in xtext [message #1716817 is a reply to message #1716665] Tue, 08 December 2015 11:44 Go to previous messageGo to next message
Dongho Yang is currently offline Dongho YangFriend
Messages: 10
Registered: August 2015
Junior Member
I made up a sample for analysis.
Please check below.

1. The code below is my sample test code. I call
new SampleConfigLoadOperation3().run(monitor); on my RCP Application.

SampleConfigLoadOperation3.java

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.common.util.URI;
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.jface.operation.IRunnableWithProgress;

import com.mdstec.ide.kcdsl.ConfigDSL.ConfigurationItem;
import com.mdstec.ide.kcdsl.ConfigDSL.Configuration;


public class SampleConfigLoadOperation3 implements IRunnableWithProgress {

	// Progress message
	final String loadConfigTaskBeginMsg = "load configuration.";

	IProject project;

	DataListener dataListener;

	/**
	 * Constructor for project configuration object
	 * 
	 * @param prjConfig
	 *            the project configuration object
	 */
	public SampleConfigLoadOperation3() {
		// TODO Auto-generated constructor stub
	}


    public SampleConfigLoadOperation3(IProject project, DataListener listner) {
		// TODO Auto-generated constructor stub
    	this.project = project;
    	this.dataListener = listner;

	}
	@Override
	public void run(IProgressMonitor monitor) throws InvocationTargetException,
			InterruptedException {
		// TODO Auto-generated method stub
		if (monitor != null) {
			monitor.beginTask(loadConfigTaskBeginMsg, IProgressMonitor.UNKNOWN);
		}

		try {
			loadConfigData(monitor);
		} catch (Exception e) {
			throw new InvocationTargetException(e, "Loading error" + ": "
					+ e.getMessage());
		} finally {
			if (monitor != null) {
				monitor.done();
			}
		}

		if (monitor != null) {
			if (monitor.isCanceled()) {
				throw new InterruptedException("Cancel loading");
			}
		}

	}

	private void loadConfigData(IProgressMonitor monitor) {
		IWorkspace workspace = ResourcesPlugin.getWorkspace();
		IWorkspaceRoot workspaceRoot = workspace.getRoot();
		project  = workspaceRoot.getProject("testproject");
		IFolder sampleFolder = project.getFolder("data");
		//at this point, no resources have been created
		try {
			if (!project.exists())
				project.create(null);
			if (!project.isOpen()) 
				project.open(null);
		} catch (CoreException e2) {
			// TODO Auto-generated catch block
			e2.printStackTrace();
		}
	
		if (!sampleFolder.exists()) {
			try {
				sampleFolder.create(IResource.NONE, true, null);
			} catch (CoreException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		copyDataFileToProject("sample1.cdl", "data");
		copyDataFileToProject("sample2.cdl", "data");
//		copyDataFileToProject("sample3.cdl", "data");

		ResourceSet resourceSet = new ResourceSetImpl();
		
		IResource[] resources = null;
		try {
			resources = sampleFolder.members();
		} catch (CoreException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		if (resources != null) {
			IFile[] samples = findFiles(resources);
			List<Resource> resourceList = new ArrayList<Resource>();
			for (IFile sample : samples) {
				Resource resourceSample = resourceSet.getResource(
						URI.createURI(sample.getFullPath().toString()), true);

				resourceList.add(resourceSample);
			}

			// add all to configuration item list
			List<ConfigurationItem> configItemList = new ArrayList<ConfigurationItem>();
			for (Resource rc : resourceList) {
				Configuration config = (Configuration) rc
						.getContents().get(0);
				configItemList.addAll(config.getConfigurationItems());
			}

			// root model
			List<ConfigurationItem> rootItemList = new ArrayList<ConfigurationItem>();
			// set root list in configuration item list
			for (int i = 0; i < configItemList.size(); i++) {
				ConfigurationItem item = configItemList.get(i);
				if (item instanceof com.mdstec.ide.kcdsl.ConfigDSL.Package) {
					if (((com.mdstec.ide.kcdsl.ConfigDSL.Package) item)
							.isIsRoot()) {
						rootItemList.add(item);
					}
				}
			}

			// set parents
			for (int i = 0; i < rootItemList.size(); i++) {
				ConfigurationItem root = rootItemList.get(i);
				ConfigurationItem[] children = (ConfigurationItem[]) root
						.getChildren().toArray();
				setParent(children, root);

			}

			System.out.println("root size = " + rootItemList.size());
			for (ConfigurationItem item : rootItemList) {
				findChildren(item);
			}


		}
	}

	private void copyDataFileToProject(String fileName, String prjDir) {
		// TODO Auto-generated method stub
		File file = new File("C:/test/data/" + fileName);
		URL sourceURL = null;
		try {
			sourceURL = file.toURL(); // using .toURI().toURL()
										// fails,
										// due to
										// spaces substitution

		} catch (MalformedURLException e) {
			e.printStackTrace();
		}
		InputStream in = null;
		try {
			in = sourceURL.openStream();
		} catch (IOException e) {
			e.printStackTrace();
		}
		IFile iFile = project.getFile(prjDir + "/" + fileName);
		if (!iFile.exists()) {
			try {
				iFile.create(in, true, null);
				iFile.refreshLocal(IResource.DEPTH_ONE, null);
			} catch (CoreException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	}

	private void findChildren(ConfigurationItem item) {
		// TODO Auto-generated method stub
		
		ConfigurationItem[] children = (ConfigurationItem[]) item.getChildren()
				.toArray();
		if (children != null && children.length > 0) {
			for (ConfigurationItem child : children) {
				System.out.println("child name of " + item.getName() + " : "
						+ child.getName());
				findChildren(child);
			}
		}
	}

	private void setParent(ConfigurationItem[] children,
			ConfigurationItem parent) {
		// TODO Auto-generated method stub
		if (children != null && children.length > 0) {
			for (ConfigurationItem child : children) {
				child.setParent(parent);
				setParent((ConfigurationItem[]) child.getChildren().toArray(),
						child);
			}
		}
	}

	private IFile[] findFiles(IResource[] resources) {
		List<IFile> fileList = new ArrayList<IFile>();
		find(resources, fileList);
		return fileList.toArray(new IFile[fileList.size()]);
	}

	private void find(IResource[] resources, List<IFile> fileList) {
		// TODO Auto-generated method stub

		if (resources != null && resources.length > 0) {
			for (IResource res : resources) {
				if (res instanceof IFile) {
					fileList.add((IFile) res);
				} else if (res instanceof IFolder) {
					IResource[] reses;
					try {
						reses = ((IFolder) res).members();
						find(reses, fileList);
					} catch (CoreException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}

				}
			}
		}
	}

}





2. I defined my DSL using xtext as below and generated the models and parser.

ConfigDSL.xtext



generate ConfigDSL "............."

Configuration:
	((configurationItems+=ConfigurationItem)*
;

ConfigurationItem:
	Package | Component
;

Package:
	'Package' name=ID
	'{'
		(('display' display=STRING) &
		('description' description=STRING)? &
		('children' children += [ConfigurationItem|ID] (',' children += [ConfigurationItem|ID])*)?  &
		('parent' parent = [ConfigurationItem|ID])? &
		('isRoot' isRoot=BOOLEAN)?
		)
	'}'
;

Component:
	'Component' name=ID
	'{'
		(('display' display=STRING) &
		('parent' parent = [ConfigurationItem|ID])?
		)
	'}'
;

terminal BOOLEAN returns ecore::EBoolean
	: 'true' | 'false';
	



3. I created two DSL files (sample1.cdl, sample2.cdl) as below and located in "C:/test/data" directory.

sample1.cdl
Component ds1 {
	display "ds1"
}

Component ds2 {
	display "ds2"
}


Package pk1 {
	display "pk1"
	children ds1, ds2, ds3
	isRoot true
}


sample2.cdl
Component ds3 {
	display "ds3"
}



4. When I call "new SampleConfigLoadOperation3().run(monitor);" on my RCP Application, the result is as follows.

root size = 1
child name of pk1 : ds1
child name of pk1 : ds2
child name of pk1 : null


I don't know why the result of the 3rd line is "child name of pk1 : null".
I expected the result is "child name of pk1 : ds3".
Re: cross-file reference and link in xtext [message #1716820 is a reply to message #1716817] Tue, 08 December 2015 12:06 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14669
Registered: July 2009
Senior Member
- the code does not compile. even if i remove the datalistener
- why do you copy files around? i always asumed you try to load model files from an xtext project that is clean built (xtext nature, incr. build was run after copy)
- after you read the model you seem to make a model 2 model transformation

so this is not really code i can simply import and execute


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: cross-file reference and link in xtext [message #1716908 is a reply to message #1716820] Wed, 09 December 2015 01:05 Go to previous messageGo to next message
Dongho Yang is currently offline Dongho YangFriend
Messages: 10
Registered: August 2015
Junior Member
Sorry Christian. I don't know why the sample isn't compiled. I use the sample. Anyway, My RCP application will provide a function that can create a CProject. The created CProject has a treeview. When user creates a CProject and select a menu in the project, the application will collect one more DSL files In a specific folder (outside the project) and display the models on the treeview. Also user can edit the model data on the treeview. Is that possible using xtext? If that is impossible, is there an alternative for that?
In addition, I want a flat DSL to express a tree structure. That means that I want a DSL using not containment reference (layered DSL). So I will transform the models parsed by xtext to models that can be displayed on tree view.

[Updated on: Wed, 09 December 2015 01:20]

Report message to a moderator

Re: cross-file reference and link in xtext [message #1716923 is a reply to message #1716908] Wed, 09 December 2015 05:43 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14669
Registered: July 2009
Senior Member
Simply make sure the project has xtext nature and xtext builder and you call a build on the project

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: cross-file reference and link in xtext [message #1716937 is a reply to message #1716923] Wed, 09 December 2015 06:54 Go to previous message
Dongho Yang is currently offline Dongho YangFriend
Messages: 10
Registered: August 2015
Junior Member
I solved the problem.
When creating ResourceSet object, I Modified the codes as below.
Now it works well.

		 Injector injector = new MyDSLStandaloneSetup().createInjectorAndDoEMFRegistration();
		 XtextResourceSet resourceSet = injector.getInstance(XtextResourceSet.class);



I understood wrong that MyDSLStandaloneSetup() should not use in RCP.
Previous Topic:update specific outline node by changing its background
Next Topic:Please check if using xtext is suitable in my case
Goto Forum:
  


Current Time: Fri Apr 26 23:11:51 GMT 2024

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

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

Back to the top