GME 1.3 Developers Guide
[ caGrid 1.3 Documentation | GME 1.3 Documentation | GME 1.3 Developers Guide ]
GME Overview
Service Operations Overview
The GME, as an XML Schema registry, supports basic publish, update, delete, and retrieve operations. XML Schemas (represented using XMLSchema) are uniquely identified by GME using their target namespaces (represented using XMLSchemaNamespace).
The publishXMLSchemas operation is used for all publish and update operations (update is not yet supported in the current version of the GME, but will use this operation when it is). It is used to store new XML Schemas in the GME, and the schemas that are published are required to be fully defined (i.e. all imported schemas must be valid and present), using the combination of XML Schemas supplied and those already published. For example, if one uploads XML Schema "A" that imports XML Schema "B," the "B" XML Schema must already be published or be contained in the array of XMLSchema being published. For more information on the processing behavior of the publish operation, see the GME Design Guide.
Once an XML Schema is published, the GME provides various operations for viewing information about the schema, including its dependencies (getImportedXMLSchemaNamespaces) and the schemas which depend upon it (getImportingXMLSchemaNamespaces). It can then be downloaded via the getXMLSchema operation, which only retrieves that particular schema, or the getXMLSchemaAndDependencies operation, which returns an XMLSchemaBundle containing that schema and every schema required to fully resolve its dependencies (which could be a complex graph of schemas). The client API also provides a utility operation, cacheSchemas, which internally calls the getXMLSchemaAndDependencies operation, and writes all of the retrieved schemas to the file system, handling any potential naming conflicts.
The GME allows one to retrieve the list of targetNamespaces of all of its published XML Schemas via the getXMLSchemaNamespaces operation. Finally, it allows a collection of XML Schemas to be deleted via the deleteXMLSchemas operation. Similar to the publishXMLSchemas operation, this takes an array of XML Schemas (actually just their targetNamespace) so that a schema and all of the schemas which depend upon it can be deleted at the same time (as attempting to delete a schema which has other schemas depending upon it will generate an error). For more information on the processing behavior of the delete operation, see the GME Design Guide.
GME Class Model
All operations of the GME work with the Class Model shown below, which is a representational model for describing XML Schemas and their dependencies.

The primary means by which an XML Schema is identified by external entities is its targetNamespace (see the XML Schema Specification
). This is a URI, and is represented as such in the GME model when used as an attribute within a class (such as in the XMLSchema class), but is represented using the XMLSchemaNamespace when used by itself (such as when it is the input or output of an operation).
XML Schemas can be comprised of multiple actual "documents." As such, the GME model represents XML Schemas using the XMLSchema class, which consists of one or more XMLSchemaDocuments. An XMLSchema has a targetNamespace a "root" document (XMLSchemaDocument), and zero or more additional documents (XMLSchemaDocuments). Each XMLSchemaDocument has a unique (within an XMLSchema) identifier, represented by the systemID attribute (see the XML Specification
), and the actual text of the document, represented by the schemaText attribute.
The XMLSchema, XMLSchemaDocument, and XMLSchemaNamespace are the only Classes the GME client uses to describe XML Schemas to the GME service. The GME service uses two additional Classes, XMLSchemaBundle and XMLSchemaImportInformation to describe, to the client, additional details about how XML Schemas relate to each other. The XMLSchemaImportInformation Class is used to describe the set of XML Schemas (identified via a set of XMLSchemaNamespace representing their targetNamespaces) imported by a given XML Schema (identified via its targetNamespace). The XMLSchemaBundle class conceptually represents a graph of XML Schemas. It is a complex data structure which contains a set of XMLSchema and a set of XMLSchemaImportInformation and utility methods to interrogate those sets, such as getImportedSchemasForTargetNamespace{*}.
The GME is able to provide a class model with complex data structures (such as using Java5 typed collections), and utility operations, as it leverages Castor
for serialization and deserialization into custom, hand written Java Beans.
Migrating from the Deprecated GME
Previous versions of caGrid included a conceptually similar but functionally different GME. There is no API-level equivalency between these projects, as the current GME is a ground up redesign aimed at addressing the limitations of the previous GME. For example, the current GME models XML Schemas as being comprised of one or more XML Schema Documents. This allows it to support such features as xsd:include
and xsd:redefine
. In addition, the current GME allows multiple schemas to be published at the same time, whereas the previous implementation only allowed a single document to be published at a time. This prevented XML Schemas with cyclic imports (for example A imports B imports A) from being published as their dependencies could never be resolved; the new GME supports processing such schemas.
In using the new GME, the basic workflow of the API is similar to the previous API. However, the current client API, now being a standard Introduce-created service, follows the expected usage, whereas the previous API required using a specialized Mobius API
to leverage the grid service; this is no longer necessary.
Using the GME User Interface
The GME provides graphical user interface components via integration with the Introduce service development environment; even if you aren't planning to develop services, you may use this capability. The integration takes two forms: 1) a general ability to view, download, and upload XML Schemas, described in the GME Browsing and Upload section and 2) an ability to add XML Schemas from a GME to an Introduce service, described in the GME Schema Discovery section.
The GME with which Introduce will communicate is configured via the GME Service URL value in the Global Extension Properties in the Introduce Preferences. Generally this value is automatically set when you configure caGrid to use a particular grid.
GME Browsing and Upload
To use the GME's ability to upload, view, or download schemas, you must first launch Introduce, by typing 'ant introduce' from the caGrid directory, as described in the Introduce documentation. Once Introduce has launched, you can click the Browse Data Types button on the top toolbar, and click the Global Model Exchange tab on the Browse Data Types window that opens up (shown below).

