2012-05-02 46 views
2

的容器,我有以下类型的简单EMF模型:数据绑定到未知类型

EClass FooGroup { 
    EString name; 
    @Properties(containment=true, upper=-1) 
    List<Node> nodes; 
} 
EClass BarGroup { 
    EString name; 
    @Properties(containment=true, upper=-1) 
    List<Node> nodes; 
} 
EClass Node { 
    EString name; 
} 

我想展示的所有节点名称的简单TableViewer,与其父组的名字联系在一起。不幸的是,eContainer()是一个操作,而不是一个功能。这意味着我不能使用JFace Databinding框架将此属性链接到GUI。

我该如何解决这个问题?我是否创建衍生功能?有什么技巧吗?

+1

是否有理由不让Node参考其父组? –

+0

上面的例子被简化了。组中有多个属性可以包含一个节点,所以没有单个EOpposite关系。 – parasietje

回答

3

我无法想象在EMF数据绑定中使用eContainer的方法,但向节点添加指定的父引用并且在eContainer更改时以编程方式更新它并不困难。

另一种解决方案是增加父母,然后改变其生成的代码:

/* 
* @generated NOT 
*/ 
public Group getParent() { 
    if (eContainer() instanceof Group) { 
     return (Group) eContainer(); 
    } 
    return null; 
} 

那么你可以使用一个FeaturePath得到EMFProperty这样的:

IEMFProperty groupNameProperty = EMFProperties.value(
     FeaturePath.fromList(
     ModelPackage.Literals.NODE__PARENT, 
     ModelPackage.Literals.GROUP__NAME 
    ) 
    ); 
+1

我已经添加了一个派生属性'parent',它通过在对象的构造函数中注册Adapter来自动更新。 – parasietje

0

有一个标准的方法要执行此操作:

在子对象中创建一个引用与父对象相应oppositecontainer属性设置为它。

通过这种方式,类之间的关系在模型中很明显,并且它是自动维护的,因此您不必编写任何自定义代码。

以下是这Xcore一个例子:

class Master { 
    contains Slave[] slaves opposite master 
} 

class Slave { 
    container Master master opposite slaves 
} 

为什么没有在Ecore的同样的事情也,而我们在这里:

<eClassifiers xsi:type="ecore:EClass" name="Master"> 
    <eStructuralFeatures xsi:type="ecore:EReference" name="slaves" eType="#//Slave" 
     containment="true" eOpposite="#//Slave/master"/> 
</eClassifiers> 
<eClassifiers xsi:type="ecore:EClass" name="Slave"> 
    <eStructuralFeatures xsi:type="ecore:EReference" name="master" eType="#//Master" 
     eOpposite="#//Master/slaves"/> 
</eClassifiers> 
+0

这确实可以在上面的例子中工作。我已经更改了问题以更清楚地显示问题:如果Node可以包含在不同的对象类型中,则不能定义单个相反的引用。 – parasietje

+0

@parasietje:啊,我明白了。但是,无论如何,将这项技术发布在本网站上是件好事。直到最近我才知道它。 – Lii

1

如果你永远需要将节点从其中一个容器移动到另一个容器,并且从不将不同容器中的节点混合在一起,则可以使用以下解决方案。

这个想法是为节点创建子类,为它们存储的每个位置创建一个子类。子类可以有一个正常的容器引用。

编辑:更仔细地阅读你的问题我看到你必须能够统一处理对象,并且这种情况不起作用。但也许我的third solution会!

无论如何,我会留下这个答案。也许这对其他人有用。

class FooGroup { 
    String name 
    contains FooNode[] nodes opposite group 
} 

class BarGroup { 
    String name 
    contains BarNode[] nodes opposite group 
} 

class Node { 
    String name 
} 

class BarNode extends Node { 
    container BarGroup group opposite nodes 
} 

class FooNode extends Node { 
    container FooGroup group opposite nodes 
} 
0

可以创建自定义容器属性类来解决这个问题。

这样你不必修改你的模型类就可以绑定到容器。新的属性将对所有电子对象有用。

public static IValueProperty containerProperty() { 
    return new ContainerProperty(); 
} 

public class ContainerProperty extends ValueProperty { 
    @Override 
    public IObservableValue observe(Realm realm, Object source) { 
     return Observables.constantObservableValue(realm, 
      source == null ? null : ((EObject) source).eContainer(), 
      getValueType()); 
    } 

    @Override 
    protected Object doGetValue(Object source) { 
     return ((EObject) source).eContainer(); 
    } 

    @Override 
    public Object getValueType() { 
     return EObject.class; 
    } 
}; 

实施例使用:

IObservableValue obs = containerProperty().observeDetail(node); 

这个类不听到容器的变化。但我认为可以实施这样的一项财产。也许使用SimpleValueProperty类将适用于此。