ECore 反射和交叉引用
ECore reflection and cross references
为了获得上下文,我目前正在研究 ecore 到 java 模型的转换。实际上,我正在读取一些 ecore 文件并生成一个字符串,该字符串恰好是有效的 java 接口源代码。
例如,这是我的代码生成工作流程。
projectA.ecore:
定义一个 EClass 'A'
package projectA : projectA = 'http://www.example.org/projectA'
{
class A;
}
projectB.ecore:
定义一个 EClass 'B',它继承自 'A',使用对 a.ecore 的交叉引用来访问它。
import projectA : '../../projectA/model/projectA.ecore#/';
package projectB : projectB = 'http://www.example.org/projectB'
{
class B extends projectA::A;
}
从那些 ecore 我首先为 projectA.ecore 生成一个接口:
package projecta;
interface ProjectA<A> {
// ...
}
现在我想为 projectB.ecore 做同样的事情并获得以下界面:
package projectb;
import projecta.ProjectA;
interface ProjectB<A,B> extends ProjectA<A> {
// ...
}
为此,我需要使用交叉引用检测 A 和 EClass,并在 projectA.ecore 中进行一些分析以生成有效的接口扩展、包导入...
我在 ecore 反射 API 中环顾四周,但没有找到一个清晰明了的方法。这可能吗?是的,怎么样?
编辑:技术细节
我正在使用这种代码加载 ecore :
final ResourceSetImpl resourceSet = new ResourceSetImpl();
resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("ecore", new XMIResourceFactoryImpl());
final Resource resource = resourceSet.getResource(uri, true);
final EPackage ePackage = (EPackage) resource.getContents().get(0);
final String fileContent = new GenerateAlgebra().process(ePackage);
GenerateAlgebra 是 class 专用于 .ecore 到 String 的转换。从技术上讲,它是使用 Xtend (https://github.com/manuelleduc/ecore-oa/blob/master/fr.inria.diverse.ecorealgebragenerator/src/fr/inria/diverse/objectalgebragenerator/popup/actions/GenerateAlgebra.xtend) 开发的。
如果您只想获取定义 EClass 的 ecore 文件的文件路径,请使用资源 URI
尝试:
ePackage.eResource().getURI()
它为您提供了 ecore 文件的实际 URI,在该文件中定义了包及其所有 EClasses。类似于:file:/Users/../../yourPath/projectA.ecore
也可以使用getNsURI()
、getName()
来识别这两个ecore文件。
如果您像以前一样使用资源集,并且您在多个 ecore 文件之间有交叉引用,那么该集也会尝试加载所有其他资源。这意味着,通过调用 resourceSet.getResource(uri, true)
,资源集应该包含这两种资源。
尝试遍历 resourceSet.getResources()
为了获得上下文,我目前正在研究 ecore 到 java 模型的转换。实际上,我正在读取一些 ecore 文件并生成一个字符串,该字符串恰好是有效的 java 接口源代码。
例如,这是我的代码生成工作流程。
projectA.ecore:
定义一个 EClass 'A'
package projectA : projectA = 'http://www.example.org/projectA'
{
class A;
}
projectB.ecore:
定义一个 EClass 'B',它继承自 'A',使用对 a.ecore 的交叉引用来访问它。
import projectA : '../../projectA/model/projectA.ecore#/';
package projectB : projectB = 'http://www.example.org/projectB'
{
class B extends projectA::A;
}
从那些 ecore 我首先为 projectA.ecore 生成一个接口:
package projecta;
interface ProjectA<A> {
// ...
}
现在我想为 projectB.ecore 做同样的事情并获得以下界面:
package projectb;
import projecta.ProjectA;
interface ProjectB<A,B> extends ProjectA<A> {
// ...
}
为此,我需要使用交叉引用检测 A 和 EClass,并在 projectA.ecore 中进行一些分析以生成有效的接口扩展、包导入...
我在 ecore 反射 API 中环顾四周,但没有找到一个清晰明了的方法。这可能吗?是的,怎么样?
编辑:技术细节
我正在使用这种代码加载 ecore :
final ResourceSetImpl resourceSet = new ResourceSetImpl();
resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("ecore", new XMIResourceFactoryImpl());
final Resource resource = resourceSet.getResource(uri, true);
final EPackage ePackage = (EPackage) resource.getContents().get(0);
final String fileContent = new GenerateAlgebra().process(ePackage);
GenerateAlgebra 是 class 专用于 .ecore 到 String 的转换。从技术上讲,它是使用 Xtend (https://github.com/manuelleduc/ecore-oa/blob/master/fr.inria.diverse.ecorealgebragenerator/src/fr/inria/diverse/objectalgebragenerator/popup/actions/GenerateAlgebra.xtend) 开发的。
如果您只想获取定义 EClass 的 ecore 文件的文件路径,请使用资源 URI
尝试:
ePackage.eResource().getURI()
它为您提供了 ecore 文件的实际 URI,在该文件中定义了包及其所有 EClasses。类似于:file:/Users/../../yourPath/projectA.ecore
也可以使用getNsURI()
、getName()
来识别这两个ecore文件。
如果您像以前一样使用资源集,并且您在多个 ecore 文件之间有交叉引用,那么该集也会尝试加载所有其他资源。这意味着,通过调用 resourceSet.getResource(uri, true)
,资源集应该包含这两种资源。
尝试遍历 resourceSet.getResources()