Operations based PATCH
This operations based PATCH behavior uses a ShareAspace specific flavor of JSON PATCH.
The solution basically makes it possible to send in more fine granular operations to be made on a SoftType, specified on port level on what to do (add, replace, remove).
Previous PATCH implementations all had their drawbacks, the operations based PATCH allows for both separation of the PATCH implementation from a regular update as well as enabling a client to send in more fine granular operations.
Updates to SoftType read
In order to support the operations based PATCH implementation an additional
system property has been added to the GET response. $entryId
is now included on all
objects within arrays. This allows for pinpointing specific entries within an array
while doing the PATCH operations.
PATCH operations
A PATCH request should be used when performing partial modification of a resource. The supported operations are:
- add
- replace
- remove
Request method and headers
When any client using the ShareAspace REST API wants to make a PATCH request/operation,
the request method should be PATCH
and the Content-Type header should be application/json-patch+json
:
PATCH https://fqdn/api/space/space1/softtype/document/03240120430124
Content-Type: application/json-patch+json
Note
The REST API Layer will look at the Content-Type header to determine if the request is a PATCH Operation.
Request payload
The request payload is a JSON document with an array of objects, where each object represents a single operation to be applied to the target resource (e.g. a Document SoftType).
Example:
PATCH https://fqdn/api/space/space1/softtype/document/03240120430124
Content-Type: application/json-patch+json
[
{
"op": "add",
"path": "/description",
"value": "A document description"
},
{
"op": "replace",
"path": "/name",
"value": "An updated name"
}
]
The order of the object members is not significant.
Operations
Each object in the request array can have any of the following operations (op
):
add
- If the target location is an array index, a new value is inserted into the array at the last position in the array.
- If the target location is an object member that does not already exist, a new member is added to the object.
- If the target location is an object member that already exist, the request will fail (the replace operation is required for this scenario).
Note
The target location is the path within the input schema. This is explained in more detail below.
remove
Removes the value at the target location.
Note that remove is a bit special, since removing an entry might make the parent entry non-compliant to the model, therefore, after a remove operation is done, the parent entry is checked. If the remove operation makes it non-compliant, the parent entry is removed as well.
This behavior was added since looking at the remove operation from the client perspective, lets say a property value assignment, removing a value in the edit form will most likely remove the port with a path similar to:
targetWeight.value
where targetWeight
is the PropertyValueAssignment
and value
is the AssignedPropertyValue
.
This means: remove the value port.
Looking at the model, we see that AssignedPropertyValue
is mandatory on the
PropertyValueAssignment
on the model level, which will make it non-compliant.
That is why we will also remove the PropertyValueAssignment
in this case.
replace
Replace the value at the target location. The target location MUST exist.
With a Replace operation, we also have to check if the value is a DatedEffectivityElementSelect
,
because in that case we also need to change the effectivity date to the one in the information
filter (since we are updating the value of a cloned entry, it will have the wrong effectivity date).
Path
The path property is a JSON Pointer that reference a location in the target that the operation should operate on. The target is the input schema and not the data section.
Example JSON data:
{
"id": "MyPart",
"description": "A generic part",
"files": [
{
"$entryId": "9876",
"name": "file1",
"location": "user:///file1"
},
{
"$entryId": "0123",
"name": "file2",
"location": "user:///file2"
}
]
}
Example input schema:
{
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"description": {
"type": "string"
},
"files": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"location": {
"type": "string"
}
}
}
}
}
}
Some JSON Pointer path examples in the JSON document above:
- "" - The whole document, not supported in ShareAspace.
- "/description" - the description property.
- "/files/0123 - The file entry with
0123
as the entry object id. - "/files/9876/name - The name of the file entry with the entry object id
9876
.
Note
ShareAspace does not use the position like 0..n, instead ShareAspace is using the entry id of the array item.
Value
The value property is the data that should be applied to the target.
If the target JSON pointer value should be removed (operation = remove), then the value property should not be in the request.
Note
ShareAspace currently only support JObject and JArray value on Patch add, not for Patch replace.
Examples
Example JSON Patch request to add a name to the target:
PATCH https://fqdn/api/space/space1/softtype/part/03240120430124
Content-Type: application/json-patch+json
[
{
"op": "add",
"path": "/name",
"value": "Now I have a name"
}
]
Example JSON Patch request to update the name on the target:
PATCH https://fqdn/api/space/space1/softtype/part/03240120430124
Content-Type: application/json-patch+json
[
{
"op": "replace",
"path": "/name",
"value": "Now I have an updated name"
}
]
Example JSON Patch request to remove the name on the target:
PATCH https://fqdn/api/space/space1/softtype/part/03240120430124
Content-Type: application/json-patch+json
[
{
"op": "remove",
"path": "/name"
}
]
Example JSON Patch request to add an element to an array (place it last):
PATCH https://fqdn/api/space/space1/softtype/part/03240120430124
Content-Type: application/json-patch+json
[
{
"op": "add",
"path": "/files/-",
"value": {
"name": "file3",
"location": "participant:///OEM/files/file3"
}
}
]
Note
The dash (-
) is used to index the end of the array, meaning appending
the value to the array. This will always be the case for us (so it is possible to
skip it in the request).
Note
According to RFC JSON Pointers support inserting an element into an array at a specific index. This is not supported in ShareAspace
Example JSON Patch request to update an element in an array:
PATCH https://fqdn/api/space/space1/softtype/part/03240120430124
Content-Type: application/json-patch+json
[
{
"op": "replace",
"path": "/files/{entryId}/name",
"value": "new file name"
}
]
Example JSON Patch request to remove an element in an array:
PATCH https://fqdn/api/space/space1/softtype/part/03240120430124
Content-Type: application/json-patch+json
[
{
"op": "remove",
"path": "/files/{entryId}/"
}
]