1
votes

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 "http://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.

  1. 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()]));
        }
    

    }

  2. 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());
             }
          }
      }
    

    }

  3. 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.

3
It should work if you remove the 'resolveAll' option from your code. It should not be necessary and in general it is to be avoided. EMF will resolve your model transparently thus the 'resolveAll' thing is a relict from earlier days. Does that solve your issue? - Sebastian Zarnekow
@Sebastian Zarnekow Thank you. It seems to be well. Now I need to test it more. I will report the result after testing. - user2663410
@ Sebastian Zarnekow I have tried to test it many times. I still have the problem. Sometimes returns "comp display : null". - user2663410
and you should remove the resolve_all load option from the resourceset as well - Christian Dietrich

3 Answers

0
votes

you can try the followingcode:

  void loadData() {
    project =               ResourcesPlugin.getWorkspace().getRoot().getProject("test");
    ResourceSet resourceSet = new ResourceSetImpl();
IFile[] samples = findFiles(project);
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
for (Resource rc : resourceList) {
    Configuration config = (Configuration) rc.getContents().get(0);
    itemList.addAll(config.getConfigurationItems()));
}
}
0
votes

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.

0
votes

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");


    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();
                }

            }
        }
    }
}

}
  1. 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';
  1. 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"
}
  1. 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".