This window initially shows the "Browse" tab, and contains a drop down labeled "Target Namespace" which is populated with all of the targetNamespaces of the XML Schemas which have been published to the GME. Selecting a particular namespace will display the text of the root document of the XML Schema with the corresponding targetNamespace, in the text area labeled "Schema Root Document Text." You can also download the schema and all of its dependencies to a directory on your local file system by selecting its namespace and pressing the "Download Schemas and Dependencies..." button. This will prompt you for a directory, and will then write all of the files to the selected directory (this uses the API described in the Retrieving an XML Schema Bundle example).
Upon switching to the "Upload" tab, a user interface for publishing schemas to the GME is shown. The top window of the panel shows any errors which currently exist in the submission package (note: it initially displays an error indicating no schemas have been selected to be published).

The Add Schemas... button can be used to launch a file browser to locate schemas from the local file system which should be published. This can be used repeatedly to locate all schemas that should be uploaded as a group. If you need to remove a schema because it contains an erorr or was accidentally added, you can select it and press the Remove Selected Schema button (NOTE: this removes it from the schema submission package, not the server). For each schema added to the submission package, it will be shown in the "XML Schemas" panel, represented by its targetNamespace. Upon selecting one of these namespaces, the "Documents comprising selected Schema" panel will be populated with the actual XML Schema Documents which are needed to comprise this schema. For most cases, this will just be the single schema file which was selected, but for schemas which make use of xsd:redefine or xsd:include, multiple documents may be shown (NOTE: to add schemas which make use of xsd:include or xsd:redefine, you should just select the "root" schema and the other documents will automatically be added). Selecting a document from the this list will display its textual content in the "Schema Preview" panel. The screen shot below illustrates the interface when a single XML Schemas is to be published which consists of two actual documents. Once all desired XML Schemas have been added to the interface, and there are no errors shown in the top panel, the Publish Schemas button can be pressed to publish the schemas. If this completes without error, a success dialog will be shown, and the schemas should be able to be found using the "Browse" tab of the same window (after pressing the Refresh button).

GME Schema Discovery
When doing service development with Introduce, a key aspect is to be able to discover and add data types (in the form of XML Schemas) for use in the service's operations. To facilitate the use of the GME for this purpose, a GME data type discovery extension (see the Introduce design guide is provided. Shown below, this component embeds itself into the "Import Data Types" panel of the "Types" tab. Its use is fairly straight forward, as a drop down of the currently publish XML Schemas (represented by their targetNamespacess) is shown, and when the Add button is pressed the selected schema and all of its dependencies are downloaded and added to the service. For example, in the screen shot below, when the "gme://a" schema was added, the "gme://b" schemas was also added as "gme://a" imports it, as was "gme://c" as "gme://b" imports it (as shown in the "Imported Data Types" window on the left of the screen shot).

