Adaptive Framework 0.9.0

Adaptive Objects

Throughout these guides, we will refer to objects, many of which were initially created in JSON format before being generated into native C structures and stored in physical memory. For convenience, we will often represent objects in the guides in JSON format. To learn more about the JSON format, please visit http://www.json.org.

Adaptive Object Model

Adaptive Objects are similar to many Object paradigms you may have been introduced to in a programming or data structure lessons. They contain data in a structured way, just as key/values, dictionaries or hashes encapsulate data in other popular languages. With Adaptive Objects, the object that contains data is described by another object, called its Object Type. The keys and values on the Adaptive Object are referred to as Adaptive Properties and the definitions of those properties, which are contained within the Object Type definition, are called Property Types. These definitions provide us with useful metadata that can be used for data validation, user interface representation, authorization controls, and even data transformation and generation. The following diagram illustrates these relationships, and is commonly referred to as the Type Square Pattern:

Type Square Pattern
Type Square Pattern

An Adaptive Object may have one or more Adaptive Properties. Likewise, an Object Type may have one or more Property Types. Moreover, an Object Type describes one or more Adaptive Object instances, just as an Adaptive Property Type may describe one or more Adaptive Properties. Let's examine these objects, in detail, in order to get a better sense of how they are related.

Let's define an Adaptive Object of interest with something that is familiar. As a Person, I have some properties that describe me. For example, I have a First Name, a Last Name and an Age.

{
    "First Name": "Kevin",
    "Last Name": "Smith",
    "Age": 40
}

Other people also have names and ages. Therefore, we can describe a Person using an Object Type. This Object Type contains Property Types, declared under a special name, propertyTypes, for "First Name", "Last Name" and "Age". In this example, you will find "First Name", "Last Name" and "Age" all have Property Type values of structured objects that contain information about them. "First Name" and "Last Name" have a dataType of string and Age is described as an integer. Both have additional description properties that provide additional:

{
    "propertyTypes": {
        "First Name": {
            "dataType": "string",
            "description" "This is a person's first name."
        },
        "Last Name": {
            "dataType": "string",
            "description": "This is a person's last name."
        },
        "Age": {
            "dataType": "integer",
            "description": "This is a person's age, in years."
        }
    }
}

This very simple example also demonstrates an aspect of Adaptive Objects that may not seem obvious on the surface. "Object Type" Person is also an Adaptive Object, and "propertyTypes" here is also an Adaptive Property, whose value is an object containing "First Name", "Last Name" and "Age". It's only when we establish the Object Type relationship between these two that we apply semantic meaning to this object. In fact, the Person Object Type in this example also has an Object Type, called _AdaptiveObjectType_, which describes how an Adaptive Object Type is structured. Likewise, the object type _AdaptivePropertyType_, is used to describe how an Adaptive Property Type is structured. These two special objects are defined by Core as compiled object definitions. We can change the Person Object Type, because it's an object not defined to core, but we cannot change "_AdaptiveObjectType_" or "_AdaptivePropertyType_" without recompiling Adaptive Framework.

Object Types and Property Types

In the previous section, we demonstrated how an Object Type and its Property Types can describe an instance of an Object. We also introduced the idea that Object Types and Property Types are also objects, themselves, described by "_AdaptiveObjectType_" and "_AdaptivePropertyType_" and defined as compiled-in objects to Adaptive Framework Core. Let's first look at what makes an Adaptive Property Type, using the example from the previous section. The Adaptive Property "First Name" had a Property Type definition that included a property called "dataType". The dataType property is an important one that we will get into more details later. Here is a more complete list of properties that define a Property Type:

