2016-06-08 96 views
1

鉴于任何Class<?> clazz对象,是否有API获取EClass的模型实例实现clazz? (即eClass为其eClass.getInstanceClass().equals(clazz)为true)从EMF模型实例类获取EClass

如果我有一个eObject,我可以简单地叫eObject.eClass()得到EClass。但在我的情况下,我没有这样的例子。我只有一个模型实例类,需要关联的EClass才能拨打EcoreUtil.create(eClass)

+0

你可以举一个例子,你必须使用它吗?你从'obj.getClass()'获得'clazz',其中'obj'是一个'EObject'实例,或者你在代码中使用'InterfaceName.class'获得'clazz'(例如:在UML中,'Activity .class')? –

+0

@VincentAranega我使用'InterfaceName.class',因为我没有任何'obj'在那一点。它想要提供方法'create(InterfaceName。因为它可以是类型安全的,并且据我所知,为了得到一个EClass我需要通过名称获得它('ePackage.getEClassifier(“MyClass”)'') )或者我需要使用奇怪的引用'MyPackage.Literals.MY_CLASS',我想避免 – Kapep

+0

好吧。我想我有一个解决方案,然后:)(我正在写这个)。 –

回答

4

为了说明答案,我会asume,我们有一个名为Foo元模型在你前面的答案,并且相关的包是FooPackage和相关的工厂FooFactory。在这个元模型中,我会假设我们有AB这是EClass

为了得到相关EClassA.class,您可以使用此:

String aName = A.class.getSimpleName(); 
EClassifier classif = FooPackage.eInstance.getEClassifier(aName); 
if (classif != null && classif instanceof EClass) { 
    // At this point, you have the right EClass, 
    // you can now create an instance using the factory 
    EObject myinstance = FooFactory.eInstance.create((EClass)classif); 
} 

之后,您将需要处理动态实例(您EObject),除非你explicitally投myinstanceA使用此:

A instance = (A) myinstance; 
// or 
A instance = A.class.cast(myinstance); 

如果你把所有的这一个方法,它可能是这样的:

public static <T> T create(java.lang.Class<T> clazz) { 
    String iName = clazz.getSimpleName(); 
    EClassif classif = FooPackage.eInstance.getEClassifier(iName); 
    if (classif != null && classif instanceof EClass) { 
    return clazz.cast(FooFactory.eInstance.create((EClass)classif)); 
    } 
    return null; // or throw exception, clazz not found or stuff like that 
} 

请注意,在这一点上,您必须确保您尝试创建的界面(A.class)确实是EClass而且不是抽象的,否则会引发异常。

为了处理这种东西的,我开始为这个几个月前编写一个类库:https://github.com/aranega/dynemf

目前尚不完全记录,但你可以做的东西是这样的:

EPackageWrapper mymm = ePackage(FooPackage.eINSTANCE); 
mymm.create(A.class) 
    .set("name", "MyAInstance") 
    .set("bRels", mymm.create(B.class) 
        .set("name", "MyB1")); 

你可以浏览代码,也许它可以帮助你。

希望我明白你的问题。

+0

谢谢!它依赖于模型名称与实例类型名称相同,但是,对吧?但它应该在大多数情况下工作,并可能会为我工作。 – Kapep

+1

是的,它依赖于生成的接口名称与您在'.ecore'中建模的接口名称完全相同的事实。 'EPackage'上的'.getEClassifier(name)'是EMF API的一部分,通常用于处理动态实例(不需要从'.ecore'生成Java代码)。然而,这些“动态反射”方法比他们生成的方法慢。 –

2

我找不到任何API。 EClass及其实例类之间的关系由生成的初始化方法设置,但不存在任何反向映射。原因似乎是没有一对一的关系,因为多个模型元素可以使用相同的实例接口。

如果您确定每个类都使用不同的接口,则可以遍历所有EClassifiers并自己构建映射。

Map<Class<?>, EClass> eClasses = new HashMap<>(); 
for (final EClassifier eClassifier : FooPackage.eINSTANCE.getEClassifiers()) { 
    if (eClassifier instanceof EClass) { 
     if(eClasses.put(eClassifier.getInstanceClass(), (EClass) eClassifier) != null) { 
      throw new RuntimeException(
       "Failed to create distinct instance class to EClass mapping for " 
       + Classifier.getInstanceClass()); 
     } 
    } 
}