001    /*
002     * Copyright 2011-2012 UnboundID Corp.
003     *
004     * This program is free software; you can redistribute it and/or modify
005     * it under the terms of the GNU General Public License (GPLv2 only)
006     * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
007     * as published by the Free Software Foundation.
008     *
009     * This program is distributed in the hope that it will be useful,
010     * but WITHOUT ANY WARRANTY; without even the implied warranty of
011     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012     * GNU General Public License for more details.
013     *
014     * You should have received a copy of the GNU General Public License
015     * along with this program; if not, see <http://www.gnu.org/licenses>.
016     */
017    
018    package com.unboundid.scim.schema;
019    
020    import com.unboundid.scim.sdk.InvalidResourceException;
021    import com.unboundid.scim.sdk.SCIMAttribute;
022    import com.unboundid.scim.sdk.SCIMAttributeValue;
023    import com.unboundid.scim.sdk.SCIMConstants;
024    import com.unboundid.scim.sdk.SCIMObject;
025    
026    import java.util.ArrayList;
027    import java.util.Arrays;
028    import java.util.Collection;
029    import java.util.List;
030    
031    /**
032     * Contains the resources and their attributes defined in
033     * Core Schema 1.0 - draft 2.
034     */
035    public class CoreSchema
036    {
037      //// 3.  SCIM Schema Structure ////
038      private static final AttributeDescriptor MULTIVALUED_PRIMARY =
039          AttributeDescriptor.createSubAttribute("primary",
040              AttributeDescriptor.DataType.BOOLEAN,
041              "A Boolean value indicating the 'primary' or preferred attribute " +
042                  "value for this attribute",
043              SCIMConstants.SCHEMA_URI_CORE, false, false, false);
044      private static final AttributeDescriptor MULTIVALUED_DISPLAY =
045          AttributeDescriptor.createSubAttribute("display",
046              AttributeDescriptor.DataType.STRING,
047              "A human readable name, primarily used for display purposes",
048              SCIMConstants.SCHEMA_URI_CORE, true, false, false);
049      private static final AttributeDescriptor MULTIVALUED_OPERATION =
050          AttributeDescriptor.createSubAttribute("operation",
051              AttributeDescriptor.DataType.STRING,
052              "The operation to perform on the multi-valued attribute during a " +
053                  "PATCH request",
054              SCIMConstants.SCHEMA_URI_CORE, false, false, false);
055    
056      /**
057       * Adds the default sub-attributes for multi-valued attributes. This
058       * will include the type, primary, display and operation attributes.
059       *
060       * @param dataType        The data type of the value sub-attribute.
061       * @param canonicalValues The list of canonical values for the type attribute.
062       * @param subAttributes  A list specifying the sub attributes of the complex
063       *                       attribute.
064       * @return The default sub-attributes for multi-valued attributes.
065       */
066      static AttributeDescriptor[] addCommonMultiValuedSubAttributes(
067          final AttributeDescriptor.DataType dataType,
068          final String[] canonicalValues,
069          final AttributeDescriptor... subAttributes)
070      {
071        final AttributeDescriptor type = AttributeDescriptor.createSubAttribute(
072            "type", AttributeDescriptor.DataType.STRING, "A label indicating the " +
073            "attribute's function; e.g., \"work\" or " + "\"home\"",
074            SCIMConstants.SCHEMA_URI_CORE, false, false, false, canonicalValues);
075    
076        int i = 0;
077        final AttributeDescriptor[] allSubAttributes;
078        if (dataType == AttributeDescriptor.DataType.COMPLEX)
079        {
080          allSubAttributes = new AttributeDescriptor[subAttributes.length + 4];
081        }
082        else
083        {
084          allSubAttributes = new AttributeDescriptor[subAttributes.length + 5];
085          allSubAttributes[i++] = AttributeDescriptor.createSubAttribute(
086            "value", dataType, "The attribute's significant value",
087              SCIMConstants.SCHEMA_URI_CORE, false, true, false);
088        }
089    
090        allSubAttributes[i++] = MULTIVALUED_DISPLAY;
091        allSubAttributes[i++] = MULTIVALUED_PRIMARY;
092        allSubAttributes[i++] = type;
093        allSubAttributes[i++] = MULTIVALUED_OPERATION;
094    
095        System.arraycopy(subAttributes, 0, allSubAttributes, i,
096                         subAttributes.length);
097    
098        return allSubAttributes;
099      }
100    
101      /**
102       * Adds the common resource attributes. This will include id, externalId,
103       * and meta.
104       *
105       * @param attributes A list specifying the attributes of a resource.
106       * @return The list of attributes including the common attributes.
107       */
108      static List<AttributeDescriptor> addCommonResourceAttributes(
109          final AttributeDescriptor... attributes)
110      {
111        List<AttributeDescriptor> attributeList =
112            new ArrayList<AttributeDescriptor>(attributes.length + 3);
113    
114        // These attributes need to be in the same order as defined in the SCIM XML
115        // schema scim-core.xsd.
116        attributeList.add(ID);
117        attributeList.add(META);
118        attributeList.add(EXTERNAL_ID);
119        attributeList.addAll(Arrays.asList(attributes));
120        return attributeList;
121      }
122    
123      //// 5.  SCIM Core Schema ////
124    
125      //// 5.1.  Common Schema Attributes ////
126      private static final AttributeDescriptor ID =
127          AttributeDescriptor.createAttribute("id",
128              AttributeDescriptor.DataType.STRING,
129              "Unique identifier for the SCIM Resource as defined by the " +
130                  "Service Provider",
131              SCIMConstants.SCHEMA_URI_CORE, true, true, false);
132      private static final AttributeDescriptor EXTERNAL_ID =
133          AttributeDescriptor.createAttribute("externalId",
134              AttributeDescriptor.DataType.STRING,
135              "Unique identifier for the Resource as defined by the " +
136                  "Service Consumer",
137              SCIMConstants.SCHEMA_URI_CORE, false, false, false);
138    
139    
140      private static final AttributeDescriptor META_CREATED =
141          AttributeDescriptor.createSubAttribute("created",
142              AttributeDescriptor.DataType.DATETIME,
143              "The DateTime the Resource was added to the Service Provider",
144              SCIMConstants.SCHEMA_URI_CORE, false, false, false);
145      private static final AttributeDescriptor META_LAST_MODIFIED =
146          AttributeDescriptor.createSubAttribute("lastModified",
147              AttributeDescriptor.DataType.DATETIME,
148              "The most recent DateTime the details of this Resource were " +
149                  "updated at the Service Provider",
150              SCIMConstants.SCHEMA_URI_CORE, false, false, false);
151      private static final AttributeDescriptor META_LOCATION =
152          AttributeDescriptor.createSubAttribute("location",
153              AttributeDescriptor.DataType.STRING,
154              "The URI of the Resource being returned",
155              SCIMConstants.SCHEMA_URI_CORE, false, false, false);
156      private static final AttributeDescriptor META_VERSION =
157          AttributeDescriptor.createSubAttribute("version",
158              AttributeDescriptor.DataType.STRING,
159              "The version of the Resource being returned",
160              SCIMConstants.SCHEMA_URI_CORE, false, false, false);
161      private static final AttributeDescriptor META_ATTRIBUTES =
162          AttributeDescriptor.createSubAttribute("attributes",
163              AttributeDescriptor.DataType.STRING,
164              "The names of the attributes to remove from the Resource during a " +
165                  "PATCH operation",
166              SCIMConstants.SCHEMA_URI_CORE, false, false, false);
167      private static final AttributeDescriptor META =
168          AttributeDescriptor.createAttribute("meta",
169              AttributeDescriptor.DataType.COMPLEX,
170              "A complex type containing metadata about the resource",
171              SCIMConstants.SCHEMA_URI_CORE, false, false, false,
172              META_CREATED, META_LAST_MODIFIED, META_LOCATION, META_VERSION,
173              META_ATTRIBUTES);
174    
175      //// 6.  SCIM User Schema ////
176      //// 6.1.  Singular Attributes ////
177    
178      private static final AttributeDescriptor USER_NAME =
179          AttributeDescriptor.createAttribute("userName",
180              AttributeDescriptor.DataType.STRING,
181              "Unique identifier for the User, typically used by the user to " +
182                  "directly authenticate to the Service Provider",
183              SCIMConstants.SCHEMA_URI_CORE, false, true, false);
184    
185      private static final AttributeDescriptor NAME_FORMATTED =
186          AttributeDescriptor.createSubAttribute("formatted",
187              AttributeDescriptor.DataType.STRING,
188              "The full name, including all middle names, titles, and suffixes " +
189                  "as appropriate, formatted for display (e.g. Ms. Barbara Jane " +
190                  "Jensen, III.)",
191              SCIMConstants.SCHEMA_URI_CORE, false, false, false);
192      private static final AttributeDescriptor NAME_FAMILY_NAME =
193          AttributeDescriptor.createSubAttribute("familyName",
194              AttributeDescriptor.DataType.STRING,
195              "The family name of the User, or \"Last Name\" in most Western " +
196                  "languages (e.g. Jensen given the full name Ms. Barbara Jane " +
197                  "Jensen, III.)",
198              SCIMConstants.SCHEMA_URI_CORE, false, false, false);
199      private static final AttributeDescriptor NAME_GIVEN_NAME =
200          AttributeDescriptor.createSubAttribute("givenName",
201              AttributeDescriptor.DataType.STRING,
202              "The given name of the User, or \"First Name\" in most Western " +
203                  "languages (e.g. Barbara given the full name Ms. Barbara Jane " +
204                  "Jensen, III.)",
205              SCIMConstants.SCHEMA_URI_CORE, false, false, false);
206      private static final AttributeDescriptor NAME_MIDDLE_NAME =
207          AttributeDescriptor.createSubAttribute("middleName",
208              AttributeDescriptor.DataType.STRING,
209              "The middle name(s) of the User (e.g. Jane given the full name Ms. " +
210                  "Barbara Jane Jensen, III.)",
211              SCIMConstants.SCHEMA_URI_CORE, false, false, false);
212      private static final AttributeDescriptor NAME_HONORIFIC_PREFIX =
213          AttributeDescriptor.createSubAttribute("honorificPrefix",
214              AttributeDescriptor.DataType.STRING,
215              "The honorific prefix(es) of the User, or \"Title\" in most " +
216                  "Western languages (e.g. Ms. given the full name Ms. Barbara " +
217                  "Jane Jensen, III.)",
218              SCIMConstants.SCHEMA_URI_CORE, false, false, false);
219      private static final AttributeDescriptor NAME_HONORIFIC_SUFFIX =
220          AttributeDescriptor.createSubAttribute("honorificSuffix",
221              AttributeDescriptor.DataType.STRING,
222              "The honorific suffix(es) of the User, or \"Suffix\" in most " +
223                  "Western languages (e.g. III. given the full name Ms. Barbara " +
224                  "Jane Jensen, III.)",
225              SCIMConstants.SCHEMA_URI_CORE, false, false, false);
226      private static final AttributeDescriptor NAME =
227          AttributeDescriptor.createAttribute("name",
228              AttributeDescriptor.DataType.COMPLEX,
229              "The components of the User's real name",
230              SCIMConstants.SCHEMA_URI_CORE, false, false, false,
231              NAME_FORMATTED, NAME_FAMILY_NAME, NAME_GIVEN_NAME, NAME_MIDDLE_NAME,
232              NAME_HONORIFIC_PREFIX, NAME_HONORIFIC_SUFFIX);
233    
234      private static final AttributeDescriptor DISPLAY_NAME =
235          AttributeDescriptor.createAttribute("displayName",
236              AttributeDescriptor.DataType.STRING,
237              "The name of the User, suitable for display to end-users",
238              SCIMConstants.SCHEMA_URI_CORE, false, false, false);
239      private static final AttributeDescriptor NICK_NAME =
240          AttributeDescriptor.createAttribute("nickName",
241              AttributeDescriptor.DataType.STRING,
242              "The casual way to address the user in real life, e.g. \"Bob\" or " +
243                  "\"Bobby\" instead of \"Robert\"",
244              SCIMConstants.SCHEMA_URI_CORE, false, false, false);
245      private static final AttributeDescriptor PROFILE_URL =
246          AttributeDescriptor.createAttribute("profileUrl",
247              AttributeDescriptor.DataType.STRING,
248              "URL to a page representing the User's online profile",
249              SCIMConstants.SCHEMA_URI_CORE, false, false, false);
250      private static final AttributeDescriptor TITLE =
251          AttributeDescriptor.createAttribute("title",
252              AttributeDescriptor.DataType.STRING,
253              "The User's title, such as \"Vice President\"",
254              SCIMConstants.SCHEMA_URI_CORE, false, false, false);
255      private static final AttributeDescriptor USER_TYPE =
256          AttributeDescriptor.createAttribute("userType",
257              AttributeDescriptor.DataType.STRING,
258              "The organization-to-user relationship",
259              SCIMConstants.SCHEMA_URI_CORE, false, false, false);
260      private static final AttributeDescriptor PREFERRED_LANGUAGE =
261          AttributeDescriptor.createAttribute("preferredLanguage",
262              AttributeDescriptor.DataType.STRING,
263              "The User's preferred written or spoken language. Generally used " +
264                  "for selecting a localized User interface.  Valid values are " +
265                  "concatenation of the ISO 639-1 two letter language code, an " +
266                  "underscore, and the ISO 3166-1 2 letter country code; e.g., " +
267                  "specifies the language English and country US",
268              SCIMConstants.SCHEMA_URI_CORE, false, false, false);
269      private static final AttributeDescriptor LOCALE =
270          AttributeDescriptor.createAttribute("locale",
271              AttributeDescriptor.DataType.STRING,
272              "Used to indicate the User's default location for purposes of " +
273                  "localizing items such as currency, date time format, " +
274                  "ISO 639-1 two letter language code an underscore, and the " +
275                  "ISO 3166-1 2 letter country code; e.g., 'en_US' specifies the " +
276                  "language English and country US",
277              SCIMConstants.SCHEMA_URI_CORE, false, false, false);
278      private static final AttributeDescriptor TIMEZONE =
279          AttributeDescriptor.createAttribute("timezone",
280              AttributeDescriptor.DataType.STRING,
281              "The User's time zone in the \"Olson\" timezone database format; " +
282                  "e.g.,'America/Los_Angeles'",
283              SCIMConstants.SCHEMA_URI_CORE, false, false, false);
284      private static final AttributeDescriptor ACTIVE =
285          AttributeDescriptor.createAttribute("active",
286              AttributeDescriptor.DataType.BOOLEAN,
287              "A Boolean value indicating the User's administrative status",
288              SCIMConstants.SCHEMA_URI_CORE, false, false, false);
289      private static final AttributeDescriptor PASSWORD =
290          AttributeDescriptor.createAttribute("password",
291              AttributeDescriptor.DataType.STRING,
292              "The User's clear text password. This attribute is intended to be " +
293                  "used as a means to specify an initial password when creating " +
294                  "a new User or to reset an existing User's password. This " +
295                  "value will never be returned by a Service Provider in any form",
296              SCIMConstants.SCHEMA_URI_CORE, false, false, false);
297    
298      //// 6.2. Multi-valued Attributes ////
299    
300      private static final AttributeDescriptor EMAILS =
301          AttributeDescriptor.createMultiValuedAttribute("emails",
302              "email", AttributeDescriptor.DataType.STRING,
303              "E-mail addresses for the User",
304              SCIMConstants.SCHEMA_URI_CORE, false, false, false,
305              new String[] {"work", "home", "other"});
306      private static final AttributeDescriptor PHONE_NUMBERS =
307          AttributeDescriptor.createMultiValuedAttribute("phoneNumbers",
308              "phoneNumber", AttributeDescriptor.DataType.STRING,
309              "Phone numbers for the User",
310              SCIMConstants.SCHEMA_URI_CORE,
311              false, false, false, new String[] {"fax", "pager", "other"});
312      private static final AttributeDescriptor IMS =
313          AttributeDescriptor.createMultiValuedAttribute("ims",
314              "im", AttributeDescriptor.DataType.STRING,
315              "Instant messaging address for the User",
316              SCIMConstants.SCHEMA_URI_CORE, false, false, false,
317              new String[] {"aim", "gtalk", "icq", "xmpp", "msn", "skype", "qq",
318                  "yahoo"});
319      private static final AttributeDescriptor PHOTOS =
320          AttributeDescriptor.createMultiValuedAttribute("photos",
321              "photo", AttributeDescriptor.DataType.STRING,
322              "URL of photos of the User",
323              SCIMConstants.SCHEMA_URI_CORE, false, false, false,
324              new String[] {"photo", "thumbnail"});
325    
326      private static final AttributeDescriptor ADDRESS_FORMATTED =
327          AttributeDescriptor.createSubAttribute("formatted",
328              AttributeDescriptor.DataType.STRING,
329              "The full mailing address, formatted for display or use with a " +
330                  "mailing label",
331              SCIMConstants.SCHEMA_URI_CORE, false, false, false);
332      private static final AttributeDescriptor ADDRESS_STREET_ADDRESS =
333          AttributeDescriptor.createSubAttribute("streetAddress",
334              AttributeDescriptor.DataType.STRING,
335              "The full street address component, which may include house " +
336                  "number, street name, P.O. box, and multi-line extended street " +
337                  "address information",
338              SCIMConstants.SCHEMA_URI_CORE, false, false, false);
339      private static final AttributeDescriptor ADDRESS_LOCALITY =
340          AttributeDescriptor.createSubAttribute("locality",
341              AttributeDescriptor.DataType.STRING,
342              "The city or locality component",
343              SCIMConstants.SCHEMA_URI_CORE, false, false, false);
344      private static final AttributeDescriptor ADDRESS_REGION =
345          AttributeDescriptor.createSubAttribute("region",
346              AttributeDescriptor.DataType.STRING,
347              "The state or region component",
348              SCIMConstants.SCHEMA_URI_CORE, false, false, false);
349      private static final AttributeDescriptor ADDRESS_POSTAL_CODE =
350          AttributeDescriptor.createSubAttribute("postalCode",
351              AttributeDescriptor.DataType.STRING,
352              "The zipcode or postal code component",
353              SCIMConstants.SCHEMA_URI_CORE, false, false, false);
354      private static final AttributeDescriptor ADDRESS_COUNTRY =
355          AttributeDescriptor.createSubAttribute("country",
356              AttributeDescriptor.DataType.STRING,
357              "The country name component",
358              SCIMConstants.SCHEMA_URI_CORE, false, false, false);
359      private static final AttributeDescriptor ADDRESSES =
360          AttributeDescriptor.createMultiValuedAttribute("addresses",
361              "address", AttributeDescriptor.DataType.COMPLEX,
362              "A physical mailing address for this User",
363              SCIMConstants.SCHEMA_URI_CORE, false, false, false,
364              new String[]{"work", "home", "other"},
365              ADDRESS_FORMATTED, ADDRESS_STREET_ADDRESS, ADDRESS_LOCALITY,
366              ADDRESS_REGION, ADDRESS_POSTAL_CODE, ADDRESS_COUNTRY);
367    
368      private static final AttributeDescriptor GROUPS =
369          AttributeDescriptor.createMultiValuedAttribute("groups",
370              "group", AttributeDescriptor.DataType.STRING,
371              "A list of groups that the user belongs to",
372              SCIMConstants.SCHEMA_URI_CORE, false, false, false,
373              new String[] {"direct", "indirect"});
374      private static final AttributeDescriptor ENTITLEMENTS =
375          AttributeDescriptor.createMultiValuedAttribute("entitlements",
376              "entitlement", AttributeDescriptor.DataType.STRING,
377              "A list of entitlements for the User that represent a thing the " +
378                  "User has. That is, an entitlement is an additional right to a " +
379                  "thing, object or service",
380              SCIMConstants.SCHEMA_URI_CORE, false, false, false, null);
381      private static final AttributeDescriptor ROLES =
382          AttributeDescriptor.createMultiValuedAttribute("roles",
383              "role", AttributeDescriptor.DataType.STRING,
384              "A list of roles for the User that collectively represent who the " +
385                  "User is",
386              SCIMConstants.SCHEMA_URI_CORE, false, false, false, null);
387      private static final AttributeDescriptor X509CERTIFICATES =
388          AttributeDescriptor.createMultiValuedAttribute("x509Certificates",
389              "x509Certificate", AttributeDescriptor.DataType.BINARY,
390              "A list of certificates issued to the User. Values are DER " +
391                  "encoded x509.",
392              SCIMConstants.SCHEMA_URI_CORE, false, false, false, null);
393    
394      //// 7.  SCIM Enterprise User Schema Extension ////
395    
396      private static final AttributeDescriptor EMPLOYEE_NUMBER =
397          AttributeDescriptor.createAttribute("employeeNumber",
398              AttributeDescriptor.DataType.STRING,
399              "Numeric or alphanumeric identifier assigned to a person, " +
400                  "typically based on order of hire or association with an " +
401                  "organization",
402              SCIMConstants.SCHEMA_URI_ENTERPRISE_EXTENSION, false,
403              false, false);
404      private static final AttributeDescriptor COST_CENTER =
405          AttributeDescriptor.createAttribute("costCenter",
406              AttributeDescriptor.DataType.STRING,
407              "Identifies the name of a cost center",
408              SCIMConstants.SCHEMA_URI_ENTERPRISE_EXTENSION, false,
409              false, false);
410      private static final AttributeDescriptor ORGANIZATION =
411          AttributeDescriptor.createAttribute("organization",
412              AttributeDescriptor.DataType.STRING,
413              "Identifies the name of an organization",
414              SCIMConstants.SCHEMA_URI_ENTERPRISE_EXTENSION, false,
415              false, false);
416      private static final AttributeDescriptor DIVISION =
417          AttributeDescriptor.createAttribute("division",
418              AttributeDescriptor.DataType.STRING,
419              "Identifies the name of a division",
420              SCIMConstants.SCHEMA_URI_ENTERPRISE_EXTENSION, false,
421              false, false);
422      private static final AttributeDescriptor DEPARTMENT =
423          AttributeDescriptor.createAttribute("department",
424              AttributeDescriptor.DataType.STRING,
425              "Identifies the name of a department",
426              SCIMConstants.SCHEMA_URI_ENTERPRISE_EXTENSION, false,
427              false, false);
428    
429      private static final AttributeDescriptor MANAGER_ID =
430          AttributeDescriptor.createSubAttribute("managerId",
431              AttributeDescriptor.DataType.STRING,
432              "The id of the SCIM resource representing the User's manager",
433              SCIMConstants.SCHEMA_URI_ENTERPRISE_EXTENSION, false, false, false);
434      private static final AttributeDescriptor MANAGER_DISPLAY_NAME =
435          AttributeDescriptor.createSubAttribute("displayName",
436              AttributeDescriptor.DataType.STRING,
437              "The displayName of the User's manager",
438              SCIMConstants.SCHEMA_URI_ENTERPRISE_EXTENSION, false, false, false);
439      private static final AttributeDescriptor MANAGER =
440          AttributeDescriptor.createAttribute("manager",
441              AttributeDescriptor.DataType.COMPLEX, "The User's manager",
442              SCIMConstants.SCHEMA_URI_ENTERPRISE_EXTENSION, false,
443              false, false, MANAGER_ID, MANAGER_DISPLAY_NAME);
444    
445      //// 8.  SCIM Group Schema ////
446    
447      private static final AttributeDescriptor GROUP_DISPLAY_NAME =
448          AttributeDescriptor.createAttribute("displayName",
449              AttributeDescriptor.DataType.STRING,
450              "A human readable name for the Group",
451              SCIMConstants.SCHEMA_URI_CORE, false, false, false);
452      private static final AttributeDescriptor MEMBERS =
453          AttributeDescriptor.createMultiValuedAttribute("members",
454              "member", AttributeDescriptor.DataType.STRING,
455              "A list of members of the Group",
456              SCIMConstants.SCHEMA_URI_CORE, true, false, false,
457              new String[] {"User", "Group"});
458    
459      //// 9.  Service Provider Configuration Schema ////
460    
461      private static final AttributeDescriptor CONFIG_DOCUMENTATION_URL =
462          AttributeDescriptor.createAttribute("documentationUrl",
463              AttributeDescriptor.DataType.STRING,
464              "An HTTP addressable URL pointing to the Service Provider's human " +
465                  "consumable help documentation",
466              SCIMConstants.SCHEMA_URI_CORE, true, false, false);
467      private static final AttributeDescriptor PATCH_SUPPORTED =
468          AttributeDescriptor.createSubAttribute("supported",
469              AttributeDescriptor.DataType.BOOLEAN,
470              "Boolean value specifying whether the PATCH operation is supported",
471              SCIMConstants.SCHEMA_URI_CORE, true, true, false);
472      private static final AttributeDescriptor BULK_SUPPORTED =
473          AttributeDescriptor.createSubAttribute("supported",
474              AttributeDescriptor.DataType.BOOLEAN,
475              "Boolean value specifying whether the BULK operation is supported",
476              SCIMConstants.SCHEMA_URI_CORE, true, true, false);
477      private static final AttributeDescriptor BULK_MAX_OPERATIONS =
478          AttributeDescriptor.createSubAttribute("maxOperations",
479              AttributeDescriptor.DataType.INTEGER,
480              "An integer value specifying the maximum number of resource " +
481                  "operations in a BULK operation",
482              SCIMConstants.SCHEMA_URI_CORE, true, true, false);
483      private static final AttributeDescriptor BULK_MAX_PAYLOAD_SIZE =
484          AttributeDescriptor.createSubAttribute("maxPayloadSize",
485              AttributeDescriptor.DataType.INTEGER,
486              "An integer value specifying the maximum payload size in bytes " +
487                  "of a BULK operation",
488              SCIMConstants.SCHEMA_URI_CORE, true, true, false);
489      private static final AttributeDescriptor FILTER_SUPPORTED =
490          AttributeDescriptor.createSubAttribute("supported",
491              AttributeDescriptor.DataType.BOOLEAN,
492              "Boolean value specifying whether the BULK operation is supported",
493              SCIMConstants.SCHEMA_URI_CORE, true, true, false);
494      private static final AttributeDescriptor FILTER_MAX_RESULTS =
495          AttributeDescriptor.createSubAttribute("maxResults",
496              AttributeDescriptor.DataType.INTEGER,
497              "Integer value specifying the maximum number of Resources returned " +
498                  "in a response",
499              SCIMConstants.SCHEMA_URI_CORE, true, true, false);
500      private static final AttributeDescriptor CHANGE_PASSWORD_SUPPORTED =
501          AttributeDescriptor.createSubAttribute("supported",
502              AttributeDescriptor.DataType.BOOLEAN,
503              "Boolean value specifying whether the Change Password operation " +
504                  "is supported",
505              SCIMConstants.SCHEMA_URI_CORE, true, true, false);
506      private static final AttributeDescriptor SORT_SUPPORTED =
507          AttributeDescriptor.createSubAttribute("supported",
508              AttributeDescriptor.DataType.BOOLEAN,
509              "Boolean value specifying whether sorting is supported",
510              SCIMConstants.SCHEMA_URI_CORE, true, true, false);
511      private static final AttributeDescriptor ETAG_SUPPORTED =
512          AttributeDescriptor.createSubAttribute("supported",
513              AttributeDescriptor.DataType.BOOLEAN,
514              "Boolean value specifying whether Etag resource versions are " +
515                  "supported",
516              SCIMConstants.SCHEMA_URI_CORE, true, true, false);
517      private static final AttributeDescriptor AUTH_SCHEME_NAME =
518          AttributeDescriptor.createSubAttribute("name",
519              AttributeDescriptor.DataType.STRING,
520              "The common authentication scheme name.",
521              SCIMConstants.SCHEMA_URI_CORE, true, true, false);
522      private static final AttributeDescriptor AUTH_SCHEME_DESCRIPTION =
523          AttributeDescriptor.createSubAttribute("description",
524              AttributeDescriptor.DataType.STRING,
525              "A description of the Authentication Scheme.",
526              SCIMConstants.SCHEMA_URI_CORE, true, true, false);
527      private static final AttributeDescriptor AUTH_SCHEME_SPEC_URL =
528          AttributeDescriptor.createSubAttribute("specUrl",
529              AttributeDescriptor.DataType.STRING,
530              "A HTTP addressable URL pointing to the Authentication Scheme's " +
531                  "specification.",
532              SCIMConstants.SCHEMA_URI_CORE, true, false, false);
533      private static final AttributeDescriptor AUTH_SCHEME_DOCUMENTATION_URL =
534          AttributeDescriptor.createSubAttribute("documentationUrl",
535              AttributeDescriptor.DataType.STRING,
536              "A HTTP addressable URL pointing to the Authentication Scheme's " +
537                  "usage documentation.",
538              SCIMConstants.SCHEMA_URI_CORE, true, false, false);
539      private static final AttributeDescriptor XML_DATA_TYPE_SUPPORTED =
540          AttributeDescriptor.createSubAttribute("supported",
541              AttributeDescriptor.DataType.BOOLEAN,
542              "Boolean value specifying whether the XML data format is supported",
543              SCIMConstants.SCHEMA_URI_CORE, true, true, false);
544      private static final AttributeDescriptor PATCH_CONFIG =
545          AttributeDescriptor.createAttribute("patch",
546              AttributeDescriptor.DataType.COMPLEX,
547              "A complex type that specifies PATCH configuration options",
548              SCIMConstants.SCHEMA_URI_CORE, true, true, false,
549              PATCH_SUPPORTED);
550      private static final AttributeDescriptor BULK_CONFIG =
551          AttributeDescriptor.createAttribute("bulk",
552              AttributeDescriptor.DataType.COMPLEX,
553              "A complex type that specifies BULK configuration options",
554              SCIMConstants.SCHEMA_URI_CORE, true, true, false,
555              BULK_SUPPORTED, BULK_MAX_OPERATIONS, BULK_MAX_PAYLOAD_SIZE);
556      private static final AttributeDescriptor FILTER_CONFIG =
557          AttributeDescriptor.createAttribute("filter",
558              AttributeDescriptor.DataType.COMPLEX,
559              "A complex type that specifies Filter configuration options",
560              SCIMConstants.SCHEMA_URI_CORE, true, true, false,
561              FILTER_SUPPORTED, FILTER_MAX_RESULTS);
562      private static final AttributeDescriptor CHANGE_PASSWORD_CONFIG =
563          AttributeDescriptor.createAttribute("changePassword",
564              AttributeDescriptor.DataType.COMPLEX,
565              "A complex type that specifies Change Password configuration options",
566              SCIMConstants.SCHEMA_URI_CORE, true, true, false,
567              CHANGE_PASSWORD_SUPPORTED);
568      private static final AttributeDescriptor SORT_CONFIG =
569          AttributeDescriptor.createAttribute("sort",
570              AttributeDescriptor.DataType.COMPLEX,
571              "A complex type that specifies Sort configuration options",
572              SCIMConstants.SCHEMA_URI_CORE, true, true, false,
573              SORT_SUPPORTED);
574      private static final AttributeDescriptor ETAG_CONFIG =
575          AttributeDescriptor.createAttribute("etag",
576              AttributeDescriptor.DataType.COMPLEX,
577              "A complex type that specifies Etag configuration options",
578              SCIMConstants.SCHEMA_URI_CORE, true, true, false,
579              ETAG_SUPPORTED);
580      private static final AttributeDescriptor AUTH_SCHEMES =
581          AttributeDescriptor.createMultiValuedAttribute("authenticationSchemes",
582              "authenticationScheme", AttributeDescriptor.DataType.COMPLEX,
583              "A complex type that specifies supported Authentication Scheme " +
584                  "properties.",
585              SCIMConstants.SCHEMA_URI_CORE, true, true, false,
586              new String[]{"OAuth", "OAuth2", "HttpBasic", "httpDigest"},
587              AUTH_SCHEME_NAME, AUTH_SCHEME_DESCRIPTION, AUTH_SCHEME_SPEC_URL,
588              AUTH_SCHEME_DOCUMENTATION_URL);
589      private static final AttributeDescriptor XML_DATA_TYPE_CONFIG =
590          AttributeDescriptor.createAttribute(
591              "xmlDataFormat",
592              AttributeDescriptor.DataType.COMPLEX,
593              "A complex type that specifies whether the XML data format is " +
594              "supported",
595              SCIMConstants.SCHEMA_URI_CORE, true, true, false,
596              XML_DATA_TYPE_SUPPORTED);
597    
598      //// 10.  Resource Schema ////
599    
600      private static final AttributeDescriptor RESOURCE_NAME =
601          AttributeDescriptor.createAttribute("name",
602              AttributeDescriptor.DataType.STRING,
603              "The addressable Resource endpoint name",
604              SCIMConstants.SCHEMA_URI_CORE, true, true, false);
605      private static final AttributeDescriptor RESOURCE_DESCRIPTION =
606          AttributeDescriptor.createAttribute("description",
607              AttributeDescriptor.DataType.STRING,
608              "The Resource's human readable description",
609              SCIMConstants.SCHEMA_URI_CORE, true, true, false);
610      private static final AttributeDescriptor RESOURCE_SCHEMA =
611          AttributeDescriptor.createAttribute("schema",
612              AttributeDescriptor.DataType.STRING,
613              "The Resource's associated schema URN",
614              SCIMConstants.SCHEMA_URI_CORE, true, true, false);
615      private static final AttributeDescriptor RESOURCE_ENDPOINT =
616          AttributeDescriptor.createAttribute("endpoint",
617              AttributeDescriptor.DataType.STRING,
618              "The Resource's HTTP addressable query endpoint relative to the " +
619                  "Base URL",
620              SCIMConstants.SCHEMA_URI_CORE, true, true, false);
621    
622      private static final AttributeDescriptor ATTRIBUTES_NAME =
623          AttributeDescriptor.createSubAttribute("name",
624              AttributeDescriptor.DataType.STRING,
625              "The attribute's name", SCIMConstants.SCHEMA_URI_CORE,
626              true, true, false);
627      private static final AttributeDescriptor ATTRIBUTES_TYPE =
628          AttributeDescriptor.createSubAttribute("type",
629              AttributeDescriptor.DataType.STRING,
630              "The attribute's data type", SCIMConstants.SCHEMA_URI_CORE,
631              true, true, false);
632      private static final AttributeDescriptor ATTRIBUTES_MULTIVALUED =
633          AttributeDescriptor.createSubAttribute("multiValued",
634              AttributeDescriptor.DataType.BOOLEAN,
635              "Boolean value indicating the attribute's plurality",
636              SCIMConstants.SCHEMA_URI_CORE, true, true, false);
637      private static final AttributeDescriptor ATTRIBUTES_MULTIVALUED_CHILD_NAME =
638          AttributeDescriptor.createSubAttribute("multiValuedAttributeChildName",
639              AttributeDescriptor.DataType.STRING,
640              "String value specifying the child XML element name; e.g., the " +
641                  "'emails' attribute value is 'email', 'phoneNumbers', is " +
642                  "'phoneNumber'.",
643              SCIMConstants.SCHEMA_URI_CORE, true, false, false);
644      private static final AttributeDescriptor ATTRIBUTES_DESCRIPTION =
645          AttributeDescriptor.createSubAttribute("description",
646              AttributeDescriptor.DataType.STRING,
647              "The attribute's human readable description",
648              SCIMConstants.SCHEMA_URI_CORE, true, true, false);
649      private static final AttributeDescriptor ATTRIBUTES_SCHEMA =
650          AttributeDescriptor.createSubAttribute("schema",
651              AttributeDescriptor.DataType.STRING,
652              "The attribute's associated schema", SCIMConstants.SCHEMA_URI_CORE,
653              true, true, false);
654      private static final AttributeDescriptor ATTRIBUTES_READ_ONLY =
655          AttributeDescriptor.createSubAttribute("readOnly",
656              AttributeDescriptor.DataType.BOOLEAN,
657              "A Boolean value that specifies if the attribute is mutable",
658              SCIMConstants.SCHEMA_URI_CORE, true, true, false);
659      private static final AttributeDescriptor ATTRIBUTES_REQUIRED =
660          AttributeDescriptor.createSubAttribute("required",
661              AttributeDescriptor.DataType.BOOLEAN,
662              "A Boolean value that specifies if the attribute is required",
663              SCIMConstants.SCHEMA_URI_CORE, true, true, false);
664      private static final AttributeDescriptor ATTRIBUTES_CASE_EXACT =
665          AttributeDescriptor.createSubAttribute("caseExact",
666              AttributeDescriptor.DataType.BOOLEAN,
667              "A Boolean value that specifies if the string attribute is case " +
668                  "sensitive",
669              SCIMConstants.SCHEMA_URI_CORE, true, true, false);
670      private static final AttributeDescriptor ATTRIBUTES_CANONICAL_VALUES =
671          AttributeDescriptor.createMultiValuedAttribute("canonicalValues",
672              "canonicalValue", AttributeDescriptor.DataType.STRING,
673              "A collection of canonical values",
674              SCIMConstants.SCHEMA_URI_CORE, true, false, false, null);
675    
676      private static final AttributeDescriptor RESOURCE_SUB_ATTRIBUTES =
677          AttributeDescriptor.newAttribute("subAttributes",
678              "subAttribute", AttributeDescriptor.DataType.COMPLEX,
679              "A list specifying the contained attributes",
680              SCIMConstants.SCHEMA_URI_CORE, true, false,
681              false, ATTRIBUTES_NAME, ATTRIBUTES_TYPE, ATTRIBUTES_DESCRIPTION,
682              ATTRIBUTES_READ_ONLY, ATTRIBUTES_REQUIRED, ATTRIBUTES_CASE_EXACT,
683              ATTRIBUTES_CANONICAL_VALUES);
684    
685      private static final AttributeDescriptor RESOURCE_ATTRIBUTES =
686          AttributeDescriptor.newAttribute("attributes",
687              "attribute", AttributeDescriptor.DataType.COMPLEX,
688              "A complex type that specifies the set of associated " +
689                  "Resource attributes", SCIMConstants.SCHEMA_URI_CORE,
690              true, true, false, ATTRIBUTES_NAME, ATTRIBUTES_TYPE,
691              ATTRIBUTES_MULTIVALUED, ATTRIBUTES_MULTIVALUED_CHILD_NAME,
692              ATTRIBUTES_DESCRIPTION, ATTRIBUTES_SCHEMA,
693              ATTRIBUTES_READ_ONLY, ATTRIBUTES_REQUIRED, ATTRIBUTES_CASE_EXACT,
694              RESOURCE_SUB_ATTRIBUTES);
695    
696      private static final AttributeDescriptor.AttributeDescriptorResolver
697            NESTING_ATTRIBUTES_RESOLVER =
698            new AttributeDescriptor.AttributeDescriptorResolver(true);
699      static
700      {
701        SCIMObject scimObject = new SCIMObject();
702        scimObject.setAttribute(SCIMAttribute.create(
703            RESOURCE_NAME, SCIMAttributeValue.createStringValue(
704            SCIMConstants.RESOURCE_NAME_SCHEMA)));
705        scimObject.setAttribute(SCIMAttribute.create(
706            RESOURCE_DESCRIPTION, SCIMAttributeValue.createStringValue(
707            "The Resource schema specifies the Attribute(s) and meta-data that " +
708                "constitute a Resource")));
709        scimObject.setAttribute(SCIMAttribute.create(
710            RESOURCE_SCHEMA, SCIMAttributeValue.createStringValue(
711            SCIMConstants.SCHEMA_URI_CORE)));
712        scimObject.setAttribute(SCIMAttribute.create(
713            RESOURCE_ENDPOINT, SCIMAttributeValue.createStringValue(
714            SCIMConstants.RESOURCE_ENDPOINT_SCHEMAS)));
715    
716        SCIMAttributeValue[] entries = new SCIMAttributeValue[8];
717    
718        try
719        {
720          entries[0] = AttributeDescriptor.ATTRIBUTE_DESCRIPTOR_RESOLVER.
721              fromInstance(RESOURCE_ATTRIBUTES, ID);
722          entries[1] = NESTING_ATTRIBUTES_RESOLVER.
723              fromInstance(RESOURCE_ATTRIBUTES, META);
724          entries[2] = AttributeDescriptor.ATTRIBUTE_DESCRIPTOR_RESOLVER.
725              fromInstance(RESOURCE_ATTRIBUTES, EXTERNAL_ID);
726          entries[3] = AttributeDescriptor.ATTRIBUTE_DESCRIPTOR_RESOLVER.
727              fromInstance(RESOURCE_ATTRIBUTES, RESOURCE_NAME);
728          entries[4] = AttributeDescriptor.ATTRIBUTE_DESCRIPTOR_RESOLVER.
729              fromInstance(RESOURCE_ATTRIBUTES, RESOURCE_DESCRIPTION);
730          entries[5] = AttributeDescriptor.ATTRIBUTE_DESCRIPTOR_RESOLVER.
731              fromInstance(RESOURCE_ATTRIBUTES, RESOURCE_SCHEMA);
732          entries[6] = AttributeDescriptor.ATTRIBUTE_DESCRIPTOR_RESOLVER.
733              fromInstance(RESOURCE_ATTRIBUTES, RESOURCE_ENDPOINT);
734          entries[7] = NESTING_ATTRIBUTES_RESOLVER.
735              fromInstance(RESOURCE_ATTRIBUTES, RESOURCE_ATTRIBUTES);
736        }
737        catch(InvalidResourceException e)
738        {
739          // This should not occur as these are all defined here...
740          throw new RuntimeException(e);
741        }
742    
743        scimObject.setAttribute(
744            SCIMAttribute.create(RESOURCE_ATTRIBUTES, entries));
745    
746    
747        RESOURCE_SCHEMA_DESCRIPTOR = new ResourceDescriptor(null, scimObject)
748        {
749          @Override
750          public ResourceDescriptor getResourceDescriptor() {
751            return this;
752          }
753    
754          @Override
755          public Collection<AttributeDescriptor> getAttributes() {
756            return getAttributeValues(SCIMConstants.SCHEMA_URI_CORE,
757                "attributes", NESTING_ATTRIBUTES_RESOLVER);
758          }
759        };
760      }
761    
762      /**
763       * The SCIM Resource Schema.
764       */
765      public static final ResourceDescriptor RESOURCE_SCHEMA_DESCRIPTOR;
766    
767    
768      /**
769       * The SCIM Service Provider Configuration Schema.
770       */
771      public static final ResourceDescriptor
772          SERVICE_PROVIDER_CONFIG_SCHEMA_DESCRIPTOR =
773          ResourceDescriptor.create(
774              SCIMConstants.RESOURCE_NAME_SERVICE_PROVIDER_CONFIG,
775              "The Service Provider Configuration Resource enables a Service " +
776              "Provider to expose its compliance with the SCIM specification in " +
777              "a standardized form as well as provide additional implementation " +
778              "details to Consumers",
779              SCIMConstants.SCHEMA_URI_CORE,
780              SCIMConstants.RESOURCE_ENDPOINT_SERVICE_PROVIDER_CONFIG,
781              CONFIG_DOCUMENTATION_URL, PATCH_CONFIG, BULK_CONFIG, FILTER_CONFIG,
782              CHANGE_PASSWORD_CONFIG, SORT_CONFIG, ETAG_CONFIG, AUTH_SCHEMES,
783              XML_DATA_TYPE_CONFIG);
784    
785    
786      /**
787       * The SCIM User Schema.
788       */
789      public static final ResourceDescriptor USER_DESCRIPTOR =
790          ResourceDescriptor.create(SCIMConstants.RESOURCE_NAME_USER,
791              "SCIM core resource for representing users",
792              SCIMConstants.SCHEMA_URI_CORE, SCIMConstants.RESOURCE_ENDPOINT_USERS,
793              USER_NAME, NAME, DISPLAY_NAME, NICK_NAME, PROFILE_URL, TITLE,
794              USER_TYPE, PREFERRED_LANGUAGE, LOCALE, TIMEZONE, ACTIVE, PASSWORD,
795              EMAILS, PHONE_NUMBERS, IMS, PHOTOS, ADDRESSES, GROUPS, ENTITLEMENTS,
796              ROLES, X509CERTIFICATES, EMPLOYEE_NUMBER, COST_CENTER, ORGANIZATION,
797              DIVISION, DEPARTMENT, MANAGER);
798    
799      /**
800       * The SCIM Group Schema.
801       */
802      public static final ResourceDescriptor GROUP_DESCRIPTOR =
803          ResourceDescriptor.create(SCIMConstants.RESOURCE_NAME_GROUP,
804              "SCIM core resource for representing groups",
805              SCIMConstants.SCHEMA_URI_CORE, SCIMConstants.RESOURCE_ENDPOINT_GROUPS,
806              GROUP_DISPLAY_NAME, MEMBERS);
807    
808      /**
809       * The SCIM AttributeDescriptor for the meta attribute.
810       */
811      public static final AttributeDescriptor META_DESCRIPTOR = META;
812    
813      /**
814       * The SCIM AttributeDescriptor for the id attribute.
815       */
816      public static final AttributeDescriptor ID_DESCRIPTOR = ID;
817    }