Subject: Re: [scim] #18 (api): Review patch function

From: Phil Hunt <[email-masked]>
Date: Sun, 16 Mar 2014 10:52:13 -0700

Oops… the text I posted to the ticket was old text.  I have updated the ticket.  This is the correct "proposed" text.

Do we want full conformance including all operations and json pointer?

Here is just the new PATCH section alone:
----------------------------------
 3.3.2.  Modifying with PATCH
 
    PATCH is OPTIONAL.  PATCH enables clients to send only those
    attributes requiring modification, reducing network and processing
    overhead.  Attributes may be deleted, replaced, merged, or added in a
    single request.
 
|   The body of a PATCH request MUST contain ONE or more JSON Patch
|   operations [RFC6902].  The server MUST return either a 200 OK
    response code and the entire resource (subject to the "attributes"
    query parameter - see Additional Retrieval Query Parameters
    (Section 3.7)) within the response body, or a 204 No Content response
    code and the appropriate response headers for a successful PATCH
    request.  The server MUST return a 200 OK if the "attributes"
    parameter is specified on the request.
 
|   The "path" and "from" attributes are strings containing a SCIM
|   attribute path or a json pointer and optional SCIM multi-value array
|   filter.
 
|       The ABNF syntax for "path" and "from" is specified by "PATH":
 
|   PATH = ATPATH / json6901path
 
|   json6901path = json-pointer ["/[" FILTER "]" [json-pointer] ]
 
|                ABNF for PATCH "path" and "from" Attributes
 
|   "ATPATH" and "FILTER" are as per Figure 1, and "json-pointer" is as
|   per [RFC6901].
 
|   As SCIM servers do not guarantee order of multi-value arrays, a SCIM
|   client should use caution when using JSON Pointer array addressing.
|   SCIM sub-attribute filtes MUST be specified within square brackets ([
|   ]) to distinguish from array indexing.  Clients should consider that
|   entries with high-update rates may change array indexes frequently.
|   Clients SHOULD use "Etags" when accessing multi-valued attributes by
|   array index.
|
|          Valid example "path" and "from" values are as follows:
|
|   "path" = "members"
|
|   "path" = "name.familyName"
|
|   "path" = "/name/familyName"
|
|   "path" = "addresses[type eq \"work\"]"
|
|   "path" = "members[value eq
|            \"2819c223-7f76-453a-919d-413861904646\"]"
|
|   "path" = "/members/1/displayName"
|
|   "path" = "members[value eq
|            \"2819c223-7f76-453a-919d-413861904646\"].displayName"
|
|   "path" = "/members/[value eq
|            \"2819c223-7f76-453a-919d-413861904646\"]/displayName
|
|3.3.2.1.  Supported JSON Patch Operations
|
|   SCIM supports the JSON Patch operations: "add", "remove", "replace",
|   "copy","move", and "test".
|
|   As specified in [RFC6902], a PATCH MAY contain one or more JSON patch
|   operation in a JSON array.  The PATCH request comprising the entire
|   array of operations SHALL be treated as atomic.  If a single
|   operation encounters an error condition, the original SCIM resource
|   MUST be restored.
|
|   Each operation represents a single action to be applied to the same
|   SCIM resource specified by the request URI.  Operations are applied
|   sequentially in the order they appear in the array.  Each operation
|   in the sequence is applied to the target resource; the resulting
|   resource becomes the target of the next operation.  Evaluation
|   continues until all operations are successfully applied or until an
|   error condition is encountered.
|
|3.3.2.2.  Add Operation
|
|   The "add" operation performs one of the following functions,
|   depending upon what the target location indicated by "path"
|   references:
|
|   o  If the target location does not exist, the attribute and value is
|      added.
|
|   o  If the target location specifies a multi-valued attribute, a new
|      value is added to the attribute.
|
|   o  if the target location specifies a single-valued attribute, the
|      existing value is replaced.
|
|   o  If the target location specifies an attribute that does not exist
|      (has no value), the attribute is added with the new value.
|
|   o  If the target location already contains the value specified, no
|      changes SHOULD be made to the resource and a success response
|      SHOULD be returned.
|
|   o  If the target location already exists the value is replaced.
|
|   The operation MUST contain a "value" member whose content specifies
|   the value to be added.  The value MAY be a quoted value OR it may be
|   a JSON object containing the sub-attributes of the complex attribute
|   specified in the operation's "path".
|
|   The following example shows how to add a member to a group.  Some
|   text removed for readability ("..."):
 
 PATCH /Groups/acbf3ae7-8463-4692-b4fd-9b4da3f908ce
 Host: example.com
 Accept: application/json
 Content-Type: application/json
 Authorization: Bearer h480djs93hd8
 If-Match: W/"a330bc54f0671c9"
 
 {
|  "op":"add",
|  "path":"members",
|  "value":[
     {
       "display": "Babs Jensen",
|      "$ref": "https://example.com/v2/Users/2819c223-...919d-413861904646",
       "value": "2819c223-7f76-453a-919d-413861904646"
     }
   ]
 }
 
    The "display" Sub-Attribute in this request is optional since the
    value attribute uniquely identifies the user to be added.  If the
    user was already a member of this group, no changes should be made to
    the resource and a success response should be returned.  The server
    responds with either the entire updated Group or no response body:
 
 HTTP/1.1 204 No Content
 Authorization: Bearer h480djs93hd8
 ETag: W/"b431af54f0671a2"
 Location: "https://example.com/v2/Groups/acbf3ae7-8463-4692-b4fd-9b4da3f908ce"
 
