|Table of Contents|
This page describes what subobjects in SMW are and how they are handled internally. It is intended for developers, not for users.
TODO: Link to relevant user documentation here. TODO: Add links to other documentation pages below.
What are subobjects?
The data that SMW stores is normally data about pages in a wiki. Users can assign property values to a page in various ways by writing suitable things into the wikitext of that page. However, some complex forms of data cannot be captured by single property values. For example, if one wanted to store a street address, you might want to give multiple fields separately (street, postcode, country, etc.). If a page can have multiple addresses, then it would not work to store this with many properties (has street, has postcode, has country, etc.), because one would not know which values belong together (e.g., with two streets and two countries, there are four combinations already). To solve this, one would have to create a new page for each address, assign the relevant property values to this page, and use this page as an address value. This is often not a good solution, since one does not want to have pages for every possible address. To solve this, SMW supports the creation of subobjects, which behave like pages as far as property value assignments are concerned, but which do not have a page in the wiki. So, in a nutshell:
"Subobjects are like wikipages, but without the page."
How are subobjects represented in SMW?
Every subobject belongs to exactly one wikipage. Moreover, every subobject has a name, that is, a string that will help to identify it everywhere. In particular, subobjects have a clear identity, that is, they are not defined by their data, but really have an independent existence, just like pages. Internally, SMW represents subobjects just like wikipages, using objects of type SMWDIWikiPage. In fact, every SMWDIWikiPage has a subobject name; for real pages this field is simply the empty string "".
The name of a subobject can be any string, but it should only contain ASCII characters (Latin letters, numerals, basic punctuation). Moreover, the length of the subobject name should be at most 256 characters (same as page titles in MediaWiki). If the name of the subobject starts with "_", SMW will assume that it is not human-readable. Most user interfaces will hide the name in this case. Otherwise, the name is assumed to be human-readable and will be shown in all interfaces. This does not affect data handling or storage; it is just a matter of presentation.
Where do subobjects occur naturally in SMW?
Subobjects can be created and addressed in various ways by users of SMW:
- The parser function #subobject is the most general way to create arbitrary subobjects with data.
- Properties of datatype Record use subobjects to store their "values" (which are really sets of property-value assignments to a subobject with an internal name)
- Users can use subobjects as values for properties of type Wikipage by writing the subobject name behind the page name, separated with a #. Subobject names are thus related to fragment (section) identifiers on a page.
Extensions can introduce more functions that create subobjects. In general, programmers must be prepared to encounter subobjects in any place where a wikipage could occur.
Querying and viewing subobjects
There is no semantic query (#ask) that returns all subobjects of a specific page. The #subobject parser function uses a special property _SOBJ to link from the wikipage to the created subobject, that can be used to retrieve subobjects that were created in this way. But this property is not generally used for subobjects. As explained above, subobjects are really a special kind of "wikipage" object in SMW; they do not become subobjects due to the use in any property. In particular, if users use subobjects as property values directly, then a subobject might not be assigned as a property value to its own page at all, but only to other pages. This also means that there is currently no way for developers to get all subobjects of a page without code that depends on the internals of a particular storage backend.
All internal functions that can query data about wikipages can also be given subobjects. However, some user interfaces and Web APIs are not able to process subobject identifiers in the input, so one may not always be able to use them for getting the data. However, Special:Browse works and can be very helpful for inspecting subobject data that is currently stored.
DIContainer: handling subobject data during parsing and querying
There is currently a special "virtual" DI type SMWDIContainer for handling semantic data, especially for subobjects. Its main task is to store the data that is assigned to subobjects during parsing. Since only one SMWSemanticData object is used to hold all semantic data during parsing, there is no way to give additional data for subobjects. This is currently solved by allowing container property values that contain a subobject (the actual value) plus additional data (the property-value assingments for this subobject). Code that wants to add data about a subobject during parsing should do so by creating a container DI and using it as the value of some property of type Wikipage (_wpg). An example is found in the file includes/parserhooks/SMW_Subobject.php, which implements #subobject.
Note: This design is under discussion. The use of DIContainer might change. (14 Aug 2012)
Using subobject class in SMW 1.9
// Subobject instantiation $subobject = Subobject::Factory( $subject, $subobjectName ); // Add property and values $subobject->addPropertyValue( $property, $value ); ... // Add subobject property/container to the existing semantic data pool ...(instanceof SMWSemanticData)->addPropertyObjectValue( $subobject->getSubobjectProperty(), $subobject->getSubobjectContainer() );