![]() |
International Virtual Observatory Alliance |
Your abstract goes here...
This is a Note. The first release of this document was 2009 February 17.
This is an IVOA Note expressing suggestions from and opinions of the authors. It is intended to share best practices, possible approaches, or other perspectives on interoperability with the Virtual Observatory. It should not be referenced or otherwise interpreted as a standard specification.
A list of current IVOA Recommendations and other technical documents can be found at http://www.ivoa.net/Documents/.
The author would like to thank Alasdair Alan of the eStar project (University of Exeter, UK) for his assistance in getting started with VOEvent, as well as Roy Williams of Caltech and Rob Seaman of NOAO, without whose encouragement this Note would not have been published.
The author has, over the last year, implemented a software system that interfaces with VOEvent. In the process of designing and implementing this system, roadblocks and problems were encountered. It is typical for such things to be a part of the implementation of a system that involves a complex technology such as VOEvent. The purpose of this paper is to provide the VOEvent community with feedback from a developer who implemented the technology and thus hopefully influence the direction in which VOEvent will evolve.
In order to provide a robust, low-maintenance facility that consumes VOEvent messages, it is necessary to implement a receiver that can validate and understand anything that comes along which conforms with the relevant specification, Sky Event Reporting Metadata (VOEvent) Version 1.1 (VOEvent 1.1). In the commercial software arena, one of the primary design goals must be to minimize the need for ad-hoc software tweaks and patches which would render the software author ineffective as a developer, turning him into a service programmer. This may be an unusual viewpoint among current VOEvent software developers, as most are associated with education and science organizations who develop and maintain one-off software systems, and who "are there" to make such tweaks and patches as needed. Nonetheless, broad-scale adoption of VOEvent will be affected by roadblocks and problems, so the author hopes that his experiences will provide some guidance going forward.
Most XML engines provide validation of input XML documents against the schema references contained therein. It was found that XML validation warnings were being reported in the What section of the VOEvent 1.1 messages by all of the author's XML tools. Currently, the What section of VOEvent 1.1 is written like this:
<xs:complexType name="What">
<xs:choice maxOccurs="unbounded">
<xs:element name="Param" />
<xs:element name="Group" />
<xs:element name="Description" type="Description" />
<xs:element name="Reference" />
</xs:choice>
</xs:complexType>
<xs:complexType name="Param">
<xs:attribute name="name" type="xs:token" />
<xs:attribute name="ucd" type="xs:token" />
<xs:attribute name="value" type="xs:string" />
<xs:attribute name="unit" type="xs:string" />
</xs:complexType>
<xs:complexType name="Group">
<xs:choice maxOccurs="unbounded">
<xs:element name="Param" />
<xs:element name="Description" type="Description" />
<xs:element name="Reference" />
</xs:choice>
<xs:attribute name="name" type="xs:string" />
<xs:attribute name="type" type="xs:string" />
</xs:complexType>
Graphically, it looks like this:
While Param is defined as to its attributes (name, ucd, value, and unit), neither What/Param nor Group/Param are typed as Param, so the validator cannot find any schema information for either one (Despite Param being a defined type in the Schema). The same sort of problem exists for What/Group, which is not typed as Group, as well as What/Reference, and What/Group/Reference (there is already a Reference type also). In contrast, What/Description and What/Group/Description are already typed as Description, and thus they can be validated.
The problems have simple solutions, shown in bold below:
<xs:complexType name="What">
<xs:choice maxOccurs="unbounded">
<xs:element name="Param" type="Param" />
<xs:element name="Group" type="Group" />
<xs:element name="Description" type="Description" />
<xs:element name="Reference" type="Reference" />
</xs:choice>
</xs:complexType>
<xs:complexType name="Param">
<xs:attribute name="name" type="xs:token" />
<xs:attribute name="ucd" type="xs:token" />
<xs:attribute name="value" type="xs:string" />
<xs:attribute name="unit" type="xs:string" />
</xs:complexType>
<xs:complexType name="Group">
<xs:choice maxOccurs="unbounded">
<xs:element name="Param" type="Param" />
<xs:element name="Description" type="Description" />
<xs:element name="Reference" type="Reference" />
</xs:choice>
<xs:attribute name="name" type="xs:string" />
<xs:attribute name="type" type="xs:string" />
</xs:complexType>
Here's the result graphically, showing that the links for Param and Group/param are made and the validator can work all the way through the XML. The same goes for the Reference nodes, which I typed in bold above (but didn't expand in the diagram):
This should be fixed in future versions of the VOEvent schema.
In a commercial environment, where time is money, it is not practical to hand-code schema-derived object models and generators for schema-conforming XML documents. Doing so invites bugs and can consume vast amounts of time. Instead, practicality requires using tools such as Java Architecture for XML Binding (JAXB), Liquid XML Data Binder (Liquid), and Altova XML Spy. These tools generate object model code that can be programmatically used to consume and produce conforming XML documents. This is a huge step above spelunking the XML Document Object Model (DOM) of the subject XML documents and the schemas they reference and/or constructing documents using the DOM. The most important feature of the code produced by these tools is guaranteed correctness of output XML. The benefits are huge. A developer can, with assurance, say that his output XML is correct.
VOEvent 1.1 has, in its totality, an extremely complex data model, by anyone's standards. Most of this complexity resides in the Space-Time Coordinate Metadata for the Virtual Observatory schema and its associated XML Linking Language (XLink) Version 1.0 schema ("STC"). Anecdotally, it has not been practical to submit the entire schema (with included STC/XLink) to an automated parser-generator. Attempts to do so have failed (the author has discussed this with several others who have attempted to do this and found their tools to have failed, and he has personally failed with two of the tools). The reason for failures will not be discussed here, it's just important that today's automated parser generation technology can't handle VOEvent 1.1.
Such practicalities notwithstanding, since the schema is so huge, any schema-derived object model would consequently be huge, regardless of how it is made. In order to be complete, any VOEvent receiver that purports to strictly conform would have to implement the handling of the myriad of types, units, forms, and metadata that can appear in a VOEvent message. This itself is a huge task.
Since it is impractical to implement an object model and generator for the entire VOEvent protocol/schema, it was decided to take a pragmatic approach. A collection of all VOEvent messages that had been sent between 1-Jan-2007 and 03-Mar-2008 was obtained and the used to develop a "real world" schema that represented the union of all of the forms that appear in then-current messages (see Appendix A). The schema was also designed to produce a straightforward object model via JAXB or Liquid, both of which faithfully reflect the strict meaning of a schema and provide strict validation. The process was an iterative one: First the schema was run through Liquid to produce an object model parser-generator. Then the collection of messages was fed into the parser and any validation errors trapped. Validation errors then led to another iteration of the schema, etc.
Eventually the process reached a point where the remaining validation errors were violations of the real VOEvent 1.1 schema. Rather than incorporate real errors into the mini-schema, an approach similar to that used for anti-virus updates was taken. Prior to submission to the parser, incoming messages are passed through a scripted "pre-patcher" which fixes up the errors so that the message is VOEvent 1.1 conformant. The intention is to distribute updates to the patching rules as new violating messages appear on the network. This eliminates patching or updating the software itself, as it is designed to be rule-driven and to have its rules easily updated by non-technical people, possibly via a subscription mechanism.
It's not the purpose of this Note to advocate the above as a solution for VOEvent interoperability issues!
As just mentioned, some of the validation errors encountered in the above process turned out to be violations of VOEvent 1.1 itself. The interesting thing is that these messages were being routinely passed around the VOEvent network (and some still are). This means that there are receiving parsers out there that are not validating. This seems strange since just about any XML engine out there provides validation of incoming XML documents against their referenced schema(s), regardless of whether an object model is used to access its content. It is presumed that most receivers are simply picking through the incoming XML document object model (with XPath or something) and extracting what they're interested in. In this scenario, very little if any real validation can be done (apart from the basic XML structure), leaving the burden of catching errors on the receiver developer(s). The collection of real-world messages referenced in the previous section contained the following VOEvent 1.1 errors:
The reason that we're getting away with this today is that there are relatively few nodes on the VOEvent network. As the network scales, and the number of different VOEvent message forms that flow over the network increases, this will become a major problem. This will be especially problematic when the network's receiver population grows if the majority use ad-hoc DOM-picking software developed by others. When a new message form appears for which the logic is not in the receiver software, all of those receivers could need updating. Who is going to do that? How long will it take? Where will the funding come from? Will the constant stream of "software problems" cast a pall over VOEvent?
At one end of the spectrum is the all-powerful VOEvent 1.1 schema and at the other end is an ad-hoc set of gentleman's agreements regarding what sub-set of forms is in the VOEvent messages actually in use. This can't go on if VOEvent is to grow successfully.
Apart from the content of VOEvent messages, there is the question of how they are transmitted across the Internet. The basic requirement is to simply move a block of XML from one place to another. Distributing messages is done with brokers, to which interested parties connect and listen for messages. A sender connects to the broker, sends the message, and disconnects. Listeners remain connected to the broker continuously. The broker sends copies of messages sent to it to all connected receivers (or to other brokers). The model is simple and elegant.
In implementation, however, things get more complicated. There are at least three transmission protocols currently in use for "moving the text":
Both potential senders and receivers of VOEvent messages are faced with either making a choice between these protocols or implementing more than one (and possible all three). Today, there are two generally accessible brokers: eStar (University of Exeter, UK) and VOEventNet (Caltech, USA). eStar supports Simple TCP and SOAP, Caltech supports Simple TCP and Jabber. eStar has stated that SOAP is a legacy protocol and should not be used for new applications. VOEventNet is using Jabber to support not only VOEvent messages, but also several value-added alerting services, some of which won't use VOEvent messages.
It's beyond the scope of this document to present all sides of the Simple TCP vs Jabber question. Suffice it to say that it is the author's position that a common protocol should be universally supported as the base VOEvent transmission protocol. Hopefully, this discussion and choice will be a part of VOEvent's future.
The author's experiences with the real-world of VOEvent have revealed some areas that, in his opinion, should be considered for VOEvent's future:
Considering the above in order, 1 can lead to 2, the results of which can make it much easier to accomplish 3.
Consider decoupling VOEvent from STC.
A future VOEvent schema could be greatly simplified if it were decoupled from STC and incorporated only those things that are in current use or for which can be shown clear use cases. Whether or not this is done, for future VOEvent schema designs, addition of "It would be nice if" items should be disallowed.
Please note: The mini-schema in Appendix A is included for only for reference as a schema that encompasses all of the messages that are currently flowing over the VOEvent network. While it does include XLink, it does not include STC. Instead, it specifies only those things in STC that are actually being used. It is not intended as a proposal for a minimum VOEvent schema.
Design-and-decree is a road to mediocrity or failure. A schema should not be adopted until it has been completely implemented (and even better, tested in a real world environment) by at least a few unrelated developers. Their implementations must generate a broad range of message forms which pass validation 100% of the time. Implementations must also understand the entire breadth of messages permitted by the candidate schema, and must be able to detect non-conforming messages.
As part of this, the candidate schema should be used as input to one or more automated object model generators. This process sometimes uncovers quirks in the schema design, usually due to not understanding the true significance of some design choice. For example, let's say a node in the schema is specified to have a cardinality of "any" and min/max of 0-∞. This could have been chosen in order to allow elements below the node to appear in any order instead of forcing them to appear in a strict order (as the "sequence" cardinality would require). After running it through (e.g.) Liquid, it becomes clear that the schema actually permits an infinite number of each sub element to appear in a valid message. A client of the object model would then need to count the number of occurrences of the sub elements and process each one as a collection of instances of one sub element. Thus, client code such as foo.bar.baz would be impossible. It would be foo.bar[index].baz - and what to use as index? And if the intention is to have only one of each type of sub element in the message, the schema design fails to implement that restriction. The better choice in that case would be a cardinality of "all". The Who and Author elements of VOEvent 1.1 are examples. It is completely legal in VOEvent 1.1 to have a million AuthorIVORNs! XML engine validation can therefore not protect against such things.
Brokers should be required to reject non-conforming VOEvent messages.
There is only one place where conformance is critical, the receiving end. There are three places where conformance assurance can be performed: the sender, the broker, and the receiver. With no control over the broker or the sender, the receiver is left with the tasks of pre-patching and rejection of patently incorrect messages at the receiving end. It should be clear that this isn't the best model. The receiver is susceptible to every new erroneous message form that appears. The best place to assure conformance is at the sender, preventing erroneous messages from getting into the network in the first place. But this requires rigorous programming and/or the use of an automated schema-driven tool as previously described, both of which require a minimized schema to be generally practical. And there are relatively many more senders than brokers.
It's worth considering the next-best thing – checking and filtering messages at the broker. In fact, this should probably be part of the future VOEvent model in any case. It will (also) prevent erroneous messages from getting out on the network. Since there will always be relatively few brokers, it seems reasonable to ask that each of them be rigorous in message conformance checking and rejection of messages which don't conform. In that case a sender is left with the choice of making certain that its messages are good before sending them or relying on the broker for conformance and dealing with rejection from the broker in some reasonable way. Either way, receivers (the most numerous elements) will have a minimum of problems to deal with.
The VOEvent WG should select a single universal transmission protocol.
Hopefully, this means choosing between Simple TCP and Jabber. The basic VOEvent network will work equally well with either.
This is the schema that resulted from the process described in Section 3.2.
<?xml version="1.0" encoding="utf-8" ?>
<xs:schema xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.ivoa.net/xml/VOEvent/v1.1" targetNamespace="http://www.ivoa.net/xml/VOEvent/v1.1" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:import schemaLocation="http://www.ivoa.net/xml/Xlink/xlink.xsd" namespace="http://www.w3.org/1999/xlink" />
<xs:element name="VOEvent">
<xs:complexType>
<xs:all>
<xs:element minOccurs="0" name="Who" type="Who" />
<xs:element minOccurs="0" name="What" type="What" />
<xs:element minOccurs="0" name="WhereWhen" type="WhereWhen" />
<xs:element minOccurs="0" name="How" type="How" />
<xs:element minOccurs="0" name="Why" type="Why" />
<xs:element minOccurs="0" name="Citations" type="Citations" />
<xs:element minOccurs="0" name="Description" type="Description" />
<xs:element minOccurs="0" name="Reference" type="Reference" />
</xs:all>
<xs:attribute name="version" type="xs:token" use="required" />
<xs:attribute name="ivorn" type="xs:anyURI" use="required" />
<xs:attribute default="observation" name="role" type="roleTypes" use="optional" />
</xs:complexType>
</xs:element>
<xs:complexType name="Author">
<xs:all>
<xs:element minOccurs="0" name="title" type="xs:string" />
<xs:element minOccurs="0" name="shortName" type="xs:string" />
<xs:element minOccurs="0" name="logoURL" type="xs:string" />
<xs:element minOccurs="0" name="contactName" type="xs:string" />
<xs:element minOccurs="0" name="contactEmail" type="xs:string" />
<xs:element minOccurs="0" name="contactPhone" type="xs:string" />
<xs:element minOccurs="0" name="contributor" type="xs:string" />
</xs:all>
</xs:complexType>
<xs:complexType name="Citations">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="EventIVORN" type="IVORN" />
<xs:element name="Description" type="Description" />
<xs:element name="Reference" type="Reference" />
</xs:choice>
</xs:complexType>
<xs:complexType name="Coordinates">
<xs:all>
<xs:element minOccurs="0" name="Time" type="Time" />
<xs:element minOccurs="0" name="Position2D" type="Position2D" />
<xs:element minOccurs="0" name="Position3D" type="Position3D" />
</xs:all>
<xs:attributeGroup ref="STCReference" />
<xs:attribute name="coord_system_id" type="xs:string" use="required" />
</xs:complexType>
<!-- Empty sequence here NOT in original schema -->
<xs:complexType name="CoordinateSystem">
<xs:sequence />
<xs:attributeGroup ref="STCReference" />
</xs:complexType>
<xs:complexType name="Description">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute default="text/plain" name="format" type="xs:string" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="Double1">
<xs:simpleContent>
<xs:extension base="xs:double">
<xs:attribute name="id" type="xs:ID" use="optional" />
<xs:attribute name="idref" type="xs:IDREF" use="optional" />
<xs:attribute name="ucd" type="xs:string" use="optional" />
<xs:attribute name="type" type="xs:string" use="optional" />
<xs:attribute name="href" type="xs:anyURI" use="optional" />
<xs:attribute name="ID_type" type="xs:string" use="optional" />
<xs:attribute name="IDREF_type" type="xs:string" use="optional" />
<xs:attribute name="time_unit" type="timeUnitTypes" use="optional" />
<xs:attribute name="pos_unit" type="posUnitTypes" use="optional" />
<xs:attribute name="pos_angle_unit" type="angleUnitTypes" use="optional" />
<xs:attribute name="vel_time_unit" type="velTimeUnitTypes" use="optional" />
<xs:attribute name="gen_unit" type="unitType" use="optional" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="Group">
<xs:choice maxOccurs="unbounded">
<xs:element minOccurs="0" name="Param" type="Param" />
<xs:element minOccurs="0" maxOccurs="1" name="Description" type="Description" />
<xs:element minOccurs="0" maxOccurs="1" name="Reference" type="Reference" />
</xs:choice>
<xs:attribute name="type" type="xs:string" use="optional" />
<xs:attribute name="name" type="xs:string" use="optional" />
</xs:complexType>
<xs:complexType name="How">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="Description" type="Description" />
<xs:element name="Reference" type="Reference" />
</xs:choice>
</xs:complexType>
<xs:complexType name="Inference">
<xs:all>
<xs:element minOccurs="0" name="Name" type="xs:string" />
<xs:element minOccurs="0" name="Concept" type="xs:string" />
<xs:element minOccurs="0" name="Description" type="Description" />
<xs:element minOccurs="0" name="Reference" type="Reference" />
</xs:all>
<xs:attribute name="probability" type="xs:float" />
<xs:attribute name="relation" type="xs:string" />
</xs:complexType>
<xs:complexType name="ISOTime">
<xs:simpleContent>
<xs:extension base="xs:dateTime">
<xs:attributeGroup ref="STCReference" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="IVORN">
<xs:simpleContent>
<xs:extension base="xs:anyURI">
<xs:attribute name="cite" type="citeTypes" use="optional" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="JDTime">
<xs:simpleContent>
<xs:extension base="xs:double">
<xs:attributeGroup ref="STCReference" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="Location">
<xs:sequence>
<xs:element minOccurs="0" name="AstroCoordSystem" type="CoordinateSystem" />
<xs:element minOccurs="0" name="AstroCoords" type="Coordinates" />
</xs:sequence>
<xs:attributeGroup ref="STCReference" />
</xs:complexType>
<xs:complexType name="MJDTime">
<xs:simpleContent>
<xs:extension base="xs:double">
<xs:attributeGroup ref="STCReference" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="ObsDataLocation">
<xs:sequence>
<xs:element name="ObservatoryLocation" type="Location" />
<xs:element name="ObservationLocation" type="Location" />
</xs:sequence>
<xs:attributeGroup ref="STCReference" />
</xs:complexType>
<!-- The empty sequence here is NOT in the original schema -->
<xs:complexType name="Param">
<xs:sequence />
<xs:attribute name="name" type="xs:token" use="optional" />
<xs:attribute name="ucd" type="xs:token" use="optional" />
<xs:attribute name="value" type="xs:string" use="optional" />
<xs:attribute name="unit" type="unitType" use="optional" />
<xs:attribute name="url" type="xs:anyURI" use="optional">
<xs:annotation>
<xs:documentation>For swift botch, not part of spec</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
<xs:complexType name="Position2D">
<xs:sequence>
<xs:element minOccurs="0" name="Name1" type="xs:string" />
<xs:element minOccurs="0" name="Name2" type="xs:string" />
<xs:element name="Value2" type="Value2" />
<xs:element minOccurs="0" name="Error2Radius" type="Double1" />
</xs:sequence>
<xs:attributeGroup ref="STCReference" />
<xs:attribute name="coord_system_id" type="xs:string" use="optional" />
<xs:attribute name="frame_id" type="xs:IDREF" />
<xs:attribute name="unit" type="posUnitTypes" />
</xs:complexType>
<xs:complexType name="Position3D">
<xs:sequence>
<xs:element minOccurs="0" name="Name1" type="xs:string" />
<xs:element minOccurs="0" name="Name2" type="xs:string" />
<xs:element minOccurs="0" name="Name3" type="xs:string" />
<xs:element name="Value3" type="Value3" />
<xs:element minOccurs="0" name="Error3Radius" type="Double1" />
</xs:sequence>
<xs:attributeGroup ref="STCReference" />
<xs:attribute name="coord_system_id" type="xs:string" use="optional" />
<xs:attribute name="frame_id" type="xs:IDREF" />
<xs:attribute name="unit" type="posUnitTypes" />
</xs:complexType>
<!-- The empty sequence is in the real schema, it closes this to content -->
<xs:complexType name="Reference">
<xs:sequence />
<xs:attribute name="uri" type="xs:anyURI" use="required" />
<xs:attribute name="name" type="xs:string" />
<xs:attribute default="url" name="type" type="xs:string" />
</xs:complexType>
<xs:complexType name="Time">
<xs:sequence>
<xs:element name="TimeInstant" type="TimeInstant" />
<xs:element minOccurs="0" maxOccurs="2" name="Error" type="Double1" />
<xs:element minOccurs="0" name="Name" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="2" name="Resolution" type="Double1" />
<xs:element minOccurs="0" maxOccurs="2" name="Size" type="Double1" />
</xs:sequence>
<xs:attributeGroup ref="STCReference" />
<xs:attribute name="coord_system_id" type="xs:string" use="optional" />
<xs:attribute name="frame_id" type="xs:IDREF" />
<xs:attribute name="unit" type="timeUnitTypes" />
</xs:complexType>
<xs:complexType name="TimeInstant">
<xs:all>
<xs:element minOccurs="0" name="ISOTime" type="ISOTime" />
<xs:element minOccurs="0" name="JDTime" type="JDTime" />
<xs:element minOccurs="0" name="MJDTime" type="MJDTime" />
</xs:all>
</xs:complexType>
<xs:complexType name="Value2">
<xs:sequence>
<xs:element name="C1" type="Double1" />
<xs:element name="C2" type="Double1" />
</xs:sequence>
<xs:attributeGroup ref="STCReference" />
<xs:attribute name="unit" type="posUnitTypes" use="optional" />
<xs:attribute name="vel_time_unit" type="velTimeUnitTypes" />
<xs:attribute name="gen_unit" type="unitType" />
</xs:complexType>
<xs:complexType name="Value3">
<xs:sequence>
<xs:element name="C1" type="Double1" />
<xs:element name="C2" type="Double1" />
<xs:element name="C3" type="Double1" />
</xs:sequence>
<xs:attributeGroup ref="STCReference" />
<xs:attribute name="unit" type="posUnitTypes" use="optional" />
<xs:attribute name="vel_time_unit" type="velTimeUnitTypes" />
<xs:attribute name="gen_unit" type="unitType" />
</xs:complexType>
<xs:complexType name="What">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element minOccurs="0" name="Param" type="Param" />
<xs:element minOccurs="0" name="Group" type="Group" />
<xs:element minOccurs="0" name="Description" type="Description" />
<xs:element minOccurs="0" name="Reference" type="Reference" />
</xs:choice>
</xs:complexType>
<xs:complexType name="WhereWhen">
<xs:all>
<xs:element name="ObsDataLocation" type="ObsDataLocation" />
<xs:element minOccurs="0" name="Description" type="Description" />
<xs:element minOccurs="0" name="Reference" type="Reference" />
</xs:all>
</xs:complexType>
<xs:complexType name="Who">
<xs:all>
<xs:element minOccurs="0" name="AuthorIVORN" type="IVORN" />
<xs:element minOccurs="0" name="Date" type="xs:dateTime" />
<xs:element minOccurs="0" name="Description" type="Description" />
<xs:element minOccurs="0" name="Author" type="Author" />
<xs:element minOccurs="0" name="Reference" type="Reference" />
</xs:all>
</xs:complexType>
<xs:complexType name="Why">
<xs:sequence>
<xs:element minOccurs="0" name="Name" type="xs:string" />
<xs:element minOccurs="0" name="Concept" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="unbounded" name="Inference" type="Inference" />
<xs:element minOccurs="0" name="Description" type="Description" />
<xs:element minOccurs="0" name="Reference" type="Reference" />
</xs:sequence>
<xs:attribute name="importance" type="xs:float" />
<xs:attribute name="expires" type="xs:dateTime" />
</xs:complexType>
<xs:attributeGroup name="STCReference">
<xs:attribute name="id" type="xs:ID" use="optional" />
<xs:attribute name="idref" type="xs:IDREF" use="optional" />
<xs:attribute name="ucd" type="xs:string" use="optional" />
<xs:attribute default="simple" ref="xlink:type" use="optional" />
<xs:attribute ref="xlink:href" use="optional" />
<xs:attribute name="ID_type" type="xs:string" use="optional" />
<xs:attribute name="IDREF_type" type="xs:string" use="optional" />
</xs:attributeGroup>
<xs:simpleType name="angleUnitTypes">
<xs:restriction base="unitType">
<xs:enumeration value="deg" />
<xs:enumeration value="rad" />
<xs:enumeration value="h" />
<xs:enumeration value="arcmin" />
<xs:enumeration value="arcsec" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="citeTypes">
<xs:restriction base="xs:string">
<xs:enumeration value="followup" />
<xs:enumeration value="supersedes" />
<xs:enumeration value="retraction" />
</xs:restriction>
</xs:simpleType>
<xs:complexType name="posAngleTypes">
<xs:simpleContent>
<xs:extension base="xs:double">
<xs:attribute default="deg" name="unit" type="angleUnitTypes" />
<xs:attribute default="X" name="reference" type="posAngleReferenceTypes" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:simpleType name="posAngleReferenceTypes">
<xs:restriction base="xs:string">
<xs:enumeration value="North" />
<xs:enumeration value="X" />
<xs:enumeration value="Y" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="posUnitTypes">
<xs:restriction base="unitType">
<xs:enumeration value="deg" />
<xs:enumeration value="deg deg m" />
<xs:enumeration value="deg deg Mpc" />
<xs:enumeration value="rad" />
<xs:enumeration value="h" />
<xs:enumeration value="arcmin" />
<xs:enumeration value="arcsec" />
<xs:enumeration value="m" />
<xs:enumeration value="km" />
<xs:enumeration value="mm" />
<xs:enumeration value="AU" />
<xs:enumeration value="pc" />
<xs:enumeration value="kpc" />
<xs:enumeration value="Mpc" />
<xs:enumeration value="lyr" />
<xs:enumeration value="" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="roleTypes">
<xs:restriction base="xs:string">
<xs:enumeration value="observation" />
<xs:enumeration value="test" />
<xs:enumeration value="utility" />
<xs:enumeration value="retraction" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="timeScaleTypes">
<xs:restriction base="xs:string">
<xs:enumeration value="TT" />
<xs:enumeration value="TDT" />
<xs:enumeration value="ET" />
<xs:enumeration value="TDB" />
<xs:enumeration value="TEB" />
<xs:enumeration value="TCG" />
<xs:enumeration value="TCB" />
<xs:enumeration value="TAI" />
<xs:enumeration value="IAT" />
<xs:enumeration value="UTC" />
<xs:enumeration value="GPS" />
<xs:enumeration value="LST" />
<xs:enumeration value="GMST" />
<xs:enumeration value="LOCAL" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="timeUnitTypes">
<xs:restriction base="unitType">
<xs:enumeration value="s" />
<xs:enumeration value="h" />
<xs:enumeration value="d" />
<xs:enumeration value="a" />
<xs:enumeration value="yr" />
<xs:enumeration value="cy" />
<xs:enumeration value="" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="unitType">
<xs:restriction base="xs:string" />
</xs:simpleType>
<xs:simpleType name="velTimeUnitTypes">
<xs:restriction base="unitType">
<xs:enumeration value="s" />
<xs:enumeration value="h" />
<xs:enumeration value="d" />
<xs:enumeration value="a" />
<xs:enumeration value="yr" />
<xs:enumeration value="cy" />
</xs:restriction>
</xs:simpleType>
</xs:schema>
The Simple TCP transmission protocol (also known as VTCP) was originally designed by Alasdair Alan for the Heterogeneous Telescope Network. It uses a TCP connection which provides reliable delivery of data. In VOEvent, the message is an XML document that conforms to the VOEvent schema. Simple TCP, however, is a layer below the message payload and does not care what the payload is, apart from it being UTF8 text. As used in VOEvent, there are three types of end-points that must implement Simple TCP: senders, listeners, and brokers. It is expected that Simple TCP will be formally described and submitted for acceptance by the VOEvent WG.
This description is by no means complete, it is intended to give the reader a flavor for the protocol and its simplicity.
Each message sent over the TCP connection is prefaced by a 4-octet count, followed by count octets which are presumed to be UTF8 encoded text. The 4-octet count must be in so-called network order forming a 32-bit integer count. This allows a receiver to know how many bytes to read in order to get the complete message.
When a sender wishes to send a message to a broker, it opens a TCP connection to the broker's receiving port and then sends the message. It then attempts to receive a response message from the broker. The broker responds with a Service Message of type "ack" indicating that it successfully received the message. After the sender gets the broker's response message, the sender closes the TCP connection.
To listen for messages from a broker, the receiver opens a TCP connection to the broker's sending port and waits for a message to arrive. Once a message has been received, the listener responds to the broker with Service Message of type "ack" that indicates that the message was successfully received. It then queues the just-received message for other resources and returns to listening for another message. The TCP connection remains open "forever".
Service Messages are XML documents used by the Simple TCP endpoints for two purposes: responses to data messages and listener connection "keepalive". The format of the XML message has tentatively been established but is beyond the scope of this document. It is enough to know that it expresses a simple enumerated response code (e.g. "ack") and some metadata.
As outlined in Section B.3, the listener's connection to the broker remains open "forever". The reality is that the connection can be lost for various reasons, thus the broker needs to know so it can close and drop the connection from its list. To accomplish this the broker sends periodic "iamalive" Service Messages to all connected listeners, and it expects the listeners to respond with an "iamalive" Service Message. As long as the broker gets responses, it keeps the connection open and on its list.
As stated above, Simple TCP is independent of the data message payload (except for the assumption that it is UTF8 text). If the layering between Simple TCP and VOEvent Messaging were blurred, it would be possible for a broker to respond with a Service Message that not only indicates that it successfully received the VOEvent message, but also that it passed VOEvent schema validation. Thus, an "ack" would mean that the message is valid VOEvent XML. If the message fails to validate, the response Service Message could be "nak" or "error" with metadata describing the validation error, line number in the XML, etc. this would accomplish the broker-based validity assurance suggested in Section 6.3. It may not be practical with Jabber.
Referenced documents are all online and are thus hyperlinked in context for convenience. No printed or otherwise offline documents are referenced by this Note.