|3.3.2.3.  Remove Operation
|
|   The "remove" operation removes the value at the target location
|   specified by the "path".  The operation performs the following
|   functions depending on the target location specified by "path":
|
|   o  If the target location is a single-value attribute, the attribute
|      and its associated value is removed.
|
|   o  If the target location is a multi-valued attribute and no filter
|      is specified, the attribute and all values are removed.
|
|   o  If the target location is a multi-valued attribute and a complex
|      filter is specified comparing a "value", the values matched by the
|      filter are removed.
|
|   o  If the target location is a complex-multi-valued attribute and a
|      complex filter is specified based on the attribute's sub-
|      attributes, the matching records are removed.
|
    The following example shows how to remove a member from a group.  As
    with the previous example, the "display" Sub-Attribute is optional.
    If the user was not a member of this group, no changes should be made
    to the resource and a success response should be returned.
 
    Note that server responses have been omitted for the rest of the
    PATCH examples.
 
|   Remove a single member from a group.  Some text removed for
|   readability ("..."):
|
 PATCH /Groups/acbf3ae7-8463-4692-b4fd-9b4da3f908ce
 Host: example.com
 Accept: application/json
 Content-Type: application/json
 Authorization: Bearer h480djs93hd8
 If-Match: W/"a330bc54f0671c9"
 
 {
|     "op":"remove",
|     "path":"members[value eq \"2819c223-7f76-...413861904646\"]"
 }
 
|   Remove all members of a group:
 
    PATCH /Groups/acbf3ae7-8463-4692-b4fd-9b4da3f908ce
    Host: example.com
    Accept: application/json
    Content-Type: application/json
    Authorization: Bearer h480djs93hd8
    If-Match: W/"a330bc54f0671c9"
 
|   { "op":"remove","path":"members"}
|
|   Removal of a value from a complex-multi-valued attribute (request
|   headers removed for brevity):
|
    {
|     "op":"remove",
|     "path":"address[type eq \"work\" and value ew \"example.com\"]"
    }
|   Example request to remove and add a member.  Some text removed for
|   readability ("..."):
 
 PATCH /Groups/acbf3ae7-8463-4692-b4fd-9b4da3f908ce
 Host: example.com
 Accept: application/json
 Content-Type: application/json
 Authorization: Bearer h480djs93hd8
 If-Match: W/"a330bc54f0671c9"
 
