Dependent object list editing

You can edit the dependent objects lists instead of replacing the entire list with new objects in a dependent objects list.

Dependent objects are objects whose lifetime is tied up to a parent-independent object, such as a document. Dependent Objects are always contained in a List property on the parent object. Lists of dependent objects include things like Content Elements and Permissions on the core classes of Content Engine objects – Documents, Folders, and Custom Objects.

With the support of authoring new metadata, other types of dependent objects are now supported in the Content Services GraphQL API and the editing features are enhanced to support these types of objec

With the types of dependent objects on metadata and other administrative objects, it is advantageous to edit these lists in ways other than replacing the entire list. With property definitions, for example, the programming model is to edit an existing list even when creating a new class definition. When you are creating a class definition, it starts out with the list of inherited property definitions and you can then modify certain attributes of those inherited definitions or add new property definitions.

To edit a list of dependent objects, the input objects that are passed to a mutation follow a similar pattern for any type of dependent object. The following definitions are in GraphQL’s Schema Definition Language format and illustrate this pattern.
input SomeObjectListInput {
    replace: [SomeObjectInput!]
    modify: [SomeObjectInput!]
}

input SomeObjectInput {
    insertAction: InsertDependentActionInput
    updateAction: UpdateDependentActionInput
    moveAction: MoveDependentActionInput
    deleteAction: DeleteDependentActionInput

    ## Object type specific input fields
    ...
}
Specific input types for each type of dependent object:
  • ...ListInput
  • ...Input
...ListInput
The ...ListInput is the type of object that is supplied as the value when you update some list of dependent objects – for example, the value of a contentElements field or permissions field. The ...ListInput type has two fields:
  • replace
  • modify
You can specify only one of these fields. The replace field was supported in previous versions. You can insert only new objects using the replace field, which is equivalent to removing all existing objects and inserting new objects. With the help of the modify field, you can update, move, or delete the existing objects to and inserting the new objects.
When you are creating new independent parent objects, the use of the modify field is meaningful for certain types of dependent objects.
  • For permissions, the default list of permissions is applied and other permissions can be added to the default list.
  • For property definitions of a class definition, the inherited list of permissions is applied, which can be modified. The list of property definitions can be modified, not replaced.
...Input
The ...Input type has fields with the following input types that are common across all dependent object types.
input InsertDependentActionInput {
    classIdentifier: String
    newIndex: Int
}

input UpdateDependentActionInput {
    itemReference: DependentItemReferenceInput!
}

input MoveDependentActionInput {
    itemReference: DependentItemReferenceInput!
    newIndex: Int!
}

input DeleteDependentActionInput {
    itemReference: DependentItemReferenceInput!
}

input DependentItemReferenceInput {
    id: ID
    identifier: String
    originalIndex: Int
    sequenceNumber: Int
}
Any ...Input type has four action fields:
  1. insertAction
  2. updateAction
  3. moveAction
  4. deleteAction

One action field can be specified. If none are specified, it defaults to an insert action, and the item is appended to the end of the list. If you are using the replace field of ...ListInput then you can specify insertAction (or no actions, defaulting to an insert). InsertDependentActionInput has a classIdentifier field to identify the class of the new dependent object. It is optional often.

Many ...Input types for specific dependent objects have a “type” or similar field to identify the class of the object with a typed enum value. Sometimes, the class of object is implied by the required class of the list property on the parent object, if that required class allows instances to be created.

There is a newIndex field on InsertDependentActionInput or MoveDependentActionInput to specify the index when you are inserting a new object or moving an existing object. It is optional, when you insert an object and by default that goes to the end of the list.

UpdateDependentActionInput, MoveDependentActionInput, and DeleteDependentActionInput all have a required itemReference field to reference the existing object. Only one of the fields of DependentItemReferenceInput can be completed to reference the object.
  • The existing object can always be referenced by originalIndex.
  • If the class of objects have a unique ID property, the object can be referenced by ID.
  • The identifier field serves to identify an object by some other unique identifier, such as a symbolic name.
  • The sequenceNumber field applies mainly to content elements that have a unique element sequence number field.
To update a list of dependent objects by using the modify field you require: 1) a non-null Update Sequence Number (USN) specified on the parent independent object; or 2) the parent independent object is being created. This way that you can know the starting state of the list, and change accurately. The USN (of an object not being created) can be determined in one of the following ways:
  • The caller can specify a non-null updateSequenceNumber argument.
  • The caller does not specify an updateSequenceNumber argument but the object is fetched before applying changes. The USN of the fetched object is used if any dependent object lists are being modified as part of the mutation. This is an exception to the previous behavior for USN handling where a null value is used if updateSequenceNumber is not specified.
  • However, if any dependent objects are managed by index, newIndex is specified when creating or moving an object or originalIndex is used to refer an existing object, then the caller must specify a non-null updateSequenceNumber argument. Any index that is specified must correspond to a known state of the parent-independent object.

When multiple mutations are in a batch and conditions are such that a fetch-less object is obtained based on the behavior for batched mutations, then it is not possible to update a dependent object list by using the modify field. The same applies if the caller explicitly specifies a null updateSequenceNumber value.

You can refer the examples of mutations on enhanced editing of dependent object lists in later sections.