| TOC |
|
The Simple Cloud Identity Management (SCIM) specification is designed to make managing user identity in cloud based applications and services easier. The specification suite seeks to build upon experience with existing schemas and deployments, placing specific emphasis on simplicity of development and integration, while applying existing authentication, authorization, and privacy models. It's intent is to reduce the cost and complexity of user management operations by providing a common user schema and extension model, as well as binding documents to provide patterns for exchanging this schema using standard protocols. In essence, make it fast, cheap, and easy to move users in to, out of, and around the cloud.
1.
Introduction and Overview
1.1.
Intended Audience
1.2.
Notational Conventions
1.3.
Definitions
2.
Authentication and Authorization
3.
API
3.1.
Creating Resources
3.2.
Retrieving Resources
3.2.1.
Retrieving a known Resource
3.2.2.
List/Query Resources
3.3.
Modifying Resources
3.3.1.
Modifying with PUT
3.3.2.
Modifying with PATCH
3.4.
Deleting Resources
3.5.
Bulk
3.6.
Data Input/Output Formats
3.7.
Additional retrieval query parameters
3.8.
Attribute Notation
3.9.
HTTP Response Codes
3.10.
API Versioning
3.11.
Versioning Resources
3.12.
HTTP Method Overloading
4.
Security Considerations
5.
Contributors
6.
Acknowledgments
§
Authors' Addresses
| TOC |
The SCIM Protocol is an application-level, REST protocol for provisioning and managing identity data on the web. The protocol supports creation, modification, retrieval, and discovery of core identity Resources; i.e., Users and Groups, as well as custom Resource extensions.
| TOC |
This document is intended as a guide to SCIM API usage for both identity Service Providers and Consumers.
| TOC |
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC2119]. These keywords are capitalized when used to unambiguously specify requirements of the protocol or application features and behavior that affect the interoperability and security of implementations. When these words are not capitalized, they are meant in their natural-language sense.
For purposes of readability examples are not URL encoded. Implementers MUST percent encode URLs as described in RFC3896 2.1.
| TOC |
- Base URL:
- The SCIM REST API is always relative to a Base URL. The Base URL MUST NOT contain a query string as Consumers may append additional path information and query parameters as part of forming the request. Example: https://example.com/scim/v1/
| TOC |
The SCIM protocol does not define a scheme for authentication and authorization therefore implementers are free to choose mechanisms appropriate to their use cases. The choice of authentication mechanism will impact interoperability. It is RECOMMENDED that clients be implemented in such a way that new authentication schemes can be deployed. Implementers SHOULD support existing authentication/authorization schemes. In particular, OAuth2 Bearer Token is RECOMMENDED. Appropriate security considerations of the selected authentication and authorization schemes SHOULD be taken. Because this protocol uses HTTP response status codes as the primary means of reporting the result of a request, servers are advised to respond to unauthorized or unauthenticated requests using the 401 response code in accordance with section 10.4.2 of RFC2616.
All examples assume OAuth2 bearer token; e.g.,
GET /Users/2819c223-7f76-453a-919d-413861904646 HTTP/1.1 Host: example.com Authorization: Bearer h480djs93hd8
The context of the request (i.e. the user for whom data is being requested) MUST be inferred by Service Providers.
| TOC |
The SCIM protocol specifies well known endpoints and HTTP methods for managing Resources defined in the core schema; i.e., User and Group Resources correspond to /Users and /Groups respectively. Service Providers that support extended Resources SHOULD define Resource endpoints using the established convention; pluralize the Resource name defined in the extended schema by appending an 's'. Given there are cases where Resource pluralization is ambiguous; e.g., a Resource named 'person' is legitimately 'persons' and 'people' Consumers SHOULD discover Resource endpoints via the Schema Sub-Attribute 'endpoint'.
- GET
- Retrieves a complete or partial Resource.
- POST
- Create new Resource or bulk modify Resources.
- PUT
- Modifies a Resource with a complete, Consumer specified Resource (replace).
- PATCH
- Modifies a Resource with a set of Consumer specified changes (partial update).
- DELETE
- Deletes a Resource.
| Resource | Endpoint | Operations | Description |
|---|---|---|---|
| User | /Users | GET (Retrieving a known Resource), POST (Creating Resources), PUT (Modifying with PUT), PATCH (Modifying with PATCH), DELETE (Deleting Resources) | Retrieve/Add/Modify Users |
| Group | /Groups | GET (Retrieving a known Resource), POST (Creating Resources), PUT (Modifying with PUT), PATCH (Modifying with PATCH), DELETE (Deleting Resources) | Retrieve/Add/Modify Groups |
| Service Provider Configuration | /ServiceProviderConfigs | GET (Retrieving a known Resource) | Retrieve the Service Provider's Configuration |
| Schema | /Schemas | GET (Retrieving a known Resource) | Retrieve a Resource's Schema |
| Bulk | /Bulk | POST (Bulk) | Bulk modify Resources |
| Table 1: Defined endpoints |
All requests to the Service Provider are made via HTTP operations on a URL derived from the Base URL. Responses are returned in the body of the HTTP response, formatted as JSON or XML, depending on what is requested. Response and error codes SHOULD be transmitted via the HTTP status code of the response (if possible), and SHOULD also be specified in the body of the response.
| TOC |
To create new Resources, clients send POST requests to the Resource endpoint; i.e., /Users or /Groups.
Successful Resource creation is indicated with a 201 ("Created") response code. Upon successful creation, the response body MUST contain the newly created Resource. Since the server is free to alter and/or ignore POSTed content, returning the full representation can be useful to the client, enabling it to correlate the client and server views of the new Resource. When a Resource is created, its URI must be returned in the response Location header.
Below, the client sends a POST request containing a User
POST /Users HTTP/1.1 Host: example.com Accept: application/json Authorization: Bearer h480djs93hd8 Content-Length: ... { "schemas":["urn:scim:schemas:core:1.0"], "userName":"dschrute", "externalId":"dschrute", "name":{ "formatted":"Mr. Dwight Kurt Schrute III", "familyName":"Schrute", "givenName":"Dwight" } }
The server signals a successful creation with a status code of 201. The response includes a Location header indicating the User URI, and a representation of that User in the body of the response.
HTTP/1.1 201 Created Content-Type: application/json Location: https://example.com/v1/Users/2819c223-7f76-453a-919d-413861904646 ETag: W/"e180ee84f0671b1" { "schemas":["urn:scim:schemas:core:1.0"], "id":"2819c223-7f76-453a-919d-413861904646", "externalId":"dschrute", "meta":{ "created":"2011-08-01T21:32:44.882Z", "lastModified":"2011-08-01T21:32:44.882Z", "location":"https://example.com/v1/Users/2819c223-7f76-453a-919d-413861904646", "version":"W\/\"e180ee84f0671b1\"" }, "name":{ "formatted":"Mr. Dwight Kurt Schrute III", "familyName":"Schrute", "givenName":"Dwight" }, "userName":"dschrute" }
| TOC |
Users and Group Resources are retrieved via opaque, unique URLs or via Query. Service Providers MAY choose to respond with a sub-set of Resource attributes, though MUST minimally return the Resource id and meta attributes.
| TOC |
To retrieve a known Resource, clients send GET requests to the Resource endpoint; e.g., /Users/{id} or /Groups/{id}.
If the Resource exists the server responds with a status code of 200 and includes the result in the body of the response.
The below example retrieves a single User via the /Users endpoint.
GET /Users/2819c223-7f76-453a-919d-413861904646 Host: example.com Accept: application/json Authorization: Bearer h480djs93hd8
The server responds with:
HTTP/1.1 200 OK Content-Type: application/json Location: https://example.com/v1/Users/2819c223-7f76-453a-919d-413861904646 ETag: W/"f250dd84f0671c3" { "schemas":["urn:scim:schemas:core:1.0"], "id":"2819c223-7f76-453a-919d-413861904646, "externalId":"dschrute", "meta":{ "created":"2011-08-01T18:29:49.793Z", "lastModified":"2011-08-01T18:29:49.793Z", "location":"https://example.com/v1/Users/2819c223-7f76-453a-919d-413861904646", "version":"W\/\"f250dd84f0671c3\"" }, "name":{ "formatted":"Mr. Dwight Kurt Schrute III", "familyName":"Schrute", "givenName":"Dwight" }, "userName":"dschrute", "phoneNumbers":[ { "value":"555-555-8377", "type":"work" } ], "emails":[ {<EMAIL_ADDRESS>"type":"work" } ] }
| TOC |
SCIM defines a standard set of operations that can be used to filter, sort, and paginate response results. The operations are specified by adding query parameters to the Resource's endpoint. Service Providers MAY support additional query parameters not specified here, and Providers SHOULD ignore any query parameters they don't recognize.
The below example returns the userName for all Users:
GET /Users?attributes=userName Host: example.com Accept: application/json Authorization: Bearer h480djs93hd8
HTTP/1.1 200 OK Content-Type: application/json { "totalResults":2, "schemas":["urn:scim:schemas:core:1.0"], "Resources":[ { "userName":"dschrute" }, { "userName":"jsmith" } ] }
| TOC |
Filtering is OPTIONAL. Consumers may request a subset of Resources by specifying the 'filter' URL query parameter containing a filter expression. When specified only those Resources matching the filter expression SHALL be returned. The expression language that is used in the filter parameter supports references to attributes and literals. The literal values can be strings enclosed in double quotes, numbers, date times enclosed in double quotes, and Boolean values; i.e., true or false. String literals MUST be valid JSON strings.
The attribute name and attribute operator are case insensitive. For example, the following two expressions will evaluate to the same logical value:
filter=userName Eq "john" filter=Username eq "john"
The filter parameter MUST contain at least one valid Boolean expression. Each expression MUST contain an attribute name followed by an attribute operator and optional value. Multiple expressions MAY be combined using the two logical operators. Furthermore expressions can be grouped together using "()".
The operators supported in the expression are listed in the following table.
| Operator | Description | Behavior |
|---|---|---|
| eq | equal | The attribute and operator values must be identical for a match. |
| co | contains | The entire operator value must be a substring of the attribute value for a match. |
| sw | starts with | The entire operator value must be a substring of the attribute value, starting at the beginning of the attribute value. This criterion is satisfied if the two strings are identical. |
| pr | present (has value) | If the attribute has a non-empty value, or if it contains a non-empty node for complex attributes there is a match. |
| gt | greater than | If the attribute value is greater than operator value, there is a match. The actual comparison is dependent on the attribute type. For string attribute types, this is a lexicographical comparison and for DateTime types, it is a chronological comparison. |
| ge | greater than or equal | If the attribute value is greater than or equal to the operator value, there is a match. The actual comparison is dependent on the attribute type. For string attribute types, this is a lexicographical comparison and for DateTime types, it is a chronological comparison. |
| lt | less than | If the attribute value is less than operator value, there is a match. The actual comparison is dependent on the attribute type. For string attribute types, this is a lexicographical comparison and for DateTime types, it is a chronological comparison. |
| le | less than or equal | If the attribute value is less than or equal to the operator value, there is a match. The actual comparison is dependent on the attribute type. For string attribute types, this is a lexicographical comparison and for DateTime types, it is a chronological comparison. |
| Table 2: Attribute
Operators |
| Operator | Description | Behavior |
|---|---|---|
| and | Logical And | The filter is only a match if both expressions evaluate to true. |
| or | Logical or | The filter is a match if either expression evaluates to true. |
| Table 3: Logical
Operators |
| Operator | Description | Behavior |
|---|---|---|
| () | Precedence grouping | Boolean expressions may be grouped using parentheses to change the standard order of operations; i.e., evaluate OR logical operators before logical AND operators. |
| Table 4: Grouping
Operators |
Filters MUST be evaluated using standard order of operations. Attribute operators have the highest precedence, followed by the grouping operator (i.e, parentheses), followed by the logical AND operator, followed by the logical OR operator.
If the specified attribute in a filter expression is a multi-valued attribute, the Resource MUST match if any of the instances of the given attribute match the specified criterion; e.g. if a User has multiple emails values, only one has to match for the entire User to match. For complex attributes, a fully qualified Sub-Attribute MUST be specified using standard attribute notation (Attribute Notation). For example, to filter by userName the parameter value is userName and to filter by first name, the parameter value is name.givenName.
Providers MAY support additional filter operations if they choose. Providers MUST decline to filter results if the specified filter operation is not recognized and return a HTTP 400 error with an appropriate human readable response. For example, if a Consumer specified an unsupported operator named 'regex' the Service Provider should specify an error response description identifying the Consumer error; e.g., 'The operator 'regex' is not supported.'
String type attributes are case insensitive by default unless the attribute type is defined as a caseExact string. Attribute operators 'eq', 'co', and 'sw' MUST perform caseIgnore matching for all string attributes unless the attribute is defined as caseExact. By default all string attributes are caseIgnore.
Examples:
filter=userName eq "dschrute" filter=name.familyName co "O'Malley" filter=userName sw "J" filter=title pr filter=meta.lastModified gt "2011-05-13T04:42:34Z" filter=meta.lastModified ge "2011-05-13T04:42:34Z" filter=meta.lastModified lt "2011-05-13T04:42:34Z" filter=meta.lastModified le "2011-05-13T04:42:34Z" filter=title pr and userType eq "Employee" filter=title pr or userType eq "Intern" filter=userType eq "Employee" and (emails co "example.com" or emails co "example.org")
| TOC |
Sort is OPTIONAL. Sorting allows Consumers to specify the order in which Resources are returned by specifying a combination of sortBy and sortOrder URL parameters.
- sortBy:
- The sortBy parameter specifies the attribute whose value SHALL be used to order the returned responses. If the sortBy attribute corresponds to a Singular Attribute, Resources are sorted according to that attribute's value; if it's a Multi-valued Attribute, Resources are sorted by the value of the primary attribute, if any, or else the first value in the list, if any. If the attribute is complex the attribute name must be a path to a Sub-Attribute in standard attribute notation (Attribute Notation) ; e.g., sortBy=name.givenName. For all attribute types, if there is no data for the specified sortBy value they are sorted via the 'sortOrder' parameter; i.e., they are ordered last if ascending and first if descending.
- sortOrder:
- The order in which the sortBy parameter is applied. Allowed values are "ascending" and "descending". If a value for sortBy is provided and no sortOrder is specified, the sortOrder SHALL default to ascending. String type attributes are case insensitive by default unless the attribute type is defined as a caseExact string. sortOrder MUST sort according to the attribute type; i.e., for caseIgnore attributes, sort the result using case insensitive, Unicode alphabetic sort order, with no specific locale implied and for caseExact attribute types, sort the result using case sensitive, Unicode alphabetic sort order.
| TOC |
Pagination parameters can be used together to "page through" large numbers of Resources so as not to overwhelm the Consumer or Service Provider. Pagination is not session based hence Consumers SHOULD never assume repeatable results. For example, a request for a list of 10 Resources beginning with a startIndex of 1 may return different results when repeated as a Resource in the original result could be deleted or new ones could be added in-between requests. Pagination parameters and general behavior are derived from the OpenSearch Protocol.
The following table describes the URL pagination parameters.
| Parameter | Description | Default |
|---|---|---|
| startIndex | The 1-based index of the first search result. | 1 |
| count | Non-negative Integer. Specifies the desired maximum number of search results per page; e.g., 10. | None. When specified the Service Provider MUST not return more results than specified though MAY return fewer results. If unspecified, the maximum number of results is set by the Service Provider. |
| Table 5: Pagination Request parameters |
The following table describes the query response pagination attributes specified by the Service Provider.
| Element | Description |
|---|---|
| itemsPerPage | Non-negative Integer. Specifies the number of search results returned in a query response page; e.g., 10. |
| totalResults | Non-negative Integer. Specifies the total number of results matching the Consumer query; e.g., 1000. |
| startIndex | The 1-based index of the first result in the current set of search results; e.g., 1. |
| Table 6: Pagination Response Elements |
For example, to retrieve the first 10 Users set the startIndex to 1 and the count to 10.
GET /Users?startIndex=1&count=10 Host: example.com Accept: application/json Authorization: Bearer h480djs93hd8
{ "totalResults":100, "itemsPerPage":10, "startIndex":1, "schemas":["urn:scim:schemas:core:1.0"], "Resources":[{ ... }] }
Given the example above, to continue paging set the startIndex to 11 and re-fetch; i.e., /Users?startIndex=11&count=10
| TOC |
Resources can be modified in whole or in part via PUT or PATCH, respectively. Implementers MUST support PUT as specified in RFC2616 . Resources such as Groups may be very large hence implementers SHOULD support PATCH to enable partial resource modifications.
| TOC |
PUT performs a full update. Consumers must retrieve the entire Resource and PUT the desired modifications as the operation overwrites all previously stored data. Unless otherwise specified a successful PUT operation returns a 200 OK response code and the entire Resource within the response body. Example:
PUT /Users/2819c223-7f76-453a-919d-413861904646 Host: example.com Accept: application/json Authorization: Bearer h480djs93hd8 ETag: W/"a330bc54f0671c9" { "schemas":["urn:scim:schemas:core:1.0"], "id":"2819c223-7f76-453a-919d-413861904646", "userName":"dschrute", "externalId":"dschrute", "name":{ "formatted":"Mr. Dwight Kurt Schrute III", "familyName":"Schrute", "givenName":"Dwight", "middleName":"Kurt" }, "emails":[ {<EMAIL_ADDRESS>}, {<EMAIL_ADDRESS>} ] }
The service responds with the entire, updated User
HTTP/1.1 200 OK Content-Type: application/json ETag: W/"b431af54f0671a2" Location:"https://example.com/v1/Users/2819c223-7f76-453a-919d-413861904646" { "schemas":["urn:scim:schemas:core:1.0"], "id":"2819c223-7f76-453a-919d-413861904646", "userName":"dschrute", "externalId":"dschrute", "name":{ "formatted":"Mr. Dwight Kurt Schrute III", "familyName":"Schrute", "givenName":"Dwight", "middleName":"Kurt" }, "emails":[ {<EMAIL_ADDRESS>}, {<EMAIL_ADDRESS>} ], "meta": { "created":"2011-08-08T04:56:22Z", "lastModified":"2011-08-08T08:00:12Z", "location":"https://example.com/v1/Users/2819c223-7f76-453a-919d-413861904646", "version":"W\/\"b431af54f0671a2\"" } }
| TOC |
PATCH is OPTIONAL. PATCH enables consumers 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 (Additional retrieval query parameters)) 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 server MUST process a PATCH request by first removing any attributes specified in the meta.attributes Sub-Attribute (if present) and then merging the attributes in the PATCH request body into the Resource.
The meta.attributes Sub-Attribute MAY contain a list of attributes to be removed from the Resource. If the PATCH request body contains an attribute that is present in the meta.attributes list, the attribute on the Resource is replaced with the value from the PATCH body. If the attribute is complex the attribute name must be a path to a Sub-Attribute in standard attribute notation (Attribute Notation); e.g., name.givenName.
Attributes that exist in the PATCH request body but not in the meta.attributes Sub-Attribute will be either be updated or added to the Resource according to the following rules.
- Singular attributes:
- Singular attributes in the PATCH request body replace the attribute on the Resource.
- Complex attributes:
- Complex Sub-Attribute values in the PATCH request body are merged into the complex attribute on the Resource.
- Multi-valued attributes:
- An attribute value in the PATCH request body is added to the value collection if the value does not exist and merged if a matching value is present. Values are matched by comparing the value Sub-Attribute from the PATCH request body to the value Sub-Attribute of the Resource. Attributes that do not have a value Sub-Attribute; e.g., addresses, or do not have unique value Sub-Attributes cannot be matched and must instead be deleted then added. Specific values can be removed from a Resource by adding an "operation" Sub-Attribute with the value "delete" to the attribute in the PATCH request body. As with adding/updating attribute value collections, the value to delete is determined by comparing the value Sub-Attribute from the PATCH request body to the value Sub-Attribute of the Resource. Attributes that do not have a value Sub-Attribute or that have a non-unique value Sub-Attribute are matched by comparing all Sub-Attribute values from the PATCH request body to the Sub-Attribute values of the Resource. A delete operation is ignored if the attribute's name is in the meta.attributes list. If the requested value to delete does not match a unique value on the Resource the server MAY return a HTTP 400 error.
The following example shows how to add a member to a group:
PATCH /Groups/acbf3ae7-8463-4692-b4fd-9b4da3f908ce Host: example.com Accept: application/json Authorization: Bearer h480djs93hd8 ETag: W/"a330bc54f0671c9" { "schemas": ["urn:scim:schemas:core:1.0"], "members": [ { "display": "Dwight Schrute", "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/v1/Groups/acbf3ae7-8463-4692-b4fd-9b4da3f908ce"
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.
PATCH /Groups/acbf3ae7-8463-4692-b4fd-9b4da3f908ce Host: example.com Accept: application/json Authorization: Bearer h480djs93hd8 ETag: W/"a330bc54f0671c9" { "schemas": ["urn:scim:schemas:core:1.0"], "members": [ { "display": "Dwight Schrute", "value": "2819c223-7f76-453a-919d-413861904646" "operation": "delete" } ] }
The following example shows how to remove all members from a group:
PATCH /Groups/acbf3ae7-8463-4692-b4fd-9b4da3f908ce Host: example.com Accept: application/json Authorization: Bearer h480djs93hd8 ETag: W/"a330bc54f0671c9" { "schemas": ["urn:scim:schemas:core:1.0"], "meta": { "attributes": [ "members" ] } }
The following example shows how to replace all of the members of a group with a different members list:
PATCH /Groups/acbf3ae7-8463-4692-b4fd-9b4da3f908ce Host: example.com Accept: application/json Authorization: Bearer h480djs93hd8 ETag: W/"a330bc54f0671c9" { "schemas": ["urn:scim:schemas:core:1.0"], "meta": { "attributes": [ "members" ] }, "members": [ { "display": "Dwight Schrute", "value": "2819c223-7f76-453a-919d-413861904646" }, { "display": "James Smith", "value": "08e1d05d-121c-4561-8b96-473d93df9210" } ] }
The following example shows how to add a member to and remove a member from a Group in a single request:
PATCH /Groups/acbf3ae7-8463-4692-b4fd-9b4da3f908ce Host: example.com Accept: application/json Authorization: Bearer h480djs93hd8 ETag: W/"a330bc54f0671c9" { "schemas": ["urn:scim:schemas:core:1.0"], "members": [ { "display": "Dwight Schrute", "value": "2819c223-7f76-453a-919d-413861904646" "operation": "delete" }, { "display": "James Smith", "value": "08e1d05d-121c-4561-8b96-473d93df9210" } ] }
The following example shows how to change a User's primary email. If the User already has the email address, it is made the primary address and the current primary address (if present) is made non-primary. If the User does not already have the email address, it is added and made the primary address.
PATCH /Users/2819c223-7f76-453a-919d-413861904646 Host: example.com Accept: application/json Authorization: Bearer h480djs93hd8 ETag: "a330bc54f0671c9" { "schemas": ["urn:scim:schemas:core:1.0"], "emails": [ { "value"<EMAIL_ADDRESS>"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 Authorization: Bearer h480djs93hd8 ETag: W/"a330bc54f0671c9" { "schemas": ["urn:scim:schemas:core:1.0"], "addresses": [ { "type": "work", "streetAddress": "100 Universal City Plaza", "locality": "Hollywood", "region": "CA", "postalCode": "91608", "country": "US", "formatted": "100 Universal City Plaza\nHollywood, CA 91608 US", "primary": true "operation": "delete" }, { "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 nickname:
PATCH /Users/2819c223-7f76-453a-919d-413861904646 Host: example.com Accept: application/json Authorization: Bearer h480djs93hd8 ETag: W/"a330bc54f0671c9" { "schemas": ["urn:scim:schemas:core:1.0"], "nickName": "Barbie" }
The following example shows how to remove a User's nickname:
PATCH /Users/2819c223-7f76-453a-919d-413861904646 Host: example.com Accept: application/json Authorization: Bearer h480djs93hd8 ETag: W/"a330bc54f0671c9" { "schemas": ["urn:scim:schemas:core:1.0"], "meta": { "attributes": [ "nickName" ] } }
The following example shows how to change a User's familyName. This only updates the familyName and formatted on the "name" complex attribute. Any other name Sub-Attributes on the Resource remain unchanged.
PATCH /Users/2819c223-7f76-453a-919d-413861904646 Host: example.com Accept: application/json Authorization: Bearer h480djs93hd8 ETag: W/"a330bc54f0671c9" { "schemas": ["urn:scim:schemas:core:1.0"], "name": { "formatted": "Mr. Dwight Kurt Schrute III", "familyName": "Schrute" } }
The following example shows how to remove a complex Sub-Attribute and an extended schema attribute from a User.
PATCH /Users/2819c223-7f76-453a-919d-413861904646 Host: example.com Accept: application/json Authorization: Bearer h480djs93hd8 ETag: W/"a330bc54f0671c9" { "schemas": ["urn:scim:schemas:core:1.0"], "meta": { "attributes": [ "name.formatted", "urn:hr:schemas:user:age" ] } }
| TOC |
Consumers request Resource removal via DELETE. Service Providers MAY choose not to permanently delete the Resource, but MUST return a 404 error code for all operations associated with the previously deleted Id. Service Providers MUST also omit the Resource from future query results.
DELETE /Users/2819c223-7f76-453a-919d-413861904646 Host: example.com Authorization: Bearer h480djs93hd8 ETag: W/"c310cd84f0281b7"
HTTP/1.1 200 OK
Example: Consumer attempt to retrieve the previously deleted User
GET /Users/2819c223-7f76-453a-919d-413861904646 Host: example.com Authorization: Bearer h480djs93hd8
HTTP/1.1 404 NOT FOUND { "Errors":[ { "description":"Resource 2819c223-7f76-453a-919d-413861904646 not found", "code":"404" } ] }
| TOC |
Bulk is OPTIONAL. The bulk operation enables Consumers to send a potentially large collection of Resource operations in a single request. The body of a a bulk operation contains a set of HTTP Resource operations using one of the API supported HTTP methods; i.e., POST, PUT, PATCH or DELETE.
The following Singular Attribute is defined in addition to the common attributes defined in SCIM core schema.
- failOnErrors
- An Integer specifying the number of errors that the Service Provider will accept before the operation is terminated and an error response is returned. OPTIONAL.
The following Complex Multi-valued Attribute is defined in addition to the common attributes defined in core schema.
- Operations
- Defines operations within a bulk job. Each operation corresponds to a single HTTP request against a Resource endpoint. REQUIRED.
- method
- The HTTP method of the current operation. Possible values are POST, PUT, PATCH or DELETE. REQUIRED.
- bulkId
- The transient identifier of a newly created Resource, unique within a bulk request and created by the Consumer. The bulkId serves as a surrogate Resource id enabling Consumers to uniquely identify newly created Resources in the Response and cross reference new Resources in and across operations within a bulk request. REQUIRED when method is POST.
- version
- The current Resource version. Version is REQUIRED if the Service Provider supports ETags and the method is PUT, DELETE, or PATCH.
- path
- The Resource's relative path. If the method is POST the value must specify a Resource type endpoint; e.g., /Users or /Groups whereas all other method values must specify the path to a specific Resource; e.g., /Users/2819c223-7f76-453a-919d-413861904646. REQUIRED in a request.
- data
- The Resource data as it would appear for a single POST, PUT or PATCH Resource operation. REQUIRED in a request when method is POST, PUT and PATCH.
- location
- The Resource endpoint URL. REQUIRED in a response, except in the event of a POST failure.
- status
- A complex type that contains information about the success or failure of one operation within the bulk job. REQUIRED in a response.
- code
- The HTTP response code that would have been returned if a a single HTTP request would have been used. REQUIRED.
- description
- A human readable error message. REQUIRED when an error occurred.
If a bulk job is processed successfully the HTTP response code 200 OK MUST be returned, otherwise an appropriate HTTP error code MUST be returned.
The Service Provider MUST continue performing as many changes as possible and disregard partial failures. The Consumer MAY override this behavior by specifying a value for failOnErrors attribute. The failOnErrors attribute defines the number of errors that the Service Provider should accept before failing the remaining operations returning the response.
To be able to reference a newly created Resource the attribute bulkId MUST be specified when creating new Resources. The bulkId is defined by the Consumer as a surrogate identifier in a POST operation. The Service Provider MUST return the same bulkId together with the newly created Resource. The bulkId can then be used by the Consumer to map the Service Provider id with the bulkId of the created Resource.
There can be more then one operation per Resource in each bulk job. The Service Consumer MUST take notice of the unordered structure of JSON and the Service Provider can process operations in any order. For example, if the Service Consumer sends two PUT operations in one request, the outcome is non-deterministic.
The Service Provider response MUST include the result of all processed operations. A location attribute that includes the Resource's end point MUST be returned for all operations excluding failed POSTs. The status attribute includes information about the success or failure of one operation within the bulk job. The attribute status MUST include the code attribute that holds the HTTP response code that would have been returned if a single HTTP request would have been used. If an error occurred the status MUST also include the description attribute containing a human readable explanation of the error.
"status": { "code": "201" }
The following is an example of a status in a failed operation.
"status": { "code": "400", "description": "Request is unparseable, syntactically incorrect, or violates schema." }
The following example shows how to add, update, and remove a user. The failOnErrors attribute is set to '1' indicating the Service Provider should return on the first error. The POST operation's bulkId value is set to 'qwerty' enabling the Consumer to match the new User with the returned Resource id '92b725cd-9465-4e7d-8c16-01f8e146b87a'.
POST /v1/Bulk Host: example.com Accept: application/json Authorization: Bearer h480djs93hd8 Content-Length: ... { "schemas":[ "urn:scim:schemas:core:1.0" ], "failOnErrors":1, "Operations":[ { "method":"POST", "path":"/Users", "bulkId":"qwerty", "data":{ "schemas":[ "urn:scim:schemas:core:1.0" ], "userName":"Alice" } }, { "method":"PUT", "path":"/Users/b7c14771-226c-4d05-8860-134711653041", "version":"W\/\"3694e05e9dff591\"", "data":{ "schemas":[ "urn:scim:schemas:core:1.0" ], "id":"b7c14771-226c-4d05-8860-134711653041", "userName":"Bob" } }, { "method":"PATCH", "path":"/Users/5d8d29d3-342c-4b5f-8683-a3cb6763ffcc", "version":"W\/\"edac3253e2c0ef2\"", "data":{ "schemas":[ "urn:scim:schemas:core:1.0" ], "id":"5d8d29d3-342c-4b5f-8683-a3cb6763ffcc", "userName":"Dave", "meta":{ "attributes":[ "nickName" ] } } }, { "method":"DELETE", "path":"/Users/e9025315-6bea-44e1-899c-1e07454e468b", "version":"W\/\"0ee8add0a938e1a\"" } ] }
The Service Provider returns the following response.
HTTP/1.1 200 OK Content-Type: application/json { "schemas": [ "urn:scim:schemas:core:1.0" ], "Operations": [ { "location": "https://example.com/v1/Users/92b725cd-9465-4e7d-8c16-01f8e146b87a", "method": "POST", "bulkId": "qwerty", "version": "W\/\"oY4m4wn58tkVjJxK\"", "status": { "code": "201" } }, { "location": "https://example.com/v1/Users/b7c14771-226c-4d05-8860-134711653041", "method": "PUT", "version": "W\/\"huJj29dMNgu3WXPD\"", "status": { "code": "200" } }, { "location": "https://example.com/v1/Users/5d8d29d3-342c-4b5f-8683-a3cb6763ffcc", "method": "PATCH", "version": "W\/\"huJj29dMNgu3WXPD\"", "status": { "code": "200" } }, { "location": "https://example.com/v1/Users/e9025315-6bea-44e1-899c-1e07454e468b", "method": "DELETE", "status": { "code": "200" } } ] }
The following response is returned if an error occurred when attempting to create the User 'Alice'. The Service Provider stops processing the bulk operation and immediately returns a response to the Consumer. The response contains the error and any successful results prior to the error.
HTTP/1.1 200 OK Content-Type: application/json { "schemas": [ "urn:scim:schemas:core:1.0" ], "Operations": [ { "method": "POST", "bulkId": "qwerty", "status": { "code": "400", "description": "Request is unparseable, syntactically incorrect, or violates schema." } } ] }
If the failOnErrors attribute is not specified or the Service Provider has not reached the error limit defined by the Consumer the Service Provider will continue to process all operations. The following is an example in which all operations failed.
HTTP/1.1 200 OK Content-Type: application/json { "schemas": [ "urn:scim:schemas:core:1.0" ], "Operations": [ { "method": "POST", "bulkId": "qwerty", "status": { "code": "400", "description": "Request is unparseable, syntactically incorrect, or violates schema." } }, { "location": "https://example.com/v1/Users/b7c14771-226c-4d05-8860-134711653041", "method": "PUT", "status": { "code": "412", "description": "Failed to update as user changed on the server since you last retrieved it." } }, { "location": "https://example.com/v1/Users/5d8d29d3-342c-4b5f-8683-a3cb6763ffcc", "method": "PATCH", "status": { "code": "412", "description": "Failed to update as user changed on the server since you last retrieved it." } }, { "location": "https://example.com/v1/Users/e9025315-6bea-44e1-899c-1e07454e468b", "method": "DELETE", "status": { "code": "404", "description": "Specified resource; e.g., User, does not exist." } } ] }
The Consumer can, within one bulk operation, create a new User, a new Group and add the newly created User to the newly created Group. In order to add the new User to the Group the Consumer must use the surrogate id attribute, bulkId, to reference the User. The bulkId attribute value must be pre-pended with the literal "bulkId:"; e.g., if the bulkId is 'qwerty' the value is “bulkId:qwerty”. The Service Provider MUST replace the string “bulkId:qwerty” with the permanent Resource id once created.
The following example creates a User with the userName 'Alice' and a Group with the displayName 'Sales Reps' with Alice as a member.
POST /v1/Bulk Host: example.com Accept: application/json Authorization: Bearer h480djs93hd8 Content-Length: ... { "schemas": [ "urn:scim:schemas:core:1.0" ], "Operations": [ { "method": "POST", "path": "/Users", "bulkId": "qwerty", "data": { "schemas": [ "urn:scim:schemas:core:1.0" ], "userName": "Alice" } }, { "method": "POST", "path": "/Groups", "bulkId": "ytrewq", "data": { "schemas": [ "urn:scim:schemas:core:1.0" ], "displayName": "Sales Reps", "members": [ { "type": "user", "value": "bulkId:qwerty" } ] } } ] }
The Service Provider returns the following response.
HTTP/1.1 200 OK Content-Type: application/json { "schemas": [ "urn:scim:schemas:core:1.0" ], "Operations": [ { "location": "https://example.com/v1/Users/92b725cd-9465-4e7d-8c16-01f8e146b87a", "method": "POST", "bulkId": "qwerty", "version": "W\/\"4weymrEsh5O6cAEK\"", "status": { "code": "201" } }, { "location": "https://example.com/v1/Groups/e9e30dba-f08f-4109-8486-d5c6a331660a", "method": "POST", "bulkId": "ytrewq", "version": "W\/\"lha5bbazU3fNvfe5\"", "status": { "code": "201" } } ] }
A subsequent request for the 'Sales Reps' Group ('e9e30dba-f08f-4109-8486-d5c6a331660a') returns the following:
GET /v1/Groups/e9e30dba-f08f-4109-8486-d5c6a331660a Host: example.com Accept: application/json Authorization: Bearer h480djs93hd8
HTTP/1.1 200 OK Content-Type: application/json Location: https://example.com/v1/Groups/e9e30dba-f08f-4109-8486-d5c6a331660a ETag: W/"lha5bbazU3fNvfe5" { "schemas":["urn:scim:schemas:core:1.0"], "id": "e9e30dba-f08f-4109-8486-d5c6a331660a", "displayName": "Sales Reps", "meta": { "created":"2011-08-01T18:29:49.793Z", "lastModified":"2011-08-01T20:31:02.315Z", "location": "https://example.com/v1/Groups/e9e30dba-f08f-4109-8486-d5c6a331660a", "version": "W\/\"lha5bbazU3fNvfe5\"" }, "members": [ { "value": "92b725cd-9465-4e7d-8c16-01f8e146b87a", "type": "user" } ] }
Extensions that include references to other Resources MUST be handled in the same way by the Service Provider. The following example uses the bulkId attribute within the enterprise extension managerId attribute.
POST /v1/Bulk Host: example.com Accept: application/json Authorization: Bearer h480djs93hd8 Content-Length: ... { "schemas": [ "urn:scim:schemas:core:1.0" ], "Operations": [ { "method": "POST", "path": "/Users", "bulkId": "qwerty", "data": { "schemas": [ "urn:scim:schemas:core:1.0" ], "userName": "Alice" } }, { "method": "POST", "path": "/Users", "bulkId": "ytrewq", "data": { "schemas": [ "urn:scim:schemas:core:1.0", "urn:scim:schemas:extension:enterprise:1.0" ], "userName": "Bob", "urn:scim:schemas:extension:enterprise:1.0": { "employeeNumber": "11250", "manager": { "managerId": "batchId:qwerty", "displayName": "Alice" } } } } ] }
The Service Provider MUST try to resolve circular cross references between Resources in a single bulk job but MAY stop after a failed attempt and instead return the status code 409 Conflict. The following example exhibits the potential conflict.
POST /v1/Bulk Host: example.com Accept: application/json Authorization: Bearer h480djs93hd8 Content-Length: ... { "schemas": [ "urn:scim:schemas:core:1.0" ], "Operations": [ { "method": "POST", "path": "/Groups", "bulkId": "qwerty", "data": { "schemas": [ "urn:scim:schemas:core:1.0" ], "displayName": "Group A", "members": [ { "type": "group", "value": "bulkId:ytrewq" } ] } }, { "method": "POST", "path": "/Groups", "bulkId": "ytrewq", "data": { "schemas": [ "urn:scim:schemas:core:1.0" ], "displayName": "Group B", "members": [ { "type": "group", "value": "bulkId:qwerty" } ] } } ] }
If the Service Provider resolved the above circular references the following is returned from a subsequent GET request.
GET /v1/Groups?filter=displayName sw 'Group' Host: example.com Accept: application/json Authorization: Bearer h480djs93hd8
HTTP/1.1 200 OK Content-Type: application/json { "totalResults": 2, "schemas": [ "urn:scim:schemas:core:1.0" ], "Resources": [ { "id": "c3a26dd3-27a0-4dec-a2ac-ce211e105f97", "schemas": [ "urn:scim:schemas:core:1.0" ], "displayName": "Group A", "meta": { "created":"2011-08-01T18:29:49.793Z", "lastModified":"2011-08-01T18:29:51.135Z", "location":"https://example.com/v1/Groups/c3a26dd3-27a0-4dec-a2ac-ce211e105f97", "version":"W\/\"mvwNGaxB5SDq074p\"" }, "members": [ { "value": "6c5bb468-14b2-4183-baf2-06d523e03bd3", "type": "group" } ] }, { "id": "6c5bb468-14b2-4183-baf2-06d523e03bd3", "schemas": [ "urn:scim:schemas:core:1.0" ], "displayName": "Group B", "meta": { "created":"2011-08-01T18:29:50.873Z", "lastModified":"2011-08-01T18:29:50.873Z", "location":"https://example.com/v1/Groups/6c5bb468-14b2-4183-baf2-06d523e03bd3", "version":"W\/\"wGB85s2QJMjiNnuI\"" }, "members": [ { "value": "c3a26dd3-27a0-4dec-a2ac-ce211e105f97", "type": "group" } ] } ] }
The Service Provider MUST define a limit on how many operations can be sent in one bulk request. The Service Provider MUST also define the max payload size of a bulk request. If either limits are exceeded the Service Provider MUST return the HTTP response code 413 Request Entity Too Large. The returned response must also include the attributes maxOperations and maxPayloadSize with the limits accepted by the Service Provider.
In the following example the Consumer sent a request that exceeded the Service Provider's max payload size 1 megabyte.
POST /v1/Bulk Host: example.com Accept: application/json Authorization: Bearer h480djs93hd8 Content-Length:<PHONE_NUMBER> …
HTTP/1.1 413 Request Entity Too Large Content-Type: application/json Location: https://example.com/v1/Bulk/yfCrVJhFIJagAHj8 { "maxOperations": 1000, "maxPayload": 1048576 }
| TOC |
Consumers MUST specify the format in which the data is submitted via the HTTP header content-type and MAY specify the desired response data format via an HTTP Accept Header; e.g.,"Accept: application/json" or via URI suffix; e.g.,
GET /Users/2819c223-7f76-453a-919d-413861904646.json Host: example.com GET /Users/2819c223-7f76-453a-919d-413861904646.xml Host: example.com
Service Providers MUST support the Accept Headers "Accept: application/json" for JSON and, if supported, "Accept: application/xml" for XML. The format defaults to JSON if no format is specified. The data structure returned is equivalent in both formats; the only difference is in the encoding of the data.
Singular attributes are encoded as string name-value-pairs in JSON; e.g.,
"attribute": "value"
and elements in XML; e.g.,
<attribute>value</attribute>
Multi-valued attributes in JSON are encoded as arrays; e.g.,
"attributes": [ "value1", "value2" ]
and repeated tags in XML; e.g.,
<attributes>value1</attributes> <attributes>value2</attributes>
Elements with nested elements are represented as objects in JSON; e.g,
"attribute": { "subattribute1": "value1", "subattribute2": "value2" }
and repeated tags in XML; e.g.,
<attribute> <subattribute1>value1</subattribute1> <subattribute2>value2</subattribute2> </attribute>
| TOC |
Consumers MAY request a partial Resource representation on any operation that returns a Resource within the response by specifying the URL query parameter 'attributes'. When specified, each Resource returned MUST contain the minimal set of Resource attributes and, MUST contain no other attributes or Sub-Attributes than those explicitly requested. The query parameter attributes value is a comma separated list of Resource attribute names in standard, attribute notation (Attribute Notation) form (e.g. userName, name, emails).
GET /Users/2819c223-7f76-453a-919d-413861904646?attributes=userName Host: example.com Accept: application/json Authorization: Bearer h480djs93hd8
Giving the response
HTTP/1.1 200 OK Content-Type: application/json Location: https://example.com/v1/Users/2819c223-7f76-453a-919d-413861904646 ETag: W/"a330bc54f0671c9" { "schemas":["urn:scim:schemas:core:1.0"], "id":"2819c223-7f76-453a-919d-413861904646", "userName":"dschrute", "meta":{ "created":"2011-08-01T18:29:49.793Z", "lastModified":"2011-08-01T18:29:49.793Z", "location":"https://example.com/v1/Users/2819c223-7f76-453a-919d-413861904646", "version":"W\/\"a330bc54f0671c9\"" } }
| TOC |
All operations share a common scheme for referencing simple and complex attributes. In general, attributes are identified by prefixing the attribute name with its schema URN separated by a ':' character; e.g., the core User Resource attribute 'userName' is identified as 'urn:scim:schemas:core:1.0:userName'. Consumers MAY omit core schema attribute URN prefixes though MUST fully qualify extended attributes with the associated Resource URN; e.g., the attribute 'age' defined in 'urn:hr:schemas:user' is fully encoded as 'urn:hr:schemas:user:age'. A Complex attributes' Sub-Attributes are referenced via nested, dot ('.') notation; i.e., {urn}:{Attribute name}.{Sub-Attribute name}. For example, the fully qualified path for a User's givenName is urn:scim:schemas:core:1.0:name.givenName All facets (URN, attribute and Sub-Attribute name) of the fully encoded Attribute name are case insensitive.
| TOC |
The SCIM Protocol uses the response status codes defined in HTTP to indicate operation success or failure. In addition to returning a HTTP response code implementers MUST return the errors in the body of the response in the client requested format containing the error response and, per the HTTP specification, human-readable explanations. Implementers SHOULD handle the identified errors as described below.
| Code | Applicability | Suggested Explanation |
|---|---|---|
| 400 BAD REQUEST | GET,POST,PUT,PATCH,DELETE | Request is unparseable, syntactically incorrect, or violates schema |
| 401 UNAUTHORIZED | GET,POST,PUT,PATCH,DELETE | Authorization failure |
| 403 FORBIDDEN | GET,POST,PUT,PATCH,DELETE | Server does not support requested operation |
| 404 NOT FOUND | GET,PUT,PATCH,DELETE | Specified resource; e.g., User, does not exist |
| 409 CONFLICT | PUT,PATCH,DELETE | The specified version number does not match the resource's latest version number or a Service Provider refused to create a new, duplicate resource |
| 412 PRECONDITION FAILED | PUT,PATCH,DELETE | Failed to update as Resource {id} changed on the server last retrieved |
| 413 REQUEST ENTITY TOO LARGE | POST | {"maxOperations": 1000,"maxPayload": 1048576} |
| 500 INTERNAL SERVER ERROR | GET,POST,PUT,PATCH,DELETE | An internal error. Implementers SHOULD provide descriptive debugging advice |
| 501 NOT IMPLEMENTED | GET,POST,PUT,PATCH,DELETE | Service Provider does not support the request operation; e.g., PATCH |
| Table 7: Defined error cases |
Error example in response to a non-existent GET request.
HTTP/1.1 404 NOT FOUND { "Errors":[ { "description":"Resource 2819c223-7f76-453a-919d-413861904646 not found", "code":"404" } ] }
| TOC |
The Base URL MAY be appended with a version identifier as a separate segment in the URL path. At this time the only valid identifier is 'v1'. If specified, the version identifier MUST appear in the URL path immediately preceding the Resource endpoint and conform to the following scheme: the character 'v' followed by the desired SCIM version number; e.g., a version 'v1' User request is specified as /v1/Users. When specified Service Providers MUST perform the operation using the desired version or reject the request. When omitted Service Providers SHOULD perform the operation using the most recent API supported by the Service Provider.
| TOC |
The API supports resource versioning via standard,HTTP ETags. Service providers MAY support weak ETags as the preferred mechanism for performing conditional retrievals and ensuring Consumers do not inadvertently overwrite each others changes, respectively. When supported SCIM ETags MUST be specified as an HTTP header and SHOULD be specified within the 'version' attribute contained in the Resource's 'meta' attribute.
Example:
POST /Users HTTP/1.1 Host: example.com Content-Type: application/json Authorization: Bearer h480djs93hd8 Content-Length: ... { "schemas":["urn:scim:schemas:core:1.0"], "userName":"dschrute", "externalId":"dschrute", "name":{ "formatted":"Mr. Dwight Kurt Schrute III", "familyName":"Schrute", "givenName":"Dwight" } }
The server responds with an ETag in the response header and meta structure.
HTTP/1.1 201 Created Content-Type: application/json Location: https://example.com/v1/Users/2819c223-7f76-453a-919d-413861904646 ETag: W/"e180ee84f0671b1" { "schemas":["urn:scim:schemas:core:1.0"], "id":"2819c223-7f76-453a-919d-413861904646", "meta":{ "created":"2011-08-01T21:32:44.882Z", "lastModified":"2011-08-01T21:32:44.882Z", "location":"https://example.com/v1/Users/2819c223-7f76-453a-919d-413861904646", "version":"W\/\"e180ee84f0671b1\"" }, "name":{ "formatted":"Mr. Dwight Kurt Schrute III", "familyName":"Schrute", "givenName":"Dwight" }, "userName":"dschrute" }
With the returned ETag, Consumers MAY choose to retrieve the Resource only if the Resource has been modified. In addition, if updating, specifying an ETag guarantees that previous updates will not be overwritten.
Conditional retrieval example using If-None-Match header:
GET /Users/2819c223-7f76-453a-919d-413861904646?attributes=displayName Host: example.com Accept: application/json Authorization: Bearer h480djs93hd8 If-None-Match: W/"e180ee84f0671b1"
If the Resource has not changed the Service Provider simply returns an empty body with a 304 "Not Modified" response code.
Similarly, consumers MAY supply an If-Match ETag header for PUT, PATCH, and DELETE operations to ensure that the requested operation succeeds only if the supplied ETag matches the latest Service Provider Resource; e.g., If-Match: W/"e180ee84f0671b1"
To perform DELETE, PATCH, or PUT operations and override ETag versioning specify "If-Match: *" in lieu of an ETag header.
| TOC |
In recognition that some clients, servers and firewalls prevent PUT, PATCH and DELETE operations a client MAY override the POST operation by specifying the custom header "X-HTTP-Method-Override" with the desired PUT, PATCH, DELETE operation. For example:
POST /Users/2819c223-7f76-453a-919d-413861904646 X-HTTP-Method-Override: DELETE
| TOC |
The SCIM Protocol is based on HTTP and thus subject to the security considerations found in Section 15 of [RFC2616]. SCIM Resources (e.g., Users and Groups) can contain sensitive information. Therefore, SCIM Consumers and Service Providers MUST implement TLS. Which version(s) ought to be implemented will vary over time, and depend on the widespread deployment and known security vulnerabilities at the time of implementation. At the time of this writing, TLS version 1.2 [RFC5246] is the most recent version, but has very limited actual deployment, and might not be readily available in implementation toolkits. TLS version 1.0 [RFC2246] is the most widely deployed version, and will give the broadest interoperability.
| TOC |
Samuel Erdtman<EMAIL_ADDRESS>Patrick Harding<EMAIL_ADDRESS>| TOC |
The editor would like to thank the participants in the the SCIM working group for their support of this specification.
| TOC |
| Trey Drake (editor) | |
| UnboundID | |
| Email: |<EMAIL_ADDRESS>|
| Chuck Mortimore | |
| SalesForce | |
| Email: |<EMAIL_ADDRESS>|
| Morteza Ansari | |
| Cisco | |
| Email: |<EMAIL_ADDRESS>|
| Kelly Grizzle | |
| SailPoint | |
| Email: |<EMAIL_ADDRESS>|
| Erik Wahlström | |
| Technology Nexus | |
| Email: |<EMAIL_ADDRESS>|


This page tracks the new paper links made to my list of Eurographics 2007 papers.
Page maintained by Ke-Sen Huang.
If you have additions or changes, send an e-mail.
October 11, 2009
September 4, 2008
March 12, 2008
October 16, 2007
September 27, 2007
September 20, 2007
September 11, 2007
August 22, 2007
August 15, 2007
August 3, 2007
July 30, 2007
July 26, 2007
- A Generic Pigment Model for Digital Painting (Project)
July 17, 2007
July 9, 2007
July 2, 2007
June 30, 2007
June 19, 2007
June 16, 2007
June 8, 2007
June 7, 2007
June 3, 2007
June 1, 2007
May 29, 2007
May 28, 2007
May 25, 2007
May 24, 2007
- Stackless KD-Tree Traversal for High Performance GPU Ray Tracing (TR)
May 22, 2007
May 9, 2007
May 3, 2007
May 2, 2007
- Style Transfer Functions for Illustrative Volume Rendering (TR)
- Real-Time Simulation of Thin Shells (Abstract)
- Image Dequantization: Restoration of Quantized Colors (Abstract)
- High-Quality Adaptive Soft Shadow Mapping (Abstract)
- Sync with EG program
May 1, 2007
- Diorama Construction from a Single Image (Project)
- Geodesic-Controlled Developable Surfaces for Modeling Paper Bending
- Variational 3D Shape Segmentation for Bounding Volume Computation
April 30, 2007
- On-the-fly Curve-skeleton Computation for 3D Shapes (project page)
April 28, 2007
- Mesh Segmentation via Spectral Embedding and Contour Analysis
- Online Motion Capture Marker Labeling for Multiple Interacting Articulated Targets
- Soft Articulated Characters with Fast Contact Handling
- Texturing Internal Surfaces from a Few Cross Sections
April 25, 2007
April 23, 2007
- Volume Preservation of Multiresolution Meshes (Video)
- Skeleton-based variational mesh deformations
- Interactive Simulation of the Human Eye Depth of Field and Its Correction with Spectacle Lenses
April 18, 2007
- A Finite Element Method on Convex Polyhedra
- Adaptive Space Deformations Based on Rigid Cells
- Defocus Magnification
- Efficient Reflectance and Visibility Approximations for Environment Map Rendering
- Shape-aware Volume Illustration
- Page published
kesen.huang@gmail.com


Any savvy web developer can tell you how many kilobytes their code consumes. They bundle, minify, compress and tune the data sent out to within an inch of its life. Wire weight is easy to measure and has a direct impact on your application's launch time. But how many milliseconds does it take the user's computer to parse and load your code once it's arrived? What differences are there between CPUs, operating systems, browsers and plugins? What speed leaks are we overlooking?
As you look at the data below, keep in mind four things:
Even if you look at just sexy new hardware it's hard to ignore low-power clients: there are about 50 million netbooks and 43 million iPhones out there, alongside 10-15 million Android devices. Almost all of them are in the 600-1,600 MHz range and have less than 512MB of RAM. A juicy, growing slice of the market wants to use your software on the equivalent of a desktop from 1998. This includes rich Westerners as well as people in the fastest-growing international markets.
The test harness loads a given block of Javascript from a local file over and over and measures the setup time. My test subjects were the Yahoo User Interface (YUI) libraries, Scriptaculous, and jQuery UI. I've also included the main Javascript application code from GitHub.
The core test is as simple as can be: record a start time, load the script, record the end time, and repeat over 1,000 iterations. The tests were run on recently-booted machines with no other programs running. You can check out the project on GitHub and play along at home.
The point of this benchmark is to compare browsers and CPUs. Comparing the parse-n-load of different libraries puts you on shaky ground. For example, the YUI2 libraries are as of this writing more comprehensive than, say, YUI3 or Scriptaculous. On the other hand it's rare for an application to load every module as we're doing here. Also, each library has a diffferent approach to initialization. YUI2 does a lot of work up-front while YUI3 does things more lazily. From there you get into a complex question about what benefits each library buys you. Do not base the choice of library on this benchmark.
| Chrome | Safari 4 | Firefox 3 | Firefox 3.5 | Firefox 3.6 | Opera 10 | Safari 3 | |
|---|---|---|---|---|---|---|---|
| YUI3 | |||||||
| YUI2 | |||||||
| Scriptaculous | |||||||
| jQuery UI | |||||||
| GitHub |
| Chrome | Firefox 3 | Firefox 3.5 | Firefox 3.6 | IE 6 | IE 7 | IE 8 | |
|---|---|---|---|---|---|---|---|
| YUI3 (raw) | |||||||
| YUI3 | |||||||
| YUI2 (raw) | |||||||
| YUI2 | |||||||
| Scriptaculous | |||||||
| jQuery UI | |||||||
| GitHub |
| Chrome | Safari 4 | Firefox 3 | Firefox 3.5 | Firefox 3.6 | |
|---|---|---|---|---|---|
| YUI3 (raw) | |||||
| YUI3 | |||||
| YUI2 (raw) | |||||
| YUI2 | |||||
| Scriptaculous | |||||
| jQuery UI | |||||
| GitHub |
NB: the MacBook Air had overheating problems so some of these numbers in this table may be skewed upwards.
So it seems that there is a measurable cost to parse-n-load, and parsing speed does not seem to be correlated with the speed of the interpreter or DOM. Chrome has some anomalies in the data so for now I am withholding judgement. See "Curious Case of Chrome" in the appendix.
There is a noticeable spread between different browsers on the same hardware and OS. Firefox 3.5 is a few points slower than 3.0, but 3.6 improved on that. Internet Explorer is surprisingly fast at parse-n-load across all tested versions. I didn't include standard deviations because aside from some pathological cases they were small. If you run the benchmark for yourself you will get mean average, stddev, and a time series graph for your enjoyment.
Here is a comparison of the YUI libraries in "raw" form (with comments, whitespace, etc) and the same code minified using YUI Compressor. As expected, minification helps parse-n-load in addition to network transmission time. This is probably due to the absence of comments and extra whitespace.
| Chrome | Firefox 3 | Firefox 3.5 | Firefox 3.6 | IE 6 | IE 7 | IE 8 | |
|---|---|---|---|---|---|---|---|
| YUI3 (raw) | |||||||
| YUI3 (minified) | |||||||
| YUI2 (raw) | |||||||
| YUI2 (minified) |
If you have a large amount of Javascript in your application it's natural to bundle it all up into one file to save on network transit time and increase cacheability. But if certain parts of your application only use certain parts of the bundle, you might cause the user to unnecessarily parse unused code on every page load. The ideal would be to decouple three things that are now tightly wound together: network transit, parse-n-load, and cacheability. There is a lot of work going on in this space but so far there is no silver bullet.
The Parse-N-Load benchmark is open source and free for use. It's early and I'm sure there are bugs. If you have other kinds of hardware (Netbooks! Windows! Linux!), please try it out and let me know what you find.
While Google Chrome appears to be an order of magnitude faster at parse-n-load, the truth may be a little more complex. Running this benchmark in Chrome sometimes produces sharp cliffs in the time series graph, especially on slower CPUs. That might be the V8 engine's inline caching kicking in. I also suspect it could be caching the machine code it compiles on the first pass. Or this could be something silly like the CPU coming out of low-power mode. If anyone who knows more about what's going on can speak up, please do.
The first problem that came up was different blocking behavior between browsers. In Safari 4 (but not 3) if you create a script tag that points to an external file, that action will block, ie, wait until that file is completely parsed and loaded. This makes timing it very easy. In Firefox, however, this action asynchronous: the statement that creates the script element returns immediately and the file is loaded in a separate thread. This means you have to set up a callback in the separate thread to both measure elapsed time and kick off the next iteration of the test. You have to be careful not the blow the stack with too many nested function calls. Google Chrome is also asynchronous and has an altogether different stack behavior. If all that wasn't enough, browsers have very different memory allocation behavior, of which more (oh, much more) below.
Every browser seems to have a different system for allocating memory while parsing Javascript code. When you graph the results from Safari 4 this is what I saw initially:
Interesting. All of the source files in the benchmark are local so that's not I/O wait. The regularity of huge spikes suggests that the browser is pausing every so often to free up memory via garbage collection. When you remove those spikes another interesting pattern shows up. Here is the same graph with the top 5% of datapoints removed:
It appears that the parse-n-load time of a given piece of Javascript in Safari 4 will increase linearly with the amount of garbage. The load time can grow as much as 3X longer than normal before GC kicks in. I'm not certain whether this is an artifact of the benchmark or if it actually happens a lot during real-world use. When I added code to explicitly delete the previous script tag before creating a new one, the sawtooth elongated but did not go away. Other browsers exhibit similar halt-the-world GC behavior but only Safari 4 and Opera 10.5alpha have this sawtooth. Firefox's graph stays fairly horizontal but has many more small spikes:
Initially results for Opera 10.0 had asterisks because I couldn't get it to run the complete test. Opera got steadily slower up to 250 iterations after which it started serious thrashing and had to be killed. Geoffrey Sneddon from Opera software kindly suggested an alternate way to run this benchmark, ie destroying and re-creating the iframe for each trial instead of overwriting the same document object. This new method (dubbed "v2") works well and the Opera column has been updated. New test runs against the other browsers did not move their 95th percentile numbers more than a few percent, though the standard deviations and number of GC pauses did decrease.
Geoffrey also mentioned that while the condition I triggered is rare in the wild, they will work to fix it in a future release.
Safari 3 hit the wall even earlier, triggering an Out-of-Memory error after just a couple hundred iterations. The v2 of the benchmark works much better.
Many thanks to Adrien Arculeo, Ryan Tomayko (GitHub), Geoffrey Sneddon (Opera Software), Robert Halliday (Yahoo), Eric Miraglia (Yahoo), Lucas Smith (Yahoo), and random internet heroes for their help, ideas and corrections.


Scaltis1021.github.io
The laws of physics! The laws of physics don't change just because it's "digital". Whether you're receiving DAB or DMB, indoors or outdoors, the only way to ensure good reliable reception is to feed your receiver with a good signal. Lenco Ipod Tower Benutzerhandbuch. Digicomparison DAB+ and DMB Table Radios.


Version 1.0.1 - Tue 14 Dec 2004
by John Gruber
http://daringfireball.net/
Markdown is a text-to-HTML conversion tool for web writers. Markdown allows you to write using an easy-to-read, easy-to-write plain text format, then convert it to structurally valid XHTML (or HTML).
Thus, "Markdown" is two things: a plain text markup syntax, and a software tool, written in Perl, that converts the plain text markup to HTML.
Markdown works both as a Movable Type plug-in and as a standalone Perl script -- which means it can also be used as a text filter in BBEdit (or any other application that supporst filters written in Perl).
Full documentation of Markdown's syntax and configuration options is available on the web: http://daringfireball.net/projects/markdown/. (Note: this readme file is formatted in Markdown.)
Markdown requires Perl 5.6.0 or later. Welcome to the 21st Century.
Markdown also requires the standard Perl library module Digest::MD5
.
Markdown works with Movable Type version 2.6 or later (including MT 3.0 or later).
Copy the "Markdown.pl" file into your Movable Type "plugins" directory. The "plugins" directory should be in the same directory as "mt.cgi"; if the "plugins" directory doesn't already exist, use your FTP program to create it. Your installation should look like this:
(mt home)/plugins/Markdown.pl
Once installed, Markdown will appear as an option in Movable Type's Text Formatting pop-up menu. This is selectable on a per-post basis. Markdown translates your posts to HTML when you publish; the posts themselves are stored in your MT database in Markdown format.
If you also install SmartyPants 1.5 (or later), Markdown will offer a second text formatting option: "Markdown with SmartyPants". This option is the same as the regular "Markdown" formatter, except that automatically uses SmartyPants to create typographically correct curly quotes, em-dashes, and ellipses. See the SmartyPants web page for more information: http://daringfireball.net/projects/smartypants/
To make Markdown (or "Markdown with SmartyPants") your default text formatting option for new posts, go to Weblog Config -> Preferences.
Note that by default, Markdown produces XHTML output. To configure Markdown to produce HTML 4 output, see "Configuration", below.
Markdown works with Blosxom version 2.x.
Rename the "Markdown.pl" plug-in to "Markdown" (case is important). Movable Type requires plug-ins to have a ".pl" extension; Blosxom forbids it.
Copy the "Markdown" plug-in file to your Blosxom plug-ins folder. If you're not sure where your Blosxom plug-ins folder is, see the Blosxom documentation for information.
That's it. The entries in your weblog will now automatically be processed by Markdown.
If you'd like to apply Markdown formatting only to certain posts, rather than all of them, see Jason Clark's instructions for using Markdown in conjunction with Blosxom's Meta plugin:
Markdown works with BBEdit 6.1 or later on Mac OS X. (It also works with BBEdit 5.1 or later and MacPerl 5.6.1 on Mac OS 8.6 or later.)
Copy the "Markdown.pl" file to appropriate filters folder in your "BBEdit Support" folder. On Mac OS X, this should be:
BBEdit Support/Unix Support/Unix Filters/
See the BBEdit documentation for more details on the location of these folders.
You can rename "Markdown.pl" to whatever you wish.
That's it. To use Markdown, select some text in a BBEdit document, then choose Markdown from the Filters sub-menu in the "#!" menu, or the Filters floating palette
By default, Markdown produces XHTML output for tags with empty elements. E.g.:

Markdown can be configured to produce HTML-style tags; e.g.:

You need to use a special MTMarkdownOptions
container tag in each
Movable Type template where you want HTML 4-style output:
<MTMarkdownOptions output='html4'>
... put your entry content here ...
</MTMarkdownOptions>
The easiest way to use MTMarkdownOptions is probably to put the
opening tag right after your
tag, and the closing tag right
before
.
To suppress Markdown processing in a particular template, i.e. to
publish the raw Markdown-formatted text without translation into
(X)HTML, set the output
attribute to 'raw':
<MTMarkdownOptions output='raw'>
... put your entry content here ...
</MTMarkdownOptions>
Use the --html4tags
command-line switch to produce HTML output from a
Unix-style command line. E.g.:
% perl Markdown.pl --html4tags foo.text
Type perldoc Markdown.pl
, or read the POD documentation within the
Markdown.pl source code for more information.
To file bug reports or feature requests please send email to<EMAIL_ADDRESS>1.0.1 (14 Dec 2004):
Changed the syntax rules for code blocks and spans. Previously, backslash escapes for special Markdown characters were processed everywhere other than within inline HTML tags. Now, the contents of code blocks and spans are no longer processed for backslash escapes. This means that code blocks and spans are now treated literally, with no special rules to worry about regarding backslashes.
NOTE: This changes the syntax from all previous versions of Markdown. Code blocks and spans involving backslash characters will now generate different output than before.
Tweaked the rules for link definitions so that they must occur within three spaces of the left margin. Thus if you indent a link definition by four spaces or a tab, it will now be a code block.
[a]: /url/ "Indented 3 spaces, this is a link def"
[b]: /url/ "Indented 4 spaces, this is a code block"
IMPORTANT: This may affect existing Markdown content if it contains link definitions indented by 4 or more spaces.
Added >
, +
, and -
to the list of backslash-escapable
characters. These should have been done when these characters
were added as unordered list item markers.
Trailing spaces and tabs following HTML comments and

tags
are now ignored.
Inline links using <
and >
URL delimiters weren't working:
like [this](<http://example.com/>)
Added a bit of tolerance for trailing spaces and tabs after Markdown hr's.
Fixed bug where auto-links were being processed within code spans:
like this: `<http://example.com/>`
Sort-of fixed a bug where lines in the middle of hard-wrapped paragraphs, which lines look like the start of a list item, would accidentally trigger the creation of a list. E.g. a paragraph that looked like this:
I recommend upgrading to version
8. Oops, now this line is treated
as a sub-list.
This is fixed for top-level lists, but it can still happen for sub-lists. E.g., the following list item will not be parsed properly:
+ I recommend upgrading to version
8. Oops, now this line is treated
as a sub-list.
Given Markdown's list-creation rules, I'm not sure this can be fixed.
Standalone HTML comments are now handled; previously, they'd get
wrapped in a spurious

tag.
Fix for horizontal rules preceded by 2 or 3 spaces.

HTML tags in must occur within three spaces of left
margin. (With 4 spaces or a tab, they should be code blocks, but
weren't before this fix.)
Capitalized "With" in "Markdown With SmartyPants" for consistency with the same string label in SmartyPants.pl. (This fix is specific to the MT plug-in interface.)
Auto-linked email address can now optionally contain a 'mailto:' protocol. I.e. these are equivalent:
<EMAIL_ADDRESS><EMAIL_ADDRESS>Fixed annoying bug where nested lists would wind up with
spurious (and invalid)

tags.
You can now write empty links:
[like this]()
and they'll be turned into anchor tags with empty href attributes. This should have worked before, but didn't.
***this***
and ___this___
are now turned into
this
Instead of
this
which isn't valid. (Thanks to Michel Fortin for the fix.)
Added a new substitution in _EncodeCode()
: s/\$/$/g; This
is only for the benefit of Blosxom users, because Blosxom
(sometimes?) interpolates Perl scalars in your article bodies.
Fixed problem for links defined with urls that include parens, e.g.:
[1]: http://sources.wikipedia.org/wiki/Middle_East_Policy_(Chomsky)
"Chomsky" was being erroneously treated as the URL's title.
At some point during 1.0's beta cycle, I changed every sub's argument fetching from this idiom:
my $text = shift;
to:
my $text = shift || return '';
The idea was to keep Markdown from doing any work in a sub if the input was empty. This introduced a bug, though: if the input to any function was the single-character string "0", it would also evaluate as false and return immediately. How silly. Now fixed.
Donations to support Markdown's development are happily accepted. See: http://daringfireball.net/projects/markdown/ for details.
Copyright (c) 2003-2004 John Gruber
http://daringfireball.net/
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
Neither the name "Markdown" nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose are disclaimed. In no event shall the copyright owner or contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.


Class: Concurrent::RubyThreadPoolWorker
- Inherits:
-
Object
- Object
- Concurrent::RubyThreadPoolWorker
- Includes:
- Logging
- Defined in:
- lib/concurrent/executor/ruby_thread_pool_worker.rb
Instance Method Summary (collapse)
- - (Boolean) dead? private
-
- (RubyThreadPoolWorker) initialize(queue, parent)
constructor
private
A new instance of RubyThreadPoolWorker.
- - (Object) kill private
- - (Object) last_activity private
-
- (Object) log(level, progname, message = nil, &block)
included
from Logging
Logs through Configuration#logger, it can be overridden by setting @logger.
- - (Object) run(thread = Thread.current) private
- - (Object) status
Constructor Details
- (RubyThreadPoolWorker) initialize(queue, parent) (private)
Returns a new instance of RubyThreadPoolWorker
11 12 13 14 15 16 |
# File 'lib/concurrent/executor/ruby_thread_pool_worker.rb', line 11 def initialize(queue, parent) @queue = queue @parent = parent @mutex = Mutex.new @last_activity = Time.now.to_f end |
Instance Method Details
- (Boolean) dead? (private)
19 20 21 22 23 |
# File 'lib/concurrent/executor/ruby_thread_pool_worker.rb', line 19 def dead? return @mutex.synchronize do @thread.nil? ? false : ! @thread.alive? end end |
- (Object) kill (private)
38 39 40 41 42 43 |
# File 'lib/concurrent/executor/ruby_thread_pool_worker.rb', line 38 def kill @mutex.synchronize do Thread.kill(@thread) unless @thread.nil? @thread = nil end end |
- (Object) last_activity (private)
26 27 28 |
# File 'lib/concurrent/executor/ruby_thread_pool_worker.rb', line 26 def last_activity @mutex.synchronize { @last_activity } end |
- (Object) log(level, progname, message = nil, &block) Originally defined in module Logging
Logs through Configuration#logger, it can be overridden by setting @logger
- (Object) run(thread = Thread.current) (private)
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/concurrent/executor/ruby_thread_pool_worker.rb', line 46 def run(thread = Thread.current) @mutex.synchronize do raise StandardError.new('already running') unless @thread.nil? @thread = thread end loop do task = @queue.pop if task == :stop @thread = nil @parent.on_worker_exit(self) break end begin task.last.call(*task.first) rescue => ex # let it fail log DEBUG, ex ensure @mutex.synchronize { @last_activity = Time.now.to_f } @parent.on_end_task end end end |
- (Object) status
30 31 32 33 34 35 |
# File 'lib/concurrent/executor/ruby_thread_pool_worker.rb', line 30 def status @mutex.synchronize do return 'not running' if @thread.nil? @thread.status end end |


Preparation time
less than 30 mins
Cooking time
over 2 hours
Serves
Serves 4-6
It may seem strange to put whole lemons in a steamed pudding but fear not. The long, gentle cooking melts the sugar to create a rich, lemony caramel and infuses the dough with citrus aromas.
For the Sussex pond pudding, grease a 1.5 litre/2¾ pint heatproof basin or bowl.
Mix the flour and suet together in a bowl. In a jug combine the milk with 100ml/3½fl oz water. Mix in enough of the milk and water to the flour and suet mixture to make a dough that is soft, but firm enough to roll.
On a lightly floured work surface roll the dough into a large circle. Cut out a quarter of the circle and set aside (this will be used later to form the lid of the pudding).
Place the circle of pastry into the bowl and join the cut sides together, pressing well.
Place half of the butter cubes and half of the sugar in the bottom of the lined bowl.
Prick the lemons all over with a larding needle or skewer, so the juices can escape, and then place the lemons on top of the butter and sugar. Cover with the remaining butter and sugar to fill the bowl.
Roll out the reserved pastry into a round and place on top of the basin filling. Press the edges together to seal the pudding.
 Tie the foil in place with cooks’ string and create a handle by wrapping the string under and over the bowl (so the pudding can be easily moved when hot).
Bring a large pan of water to the boil and lower the pudding into it. The water should come halfway up the sides of the bowl.
Cover the pan with a lid and leave to simmer for 3-4 hours. Top up the pan with more water if it starts to dry out.
To serve, carefully remove the pudding from the pan and remove the foil lid. Put a deep dish over the basin and turn the pudding out onto the dish. Serve immediately with the cream and ice cream.


One Machine, Multiple Environments
There is a considerable interdependency not only between man and machine, but machine and machine.
Example: Same Page, Different Displays
Even simple improvements, such as link color or font-weight, can be assumed to be standard across browsers or operating systems. The machine must be takent into account. Below is a screen shot showing how the same page displays linked colors differently, and font weight differently, depending upon the browswer used. But even standardized pages look different among users, because no two users have the exact same habits.
Online color is not consistent. Neither is text-weight.
Notice that the exact same page is displayed differently between the browswers. Not only are the link colors different, but the font-weights are different. Both the color and the size and weight of the text are critical in determining whether the page will pass a color-contrast test. Further, notice that in the case of some browswers, more content is displayed than in other browswers. Critical information needs to be "above the fold" where all users can see it. Users with disabilities may miss important information if they don't see it, or may otherwise have difficulty accessing it.
Users are not consistent. Look at the difference with multiple tabs open.
As noted in NTI Session One, even user habits can make a difference in how your content is displayed. That's why it's so important to know your audience. The above screenshot shows how the same browser will display differently if a user has mutliple tabs open, as millenials tend to do. You may wish to visit the Nielsen Norman Group's web article: Page Parking: Millennials' Multi-Tab Mania for more information on this. The bottom line is that user preferences will affect the display of, usability of, and accessibility of your documents.


Earth Enterprise Server
GLC assembly tool
Name
Description
Polygon
Layers
2d
3d
Choose a projection to see available layers
Select a layer to add to GLC
No layers selected
Base globe options
Select a base globe
Use imagery?
Yes
No
Use terrain?
Yes
No
Assemble Glc
New glc
Cancel
Json:
close
Assembly details
close
Build in progress...


|
ActiveTcl User Guide
|
||
Tcl_CreateMathFunc, Tcl_GetMathFuncInfo, Tcl_ListMathFuncs - Define, query and enumerate math functions for expressions
#include <tcl.h>
void
Tcl_CreateMathFunc(interp, name, numArgs, argTypes, proc,
clientData)
int
Tcl_GetMathFuncInfo(interp, name, numArgsPtr,
argTypesPtr, procPtr, clientDataPtr)
Tcl_Obj *
Tcl_ListMathFuncs(interp, pattern)
Tcl allows a number of mathematical functions to be used in expressions, such as sin, cos, and hypot. Tcl_CreateMathFunc allows applications to add additional functions to those already provided by Tcl or to replace existing functions. Name is the name of the function as it will appear in expressions. If name doesn't already exist as a function then a new function is created. If it does exist, then the existing function is replaced. NumArgs and argTypes describe the arguments to the function. Each entry in the argTypes array must be either TCL_INT, TCL_DOUBLE, or TCL_EITHER to indicate whether the corresponding argument must be an integer, a double-precision floating value, or either, respectively.
Whenever the function is invoked in an expression Tcl will invoke proc. Proc should have arguments and result that match the type Tcl_MathProc:
typedef int Tcl_MathProc( ClientData clientData, Tcl_Interp *interp, Tcl_Value *args, Tcl_Value *resultPtr);
When proc is invoked the clientData and interp arguments will be the same as those passed to Tcl_CreateMathFunc. Args will point to an array of numArgs Tcl_Value structures, which describe the actual arguments to the function:
typedef struct Tcl_Value { Tcl_ValueType type; long intValue; double doubleValue; } Tcl_Value;
The type field indicates the type of the argument and is either TCL_INT or TCL_DOUBLE. It will match the argTypes value specified for the function unless the argTypes value was TCL_EITHER. Tcl converts the argument supplied in the expression to the type requested in argTypes, if that is necessary. Depending on the value of the type field, the intValue or doubleValue field will contain the actual value of the argument.
Proc should compute its result and store it either as an integer in resultPtr->intValue or as a floating value in resultPtr->doubleValue. It should set also resultPtr->type to either TCL_INT or TCL_DOUBLE to indicate which value was set. Under normal circumstances proc should return TCL_OK. If an error occurs while executing the function, proc should return TCL_ERROR and leave an error message in the interpreter's result.
Tcl_GetMathFuncInfo retrieves the values associated with function name that were passed to a preceding Tcl_CreateMathFunc call. Normally, the return code is TCL_OK but if the named function does not exist, TCL_ERROR is returned and an error message is placed in the interpreter's result.
If an error did not occur, the array reference placed in the variable pointed to by argTypesPtr is newly allocated, and should be released by passing it to Tcl_Free. Some functions (the standard set implemented in the core) are implemented directly at the bytecode level; attempting to retrieve values for them causes a NULL to be stored in the variable pointed to by procPtr and the variable pointed to by clientDataPtr will not be modified.
Tcl_ListMathFuncs returns a Tcl object containing a list of all the math functions defined in the interpreter whose name matches pattern. In the case of an error, NULL is returned and an error message is left in the interpreter result, and otherwise the returned object will have a reference count of zero.
expression, mathematical function
expr, info, Tcl_Free, Tcl_NewListObj
Copyright © 1989-1993 The Regents of the University of California. Copyright © 1994-1996 Sun Microsystems, Inc. Copyright © 1995-1997 Roger E. Critchlow Jr.


uiduck
front end table plug-in / supporting front-end paging / supporting template syntax / supporting other ui
return
randomly switch loading animation
background blur
multi language random switching
refresh
get the latest version
Comprehensive
Network data
Network data back pagination
Local data
Simple paging
English language
Keyword highlight
Currently, it is set to wechat field, and the key of related column is specified through UD keyword attribute
search
Auto flip


Title: {{ selectedMovie.Title }}
0" class="reviewscore">User Review Score: {{ reviewScore.toFixed(1) }}
Year(s): {{ selectedMovie.Year }}present
Release Date: {{ selectedMovie.Released }}
Runtime: {{ selectedMovie.Runtime }}
Genre: {{ selectedMovie.Genre }}
Director(s): {{ selectedMovie.Director }}
Writer(s): {{ selectedMovie.Writer }}
Actors: {{ selectedMovie.Actors }}
Awards: {{ selectedMovie.Awards }}
Plot Summary: {{ selectedMovie.Plot }}
{{ review.text}}


Before Change
def test_gradient_size(self, test_nets):
""" Checks for exploding and vanishing gradients """
net = test_nets[0]
x, y = test_nets[1], test_nets[2]
loss = test_nets[3]
steps = test_nets[4]
for i in range(steps):
net.training_step(x, y)
After Change
def test_gradient_size(self, test_nets):
""" Checks for exploding and vanishing gradients """
net = test_nets[0]
x = self.init_dummy_input(net)
y = self.init_dummy_output(net)
loss = test_nets[1]
steps = test_nets[2]
for i in range(steps):
net.training_step(x, y)


NEWS.md
Recommend that tests be placed in tests/shinytest/
instead of directly in the tests directory. Users with their tests in the tests/
directory will now see a message about this change. Storing shinytests directly in tests/
will be deprecated in the future. The new function migrateShinytestDir()
will migrate from the old to the new directory layout.
Also display the message about where to find the diff when the diff viewer was opened but the diffs were not accepted. (#131)
Added new suffix
option, which allows adding a suffix to an expected results directory. This makes it possible to store multiple sets of results, which can be useful, for example, if you run tests on multiple platforms. (#295)
Previously, on Windows, the reported resolution of screenshots depended on the actual screen resolution. For example, on one Windows machine, it might report a screenshot to be 96 ppi, while on another machine, it might report it to be 240 ppi, even though the image data is exactly the same from the two machines. This caused problems when expected results were generated on one machine and the tests were run on another machine. Now, the screenshots are modified so that they always report 72 ppi resolution, which is the same as on Mac and Linux. (#297)
Added new ShinyDriver
method app$waitForValue()
which will wait until the current application’s input
(or output
) value is not one of the supplied invalid values. (#304)
Added support for setting inputs that do not have an input binding (#232); furthermore, inputs set with event priority (e.g., Shiny.setInputValue('key', 'value', {priority: 'event'})
) are also supported (#239).
Added support for triggering snapshots from the keyboard (by pressing Ctrl-Shift-S or Command-Shift-S) while recording tests with recordTest()
(#240).
recordTest()
gains a debug
argument for displaying ("shiny_console"
, "browser"
, and/or "shinytest
) logs into the R console (#146). When these logs are displayed, they use format.shinytest_logs()
with short = TRUE
which suppress the timestamp and level.


Collection of econometric functions for performance and risk analysis. This package aims to aid practitioners and researchers in utilizing the latest research in analysis of non-normal return streams. In general, it is most tested on return (rather than price) data on a regular scale, but most functions will work with irregular return data as well, and increasing numbers of functions will work with P&L or price data where possible.
| Version: | 1.5.2 |
| Depends: | R (≥ 3.0.0), xts (≥ 0.10.0) |
| Imports: | methods, quadprog, zoo |
| Suggests: | dygraphs, Hmisc, MASS, quantmod, gamlss, gamlss.dist, robustbase, quantreg, gplots, testthat |
| Published: | 2018-03-02 |
| Author: | Brian G. Peterson [cre, aut, cph], Peter Carl [aut, cph], Kris Boudt [ctb, cph], Ross Bennett [ctb], Joshua Ulrich [ctb], Eric Zivot [ctb], Dries Cornilly [ctb], Eric Hung [ctb], Matthieu Lestel [ctb], Kyle Balkissoon [ctb], Diethelm Wuertz [ctb] |
| Maintainer: | Brian G. Peterson <brian at braverock.com> |
| License: | GPL-2 | GPL-3 |
| Copyright: | (c) 2004-2018 |
| URL: | https://github.com/braverock/PerformanceAnalytics |
| NeedsCompilation: | yes |
| Materials: | README NEWS |
| In views: | Finance |
| CRAN checks: | PerformanceAnalytics results |
| Reference manual: | PerformanceAnalytics.pdf |
| Vignettes: |
Estimation of Higher Order Moments Performance Attribution from Bacon PerformanceAnalytics Charts and Tables Reference PerformanceAnalytics Charts and Tables Presentation - Meielisalp - 2007 PerformanceAnalytics Data Mining Presentation - UseR - 2007 Portfolio Returns How to Present Tables in Plot Devices |
| Package source: | PerformanceAnalytics_1.5.2.tar.gz |
| Windows binaries: | r-devel: PerformanceAnalytics_1.5.2.zip, r-release: PerformanceAnalytics_1.5.2.zip, r-oldrel: PerformanceAnalytics_1.5.2.zip |
| OS X binaries: | r-release: PerformanceAnalytics_1.5.2.tgz, r-oldrel: PerformanceAnalytics_1.5.2.tgz |
| Old sources: | PerformanceAnalytics archive |
| Reverse depends: | PortfolioAnalytics, tidyquant |
| Reverse imports: | JFE, scRNAtools, SMNCensReg, tawny, tbl2xts |
| Reverse suggests: | cvar, Dowd, pbo, portsort, timeSeries |
Please use the canonical form https://CRAN.R-project.org/package=PerformanceAnalytics to link to this page.


On this small website I collect my experience with indian cooking for people who experiment with it like me outside of India. This site is not a substitute for professional sites on Indian cooking, but it shows him how to approach this topic if you are neither a cook nor have learned this kind of cooking already at home.
I came to the topic of indian cooking mainly because one of my sons started eating only vegetarian at an early age. I wanted to cook something for him that wasn't just a poorer substitute for dishes with meat. I experimented somewhat fruitlessly with Indian recipes but then learned mostly through a cookbook, to cook things thatwere quite well received at least by my son and by my guests. I still cook mainly with this cookbook but I have learned a lot more in the meantime.
One learns to cook, as by the way also writing HTML, only in practice. The following are some of the recipes I make more often, they are all pretty simple. When cooking Indian, it is usually good to make a dish with legumes and maybe another dish with vegetables. Here are some recipes:
I mentioned it before: one cookbook in particular has helped me the most. Here also are a few other resources I refer back to often:


CCTV on the cards after Market Drayton community centre hit by vandals
by Dominic RobertsonCCTV could be installed in a bid to deter vandals who have struck at a popular community centre twice in the past 10 days.
The Zone, on Linden Way in Market Drayton, has been targeted twice in little more than a week, with vandals putting glue into the building's locks.
The vandalism meant sessions which take place at the centre were cancelled, and have resulted in extra expense for Market Drayton Town Council, falling on the public purse.
Now town councillor Roy Aldcroft, has said the council is considering a number of measures to prevent a repeat occurrence.
He said they could install CCTV, and would even consider a private prosecution to recover the costs of the damage if they can find out who is responsible.
The centre hosts a number of session for groups of all ages, and is used by around 70 people every week.
It has three rooms, a kitchen/cafe and two disabled toilets.
Councillor Aldcroft said: "It really does disrupt the work that goes on there.
Court
"It is there for the community, after all it is a community asset, but it would appear that a very small part of the community is determined to interrupt the activities that go on there for people of all ages.
"We are in the process of putting CCTV in so we can see who is doing it."
The centre opened last year after after five years of planning and was made possible with a grant of £350,000 from the National Lottery.
Mr Aldcroft said he could not understand the mindset of people who would want to disrupt community activities.
"At the moment, with Christmas approaching, there are all sorts of activities going on," he added.
"People are looking forward to them, particularly the elderly and the children, and they are being denied access by the people who think it it is fun to do things like this.
"The town council is currently looking as the possibility of a private prosecution in terms of damage like this because it costs the town council and the community again to fix these things, so we may be taking people to court."


Automatic creation/injection of arrays
As with all IOC containers, you can create registrations for array types just as you would any type, e.g:
// registers a constant integer array
container.RegisterObject(new int[] { 1, 2, 3 });
However, arrays of objects can also be injected automatically by Rezolver just the same as
IEnumerable<T>
instances - i.e. by building them dynamically from the registrations present
against the array's element type.
As a result, if you read through the enumerables documentation,
all of the examples there can be repeated with the corresponding array type - e.g. int[]
instead of IEnumerable<int>
.
Examples
By default, an empty container (or one which has not had any specific registrations for the array's element type) will automatically build an empty array:
// this is fundamentally identical to the first example in the
// enumerables section
var container = new Container();
var result = container.Resolve<IMyService[]>();
Assert.NotNull(result);
Assert.Empty(result);
And, as you would expect, as soon as you start registering objects of a particular type, you can inject an array of that type:
var container = new Container();
container.RegisterType<MyService1, IMyService>();
container.RegisterType<MyService2, IMyService>();
container.RegisterType<MyService3, IMyService>();
var result = container.Resolve<IMyService[]>();
Assert.NotNull(result);
Assert.Equal(3, result.Length);
Assert.IsType<MyService1>(result[0]);
Assert.IsType<MyService2>(result[1]);
Assert.IsType<MyService3>(result[2]);
All the other enumerable behaviour - such as open generics etc also applies to arrays.
Tip
The same is also true for lists and collections.
Decorating arrays
Note
Decoration of array elements is exactly the same as it is for enumerables - if you register a decorator for a particular type, then it will decorate every instance of that type when regardless of whether the object is destined for an enumerable/array/collection/list - see 'decorators and enumerables' for more on this.
If you want to decorate an array instance (e.g. to pad an array with certain values, perhaps), you cannot do it using a decorator class - for the obvious reason that you cannot inherit from .Net's array type.
Instead, you will need to use decorator delegates - a delegate that will be executed every time an instance of a given type is produced by the container - which will be passed the undecorated instance as an argument and which returns a (potentially different) instance to be used in its place.
Disabling Automatic Array Injection
As with many other Rezolver behaviours, the automatic injection of arrays can be enabled (the default) and disabled via an option - however, it is an option that must be applied when the container's ITargetContainer is created, and before some of the core configurations have been applied to it.
To do this, you need to supply an instance of ITargetContainer (typically
TargetContainer) to your Container
(or ScopedContainer) to which you pass a specific ITargetContainerConfig
in which you add a configuration object that will set the EnableArrayInjection
option to false
.
Note
You can of course supply an empty ITargetContainerConfig to the TargetContainer on construction, but this will also disable other configurations such as enumerable injection, contravariance and so on.
The easiest way to do this, then, is to use the DefaultConfig collection -
either manipulate it directly (which will change the options for all TargetContainer instances)
or use it as a starting point for a custom configuration - which what this example shows, using the
Clone()
method, followed by the ConfigureOption<T>
extension method:
// create a clone of the default config
// and then explicitly set the EnableArrayInjection option to false
var config = TargetContainer.DefaultConfig
.Clone()
.ConfigureOption<Options.EnableArrayInjection>(false);
// now explicitly create a TargetContainer using this config
var container = new Container(new TargetContainer(config));
Assert.Throws<InvalidOperationException>(
() => container.Resolve<IMyService[]>());
Tip
Another option is to remove the InjectArrays configuration from the DefaultConfig or a clone of it.


${include "/pages/includes/jquery.html" .} ${include "/pages/includes/bootstrap.html" .} ${include "/pages/includes/jqGrid.html" .} ${include "/pages/includes/my97.html" .} ${include "/pages/template/common.html" .} ${include "/pages/theme/flat.html" .}


Guess the language
Think of your favarite programming language, I'm going to try to guess
Ready? Click
here
to begin!