|[
 {
|    "op":"remove",
|    "path":"members[value eq\"2819c223-...919d-413861904646\"]"
   },
|  {
|    "op":"add",
|    "path":"members",
|    "value": [
|      {
|        "display": "James Smith",
|        "$ref": "https://example.com/v2/Users/08e1d05d-...8b96-473d93df9210",
|        "value": "08e1d05d-121c-4561-8b96-473d93df9210"
|      }
|    ]
|  }
|]
|   The following example shows how to replace all the members of a group
|   with a different members list.  Some text removed for readabilty
|   ("..."):
|
|PATCH /Groups/acbf3ae7-8463-4692-b4fd-9b4da3f908ce
|Host: example.com
|Accept: application/json
|Content-Type: application/json
|Authorization: Bearer h480djs93hd8
|If-Match: W/"a330bc54f0671c9"
|
|[
|  { "op":"remove","path":"members"},
|  {
|    "op":"add",
|    "path":"members",
|    "value":[
     {
       "display": "Babs Jensen",
|      "$ref": "https://example.com/v2/Users/2819c223-...919d-413861904646",
       "value": "2819c223-7f76-453a-919d-413861904646"
     },
     {
       "display": "James Smith",
|      "$ref": "https://example.com/v2/Users/08e1d05d-121c-...473d93df9210",
       "value": "08e1d05d-121c-4561-8b96-473d93df9210"
|    }]
     }
   ]
 
|3.3.2.4.  Replace Operation
|
|   The "replace" operation replaces the value at the target location
|   specified by the "path".  The operation performs the following
|   functions depending on the target location specified by "path":
|
|   o  If the target location is a single-value attribute, the attributes
|      value is replaced.
|
|   o  If the target location is a multi-valued attribute and no filter
|      is specified, the attribute and all values are replaced.
|
|   o  If the target location is a multi-valued attribute and a complex
|      filter is specified comparing a "value", the values matched by the
|      filter are replaced.
|
|   o  If the target location is a complex-multi-valued attribute and a
|      complex filter is specified based on the attribute's sub-
|      attributes, the matching records are replaced.
|
|   o  If the target location is a complex-multi-valued attribute with a
|      complex filter and a specific sub-attribute (e.g.  "addresses[type
|      eq "work"].streetAddress"), the matching sub-attribute of the
|      matching record is replaced.
|
|   The following example shows how to replace all the members of a group
|   with a different members list in a single replace operation.  Some
|   text removed for readability ("..."):
 
 PATCH /Groups/acbf3ae7-8463-4692-b4fd-9b4da3f908ce
 Host: example.com
 Accept: application/json
 Content-Type: application/json
 Authorization: Bearer h480djs93hd8
 If-Match: W/"a330bc54f0671c9"
 
 {
|  "op":"replace",
|  "path":"members",
|  "value":[
     {
       "display": "Babs Jensen",
|      "$ref": "https://example.com/v2/Users/2819c223-...919d-413861904646",
|      "value": "2819c223-7f76-453a-919d-413861904646"
     },
     {
       "display": "James Smith",
|      "$ref": "https://example.com/v2/Users/08e1d05d-121c-...473d93df9210",
       "value": "08e1d05d-121c-4561-8b96-473d93df9210"
     }
   ]
 }
|   The following example shows how to change a User's entire "work"
|   address.
 
    PATCH /Users/2819c223-7f76-453a-919d-413861904646
    Host: example.com
    Accept: application/json
    Content-Type: application/json
    Authorization: Bearer h480djs93hd8
    If-Match: W/"a330bc54f0671c9"
 
    {
|     "op":"replace",
|     "path":"addresses[type eq \"work\"]",
|     "value":
        {
|       "type": "work",
|       "streetAddress": "911 Universal City Plaza",
|       "locality": "Hollywood",
|       "region": "CA",
|       "postalCode": "91608",
|       "country": "US",
|       "formatted": "911 Universal City Plaza\nHollywood, CA 91608 US",
          "primary": true
        }
    }
