EMF References

来源:互联网 发布:理财风险数据 编辑:程序博客网 时间:2024/05/20 20:02

Non-Changeable与Unsettable Attributes

Non-Changeable Attributes:没有相应的set方法,不能externly修改其value.
Unsettable Attributes:一个attribute具有unset状态.unset的用途,比如:item的一个attribute:shipDate,那么shipDate是unset,那么表示该item还没ship出去,自然不会有shipDate;shipDate是null,就表示这个item是不可ship的.
 
Reference
 One-Way references
生成的model code有一段:
public PurchaseOrder getPreviousOrder() {
  
if (previousOrder != null && previousOrder.eIsProxy()) {
    PurchaseOrder oldPreviousOrder 
= previousOrder;
    previousOrder 
=
      (PurchaseOrder)EcoreUtil.resolve(previousOrder, 
this);
    
if (previousOrder != oldPreviousOrder) {
      
if (eNotificationRequired()) eNotify(
        
new ENotificationImpl(this, Notification.RESOLVE, ...));
    }

  }

  
return previousOrder;
}

EMF persistence framework 使用lazy loading机制,那么这个previousOrder很有可能直接指向了一个null,导致不可预料的结果.所以将previousOrder指向一个代理.eIsProxy()判断是否指向一个代理,resolve()将第一次去load这个refernced object's document.

Bidirectional References

一个order只能有一个customer.此外,bidirectional references要注意的是在set的时候,在reference的两端都要进行操作。

code:[PurchaseOrderImpl]

public void setCustomer(Customer newCustomer) {
           
if (newCustomer != customer) 
{
    NotificationChain msgs 
= null
;
    
if (customer != null
)
    msgs 
= ((InternalEObject)customer).eInverseRemove(this, PurchaseOrderPackage.CUSTOMER__ORDERS, Customer.class
, msgs);//调用的是customer的方法,在它们之间关系的另一端(customer)的order list去除这个order.
    
if (newCustomer != null
)
    msgs 
= ((InternalEObject)newCustomer).eInverseAdd(this, PurchaseOrderPackage.CUSTOMER__ORDERS, Customer.class
, msgs);//再在新的customer里的order list加上这个order.
    msgs 
=
 basicSetCustomer(newCustomer, msgs);//自己这一端
    
if (msgs != null
) msgs.dispatch();
             }

             
else if (eNotificationRequired())
    eNotify(
new ENotificationImpl(this
, Notification.SET, PurchaseOrderPackage.PORDER_BIDIRECTION__CUSTOMER, newCustomer, newCustomer));
}

public NotificationChain basicSetCustomer(Customer newCustomer, NotificationChain msgs) {
    Customer oldCustomer 
=
 customer;
    customer 
=
 newCustomer;     //设置customer,其他都是notify相关
    
if (eNotificationRequired()) 
{
        ENotificationImpl notification 
= new ENotificationImpl(this
, Notification.SET, PurchaseOrderPackage.PORDER_BIDIRECTION__CUSTOMER, oldCustomer, newCustomer);
        
if (msgs == null) msgs = notification; else
 msgs.add(notification);
    }

    
return msgs;
}

Multi References

对于multi reference(不仅仅是multi reference,只要某一端的关系是属于*),那么产生的代码中就没有set方法,只有单纯的get,如上面的PurchaseOrder,是“多对1”中的多,那么在Customer中只有getOrders():(如果定义一个multi Attribute 同样是只有一个getXXX())

public EList getOrders() {
        
if (orders == null{
            orders 
= new EObjectWithInverseResolvingEList(POrderBidirection.classthis, PurchaseOrderPackage.CUSTOMER__ORDERS, PurchaseOrderPackage.PORDER_BIDIRECTION__CUSTOMER);
        }

        
return orders;
    }

要添加什么的,直接对getOrders()返回的list进行add等操作。

Containment References

EObjectList的三个子类:EObjectContainmentEList,EObjectResolvingElist,EObjectWithInverseElist。先看几个图:

[implicitly]--

[explicitly]--

Containment References的“多”端:1)explicitly:getItems()返回的是EObjectContainmentWithInverseEList,并且在关系的另一端的setOrder不再使用proxy,而是eContainer。
public ContainPurchaseOrder getOrder() {
        
if (eContainerFeatureID != PurchaseOrderPackage.CONTAIN_ITEMS__ORDER) return null;
        
return (ContainPurchaseOrder)eContainer();
    }
                                2)implicitly:getItems()返回的是EObjectContainmentEList,在item端里面没有其他的方法。在Item里面有个eContainer,返回的就是这个containment关系中的container,亦即ContainImplicityPurchaseOrder.使用方法如下:
EObject container = item.eContainer();//定义一个container,从item里面获得它的container
if (container instanceof PurchaseOrder)//保证类型能正确转换
  purchaseOrder = (PurchaseOrder)container;//ok,转换为purchaseOrder

此外,Multi References的“多”端:getItems()返回的是EObjectWithInverseResolvingEList。

Map References

模型定义如下:注意改IntToOrderMapEntry的property sheet中的instance class name为java.util.Map$Entry.

生成代码后可以看到Map类型,表现在:

public class IntToOrderMapEntryImpl extends EObjectImpl implements BasicEMap.Entry {

 

在indexImpl中对该map类型的使用

public EMap getOrdermaps() {
        
if (ordermaps == null
{
            ordermaps 
= new EcoreEMap(PurchaseOrderPackage.Literals.INT_TO_ORDER_MAP_ENTRY, IntToOrderMapEntryImpl.classthis
, PurchaseOrderPackage.INDEX__ORDERMAPS);
        }

        
return ordermaps;
    }