Working With The Omixed Server API

Introduction

Before attempting to interact with the omixed server API it is important to have an understanding of the terminology being used. The Omixed Server Overview document provides an overview of the omixed design philosophy and defines some key concepts.

Syntax conventions in this document

The description of the API in this document assumes that the client code is written using Java. The semantics of the server interface are of course independent of the language being used to access them, i.e. the method and parameters names and the return types and contents are always the same. Instructions for language-specific libraries will explain how the server API is mapped to that language.

Client-Server Communications

There are two communication methods available to clients; the SOAP interface and the REST interface.

If you are using one of the language-specific libraries provided by the omixed developers, then you will not need to be concerned with the details of how methods and their parameters are passed to the server or how the responses are encoded. Instead you will be able interact with the server via a proxy object which hides these details from you. Please see the relevant section of the omixed website for details about which language specific libraries are available.

The SOAP interface involves constructing messages according to the SOAP standard and passing them to the server. Typically this layer will be handled by a language-specific library, however, if this is not available, it is possible to construct and transmit the messages using only standard string manipulation and TCP/IP networking capabilities.

Full details of the methods available from the server and the format of the input and output from those methods is provided by a WSDL document, which can be retrieved via the URL:

http://[YOUR MACHINE]:8080/omixed/server/wsdl

Invoking server methods using the REST interface is simpler because conventional URLs and URL entity encoding are used. This means that any language that has a HTTP-aware library will be able to access the server using this interface.

Forming requests

Instructions for constructing SOAP request messages are beyond the scope of this document. If your chosen client language does not offer a SOAP library, or the SOAP library exists but cannot parse the WSDL, then it is probably worth considering using the REST interface rather than attempting the use the SOAP interface by hand.

Server requests using the REST interface use the conventional encoding or URLs. The host and port part of the URL point to the machine running the omixed server. The path portion should match the service path that the omixed server is deployed to (this is set when the server is deployed, and by default is "omixed/server/") followed by the name of the method to invoke and finally, the query portion of the URL should encode the parameters as name=value pairs.

This is most easily illustrated by example. To invoke the connect method with the parameters 'userName = fred' and 'password = 4321' the URL would be:

http://example.org:8080/omixed/server/connect?userName=fred&password=4321

Note that the ordering of the parameters is vital; it must match the order of the parameters in the method signature, and all parameters must be present and must have values.

Conventional URL encoding rules are used to handle non-alphanumeric characters in either the parameters or the values, for example, using "%20" or "+" to represent a whitespace character.

Parsing server responses

Responses from the server are always SOAP encoded, irrespective of whether they are in response to a SOAP or REST call. However, when the REST interface is being used, the SOAP envelope will not be present in responses.

In cases where you are processing the results yourself (rather than using one of the supplied language-specific libraries) the key detail to be aware of is that the payload of the response is embedded in a <ns:return> element.

For example, the response to a successful invocation of the connect() method looks (mostly) like this:

<ns:connectResponse xmlns:ns="http://endpoint.omixedserver.omixed.org">
  <ns:return>
    <ConnectionDetails>
      <SessionID>177k9xb8yhkzkj6rnooa</SessionID>
      <ServerDomainName>something.somewhere.com</ServerDomainName>
      <ServerAPIVersion>2.0</ServerAPIVersion>
      <UserClass>guest</UserClass>
    </ConnectionDetails>
  </ns:return>
</ns:connectResponse>

The relevant part of the response is the XML encoded imformation found inside the <ns:return> element.

The omixed APIs employ three possible return types, namely String and String[ ] and Element. For methods which return String or Element, the SOAP response will contain a single <ns:return> element, the contents of which will be the return value of the method. The SOAP response for those methods which return String[ ] will contain one or more <ns:return> elements.

For example, the response to the accessGroupEnumerate method is a String[ ] which would be encoded in a SOAP response as follows:

<ns:AccessGroupEnumerateResponse xmlns:ns="http://endpoint.omixedserver.omixed.org">
  <ns:return>firstThing</ns:return>
  <ns:return>secondThing</ns:return>
  <ns:return>thirdThing</ns:return>
</ns:AccessGroupEnumerateResponse>

In situations where the server wishes to return a null value (typically used to indicate "no result"), then the response will contain a single <ns:return> element with no contents.

When the server encounters a problem in servicing a request it will throw an exception. Exceptions are used in Java applications as a system for handling situations where a method wishes to indicate that it could not return value as expected. In web service implementations, exceptions are represented using the SOAP fault mechanism. Instead of a normal response, the server will reply with a single <soapenv:Fault> element. For example, if an invalid user name or password is passed to the connect() method, then the response will be:

<soapenv:Fault>
  <faultcode>soapenv:Sender</faultcode>
  <faultstring>Unable to connect, incorrect user name or password</faultstring>
  <detail>
    <omixed:ErrorCode>2000</omixed:ErrorCode>
    <omixed:ErrorClass>
      org.omixed.omixedserver.database.ConnectionFailedException
    </omixed:ErrorClass>
  </detail>
</soapenv:Fault>

The message designed for the user is held in the <faultstring> element. Additional information in the form of an error code and an error class is also available.