|
    The following example shows how to change a User's address.  Since
    address does not have a value Sub-Attribute, the existing address
    must be removed and the modified address added.
 
   PATCH /Users/2819c223-7f76-453a-919d-413861904646
   Host: example.com
   Accept: application/json
   Content-Type: application/json
   Authorization: Bearer h480djs93hd8
   If-Match: W/"a330bc54f0671c9"
 
   {
|     "op":"replace",
|     "path":"addresses[type eq \"work\"].streetAddress",
|     "value":"911 Universal City Plaza"
|   }
|
|3.3.2.5.  Move Operation
|
|   The "move" operation moves the value at a specified location ("from")
|   and adds it at a target location ("path").  The operation is
|   functionally identical to a "remove" operation on the "from"
|   location, frollowed immediately by an "add" operation at the target
|   location with the value that was just removed.  If a filter was used
|   to select the path location, any filter term with an attribute
|   equality condition (e.g. "[type eq \"home\"]") SHALL retain the value
|   of the filtered attribute and SHALL NOT be overwritten by a
|   corresponding attribute value from the "from" location.
|
|   The following shows two existing "addresses" that are part of a
|   resource in the SCIM server before patching:
|
     "addresses": [
       {
         "type": "work",
         "streetAddress": "100 Universal City Plaza",
         "locality": "Hollywood",
         "region": "CA",
         "postalCode": "91608",
|       "country": "USA",
|       "formatted": "100 Universal City Plaza\nHollywood, CA 91608 USA",
|       "primary": true
       },
       {
|       "type": "home",
|       "streetAddress": "456 Hollywood Blvd",
         "locality": "Hollywood",
         "region": "CA",
         "postalCode": "91608",
|       "country": "USA",
|       "formatted": "456 Hollywood Blvd\nHollywood, CA 91608 USA"
       }
     ]
 
|   The following example shows how to move an address from type "work"
|   to type "home":
 
    PATCH /Users/2819c223-7f76-453a-919d-413861904646
    Host: example.com
    Accept: application/json
    Content-Type: application/json
    Authorization: Bearer h480djs93hd8
    If-Match: W/"a330bc54f0671c9"
 
    {
|     "op":"move",
|     "from":"/addresses/[type eq \"work\"]"
|     "path":"/addresses/[type eq \"home\"]"
|
    }
|   The following shows the attribute "addresses" after the preceding
|   PATCH "move" operation.
 
|   "addresses": [
|     {
|       "type": "home",
|       "streetAddress": "100 Universal City Plaza",
|       "locality": "Hollywood",
|       "region": "CA",
|       "postalCode": "91608",
|       "country": "USA",
|       "formatted": "100 Universal City Plaza\nHollywood, CA 91608 USA",
|       "primary": true
|     }
|   ]
 
|3.3.2.6.  Copy Operation
|
|   The "copy" operation copies the value at a specified location
|   ("from") and adds it the target location ("path").  This operation is
|   functionalty the similar to an "add" operation at the target location
|   with the value that specified by the "from" attribute.  If a filter
|   was used to select the path location, any filter term with an
|   attribute equality condition (e.g. "[type eq \"home\"]") SHALL retain
|   the value of the filtered attribute and SHALL NOT be overwritten by a
|   corresponding attribute value from the "from" location.
|
|   The following shows two existing "addresses" that are part of a
|   resource in the SCIM server before patching:
 
|   "addresses": [
    {
|       "type": "work",
|       "streetAddress": "100 Universal City Plaza",
|       "locality": "Hollywood",
|       "region": "CA",
|       "postalCode": "91608",
|       "country": "USA",
|       "formatted": "100 Universal City Plaza\nHollywood, CA 91608 USA",
|       "primary": true
|     },
|     {
|       "type": "home",
|       "streetAddress": "456 Hollywood Blvd",
|       "locality": "Hollywood",
|       "region": "CA",
|       "postalCode": "91608",
|       "country": "USA",
|       "formatted": "456 Hollywood Blvd\nHollywood, CA 91608 USA"
    }
|   ]
 
|   The following example shows how to copy an address from type "work"
|   to type "home":
 
    PATCH /Users/2819c223-7f76-453a-919d-413861904646
    Host: example.com
    Accept: application/json
    Content-Type: application/json
    Authorization: Bearer h480djs93hd8
    If-Match: W/"a330bc54f0671c9"
 
    {
|     "op":"copy",
|     "from":"/addresses/[type eq \"work\"]"
|     "path":"/addresses/[type eq \"home\"]"
|
      }
|   The following shows the attribute "addresses" after the preceding
|   PATCH "copy" operation.
|
|   "addresses": [
|     {
|       "type": "work",
|       "streetAddress": "100 Universal City Plaza",
|       "locality": "Hollywood",
|       "region": "CA",
|       "postalCode": "91608",
|       "country": "USA",
|       "formatted": "100 Universal City Plaza\nHollywood, CA 91608 USA",
|       "primary": true
|     },
|     {
|       "type": "home",
|       "streetAddress": "100 Universal City Plaza",
|       "locality": "Hollywood",
|       "region": "CA",
|       "postalCode": "91608",
|       "country": "USA",
|       "formatted": "100 Universal City Plaza\nHollywood, CA 91608 USA",
|       "primary": true
    }
|   ]
 
