数据对象
数据对象用于描述业务数据,数据对象利用属性保存数据。
数据对象接口的设计原则是:使编程更为简单,因为它提供了对所有普通类型的业务数据的访问以及各种访问模式的支持,如基于名字、索引和路径进行访问。
数据对象接口包含以下方法:
-
获取和设置数据对象的属性;
-
查询一个属性是否是集合;
-
创建一个新的被包含的子数据对象实例;
-
从数据对象的容器删除该数据对象;
-
从数据对象的容器分派该数据对象;
-
获取数据对象的容器及其包含的属性;
-
获取根数据对象;
-
获取数据对象所属的数据图;
-
获取数据对象的类型;
-
获取数据对象的顺序(如果存在的话);
-
获取数据对象的额外属性(如果存在的话);
对于许多不使用生成代码的应用而言,数据对生成象接口是唯一用来编写应用的SDO部件。对于那些使用生成代码的应用来说,将直接使用生成的接口。SDO的其它部件主要根据用户需要加以使用。
数据对象概念
数据对象可以分为以下几类。在分类过程中,开放(open)或顺序(sequenced)概念能够独自或一起使用。
-
Basic 。数据对象和一个每个属性都有一个赋值域的 JavaBean 类似。所有允许的属性集合可以通过 getType().getProperties() 方法获得。通过 get(property) 方法可以访问属性的值。属性内部的顺序是可以维护的,但是跨越多个属性之间的顺序是不可维护的。
-
Open 。数据对象和一个容许有额外属性的 JavaBean 类似。在 XML 中,这等同于开放(通配符)内容。它类似于一个和新属性拥有额外映射的 JavaBean 。额外属性不是由 getType().getProperties() 方法返回属性的一部分。通过使用 getInstanceProperties() 方法,能够获得一个特殊数据对象的实际拥有的属性。属性值可以使用 get(property) 方法访问。属性内部的顺序是可以维护的,但是跨越多个属性之间的顺序是不可维护的。
-
Sequenced 。数据对象和一个能够同时维护属性内部和属性之间顺序的 JavaBean 类似。在 XML 中,这等同于一个 DOM 。在使用 XML 时, Sequence 表示了数据对象内部所有 XML 元素的顺序。使用 get(property) 方法可以获得属性值,但是维护跨越多个属性之间的顺序,则需要通过顺序 interface. getSequence() 方法返回 XML 实例的所有 XML 元素的 Sequence 进行。 XML 属性没有顺序的概念并且可以通过 get(property) 方法进行访问。
数据对象的值和属性
数据对象拥有给其属性所赋的数据值。例如,一个采购订单数据对象的orderDate属性有一个值为:2005-6-30。通过使用数据对象的get("orderDate") 和 set("orderDate")方法,可以获取或修改其orderDate属性的值。当使用生成的代码时,也可以通过使用PurchaseOder接口上的getOrderDate() 和setOrderDate()方法访问属性的值。
在数据对象接口上,可以基于属性的名字通过使用get(String path)方法访问属性值,也可以利用属性的索引或者直接利用属性对象访问属性值。数据对象的get(String path)方法可以使用别名,也可以使用路径里的属性名。在这里,路径可能仅仅是一个属性的名字,也有可能是一个基于XPath子集的路径表达。
类型转换
有时属性的类型会和应用程序中习惯使用的类型不同。例如,当在用户界面中显示一个整型数量时,字符串型可能比整型表达更有效。可以方便的访问整型数量属性的getString(“quantity”)方法将会返回一个字符串类型的值。在许多应用中,这使一个常用的任务得以简化。
在调用一个数据对象的类型访问器(accessor)get和set时,如果值不是请求所需要的类型T的实例,则必须进行类型转换。类型转换由数据对象的实现自动完成。SDO实现被期望能够实现任何数据类型与数据对象内定义的类型之间的转换,并且在转换过程中尽可能不丢失信息。所支持的数据类型在SDO DataTypes片段中定义。这些类型包括:
-
Java 基本类型;
-
Java 基本类型的对象包装;
-
String ;
-
Date 和时间类型;
-
URI ;
-
Byte[] ;
-
BigDecimal ;
-
BigInteger ;
Java和DataHelper描述了类型转换。本规范145页“DataType Conversions”中说明了所支持的类型转换。
多值(Many-Valued)数据对象属性
属性可能有一个或多个值。如果一个属性是多值的,那么property.many返回true,get(property)方法将返回一个列表(List)。
在数据接口或自动生成的代码上,当属性没有值时,返回值为List的数据对象方法将返回一个空列表而不是返回一个null。返回的列表可以描述数据对象的值的任何变化。
对于访问多值属性来说,getList(property)访问器是极其方便的。如果property.many是true,那么set(property, value)和setList(property, value) 方法需要“value”分别为java.util.Collection和List对象。这些方法和在使用完getList(property).clear()之后紧接着使用getList(property).addAll(value)方法效果一样。
对于多值属性,get()和getList()方法将返回一个包含当前值的列表List。通过List接口立即可以对数据对象的当前值进行更新操作。每次使用get()或getList()方法访问时,都将返回同一个List对象。
判断一个属性是否是集合
对于一个多值属性,isSet(property)方法将返回:
-
True ,如果 List 不为空;
-
False ,如果 List 为空;
对于一个单值属性,isSet(property) 方法将返回:
-
False ,如果 Property 还没有被 set() 或者已经被 unset() 了;
-
True ,如果当前值不是 Property 的缺省值;
-
对于某些实例,实现基于下列策略决定 isSet(property) 的值:
-
调用 set() 之后而没有调用 unset() , isSet() 返回 True 。在 set(property, property.getDefault()) 之后, isSet(property) 返回 True ;
-
当前值不等于缺省值时, isSet() 返回 true ;在 set(property, property.getDefault()) 之后, isSet(property) 返回 false 。
unset(property)访问器可以用来清空一个简单属性,因此在unset(property)之后,isSet(property)返回false,get(property)返回缺省值。delete()方法将取消数据对象的所有属性的值,除非该属性为只读属性。在unset()之后,get(property)将返回缺省值,对于多值属性,则返回一个空列表。
注意:试图使用set,unset或者delete修改一个只读属性将会引发一个异常。
包含内容(Containment)
数据图内的数据对象被组织成一个树型结构。有一个数据对象作为树的根节点,而其它数据对象则组成这个树的其它叶子节点。
通过使用由根数据对象开始的包含内容引用(containment references)就可以创建一个树型结构。根数据对象引用其它数据对象,而这些数据对象则可以进一步引用更深一层的数据对象。除了根数据对象,数据图内的每一个数据对象必定有一个从树内其它节点而来的包含内容引用。图内的每一个数据对象可以跟踪它的包含内容引用的位置。
对于一个数据图来说,拥有一个非包含内容引用(containment references)是可能的。这些引用所指向的数据对象是同一个数据图的一部分(引用的数据对象必定是同一个树的一部分),但是这些引用对该数据图的树型结构没有影响。
包含内容和非包含内容都是数据对象的属性。该属性的类型可以是任何一种数据对象类型。
一个特殊的数据对象引用属性是否是一个包含内容引用或非包含内容引用由该数据图的数据模型定义,例如定义一个XML文档数据类型的XSD。一旦数据模型被定义好后,将不能被修改。可以通过访问property.containment来查询一个特殊的引用是否是一个包含内容引用。
容器型数据对象包含其它数据对象。数据对象能够拥有一个容器数据对象的最大数目。如果一个数据对象没有容器,那么它就是一个根数据对象。
getContainer()和getContainmentProperty()方法提供了自上而下的简单浏览数据对象所包含的内容的方法。getContainer()方法返回一个父数据对象,getContainmentProperty()方法返回包含该对象的容器属性。使用detach()方法,在不做任何改变的情况下,可以将一个数据对象能够从它的容器中移出。
包含内容可以被管理。当一个数据对象作为一个包含内容属性的值被设置或添加时,它将被从先前的任何一个包含内容属性中移出。包含内容不可能有循环。如果设置或添加将生成一个循环,一个异常将会抛出。
创建和删除数据对象
创建方法可以创建一个该属性所属类型的数据对象,或者创建一个在参数中说明的类型的数据对象,并且能够将一个创建好的数据对象添加到指定的属性。如果数据对象的类型是一个顺序型(getType().isSequenced()方法返回true),新创建的数据对象将被添加在顺序的末尾。如果属性是单值的,属性的值将被设置为该新创建的对象。如果属性是多值的,新创建的对象将被作为最后一个对象而添加。只有包含内容属性能够被用来创建对象。一个新创建的对象的所有属性都被取消(未赋值或仅是缺省值)。
delete()方法取消了数据对象的所有非只读属性。如果包含内容属性不是只读的,delete()方法也将把该数据对象从包含其的数据对象中移出。包含内容属性所包含的递归的子数据对象也将被删除。
如果其它数据对象有一个单步的或非包含内容属性指向已删除的数据对象,那么这些引用将不会被修改。然而为了满足数据图的封闭特性,上述属性的值需要改变。一个被删除的数据对象能够被再次使用,并且能够被再次添加到数据图中。
顺序型数据对象
数据对象可能是顺序型的或非顺序型的。getType().isSequenced()方法可以告诉你该数据对象的类型是否是顺序型的。
如果数据对象的类型是顺序型的,那么getSequence()方法将会返回一个顺序(Sequence),否则getSequence()方法返回null。
数据对象的顺序和表达其属性值的XML元素一致。如果更新一个数据对象的话,那么从该数据对象返回的列表或顺序,也进行同样的数据操作。
返回的顺序可以有效的描述数据对象值的任何变化。
开放内容的数据对象属性
数据对象有两种类型的属性:
-
由类型( Type )说明的属性;
-
不是由类型( Type )说明的属性,这样的属性叫做开放内容( open content );
与数据对象类型相关的属性可以通过getType().getProperties()方法获得,该方法将返回一个列表。
除了拥有由类型描述的属性之外,数据对象还能够拥有其它属性:
-
处理开放的或者混合的 XML 内容。
-
动态的遭遇新的属性。
当Type.open为true时,允许拥有开放内容属性。一些类型将开放(open)设置为false,因为它们不能接受附加的属性。
一个属性如果出现在getInstanceProperties()方法返回值中而不是出现在getType().getProperties()方法的返回值中,那么该属性来源于开放内容。如果一个属性来源于开放内容,那么isSet(property)方法必定返回true。
如果equals()方法为true的话,由DataType Types说明的属性可以返回不同的对象。对于多变的数据值(例如,日期型或字符串列表),对这些值进行修改直接由实现决定。
当你使用getInstanceProperties()方法时,将返回一个只读的列表,里面包含一个数据对象当前所使用的所有属性。这包括开放内容的属性。属性的顺序由所有getType().getProperties()方法返回值开始;其它属性的顺序由实现决定。每一次对getInstanceProperties()方法的调用将返回同一个列表对象,除非该数据对象已经更新,从而导致列表内容改变。
在一个实例属性中,通过调用getProperty()方法并基于属性名就能够有效的查找数据对象上对应的属性。
为了设置一个该属性尚未设置(其并未出现在getInstanceProperties()方法返回值中)的开放内容值,一个数据对象的设置或创建访问器,或者在列表或顺序中添加,一个属性的参数将要被使用,该参数可以通过访问TypeHelper或者 XSDHelper查找到。创建一个开放内容的例子可以在135页“Creating open content XML documents”中找到。
对于所有通过getInstanceProperties()方法获得的开放内容属性,其isSet(property)方法将返回真。
属性索引
当一个数据对象拥有多个属性时,每一个属性都能够被一个数字索引所引用,其中第一个属性的数字索引从0开始。
get(int property)方法中使用的属性索引是该属性在getInstanceProperties()方法返回的列表中的位置。
如果数据正在修改之中,不推荐对开放内容使用索引参数访问器;除非该索引被用在getInstanceProperties()方法获得的属性中,因为在getInstanceProperties()方法中,开放内容的属性索引能够改变,如果几个开放内容属性的值能够被重复的设置和取消设置。
下面的例子是正确的,因为索引和getInstanceProperties()方法一起使用。注意由于数据对象不是同步的,因此用户不应该在读的同时对其进行更新操作。该实例显示了一个普通的模式,在所有实例属性中循环并且打印属性名和值:
for (int i=0; i
{
Property p = (Property) myDo.getInstanceProperties().get(i);
System.out.println(p.getName()+"="+myDo.getString(i));
}
getInstanceProperties()方法获得的属性的名称和别名与那些拥有较高的索引的属性相比,具有一个较高的优先级,因此开放内容属性可以通过使用类型属性中定义的名称隐藏其真实名称,因为这些属性在列表的开始。优先级的顺序就是getInstanceProperties()方法返回值中的顺序。
在一个复制名称的事件中,开放内容属性可以通过它的别名访问,前提条件是该别名和已有其它属性的名称、别名不冲突。
数据对象的当前状态(current state)
数据对象的current state包含所有用来区分其与由DataFactory创建的新对象的值,因为由DataFactory新创建的对象还没有属性集合和容器。数据对象的当前状态是getInstanceProperties()方法返回值中所有isSet()为真的属性。容器和包含内容属性是包含该数据对象的数据对象的状态的一部分。下列程序将打印出数据对象myDO的当前状态:
for (int i=0; i
{
Property p = (Property) myDo.getInstanceProperties().get(i);
if (myDo.isSet(p))
{
System.out.println(p.getName()+"="+myDo.getString(i));
}
}
数据对象接口
public interface DataObject extends Serializable
{
Object get(String path);
void set(String path, Object value);
boolean isSet(String path);
void unset(String path);
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/8042616/viewspace-907244/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/8042616/viewspace-907244/