OASIS OData TC - Examples

Annotating capabilities

Consider a Headers entity set with contained entity sets Headers(...)/Items and Headers(...)/Items(...)/Subitems. Each entity type has a server-generated uuid and a canUpdate property. The header has an additional canInsertItems and the item has canInsertSubitems which govern insertability. Insertability of headers depends on the permissions contained in a Permissions singleton. The header also has a canUpdateSubsetOfItems which governs updatability with /$filter(...)/$each (the analogous thing on item level is omitted from this example).

The following annotations express insertability and updatability in terms of these properties. Deletability is analogous to updatability but omitted from this example.

For the header level, the entity set is annotated directly.

"self.Container/Headers": {
  "@Capabilities.InsertRestrictions": {
    "Insertable": {"$Path": "/self.Container/Permissions/canInsertHeaders"},
    "NonInsertableProperties": ["uuid"]
  },
  "@Capabilities.UpdateRestrictions": {
    "Updatable": {"$Path": "canUpdate"},
    "NonUpdatableProperties": ["uuid"]
  }
}

The item level has no named entity set. It is annotated using NavigationRestrictions on header level and InsertRestrictions and UpdateRestrictions on item level. When a property could be expressed either on the deeper item level or on the higher-up header level, the deeper level is generally preferred: For example, annotating the Headers/Items target with UpdateRestrictions/NonUpdatableProperties is favored over the commented-out annotation NavigationRestrictions/UpdateRestrictions/NonUpdatableProperties on the Headers target, and the commented-out Updatable is even invalid, because the instance path to canUpdate is collection-valued. But annotating NavigationRestrictions/InsertRestrictions/Insertable and NavigationRestrictions/UpdateRestrictions/FilterSegmentSupported on the Headers target cannot be avoided, because the instance paths to canInsertItems and canUpdateSubsetOfItems must be evaluated on header level.

"self.Container/Headers": {
  "@Capabilities.NavigationRestrictions": {
    "RestrictedProperties": [{
      "NavigationProperty": "Items",
      "InsertRestrictions": {
        // DISCOURAGED: "NonInsertableProperties": ["Items/uuid"],
        "Insertable": {"$Path": "canInsertItems"}
      },
      "UpdateRestrictions": {
        // INVALID: "Updatable": {"$Path": "Items/canUpdate"},
        // DISCOURAGED: "NonUpdatableProperties": ["Items/uuid"],
        "FilterSegmentSupported": {"$Path": "canUpdateSubsetOfItems"}
      }
    }]
  }
},
"self.Container/Headers/Items": {
  "@Capabilities.InsertRestrictions": {
    "NonInsertableProperties": ["uuid"]
  },
  "@Capabilities.UpdateRestrictions": {
    "Updatable": {"$Path": "canUpdate"},
    "NonUpdatableProperties": ["uuid"]
  }
}

However, if insertability was static, the value would be a boolean literal and no path expressions would be required. In that case directly annotating the Headers/Items target with InsertRestrictions/Insertable would be favored over annotating the Headers target with NavigationRestrictions/InsertRestrictions/Insertable.

"self.Container/Headers/Items": {
  "@Capabilities.InsertRestrictions": {
    "Insertable": true,
    "NonInsertableProperties": ["uuid"]
  }
}

If limitations, such as tool restrictions, prevent annotation targets with navigation properties in them, like the Headers/Items target, then non-insertable and non-updatable properties on item and subitem level would be annotated on the Headers target:

"self.Container/Headers": {
  "@Capabilities.InsertRestrictions": {
    "NonInsertableProperties": ["uuid", "Items/uuid", "Items/Subitems/uuid"],
    "NonUpdatableProperties": ["uuid", "Items/uuid", "Items/Subitems/uuid"]
  }
}

If there are no such limitations, the subitem level is annotated using NavigationRestrictions on item level and InsertRestrictions and UpdateRestrictions on subitem level.

"self.Container/Headers/Items": {
  "@Capabilities.NavigationRestrictions": {
    "RestrictedProperties": [{
      "NavigationProperty": "Subitems",
      "InsertRestrictions": {
        "Insertable": {"$Path": "canInsertSubitems"}
      }
    }]
  }
},
"self.Container/Headers/Items/Subitems": {
  "@Capabilities.InsertRestrictions": {
    "NonInsertableProperties": ["uuid"]
  },
  "@Capabilities.UpdateRestrictions": {
    "Updatable": {"$Path": "canUpdate"},
    "NonUpdatableProperties": ["uuid"]
  }
}