我使用xtext创建了一个新的DSL,如下所示。 (实际上我将在RCP应用程序上访问DSL。)
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])?)
'}'
;
我有两个文件:sample1.mydsl
Component comp1 {
display "comp1"
children comp2
}
sampl2.mydsl
Component comp2 {
display "comp2"
}
我按如下方式加载了模型数据:
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()]));
}
}
测试代码
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());
}
}
}
}
结果
comp display : null
我希望结果是&#34; comp display:comp2&#34;。
但有时结果是&#34; comp显示:comp2&#34;
有时结果是&#34; comp display:null&#34;
我认为这是因为xtext的延迟链接。
我怎样才能得到正确的结果 - &gt; &#34; comp显示:comp2&#34;?
我希望有人可以帮我解决。感谢。
答案 0 :(得分:0)
您可以尝试以下代码:
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()));
}
}
答案 1 :(得分:0)
我制作了一份分析样本。 请查看以下内容。
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();
}
}
}
}
}
}
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';
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"
}
当我调用&#34; new SampleConfigLoadOperation3()。run(monitor);&#34;在我的RCP应用程序中,结果如下。
root size = 1
child name of pk1 : ds1
child name of pk1 : ds2
child name of pk1 : null
我不知道为什么第3行的结果是&#34; pk1的子名称:null&#34;。 我希望结果是&#34; pk1的子名:ds3&#34;。
答案 2 :(得分:0)
我解决了这个问题。 创建ResourceSet对象时,我修改了如下代码。 现在效果很好。
Injector injector = new MyDSLStandaloneSetup().createInjectorAndDoEMFRegistration();
XtextResourceSet resourceSet = injector.getInstance(XtextResourceSet.class);
我理解错误,MyDSLStandaloneSetup()不应该在RCP中使用。