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