If you are having difficulty parsing the server responses manually, a useful exercise is to access the REST service via a web browser and examine the raw responses.

For more details about error encoding in SOAP see the SOAP 1.2 specification)

In the remainder of this documentation, abnormal responses from the server will be referred to as exceptions being thrown. The provided language-specific libraries will use exception handling mechanisms if the language supports it, failing that, other error signalling solutions will be employed. Clients which are parsing the server responses directly should always check the response to determine whether it is an exception (i.e. it contains a <soapenv:Fault> element) before attempting to process the response normally.

Using Secure Connections

More secure communications are achieved by using SSL encryption. If the application server has been configured to support it, then a HTTPS connection can be used instead of a HTTP connection.

Connecting and Sessions

connect()

All interactions with the server require a session ID which can be acquired from the server using the connect() method.

String connect ( String resourceName, String userName, String password )

The three parameters identify the resource to connect to and a valid user name and password for that resource. All parameters are required.

If the connection is successful, then the response will be an XML document of this form:

<ConnectionDetails>
  <ServerAPIVersion> 2.0 </ServerAPIVersion>
  <SessionID> 54786325gfsahgdf </SessionID>
  <ServerDomainName> www.omixed.org </ServerDomainName>

  <UserClass> guest </UserClass>

  <PermissableGuestAction> TAG_ITEM </PermissableGuestAction>
  <PermissableGuestAction> POST_MESSAGE </PermissableGuestAction>
  <PermissableGuestAction> DOWNLOAD_FILE </PermissableGuestAction>

</ConnectionDetails>