|3.3.2.7.  Test Operation
|
|   The "test" operation tests the value at the target location specified
|   by the "path"is equal to the specified value.  The operation performs
|   the following functions depending on the target location specified by
|   "path":
|
|   o  If the target location is a single-value attribute, the attributes
|      value is compared for equality to the value specified.
|
|   o  If the target location is a multi-valued attribute and no filter
|      is specified, all values are compared as if the "eq" filter were
|      applied to the attribute.
|
|   o  If the target location is a multi-valued attribute and a complex
|      filter is specified comparing a "value", the values matched by the
|      filter are compared for equality to the value specified.
|
|   o  If the target location is a complex-multi-valued attribute and a
|      complex filter is specified based on the attribute's sub-
|      attributes, the matching record is compared for equality to the
|      value specified.
|
|   o  If the target location is a complex-multi-valued attribute with a
|      complex filter and a specific sub-attribute (e.g.  "addresses[type
|      eq "work"].streetAddress"), the matching sub-attribute of the
|      matching record is compared to the value specified.
|
|   The following is an example of a test operation performing
|   conditional replace if a record has a specific value.
 
    PATCH /Users/2819c223-7f76-453a-919d-413861904646
    Host: example.com
    Accept: application/json
    Content-Type: application/json
    Authorization: Bearer h480djs93hd8
    If-Match: W/"a330bc54f0671c9"
 
|   [
    {
|       "op":"test",
|       "path":"addresses[type eq \"work\"].streetAddress",
|       "value":"100 Universal City Plaza"
|     },
|     {
|       "op":"replace",
|       "path":"addresses[type eq \"work\"].streetAddress",
|       "value":"911 Universal City Plaza"
    }
|   ]
 
----------------------------------

Phil

@independentid
www.independentid.com
[email-masked]

On 2014-03-16, at 10:40 AM, "scim issue tracker" <[email-masked]> wrote:

