Object model
Documents
The main model object handled by Carbon LDP™ is called a Document. A Document begins as a normal JavaScript object containing any number of data attributes (key/value pairs) that you care to define. Typically, a Document represents a data entity of a given type (e.g. Person, Project, Product, Invoice). It can have literal datatype properties (e.g. string, date, number) and pointers that link to other resources. When a normal JavaScript object is saved to Carbon, it receives a URI that uniquely identifies it on a network or the web. That URI can then be used to retrieve the document or to query for specific data attributes within it. Of course, queries can also be used to find data across multiple documents.
URIs as identifiers
Using a numerical value as an ID would be prone to collisions. Using a UUID would solve the collision problem but would make the ID relative to the application (making the ID hard to resolve without knowing where it came from). That’s why Carbon uses Unique Resource Identifiers (or URIs).
URIs are strings that identify resources in a network. Any URL you can think of is also considered a URI, but not all URIs are URLs. The main difference is that a URL can change the resource it is pointing at, while URIs can also belong to a resource forever (in which case they would be URNs (Unique Resource Names).
Basically, URI = URL + URN
URIs follow a scheme. Carbon document’ URIs, follow the http
or https
scheme (depending on the platform’s configuration).
Using URIs as identifiers allow Carbon documents to be unique, resolvable and relative to the network.
Properties
Like any JavaScript object, Carbon documents store data in properties. Properties can be named and contain whatever data values your application needs, but there are reserved properties that you should be aware of:
id
: URI of the document.slug
: Holds the last part of the URI the document is identified with. For example the URI:https://example.com/resource-1/
would have as a slugresource-1
. This property can be useful when used as a relative URI when retrieving a child Document from a parent.types
: An array holding one or more named classes that describe the type of the document (e.g. Person, Project, Product, Invoice).created
: Date when the document was created.modified
: Date when the document was last modified.hasMemberRelation
: Configures the property that will hold the array of Document members.isMemberOfRelation
: Specifies the property that a member Document will acquire that links back to its container Document.
Fragments and named fragments
Documents may also contain nested objects. There are two types of nested objects, fragments
and named fragments
:
var document = { // =================== Document
id: "https://.../projects/project-x/",
name: "Project X",
description: { // -------- Fragment
format: "html",
content: "<div>Some content</div>"
}, // -------- End: Fragment
sow: { // -------- Named Fragment
id: "#sow",
signedOn: new Date( "2016-04-03" ),
clauses: [ // ... ]
} // -------- End: Named Fragment
}; // =================== End: Document
Fragments are identified by an ID, just like documents, but the key difference is that their ID is not a URI. Instead fragments use IDs of the form _:RANDOM-STRING
. These IDs are local to the document, making it impossible to link to fragments from outside of the document.
Named fragments on the other hand, are identified by a URI relative to the document. This means, named fragments ARE referenceable from outside the document. Their URIs have the form DOCUMENT-URI#NAMED-FRAGMENT-SLUG
, but there are times (as shown in the example) where they can be written relative to the document like #NAMED-FRAGMENT-SLUG
.
Object types
Any object stored in Carbon (documents, fragments or named fragments), can be marked with “types”. These types can be thought of as classes or classifications that describe the type of the object.
You can classify an object as any custom type, but be aware that Carbon also automatically assigns certain system types when an object is saved.
The property types
will contain an array of types. To determine whether a document represents an object of a given type, you can use the document’s hasType
method:
// ... imports
let project;
// ... project retrieval
project.types.push( "project", "important-project" );
console.log( project.hasType( "project" ) ); // true
console.log( project.types.length !== 2 ); // true, remember Carbon may add more types to the document
// ... additional imports
import * as PersistedDocument from "carbonldp/PersistedDocument";
let project:Project & PersistedDocument.Class;
// ... project retrieval
project.types.push( "project", "important-project" );
console.log( project.hasType( "project" ) ); // true
console.log( project.types.length !== 2 ); // true, remember Carbon may add more types to the document
var project;
// ... project retrieval
project.types.push( "project", "important-project" );
console.log( project.hasType( "project" ) ); // true
console.log( project.types.length !== 2 ); // true, remember Carbon may add more types to the document
Conclusion
JavaScript objects can be defined with datatype properties, pointers (links) to other resources, fragments (inner-objects), and named fragments (externally referenceable inner-objects). These objects, once saved and/or retrieved using the JavaScript SDK are Document objects. Each Document object is uniquely identified by a URI, which can be used to link to, retrieve, update, or delete the Document. Persisted Documents will always be classified with certain system types, but can also be classified with custom types (e.g. Person, Project, Product, Invoice). Document objects are the main data objects you work with using the JavaScript SDK and the primary means by which you create, read, update, and delete data.