PropertyDescription
additionalConstraintsAdditional constraint for the value.
allowQueryIf false, this value can NEVER be queried. If true, this value can be queried if allowed by authorization policy.
allowWriteIf true, the value can be written if allowed by authorization policy as long as allowChange for the instance is also true. If false, the value can only be written if required is true when adding a new object.
allowedValuesThis is a list of the allowed values for this adaptive value. The dataType and dataTypeParameter of these values is the same as for the adaptive value itself.
briefThis is a predicate for this value, with the first letter capitalized and without a trailing period.
collectionURIsThis is the URIs of the collections that this value is a part of and preferably a URIs that can be used to locate an object with objects type _AdaptiveCollection_ that describes the collections. If a collection is used outside of the local instance, it should be a full URI. The URI can also be a local path of the collection object or just the collection's objectId if it resides in the in the same adaptor.
contextTypeFor data types that are evaluated (evaluate property true), this is the context type used for the evaluation.
dataTypeData type of this value.
dataTypeParameterSee the data type's dataTypeParameterType property to determine how to interpret this.
dataTypeParameterFormattedThis is the same as dataTypeParameter with possible comments and whitespace. This is especially useful for data type function to document its signature. If this property is not present, dataTypeParameter can be used in its place.
defaultValueThis is the default value. The dataType and dataTypeParameter properties apply to this value. If needed, this value will be normalized.
descriptionThe description of this value.
hintsHints that can optionally be used by UI to render this value.
labelLabel used to identify this value.
maxLengthThis is maximum length of the to_string() for this value. If not specified, there is no maximum length.
maxNormalLengthThis is maximum normal length of the to_string() for this value. If not specified, maxLength is used.
maxValueThis is the maximum for this value. If not specified, there is no maximum value. The dataType and dataTypeParameter of this value is the same as for the value.
minLengthThis is minimum length of the to_string() for this value. If not specified, there is no minimum length.
minValueThis is the minimum for this. If not specified, there is no minimum value. The dataType and dataTypeParameter of this value is the same as for the value.
originURIThe origin URI of this value meta. Descendant object types should be used for any deviations. This URI may be different from the URI within this instance of Adaptive Framework.
possibleValuesPossible values of this value. This can be the typed value or the string value.
referenceURIURI of more reference information about this value meta.
requiredIndicates that value is required.
runtimeThis is only valid for runtime object types. These are objects that are accessed with adaptorId afw. See afw_runtime.h for more information.
skeletonThis is a skeleton example that can optionally be used by an application as an initial value. For example, if this is a new data type hybrid value, this can be the text used to prime the edit window with sample Adaptive Script code including comments.
tagsThis is a list of keywords and terms associated with values with the meta. An instance of _AdaptiveTag_ can be used to define and document the purpose of a tag. Adaptive Framework reserves the definition of all tags that begin with "_Adaptive".
testDataParameterThis contains additional information about values with this meta that is used to produce test data.
uniqueValue of property must be unique within object type.
valueInfIdThis is a runtime property that is the implementation id of the value interface.

Object Meta

We've now covered Object Types and Property Types and how useful they are in describing an object or collection of objects by extracting their "metadata" and storing it in a common place. In addition to Object Types and Property Types, all objects contain some additional metadata that is useful for Adaptive Framework Core, Adaptors, and even clients. As you may have already guessed, these too are documented and stored in a special Object Type called _AdaptiveMeta_, which looks like the following:

PropertyDescription
allowChangeIf false this object is read only. If true, the object can be changed unless denied by authorization policy or by the adaptor.
allowDeleteIf false this object can not be deleted. If true, the object can be deleted unless denied by authorization policy or by the adaptor.
ancestorPathsThis is all of the associated object's ancestor paths.
descriptionThe optional description of the object.
errorsObject errors.
hasErrorsIndicates that at least one errors property exists in the meta.
objectIdThis the id that uniquely defines the associated object when combined with its adaptor id and object type id within an Adaptive Framework environment. The objectId should be considered opaque unless the associated adaptor or mapping specifies otherwise.
objectTypeThis the id of the associated object's object type within the object's adaptor.
objectTypesThis is a object with a property with a name of the objectType for each _AdaptiveObjectType_ used by this object and all of its embedded objects.
parentPathsThis is the associated object's direct parent paths.
pathThis is the associated object's path within an Adaptive Framework environment. The path is of the form "/adaptorId/objectType/objectId".
propertyTypesThis is additional meta information that overrides and supplements property type information for specific associated object's properties. The property name of properties in this object corresponds to properties with the same name in the associated object.
reconcilableThis strings represents a stateful token, used by the reconcile_object() method, to perform a reconcile request on an object that has been obtained in reconcilable mode.
resolvedParentPathsThis is the associated object's direct parent paths before they were resolved by object option composite.

