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 数据绑定框架将此属性链接到 GUI。

我怎么解决这个问题?我要创建派生特征吗?有什么技巧吗?

4

4 回答 4

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
      )
    );
于 2012-05-05T08:34:12.487 回答
1

如果您永远不需要将节点从一个容器移动到另一个容器,并且您永远不会将来自不同容器的节点混合在一起,那么您可以使用以下解决方案。

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

编辑:更仔细地阅读您的问题,我发现您必须能够统一处理对象,并且在这种情况下这是行不通的。但也许我的第三个解决方案会!

无论如何我都会把这个答案留在这里。也许它对其他人有用。

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
}
于 2017-07-01T07:58:28.867 回答
0

有一种标准方法可以做到这一点:

在子对象中创建对父对象的引用,并为其设置适当的opposite属性container

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

以下是 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>
于 2017-03-21T21:11:59.417 回答
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类会适合那个。

于 2017-07-01T08:18:40.637 回答