Security Considerations
As the GME is typically deployed as a secure service (though currently it is not strictly required by the GME), in order to use its client API one must synchronize with a trust fabric as described in the GTS Developer's Guide. Failure to do so, may yield exceptions similar to the stack trace shown below (pay particular attention to the "Caused by: Unknown CA" message).
AxisFault
faultCode: {http://schemas.xmlsoap.org/soap/envelope/}Server.userException
faultSubcode:
faultString: org.globus.common.ChainedIOException: Authentication failed [Caused by: Failure unspecified at GSS-API level [Caused by: Unknown CA]]
faultActor:
faultNode:
faultDetail:
{http://xml.apache.org/axis/}stackTrace:Authentication failed. Caused by Failure unspecified at GSS-API level. Caused by COM.claymoresystems.ptls.SSLThrewAlertException: Unknown CA
at COM.claymoresystems.ptls.SSLConn.alert(SSLConn.java:235)
at COM.claymoresystems.ptls.SSLHandshake.recvCertificate(SSLHandshake.java:304)
at COM.claymoresystems.ptls.SSLHandshakeClient.processTokens(SSLHandshakeClient.java:128)
at COM.claymoresystems.ptls.SSLHandshake.processHandshake(SSLHandshake.java:135)
at org.globus.gsi.gssapi.GlobusGSSContextImpl.initSecContext(GlobusGSSContextImpl.java:483)
at org.globus.gsi.gssapi.net.GssSocket.authenticateClient(GssSocket.java:102)
at org.globus.gsi.gssapi.net.GssSocket.startHandshake(GssSocket.java:140)
at org.globus.gsi.gssapi.net.GssSocket.getOutputStream(GssSocket.java:161)
at org.apache.axis.transport.http.HTTPSender.writeToSocket(HTTPSender.java:433)
at org.apache.axis.transport.http.HTTPSender.invoke(HTTPSender.java:135)
at org.apache.axis.strategies.InvocationStrategy.visit(InvocationStrategy.java:32)
at org.apache.axis.SimpleChain.doVisiting(SimpleChain.java:118)
at org.apache.axis.SimpleChain.invoke(SimpleChain.java:83)
at org.apache.axis.client.AxisClient.invoke(AxisClient.java:165)
at org.apache.axis.client.Call.invokeEngine(Call.java:2727)
at org.apache.axis.client.Call.invoke(Call.java:2710)
at org.apache.axis.client.Call.invoke(Call.java:2386)
at org.apache.axis.client.Call.invoke(Call.java:2309)
at org.apache.axis.client.Call.invoke(Call.java:1766)
at org.cagrid.gme.stubs.bindings.GlobalModelExchangePortTypeSOAPBindingStub.getServiceSecurityMetadata(GlobalModelExchangePortTypeSOAPBindingStub.java:1520)
at org.cagrid.gme.client.GlobalModelExchangeClient.getServiceSecurityMetadata(GlobalModelExchangeClient.java:87)
at gov.nih.nci.cagrid.introduce.security.client.ServiceSecurityClient.configureStubSecurity(ServiceSecurityClient.java:210)
at org.cagrid.gme.client.GlobalModelExchangeClient.getXMLSchemaNamespaces(GlobalModelExchangeClient.java:122)
at DevelopersGuideExamples.main(DevelopersGuideExamples.java:16)
{http://xml.apache.org/axis/}hostname:meadowgrain.local
org.globus.common.ChainedIOException: Authentication failed [Caused by: Failure unspecified at GSS-API level [Caused by: Unknown CA]]
at org.apache.axis.AxisFault.makeFault(AxisFault.java:101)
at org.apache.axis.transport.http.HTTPSender.invoke(HTTPSender.java:144)
at org.apache.axis.strategies.InvocationStrategy.visit(InvocationStrategy.java:32)
at org.apache.axis.SimpleChain.doVisiting(SimpleChain.java:118)
at org.apache.axis.SimpleChain.invoke(SimpleChain.java:83)
at org.apache.axis.client.AxisClient.invoke(AxisClient.java:165)
at org.apache.axis.client.Call.invokeEngine(Call.java:2727)
at org.apache.axis.client.Call.invoke(Call.java:2710)
at org.apache.axis.client.Call.invoke(Call.java:2386)
at org.apache.axis.client.Call.invoke(Call.java:2309)
at org.apache.axis.client.Call.invoke(Call.java:1766)
at org.cagrid.gme.stubs.bindings.GlobalModelExchangePortTypeSOAPBindingStub.getServiceSecurityMetadata(GlobalModelExchangePortTypeSOAPBindingStub.java:1520)
at org.cagrid.gme.client.GlobalModelExchangeClient.getServiceSecurityMetadata(GlobalModelExchangeClient.java:87)
at gov.nih.nci.cagrid.introduce.security.client.ServiceSecurityClient.configureStubSecurity(ServiceSecurityClient.java:210)
at org.cagrid.gme.client.GlobalModelExchangeClient.getXMLSchemaNamespaces(GlobalModelExchangeClient.java:122)
at DevelopersGuideExamples.main(DevelopersGuideExamples.java:16)
Caused by: org.globus.common.ChainedIOException: Authentication failed [Caused by: Failure unspecified at GSS-API level [Caused by: Unknown CA]]
at org.globus.gsi.gssapi.net.GssSocket.startHandshake(GssSocket.java:145)
at org.globus.gsi.gssapi.net.GssSocket.getOutputStream(GssSocket.java:161)
at org.apache.axis.transport.http.HTTPSender.writeToSocket(HTTPSender.java:433)
at org.apache.axis.transport.http.HTTPSender.invoke(HTTPSender.java:135)
... 14 more
Code Examples
| Be sure to note the information in the Security Considerations section before running these examples. These examples make use of the caGrid Traning Grid. |
Further examples of use of the GME API can be found in the globalModelExchange-ui project, which contains the source code for the user interface components described above in the user interface section.
Prerequisites
To get started developing against the GME APIs, your project will require the Java libraries found in the GME project's ext/dependencies/jars directory, and those in its build/lib directory.
Developers using Ivy to integrate with the caGrid build artifacts may use the following line in their dependencies:
<dependency rev="1.3" org="caGrid" name="globalModelExchange" conf="client"/>
Listing the Published XML Schemas
The code shown below prints the list the targetNamespaces of the published XML Schemas.
import java.rmi.RemoteException; import org.apache.axis.types.URI.MalformedURIException; import org.cagrid.gme.client.GlobalModelExchangeClient; import org.cagrid.gme.domain.XMLSchemaNamespace; public class DevelopersGuideExamples { public static void main(String[] args) { try { GlobalModelExchangeClient gme = new GlobalModelExchangeClient( "https://globalmodelexchange.training.cagrid.org:8443/wsrf/services/cagrid/GlobalModelExchange"); XMLSchemaNamespace[] namespaces = gme.getXMLSchemaNamespaces(); if (namespaces != null && namespaces.length > 0) { System.out.println("The GME has published XML Schemas with the following namespaces:"); for (XMLSchemaNamespace ns : namespaces) { System.out.println("\t"+ns); } } else { System.out.println("The GME has no published schemas."); } } catch (MalformedURIException e) { // TODO handle the case where the client is constructed with an // invalid URL e.printStackTrace(); return; } catch (RemoteException e) { // TODO handle general errors, such as connection refused e.printStackTrace(); return; } } }
Retrieving an XML Schema
The code example below shows how to get the text of a given schema, identified by its targetNamespace. Note the NoSuchNamespaceExistsFault addition to the catch block, which will be raised by the GME if the requested XML Schema has not been published.
import java.net.URISyntaxException; import java.rmi.RemoteException; import org.apache.axis.types.URI.MalformedURIException; import org.cagrid.gme.client.GlobalModelExchangeClient; import org.cagrid.gme.domain.XMLSchema; import org.cagrid.gme.domain.XMLSchemaDocument; import org.cagrid.gme.domain.XMLSchemaNamespace; import org.cagrid.gme.stubs.types.NoSuchNamespaceExistsFault; public class DevelopersGuideExamples { public static void main(String[] args) { try { GlobalModelExchangeClient gme = new GlobalModelExchangeClient( "https://globalmodelexchange.training.cagrid.org:8443/wsrf/services/cagrid/GlobalModelExchange"); XMLSchemaNamespace schemaTargetNamespace = new XMLSchemaNamespace( "gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata"); XMLSchema schema = gme.getXMLSchema(schemaTargetNamespace); XMLSchemaDocument rootDocument = schema.getRootDocument(); System.out.println("The XML Schema with targetNamespace " + schema.getTargetNamespace() + " has the following text:\n" + rootDocument.getSchemaText()); } catch (MalformedURIException e) { // TODO handle the case where the client is constructed with an // invalid URL e.printStackTrace(); return; } catch (URISyntaxException e) { // TODO handle the case where the schemaTargetNamespace is // constructed with an invalid URI e.printStackTrace(); } catch (NoSuchNamespaceExistsFault e) { // TODO handle the case where the schema requested is not actually // published e.printStackTrace(); } catch (RemoteException e) { // TODO handle general errors, such as connection refused e.printStackTrace(); return; } } }
Running this code should yield the output shown below:
The XML Schema with targetNamespace gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata has the following text:
<?xml version="1.0"?>
<xs:schema targetNamespace="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:cagrid="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata"
xmlns:serv="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.service"
xmlns:com="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.common"
elementFormDefault="qualified">
<xs:import namespace="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.common"
schemaLocation="common/common.xsd" />
<xs:import namespace="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.service"
schemaLocation="service/servicemodel.xsd" />
<xs:element name="ServiceMetadata" type="cagrid:ServiceMetadata" />
<xs:complexType name="ServiceMetadata">
<xs:sequence>
<xs:element name="serviceDescription">
<xs:complexType>
<xs:sequence>
<xs:element ref="serv:Service" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="hostingResearchCenter">
<xs:complexType>
<xs:sequence>
<xs:element ref="com:ResearchCenter" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:schema>
Retrieving an XML Schema Bundle
If you inspect the example above, and the output it produces, you'll notice we only retrieved the actual text of the specific schema we requested and that schema contains xsd:imports of two other schemas which we did not get from the GME. This example extends the previous example by requesting the GME to return all such imported schemas, and any they may import, and so on such that we have all such referenced schemas.
import java.net.URISyntaxException; import java.rmi.RemoteException; import java.util.Set; import org.apache.axis.types.URI.MalformedURIException; import org.cagrid.gme.client.GlobalModelExchangeClient; import org.cagrid.gme.domain.XMLSchemaBundle; import org.cagrid.gme.domain.XMLSchemaNamespace; import org.cagrid.gme.stubs.types.NoSuchNamespaceExistsFault; public class DevelopersGuideExamples { public static void main(String[] args) { try { GlobalModelExchangeClient gme = new GlobalModelExchangeClient( "https://globalmodelexchange.training.cagrid.org:8443/wsrf/services/cagrid/GlobalModelExchange"); XMLSchemaNamespace schemaTargetNamespace = new XMLSchemaNamespace( "gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata"); XMLSchemaBundle schemaBundle = gme.getXMLSchemaAndDependencies(schemaTargetNamespace); Set<XMLSchemaNamespace> schemaTargetNamespaces = schemaBundle.getXMLSchemaTargetNamespaces(); System.out.println("Fully retrieving the XML Schema with targetNamespace " + schemaTargetNamespace + " requires the following XML Schemas:"); System.out.println("=================================================="); for (XMLSchemaNamespace ns : schemaTargetNamespaces) { System.out.println("--------------------------------------------------"); System.out.println("\t" + ns); System.out.println("--------------------------------------------------"); // extract the schema from the bundle, and print its root // document's text System.out.println(schemaBundle.getXMLSchemaForTargetNamespace(ns).getRootDocument().getSchemaText()); } } catch (MalformedURIException e) { // TODO handle the case where the client is constructed with an // invalid URL e.printStackTrace(); return; } catch (URISyntaxException e) { // TODO handle the case where the schemaTargetNamespace is // constructed with an invalid URI e.printStackTrace(); } catch (NoSuchNamespaceExistsFault e) { // TODO handle the case where the schema requested is not actually // published e.printStackTrace(); } catch (RemoteException e) { // TODO handle general errors, such as connection refused e.printStackTrace(); return; } } }
Running the example above should yeild output similar to the below:
Fully retrieving the XML Schema with targetNamespace gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata requires the following XML Schemas:
==================================================
--------------------------------------------------
gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.service
--------------------------------------------------
<?xml version="1.0"?>
<xs:schema targetNamespace="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.service" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:serv="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.service" xmlns:com="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.common" elementFormDefault="qualified">
<xs:import namespace="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.common" schemaLocation="../common/common.xsd"/>
<xs:element name="Service" type="serv:Service"/>
<xs:complexType name="Service">
<xs:annotation>
<xs:documentation>A service is a "conceptual" definition of a collection of functional contexts.
This has no physical manifestation in the grid.</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="pointOfContactCollection">
<xs:complexType>
<xs:sequence>
<xs:element ref="com:PointOfContact" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="serviceContextCollection">
<xs:complexType>
<xs:sequence>
<xs:element ref="serv:ServiceContext" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element ref="serv:CaDSRRegistration" minOccurs="0"/>
<xs:element ref="com:SemanticMetadata" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="description" use="required" type="xs:string"/>
<xs:attribute name="name" use="required" type="xs:string"/>
<xs:attribute name="version" use="required" type="xs:string"/>
</xs:complexType>
<xs:element name="Operation" type="serv:Operation"/>
<xs:complexType name="Operation">
<xs:annotation>
<xs:documentation>This represents a method/operation/function in a service context. Its input parameters are described by its InputParameter associations, its output by its Output association, and any errors it produces by its Fault associations.
This is manifested as an operation of a service in the grid.</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="inputParameterCollection">
<xs:complexType>
<xs:sequence>
<xs:element ref="serv:InputParameter" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element ref="serv:Output" minOccurs="0"/>
<xs:element name="faultCollection">
<xs:complexType>
<xs:sequence>
<xs:element ref="serv:Fault" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element ref="com:SemanticMetadata" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="description" use="required" type="xs:string"/>
<xs:attribute name="name" use="required" type="xs:string"/>
</xs:complexType>
<xs:element name="Output" type="serv:Output"/>
<xs:complexType name="Output">
<xs:annotation>
<xs:documentation>Represents the result/output of an operation. Its non-existence represents the operation produces no result.
This is manifested as the value of an operation response in the grid.</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element ref="com:UMLClass" minOccurs="0"/>
</xs:sequence>
<xs:attribute name="dimensionality" use="required" type="xs:int">
<xs:annotation>
<xs:documentation>Only valid if isArray is true; indicates number of dimensions in the array</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="isArray" use="required" type="xs:boolean"/>
<xs:attribute name="qName" use="required" type="xs:QName"/>
</xs:complexType>
<xs:element name="InputParameter" type="serv:InputParameter"/>
<xs:complexType name="InputParameter">
<xs:annotation>
<xs:documentation>Represents an input parameter to an operation.
This is manifested as a parameter of a service request in the grid.</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element ref="com:UMLClass" minOccurs="0"/>
</xs:sequence>
<xs:attribute name="dimensionality" use="required" type="xs:int">
<xs:annotation>
<xs:documentation>Only valid if isArray is true; represents the dimensionality of the array</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="index" use="required" type="xs:int">
<xs:annotation>
<xs:documentation>This is the 0-based index of the parameter in the operation's signature</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="isArray" use="required" type="xs:boolean"/>
<xs:attribute name="isRequired" use="required" type="xs:boolean">
<xs:annotation>
<xs:documentation>Whether the given parameter is allowed to be null or not</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="name" use="required" type="xs:string"/>
<xs:attribute name="qName" use="required" type="xs:QName"/>
</xs:complexType>
<xs:element name="Fault" type="serv:Fault"/>
<xs:complexType name="Fault">
<xs:annotation>
<xs:documentation>This represents an error that could occur during the execution of the operation.
This is manifested as an operation fault in the grid.</xs:documentation>
</xs:annotation>
<xs:sequence/>
<xs:attribute name="description" use="required" type="xs:string"/>
<xs:attribute name="name" use="required" type="xs:string"/>
</xs:complexType>
<xs:element name="ServiceContext" type="serv:ServiceContext"/>
<xs:complexType name="ServiceContext">
<xs:annotation>
<xs:documentation>This is a functional collection of operations that work over a common collection of stateful resources.
A service without stateful resources would have a single context.
This is manifested as an actual service in the grid.</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="operationCollection">
<xs:complexType>
<xs:sequence>
<xs:element ref="serv:Operation" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="contextPropertyCollection">
<xs:complexType>
<xs:sequence>
<xs:element ref="serv:ContextProperty" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="description" use="required" type="xs:string"/>
<xs:attribute name="name" use="required" type="xs:string"/>
</xs:complexType>
<xs:element name="ContextProperty" type="serv:ContextProperty"/>
<xs:complexType name="ContextProperty">
<xs:annotation>
<xs:documentation>This represents an exposed property of a service context's state.
This is manifested as a resource property in the grid.</xs:documentation>
</xs:annotation>
<xs:sequence/>
<xs:attribute name="description" use="required" type="xs:string"/>
<xs:attribute name="name" use="required" type="xs:string"/>
</xs:complexType>
<xs:element name="CaDSRRegistration" type="serv:CaDSRRegistration"/>
<xs:complexType name="CaDSRRegistration">
<xs:sequence/>
<xs:attribute name="registrationStatus" use="required" type="xs:string"/>
<xs:attribute name="workflowStatus" use="required" type="xs:string"/>
</xs:complexType>
</xs:schema>
--------------------------------------------------
gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata
--------------------------------------------------
<?xml version="1.0"?>
<xs:schema targetNamespace="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:cagrid="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata"
xmlns:serv="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.service"
xmlns:com="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.common"
elementFormDefault="qualified">
<xs:import namespace="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.common"
schemaLocation="common/common.xsd" />
<xs:import namespace="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.service"
schemaLocation="service/servicemodel.xsd" />
<xs:element name="ServiceMetadata" type="cagrid:ServiceMetadata" />
<xs:complexType name="ServiceMetadata">
<xs:sequence>
<xs:element name="serviceDescription">
<xs:complexType>
<xs:sequence>
<xs:element ref="serv:Service" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="hostingResearchCenter">
<xs:complexType>
<xs:sequence>
<xs:element ref="com:ResearchCenter" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:schema>
--------------------------------------------------
gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.common
--------------------------------------------------
<?xml version="1.0"?>
<xs:schema targetNamespace="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.common" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:com="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.common" elementFormDefault="qualified">
<xs:element name="Enumeration" type="com:Enumeration"/>
<xs:complexType name="Enumeration">
<xs:sequence>
<xs:element ref="com:SemanticMetadata" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="permissibleValue" use="required" type="xs:string"/>
<xs:attribute name="valueMeaning" use="required" type="xs:string"/>
</xs:complexType>
<xs:element name="ValueDomain" type="com:ValueDomain"/>
<xs:complexType name="ValueDomain">
<xs:sequence>
<xs:element ref="com:SemanticMetadata" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="enumerationCollection">
<xs:complexType>
<xs:sequence>
<xs:element ref="com:Enumeration" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="longName" use="required" type="xs:string"/>
<xs:attribute name="unitOfMeasure" use="optional" type="xs:string"/>
</xs:complexType>
<xs:element name="SemanticMetadata" type="com:SemanticMetadata"/>
<xs:complexType name="SemanticMetadata">
<xs:sequence/>
<xs:attribute name="conceptCode" use="required" type="xs:string"/>
<xs:attribute name="conceptDefinition" use="required" type="xs:string"/>
<xs:attribute name="conceptName" use="required" type="xs:string"/>
<xs:attribute name="order" use="optional" type="xs:int"/>
<xs:attribute name="orderLevel" use="optional" type="xs:int"/>
</xs:complexType>
<xs:element name="PointOfContact" type="com:PointOfContact"/>
<xs:complexType name="PointOfContact">
<xs:annotation>
<xs:documentation>For the static model, instances of these should be the POCs associated with the design and implementation of the service itself (not deployments of it, e.g. not system support staff)
The "role" attribute should probably be an enumeration of known types</xs:documentation>
</xs:annotation>
<xs:sequence/>
<xs:attribute name="affiliation" use="required" type="xs:string"/>
<xs:attribute name="email" use="required" type="xs:string"/>
<xs:attribute name="firstName" use="required" type="xs:string"/>
<xs:attribute name="lastName" use="required" type="xs:string"/>
<xs:attribute name="phoneNumber" use="optional" type="xs:string"/>
<xs:attribute name="role" use="required" type="xs:string"/>
</xs:complexType>
<xs:element name="UMLClass" type="com:UMLClass"/>
<xs:complexType name="UMLClass">
<xs:annotation>
<xs:documentation>caDSR-related
Represents the UML Class of the given input or output.</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="umlAttributeCollection">
<xs:complexType>
<xs:sequence>
<xs:element ref="com:UMLAttribute" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element ref="com:SemanticMetadata" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="className" use="required" type="xs:string"/>
<xs:attribute name="description" use="required" type="xs:string"/>
<xs:attribute name="id" use="required" type="xs:string">
<xs:annotation>
<xs:documentation>This is used soley for the purposes of referencing this class in associations. It does not represent any caDSR identifier.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="packageName" use="required" type="xs:string"/>
<xs:attribute name="projectName" use="required" type="xs:string"/>
<xs:attribute name="projectVersion" use="required" type="xs:string"/>
</xs:complexType>
<xs:element name="UMLAttribute" type="com:UMLAttribute"/>
<xs:complexType name="UMLAttribute">
<xs:annotation>
<xs:documentation>caDSR-related
Represents a UML attribute of the parent UML Class. Indication of isRequired=false means the operation will function without the existence of this attribute.</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element ref="com:SemanticMetadata" minOccurs="0" maxOccurs="unbounded"/>
<xs:element ref="com:ValueDomain" minOccurs="0"/>
</xs:sequence>
<xs:attribute name="dataTypeName" use="required" type="xs:string"/>
<xs:attribute name="description" use="required" type="xs:string"/>
<xs:attribute name="name" use="required" type="xs:string"/>
<xs:attribute name="publicID" use="required" type="xs:long"/>
<xs:attribute name="version" use="required" type="xs:float"/>
</xs:complexType>
<xs:element name="ResearchCenter" type="com:ResearchCenter"/>
<xs:complexType name="ResearchCenter">
<xs:sequence>
<xs:element ref="com:Address" minOccurs="0"/>
<xs:element ref="com:ResearchCenterDescription" minOccurs="0"/>
<xs:element name="pointOfContactCollection">
<xs:complexType>
<xs:sequence>
<xs:element ref="com:PointOfContact" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="displayName" use="required" type="xs:string"/>
<xs:attribute name="shortName" use="required" type="xs:string"/>
</xs:complexType>
<xs:element name="Address" type="com:Address"/>
<xs:complexType name="Address">
<xs:sequence/>
<xs:attribute name="country" use="required" type="xs:string"/>
<xs:attribute name="locality" use="optional" type="xs:string"/>
<xs:attribute name="postalCode" use="optional" type="xs:string"/>
<xs:attribute name="stateProvince" use="optional" type="xs:string"/>
<xs:attribute name="street1" use="required" type="xs:string"/>
<xs:attribute name="street2" use="optional" type="xs:string"/>
</xs:complexType>
<xs:element name="ResearchCenterDescription" type="com:ResearchCenterDescription"/>
<xs:complexType name="ResearchCenterDescription">
<xs:sequence/>
<xs:attribute name="description" use="required" type="xs:string"/>
<xs:attribute name="homepageURL" use="required" type="xs:string"/>
<xs:attribute name="imageURL" use="optional" type="xs:string"/>
<xs:attribute name="rssNewsURL" use="optional" type="xs:string"/>
</xs:complexType>
</xs:schema>
Downloading an XML Schema and its Dependencies
Extending upon the example above, we can use the cacheSchemas operation to get the XMLSchemaBundle and write it to the local filesystem. We can then walk the metadata returned from this operation to see where the files were written.
import java.io.File; import java.io.IOException; import java.net.URISyntaxException; import java.rmi.RemoteException; import java.util.Map; import org.apache.axis.types.URI.MalformedURIException; import org.cagrid.gme.client.GlobalModelExchangeClient; import org.cagrid.gme.domain.XMLSchemaNamespace; import org.cagrid.gme.stubs.types.NoSuchNamespaceExistsFault; public class DevelopersGuideExamples { public static void main(String[] args) { try { GlobalModelExchangeClient gme = new GlobalModelExchangeClient( "https://globalmodelexchange.training.cagrid.org:8443/wsrf/services/cagrid/GlobalModelExchange"); XMLSchemaNamespace schemaTargetNamespace = new XMLSchemaNamespace( "gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata"); File directory = new File(".", "gme_schemas"); Map<XMLSchemaNamespace, File> cachedSchemas = gme.cacheSchemas(schemaTargetNamespace, directory); System.out.println("Downloaded the XML Schema with targetNamespace " + schemaTargetNamespace + ", and its dependencies, to the local file system directory:" + directory); System.out.println("The schemas were written to the following files:"); for (XMLSchemaNamespace ns : cachedSchemas.keySet()) { File f = cachedSchemas.get(ns); System.out.println("\t"+ns+" => "+f); } } catch (MalformedURIException e) { // TODO handle the case where the client is constructed with an // invalid URL e.printStackTrace(); return; } catch (URISyntaxException e) { // TODO handle the case where the schemaTargetNamespace is // constructed with an invalid URI e.printStackTrace(); } catch (NoSuchNamespaceExistsFault e) { // TODO handle the case where the schema requested is not actually // published e.printStackTrace(); } catch (RemoteException e) { // TODO handle general errors, such as connection refused e.printStackTrace(); return; } catch (IOException e) { // TODO handle issues creating directories/files for caching the // schemas e.printStackTrace(); } } }
Running this code should yield output similar to the below:
Downloaded the XML Schema with targetNamespace gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata, and its dependencies, to the local file system directory:./gme_schemas The schemas were written to the following files: gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.common => ./gme_schemas/common.xsd gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata => ./gme_schemas/caGridMetadata.xsd gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.service => ./gme_schemas/servicemodel.xsd
If the example code is ran again, you'll notice the results change to something like the below:
Downloaded the XML Schema with targetNamespace gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata, and its dependencies, to the local file system directory:./gme_schemas The schemas were written to the following files: gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.common => ./gme_schemas/0_common.xsd gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata => ./gme_schemas/0_caGridMetadata.xsd gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.service => ./gme_schemas/0_servicemodel.xsd
This is because the operation tries to honor the original names of the XML Schemas (as defined by their systemIDs at publish time) but takes care to no overwrite existing files, and comes up with unique names for them.
You will also notice if you open a file, that the xsd:import tags have been appropriately modified to point to their local locations. For example, in the example above we saw the root document had imports like below (as they were published):
<xs:import namespace="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.common"
schemaLocation="common/common.xsd" />
<xs:import namespace="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.service"
schemaLocation="service/servicemodel.xsd" />
Whereas, the schemas retrieved in this example have the following imports, which point to the locally written files:
<xs:import namespace="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.common"
schemaLocation="0_common.xsd" />
<xs:import namespace="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.service"
schemaLocation="0_servicemodel.xsd" />
Publishing an XML Schema
This example shows how to use the XSDUtil utility class to help construct an XML Schema from the file system, and publish it the GME. This example should be run from the GME_HOME directory, as it references a test schema from the project.
import java.io.File; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.rmi.RemoteException; import org.apache.axis.types.URI.MalformedURIException; import org.cagrid.gme.client.GlobalModelExchangeClient; import org.cagrid.gme.common.XSDUtil; import org.cagrid.gme.domain.XMLSchema; import org.cagrid.gme.stubs.types.NoSuchNamespaceExistsFault; public class DevelopersGuideExamples { public static void main(String[] args) { try { GlobalModelExchangeClient gme = new GlobalModelExchangeClient( "https://globalmodelexchange.training.cagrid.org:8443/wsrf/services/cagrid/GlobalModelExchange"); // the targetNamespace of the schema we are publishing URI schemaToPublishTargetNamespace = new URI("gme://f"); // the file containing the schema's text File schemaToPublishRootDocument = new File("test/resources/schema/simple/F.xsd"); // Use the XSDUtil to help build the XMLSchema XMLSchema schemaToPublish = XSDUtil.createSchema(schemaToPublishTargetNamespace, schemaToPublishRootDocument); // build an array of all the schemas to publish XMLSchema[] schemasToPublish = new XMLSchema[1]; schemasToPublish[0] = schemaToPublish; gme.publishXMLSchemas(schemasToPublish); } catch (MalformedURIException e) { // TODO handle the case where the client is constructed with an // invalid URL e.printStackTrace(); return; } catch (URISyntaxException e) { // TODO handle the case where the schemaTargetNamespace is // constructed with an invalid URI e.printStackTrace(); } catch (NoSuchNamespaceExistsFault e) { // TODO handle the case where the schema requested is not actually // published e.printStackTrace(); } catch (RemoteException e) { // TODO handle general errors, such as connection refused e.printStackTrace(); return; } catch (IOException e) { // TODO handle issues reading directories/files passed to XSDUtil e.printStackTrace(); } } }
Deleting an XML Schema
This example will delete the schema that was published in the preceding example. Note an XML Schema cannot be deleted if their are any remaining references to it, so in order to delete a referenced schema, the referencing schemas must also be deleted (by passing all their targetNamespaces in the array). Also note, schema deletion is irreversible, so should not be used unless strictly necessary.
import java.net.URISyntaxException; import java.rmi.RemoteException; import org.apache.axis.types.URI.MalformedURIException; import org.cagrid.gme.client.GlobalModelExchangeClient; import org.cagrid.gme.domain.XMLSchemaNamespace; import org.cagrid.gme.stubs.types.NoSuchNamespaceExistsFault; public class DevelopersGuideExamples { public static void main(String[] args) { try { GlobalModelExchangeClient gme = new GlobalModelExchangeClient( "https://globalmodelexchange.training.cagrid.org:8443/wsrf/services/cagrid/GlobalModelExchange"); // the targetNamespace of the schema we are deleting XMLSchemaNamespace schemaToDeleteTargetNamespace = new XMLSchemaNamespace("gme://f"); XMLSchemaNamespace[] targetNamespacesToDelete = new XMLSchemaNamespace[1]; targetNamespacesToDelete[0] = schemaToDeleteTargetNamespace; gme.deleteXMLSchemas(targetNamespacesToDelete); } catch (MalformedURIException e) { // TODO handle the case where the client is constructed with an // invalid URL e.printStackTrace(); return; } catch (URISyntaxException e) { // TODO handle the case where the schemaTargetNamespace is // constructed with an invalid URI e.printStackTrace(); } catch (NoSuchNamespaceExistsFault e) { // TODO handle the case where the schema requested is not actually // published e.printStackTrace(); } catch (RemoteException e) { // TODO handle general errors, such as connection refused e.printStackTrace(); return; } } }





