|
Key
This line was removed.
This word was removed. This word was added.
This line was added.
|
Comment:
Changes (4)
View Page Historyh1. GME 1.4 Developers Guide
----
{include:Developers Guide Navigation}
{toc}\\
h1. GME Overview
----
----
{include:gme:GME Overview}
The Global Model Exchange (GME) Grid Service is a simple, stateless service, created with [Introduce|introduce14:Home], which acts as an authoritative XML Schema registry for the grid. It's primary function is to ensure global referential integrity of all the XML Schemas used on the grid, and provide operations for their registration and discovery. It provides utility APIs for uploading from and downloading to a local file system, graphical interfaces, and integration into as a data type discovery mechanism.
h1. Service Operations Overview
----
----
The *publishXMLSchemas* operation is used for all publish and update operations (Note: 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 the _XMLSchema_ being published. For more information on the processing behavior of the publish operation, see the [GME Design Guide|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 that 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 (this could be a complex graph of schemas).
The client API provides some convenience methods in the *org.cagrid.gme.client.GlobalModelExchangeClient* class. A method named *cacheSchemas* internally calls the *getXMLSchemaAndDependencies* operation, and writes all of the retrieved schemas to the file system, handling any potential naming conflicts. A method named *validateXML* validates an XML document in String using the namespace of the document's root element to retrieve the schema from GME. A similar method named *validateXMLFile* validates an XML document in a file.
The GME allows one to retrieve the list of _targetNamespace{_}s 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 that depend upon it can be deleted at the same time. This is because 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.
h1. GME Class Model
----
{include:gme14:Class Model}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|http://castor.org/] for serialization and deserialization into custom, hand-written Java Beans.
h1. 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|http://www.w3.org/TR/xmlschema-0/#SchemaInMultDocs] and [xsd:redefine|http://www.w3.org/TR/xmlschema-0/#Redefine]. Additionally, 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 (i.e., 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|http://projectmobius.org] to leverage the grid service; this is no longer necessary.
h1. Using the GME User Interface
----
----
The GME provides graphical user interface components via integration with the [Introduce service development environment|introduce:Home]; 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|#GME Browsing and Upload] and 2) an ability to add XML Schemas from a GME to an Introduce service, described in the [GME Schema Discovery section|#GME Schema Discovery].
The GME with which Introduce will communicate is configured via the _GME Service URL_ value in the _Global Extension Properties_ in the [Introduce Preferences|introduce14:Developers Guide#Preferences]. Generally this value is automatically set when you [configure caGrid|caGrid14:How to Change Target Grid] to use a particular grid.
h2. 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|introduce14:Developers Guide#Launching_Introduce]. Once Introduce has launched, 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).
!Introduce_Browse_GME.png!
This window initially shows the "Browse" tab and contains a drop-down menu labeled "Target Namespace", which is populated with all of the _targetNamespace{_}s 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|#Retrieving an XML Schema Bundle].
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).
!Introduce_GME_Upload_initial.png!
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. In the even that a scheme must be removed because it contains an error or was accidentally added, 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, as 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 needed to comprise this schema. For most cases, this will just be the single schema file which was selected, but for schemas that 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, select the "root" schema and the other documents will automatically be added). Selecting a document from this list will display its textual content in the "Schema Preview" panel. The screen shot below illustrates the interface when a single XML Schema that consists of two actual documents is to be published. Once all desired XML Schemas have been added to the interface and there are no errors shown in the top panel, click the *Publish Schemas* button. If this completes without error, a success dialog will display, and the schemas should be able to be found using the "Browse" tab of the same window after pressing the *Refresh* button.
!Introduce_GME_Upload_With_Schemas.png!
h2. 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|introduce14:Design#Data_Type_Discovery_Extensions]) is provided. Shown below, this component embeds itself into the "Import Data Types" panel of the "Types" tab. Its use is fairly straightforward, as a drop-down menu of the currently published XML Schemas represented by their _targetNamespaces{_}s 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" schema was also added because "gme://a" imports it. Accordingly, so was "gme://c" because "gme://b" imports it, as shown in the "Imported Data Types" window on the left of the screen shot.
!Introduce_Add_GME_Types.png!
h1. Security Considerations
----
Because the GME is typically deployed as a secure service (though currently it is not strictly required by the GME), one must synchronize with a trust fabric as described in the [GTS Developer's Guide|gts14:Developers Guide] in order to use its client API. Failure to do so may yield exceptions similar to the stack trace shown below. Be sure to pay particular attention to the "Caused by: Unknown CA" message.
{noformat}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
{noformat}
h1. Code Examples
----
{tip}Be sure to note the information in the [Security Considerations section|#Security Considerations] before running these examples. These examples make use of the [caGrid Training Grid|community:Community Training Grid].{tip}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|#Using the GME User Interface].
h2. Prerequisites
To get started developing against the GME APIs, the 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|knowledgebase14:Use caGrid Libraries in Your Application] may use the following line in their dependencies:
{code:xml}<dependency rev="1.3" org="caGrid" name="globalModelExchange" conf="client"/>
{code}
{code}
The code shown below prints the list of the targetNamespaces of the published XML Schemas.
\\
{code}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;
}
}
}
{code}
h2. Retrieving an XML Schema
The code example below shows how to acquire the text of a given schema, as 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.
\\
{code}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;
}
}
}
{code}\\
Running this code should yield the output shown below:
\\
{noformat}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>
{noformat}
h2. 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 not retrieved from the GME. This example extends the previous example by requesting the GME to return all such imported schemas, as well as any they may import and so on, such that we have all such referenced schemas.
{code}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;
}
}
}
{code}\\
Running the example above should yield output similar to the following:
\\
{noformat}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>
{noformat}
h2. 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.
{code}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();
}
}
}
{code}\\
Running this code should yield output similar to the below:
\\
{noformat}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
{noformat}\\
If the example code is ran again, the results change to something like this:
\\
{noformat}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
{noformat}\\
This is because the operation tries to honor the original names of the XML Schemas, as defined by their systemIDs at publish time, but it takes care to not overwrite existing files and thus 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|#Retrieving an XML Schema] the root document had imports like below (as they were published):
{noformat} <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" />
{noformat}\\
Whereas, the schemas retrieved in this example have the following imports, which point to the locally written files:
\\
{noformat}<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" />
{noformat}
h2. 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 because it references a test schema from the project.
{code}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();
}
}
}
{code}
h2. Client-Side Validation of XML Documents
This example validates an XML document in a file using an XML schema from GME. The validation is done by calling the *GlobalModelExchangeClient* class's *validateXMLFile* method. It expects the root element of the XML document to specify an {{xmlns}} that it will use to identify the schema for retrieval from GME.
The *GlobalModelExchangeClient* class has a similar method named *validateXML* that is passed as a string that contains the actual XML document for validation.
\\
{code}import gov.nih.nci.cagrid.common.SchemaValidationException;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.rmi.RemoteException;
import org.apache.axis.types.URI.MalformedURIException;
import org.cagrid.gme.client.GlobalModelExchangeClient;
public class GMEListingExample {
static final String GME_URL = "https://globalmodelexchange.training.cagrid.org:8443/wsrf/services/cagrid/GlobalModelExchange";
public static void main(String[] args) {
File xmlFile = new File("resources", "gme_example.xml");
GlobalModelExchangeClient gme;
try {
gme = new GlobalModelExchangeClient(GME_URL);
} 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;
}
try {
gme.validateXMLFile(xmlFile);
System.out.println(xmlFile.getCanonicalPath() + " is valid");
} catch (IOException e) {
// TODO Handle problems reading the file.
e.printStackTrace();
return;
} catch (URISyntaxException e) {
// TODO Handle XML namespace not being a valid URI.
e.printStackTrace();
return;
} catch (SchemaValidationException e) {
// TODO Handle invalid XML document.
e.printStackTrace();
}
}
}
{code}
h2. Deleting an XML Schema
This example will delete the schema that was published in the preceding example. An XML Schema cannot be deleted if there are any remaining references to it. Accordingly, in order to delete a referenced schema, the referencing schemas must also be deleted by passing all their targetNamespaces in the array. Also, schema deletion is irreversible so it should not be used unless strictly necessary.
{code}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;
}
}
}
{code}





