模式管理
本节将阐述如何创建和使用模式,并将解释一些模式管理相关的问题,例如如何使用FDO要素模式来描述空间要素。
1.1.1 模式概述
FDO要素模式提供了一种对空间要素的逻辑描述机制,而FDO Provider负责将要素模式映射为底层的物理数据结构。要素模式是空间要素数据的逻辑视图,它完全独立于数据存储,一切FDO中的数据操作都是针对逻辑要素模式中定义的类以及关系。FDO要素模式在某种程度上是基于OpenGIS和ISO要素模型的子集的,它既可以描述非空间要素,也可以描述空间要素。
1) 基本属性(Base Properties)
基本属性是在FDO API或某个FDO Provider中预定义的属性,要素模式中的所有类都支持基本属性,例如模式中所有的类都有“ClassName”和“SchemaName”两个基本属性。表9‑2列出了FDO API中预定义的基本属性。
属性名 |
是否必须 |
描述 |
SchemaName |
是 |
类实例所属的模式名,只读字符串属性。 |
ClassName |
是 |
实例的类名,只读字符串属性。 |
RevisionNumber |
否 |
实例的修订号,只读64位整型属性。有些Provider用该属性来支持乐观锁。 |
表 9‑2 FDO API预定义的基本属性
2) 模式间的交叉引用(Cross-Schema References)
一些FDO Provider支持多个模式,于是就引出了模式间交叉引用的概念,对于这些Provider一个模式中的类可以是从另一个模式中的类继承而来的,关联于另一个模式中的类,或者包含了一个基于另一个模式中的类的对象属性。
3) 模式类导航(Parenting in the Schema Classes)
FDO API定义的要素模式对象模型支持完全导航,也就是说,从任何一个FdoFeatureSchema对象的模式元素都就可以向上导航到该对象的根节点,而从根节点也可以向下导航到任何要素模式元素。这个功能是在FdoSchemaElement抽象基类中定义的。要实现完全导航,就要求子元素在插入到父元素时记录父元素的ID。
4) 物理映射(Physical Mappings)
每个要素Provider都要负责逻辑要素模式和物理存储之间的物理映射,其中一些Provider甚至要对映射提供多级别的控制,例如基于RDBMS的要素Provider可能会允许用户为类和属性指定表名和列名。由于各个Provider的映射差别很大,于是FDO API提供了一些接口,由每个Provider分别实现这些接口。这些类有FdoPhysicalSchemaMapping,FdoPhysicalClassMapping,FdoPhysicalPropertyMapping和FdoPhysicalElementMapping。
1.1.2 模式的组成
FDO使用类FdoFeatureSchema表示一个模式,FdoClass表示一个类,FdoFeatureClass表示一个要素类。每个模式由一个或多个类或要素类组成,类用于表示非空间数据,要素类用于表示空间数据。每个类和要素类由一个或多个属性组成,要素类必须有一个几何属性。
对于大部分Provider说来,每个类和要素类需要有一个关键属性(Identity Property)来加以标识每一个要素,关键属性可以由一个属性或多个属性组成。如果一个类和要素类是从某个类或要素类继承而来,关键属性只能在基类中定义,子类的关键属性只能从基类中继承而来。也就是说,任何一个有父类的类或要素类都不能设置关键属性
图 9‑3 FDO模式元素类图
1.1.3 模式的使用
模式管理主要包括模式的创建、模式的描述和模式的修改三种操作。
1) 创建模式
以下是创建模式所需的基本步骤(其中一些步骤可以省略,也有一些步骤之间可以交换顺序):
l 调用FdoFeatureSchema::Create("SchemaName", "FeatureSchemaDescription")方法创建一个模式。
l 调用FdoFeatureSchema::GetClasses()方法得到一个类的集合。
l 调用FdoClass::Create("className","classDescription")或者FdoFeatureClass::Create(
"className","classDescription")方法得到FdoClass或FdoFeatureClass类的实例。
l 调用FdoClassCollection::Add(class)方法将FdoClass或FdoFeatureClass类的实例加入到GetClasses()得到的类的集合中。
l 调用FdoGeometricPropertyDefinition::Create("name","Description")方法来创建FdoGeometryProperty的实例。
l 调用FdoDataPropertyDefinition::Create("name","Description")方法来创建FdoDataProperty的实例。
l 调用FdoObjectPropertyDefinition::Create("name","Description")方法来创建FdoObjectProperty的实例。
l 调用FdoClassDefinition::GetProperties()和Add(property)方法把以上的属性实例加入到类定义中。
l 调用FdoClassDefinition::GetIdentityProperties()和Add(Property)方法来添加FdoClass或FdoFeatureClass的ID。
l 调用FdoIApplySchemaCommand::SetFeatureSchema(featureSchema)方法为IFdoApplySchemaCommand设置模式对象。
l 用FdoAssociationPropertydefinition类描述两类之间的关系,当然,类已经在要素模式中定义并且不能是抽象类。
l 最后调用FdoIApplySchemaCommand::Execute()方法来应用对要素schema的改动。
2) 描述模式
为了得到现存模式的信息,可以调用FdoIDescribeSchema::Execute()方法得到一个FdoFeatureSchemaCollection实例,它包含了Data Store中的所有FdoFeatureSchema,并且可以通过它得到包括FdoFeatureSchema、FdoClass和FdoFeatureClass在内的任何模式对象,以及它们各自的属性。以下方法返回能够得到模式对象信息的主要集合:
l FdoFeatureSchema::GetClasses()方法得到FdoFeatureClasses。
l FdoClassDefinition::GetProperties()方法得到FdoPropertyDefinitionCollection。
l FdoClassDefinition::GetBaseProperties()方法得到从基类继承而来的FdoPropertyDefinitionCollection。
3) 修改模式
在修改模式前,一般会通过描述模式先得到一个FdoFeatureSchemaCollection实例,然后再修改此实例,最后调用方法FdoIApplySchema::Execute()。
插入操作非常简单,只需要把模式元素插入到相应的集合。删除操作可以通过如下任意一种办法:
l 调用方法FdoSchemaElement::Delete(),该方法只是把元素做一个删除标记,当该修改被接受(一般是通过FdoIApplySchema)时才真正删除掉。
l 调用FdoSchemaCollection::Remove()或FdoSchemaCollection::RemoveAt()方法从相应的集合删除元素。
模式元素都有一个状态标记,该标记可以通过调用FdoSchemaElement::GetElementState()得到。状态不能直接设置,它只能随着以下的操作而改变:
l Unchanged:当schema原型通过FdoIDescribeSchema得到时,所有的元素被初始化为Unchanged状态。
l Detached:调用特有集合的删除元素操作,该元素将被标记为Detached。
l Deleted:调用元素的Delete()方法把该元素标记为Deleted。
l Added:把元素添加到一个集合,该元素将被标记为Added。
l Modified:当添加或删除一个元素的子元素,该元素将被标记为Modified。另外,一旦一个元素被标记为Modified,那么包含它的元素也要被标记为Modified。例如,SchemaAttributeDictionary中的“Class3”元素添加了一个新值,那么SchemaAttributeDictionary和“Class3”元素都将被标记为Modified。
状态标记一直保留到改动被接受为止,也就是说,保留到执行了IApplySchema为止。此时,所有标记为Deleted的元素都将被清除,而所有其他元素都将被标记为Unchanged。
FdoFeatureSchema的回滚机制可以让模式返回到上一次接受变动的状态。例如,一个原型通过FdoIDescribeSchema做了添加类,删除属性等操作,所有这些操作都将通过调用FdoFeatureSchema::RejectChanges()方法被拒绝,所有元素的状态又重新被标记为Unchanged。该方法的相反操作是FdoFeatureSchema::AcceptChanges(),一般情况下,该方法只有在FDO Provider在执行FdoIApplySchema::Execute()命令时才被调用到。
1.1.4 FDO XML格式
FDO支持使用GML(Geography Markup Language)格式的描述模式。GML(Geography Markup Language)即地理标识语言,是一种使用XML语法描述地理空间要素的标记语言,它由OGC于1999年提出,它由OGC于1999年提出,并得到了许多公司的大力支持。
FdoFeatureSchema和FdoFeatureSchemaCollection两个类都实现了FdoXmlSerializable接口,这意味着FDO模式可以写入到一个GML格式XML文件;FdoFeatureSchemaCollection还实现了FdoXmlDeserializable接口,这意味着也可以从一个GML格式XML文件得到FDO模式。
在指定模式覆盖时,往往需要手工编写GML格式XML文件指定模式和模式覆盖,这时我们必须了解GML的语法。表 9‑3显示了FDO模式元素和GML元素之间的对应关系,其中使用双引号括起来的尖括号部分的内容和使用花括号括起来的内容代表需要用户替换的内容。
FDO模式元素 |
GML模式片段 |
FeatureSchema |
<xs:schema xmlns:xs=“http://www.w3.org/2001/XMLSchema” targetNamespace=“http://<customer_url>/<FeatureSchemaName>“ xmlns:fdo=“http://fdo.osgeo.org/isd/schema” xmlns:gml=“http://www.opengis.net/gml” xmlns:<FeatureSchemaName>=“http://<customer_url>/<FeatureSchemaName>“ elementFormDefault=“qualified” attributeFormDefault=“unqualified”> { 可选元素 xs:import 元素用来使schema生效 <xs:import namespace=“http://fdo.osgeo.org/schema” schemaLocation=“<FDO SDK安装位置>/docs/XmlSchema/FdoDocument.xsd”/> } {<每个schema中只能有一个 xs:element 和/或 xs:complexType >} </xs:schema> |
ClassDefinition (带有主键属性) |
<xs:element name=“<className>“ type=“<className>Type” abstract=“<true | false>“ substitutionGroup=“gml:_Feature”> <xs:key name=“<className>Key”> <xs:selector xpath=“.//<className>“/> <xs:field xpath=“<identityProperty1Name>“/> <xs:field xpath=“...”/> <xs:field xpath=“<identityProperty<n>Name>“ </xs:key> </xs:element> |
FeatureClass |
<xs:element ...请参考 ClassDefinition (带有主键属性)... </xs:element> <xs:complexType name=“<className>Type” abstract=“<true | false>“/> { 请参考FeatureClass.GeometryProperty } <xs:complexContent> <xs:extension base=“{baseClass}?{baseClass.schema.name}:{baseClass.name} : ‘gml:AbstractFeatureType’ “ > <xs:sequence> {属性列表请参考DataProperty和Geometric属性} </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> |
FeatureClass. GeometryProperty |
<!--这些是xs:complexType元素的属性--> fdo:geometryName=“<geometryPropertyName>“ fdo:geometricTypes=“<list of FdoGeometricTypes>“ fdo:geometryReadOnly=“<true | false>“ fdo:hasMeasure=“<true | false>“ fdo:hasElevation=“<true | false>“ |