Absolute Object Paths

Object Paths

Every Adaptive Object in Adaptive Framework is uniquely identified by an Object Path of the form:

/<adaptorId>/<objectTypeId>/<objectId>

An objectId is the unique object identifier of the entity, optionally followed by a slash-separated representation of embedded properties.

/<adaptorId</<objectType</objectId
/<adaptorId</<objectType</objectId/propertyName
/<adaptorId</<objectType</objectId/propertyNameA/propertyNameB

If the property value is a list, a property name can be followed with a zero based integer index enclosed in square brackets ([n]).

/<adaptorId>/<objectTypeId>/<objectId>/<propertyNameA>[<index>]
/<adaptorId>/<objectTypeId>/<objectId>/<propertyNameA>[<index>]/<property name>
/<adaptorId>/<objectTypeId>/<objectId>/<propertyNameA>/<propertyNameB>[<index>]
/<adaptorId>/<objectTypeId>/<objectId>/<propertyNameA>[<index>]/<propertyNameB>[<index>]

Relative Adaptive Object Path

An Object URI can contain a path as defined above, a full URI with scheme, or a relative path. If a path is relative, it must be resolved relative to a supplied path.

If a relative path begins with a /, its structure is the same as an absolute path with * used in place of <adaptorId>, <objectTypeId>, and each shashed part of <objectId> to use the corresponding value from the supplied path. The <objectId> can also be ** to indicate that the entire <objectId> including all slash-separated properties should be used.

If a relative path does not begin with a /, the <adaptorId> and <objectTypeId> from the supplied path will be used and the relative path will be used as the /<objectId>. The character sequence /* can be used as a corresponding part from the supplied path's /<objectId>.

The following are some examples of relative references using the given path: /adaptorId/objectTypeId/objectId/prop1/prop2:

Relative PathResolved Path
objectId2/adaptorId/objectTypeId/objectId2
objectId2/prop4/adaptorId/objectTypeId/objectId2/prop4
/*/objectTypeId2/objectId3/prop5/adaptorId/objectTypeId2/objectId3/prop5
/*/objectTypeId2/*/prop5/adaptorId/objectTypeId2/objectId/prop5
*/prop6/adaptorId/objectTypeId/objectId/prop6
*/*/prop7/adaptorId/objectTypeId/objectId/prop1/prop7
/adaptorId2/*/**/adaptorId2/objectTypeId/objectId/prop1/prop2
/*/*/**/adaptorId/objectTypeId/objectId/prop1/prop2
/*/*/*/adaptorId/objectTypeId/objectId

Embedded Objects

Some Adaptive Objects may have properties that also contain objects. We call these objects Embedded Objects. The following object illustrates an example of an Embedded Object, referenced by the Embedding Property address:

{
    "name": "John Doe",
    "address": {
        "street": "123 Main St.",
        "city": "Anytown",
        "state": "CA",
        "zip": "12345"
    }
}

Inheritance

Adaptive Objects also allow for inheritance, so that Adaptive Objects can borrow properties from other Adaptive Objects. This is done through a special "meta" property called parentPaths:

{
    "_meta_": {
        "parentPaths": [
            "/registry/_AdaptiveObjectType_/Person"
        ]
    },
    "employeeId": "12345",
    "officeAddress": {
        "street": "123 Main St.",
        "city": "Anytown",
        "state": "CA",
        "zip": "12345"
    }
}

