| Schema

## Two Practical Examples

> How could you use this schema facility? This section shows two examples that use the schema. The first is a program that creates a new entry in the directory. It uses the schema to find out what attributes are required for the new entry. The second example is more ambitious. It creates an entry that may use new object classes, which in turn may use new attribute type definitions.

> #### Using the Existing Schema

> The following example is called `UseSchema`. It accepts as a command line argument the name of the entry to create. For example, to create a new entry called `"cn=TestPerson"` in the `"ou=People"` subtree, you enter at the prompt

> >     # java UseSchema "cn=TestPerson, ou=People"

> The program starts by asking you to enter the list of object classes for the new entry. After entering a list of object class names, you terminate the list by pressing Return. Working with this list of object class names, the program uses the schema to determine the list of mandatory and optional attributes required to create the new entry. This determination process is implemented by `getAttributeLists()`.

> >     static Vector[] getAttributeLists(DirContext schema, Vector objectClasses)
> >         throws NamingException {
> >         Vector mandatory = new Vector();
> >         Vector optional = new Vector();

> >         for (int i = 0; i < objectClasses.size(); i++) {
> >             String oc = (String)objectClasses.elementAt(i);
> >             Attributes ocAttrs =
> >       	    schema.getAttributes("ClassDefinition/" + oc);
> >     	Attribute must = ocAttrs.get("MUST");
> >     	Attribute may = ocAttrs.get("MAY");

> >     	if (must != null) {
> >     	    addAttrNameToList(mandatory, must.getAll());
> >     	}
> >     	if (may != null) {
> >     	    addAttrNameToList(optional, may.getAll());
> >     	}
> >         }
> >         return new Vector[] {mandatory, optional};
> >     }

> Note that for completeness, you should modify this example to recursively fetch the parents of the object classes and include them in your list of object classes to process. This is because some servers might follow subclassing rules and list only attributes of the most derived object class. Some servers list all of the attributes of the object class, including those inherited from superclasses.

> The program looks up each object class name in the `"ClassDefinition"` portion of the schema tree and extracts from it the `"MUST"`/`"MAY"` attributes. These contain lists of names of attributes that an entry of that object class must and may have.

> After constructing the list of mandatory and optional attribute names, the program uses `getAttributeValues()` to ask you to enter values for each attribute. (Press Return if you do not want to enter a value for an attribute.) The program uses each attribute's schema definition to get the attribute's syntax and then uses that syntax as part of the user prompt.

> >     Attributes attrSchema = schema.getAttributes("AttributeDefinition/" + name);
> >     Attribute syntax = attrSchema.get("SYNTAX");

> In practice, this is not very helpful because the syntax is an OID and few users will recognize what it represents. However, you can use the attribute schema definition in more useful ways, such as displaying its description and looking up the syntax to get its description.

> After getting the attributes for the new entry, the program invokes `DirContext.createSubcontext()` to create the new entry.

> #### Augmenting the Existing Schema

> > Before you go on: See the Object Class Definitions section for notes regarding updating the schema.

> In the `UseSchema` example, you can only enter object classes defined in the schema. If you enter an object class that does not exist in the schema, then the program throws a `NameNotFoundException`.

> The next example, `AugmentSchema`, allows you to enter object classes that have not been defined yet. You run the program by supplying the name of the entry to create as a command line argument as follows:

> >     # java AugmentSchema "cn=TestPerson, ou=People"

> As with the `UseSchema` program, you next enter a list of object classes for the new entry. With the `AugmentSchema` program, you may enter object classes that have not yet been defined. After getting this list, the program uses `checkDefinition()` to check whether the object classes have been defined. This method accepts as arguments the root of the schema tree, the list of object class names to check, the type of schema object (e.g., `"ClassDefinition"` or `"AttributeDefinition"`), and the list of attributes required for defining a schema object of that type. Here is the code for `checkDefinition()`.

> >     static void checkDefinition(DirContext schema, Vector names,
> >         String schemaType, String[]schemaAttrIDs) throws NamingException, IOException {
> >             DirContext root = (DirContext)schema.lookup(schemaType);
> >             for (int i = 0; i < names.size(); i++) {
> >       	    String name = (String)names.elementAt(i);
> >     	    try {
> >     		// Check if the definition already exists in the schema
> >     		root.lookup(name);
> >         	    } catch (NameNotFoundException e) {
> >      	        // Get the definition from the user
> >     	        Attributes schemaAttrs = getDefinition(schemaType, name, schemaAttrIDs);

> >     	        // Add the definition to the schema
> >     	        root.createSubcontext(name, schemaAttrs);
> >                 }
> >     	}
> >         }
> >     }

> For each object class that does not have a schema definition, the program creates a schema definition by asking you for the attributes needed to define it in the schema, such as its OID, name, and its list of mandatory and optional attributes. The program then creates an object class definition by invoking `createSubcontext()` on the schema tree.

> > Note: When using the Netscape Directory Server v4.1 you need to ensure that an object class's `"MUST"`/`"MAY"` attributes have more than one attribute value. See the Object Class Definitions section for details.

> After doing this for all object classes in the list, the program gets the object classes' lists of mandatory and optional attributes from the schema. It then checks these lists to make sure that they have attribute definitions in the schema, again by using `checkDefinition()`. For each attribute that does not have a definition in the schema, the program creates a schema definition by asking you for the attributes needed to define it in the schema, such as its OID, name, and syntax. The program then creates an attribute definition by invoking `createSubcontext()` on the schema tree.

> The program gathers data for the attributes for the new entry and uses `createSubcontext()` to create the new entry.

> Schema: End of Lesson

> What's next? Now you can:

> - Continue on in this trail to learn about LDAP controls and extensions.
> - Go to the Frequently Asked Questions lesson to read about questions that LDAP users have when using the JNDI.

| Schema