> #18: Review patch function
> 
> 
> Comment (by [email-masked]):
> 
> Here is a proposal with full 6902/6901 compliance:
> 
> {{{
> 
>  3.3.2.  Modifying with PATCH
> 
>     PATCH is OPTIONAL.  PATCH enables clients to send only those
>     attributes requiring modification, reducing network and processing
>     overhead.  Attributes may be deleted, replaced, merged, or added in a
>     single request.
> 
>     The body of a PATCH request MUST contain a partial resource with the
>     desired modifications.  The server MUST return either a 200 OK
>     response code and the entire resource (subject to the "attributes"
>     query parameter - see Additional Retrieval Query Parameters
>     (Section 3.7)) within the response body, or a 204 No Content response
>     code and the appropriate response headers for a successful PATCH
>     request.  The server MUST return a 200 OK if the "attributes"
>     parameter is specified on the request.
> 
> |   The format of the SCIM PATCH operation is based upon JavaScript
> |   Object Notation (JSON) Patch [RFC6902].  However instead of using
> |   JSON-Pointer values [RFC6901], SCIM PATCH operation objects have
> |   a"path" member whose value is a string containing a SCIM attribute
> |   path value whose ABNF syntax is PATH as per Figure 1).
> 
> |   The attribute-path is a SCIM attribute or attribute and sub-attribute
> |   combined with an optional complex filter to select the correct value
> |   of a multi-valued complex attribute.  Valid examples are as follows:
> 
> |   "path" = "members"
> 
> |   "path" = "name.familyName"
> 
> |   "path" = "addresses[ty[e eq \"work\"]"
> 
> |   "path" = "members[value eq
> |            \"2819c223-7f76-453a-919d-413861904646\"]"
> 
> |   "path" = "members[value eq
> |            \"2819c223-7f76-453a-919d-413861904646\"].displayName"
> |
> |3.3.2.1.  Supported JSON Patch Operations
> |
> |   SCIM supports the JSON Patch operations: "add", "remove", "replace",
> |   and "test".  The JSON patch operations "move" and "copy" SHALL NOT be
> |   supported as SCIM does not support array based addressing.
> |
> |   As specified in [RFC6902], a PATCH MAY contain one or more JSON patch
> |   operation in a JSON array.  The PATCH request comprising the entire
> |   array of operations SHALL be treated as atomic.  If a single
> |   operation encounters an error condition, the original SCIM resource
> |   MUST be restored.
> |
> |   Each operation represents a single action to be applied to a single
> |   SCIM resource.  Operations are applied sequentially in the order they
> |   appear in the array.  Each operation in the sequence is applied to
> |   the target document; the resulting document becomes the target of the
> |   next operation.  Evaluation continues until all operations are
> |   successfully applied or until an error condition is encountered.
> |
> |3.3.2.2.  Add Operation
> |
> |   The "add" operation performs one of the following functions,
> |   depending upon what the target location inidicated by "path"
> |   references:
> |
> |   o  If the target location specifies a multi-valued attribute, a new
> |      value is added to the attribute.
> |
> |   o  if the target location specifies a single-valued attribute, the
> |      existing value is replaced.
> |
> |   o  If the target location specifies an attribute that does not exist
> |      (has no value), the attribute is added with the new value.
> |
> |   o  If the target location already contains the value specified, no
> |      changes SHOULD be made to the resource and a success response
> |      SHOULD be returned.  The server MAY respond with either the entire
> |      updated resource or no response body (e.g. in the case of a
> |      "Group").
> |
> |   The operation MUST contain a "value" member whose content specifies
> |   the value to be added.  The value MAY be a quoted value OR it may be
> |   a JSON object containing the sub-attributes of the complex attribute
> |   specified in the operation's "path".
> |
> |   The following example shows how to add a member to a group.  Some
> |   text removed for readability ("..."):
> 
>  PATCH /Groups/acbf3ae7-8463-4692-b4fd-9b4da3f908ce
>  Host: example.com
>  Accept: application/json
>  Content-Type: application/json
>  Authorization: Bearer h480djs93hd8
>  If-Match: W/"a330bc54f0671c9"
> 
>  {
> |  "op":"add",
> |  "path":"members",
> |  "value":[
>      {
>        "display": "Babs Jensen",
> |      "$ref":
> "https://example.com/v2/Users/2819c223-...919d-413861904646",
>        "value": "2819c223-7f76-453a-919d-413861904646"
>      }
>    ]
>  }
> 
>     The "display" Sub-Attribute in this request is optional since the
>     value attribute uniquely identifies the user to be added.  If the
>     user was already a member of this group, no changes should be made to
>     the resource and a success response should be returned.  The server
>     responds with either the entire updated Group or no response body:
> 
>  HTTP/1.1 204 No Content
>  Authorization: Bearer h480djs93hd8
>  ETag: W/"b431af54f0671a2"
>  Location: "https://example.com/v2/Groups/acbf3ae7-8463-4692-b4fd-
> 9b4da3f908ce"
> 
> |3.3.2.3.  Remove Operation
> |
> |   The "remove" operation removes the value at the target location
> |   specified by the "path".  The operation performs the following
> |   functions depending on the target location specified by "path":
> |
> |   o  If the target location is a single-value attribute, the attribute
> |      and its associated value is removed.
> |
> |   o  If the target location is a multi-valued attribute and no filter
> |      is specified, the attribute and all values are removed.
> |
> |   o  If the target location is a multi-valued attribute and a complex
> |      filter is specified comparing a "value", the values matched by the
> |      filter are removed.
> |
> |   o  If the target location is a complex-multi-valued attribute and a
> |      complex filter is specified based on the attribute's sub-
> |      attributes, the matching records are removed.
> |
>     The following example shows how to remove a member from a group.  As
>     with the previous example, the "display" Sub-Attribute is optional.
>     If the user was not a member of this group, no changes should be made
>     to the resource and a success response should be returned.
> 
>     Note that server responses have been omitted for the rest of the
>     PATCH examples.
> 
> |   Remove a single member from a group.  Some text removed for
> |   readability ("..."):
> |
>  PATCH /Groups/acbf3ae7-8463-4692-b4fd-9b4da3f908ce
>  Host: example.com
>  Accept: application/json
>  Content-Type: application/json
>  Authorization: Bearer h480djs93hd8
>  If-Match: W/"a330bc54f0671c9"
> 
>  {
> |     "op":"remove",
> |     "path":"members[value eq \"2819c223-7f76-...413861904646\"]"
>  }
> |   Remove all members of a group:
> 
>     PATCH /Groups/acbf3ae7-8463-4692-b4fd-9b4da3f908ce
>     Host: example.com
>     Accept: application/json
>     Content-Type: application/json
>     Authorization: Bearer h480djs93hd8
>     If-Match: W/"a330bc54f0671c9"
> 
> |   { "op":"remove","path":"members"}
> |
> |   Removal of a value from a complex-mulit-valued attribute (request
> |   headers removed for brevity):
> |
>     {
> |     "op":"remove",
> |     "path":"address[type eq \"work\" and value ew \"example.com\"]"
>     }
> 
> |   Example request to remove and add a member.  Some text removed for
> |   readability ("..."):
> 
>  PATCH /Groups/acbf3ae7-8463-4692-b4fd-9b4da3f908ce
>  Host: example.com
>  Accept: application/json
>  Content-Type: application/json
>  Authorization: Bearer h480djs93hd8
>  If-Match: W/"a330bc54f0671c9"
> 
> |[
>  {
> |    "op":"remove",
> |    "path":"members[value eq\"2819c223-...919d-413861904646\"]"
>    },
>      {
> |    "op":"add",
> |    "path":"members",
> |    "value": [
>      {
>        "display": "James Smith",
> |        "$ref":
> "https://example.com/v2/Users/08e1d05d-...8b96-473d93df9210",
>        "value": "08e1d05d-121c-4561-8b96-473d93df9210"
>      }
>    ]
>  }
> |]
> |   The following example shows how to replace all the members of a group
> |   with a different members list.  Some text removed for readabilty
> |   ("..."):
> 
>  PATCH /Groups/acbf3ae7-8463-4692-b4fd-9b4da3f908ce
>  Host: example.com
>  Accept: application/json
>  Content-Type: application/json
>  Authorization: Bearer h480djs93hd8
>  If-Match: W/"a330bc54f0671c9"
> 
> |[
> |  { "op":"remove","path":"members"},
>  {
> |    "op":"add",
> |    "path":"members",
> |    "value":[
>      {
>        "display": "Babs Jensen",
> |      "$ref":
> "https://example.com/v2/Users/2819c223-...919d-413861904646",
> |      "value": "2819c223-7f76-453a-919d-413861904646"
>      },
>      {
>        "display": "James Smith",
> |      "$ref": "https://example.com/v2/Users/08e1d05d-
> 121c-...473d93df9210",
>        "value": "08e1d05d-121c-4561-8b96-473d93df9210"
> |    }]
>      }
>    ]
> 
> |3.3.2.4.  Replace Operation
> 
> |   The "replace" operation replaces the value at the target location
> |   specified by the "path".  The operation performs the following
> |   functions depending on the target location specified by "path":
> |
> |   o  If the target location is a single-value attribute, the attributes
> |      value is replaced.
> |
> |   o  If the target location is a multi-valued attribute and no filter
> |      is specified, the attribute and all values are replaced.
> |
> |   o  If the target location is a multi-valued attribute and a complex
> |      filter is specified comparing a "value", the values matched by the
> |      filter are replaced.
> |
> |   o  If the target location is a complex-multi-valued attribute and a
> |      complex filter is specified based on the attribute's sub-
> |      attributes, the matching records are replaced.
> |
> |   o  If the target location is a complex-multi-valued attribute with a
> |      complex filter and a specific sub-attribute (e.g.  "addresses[type
> |      eq "work"].streetAddress"), the matching sub-attribute of the
> |      matching record is replaced.
> |
> |   The following example shows how to replace all the members of a group
> |   with a different members list in a single replace operation.  Some
> |   text removed for readability ("..."):
> |
> |PATCH /Groups/acbf3ae7-8463-4692-b4fd-9b4da3f908ce
>     Host: example.com
>     Accept: application/json
>     Content-Type: application/json
>     Authorization: Bearer h480djs93hd8
>     If-Match: W/"a330bc54f0671c9"
> 
>     {
> |  "op":"replace",
> |  "path":"members",
> |  "value":[
>         {
> |      "display": "Babs Jensen",
> |      "$ref":
> "https://example.com/v2/Users/2819c223-...919d-413861904646",
> |      "value": "2819c223-7f76-453a-919d-413861904646"
> |    },
> |    {
> |      "display": "James Smith",
> |      "$ref": "https://example.com/v2/Users/08e1d05d-
> 121c-...473d93df9210",
> |      "value": "08e1d05d-121c-4561-8b96-473d93df9210"
>         }
>       ]
>     }
> |   The following example shows how to change a User's entire "work"
> |   address.
> 
>    PATCH /Users/2819c223-7f76-453a-919d-413861904646
>    Host: example.com
>    Accept: application/json
>    Content-Type: application/json
>    Authorization: Bearer h480djs93hd8
>    If-Match: W/"a330bc54f0671c9"
> 
>    {
> |     "op":"replace",
> |     "path":"addresses[type eq \"work\"]",
> |     "value":
>        {
>          "type": "work",
>          "streetAddress": "911 Universal City Plaza",
>          "locality": "Hollywood",
>          "region": "CA",
>          "postalCode": "91608",
>          "country": "US",
>          "formatted": "911 Universal City Plaza\nHollywood, CA 91608 US",
>          "primary": true
>        }
>    }
> 
> |   The following example shows how to change a User's address.  Since
> |   address does not have a value Sub-Attribute, the existing address
> |   must be removed and the modified address added.
> 
>     PATCH /Users/2819c223-7f76-453a-919d-413861904646
>     Host: example.com
>     Accept: application/json
>     Content-Type: application/json
>     Authorization: Bearer h480djs93hd8
>     If-Match: W/"a330bc54f0671c9"
> 
>     {
> |     "op":"replace",
> |     "path":"addresses[type eq \"work\"].streetAddress",
> |     "value":"911 Universal City Plaza"
>     }
> 
> |3.3.2.5.  Test Operation
> 
> |   The "test" operation tests the value at the target location specified
> |   by the "path"is equal to the specified value.  The operation performs
> |   the following functions depending on the target location specified by
> |   "path":
> 
> |   o  If the target location is a single-value attribute, the attributes
> |      value is compared for equality to the value specified.
> 
> |   o  If the target location is a multi-valued attribute and no filter
> |      is specified, all values are compared as if the "eq" filter were
> |      applied to the attribute.
> 
> |   o  If the target location is a multi-valued attribute and a complex
> |      filter is specified comparing a "value", the values matched by the
> |      filter are compared for equality to the value specified.
> 
> |   o  If the target location is a complex-multi-valued attribute and a
> |      complex filter is specified based on the attribute's sub-
> |      attributes, the matching record is compared for equality to the
> |      value specified.
> 
> |   o  If the target location is a complex-multi-valued attribute with a
> |      complex filter and a specific sub-attribute (e.g.  "addresses[type
> |      eq "work"].streetAddress"), the matching sub-attribute of the
> |      matching record is compared to the value specified.
> |
> |   The following is an example of a test operation performing
> |   conditional replace if a record has a specific value.
> 
>     PATCH /Users/2819c223-7f76-453a-919d-413861904646
>     Host: example.com
>     Accept: application/json
>     Content-Type: application/json
>     Authorization: Bearer h480djs93hd8
>     If-Match: W/"a330bc54f0671c9"
> 
> |   [
>     {
> |       "op":"test",
> |       "path":"addresses[type eq \"work\"].streetAddress",
> |       "value":"100 Universal City Plaza"
> |     },
> |     {
> |       "op":"replace",
> |       "path":"addresses[type eq \"work\"].streetAddress",
> |       "value":"911 Universal City Plaza"
>     }
> |   ]
> 
> 
> }}}
> 
> -- 
> -------------------------+-------------------------------------------------
> Reporter:               |       Owner:  [email-masked]
>  [email-masked]|      Status:  new
>     Type:  task         |   Milestone:
> Priority:  major        |     Version:
> Component:  api          |  Resolution:
> Severity:  -            |
> Keywords:               |
> -------------------------+-------------------------------------------------
> 
> Ticket URL: <http://trac.tools.ietf.org/wg/scim/trac/ticket/18#comment:3>
> scim <http://tools.ietf.org/scim/>
>