MAPPING UML INTO OWL REPRESENTATION

Extended example developed in "An Open-Environmental Ontology Modeling" paper

We have been working on MDE model transformation approaches in two ways: OWL2OWL transformations and UML2OWL transformations. The former (OWL2OWL) allows the system to transform EIM templates (i.e., the OWL representation for the ontologicalknowledge modeling of SOLERES) into EID templates (i.e., the OWL representation to use trading services in the SOLERES system); the latter (UML2OWL) allows us to transform UML representations of the ontological-knowledge model (EIM templates formalized in UML notation) into OWL. templates.

In this section we will focus on explaining the transformation process for the latter, mapping UML models into OWL code by means of model transformation, although the transformation technique is the same in both cases.


Contents

1. Model Transformation
2. A case study for ontological model transformation
  2.1. Example scenario
  2.2. Data types
  2.3. UML2OWL
3. Process of transformation
  3.1. UML2OWL rules
    Model2Graph
    Package2Ontology
    UMLClass2OWLClass
    DataType2RDFSDataType
    Property2DataTypeProperty
    Property2InverseObjectProperty
    Property2InverseFunctionalProperty
    addFunctionalProperty
    addCardinality
    addMinCardinality
  3.2. OWL2XML rules
    Graph2Root
    Ontology2Element
    Class2Element
    makeCardinalityRestrictionSubClass
    makeMinCardinalityRestrictionSubClass
    DataTypeProperty2Element
    ObjectProperty2Element
    InverseFunctionalProperty2Element
    FunctionalProperty2Element
  3.3. Result of process


1. Model Transformation

Model transformation is a general framework of software engineering in which some (visual) models are transformed into other models. In UML models represent instances of UML diagrams (class diagrams, state machines, sequence diagrams, etc.); such instances can be transformed in order to have different views of the same model, or to obtain code in a particular programming language, among other examples.

There are M2M transformations for model-to-model transformations, and M2T, for “model-to-text” transformations (i.e. from a UML class diagram to code). The MDA (Model-Driven Architecture) proposal of OMG (Object Management Group) presents a process of software development to support system development. The most important concepts are models and transformations between them, which create other models in turn. Describing model transformations requires specific language for their definitions. In most cases, transformations may be expressed by means of some rules. Rules must show how a given model can be transformed into another.

In the literature there are several language proposals and transformation tools. The QTV (Query-View-Transformation) language is on the context of MOF (Meta Object Facility). Such language was proposed as standard for model transformation. The ATL language (ATLAS Transformation Language) is a domain specific language (DSL) to specify model transformations. ATL is inspired on QVT. ATL is a hybrid language that allows both declarative and imperative constructs. Other hybrid proposals for model transformation are, for instance, RubyTL and MT.

For our purpose, we decided to use the ATL language for model-transformation because it is a well-known implementation and it is based on the QVT standard of MOF/OMG. To implement our transformers, we use the Eclipse platform. We specifically use the Eclipse Modeling Project package, a collection of useful tools (EMF, GMF, MDT, M2M, etc.) for modeling purposes. Therefore, all transformers developed for our research purposes have been implemented on this platform in ATL. However, for UML2OWL transformations (where a representation of the ontological model is made to transform UML to OWL), we used an open source component (plugin) of Eclipse that implements the ODM/OMG (Ontology Definition Metamodel) facility. This plugin is very useful for simple UML2OWL transformations; however it presents certain shortcomings for complex data types. Here, we extended this Eclipse implementation to include EML and GML complex data types and adapt the mapping for ontological-model transformations. Then we will explain some details of implementation and transformation process through a case study.

return to Contents

 


2. A case study for ontological-model transformation

The ontology (as a metamodel) is built only once and then designers can specialize the metamodel according to their needs. The UML ontological model collection (and its possible variations) could automatically be translated to an OWL textual model by means of an M2T tool (Model-to-Text). We will focus on explaining some correspondences between some elements of UML visual model and OWL textual model.

2.1. Example Scenario

To explain the transformation, we can see the example in next figure. Here, we can see how the same grid (Grid in the figure) is used for more than one ecological classification.

For instance, in our example we will use the same Grid (with 21,905 cells) to get the ecological maps classification of the climatology, litology, geomorphology, edaphic soils and vegetation (maps from 1 to 5); five maps for the same Grid. In Ecology, a "grid" is determined by

  • (a) the cell size (cell_size_X, cell_size_Y)
  • (b) the number of rows row_size)
  • (c) the number of columns (column_size)
  • (d) UTM coordinates for the Grid georreferenciation (georef_utm).

return to Contents


 

2.2. Data types

We only included the name of the attributes in the previous UML model, but all classes attributes are defined by means of data-types in the models. For instance, in previous figure data types are represented as "name:DataType". Integer and String data types are base types. In the Grid class there are five data types (cellSizeXDirection, cellSizeYDirection, rows, columns, georeferenceInfo) which are defined in the grammar eml-spatialRaster.xsd of EML package. Therefore, the Grid class uses the EML class with the schema name contained in the grammar. This is defined in UML by a dependence relationship between both classes. Each EML data type, in turn, can be divided into some other types, though this will be defined in the referenced grammar. For instance, the data type georeferenceInfo has the required elements of a Grid georeferenceInfo of a cartographical map, such as georreferenciation coordinates in the space (xCoordinate and yCoordinate) and a corner (corner), so that it can take the values "center", "lowerRight", "lowerLeft", "upperRight" or "upperLeft" in its instantiation.

return to Contents


 

2.3. UML2OWL

We used an Eclipse open source tool adapted to our purpose, and extended to complex data types. The transformation process runs in two stages. The first stage transforms the original model (see 2.2) into an intermediate representation of OWL: an instantiation of the OWL metamodel written in XMI. In the second stage, the intermediate representation is transformed into XML (OWL final code):

