diff --git a/API.md b/API.md
index 3c4ef726c5..b51d9038a6 100644
--- a/API.md
+++ b/API.md
@@ -1,76 +1,150 @@
-# Open MCT API
+# Building Applications With Open MCT
-The Open MCT framework public api can be utilized by building the application
-(`gulp install`) and then copying the file from `dist/main.js` to your
-directory of choice.
+## Scope and purpose of this document
-Open MCT supports AMD, CommonJS, and loading via a script tag; it's easy to use
-in your project. The [`openmct`]{@link module:openmct} module is exported
-via AMD and CommonJS, and is also exposed as `openmct` in the global scope
-if loaded via a script tag.
+This document is intended to serve as a reference for developing an application
+based on Open MCT. It will provide details of the API functions necessary to extend the
+Open MCT platform meet common use cases such as integrating with a telemetry source.
-## Overview
+The best place to start is with the [Open MCT Tutorials](https://github.com/nasa/openmct-tutorial).
+These will walk you through the process of getting up and running with Open MCT,
+as well as addressing some common developer use cases.
-Open MCT's goal is to allow you to browse, create, edit, and visualize all of
-the domain knowledge you need on a daily basis.
+## Building From Source
-To do this, the main building block provided by Open MCT is the _domain object_.
-The temperature sensor on the starboard solar panel,
-an overlay plot comparing the results of all temperature sensor,
-the command dictionary for a spacecraft,
-the individual commands in that dictionary, your "my documents" folder:
+The latest version of Open MCT is available from [our GitHub repository](https://github.com/nasa/openmct).
+If you have `git`, and `node` installed, you can build Open MCT with the commands
+```
+git clone https://github.com/nasa/openmct.git
+cd openmct
+npm install
+```
+
+These commands will fetch the Open MCT source from our GitHub repository, and build
+a minified version that can be included in your application. The output of the
+build process is placed in a `dist` folder under the openmct source directory,
+which can be copied out to another location as needed. The contents of this
+folder will include a minified javascript file named `openmct.js` as well as
+assets such as html, css, and images necessary for the UI.
+
+## Starting an Open MCT application
+
+To start a minimally functional Open MCT application, it is necessary to include
+the Open MCT distributable, enable some basic plugins, and bootstrap the application.
+The tutorials walk through the process of getting Open MCT up and running from scratch,
+but provided below is a minimal HTML template that includes Open MCT, installs
+some basic plugins, and bootstraps the application. It assumes that Open MCT is
+installed under an `openmct` subdirectory, as described in [Building From Source](#building-from-source).
+
+This approach includes openmct using a simple script tag, resulting in a global
+variable named `openmct`. This `openmct` object is used subsequently to make API
+calls.
+
+Open MCT is packaged as a UMD (Universal Module Definition) module, so common
+script loaders are also supported.
+
+```html
+
+
+
+ Open MCT
+
+
+
+
+
+
+```
+
+The Open MCT library included above requires certain assets such as html templates,
+images, and css. If you installed Open MCT from GitHub as described in the section
+on [Building from Source](#building-from-source) then these assets will have been
+downloaded along with the Open MCT javascript library. You can specify the
+location of these assets by calling `openmct.setAssetPath()`. Typically this will
+be the same location as the `openmct.js` library is included from.
+
+There are some plugins bundled with the application that provide UI, persistence,
+and other default configuration which are necessary to be able to do anything with
+the application initially. Any of these plugins can, in principle, be replaced with a custom
+plugin. The included plugins are documented in the [Included Plugins](#included-plugins)
+section.
+
+## Plugins
+
+### Defining and Installing a New Plugin
+
+```javascript
+openmct.install(function install(openmctAPI) {
+ // Do things here
+ // ...
+});
+```
+
+New plugins are installed in Open MCT by calling `openmct.install`, and providing
+a plugin installation function. This function will be invoked on application
+startup with one parameter - the openmct API object. A common approach used in
+the Open MCT codebase is to define a plugin as a function that returns this
+installation function. This allows configuration to be specified when the plugin is included.
+
+eg.
+```javascript
+openmct.install(openmct.plugins.Elasticsearch("http://localhost:8002/openmct"));
+```
+This approach can be seen in all of the [plugins provided with Open MCT](https://github.com/nasa/openmct/blob/master/src/plugins/plugins.js).
+
+## Domain Objects and Identifiers
+
+_Domain Objects_ are the basic entities that represent domain knowledge in Open MCT.
+The temperature sensor on a solar panel, an overlay plot comparing
+the results of all temperature sensors, the command dictionary for a spacecraft,
+the individual commands in that dictionary, the "My Items" folder:
All of these things are domain objects.
-Domain objects have Types, so a specific instrument temperature sensor is a
-"Telemetry Point," and turning on a drill for a certain duration of time is
-an "Activity". Types allow you to form an ontology of knowledge and provide
-an abstraction for grouping, visualizing, and interpreting data.
+A _Domain Object_ is simply a javascript object with some standard attributes.
+An example of a _Domain Object_ is the "My Items" object which is a folder in
+which a user can persist any objects that they create. The My Items object
+looks like this:
-And then we have Views. Views allow you to visualize domain objects. Views can
-apply to specific domain objects; they may also apply to certain types of
-domain objects, or they may apply to everything. Views are simply a method
-of visualizing domain objects.
-
-Regions allow you to specify what views are displayed for specific types of
-domain objects in response to different user actions. For instance, you may
-want to display a different view while editing, or you may want to update the
-toolbar display when objects are selected. Regions allow you to map views to
-specific user actions.
-
-Domain objects can be mutated and persisted, developers can create custom
-actions and apply them to domain objects, and many more things can be done.
-For more information, read on!
-
-## Running Open MCT
-
-Once the [`openmct`](@link module:openmct) module has been loaded, you can
-simply invoke [`start`]{@link module:openmct.MCT#start} to run Open MCT:
-
-
-```
-openmct.start();
+```javascript
+{
+ identifier: {
+ namespace: ""
+ key: "mine"
+ }
+ name:"My Items",
+ type:"folder",
+ location:"ROOT",
+ composition: []
+}
```
-Generally, however, you will want to configure Open MCT by adding plugins
-before starting it. It is important to install plugins and configure Open MCT
-_before_ calling [`start`]{@link module:openmct.MCT#start}; Open MCT is not
-designed to be reconfigured once started.
+### Object Attributes
-## Configuring Open MCT
+The main attributes to note are the `identifier`, and `type` attributes.
+* `identifier`: A composite key that provides a universally unique identifier for
+this object. The `namespace` and `key` are used to identify the object. The `key`
+must be unique within the namespace.
+* `type`: All objects in Open MCT have a type. Types allow you to form an
+ontology of knowledge and provide an abstraction for grouping, visualizing, and
+interpreting data. Details on how to define a new object type are provided below.
-The [`openmct`]{@link module:openmct} module (more specifically, the
-[`MCT`]{@link module:openmct.MCT} class, of which `openmct` is an instance)
-exposes a variety of methods to allow the application to be configured,
-extended, and customized before running.
+Open MCT uses a number of builtin types. Typically you are going to want to
+define your own if extending Open MCT.
-Short examples follow; see the linked documentation for further details.
+### Domain Object Types
-### Adding Domain Object Types
+Custom types may be registered via the `addType` function on the opencmt Type
+registry.
-Custom types may be registered via
-[`openmct.types`]{@link module:openmct.MCT#types}:
-
-```
+eg.
+```javascript
openmct.types.addType('my-type', {
label: "My Type",
description: "This is a type that I added!",
@@ -78,66 +152,98 @@ openmct.types.addType('my-type', {
});
```
-### Adding Views
+The `addType` function accepts two arguments:
+* A `string` key identifying the type. This key is used when specifying a type
+for an object.
+* An object type specification. An object type definition supports the following
+attributes
+ * `label`: a `string` naming this object type
+ * `description`: a `string` specifying a longer-form description of this type
+ * `initialize`: a `function` which initializes the model for new domain objects
+ of this type. This can be used for setting default values on an object when
+ it is instantiated.
+ * `creatable`: A `boolean` indicating whether users should be allowed to create
+ this type (default: `false`). This will determine whether the type appears
+ in the `Create` menu.
+ * `cssClass`: A `string` specifying a CSS class to apply to each representation
+ of this object. This is used for specifying an icon to appear next to each
+ object of this type.
-Custom views may be registered based on the region in the application
-where they should appear:
+The [Open MCT Tutorials](https://github.com/openmct/openmct-tutorial) provide a
+step-by-step examples of writing code for Open MCT that includes a [section on
+defining a new object type](https://github.com/nasa/openmct-tutorial#step-3---providing-objects).
-* [`openmct.mainViews`]{@link module:openmct.MCT#mainViews} is a registry
- of views of domain objects which should appear in the main viewing area.
-* [`openmct.inspectors`]{@link module:openmct.MCT#inspectors} is a registry
- of views of domain objects and/or active selections, which should appear in
- the Inspector.
-* [`openmct.toolbars`]{@link module:openmct.MCT#toolbars} is a registry
- of views of domain objects and/or active selections, which should appear in
- the toolbar area while editing.
-* [`openmct.indicators`]{@link module:openmct.MCT#inspectors} is a registry
- of views which should appear in the status area of the application.
+## Root Objects
-Example:
+In many cases, you'd like a certain object (or a certain hierarchy of objects)
+to be accessible from the top level of the application (the tree on the left-hand
+side of Open MCT.) For example, it is typical to expose a telemetry dictionary
+as a hierarchy of telemetry-providing domain objects in this fashion.
-```
-openmct.mainViews.addProvider({
- canView: function (domainObject) {
- return domainObject.type === 'my-type';
- },
- view: function (domainObject) {
- return new MyView(domainObject);
- }
-});
+To do so, use the `addRoot` method of the object API.
+
+eg.
+```javascript
+openmct.objects.addRoot({
+ namespace: "my-namespace",
+ key: "my-key"
+ });
```
-### Adding a Root-level Object
-
-In many cases, you'd like a certain object (or a certain hierarchy of
-objects) to be accessible from the top level of the application (the
-tree on the left-hand side of Open MCT.) It is typical to expose a telemetry
-dictionary as a hierarchy of telemetry-providing domain objects in this
-fashion.
-
-To do so, use the [`addRoot`]{@link module:openmct.ObjectAPI#addRoot} method
-of the [object API]{@link module:openmct.ObjectAPI}:
-
-```
-openmct.objects.addRoot({ key: "my-key", namespace: "my-namespace" });
-```
+The `addRoot` function takes a single [object identifier](#domain-objects-and-identifiers)
+as an argument.
Root objects are loaded just like any other objects, i.e. via an object
provider.
-### Adding Composition Providers
+## Object Providers
-The "composition" of a domain object is the list of objects it contains,
-as shown (for example) in the tree for browsing. Open MCT provides a
+An Object Provider is used to build _Domain Objects_, typically retrieved from
+some source such as a persistence store or telemetry dictionary. In order to
+integrate telemetry from a new source an object provider will need to be created
+that can build objects representing telemetry points exposed by the telemetry
+source. The API call to define a new object provider is fairly straightforward.
+Here's a very simple example:
+
+```javascript
+openmct.objects.addProvider('example.namespace', {
+ get: function (identifier) {
+ return Promise.resolve({
+ identifier: identifier,
+ name: 'Example Object',
+ type: 'example-object-type'
+ });
+ }
+});
+```
+The `addProvider` function takes two arguments:
+
+* `namespace`: A `string` representing the namespace that this object provider
+will provide objects for.
+* `provider`: An `object` with a single function, `get`. This function accepts an
+[Identifier](#domain-objects-and-identifiers) for the object to be provided.
+It is expected that the `get` function will return a
+[Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)
+that resolves with the object being requested.
+
+In future, object providers will support other methods to enable other operations
+with persistence stores, such as creating, updating, and deleting objects.
+
+## Composition Providers
+
+The _composition_ of a domain object is the list of objects it contains, as shown
+(for example) in the tree for browsing. Open MCT provides a
[default solution](#default-composition-provider) for composition, but there
may be cases where you want to provide the composition of a certain object
(or type of object) dynamically.
-For instance, you may want to populate a hierarchy under a custom root-level
-object based on the contents of a telemetry dictionary.
-To do this, you can add a new CompositionProvider:
+### Adding Composition Providers
-```
+You may want to populate a hierarchy under a custom root-level object based on
+the contents of a telemetry dictionary. To do this, you can add a new
+Composition Provider:
+
+```javascript
openmct.composition.addProvider({
appliesTo: function (domainObject) {
return domainObject.type === 'my-type';
@@ -147,20 +253,27 @@ openmct.composition.addProvider({
}
});
```
+The `addProvider` function accepts a Composition Provider object as its sole
+argument. A Composition Provider is a javascript object exposing two functions:
+* `appliesTo`: A `function` that accepts a `domainObject` argument, and returns
+a `boolean` value indicating whether this composition provider applies to the
+given object.
+* `load`: A `function` that accepts a `domainObject` as an argument, and returns
+a `Promise` that resolves with an array of [Identifier](#domain-objects-and-identifiers).
+These identifiers will be used to fetch Domain Objects from an [Object Provider](#object-provider)
-#### Default Composition Provider
+### Default Composition Provider
-The default composition provider applies to any domain object with
-a `composition` property. The value of `composition` should be an
-array of identifiers, e.g.:
+The default composition provider applies to any domain object with a `composition`
+property. The value of `composition` should be an array of identifiers, e.g.:
-```js
+```javascript
var domainObject = {
name: "My Object",
type: 'folder',
composition: [
{
- key: '412229c3-922c-444b-8624-736d85516247',
+ id: '412229c3-922c-444b-8624-736d85516247',
namespace: 'foo'
},
{
@@ -171,169 +284,146 @@ var domainObject = {
};
```
-### Adding Telemetry Providers
+## Telemetry Providers
-When connecting to a new telemetry source, you will want to register a new
-[telemetry provider]{@link module:openmct.TelemetryAPI~TelemetryProvider}
-with the [telemetry API]{@link module:openmct.TelemetryAPI#addProvider}:
+When connecting to a new telemetry source, you will need to register a new
+_Telemetry Provider_. A _Telemetry Provider_ retrieves telemetry data from some telemetry
+source, and exposes them in a way that can be used by Open MCT. A telemetry
+provider typically can support a one off __request__ for a batch of telemetry data,
+or it can provide the ability to __subscribe__ to receive new telemetry data when
+it becomes available, or both.
-```
+```javascript
openmct.telemetry.addProvider({
- canProvideTelemetry: function (domainObject) {
- return domainObject.type === 'my-type';
+ supportsRequest: function (domainObject) {
+ //...
},
- properties: function (domainObject) {
- return [
- { key: 'value', name: "Temperature", units: "degC" },
- { key: 'time', name: "UTC" }
- ];
+ supportsSubscribe: function (domainObject) {
+ //...
},
- request: function (domainObject, options) {
- var telemetryId = domainObject.myTelemetryId;
- return myAdapter.request(telemetryId, options.start, options.end);
+ request: function (domainObject, options) {
+ //...
},
- subscribe: function (domainObject, callback) {
- var telemetryId = domainObject.myTelemetryId;
- myAdapter.subscribe(telemetryId, callback);
- return myAdapter.unsubscribe.bind(myAdapter, telemetryId, callback);
+ subscribe: function (domainObject, callback, options) {
+ //...
}
-});
+})
```
+A telemetry provider is an object with the following functions defined:
+
+* `supportsRequest`: An __optional__ `function` that accepts a
+[Domain Object](#domain-objects-and-identifiers) and returns a `boolean` value
+indicating whether or not this provider supports telemetry requests for the
+given object. If this returns `true` then a `request` function must be defined.
+* `supportsSubscribe`: An __optional__ `function` that accepts a
+[Domain Object](#domain-objects-and-identifiers) and returns a `boolean` value
+indicating whether or not this provider supports telemetry subscriptions. If this
+returns `true` then a `subscribe` function must also be defined. As with `request`,
+the return value will typically be conditional, and based on attributes of
+`domainObject` such as its identifier.
+* `request`: A `function` that returns a `Promise` that will resolve with an `Array`
+of telemetry in a single query. This function accepts as arguments a
+[Domain Object](#domain-objects-and-identifiers) and an object containing some
+[request options](#telemetry-requests).
+* `subscribe`: A `function` that accepts a [Domain Object](#domain-objects-and-identifiers),
+a callback `function`, and a [telemetry request](#telemetry-requests). The
+callback is invoked whenever telemetry is available, and
+
+
The implementations for `request` and `subscribe` can vary depending on the
nature of the endpoint which will provide telemetry. In the example above,
-it is assumed that `myAdapter` contains the specific implementations
-(HTTP requests, WebSocket connections, etc.) associated with some telemetry
+it is assumed that `myAdapter` contains the implementation details
+(such as HTTP requests, WebSocket connections, etc.) associated with some telemetry
source.
-## Using Open MCT
+For a step-by-step guide to building a telemetry adapter, please see the
+[Open MCT Tutorials](https://github.com/larkin/openmct-tutorial).
-When implementing new features, it is useful and sometimes necessary to
-utilize functionality exposed by Open MCT.
-
-### Retrieving Composition
-
-To limit which objects are loaded at any given time, the composition of
-a domain object must be requested asynchronously:
-
-```
-openmct.composition(myObject).load().then(function (childObjects) {
- childObjects.forEach(doSomething);
-});
+### Telemetry Requests
+Telemetry requests support time bounded queries. A call to a _Telemetry Provider_'s
+`request` function will include an `options` argument. These are simply javascript
+objects with attributes for the request parameters. An example of a telemetry
+request object with a start and end time is included below:
+```javascript
+{
+ start: 1487981997240,
+ end: 1487982897240
+}
```
-### Support Common Gestures
+### Telemetry Data
-Custom views may also want to support common gestures using the
-[gesture API]{@link module:openmct.GestureAPI}. For instance, to make
-a view (or part of a view) selectable:
+Telemetry data is provided to Open MCT by _[Telemetry Providers](#telemetry-providers)_
+in the form of javascript objects. A collection of telemetry values (for example,
+retrieved in response to a `request`) is represented by an `Array` of javascript
+objects. These telemetry javascript objects are simply key value pairs.
-```
-openmct.gestures.selectable(myHtmlElement, myDomainObject);
+Typically a telemetry datum will have some timestamp associated with it. This
+time stamp should have a key that corresponds to some time system supported by
+Open MCT. If the `UTCTimeSystem` plugin is installed, then the key `utc` can be used.
+
+An example of a telemetry provider request function that returns a collection of
+mock telemtry data is below:
+
+```javascript
+openmct.telemetry.addProvider({
+ supportsRequest: function (domainObject) {
+ return true
+ },
+ request: function (domainObject, options) {
+ return Promise.resolve([
+ {
+ 'utc': Date.now() - 2000,
+ 'value': 1,
+ },
+ {
+ 'utc': Date.now() - 1000,
+ 'value': 2,
+ },
+ {
+ 'utc': Date.now(),
+ 'value': 3,
+ }
+ ]);
+ }
+})
```
-### Working with Domain Objects
-
-The [object API]{@link module:openmct.ObjectAPI} provides useful methods
-for working with domain objects.
-
-To make changes to a domain object, use the
-[`mutate`]{@link module:openmct.ObjectAPI#mutate} method:
-
-```
-openmct.objects.mutate(myDomainObject, "name", "New name!");
-```
-
-Making modifications in this fashion allows other usages of the domain
-object to remain up to date using the
-[`observe`]{@link module:openmct.ObjectAPI#observe} method:
-
-```
-openmct.objects.observe(myDomainObject, "name", function (newName) {
- myLabel.textContent = newName;
-});
-```
-
-### Using Telemetry
-
-Very often in Open MCT, you wish to work with telemetry data (for instance,
-to display it in a custom visualization.)
-
-
-### Synchronizing with the Time Conductor
-
-Views which wish to remain synchronized with the state of Open MCT's
-time conductor should utilize
-[`openmct.conductor`]{@link module:openmct.TimeConductor}:
-
-```
-openmct.conductor.on('bounds', function (newBounds) {
- requestTelemetry(newBounds.start, newBounds.end).then(displayTelemetry);
-});
-```
-
-## Plugins
-
-While you can register new features with Open MCT directly, it is generally
-more useful to package these as a plugin. A plugin is a function that takes
-[`openmct`]{@link module:openmct} as an argument, and performs configuration
-upon `openmct` when invoked.
-
-### Installing Plugins
-
-To install plugins, use the [`install`]{@link module:openmct.MCT#install}
-method:
-
-```
-openmct.install(myPlugin);
-```
-
-The plugin will be invoked to configure Open MCT before it is started.
-
-### Included Plugins
+## Included Plugins
Open MCT is packaged along with a few general-purpose plugins:
* `openmct.plugins.CouchDB` is an adapter for using CouchDB for persistence
of user-created objects. This is a constructor that takes the URL for the
CouchDB database as a parameter, e.g.
- `openmct.install(new openmct.plugins.CouchDB('http://localhost:5984/openmct'))`
+```javascript
+openmct.install(openmct.plugins.CouchDB('http://localhost:5984/openmct'))
+```
* `openmct.plugins.Elasticsearch` is an adapter for using Elasticsearch for
persistence of user-created objects. This is a
constructor that takes the URL for the Elasticsearch instance as a
- parameter, e.g.
- `openmct.install(new openmct.plugins.CouchDB('http://localhost:9200'))`.
- Domain objects will be indexed at `/mct/domain_object`.
-* `openmct.plugins.espresso` and `openmct.plugins.snow` are two different
+ parameter. eg.
+```javascript
+openmct.install(openmct.plugins.CouchDB('http://localhost:9200'))
+```
+* `openmct.plugins.Espresso` and `openmct.plugins.Snow` are two different
themes (dark and light) available for Open MCT. Note that at least one
of these themes must be installed for Open MCT to appear correctly.
-* `openmct.plugins.localStorage` provides persistence of user-created
+* `openmct.plugins.LocalStorage` provides persistence of user-created
objects in browser-local storage. This is particularly useful in
development environments.
-* `openmct.plugins.myItems` adds a top-level folder named "My Items"
+* `openmct.plugins.MyItems` adds a top-level folder named "My Items"
when the application is first started, providing a place for a
user to store created items.
-* `openmct.plugins.utcTimeSystem` provides support for using the time
- conductor with UTC time.
+* `openmct.plugins.UTCTimeSystem` provides a default time system for Open MCT.
Generally, you will want to either install these plugins, or install
different plugins that provide persistence and an initial folder
-hierarchy. Installation is as described [above](#installing-plugins):
+hierarchy.
+eg.
+```javascript
+openmct.install(openmct.plugins.LocalStorage());
+openmct.install(openmct.plugins.MyItems());
```
-openmct.install(openmct.plugins.localStorage);
-openmct.install(openmct.plugins.myItems);
-```
-
-### Writing Plugins
-
-Plugins configure Open MCT, and should utilize the
-[`openmct`]{@link module:openmct} module to do so, as summarized above in
-"Configuring Open MCT" and "Using Open MCT" above.
-
-### Distributing Plugins
-
-Hosting or downloading plugins is outside of the scope of this documentation.
-We recommend distributing plugins as UMD modules which export a single
-function.
-
diff --git a/src/api/types/TypeRegistry.js b/src/api/types/TypeRegistry.js
index 77c7e454c4..ee5a286f00 100644
--- a/src/api/types/TypeRegistry.js
+++ b/src/api/types/TypeRegistry.js
@@ -44,7 +44,7 @@ define(['./Type'], function (Type) {
}
/**
- * Register a new type of view.
+ * Register a new object type.
*
* @param {string} typeKey a string identifier for this type
* @param {module:openmct.Type} type the type to add