OsidRecords
Summary
OsidObjects are interfaces containing a set of general purpose methods satisfying the relational requirements of the the service model or are most always applicable in their broad domain. Additional interfaces serving more specific needs can be added to any Extensible using osid.OsidRecord.
OsidRecords
An OSID Provider may associate osid.OsidRecord to any Extensible interface. An OsidRecord is an interface definition of a set of methods used to supplement the core interface. An OsidRecord is identified by a record Type.
Example
A Resource defines a set of core methods such as:
- osid.id.Id getId()
- osid.locale.DisplayText getDisplayName()
- osid.locale.DisplayText getDescription()
- osid.type.Type getGenusType()
A Resource may be extended with an OsidRecord identified by colorResourceRecordType with:
- String getColor()
General Pattern
Every managed entity is accompanied by a series of functional service slices as indicated by the defined OsidSessions. For example, there will be one for lookup, search, and create/update/delete. There is a corresponding set of interfaces defined for the entity for use in these OsidSessions.
- OsidObject: a read-only interface into the entity
- OsidForm: an interface to create or update the entity
- OsidQuery: an interface to perform entity queries
- OsidSearchOrder: an interface to order by attributes of the entity
- OsidQueryInspector: an interface to examine the entity OsidQuery
All of the above interfaces Extensibles. Each may have OsidRecords. Typically, it makes sense that same record Type is used to identify the various OsidRecords among these different interfaces. Using the color example above, the following OsidRecords would all be identified by the same colorResourceRecordType.
colorResourceRecord | |||
Method | getColor | ||
---|---|---|---|
Description | Gets the color of this Resource. | ||
Return | string | the color | |
Compliance | mandatory | This method must be implemented. | |
colorResourceFormRecord | |||
Method | getColorMetadata | ||
Description | Gets the metadata for the color. | ||
Return | osid.Metadata | the metadata | |
Compliance | mandatory | This method must be implemented. | |
Method | setColor | ||
Description | Sets the color. | ||
Parameters | string | color | the color of this resource |
Errors | INVALID_ARGUMENT | color is invalid | |
NULL_ARGUMENT | color is null | ||
Compliance | mandatory | This method must be implemented. | |
Method | clearColor | ||
Description | Clears the color. | ||
Compliance | mandatory | This method must be implemented. | |
colorResourceQueryRecord | |||
Method | matchColor | ||
Description | Matches resources of the given color. | ||
Parameters | string | color | the color to match |
osid.type.Type | stringMatchType | the string match type | |
boolean | match | true for a positive match, false for a negative match | |
Errors | NULL_ARGUMENT | color or stringMatchType is null | |
UNSUPPORTED | supportsStringMatchType(stringMatchType) is false | ||
Compliance | mandatory | This method must be implemented. | |
colorResourceQueryInspectorRecord | |||
Method | getColorTerms | ||
Description | Gets the color query terms. | ||
Return | osid.search.terms.StringTerm[] | the string query terms | |
Compliance | mandatory | This method must be implemented. | |
colorResourceSearchOrderRecord | |||
Method | orderByColor | ||
Description | Orders the results by color. | ||
Parameters | osid.SearchOrderStyle | style | the search order style |
Errors | NULL_ARGUMENT | style is null | |
Compliance | mandatory | This method must be implemented. |
Record Types
A record Type is a Type that identifies the specification of an OsidRecord. In the OSID Java Binding, a Type acts as the identifier for the bound Java interface of the OsidRecord.
Mechanism
The Extensible provides access to OsidRecords. The OsidRecord of the specified record Type must first be requested. By specification, the OsidRecord may be cast into the specification identified with the appropriate record Type.
if (resource.hasRecordType(colorResourceRecordType)) { osid.OsidRecord record = resource.getResourceRecord(colorResourceRecordType); ColorResourceRecord colorRecord = (ColorResourceRecord) record; }
Here are some bad examples:
if (resource.hasRecordType(colorResourceRecordType)) { ColorResourceRecord colorRecord = (ColorResourceRecord) resource; }
While it might have been the case the OSID Provider implementation simply tacked on the color interface to its object implementing Resource, this isn't always the case. The extra request for the OsidRecord allows the OSID Provider greater flexibility in organizing classes and the ability to dynamically fetch OsidRecords not available in the initial request of the Resource.
if (resource.hasRecordType(userPreferenceResourceRecordType)) { java.util.Properties properties = (java.util.Properties) resource.getResourceRecord(userPreferenceResourceRecordType); }
Java's Properties class is not an OsidRecord. The record mechanism provides access to interface specifications, not pojos. The OSIDs require that OsidRecords implement OsidRecords.
Interoperability Considerations
There's bit of rigor to the process of defining records. It conceptually is no different than defining the core OSID Specifications, just in a smaller domain. The smaller the domain, the less interoperability. The broader the domain, the broader interoperability.
OsidRecord Specifications are meant to be published and shared outside the core OSIDs. Generally, one wants to define useful data in a domain that can be used by multiple parties in that domain. Sometimes OsidRecords can be used as a stop-gap measure where interoperability is not a concern or not desired and consequently not widely published.
For OsidRecord that are meant to be published and shared broadly, here are a few recommendations:
Keep the Apples Separated from the Oranges
Don't define a single OsidRecord to deal with all your data needs. Suppose another OSID Provider has the need for the following data in a Resource:
- color
- height
- weight
- number of emergency exits
Our OSID Provider in these examples already defined a color. We lose the opportunity for any interoperability around the color because the color was again defined with other random attributes. By splitting these different kinds of attributes apart, we're that much closer to getting along.
There's also good modeling practice to consider. Is there an object in the real world where all of those attributes are applicable?
Complete the Specification
You may just have the immediate need for a read-only attribute, but it doesn't take much to follow the pattern through the other interfaces for search and create/update. It's your record Type, if you expect others to use it and not re-invent the wheel, then it will all need to be there.
Stick to the OSID Framework
The OSID Specifications define a limited number of OSID Primitives from which the OSIDs themselves are constructed. This is to maintain a strong degree of language neutrality and expand the flexibility of OSID Providers.
While it may seem simpler to define an OsidRecord with methods that return language-specific complex objects, assume all the data has been retrieved and buffered in the implementation, or to wire the interfaces together for easier access, these are the things that tend to get in the way of interoperability and why the OSIDs do what they do in the first place.
Take a Moment to Think About the Problem
Our example OsidRecord uses a string to define a color. It is certainly easy. But it may have some issues that will result in changing the record specification down the road. Much of this inevitable change can be averted with good modeling and biting a bullet or two up front.
First, the color example munges an identifier for a color with the display name for a color. Is it the same color if translated into French? Second, is chartreuse a valid color? Do these colors be managed... by anyone else?
In modeling, what may appear as a data attribute is really an entity. Assuming a Resource can have only one color, our model looks like:
Let's apply a Resource to describe a color and see what happens to our records.
colorResourceRecord | |||
Method | getColorId | ||
---|---|---|---|
Description | Gets the Id of the color of this Resource. | ||
Return | osid.id.Id | the color Id | |
Compliance | mandatory | This method must be implemented. | |
Method | getColor | ||
Description | Gets the color of this Resource. | ||
Return | osid.resource.Resource | the color | |
Errors | OPERATION_FAILED | unable to complete request | |
Compliance | mandatory | This method must be implemented. | |
colorResourceFormRecord | |||
Method | getColorMetadata | ||
Description | Gets the metadata for the color. | ||
Return | osid.Metadata | the metadata | |
Compliance | mandatory | This method must be implemented. | |
Method | setColor | ||
Description | Sets the color. | ||
Parameters | osid.id.Id | colorId | the Id of the color of this resource |
Errors | INVALID_ARGUMENT | colorId is invalid | |
NULL_ARGUMENT | colorId is null | ||
Compliance | mandatory | This method must be implemented. | |
Method | clearColor | ||
Description | Clears the color. | ||
Compliance | mandatory | This method must be implemented. | |
colorResourceQueryRecord | |||
Method | matchColorId | ||
Description | Matches resources of the given color. | ||
Parameters | osid.id.Id | colorId | the color to match |
boolean | match | true for a positive match, false for a negative match | |
Errors | NULL_ARGUMENT | colorId is null | |
Compliance | mandatory | This method must be implemented. | |
Method | clearColorIdTerms | ||
Description | Clears all color Id terms. | ||
Compliance | mandatory | This method must be implemented. | |
Method | supportsColorQuery | ||
Description | Tests if a ColorQuery is available. | ||
Return | boolean | true if a color query is available, false otherwise | |
Compliance | mandatory | This method must be implemented. | |
Method | getColorQuery | ||
Description | Gets the query for a color. Multiple retrievals produce a nested Or term. | ||
Return | osid.resource.ResourceQuery | the resource query | |
Errors | UNIMPLEMENTED | supportsColorQuery() is false | |
Compliance | mandatory | This method must be implemented. | |
Method | matchAnyColor | ||
Description | Matches Resources with any color set. | ||
Parameters | boolean | match | true to match Resources with any color, false to match Resources with no color |
Compliance | mandatory | This method must be implemented. | |
Method | clearColorTerms | ||
Description | Clears all color terms. | ||
Compliance | mandatory | This method must be implemented. | |
colorResourceQueryInspectorRecord | |||
Method | getColorIdTerms | ||
Description | Gets the color Id query terms. | ||
Return | osid.search.terms.IdTerm[] | the color Id query terms | |
Compliance | mandatory | This method must be implemented. | |
Method | getColorTerms | ||
Description | Gets the color terms. | ||
Return | osid.resource.ResourceQueryInspector[] | the resource query terms | |
Compliance | mandatory | This method must be implemented. | |
colorResourceSearchOrderRecord | |||
Method | orderByColor | ||
Description | Orders the results by color. | ||
Parameters | osid.SearchOrderStyle | style | the search order style |
Errors | NULL_ARGUMENT | style is null | |
Compliance | mandatory | This method must be implemented. | |
Method | supportsColorSearchOrder | ||
Description | Tests if a ResourceSearchOrder is available. | ||
Return | boolean | true if a resource search order is available, false otherwise | |
Compliance | mandatory | This method must be implemented. | |
Method | getColorSearchOrder | ||
Description | Gets a resource search order for the color. | ||
Return | osid.resource.ResourceSearchOrder | a resource search order | |
Errors | UNIMPLEMENTED | supportsColorSearchOrder() is false | |
Compliance | mandatory | This method must be implemented. |
Let's say that the color in our hypothetical example describes the exterior color. Now we want to capture the interiod color. An alternative to adding "attributes" is to flesh out the model. In this case, it eliminates the need for the OsidRecord.