Next figure shows the intermediate representation generated in the first stage. The diagram is a UML profile for OWL. Classes in the input model are represented in the intermediate model by classes stereotyped "owlClass" (and then as owl:Class elements in the target model). The same happens with primitive data types (e.g. “String” or “Integer”) of the class attributes, which again comes as a stereotyped class attributes such as "datatypeProperty". However, for complex data types, the intermediate stage generates new data types linked to the package that defines them. For instance, the property “georef_utm” is defined in the input model (Figure in 2.2 as a class attribute with the type “georeferenceInfo” (i.e., georef_utm: georeferenceInfo). In the intermediate model, such property is represented by two associated and stereotyped classes: one for the attribute (datatypeProperty) and another for the type (dataType). The transformer includes a link to the package eml-spatialRaster.xd for mapping tasks. Finally, the association in the intermediate model is tagged with the traditional elements of OWL “has” and “inverseOf”.

The model transformation process requires a source UML model written in XMI format (e.g. “example.uml”); it also generates a target OWL model in XML format (e.g., “example.owl”): endogenous M2M transformation. Next figure shows the XMI file of the source UML model:

Now, we can see XML file of the target OWL model: exogenous M2T transformation:

return to Contents

 


3. Process of transformation

3. 1. UML2OWL rules

In this section, we explain the complete process of transformation. This transformation starts with the UML model of the example presented before:

<?xml version="1.0" encoding="UTF-8"?>
<uml:Model xmi:version="2.1" xmlns:xmi="http://schema.omg.org/spec/XMI/2.1" xmlns:uml="http://www.eclipse.org/uml2/2.1.0/UML" xmi:id="_qb8akM37EdqwVrslYOdUDA" name="ontology">
  <packagedElement xmi:type="uml:Package" xmi:id="_w8IxIM37EdqwVrslYOdUDA" name="http://www.ual.es/acg/soleres/ontology">
    <packagedElement xmi:type="uml:Class" xmi:id="_3dw8YKx5EduvtrQ7BMslhA" name="Ecological_classification">
      <ownedAttribute xmi:id="_MfAK8DAxEd--IoYfZcCMlg" name="id" type="_LbFmcKx6EduvtrQ7BMslhA" aggregation="composite"/>
      <ownedAttribute xmi:id="_Nx2S4DAxEd--IoYfZcCMlg" name="name" type="_LbFmcax6EduvtrQ7BMslhA" aggregation="composite"/>
      <ownedAttribute xmi:id="_OcBRQDAxEd--IoYfZcCMlg" name="description" type="_LbFmcax6EduvtrQ7BMslhA" aggregation="composite"/>
      <ownedAttribute xmi:id="_POYiUDAxEd--IoYfZcCMlg" name="observations" type="_LbFmcax6EduvtrQ7BMslhA" aggregation="composite"/>
    </packagedElement>
    <packagedElement xmi:type="uml:Class" xmi:id="_4xgcMKx5EduvtrQ7BMslhA" name="Grid">
      <ownedAttribute xmi:id="_fzf6cDAxEd--IoYfZcCMlg" name="id" type="_LbFmcKx6EduvtrQ7BMslhA" aggregation="composite"/>
      <ownedAttribute xmi:id="_eSBjwDD5Ed-YotXu97PIsA" name="cell_size_X" type="_W5tDgDKHEd-yToNOK4bJsQ" aggregation="composite"/>
      <ownedAttribute xmi:id="_hG7UUDD5Ed-YotXu97PIsA" name="cell_size_Y" type="_b6rDADKHEd-yToNOK4bJsQ" aggregation="composite"/>
      <ownedAttribute xmi:id="_iX_TkDD5Ed-YotXu97PIsA" name="row_size" type="_kpKdIDKHEd-yToNOK4bJsQ" aggregation="composite"/>
      <ownedAttribute xmi:id="_l1RSwDD5Ed-YotXu97PIsA" name="column_size" type="_mvuhADKHEd-yToNOK4bJsQ" aggregation="composite"/>
      <ownedAttribute xmi:id="_npC9gDD5Ed-YotXu97PIsA" name="georef_utm" type="_-V-9cDKDEd-yToNOK4bJsQ" aggregation="composite"/>
    </packagedElement>
    <packagedElement xmi:type="uml:Association" xmi:id="_TgFdgDAwEd--IoYfZcCMlg" name="A_-_Ecological_classification-Grid" memberEnd="_TgFdgTAwEd--IoYfZcCMlg _TgFdhDAwEd--IoYfZcCMlg">
      <ownedEnd xmi:id="_TgFdgTAwEd--IoYfZcCMlg" name="has_ecological_classification" type="_3dw8YKx5EduvtrQ7BMslhA" association="_TgFdgDAwEd--IoYfZcCMlg">
        <upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_TgFdgzAwEd--IoYfZcCMlg" value="*"/>
        <lowerValue xmi:type="uml:LiteralInteger" xmi:id="_TgFdgjAwEd--IoYfZcCMlg" value="1"/>
      </ownedEnd>
      <ownedEnd xmi:id="_TgFdhDAwEd--IoYfZcCMlg" name="has_grid" type="_4xgcMKx5EduvtrQ7BMslhA" aggregation="composite" association="_TgFdgDAwEd--IoYfZcCMlg">
        <upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_TgFdhjAwEd--IoYfZcCMlg" value="1"/>
        <lowerValue xmi:type="uml:LiteralInteger" xmi:id="_TgFdhTAwEd--IoYfZcCMlg" value="1"/>
      </ownedEnd>
    </packagedElement>
    <packagedElement xmi:type="uml:DataType" xmi:id="_-V-9cDKDEd-yToNOK4bJsQ" name="georeferenceInfo"/>
    <packagedElement xmi:type="uml:DataType" xmi:id="_W5tDgDKHEd-yToNOK4bJsQ" name="cellSizeXDirection"/>
    <packagedElement xmi:type="uml:DataType" xmi:id="_b6rDADKHEd-yToNOK4bJsQ" name="cellSizeYDirection"/>
    <packagedElement xmi:type="uml:DataType" xmi:id="_kpKdIDKHEd-yToNOK4bJsQ" name="rows"/>
    <packagedElement xmi:type="uml:DataType" xmi:id="_mvuhADKHEd-yToNOK4bJsQ" name="columns"/>
  </packagedElement>
  <packagedElement xmi:type="uml:PrimitiveType" xmi:id="_La8cgKx6EduvtrQ7BMslhA" name="Boolean"/>
  <packagedElement xmi:type="uml:PrimitiveType" xmi:id="_LbFmcKx6EduvtrQ7BMslhA" name="Integer"/>
  <packagedElement xmi:type="uml:PrimitiveType" xmi:id="_LbFmcax6EduvtrQ7BMslhA" name="String"/>
  <packagedElement xmi:type="uml:PrimitiveType" xmi:id="_LbFmcqx6EduvtrQ7BMslhA" name="UnlimitedNatural"/>
</uml:Model>

Next, we show the rules applied by the UML2OWL transformation (see 2.3). This rules are applied in the UML model in orden to obtain the correspoding concept in OWL model. So that, the UML2OWL.atl transformation has as input the example.uml file and constructs has output the example-OWL.ecore one.

return to Contents


Applied rule: Model2Graph

It transforms the "Model" element of UML model to the "OWLGraph" element of OWL model.

rule Model2Graph {
from
m: UML!Model (
m.oclIsTypeOf(UML!Model)
)
to
g : OWL!OWLGraph (
ontology <- m.packagedElement->select( e | e.oclIsTypeOf(UML!Package)),
uriRef <- uri
),
d : OWL!Document (
namespaceDefinition <- nd,
localName <- ln,
xmlBase <- xb
),
ln : OWL!LocalName ( name <- m.name, uriRef <- uri ),
uri : OWL!URIReference ( uri <- u_r_i ),
u_r_i : OWL!UniformResourceIdentifier ( name <- thisModule.addNamespace(m.name) ),
xb : OWL!Namespace ( namespaceURIRef <- uri),
nd : OWL!NamespaceDefinition (
namespacePrefix <- thisModule.addNamespace(m.name),
namespace <- xb
)
}

Origin code :

<uml:Model xmi:version="2.1" xmlns:xmi="http://schema.omg.org/spec/XMI/2.1" xmlns:uml="http://www.eclipse.org/uml2/2.1.0/UML" xmi:id="_qb8akM37EdqwVrslYOdUDA" name="ontology">

Generated code:

<OWLGraph ontology="/4">
<uriRef uri="/2" fragmentIdentifier="/1/@localName.0" namespace="/3"/>
</OWLGraph>
<_1:Document xmlBase="/3">
<localName name="ontology" uriRef="/0/@uriRef.0"/>
<namespaceDefinition namespacePrefix="ontology" namespace="/3"/>
</_1:Document>
<_1:UniformResourceIdentifier name="ontology" uriRef="/0/@uriRef.0"/>
<_1:Namespace document="/1" namespaceURIRef="/0/@uriRef.0" namespaceDefinition="/1/@namespaceDefinition.0"/>

return to Contents


Applied rule: Package2Ontology

It transforms the "Package" element of UML model to the "Ontology" element of OWL model.

rule Package2Ontology {
from
p : UML!Package (
p.oclIsTypeOf(UML!Package)
)
to
o : OWL!OWLOntology (
uriRef <- u,
OWLImports <- p.packageImport->collect( e | e.importedPackage ),
owlGraph <- UML!Model.allInstances()->asSequence()
->any( m | m.oclIsTypeOf(UML!Model)),
owlUniverse <- p.packagedElement
),
u : OWL!URIReference ( fragmentIdentifier <- l, uri <- uri ),
l : OWL!LocalName ( name <- p.name ),
uri : OWL!UniformResourceIdentifier (
name <- thisModule.addNamespace(p.name)
)
}

Generated code :

<OWLOntology owlUniverse="/7 /10" owlGraph="/0">
<uriRef uri="/6" fragmentIdentifier="/5"/>
</OWLOntology>
<_1:LocalName name="http://www.ual.es/acg/soleres/ontology" uriRef="/4/@uriRef.0"/>
<_1:UniformResourceIdentifier name="http://www.ual.es/acg/soleres/ontology" uriRef="/4/@uriRef.0"/>

return to Contents


Applied rule: UMLClass2OWLClass

It transforms the "Class" element of UML model to the "OWLClass" element of OWL model.

rule UMLClass2OWLClass {
from
c : UML!Class (
c.oclIsTypeOf(UML!Class) and
not thisModule.sequenceOfUnionClass.includes(c)
)
to
oc : OWL!OWLClass (
subClassOf <- c.general,
uriRef <- u,
label <- label
),
label : OWL!PlainLiteral ( lexicalForm <- c.name        ),
u : OWL!URIReference ( fragmentIdentifier <- l,uri <- uri         ),
l : OWL!LocalName ( name <- c.name    ),
uri : OWL!UniformResourceIdentifier ( name <- c.name )
}

Example of origin code:

<packagedElement xmi:type="uml:Class" xmi:id="_3dw8YKx5EduvtrQ7BMslhA" name="Ecological_classification">

Example of generated code:

<OWLClass subClassOf="/69 /71 /73 /75 /90" propertyForDomain="/33 /36 /39 /42 /63" propertyForRange="/66" ontology="/4">
<uriRef uri="/9" fragmentIdentifier="/8"/>
<label lexicalForm="Ecological_classification"/>
</OWLClass>
<_1:LocalName name="Ecological_classification" uriRef="/7/@uriRef.0"/>
<_1:UniformResourceIdentifier name="Ecological_classification" uriRef="/7/@uriRef.0"/>

return to Contents


Applied rule: DataType2RDFSDataType

It transforms the "Datatype" elements of UML model to the "RDFSDataType" element of OWL model, mapping the defined types of the model.

rule DataType2RDFSDataType {
from
p : UML!Datatype
to
d : OWL!RDFSDataType (
uriRef <- u
),
u : OWL!URIReference (
uri <- uri
),
uri : OWL!UniformResourceIdentifier (
name <- thisModule.typeMap.get(p.name)
)
}

(helper rule used):

helper def: typeMap : Map(String, String) =
Map {
('String', 'xsd:string'),
('Integer', 'xsd:nonNegativeInteger'),
('Boolean', 'xsd:boolean'),
('UnlimitedNatural', 'xsd:integer' ),
('cellSizeXDirection', 'eml:cellSizeXDirection' ),
('cellSizeYDirection', 'eml:cellSizeYDirection' ),
('rows', 'eml:rows' ),
('columns', 'eml:columns' ),
('georeferenceInfo', 'eml:georeferenceInfo' )
};

Example of origin code (String type):

<packagedElement xmi:type="uml:PrimitiveType" xmi:id="_LbFmcax6EduvtrQ7BMslhA" name="String"/>

(and this code)

<packagedElement xmi:type="uml:Package" xmi:id="_w8IxIM37EdqwVrslYOdUDA" name="http://www.ual.es/acg/soleres/ontology">
<packagedElement xmi:type="uml:Class" xmi:id="_3dw8YKx5EduvtrQ7BMslhA" name="Ecological_classification">
<ownedAttribute xmi:id="_MfAK8DAxEd--IoYfZcCMlg" name="id" type="_LbFmcKx6EduvtrQ7BMslhA" aggregation="composite"/>
<ownedAttribute xmi:id="_Nx2S4DAxEd--IoYfZcCMlg" name="name" type="_LbFmcax6EduvtrQ7BMslhA" aggregation="composite"/>
<ownedAttribute xmi:id="_OcBRQDAxEd--IoYfZcCMlg" name="description" type="_LbFmcax6EduvtrQ7BMslhA" aggregation="composite"/>
<ownedAttribute xmi:id="_POYiUDAxEd--IoYfZcCMlg" name="observations" type="_LbFmcax6EduvtrQ7BMslhA" aggregation="composite"/>

Example of generated code:

<_1:RDFSDataType propertyForRange="/36 /39 /42">
<uriRef uri="/18"/>
</_1:RDFSDataType>
<_1:UniformResourceIdentifier name="xsd:string" uriRef="/17/@uriRef.0"/>

Example of origin code (georeferenceInfo type):

<packagedElement xmi:type="uml:DataType" xmi:id="_-V-9cDKDEd-yToNOK4bJsQ" name="georeferenceInfo"/>

(and this code)

<packagedElement xmi:type="uml:Class" xmi:id="_4xgcMKx5EduvtrQ7BMslhA" name="Grid">
<ownedAttribute xmi:id="_fzf6cDAxEd--IoYfZcCMlg" name="id" type="_LbFmcKx6EduvtrQ7BMslhA" aggregation="composite"/>
<ownedAttribute xmi:id="_eSBjwDD5Ed-YotXu97PIsA" name="cell_size_X" type="_W5tDgDKHEd-yToNOK4bJsQ" aggregation="composite"/>
<ownedAttribute xmi:id="_hG7UUDD5Ed-YotXu97PIsA" name="cell_size_Y" type="_b6rDADKHEd-yToNOK4bJsQ" aggregation="composite"/>
<ownedAttribute xmi:id="_iX_TkDD5Ed-YotXu97PIsA" name="row_size" type="_kpKdIDKHEd-yToNOK4bJsQ" aggregation="composite"/>
<ownedAttribute xmi:id="_l1RSwDD5Ed-YotXu97PIsA" name="column_size" type="_mvuhADKHEd-yToNOK4bJsQ" aggregation="composite"/>
<ownedAttribute xmi:id="_npC9gDD5Ed-YotXu97PIsA" name="georef_utm" type="_-V-9cDKDEd-yToNOK4bJsQ" aggregation="composite"/>

Example of generated code:

<_1:RDFSDataType propertyForRange="/58">
<resource href="/UML2OWL/Samples/OWLModels/example-OWL.ecore#/4"/>
<uriRef uri="/14"/>
</_1:RDFSDataType>
<_1:UniformResourceIdentifier name="eml:georeferenceInfo" uriRef="/13/@uriRef.0"/>

return to Contents


Applied rule: Property2DatatypeProperty

It transforms a "Property" element which is a "PrimitiveType" or a "DataType" to an "OWLDatatypeProperty" element. In addition, it calls helper rules to add cardinality restrictions if neccesary.

rule Property2DatatypeProperty {
from
p : UML!Property
(
p.type.oclIsTypeOf(UML!PrimitiveType) or p.type.oclIsTypeOf(UML!DataType)
)
to
d : OWL!OWLDatatypeProperty (
uriRef <- u,
domain <- p.class,
range <- p.type
),
u : OWL!URIReference ( fragmentIdentifier <- l, uri <- uri ),
l : OWL!LocalName ( name <- p.class.name + '.' + p.name ),
uri : OWL!UniformResourceIdentifier ( name <- p.class.name + '.' + p.name )

do {
if ( p.upper = p.lower )  -- [n-n]
thisModule.addCardinalityRestriction( p );
else
if (( p.upper = 0-1 ) and ( p.lower >= 0 )) -- [*]
thisModule.addMinCardinalityRestriction( p );
else  { -- [m-n]
thisModule.addMinCardinalityRestriction( p );
thisModule.addMaxCardinalityRestriction( p );
}
}
}

Example of origin code:

<ownedAttribute xmi:id="_npC9gDD5Ed-YotXu97PIsA" name="georef_utm" type="_pxx2gDD3Ed-YotXu97PIsA" aggregation="composite"/>

Example of generated code:

<OWLDatatypeProperty domain="/10" range="/23" propertyRestriction="/87">
<uriRef uri="/62" fragmentIdentifier="/61"/>
</OWLDatatypeProperty>
<_1:LocalName name="Grid.georef_utm" uriRef="/60/@uriRef.0"/>
<_1:UniformResourceIdentifier name="Grid.georef_utm" uriRef="/60/@uriRef.0"/>

return to Contents


Applied rule: Property2InverseObjectProperty

It transforms a "Property" element which is a "PrimitiveType", has a binary association which not be a "Class" type, and the property was not "InverseFunctional" type. The output of the transformation is a "OWLObjectProperty" element of the OWL model. Furthermore, it calls helper rules to add cardinality restrictions if neccesary.

rule Property2InverseObjectProperty {
from
p : UML!Property (
not (p.type.oclIsTypeOf(UML!PrimitiveType))
and if (p.association.oclIsUndefined())
then false
else if (p.association.isBinary() and not (p.association.oclIsKindOf(UML!Class)))
then (not p.isSymmetric() and not p.isInverseFunctional())
else false
endif                                         
endif
)
using {
inverse : UML!Property =
p.association.ownedEnd->asSequence()
->any( e | e.oclIsTypeOf(UML!Property) and not (e = p));
}
  to
o : OWL!OWLObjectProperty (
domain <- inverse.type,
range <- p.type,
OWLInverseOf <- inverse,
uriRef <- o_u,
subPropertyOf <- p.redefinedProperty
),
o_u : OWL!URIReference (    fragmentIdentifier <- o_l, uri <- o_uri ),
o_l : OWL!LocalName ( name <- inverse.type.name + '.' + p.name ),
o_uri : OWL!UniformResourceIdentifier ( name <- inverse.type.name + '.' + p.name )

do {
if ( ( p.upper = 1) and ( p.lower = 1) )
thisModule.addFunctionalProperty( p );
if ( p.upper = p.lower )  -- [n-n]
thisModule.addCardinality( p, inverse.type );
else
if (( p.upper = 0-1 ) and ( p.lower >= 0 )) -- [*]
thisModule.addMinCardinality( p, inverse.type );
else  {-- [m-n]
thisModule.addMinCardinality( p, inverse.type );
thisModule.addMaxCardinality( p, inverse.type );
}
}
}

Origin code:

<packagedElement xmi:type="uml:Association" xmi:id="_TgFdgDAwEd--IoYfZcCMlg" name="A_-_Ecological_classification-Grid" memberEnd="_TgFdgTAwEd--IoYfZcCMlg _TgFdhDAwEd--IoYfZcCMlg">

<ownedEnd xmi:id="_TgFdgTAwEd--IoYfZcCMlg" name="has_ecological_classification" type="_3dw8YKx5EduvtrQ7BMslhA" association="_TgFdgDAwEd--IoYfZcCMlg">
<upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_TgFdgzAwEd--IoYfZcCMlg" value="*"/>
<lowerValue xmi:type="uml:LiteralInteger" xmi:id="_TgFdgjAwEd--IoYfZcCMlg" value="1"/>
</ownedEnd>

<ownedEnd xmi:id="_TgFdhDAwEd--IoYfZcCMlg" name="has_grid" type="_4xgcMKx5EduvtrQ7BMslhA" aggregation="composite" association="_TgFdgDAwEd--IoYfZcCMlg">
<upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_TgFdhjAwEd--IoYfZcCMlg" value="1"/>
<lowerValue xmi:type="uml:LiteralInteger" xmi:id="_TgFdhTAwEd--IoYfZcCMlg" value="1"/>
</ownedEnd>

Generated code:

<OWLObjectProperty definedResource="/89" domain="/7" range="/10" propertyRestriction="/90" OWLInverseOf="/66" inverseProperty="/66">
<uriRef uri="/65" fragmentIdentifier="/64"/>
</OWLObjectProperty>
<_1:LocalName name="Ecological_classification.has_grid" uriRef="/63/@uriRef.0"/>
<_1:UniformResourceIdentifier name="Ecological_classification.has_grid" uriRef="/63/@uriRef.0"/>

return to Contents


Applied rule: Property2InverseFunctionalProperty

It transforms a "Property" element which is a "PrimitiveType", has a binary association which not be a "Class" type, and the property was "InverseFunctional" type. The output of the transformation is a "InverseFuncionalProperty" of OWL model. Furthermore, it calls helper rules to add cardinality restrictions if neccesary.

rule Property2InverseFunctionalProperty {
from
p : UML!Property (
not (p.type.oclIsTypeOf(UML!PrimitiveType))
and if (p.association.oclIsUndefined())
then false
else if (p.association.isBinary() and not (p.association.oclIsKindOf(UML!Class)))
then (p.isInverseFunctional() and not p.isSymmetric())
else false
endif
endif
)
using {
inverse : UML!Property =
p.association.ownedEnd->asSequence()
->any( e | e.oclIsTypeOf(UML!Property) and not (e = p));
}
to
o : OWL!InverseFunctionalProperty (
domain <- inverse.type,
range <- p.type,
OWLInverseOf <- inverse,
uriRef <- o_u,
subPropertyOf <- p.redefinedProperty
),
o_u : OWL!URIReference ( fragmentIdentifier <- o_l, uri <- o_uri ),
o_l : OWL!LocalName ( name <- inverse.type.name + '.' + p.name ),
o_uri : OWL!UniformResourceIdentifier ( name <- inverse.type.name + '.' + p.name )

do {

if ( ( p.upper = 1) and ( p.lower = 1) )
thisModule.addFunctionalProperty( p );
if ( p.upper = p.lower )  -- [n-n]
thisModule.addCardinality( p, inverse.type );
else
if (( p.upper = 0-1 ) and ( p.lower >= 0 )) -- [*]
thisModule.addMinCardinality( p, inverse.type );
else  {-- [m-n]
thisModule.addMinCardinality( p, inverse.type );
thisModule.addMaxCardinality( p, inverse.type );
}
}
}

Origin code:

<packagedElement xmi:type="uml:Association" xmi:id="_TgFdgDAwEd--IoYfZcCMlg" name="A_-_Ecological_classification-Grid" memberEnd="_TgFdgTAwEd--IoYfZcCMlg _TgFdhDAwEd--IoYfZcCMlg">

<ownedEnd xmi:id="_TgFdgTAwEd--IoYfZcCMlg" name="has_ecological_classification" type="_3dw8YKx5EduvtrQ7BMslhA" association="_TgFdgDAwEd--IoYfZcCMlg">
<upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_TgFdgzAwEd--IoYfZcCMlg" value="*"/>
<lowerValue xmi:type="uml:LiteralInteger" xmi:id="_TgFdgjAwEd--IoYfZcCMlg" value="1"/>
</ownedEnd>

<ownedEnd xmi:id="_TgFdhDAwEd--IoYfZcCMlg" name="has_grid" type="_4xgcMKx5EduvtrQ7BMslhA" aggregation="composite" association="_TgFdgDAwEd--IoYfZcCMlg">
<upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_TgFdhjAwEd--IoYfZcCMlg" value="1"/>
<lowerValue xmi:type="uml:LiteralInteger" xmi:id="_TgFdhTAwEd--IoYfZcCMlg" value="1"/>
</ownedEnd>

Generated code:

<InverseFunctionalProperty domain="/10" range="/7" propertyRestriction="/92" OWLInverseOf="/63" inverseProperty="/63">
<uriRef uri="/68" fragmentIdentifier="/67"/>
</InverseFunctionalProperty>
<_1:LocalName name="Grid.has_ecological_classification" uriRef="/66/@uriRef.0"/>
<_1:UniformResourceIdentifier name="Grid.has_ecological_classification" uriRef="/66/@uriRef.0"/>

return to Contents


Applied rule (called rule): addFunctionalProperty

It transforms a "Property" element of the UML model to an "FunctionalProperty" element of OWL model.

rule addFunctionalProperty( p : UML!Property ) {
to
o : OWL!FunctionalProperty (
isDefinedBy <- p
)
}

Generated code:

  <FunctionalProperty isDefinedBy="/63"/>

return to Contents


Applied rule (called rule): addCardinality

This rule adds an exact cardinality restriction to the property and the class indicated by parameter:

rule addCardinality( p : UML!Property, class : UML!Class ) {
to
c : OWL!CardinalityRestriction (
superClass <- class,
OWLCardinality <- literal,
OWLOnProperty <- p
),
literal : OWL!TypedLiteral (
lexicalForm <- p.upper.toString(),
datatypeURI <- thisModule.getIntegerURI()
)
}

Example of generated code:

<CardinalityRestriction superClass="/7" OWLOnProperty="/33" OWLCardinality="/70"/>
<_1:TypedLiteral lexicalForm="1" datatypeURI="/15/@uriRef.0" cardinalityRestriction="/69"/>

return to Contents


Applied rule (called rule): addMinCardinality

This rule adds an minimum cardinality restriction to the property and the class indicated by parameter:.

rule addMinCardinality( p : UML!Property, class : UML!Class ) {
to
c : OWL!MinCardinalityRestriction (
superClass <- class,
OWLMinCardinality <- literal,
OWLOnProperty <- p
),
literal : OWL!TypedLiteral (
lexicalForm <- p.lower.toString(),
datatypeURI <- thisModule.getIntegerURI()
)
}

Example of generated code:

<MinCardinalityRestriction superClass="/10" OWLOnProperty="/66" OWLMinCardinality="/93"/>
<_1:TypedLiteral lexicalForm="1" datatypeURI="/15/@uriRef.0" minCardinalityRestriction="/92"/>

return to Contents


3. 2. OWL2XML rules

Once we have executed all rules of UML2OWL.atl file of transformation, we obtain the OWL model. This is the code of the file "example-OWL.ecore":

<?xml version="1.0" encoding="ISO-8859-1"?>
<xmi:XMI xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns="OWL" xmlns:_1="RDFS">
<OWLGraph ontology="/4">
<uriRef uri="/2" fragmentIdentifier="/1/@localName.0" namespace="/3"/>
</OWLGraph>
<_1:Document xmlBase="/3">
<localName name="ontology" uriRef="/0/@uriRef.0"/>
<namespaceDefinition namespacePrefix="ontology" namespace="/3"/>
</_1:Document>
<_1:UniformResourceIdentifier name="ontology" uriRef="/0/@uriRef.0"/>
<_1:Namespace document="/1" namespaceURIRef="/0/@uriRef.0" namespaceDefinition="/1/@namespaceDefinition.0"/>
<OWLOntology owlUniverse="/7 /10 /13 /15 /17 /19 /21" owlGraph="/0">
<uriRef uri="/6" fragmentIdentifier="/5"/>
</OWLOntology>
<_1:LocalName name="http://www.ual.es/acg/soleres/ontology" uriRef="/4/@uriRef.0"/>
<_1:UniformResourceIdentifier name="http://www.ual.es/acg/soleres/ontology" uriRef="/4/@uriRef.0"/>
<OWLClass subClassOf="/67 /69 /71 /73 /88" propertyForDomain="/31 /34 /37 /40 /61" propertyForRange="/64" ontology="/4">
<uriRef uri="/9" fragmentIdentifier="/8"/>
<label lexicalForm="Ecological_classification"/>
</OWLClass>
<_1:LocalName name="Ecological_classification" uriRef="/7/@uriRef.0"/>
<_1:UniformResourceIdentifier name="Ecological_classification" uriRef="/7/@uriRef.0"/>
<OWLClass subClassOf="/75 /77 /79 /81 /83 /85 /90" propertyForDomain="/43 /46 /49 /52 /55 /58 /64" propertyForRange="/61" ontology="/4">
<uriRef uri="/12" fragmentIdentifier="/11"/>
<label lexicalForm="Grid"/>
</OWLClass>
<_1:LocalName name="Grid" uriRef="/10/@uriRef.0"/>
<_1:UniformResourceIdentifier name="Grid" uriRef="/10/@uriRef.0"/>
<_1:RDFSDataType propertyForRange="/58">
<resource href="/UML2OWL/Samples/OWLModels/example_2-OWL.ecore#/4"/>
<uriRef uri="/14"/>
</_1:RDFSDataType>
<_1:UniformResourceIdentifier name="eml:georeferenceInfo" uriRef="/13/@uriRef.0"/>
<_1:RDFSDataType propertyForRange="/46">
<resource href="/UML2OWL/Samples/OWLModels/example_2-OWL.ecore#/4"/>
<uriRef uri="/16"/>
</_1:RDFSDataType>
<_1:UniformResourceIdentifier name="eml:cellSizeXDirection" uriRef="/15/@uriRef.0"/>
<_1:RDFSDataType propertyForRange="/49">
<resource href="/UML2OWL/Samples/OWLModels/example_2-OWL.ecore#/4"/>
<uriRef uri="/18"/>
</_1:RDFSDataType>
<_1:UniformResourceIdentifier name="eml:cellSizeYDirection" uriRef="/17/@uriRef.0"/>
<_1:RDFSDataType propertyForRange="/52">
<resource href="/UML2OWL/Samples/OWLModels/example_2-OWL.ecore#/4"/>
<uriRef uri="/20"/>
</_1:RDFSDataType>
<_1:UniformResourceIdentifier name="eml:rows" uriRef="/19/@uriRef.0"/>
<_1:RDFSDataType propertyForRange="/55">
<resource href="/UML2OWL/Samples/OWLModels/example_2-OWL.ecore#/4"/>
<uriRef uri="/22"/>
</_1:RDFSDataType>
<_1:UniformResourceIdentifier name="eml:columns" uriRef="/21/@uriRef.0"/>
<_1:RDFSDataType>
<uriRef uri="/24"/>
</_1:RDFSDataType>
<_1:UniformResourceIdentifier name="xsd:boolean" uriRef="/23/@uriRef.0"/>
<_1:RDFSDataType propertyForRange="/31 /43">
<uriRef uri="/26" literal="/68 /70 /72 /74 /76 /78 /80 /82 /84 /86 /89 /91"/>
</_1:RDFSDataType>
<_1:UniformResourceIdentifier name="xsd:nonNegativeInteger" uriRef="/25/@uriRef.0"/>
<_1:RDFSDataType propertyForRange="/34 /37 /40">
<uriRef uri="/28"/>
</_1:RDFSDataType>
<_1:UniformResourceIdentifier name="xsd:string" uriRef="/27/@uriRef.0"/>
<_1:RDFSDataType>
<uriRef uri="/30"/>
</_1:RDFSDataType>
<_1:UniformResourceIdentifier name="xsd:integer" uriRef="/29/@uriRef.0"/>
<OWLDatatypeProperty domain="/7" range="/25" propertyRestriction="/67">
<uriRef uri="/33" fragmentIdentifier="/32"/>
</OWLDatatypeProperty>
<_1:LocalName name="Ecological_classification.id" uriRef="/31/@uriRef.0"/>
<_1:UniformResourceIdentifier name="Ecological_classification.id" uriRef="/31/@uriRef.0"/>
<OWLDatatypeProperty domain="/7" range="/27" propertyRestriction="/69">
<uriRef uri="/36" fragmentIdentifier="/35"/>
</OWLDatatypeProperty>
<_1:LocalName name="Ecological_classification.name" uriRef="/34/@uriRef.0"/>
<_1:UniformResourceIdentifier name="Ecological_classification.name" uriRef="/34/@uriRef.0"/>
<OWLDatatypeProperty domain="/7" range="/27" propertyRestriction="/71">
<uriRef uri="/39" fragmentIdentifier="/38"/>
</OWLDatatypeProperty>
<_1:LocalName name="Ecological_classification.description" uriRef="/37/@uriRef.0"/>
<_1:UniformResourceIdentifier name="Ecological_classification.description" uriRef="/37/@uriRef.0"/>
<OWLDatatypeProperty domain="/7" range="/27" propertyRestriction="/73">
<uriRef uri="/42" fragmentIdentifier="/41"/>
</OWLDatatypeProperty>
<_1:LocalName name="Ecological_classification.observations" uriRef="/40/@uriRef.0"/>
<_1:UniformResourceIdentifier name="Ecological_classification.observations" uriRef="/40/@uriRef.0"/>
<OWLDatatypeProperty domain="/10" range="/25" propertyRestriction="/75">
<uriRef uri="/45" fragmentIdentifier="/44"/>
</OWLDatatypeProperty>
<_1:LocalName name="Grid.id" uriRef="/43/@uriRef.0"/>
<_1:UniformResourceIdentifier name="Grid.id" uriRef="/43/@uriRef.0"/>
<OWLDatatypeProperty domain="/10" range="/15" propertyRestriction="/77">
<uriRef uri="/48" fragmentIdentifier="/47"/>
</OWLDatatypeProperty>
<_1:LocalName name="Grid.cell_size_X" uriRef="/46/@uriRef.0"/>
<_1:UniformResourceIdentifier name="Grid.cell_size_X" uriRef="/46/@uriRef.0"/>
<OWLDatatypeProperty domain="/10" range="/17" propertyRestriction="/79">
<uriRef uri="/51" fragmentIdentifier="/50"/>
</OWLDatatypeProperty>
<_1:LocalName name="Grid.cell_size_Y" uriRef="/49/@uriRef.0"/>
<_1:UniformResourceIdentifier name="Grid.cell_size_Y" uriRef="/49/@uriRef.0"/>
<OWLDatatypeProperty domain="/10" range="/19" propertyRestriction="/81">
<uriRef uri="/54" fragmentIdentifier="/53"/>
</OWLDatatypeProperty>
<_1:LocalName name="Grid.row_size" uriRef="/52/@uriRef.0"/>
<_1:UniformResourceIdentifier name="Grid.row_size" uriRef="/52/@uriRef.0"/>
<OWLDatatypeProperty domain="/10" range="/21" propertyRestriction="/83">
<uriRef uri="/57" fragmentIdentifier="/56"/>
</OWLDatatypeProperty>
<_1:LocalName name="Grid.column_size" uriRef="/55/@uriRef.0"/>
<_1:UniformResourceIdentifier name="Grid.column_size" uriRef="/55/@uriRef.0"/>
<OWLDatatypeProperty domain="/10" range="/13" propertyRestriction="/85">
<uriRef uri="/60" fragmentIdentifier="/59"/>
</OWLDatatypeProperty>
<_1:LocalName name="Grid.georef_utm" uriRef="/58/@uriRef.0"/>
<_1:UniformResourceIdentifier name="Grid.georef_utm" uriRef="/58/@uriRef.0"/>
<OWLObjectProperty definedResource="/87" domain="/7" range="/10" propertyRestriction="/88" OWLInverseOf="/64" inverseProperty="/64">
<uriRef uri="/63" fragmentIdentifier="/62"/>
</OWLObjectProperty>
<_1:LocalName name="Ecological_classification.has_grid" uriRef="/61/@uriRef.0"/>
<_1:UniformResourceIdentifier name="Ecological_classification.has_grid" uriRef="/61/@uriRef.0"/>
<InverseFunctionalProperty domain="/10" range="/7" propertyRestriction="/90" OWLInverseOf="/61" inverseProperty="/61">
<uriRef uri="/66" fragmentIdentifier="/65"/>
</InverseFunctionalProperty>
<_1:LocalName name="Grid.has_ecological_classification" uriRef="/64/@uriRef.0"/>
<_1:UniformResourceIdentifier name="Grid.has_ecological_classification" uriRef="/64/@uriRef.0"/>
<CardinalityRestriction superClass="/7" OWLOnProperty="/31" OWLCardinality="/68"/>
<_1:TypedLiteral lexicalForm="1" datatypeURI="/25/@uriRef.0" cardinalityRestriction="/67"/>
<CardinalityRestriction superClass="/7" OWLOnProperty="/34" OWLCardinality="/70"/>
<_1:TypedLiteral lexicalForm="1" datatypeURI="/25/@uriRef.0" cardinalityRestriction="/69"/>
<CardinalityRestriction superClass="/7" OWLOnProperty="/37" OWLCardinality="/72"/>
<_1:TypedLiteral lexicalForm="1" datatypeURI="/25/@uriRef.0" cardinalityRestriction="/71"/>
<CardinalityRestriction superClass="/7" OWLOnProperty="/40" OWLCardinality="/74"/>
<_1:TypedLiteral lexicalForm="1" datatypeURI="/25/@uriRef.0" cardinalityRestriction="/73"/>
<CardinalityRestriction superClass="/10" OWLOnProperty="/43" OWLCardinality="/76"/>
<_1:TypedLiteral lexicalForm="1" datatypeURI="/25/@uriRef.0" cardinalityRestriction="/75"/>
<CardinalityRestriction superClass="/10" OWLOnProperty="/46" OWLCardinality="/78"/>
<_1:TypedLiteral lexicalForm="1" datatypeURI="/25/@uriRef.0" cardinalityRestriction="/77"/>
<CardinalityRestriction superClass="/10" OWLOnProperty="/49" OWLCardinality="/80"/>
<_1:TypedLiteral lexicalForm="1" datatypeURI="/25/@uriRef.0" cardinalityRestriction="/79"/>
<CardinalityRestriction superClass="/10" OWLOnProperty="/52" OWLCardinality="/82"/>
<_1:TypedLiteral lexicalForm="1" datatypeURI="/25/@uriRef.0" cardinalityRestriction="/81"/>
<CardinalityRestriction superClass="/10" OWLOnProperty="/55" OWLCardinality="/84"/>
<_1:TypedLiteral lexicalForm="1" datatypeURI="/25/@uriRef.0" cardinalityRestriction="/83"/>
<CardinalityRestriction superClass="/10" OWLOnProperty="/58" OWLCardinality="/86"/>
<_1:TypedLiteral lexicalForm="1" datatypeURI="/25/@uriRef.0" cardinalityRestriction="/85"/>
<FunctionalProperty isDefinedBy="/61"/>
<CardinalityRestriction superClass="/7" OWLOnProperty="/61" OWLCardinality="/89"/>
<_1:TypedLiteral lexicalForm="1" datatypeURI="/25/@uriRef.0" cardinalityRestriction="/88"/>
<MinCardinalityRestriction superClass="/10" OWLOnProperty="/64" OWLMinCardinality="/91"/>
<_1:TypedLiteral lexicalForm="1" datatypeURI="/25/@uriRef.0" minCardinalityRestriction="/90"/>
</xmi:XMI>

As we can see in section 2.3, from this model, we are going to execute de OWL2XML transformation to obtain the file OWL file representation. Next, we show the rules applied; the OWL2XML.atl transformation has as input the example-OWL.ecore file and constructs has output the example.owl one.

return to Contents


Applied rule: Graph2Root

It rule transforms the "OWLGraph" element of OWL model to the root element of XML one. Also, it adds the pre-defined namespaces to the OWL file.

rule Graph2Root {
from g : OWL!OWLGraph
to
r : XML!Root (
name <- 'rdf:RDF',
children <- Sequence {
att1, att2, att3, att4, att5, att6,
g.ontology
}
),
att1 : XML!Attribute (name <- 'xmlns:rdf', value <- 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'),
att2 : XML!Attribute (name <- 'xmlns:rdfs', value <- 'http://www.w3.org/2000/01/rdf-schema#'),
att3 : XML!Attribute (name <- 'xmlns:xsd', value <- 'http://www.w3.org/2001/XMLSchema#'),
att4 : XML!Attribute (name <- 'xmlns:owl', value <- 'http://www.w3.org/2002/07/owl#'),
att5 : XML!Attribute (name <- 'xmlns:eml', value <- 'http://www.ual.es/acg/soleres/eml/eml-spatialRaster.xsd'),
att6 : XML!Attribute (name <- 'xmlns', value <- g.ontology->first().getURI() + '#'),
att7 : XML!Attribute (name <- 'xml:base', value <- g.ontology->first().getURI())             
}

Origin code:

<OWLGraph ontology="/4">
<uriRef uri="/2" fragmentIdentifier="/1/@localName.0" namespace="/3"/>
</OWLGraph>
<_1:Document xmlBase="/3">
<localName name="ontology" uriRef="/0/@uriRef.0"/>
<namespaceDefinition namespacePrefix="ontology" namespace="/3"/>
</_1:Document>
<_1:UniformResourceIdentifier name="ontology" uriRef="/0/@uriRef.0"/>
<_1:Namespace document="/1" namespaceURIRef="/0/@uriRef.0" namespaceDefinition="/1/@namespaceDefinition.0"/>

Generated code:

<rdf:RDF xmlns:rdf = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'
xmlns:rdfs = 'http://www.w3.org/2000/01/rdf-schema#'
xmlns:xsd = 'http://www.w3.org/2001/XMLSchema#'
xmlns:owl = 'http://www.w3.org/2002/07/owl#'
xmlns:eml = 'http://www.ual.es/acg/soleres/eml/eml-spatialRaster.xsd'
xmlns = 'http://www.ual.es/acg/soleres/ontology#'>

return to Contents


Applied rule:Ontology2Element

rule Ontology2Element {
from o : OWL!OWLOntology
to
e : XML!Element ( name <- 'owl:Ontology', children <- about ),
about : XML!Attribute (
name <- 'rdf:about',
value <- o.uriRef->collect( e | e.fragmentIdentifier.name )->flatten()->first()
)       
do {
for ( i in o.OWLImports ) {
thisModule.addImports( o, i ); } } }

Origin code:

<OWLOntology owlUniverse="/7 /10 /13 /15 /17 /19 /21" owlGraph="/0">
<uriRef uri="/6" fragmentIdentifier="/5"/>
</OWLOntology>
<_1:LocalName name="http://www.ual.es/acg/soleres/ontology" uriRef="/4/@uriRef.0"/>
<_1:UniformResourceIdentifier name="http://www.ual.es/acg/soleres/ontology" uriRef="/4/@uriRef.0"/>

Generated code:

  <owl:Ontology rdf:about = 'http://www.ual.es/acg/soleres/ontology'/>

return to Contents


Applied rule:Class2Element

rule Class2Element{
from
c : OWL!OWLClass (
c.oclIsTypeOf(OWL!OWLClass)
)
to
e : XML!Element (
name <- 'owl:Class',
children <- Sequence{ID,label},
parent <- OWL!OWLGraph.allInstances()->any( e | e.oclIsTypeOf(OWL!OWLGraph))
),
ID : XML!Attribute ( name <- 'rdf:ID', value <- c.getURI() ),
label : XML!Element ( name <- 'rdfs:label', children <- label_text ),
label_text : XML!Text ( name <- '#text', value <- c.getLabel() )
do {
for (s in c.subClassOf ) {
if (s.oclIsTypeOf(OWL!OWLClass))
thisModule.makeSubClass(c,s);

if (s.oclIsTypeOf(OWL!UnionClass))
thisModule.makeSubClass(c,s);

if (s.oclIsTypeOf(OWL!CardinalityRestriction))
thisModule.makeCardinalityRestrictionSubClass(c,s);

if (s.oclIsTypeOf(OWL!MaxCardinalityRestriction))
thisModule.makeMaxCardinalityRestrictionSubClass(c,s);

if (s.oclIsTypeOf(OWL!MinCardinalityRestriction))
thisModule.makeMinCardinalityRestrictionSubClass(c,s); } } }

Example of origin code:

<OWLClass subClassOf="/67 /69 /71 /73 /88" propertyForDomain="/31 /34 /37 /40 /61" propertyForRange="/64" ontology="/4">
<uriRef uri="/9" fragmentIdentifier="/8"/>
<label lexicalForm="Ecological_classification"/>
</OWLClass>
<_1:LocalName name="Ecological_classification" uriRef="/7/@uriRef.0"/>
<_1:UniformResourceIdentifier name="Ecological_classification" uriRef="/7/@uriRef.0"/>

Example of generated code:

<owl:Class rdf:ID = 'Ecological_classification'>
<rdfs:label>Ecological_classification</rdfs:label>
</owl:Class>

return to Contents


Applied rule (called rule):makeCardinalityRestrictionSubClass

rule makeCardinalityRestrictionSubClass( c : OWL!OWLClass,  s : OWL!CardinalityRestriction ) {
to
x : XML!Element (
name <- 'rdfs:subClassOf',
children <-  e,
parent <- c
),
e : XML!Element ( name <- 'owl:Restriction', children <- Sequence{on, card} ),
on : XML!Element ( name <- 'owl:onProperty', children <- on_attr ),
on_attr : XML!Attribute ( name <- 'rdf:resource', value <- '#' + s.OWLOnProperty.getURI() ),
card : XML!Element ( name <- 'owl:cardinality ', children <- Sequence{card_attr, card_text}   ),
card_attr : XML!Attribute ( name <- 'rdf:datatype', value <- s.getDatatypeURI()     ),
card_text : XML!Text ( name <- '#text',        value <- s.OWLCardinality.lexicalForm )
}

Example of origin code:

<CardinalityRestriction superClass="/7" OWLOnProperty="/31" OWLCardinality="/68"/>
<_1:TypedLiteral lexicalForm="1" datatypeURI="/25/@uriRef.0" cardinalityRestriction="/67"/>

Example of generated code:

<rdfs:subClassOf>
<owl:Restriction>
<owl:onProperty rdf:resource = '#Ecological_classification.id'/>
<owl:cardinality  rdf:datatype = 'xsd:nonNegativeInteger'>1</owl:cardinality >
</owl:Restriction>
</rdfs:subClassOf>

return to Contents


Applied rule: makeMinCardinalityRestriction

rule makeMinCardinalityRestrictionSubClass( c : OWL!OWLClass,  s : OWL!MinCardinalityRestriction ) {
to
x : XML!Element (
name <- 'rdfs:subClassOf',
children <-  e,
parent <- c
),
e : XML!Element (
name <- 'owl:Restriction',
children <- Sequence{on, card}
),
on : XML!Element ( name <- 'owl:onProperty', children <- on_attr ),
on_attr : XML!Attribute ( name <- 'rdf:resource', value <- '#' + s.OWLOnProperty.getURI() ),
card : XML!Element ( name <- 'owl:minCardinality ',     children <- Sequence{card_attr, card_text} ),
card_attr : XML!Attribute ( name <- 'rdf:datatype', value <- s.getDatatypeURI()     ),
card_text : XML!Text ( name <- '#text',        value <- s.OWLMinCardinality.lexicalForm )
}

Example of origin code:

<MinCardinalityRestriction superClass="/10" OWLOnProperty="/64" OWLMinCardinality="/91"/>
<_1:TypedLiteral lexicalForm="1" datatypeURI="/25/@uriRef.0" minCardinalityRestriction="/90"/>

Example of generated code:

<rdfs:subClassOf>
<owl:Restriction>
<owl:onProperty rdf:resource = '#Grid.has_ecological_classification'/>
<owl:minCardinality  rdf:datatype = 'xsd:nonNegativeInteger'>1</owl:minCardinality >
</owl:Restriction>
</rdfs:subClassOf>

return to Contents


Applied rule: DatatypeProperty2Element

rule DatatypeProperty2Element {
from
d : OWL!OWLDatatypeProperty
to
e : XML!Element (
name <- 'owl:DatatypeProperty',
children <- Sequence{ID,domain,range},
parent <- OWL!OWLGraph.allInstances()->any( e | e.oclIsTypeOf(OWL!OWLGraph))
),
ID : XML!Attribute (
name <- 'rdf:ID',
value <- d.getURI()
),
domain : XML!Element (
name <- 'rdfs:domain',
children <- domain_attr
),
domain_attr : XML!Attribute (
name <- 'rdf:resource',
value <- '#' + d.domain->any( c | c.oclIsKindOf(OWL!OWLClass)).getURI()
),
range : XML!Element (
name <- 'rdfs:range',
children <- range_attr
),
range_attr : XML!Attribute (
name <- 'rdf:resource',
value <-  d.range->any(c | c.oclIsKindOf(OWL!RDFSDataType)).getURI()
)
}

Example of origin code:

<OWLDatatypeProperty domain="/7" range="/25" propertyRestriction="/67">
<uriRef uri="/33" fragmentIdentifier="/32"/>
</OWLDatatypeProperty>
<_1:LocalName name="Ecological_classification.id" uriRef="/31/@uriRef.0"/>
<_1:UniformResourceIdentifier name="Ecological_classification.id" uriRef="/31/@uriRef.0"/>

Example of generated code:

<owl:DatatypeProperty rdf:ID = 'Ecological_classification.id'>
<rdfs:domain rdf:resource = '#Ecological_classification'/>
<rdfs:range rdf:resource = 'xsd:nonNegativeInteger'/>
</owl:DatatypeProperty>

return to Contents


Applied rule: ObjectProperty2Element

rule ObjectProperty2Element {
from
o : OWL!OWLObjectProperty (
o.oclIsTypeOf(OWL!OWLObjectProperty)
)
to
e : XML!Element (
name <- 'owl:ObjectProperty',
children <- Sequence{ID, domain, range},
parent <- OWL!OWLGraph.allInstances()->any( e | e.oclIsTypeOf(OWL!OWLGraph))
),
ID : XML!Attribute (
name <- 'rdf:ID',
value <- o.getURI()
),
domain : XML!Element (
name <- 'rdfs:domain',
children <- domain_attr
),
domain_attr : XML!Attribute (
name <-  'rdf:resource',
value <- '#' + o.domain->any( c | c.oclIsKindOf(OWL!OWLClass)).getURI()
),
range : XML!Element (
name <- 'rdfs:range',
children <- range_attr
),
range_attr : XML!Attribute (
name <- 'rdf:resource',
value <- '#' + o.range->any( c | c.oclIsKindOf(OWL!OWLClass)).getURI()
)

do {
if (not o.OWLInverseOf.oclIsUndefined())
thisModule.addInverse(o);

for (s in o.subPropertyOf ) {
if (s.oclIsKindOf(OWL!OWLObjectProperty))
thisModule.makeSubProperty(o,s); } } }

 (called rule)

rule addInverse( o : OWL!OWLObjectProperty ) {
to
e : XML!Element (
name <- 'owl:inverseOf',
children <- e_attr,
parent <- o
),
e_attr : XML!Attribute (
name <- 'rdf:resource',
value <- '#' + o.OWLInverseOf.getURI()
)
}

Example of origin code:

<OWLObjectProperty definedResource="/87" domain="/7" range="/10" propertyRestriction="/88" OWLInverseOf="/64"     inverseProperty="/64">
<uriRef uri="/63" fragmentIdentifier="/62"/>
</OWLObjectProperty>
<_1:LocalName name="Ecological_classification.has_grid" uriRef="/61/@uriRef.0"/>
<_1:UniformResourceIdentifier name="Ecological_classification.has_grid" uriRef="/61/@uriRef.0"/>

Example of generated code:

<owl:ObjectProperty rdf:ID = 'Ecological_classification.has_grid'>
<rdfs:domain rdf:resource = '#Ecological_classification'/>
<rdfs:range rdf:resource = '#Grid'/>
<owl:inverseOf rdf:resource = '#Grid.has_ecological_classification'/>
</owl:ObjectProperty>

return to Contents


Applied rule: InverseFunctionalProperty2Element

rule InverseFunctionalProperty2Element {
from
o : OWL!InverseFunctionalProperty (
o.oclIsTypeOf(OWL!InverseFunctionalProperty)
)
to
e : XML!Element (
name <- 'owl:InverseFunctionalProperty',
children <- Sequence{ID, domain, range},
parent <- OWL!OWLGraph.allInstances()->any( e | e.oclIsTypeOf(OWL!OWLGraph))
),
ID : XML!Attribute (
name <- 'rdf:ID',
value <- o.getURI()
),
domain : XML!Element (
name <- 'rdfs:domain',
children <- domain_attr
),
domain_attr : XML!Attribute (
name <-  'rdf:resource',
value <- '#' + o.domain->any( c | c.oclIsKindOf(OWL!OWLClass)).getURI()
),
range : XML!Element (
name <- 'rdfs:range',
children <- range_attr
),
range_attr : XML!Attribute (
name <- 'rdf:resource',
value <- '#' + o.range->any( c | c.oclIsKindOf(OWL!OWLClass)).getURI()
)

do {
if (not o.OWLInverseOf.oclIsUndefined())
thisModule.addInverse(o);

for (s in o.subPropertyOf ) {
if (s.oclIsKindOf(OWL!OWLObjectProperty))
thisModule.makeSubProperty(o,s); } } }

(called rule)

rule addInverse( o : OWL!OWLObjectProperty ) {
to
e : XML!Element (
name <- 'owl:inverseOf',
children <- e_attr,
parent <- o
),
e_attr : XML!Attribute (
name <- 'rdf:resource',
value <- '#' + o.OWLInverseOf.getURI()
)

Example of origin code:

<InverseFunctionalProperty domain="/10" range="/7" propertyRestriction="/90" OWLInverseOf="/61" inverseProperty="/61">
<uriRef uri="/66" fragmentIdentifier="/65"/>
</InverseFunctionalProperty>
<_1:LocalName name="Grid.has_ecological_classification" uriRef="/64/@uriRef.0"/>
<_1:UniformResourceIdentifier name="Grid.has_ecological_classification" uriRef="/64/@uriRef.0"/>

Example of generated code:

<owl:InverseFunctionalProperty rdf:ID = 'Grid.has_ecological_classification'>
<rdfs:domain rdf:resource = '#Grid'/>
<rdfs:range rdf:resource = '#Ecological_classification'/>
<owl:inverseOf rdf:resource = '#Ecological_classification.has_grid'/>
</owl:InverseFunctionalProperty>

return to Contents


Applied rule (called rule): FunctionalProperty

rule FunctionalProperty {
from
o : OWL!FunctionalProperty (
o.oclIsTypeOf( OWL!FunctionalProperty )
)
to
e : XML!Element (
name <- 'owl:FunctionalProperty',
children <- a,
parent <- OWL!OWLGraph.allInstances()->any( e | e.oclIsTypeOf(OWL!OWLGraph))
),
a : XML!Attribute (
name <- 'rdf:about',
value <- '#' + o.isDefinedBy->asSequence()->any( e | e.oclIsKindOf(OWL!Property ) ).getURI()
)
}

Example of origin code:

  <FunctionalProperty isDefinedBy="/61"/>

Example of generated code:

  <owl:FunctionalProperty rdf:about = '#Ecological_classification.has_grid'/>

return to Contents


3. 3. Result of process

Once we have executed all rules of OWL2XML.atl file of transformation, we obtain the XML model which is equivalent with the ".owl" file representing the final EID ontology:

<?xml version = '1.0' encoding = 'ISO-8859-1' ?>
<rdf:RDF xmlns:rdf = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#' xmlns:rdfs = 'http://www.w3.org/2000/01/rdf-schema#' xmlns:xsd = 'http://www.w3.org/2001/XMLSchema#' xmlns:owl = 'http://www.w3.org/2002/07/owl#' xmlns:eml = 'http://www.ual.es/acg/soleres/eml/eml-spatialRaster.xsd' xmlns = 'http://www.ual.es/acg/soleres/ontology#'>
<owl:Ontology rdf:about = 'http://www.ual.es/acg/soleres/ontology'/>
<owl:Class rdf:ID = 'Ecological_classification'>
<rdfs:label>Ecological_classification</rdfs:label>
<rdfs:subClassOf>
<owl:Restriction>
<owl:onProperty rdf:resource = '#Ecological_classification.id'/>
<owl:cardinality  rdf:datatype = 'xsd:nonNegativeInteger'>1</owl:cardinality >
</owl:Restriction>
</rdfs:subClassOf>
<rdfs:subClassOf>
<owl:Restriction>
<owl:onProperty rdf:resource = '#Ecological_classification.name'/>
<owl:cardinality  rdf:datatype = 'xsd:nonNegativeInteger'>1</owl:cardinality >
</owl:Restriction>
</rdfs:subClassOf>
<rdfs:subClassOf>
<owl:Restriction>
<owl:onProperty rdf:resource = '#Ecological_classification.description'/>
<owl:cardinality  rdf:datatype = 'xsd:nonNegativeInteger'>1</owl:cardinality >
</owl:Restriction>
</rdfs:subClassOf>
<rdfs:subClassOf>
<owl:Restriction>
<owl:onProperty rdf:resource = '#Ecological_classification.observations'/>
<owl:cardinality  rdf:datatype = 'xsd:nonNegativeInteger'>1</owl:cardinality >
</owl:Restriction>
</rdfs:subClassOf>
<rdfs:subClassOf>
<owl:Restriction>
<owl:onProperty rdf:resource = '#Ecological_classification.has_grid'/>
<owl:cardinality  rdf:datatype = 'xsd:nonNegativeInteger'>1</owl:cardinality >
</owl:Restriction>
</rdfs:subClassOf>
</owl:Class>
<owl:Class rdf:ID = 'Grid'>
<rdfs:label>Grid</rdfs:label>
<rdfs:subClassOf>
<owl:Restriction>
<owl:onProperty rdf:resource = '#Grid.id'/>
<owl:cardinality  rdf:datatype = 'xsd:nonNegativeInteger'>1</owl:cardinality >
</owl:Restriction>
</rdfs:subClassOf>
<rdfs:subClassOf>
<owl:Restriction>
<owl:onProperty rdf:resource = '#Grid.cell_size_X'/>
<owl:cardinality  rdf:datatype = 'xsd:nonNegativeInteger'>1</owl:cardinality >
</owl:Restriction>
</rdfs:subClassOf>
<rdfs:subClassOf>
<owl:Restriction>
<owl:onProperty rdf:resource = '#Grid.cell_size_Y'/>
<owl:cardinality  rdf:datatype = 'xsd:nonNegativeInteger'>1</owl:cardinality >
</owl:Restriction>
</rdfs:subClassOf>
<rdfs:subClassOf>
<owl:Restriction>
<owl:onProperty rdf:resource = '#Grid.row_size'/>
<owl:cardinality  rdf:datatype = 'xsd:nonNegativeInteger'>1</owl:cardinality >
</owl:Restriction>
</rdfs:subClassOf>
<rdfs:subClassOf>
<owl:Restriction>
<owl:onProperty rdf:resource = '#Grid.column_size'/>
<owl:cardinality  rdf:datatype = 'xsd:nonNegativeInteger'>1</owl:cardinality >
</owl:Restriction>
</rdfs:subClassOf>
<rdfs:subClassOf>
<owl:Restriction>
<owl:onProperty rdf:resource = '#Grid.georef_utm'/>
<owl:cardinality  rdf:datatype = 'xsd:nonNegativeInteger'>1</owl:cardinality >
</owl:Restriction>
</rdfs:subClassOf>
<rdfs:subClassOf>
<owl:Restriction>
<owl:onProperty rdf:resource = '#Grid.has_ecological_classification'/>
<owl:minCardinality  rdf:datatype = 'xsd:nonNegativeInteger'>1</owl:minCardinality >
</owl:Restriction>
</rdfs:subClassOf>
</owl:Class>
<owl:DatatypeProperty rdf:ID = 'Ecological_classification.id'>
<rdfs:domain rdf:resource = '#Ecological_classification'/>
<rdfs:range rdf:resource = 'xsd:nonNegativeInteger'/>
</owl:DatatypeProperty>
<owl:DatatypeProperty rdf:ID = 'Ecological_classification.name'>
<rdfs:domain rdf:resource = '#Ecological_classification'/>
<rdfs:range rdf:resource = 'xsd:string'/>
</owl:DatatypeProperty>
<owl:DatatypeProperty rdf:ID = 'Ecological_classification.description'>
<rdfs:domain rdf:resource = '#Ecological_classification'/>
<rdfs:range rdf:resource = 'xsd:string'/>
</owl:DatatypeProperty>
<owl:DatatypeProperty rdf:ID = 'Ecological_classification.observations'>
<rdfs:domain rdf:resource = '#Ecological_classification'/>
<rdfs:range rdf:resource = 'xsd:string'/>
</owl:DatatypeProperty>
<owl:DatatypeProperty rdf:ID = 'Grid.id'>
<rdfs:domain rdf:resource = '#Grid'/>
<rdfs:range rdf:resource = 'xsd:nonNegativeInteger'/>
</owl:DatatypeProperty>
<owl:DatatypeProperty rdf:ID = 'Grid.cell_size_X'>
<rdfs:domain rdf:resource = '#Grid'/>
<rdfs:range rdf:resource = 'eml:cellSizeXDirection'/>
</owl:DatatypeProperty>
<owl:DatatypeProperty rdf:ID = 'Grid.cell_size_Y'>
<rdfs:domain rdf:resource = '#Grid'/>
<rdfs:range rdf:resource = 'eml:cellSizeYDirection'/>
</owl:DatatypeProperty>
<owl:DatatypeProperty rdf:ID = 'Grid.row_size'>
<rdfs:domain rdf:resource = '#Grid'/>
<rdfs:range rdf:resource = 'eml:rows'/>
</owl:DatatypeProperty>
<owl:DatatypeProperty rdf:ID = 'Grid.column_size'>
<rdfs:domain rdf:resource = '#Grid'/>
<rdfs:range rdf:resource = 'eml:columns'/>
</owl:DatatypeProperty>
<owl:DatatypeProperty rdf:ID = 'Grid.georef_utm'>
<rdfs:domain rdf:resource = '#Grid'/>
<rdfs:range rdf:resource = 'eml:georeferenceInfo'/>
</owl:DatatypeProperty>
<owl:ObjectProperty rdf:ID = 'Ecological_classification.has_grid'>
<rdfs:domain rdf:resource = '#Ecological_classification'/>
<rdfs:range rdf:resource = '#Grid'/>
<owl:inverseOf rdf:resource = '#Grid.has_ecological_classification'/>
</owl:ObjectProperty>
<owl:InverseFunctionalProperty rdf:ID = 'Grid.has_ecological_classification'>
<rdfs:domain rdf:resource = '#Grid'/>
<rdfs:range rdf:resource = '#Ecological_classification'/>
<owl:inverseOf rdf:resource = '#Ecological_classification.has_grid'/>
</owl:InverseFunctionalProperty>
<owl:FunctionalProperty rdf:about = '#Ecological_classification.has_grid'/>
</rdf:RDF>

return to Contents