(some whitespace added for clarity, it won't be present in the real reply)

The user class is provided so that clients can adjust their UI based on it, for example, knowing that 'guest' users cannot create items or that 'manager' users can masquerade as other users for the purposes of creating and updating items.

The API version is provided so that clients know what methods are available on the server.

The ordering of child elements in not guaranteed and might change. New child elements might be added in future.

The <PermissableGuestAction> elements will depend on options set in the omixed.properties file. They will only be present when the connection is for a guest level user.

Session IDs are pseudo-random, alpha-numerical strings. All subsequent interactions with the server will include this session ID as a parameter.

If there is a problem with the connection attempt, then a ConnectionFailedException will be thrown. The exception message will explain why the connection was refused. Possible messages include:

Multiple sessions for the same user on a single resource are permitted. The sessions will be considered as independent from the point of view of transaction processing.

If a session is dormant for a certain amount of time then it will be expired and the session ID will no longer be valid. Any interaction with the server which tries to make use of an invalid session ID will be rewarded with a SessionException.

disconnect()

A session can be closed using the disconnect() method:

String disconnect ( String sessionID )

The response from the server will be either the string OK or, in the event of problem, for example the session already being closed, the throwing of a SessionException.

Whilst it is not strictly necessary to close sessions as the server will eventually shut them after the idle timeout period has elapsed, it is recommended that client software explicitly disconnects from the server when no further interactions are planned.

Schema Querying

The following collection of methods are used to get information about the schema being used by the resource that has been connected to.

schemaEnumerateItemTypes()

A list of the item types in the schema can be retrieved using the schemaEnumerateItemTypes method which returns an array of strings, each string being the name of one of the item types. The ordering of the item types in the response is undetermined.

String[ ] schemaEnumerateItemTypes ( String sessionID )

schemaEnumerateRootItemTypes()

The designer of the schema will have identified one or more of the item types as being root item types which marks them as being suitable starting points for data entry or browsing. Clients may chose to present the root items types preferentially to the user. All schemata will have at least one root item type. The set of root item types can be discovered using the schemaEnumerateRootItemTypes method.

String[ ] schemaEnumerateRootItemTypes ( String sessionID )

schemaDescribeItemType()

The schemaDescribeItemType method is used to discover the structure of an item type, namely the links, files, and attributes that it is composed of. The method is invoked as follows:

String schemaDescribeItemType ( String sessionID, String itemType )

The server response will be an XML document which closely mirrors the format used to define item types in the schema definition language. For example, a simple "Person" item type might look like this:

<ItemType name="Person">
  <File name="Photo"/>
  <Attribute name="Date of Birth" type="DATE"></Attribute>
  <Attribute name="Home Page" type="URL"></Attribute>
  <Group name="Contact">
    <Attribute name="Address" type="TEXT"></Attribute>
    <Attribute name="Phone" type="STRING"></Attribute>
  </Group>
  <Link name="Colleague" to="Person" arity="many"/>
</ItemType>

schemaEnumerateLinks()

The schemaEnumerateLinks method returns a list of the names of other item types to which the specified item type has links.

String[ ] schemaEnumerateLinks ( String sessionID, String itemType )

schemaGetLayout()

Clients that wish to display a graphical representation of the schema can use the schemaGetLayout method. The GraphViz package is used to create a directed graph based on the item types and their interconnections. A wide array of different output formats are supported, most notably SVG, PDF and a selection of common image formats.

String schemaGetLayout ( String sessionID, String layoutOptions )

As most of the formats are binary (such as the PNG or PDF formats) the response from this method is not encapsulated by any SOAP infrastructure. The output from GraphViz is sent directly as the HTTP response without any SOAP envelope or other encapsulation. Additionally, the HTTP content-type of the response is set based on the format that is being returned. For example, SVG output is sent as "image/svg+xml" and PDF is sent as "application/pdf". This means that suitably aware applications, such as Web browsers, will be able to display the results directly (or will know how to pass them to a suitable viewer).

Options are passed to the server via the layoutOptions parameter. Options should be presented in the following format:

layoutMethod = neato
outputFormat = jpg
layoutArguments = -s 36 -Grankdir=LR

i.e. each layout option should be on a single line, and be of the form "name = value". Whitespace is optional.

The layout options are:

All layout options are optional; the default layout method is "dot", the default output format is "SVG" and there are no default layout arguments. If no options are being set, then the layoutOptions parameter should simply be an empty string.

This method relies on the GraphViz package being correctly installed, and the omixed.layout.graphVizBinaries property being set correctly in the omixed.properties file. If this is not the case, then a LayoutException will be thrown.

Locking

To avoid the situation whereby multiple sessions make simultaneous edits to an item and data is lost, a locking mechanism is available.

If locking is enabled, then before an item can be modified via a call to itemUpdate(), or removed using itemDelete(), a lock must be held on that item.

A session that wants to invoke with itemUpdate() or itemDelete() must first call lockAcquire() with the itemID for the item to be locked. If the call succeeds, then the item is said to be locked by that session. The session will then be able to call either itemUpdate() or itemDelete() on that item.

If the call to lockAcquire() fails then the session does not have a lock on the item and calls to itemUpdate() or itemDelete() will fail.

If you are sure that multiple clients will never try to modify the same item concurrently, or you do not care about this eventuality, then locking can be disabled. This will save a small amount of overhead when calling the itemUpdate() or itemDelete() operations. Locking is disabled by setting the property omixed.security.requireItemLocks to false in the omixed.properties file.

General principals regarding locks:

lockAcquire()

To ask for an exclusive lock on an item, use the following method:

String lockAcquire ( String sessionID, String itemID )

If it succeeds, the response will be a full description of the item that has been locked. The description will be exactly the same as that returned by a call to itemFind() with the returnType set to SHORT_ITEM_DETAILS.

Providing this response allows a client to easily verify that its version of the item is synchronised with the version on the server. This is not required behaviour, but in a highly concurrent environment, it might be a wise precaution.

On the other hand, if the call fails, then it will do so in of the the following ways:

LockException (2201)
if the lock is already held by some else
ValidationException
if the itemID is malformed
SessionException
if the sessionID is not valid

Note that is it possible to ask for, and be allocated, a lock on an item which doesn't exist. However, trying to subsequently update or delete the item will cause an error.

lockRelease()

To give up a lock which is no longer required (if, for example, the user has abandoned the editing process)

String lockRelease ( String sessionID, String itemID )

If the lock is released successfully then the response will be "OK". Otherwise, one of the following exceptions will be thrown:

LockException (2202)
if the specified lock is not held by the session
ValidationException
if the itemID is malformed
SessionException
if the sessionID is not valid

Creating, Updating and Deleting

New items are created using the itemCreate method, the itemUpdate method allows existing items to be modified. The itemDelete method permanently removes items.

The itemCreate and itemUpdate methods take similar arguments, notably an itemID to identify the item, the name of an access group for the item, and the detailed description of the item in itemXML.

itemCreate()

The itemCreate method takes the itemID of the new item, the name of accessGroup for the item and the item's description in itemXML. If the item is created successfully then the response "OK" will be sent, otherwise an exception will be thrown indicating why the item could not be created.

String itemCreate ( String sessionID, String itemID, String accessGroup, String itemXML )

The itemID must be complete and the itemOwner component should be the same as the user associated with the sessionID. Users in the manager role are excepted from this rule; they can create items which are owned by other users.

The accessGroup parameter specifies the access group to which this item belongs.

The itemXML is based on the format of the item type in the schema definition. For example, if the item type 'Photograph' is defined as follows:

<ItemType name="Photograph">
  <Link to="Camera"/>
  <Attribute name="Date Taken" type="date" />
  <Attribute name="Location" type="string" />
  <Group name="Size">
    <Attribute name="Width" type="number" />
    <Attribute name="Height" type="number" />
  </Group>
  <File name="Image Data"/>
</ItemType>

then a specific item of this type might be defined like this:

<Item>
  <Link name="Camera" itemID="someThing/someWhere/somePerson/Photograph/IMG00452"/>
  <Attribute name="Date Taken"> 2005-12-23 </Attribute>
  <Group name="Size">
    <Attribute name="Width"> 8 </Attribute>
    <Attribute name="Height"> 6 </Attribute>
  </Group>
  <File name="Image Data" fileID="ahdg34872djs"/>
</Item>

The rules for generating itemXML are as follows:

If the itemXML has a syntax errors, then a ValidationException will be thrown.

If the item type has one or more validation rules defined, (see the Schema Designer for details), then they must be satisfied for the item creation to succeed.

Even with well-formed itemXML which satisfies all of the validation rules for the item type, item creation can fail for other reasons, some of which are:

itemUpdate()

The update method is essentially identical to the create method, except that it is used to modify items that have already been created.

Updating an item can only be done by the user who owns it, or who has permission to write to that item, or by a user in the manager class.

String itemUpdate ( String sessionID, String itemID, String accessGroup, String itemXML )

Note that the name of an item can never be changed. The itemID is fixed when the item is created and it is immutable.

If the server has locking enabled, then the session must have acquired a lock on the item before updating it. This is done using the lockAcquire method. Attempting to update an item which is not locked by the session will result in a LockingException (code 2202).

The itemXML is constructed in exactly the same way as for the itemCreate method. Even if the modification is changing a singe character in one attribute value, the full itemXML must still be supplied.

If the update succeeds, the response from the server will be the string "OK", otherwise some exception will be thrown indicating the reason for failure. The possible reasons for failure will be essentially the same as those for the itemCreate method.

itemDelete()

The delete method completely removes an item. Deleting an item can only be done by the user who owns it, or who has permission to delete it, or by a user in the manager class.

If the server has locking enabled, then the session must have acquired a lock on the item before deleting it. This is done using the lockAcquire method. Attempting to delete an item which is not locked by the session will result in a LockingException (code 2202).

String itemDelete ( String sessionID, String itemID )

If the item was deleted successfully, then the server response will be the string "OK", otherwise an exception will be thrown indicating why the operation failed.

It is not permitted to delete an item that is being linked to by one or more other items. If the server refuses to delete an item for this reason, then the itemFind method can be used to discover the set of items which are linked to it.

itemValidate()

The itemValidate method allows a client to confirm that an item is valid prior to attempting to create or update it.

String itemValidate ( String sessionID,
String itemID,
String accessGroup,
String itemXML,
boolean intendedForUpdate

The parameters are the itemID, accessGroup and itemXML are the same as for both the itemCreate and itemUpdate methods.

The intendedForUpdate selects whether the item should be validated as if it is an update to an existing item, or whether it should be treated as new item.

If the server is happy with the item, then the response will be "OK". Otherwise, an exception will be thrown, the message of which will detail the problem(s) that the server detected.

File Upload and Download

The omixed schema language permits arbitrary data files to be attached to items in a similar manner to the way the items can be linked to one another.

However, files are quintessentially different to items in that the latter are well structured XML representations, typically a few hundred bytes in size, whereas the former have an unknown structure and a potentially unlimited size.

In particular, files are not very amenable to transport via the SOAP protocol (although there is a standard for 'SOAP with attachments', it is not yet well supported). For this reason, files are handled differently to items by the omixed server; Files are uploaded using HTTP POST operations and are downloaded using HTTP GET operations.

This solution makes it reasonably easy for clients to send and receive files as HTTP file transfer is relatively well supported in libraries for many languages. If your client language does not have a suitable library, the message body for file upload can be composed manually by following the guidelines in RFC 1867.

fileUpload

Files are uploaded to the server by making a HTTP POST request using the "form/multipart" encoding. The URL is the same as that used for making REST requests with "fileUpload" appended, for example:

http://example.org:8080/omixed/server/fileUpload?sessionID=...

The value of the sessionID must be a valid session belonging to a user who has permission to upload files.

The accessGroup URL parameter specifies the access group to which this file belongs.

The optional format URL parameter can be used to provide some minimal information about the format or contents of the file.

http://[host]:[port]/OmixedFileServer/OmixedFileServer?sessionID=[sessionID]&accessGroup=[accessGroup]&format=[format]

The message body should have a single attachment, namely the file to be uploaded.

The form element containing the attached file must have the ID "fileName".

The response will be a string which indicates whether the upload succeeded or not. In the case of success, the response string will be of the form:

GOOD : [fileID] : [fileSizeInBytes] : [originalNameOfFile]

The fileID is the handle to the file that can be subsequently used to refer to it in <File> elements.

The fileSizeInBytes and originalNameOfFile information can be used by the client to verify that the file upload appears to have worked.

If the upload did not succeed, then the response will be of the form:

BAD : [reason for failure]

fileDownload

Files are downloaded using a HTTP GET request. The URL is the same as that used for making REST requests with "fileDownload" appended, for example:

http://example.org:8080/omixed/server/fileDownload?sessionID=...&fileID=...

If the sessionID and fileID identify a valid session and a file that the user has permission to access, then the response will be a normal HTTP response with a 'content-type' of "application/octet-stream". No SOAP wrappers (or wrappers of any type) will be present thereby allowing the client to process the data directly. This is handy when the client is running within a Web browser as the browser may be able to determine the correct way to deal with the incoming data, e.g. to display an image, or to open it some external application.

If there is a problem with the request (for example, the file does not exist, or the session is not valid) then the response will have a 'content-type' of "text/html" and the body will contain a single line of the form:

BAD : [reason for failure]

fileEnumerate()

As files are handled separately from the items which use them, clients may sometimes wish to present the user with a list of files to chose from. The set of files that are visible to a session can be retrieved using this method:

String fileEnumerate ( String sessionID )

which returns an XML document of the form:

<FileList/>
  <File fileID="..." originalName="..." sizeInBytes="..." format="..." ownerName="..." accessGroup="..." uploadTime="..." />
  <File fileID="..." originalName="..." sizeInBytes="..." format="..." ownerName="..." accessGroup="..." uploadTime="..." />
</FileList/>

If no files are visible, then the response will be an empty <FileList> element.

Files are returned in chronological order of upload, with the most recently uploaded one first.

fileDescribe()

The information about a specific file can be retrieved using:

String fileEnumerate ( String sessionID, String fileID )

which returns a description like this:

<FilefileID="..."
originalName="..."
sizeInBytes="..."
format="..."
ownerName="..."
accessGroup="..."
uploadTime="..." />

fileDelete()

A file that is no longer required can be deleted by calling:

String fileEnumerate ( String sessionID, String fileID )

A file can only be deleted if the following conditions are met:

Item Tagging

The following set of methods are used to add tags to items. Tags are arbitrary text strings that can be used to provide a free-form organisational layer to a collection of items. The principal use of tags is for searching or sorting data. Tags make it easy to add to add ad-hoc meta-data to items without having to work within the constraints of the schema.

A tag can be applied to any item that is visible to the session. The item does not have to be owned by the user adding the tag. Tags have their own visibility rules, it is possible to add 'private' tags, visible only to the person who owns them, 'public' tags, visible to everybody, or anywhere in-between using the access group mechanism.

Items can be tagged any number of times, potentially with the same tag from different users, but each user can only tag the item once with any given tag.

The set of tags attached to one or more items can be discovered using the itemFind method with the returnType parameter set to ITEMS_WITH_TAGS

tagAdd()

A new tag is added to an item using the tagAdd method.

String tagAdd ( String sessionID,
String itemID,
String accessGroup,
String tagName )

This method add a tag specified by tagName with visibility specified by accessGroup to an existing item specified by itemID.

If the accessGroup is not recognised then a ValidationException will be thrown.

If the specified itemID does not exist or is not visible to the session then nothing will happen and no exception will be thrown. This behaviour is designed to prevent this method from being used surreptitiously to determine whether particular items exist.

Whilst there is no server enforced limit to the maximum length of a tag, it is suggested that tags should be relatively short, ideally one or two words, so that they can be displayed easily in lists.

tagRemove()

The tagRemove method removes a tag from an item.

Only the owner of the tag (or a user in the 'manager' class) can remove that tag.

String tagRemove ( String sessionID,
String itemID,
String tagName,
String tagOwnerName )

If the specified itemID does not exist or is not visible to the session then nothing will happen and no exception will be thrown. This behaviour is designed to prevent this method from being used surreptitiously to determine whether particular items exist.

Note that the tagOwnerName is required because the same tagName might be applied to a single item by multiple users. If the user is of 'manager' class, or is a member of an access group which grants them write permission on several tags, then the tagOwnerName parameter is required to disambiguate between tags.

If the specified item does exist and is visible to the session, but does not have a tag corresponding to tagName owned by the specified user, then a TaggingException will be thrown.

tagEnumerate()

Some clients will want to be able to discover which tags are currently defined in a resource, for example, if they wish to construct a user interface component for selecting from existing tags. This information is available using the tagEnumerate method.

String[ ] tagEnumerate ( String sessionID )

The server response for this method is a list of all of the tags currently defined in a resource, i.e. tags which have been used at least once since the resource was initialised.

Tags are ordered by their popularity with the most commonly used tags being listed first.

If there are no tags currently defined, then null is returned.

Notifications

The notification system is based on triggers which are rules that define one or more events that a user is interested in. For instance, a user might wish to be notified whenever some other user adds a tag to one of their items. This is achieved by defining a trigger which specifies this event. Whenever an event activates this trigger, the owner of the trigger will receive a notification message in their queue.

Clients can use the notification in a polling manner to implement a near real-time sharing experience. Clients can remain synchronised with one another by polling for new messages quite frequently, for instance, once a second. The notificationGetMessagesAndReset method is specifically designed to support this efficiently.

A notification can occur when a particular event happens to a given item. The following set of events are available for monitoring:

A trigger is the combination of one or more of these event identifiers and some regular expressions which are used to determine whether the item is of interest. The regular expressions should use Java syntax, see here for details. An empty string is treated the same as the expression ".+", i.e. it will match anything.

Two varieties of trigger are available, session and permanent. The latter are persistant and can be activated at any point, whereas the former are transient and are automatically removed when the session that created them is closed. The two types of trigger are essentially completely in dependant. Notification messages generated by session triggers are held in separate queues to those generated by permanent triggers. Each queue is queried and emptied independently. All notification related methods take a triggerType parameter which determines whether the session or permanent triggers are being manipulated.

Session-level triggers are more convenient for clients wishing to use notifications in a polling mode. The client does not have to be concerned with interfering with other triggers that the user may have set up. Instead, it can create the triggers that it needs at any given point (e.g. if it is displaying a list of "samples" then it might add a trigger watching for changes to "samples"). Once the client closes down, any triggers it created will be automatically cleaned up.

Conversely, permanent triggers are more likely to be added directly under user control, for events that they which to be alerted about next time they log in.

notificationAddTrigger()

To add a new trigger:

String notificationAddTrigger ( String sessionID,
String triggerType,
String eventTypes,
String resourceNamePattern,
String itemTypeNamePattern,
String ownerNamePattern,
String itemNamePattern )

For example, if the user "Geraldine" wishes to be notified when anybody adds a tag to one of her items, then the triggerType would be set to PERMANENT, eventTypes would be set to ADD_TAG and the ownerNamePattern set to Geraldine. All other patterns should be left empty so they will match anything.

notificationRemoveTrigger()

To remove a trigger, call notificationRemoveTrigger with exactly the same set of parameters that were used to add it.

String notificationRemoveTrigger ( String sessionID,
String triggerType,
String eventTypes,
String resourceNamePattern,
String itemTypeNamePattern,
String ownerNamePattern,
String itemNamePattern )

notificationGetTriggers()

To see the set of triggers that belong the user of the current session, use:

String notificationGetTriggers ( String sessionID,
String triggerType )

This will return an XML representation of the triggers in the following format:

<TriggerList>
...
<TriggertriggerType="..."
eventTypes="..."
resourceNamePattern="..."
itemTypeNamePattern="..."
itemOwnerPattern="..."
itemNamePattern="..." />
...
</TriggerList>

There will be one <Trigger> element for each trigger. The attributes of these elements (which are named to match the parameters of the notificationAddTrigger method) will give the full details of that trigger.

If there are no triggers in place, then an empty <TriggerList> will be returned.

notificationGetMessages()

To get the notification messages that have been queued for the user, call:

String notificationGetMessages ( String sessionID,
String triggerType )

This will return an XML representation of the triggers in the following format:

<NotificationList>
...
<NotificationtimeStamp="..."
itemID="..."
userName="..."
eventType="..." />
...
</NotificationList>

The response is a <NotificationList> element which will contain zero or more <Notification> child elements.

The attributes of the <Notification> element depending on the type of event that is being reported. The element will have at least the following four attributes:

Timestamps are in the form: shortDayName shortMonthName dayNumber hour:minute:second timezone year, for example: "Tue Mar 04 05:06:07 GMT 2008".

For ADD_TAG notifications, there will also be tagName attribute. Similarly, for POST_MESSAGE notifications, there will be an additional messageBody attribute.

notificationRemoveAllMessages()

Notification messages normally state in the queue until they are removed. Messages are queued separately for SESSION and PERMANENT triggers. To empty one of the queues, use this method:

String notificationRemoveAllMessages ( String sessionID,
String triggerType )

notificationGetMessagesAndReset()

A common operation for a client is to ask for "all new messages". This is encapsulated by the following method which returns the same <NotificationList> response as notificationGetMessages but also performs the equivalent of notificationRemoveAllMessages. This means that repeated calls to this method will only ever return 'new' notifications, i.e. those which occurred since the last call to the method.

String notificationGetMessagesAndReset ( String sessionID,
String triggerType )

Discussion Fora

In addition to tagging, the server also offers a simple discussion forum facility. A discussion forum is a collection of discussion threads, each of which has a title and contains an ordered series of messages.

Every item has its own discussion forum (although this is not created until the first message is added). If an item is visible to a session, then that session will be able to view the existing messages, post a new message and create new threads in the discussion forum for it.

Searching of the text in forum messages is integrated with the searching of all other type of data, i.e. is it available via the findItems method.

It is anticipated that discussion fora can be used in a manner similar to tagging, namely as informal, semi-structured method of attaching meta-data to items. Postings need not be made only by people, for instance, automated processing scripts might choose to post a forum message for an item when they have done some analysis using data from it.

forumCreateThread()

To create a new discussion thread and post the first message to it, a client should call the forumCreateThread method.

int forumCreateThread ( String sessionID,
String itemID,
String threadTitle,
String messageBody )

The response from this method is the index of the newly created discussion thread, which can be used if the client want to post another message to that thread.

A new thread can only be created in a forum which belongs to an item that exists and that is visible to the session. If this is not the case, then a ForumException will be thrown.

Both the threadTitle and the messageBody must be non-empty strings (i.e. they must contain at least one non-whitespace character). If this is not the case, a ForumException will be thrown.

If the forum already contains a thread with the specified threadTitle, then a new, unrelated thread with the same title will be created. As the threadTitle is not used to identify threads, this is not a problem from the point of view of the API, but might serve to confuse readers of the forum.

Messages are given a timestamp when they are created. That timestamp will subsequently be available via a call to the forumGetMessages method.

forumPostMessage()

A new message can be posted to an existing thread using the forumPostMessage method.

int forumPostMessage ( String sessionID,
String itemID,
int threadIndex,
String messageBody )

The response from this method is the index of the newly created message, which can be used if the client wishes to subsequently delete or edit the message. Forum threads are always numbered sequentially starting from 1.

Messages are given a timestamp when they are created. That timestamp will subsequently be available via a call to the forumGetMessages method.

A new message can only be posted in a forum which belongs to an item that exists and that is visible to the session. If this is not the case, then a ForumException will be thrown.

forumDeleteMessage()

A message can be deleted using the forumDeleteMessage method.

String forumDeleteMessage ( String sessionID,
String itemID,
int threadIndex,
int messageIndex )

Deleting a message destroys the contents of the message, but the now empty message still remains in the thread. Additionally, a timestamp is stored which records when the message was deleted. This information will be available in the results of a call to the forumGetMessages method.

Only the owner of a message can destroy it. Attempting to destroy a message owned by somebody else will result in a ForumException.

If the specified itemID is invalid, the item does not exist, the item exists but is not visible to the session, or the item has no discussion forum, then a ForumException will be thrown.

If the specified threadIndex or messageIndex does not match an actual thread index on the forum, then a ForumException will be thrown.

forumGetThreads()

Information about the threads in a particular forum is available using the forumGetThreads method.

String forumGetThreads ( String sessionID,
String itemID,
int fromIndex,
int toIndex,
String ordering )

The response is an XML document composed of a single Forum element containing one Thread element for each discussion thread whose index lies within the range specified by fromIndex and toIndex.

The Forum element also reveals how many threads there are in total. Clients which want to present thread lists in a page-based manner can use this number to calculate how many pages of results remain.

Forum threads are always numbered sequentially in the order that they are created. The numbering starts from 1. As it is impossible to delete a thread, thread indices will always be continuous.

The ordering parameter controls the order in which the Thread elements in the result will appear. Permitted values are "OldestFirst", in which case the threads are listed in chronological order (i.e. the oldest threads first), or "NewestFirst", in which case they are listed in reverse chronological order (i.e. the newest threads first). If the specified value is not recognised, a ForumException will be thrown.

An example output from a call to this method for a forum which contains 10 threads, where fromIndex was set to 6, toIndex was set to 8 and the specified ordering was "OldestFirst"might be:

<Forum itemID="..." threadCount="10">
  <Thread threadIndex="6" title="..." messageCount="..." mostRecentPostTime="..." mostRecentPoster="..."/>
  <Thread threadIndex="7" title="..." messageCount="..." mostRecentPostTime="..." mostRecentPoster="..."/>
  <Thread threadIndex="8" title="..." messageCount="..." mostRecentPostTime="..." mostRecentPoster="..."/>
</Forum>

If you do not wish to limit the fromIndex or toIndex, then any negative value can be used instead to signify 'unlimited'. For example setting both to -1 will result in all threads being listed in the result.

Each Thread element describes a single discussion thread. It reports the threadIndex (which will be required as a parameter in methods to read or post messages in that thread), the title of thread and the messageCount for thread.

In addition, each Thread element contains a timestamp for the most recent posting activity in that thread and the name user who made the post. This information is available in mostRecentPostTime and mostRecentPoster respectively.

Timestamps are in the form: shortDayName shortMonthName dayNumber hour:minute:second timezone year, for example: "Tue Jun 23 15:16:17 GMT 2007".

If the specified itemID is invalid, the item does not exist, the item exists but is not visible to the session, or the item exists but has no discussion forum, then a ForumException will be thrown.

forumGetMessages()

The forumGetMessages method is used to extract one or messages from a specific thread.

String forumGetMessages ( String sessionID,
String itemID,
int threadIndex,
int fromIndex,
int toIndex,
String ordering )

If the specified itemID is invalid, the item does not exist, the item exists but is not visible to the session, or the item has no discussion forum, then a ForumException will be thrown.

If the specified threadIndex does not match an actual thread index on the forum, then a ForumException will be thrown.

If the parameters are valid, then the response is an XML document composed of a single Forum element containing one Thread element which will contain one Message element for each message whose index lies within the range specified by fromIndex and toIndex.

The Thread element also reveals how many messages there in total in that thread. Clients which want to present messages in a page-based manner can use this number to calculate how many pages of results remain.

Messages are always numbered sequentially in the order in which they are posted. The numbering starts from 1. As it is impossible to permanently remove a message (see the forumDeleteMessage method), message indices will always be continuous.

The ordering parameter controls the order in which the Message elements in the result will appear. Permitted values are "OldestFirst", in which case the messages are listed in chronological order, or "NewestFirst", in which case they are listed in reverse chronological order. If the specified value is not recognised, a ForumException will be thrown.

An example output from a successful call to this method selecting a thread which has 20 messages, where fromIndex was set to 1, toIndex was set to 3 and the specified ordering was "NewestFirst", might be:

<Forum itemID="..." threadCount="10">
  <Thread threadIndex="12" title="..." messageCount="20">
    <Message messageIndex="3" owner="..." posted="...">
      this is the body for message 3
    </Message>
    <Message messageIndex="2" owner="..." posted="...">
      the body of message 2 is here
    </Message>
    <Message messageIndex="1" owner="..." posted="...">
      message 1 body will be here
    </Message>
  <Thread
</Forum>

Note that the response will always begin with a Forum element. This is supplied so that the software processing the response has some additional context as to which forum the messages come from.

Within the Forum element will be a single Thread element which will reveal the threadIndex, the title and the total messageCount for the thread in question.

Finally, within the Thread element will one Message element for each message whose index lies within the range specified by fromIndex and toIndex.

If you do not wish to limit the fromIndex or toIndex, then any negative value can be used instead to signify 'unlimited'. For example setting both to -1 will result in all of the messages in the thread being listed in the result.

Each Message element describes a single message from the discussion thread. It reports the messageIndex (which will be required as a parameter in methods to delete or update that message), the owner of the message and a timestamp indicating when the message was posted.

Timestamps are in the form: shortDayName shortMonthName dayNumber hour:minute:second timezone year for example "Tue Jun 23 15:16:17 GMT 2007".

For messages that have been deleted, the message body will be empty and an extra attribute will be present in the Message element. The deleted value will be a timestamp which indicates when the message was deleted, for instance:

<Message messageIndex="..." owner="..." posted="..." deleted="Thu Jun 25 19:18:17 GMT 2007"/>

Browsing and Searching

The itemFindText method provides simple text searching capabilities. Matching can be performed against item names, attribute values, tags and the contents of forum messages in a single operation.

More sophisticated searching functionality, for example the ability to search through specific attributes, compare values and so on comes via the itemFind method.

The third searching method, itemFindLayout is a specialised form of searching in which the results are handed to the GraphViz package to generate a visual representation.

itemFindText()

The itemFindText method searches all of the text associated with all items and returns information about the items which match.

String itemFindText ( String sessionID, String searchString, String searchOptions )

The searchString parameter specifies the text string that will be searched for.

The searchOptions parameter controls which components of the items will be examined and also determines how matching will be performed.

The server response will be an XML document identifying the items which were found. The particular components of each item which resulted in a successful match will be indicated.

If no matches are found, then the server response will be null.

Each MatchedItem in the response corresponds to a single item. Any given item will only appear at most once in the array. If the item matches the search term for multiple reasons, then the different reasons for the matches will be included.

An example response is as follows:

<SearchResults>
  <MatchedItem itemID="alpha/beta/delta/gamma/epsilon">
    <MatchedAttribute name="something"> some value that matched </MatchedAttribute>
  </MatchedItem>
  
  <MatchedItem itemID="aDomain/aResource/aType/anOwner/aName"/>
  
  <MatchedItem itemID="omixed.org/bung/bing/bang/bong">
    <MatchedTag name="some tag which matched"/>
    <MatchedTag name="some other tag which matched"/>
    <MatchedAttribute name="blah"> an attribute value that matched </MatchedAttribute >
  </MatchedItem>
</SearchResults>

Each hit is represented by a single MatchedItem element. This element can have MatchedAttribute, MatchedTag, MatchedForumThread children which are used to indicate why the item was returned in the search results.

If the element has no children, then the match for this item was caused by a hit against its name.

If children are present, then they should be interpreted as follows:

itemFind()

A itemFind method performs searching using a user-supplied pattern which describes one or more properties or the desired results, for example "items of type X" or "items owned by user Y" or "items with names beginning with Z". All items in the resource which fit that pattern will be returned.

Results can be returned in a variety of formats ranging from simply a list of itemIDs to complete item graphs.

The method takes three parameters; returnType select the format that the results will be returned in, queryXML which contains the an XML representation of the query pattern, and queryOptions which optionally contains context-specific settings to control various search options.

String itemFind ( String sessionID, String returnType, String queryXML, String queryOptions )

An initial impression of the full capabilities of itemFind can be gained from the example queries which follow. Full details of the syntax, the response formats and many more examples can be found in the Omixed Query Syntax document.

Complete details of the pattern syntax, the query options, the response formats and many more examples can be found in the Omixed Query Syntax document.

itemFindLayout()

The itemFindLayout method is a a variant of itemFind in which the results of the search are passed to the GraphViz engine which generates a graphical representation of them.

The method is invoked as follows:

String itemFindLayout ( String sessionID, String queryXML, String queryOptions, String layoutOptions )

The queryXML parameter specifies the pattern which the results must match. It is provided in the same syntax as used for itemFind.

The queryOptions parameter allows for arbitrary extra parameters to be provided for certain query types; its use is explained in the Omixed Query Syntax document.

The layoutOptions are specified in the same way as for schemaGetLayout, mostly importantly the options include the ability to select the layout method and output format.

Other Features

accessGroupEnumerate()

The Access Group mechanism is a key part of data sharing in omixed. Each discrete unit of data, i.e. items, tags and files, is allocated to an access group - and that access group controls which users have read, write and delete access to that data.

When creating or updating items (or tags, or files) a client is likely to want to to be able to present a list of possible action groups into which the item (or tag, or file) can be placed. The accessGroupEnumerate method provides that functionality:

String accessGroupEnumerate ( String sessionID, String action )

returns the names of access groups in which the user associated with the sessionID can perform the specified action.

The set of possibles action values is: read, write and delete.

If the action is not available in any access groups, then the response will be empty.

The built-in access groups public and private are not included in the results.

userPropertySet()

User properties are a convenient way for clients to store persistant state information on a per-user basis. User property values persists between sessions, hence they offer a simple method for storing preferences, history or other useful information. Properties are simple name:value pairs of String data, allowing a client to use whatever encoding method they want. A property is set by calling:

String userPropertySet ( String sessionID, String name, String value )

which returns "OK" if the property was set or which throws an exception if not. If the value is set, then it can later be retrieved by a call to userPropertyGet.

userPropertyGet()

Accessing user properties is done via the userPropertyGet method:

String userPropertyGet ( String sessionID, String name )

which returns the value associated with the named property. The value will have been previously set via a call to userPropertySet.

If the value has not been set for the property, then calling this method will result in empty response.