When observing an Adaptive Object that contains a parent path, the Object Option composite can be specified to resolve the parent and include their properties in the returned object. The following is an example of the same object with the composite option specified:

{    
    "first": "John",
    "last": "Doe",
    "age": 42,
    "employeeId": "12345",
    "officeAddress": {
        "street": "123 Main St.",
        "city": "Anytown",
        "state": "CA",
        "zip": "12345"
    }
}

Object Options

Adaptive Objects can be provided with Object Options that influence how an object should be displayed, including what metadata should be provided, or how Adaptive Property values should be interpreted or represented. The options that one uses is up to the application or client that is consuming or providing the objects. For example, a UI may require a lot of metadata to understand how to render properties on a screen, while a programmatic parser may request property values to be encoded in a way that's convenient for the client. Below is a table of the object options that are available.

PropertyDescription
checkRequiredIndicates that object should be checked for missing required properties. This option implies the normalize option.
compositeIndicates that both direct and embedded inheritance should be performed.
debugThis will cause the errors in object meta to include additional debug information. If not specified, only the message will be included.
includeDefaultValuesThis indicates that default property values should be included. This option implies the normalize option.
includeDescendentObjectTypesThis only applies to retrieve objects requests and indicates that objects with the supplied object type along with objects with any of its descendent object types should be included in the search.
inheritedFromIndicates that the inheritedFrom property in meta propertyTypes.<propertyName>, where <propertyName> is the associated property name, should be set. This option is ignored unless composite option is also set.
integersAsStringThis overrides the largeIntegersAsString option. If neither the integersAsString or large_integer_as_string is specified, integers will remain integers. If this option is specified, all data type integer values will be converted to the string data type.\n\nThis options is useful if a content type is used that represents integers as double (floating point) values.
largeIntegersAsStringThis option is overridden by the integersAsString option.\n\nIf this option is specified, all integers that have a magnitude that exceeds plus or minus 9007199254740991 (2^53-1) will be converted to the string data type.\n\nThis options is useful if integers of a content type are interpreted as double (floating point) values, but integers are normally small enough to be represented properly. An example is Javascript's use of JSON.
metaFullThis indicates that all meta, including properties that are not part of delta from object type, are to be included. This overrides metaLimited.
metaLimitedIndicates that only requested and essential (parentPaths) meta is returned.
normalizeIndicates that each object's object type should be processed, assigned each embedded object's object type, converting any properties to their correct data type, plus computing values when needed. If there is dataType or dataTypeParameter information available during normalization that is not in the associated _AdaptiveObjectType_, it will be added at the appropriate place in the object's meta.\n\nUse the includeDefaultValues option to include default values.
objectIdIndicates that objectId property should be included in the meta for entity objects.
objectTypeIndicates that objectType property should be included in the meta for entity and embedded objects, if assigned.
objectTypesIndicates that the objectTypes property should be added to the meta of the entity containing a property of each object type used by the entity and all of its embedded objects. This option implies normalize.
pathIndicates that meta path should be included for entity objects.
pathEmbeddedIndicates that meta path should be included for embedded objects.
reconcilableIndicates that meta reconcilable should be included in entity's meta. If this is specified on a get_object or retrieve_objects request and a retrieved object is changed, calling reconcile_object() with the changed object will use the information in meta reconcilable to produce a modify request for only the changes. The reconcilable option assumes the path option and possibly other options as needed.
resolvedParentPathsIndicates that meta resolvedParentPaths should be included with a list of parent paths that have been resolved by the composite option.
typedValues*** EXPERIMENTAL *** This option indicates that a value's type information (valueType, dataType, and objectType) should be included with each value. See the content type to determines how this is represented.
whitespaceThis option can be optionally supported by a content type implementation. In the case of JSON, this indicates that newline, space, and tab characters should be included to make the output more readable.