Novell is now a part of Micro Focus

Extending an NDS Schema with ConsoleOne's NDS Namespace

Articles and Tips: article

LAWRENCE V. FISHER
Senior Research Engineer
Developer Information

01 May 1998


Final article in series on using ConsoleOne and developing snap-ins to support the special NDS objects in your applications. This article describes how to extend and unextend an NDS schema using APIs from a special NDS namespace.

Introduction

Editor's Note: In the March issue of this publication, we began a series of three articles to show you how to develop snap-ins to support the special NDS objects in your applications. This article is the final one in that series.

However, the object model for both ConsoleOne and the special NDS namespace has changed since this article and the previous articles were written. Although most of the source shown in these articles is still accurate, some of it is not.

To show you the necessary revisions, the source files in the project posted on our download site will be made consistent with the April OSA-SDK version of ConsoleOne. This source will reflect the changes that should be made to code shown in all three articles of this series. Also, the project will include a change list describing the differences between the code shown in the articles and the code in the updated project.

In our March issue, an article titled "Snapping Your NDS App into ConsoleOne" described how to develop a series of ConsoleOne snap-ins to add basic support for an NDS enabled application called API_Info. In the April issue, we published a second article titled "Adding a Property Page to ConsoleOne" describing how to develop a ConsoleOne Property Book for your NDS type of object. This article is the third and final article in the series. It describes how to extend and unextend an NDS schema using APIs from a special NDS namespace that may or may not be exposed in the new OSA-SDK.

The "Developing APIInfoToolBarMenuSnapin" section of the March article explained how to extend ConsoleOne's SimpleToolBarMenuSnapin class to add menu item and toolbar button control combinations to the ConsoleOne GUI. This article will describe how to add functionality to the controls described in the March issue so that they will be able to extend and unextend an NDS schema.

In reality, API_Info implements two snap-ins for its tool button/ menu item combinations. Whenever the NDS namespace is selected, the classes for both of these snap-ins will be loaded (see Figure 2).

As shown in Figure 1, the first snap-in will install both a menu item control saying, "Add API_Info Class" and a corresponding tool button control. Both of these controls will ultimately allow a user to extend an NDS schema for API_Info.

The second snap-in will install both a menu item control saying, "Remove API_Info Class" and a corresponding tool button control. Both of these controls will ultimately allow a user to remove APIInfo extensions from an NDS schema.

Figure 1: API_Info uses ConsoleOne's SimpleToolBarMenuSnapin to add two tool button/menu item pairs to ConsoleOne's window when an NDS Namespace is selected.

Figure 2: The APIInfoToolBarMenuSnapin object model.

The APIInfoToolBarMenuSnapin Object Model

As shown in Figure 2, APIInfoToolBarMenuSnapin extends SimpleToolBarMenuSnapin. SimpleToolBarMenuSnapin is an abstract class defined by ConsoleOne which implements both the MenuSnapin and ToolBarSnapin interfaces taking care of a lot of details in the process.

The abstract APIInfoToolBarMenuSnapin further simplifies the development of toolbar button/menu item combinations for APIInfo.

APIInfoClassAdder and APIInfoClassRemover are at the end of the inheritance line. They each separately implement APIInfoToolBarMenuSnapin to produce the two different menu item/tool button snap-ins mentioned earlier. One to add the API_Info schema extensions and one to remove them. These two end classes are virtually identical with the only difference being their state variables.

APIInfoToolBarMenuSnapin Code Description

The source listing and code descriptions below explain how to add functionality to modify an NDS schema to the execute methods in APIInfoClassAdder and APIInfoClassRemover. Explanations for the remainder of code in these classes and for their ancestor APIInfoToolBarMenuSnapin can be found in the March issue.

Notes:

  1. Refer to the March 98 issue for an object model diagram of ConsoleOne. That issue also contains a complete source listing for the APIInfoToolBarMenuSnapin class and the two classes which extend it.

  2. This ConsoleOne snap-in article series uses a unique NDS namespace which simplifies NDS transactions. Refer to the March issue for an object model diagram and class hierarchy for this unique NDS namespace.

  3. In order to use these snap-ins to modify an NDS schema, the user establishing a connection to the target tree must have admin or admin equivalent rights.

  4. For more info on API_Info, see Sept/Oct/Nov 97 issues of this publication. Also, we have developed a Java applet API_Info client developed to work with the API_Info service NLM, see the Dec. 97 and Jan.98 issues of this publication for more information.

  5. The ConsoleOne snap-in sources used in "Snapping Your NDS App in to ConsoleOne" will be available at our download site on the web along with prerelease documentation and other build environment necessities.

  6. The ConsoleOne snap-in project and sources used in the "Snapping Your NDS App in to ConsoleOne" article series are for programming practice purposes only. The NDS namespace snap-in used in the project, may or may not be included with the first release of ConsoleOne.

/***********************************************************

     The group of methods below should be added to the

     APIInfoClassAdder  class described in the March 98 issue.

***********************************************************/



// Executed on  button click or menu selection.

public void execute(boolean state )// state is false (ALWAYS)

{     if( apiCom.apiInfoClassIsDefined())

     {     NMsgBox tellUserAlreadyExtended =

             new NMsgBox(shell.getShellFrame(), "API_Info NDS Tree Extension",

                "The selected NDS tree is already extended for API_Info classes",

                                     NMsgBox.INFO, null, null);

        tellUserAlreadyExtended.show();

     }

     else

     {     Frame shellFrame = shell.getShellFrame();

        Cursor oldCursor = shellFrame.getCursor();

        shellFrame.setCursor(new Cursor(Cursor.WAIT_CURSOR));

        if( addAPI_InfoExtensions() )

            {     shellFrame.setCursor(oldCursor);

             setNDSTreeIsAPI_InfoExtended (true);

             NMsgBox tellUserNowExtended =

                new NMsgBox(shell.getShellFrame(), "API_Info NDS Tree Extension",

                                             the selected NDS tree has now been"+

                                                 "extended for API_Info classes",

                                                       NMsgBox.INFO, null, null);

             tellUserNowExtended.show();

        }

        else

            {     shellFrame.setCursor(oldCursor);

             setNDSTreeIsAPI_InfoExtended (false);

        }

       }

}



public boolean addAPI_InfoExtensions( )

1{     boolean aPIInfoExtensionsAdded = false;

2     NDSSchemaDefinition schemaDefinition = apiCom.getSchemaDefinition();

3     if(schemaDefinition!= null)

4     {     NDSAttributeDefinition[] apiAttrDefs = new NDSAttributeDefinition[3];

5       apiAttrDefs[0] = apiCom.getAttributeDefinition("CN");

6       apiAttrDefs[1] =createAPIInfoAttrDef(APIInfoCommon.API_INFO_SERVER_ATTRNAME );

7       apiAttrDefs[2] = createAPIInfoAttrDef(APIInfoCommon.API_INFO_OPRTR_ATTRNAME );

8       try

9       {     schemaDefinition.putAttributeDefinition(apiAttrDefs[1]);

10               schemaDefinition.putAttributeDefinition(apiAttrDefs[2]);

11               NDSClassDefinition apiClassDef = createAPIInfoClassDef(apiAttrDefs);

12               if( apiClassDef != null )

13               {     try

14                    {     schemaDefinition.putClassDefinition(apiClassDef);

15                         aPIInfoExtensionsAdded = true;

16                    }

17                    catch(NamespaceException e) {  e.printStackTrace() }

18               }

19          }

20          catch(SPIException e)     {  e.printStackTrace() }

21          catch(NDSNamespaceException e)   {  e.printStackTrace() }

22          catch(PropertyVetoException e)   {  e.printStackTrace() }

23     }

24     return( aPIInfoExtensionsAdded );

25}



public NDSAttributeDefinition createAPIInfoAttrDef(String attrName )

1{     NDSAttributeDefinition attrDef = null;

2     int flagInt =     NDSAttributeFlags.SINGLE_VALUED |

3                                         NDSAttributeFlags.SYNC_IMMEDIATE |

4                                         NDSAttributeFlags.PUBLIC_READ ;

5     NDSAttributeFlags flags = new NDSAttributeFlags( flagInt );

6     attrDef = new NDSAttributeDefinition(     attrName,

7                                                 NDSSyntax.SYN_DIST_NAME,

8                                                 flags,

9                                                 0,0,null          );

10     return attrDef;

11}



public NDSClassDefinition createAPIInfoClassDef(NDSAttributeDefinition[] mandatorys )

1{     NDSClassDefinition classDef = null;

2     NDSSchemaDefinition schemaDefinition = apiCom.getSchemaDefinition();

3     if(schemaDefinition!= null)

4     {     int flagInt =   NDSClassFlags.EFFECTIVE_CLASS ;

5          NDSClassFlags flags = new NDSClassFlags( flagInt );

6

7          String[] supers = new String[1];

8          supers[0] = "Top";

9

10          String[] containers = new String[2];

11          containers[0] = "Organization";

12          containers[1] = "Organizational Unit";

13

14          NDSAttributeDefinition[] namers = new NDSAttributeDefinition[1];

15          namers[0] = apiCom.getAttributeDefinition("CN");

16

17          NDSAttributeDefinition[] optionals = null;

18

19          classDef = new NDSClassDefinition(     APIInfoCommon.API_INFO_CLASSNAME,

20                                                 flags,

21                                                 containers,

22                                                 supers,

23                                                 mandatorys,

24                                                 namers,

25                                                 optionals,

26                                                 null   );

27     }

28     return (classDef);

29 }





/***********************************************************

  The group of methods below should be added to the

  APIInfoClassRemover  class described in the March 98 issue.

***********************************************************/

public void execute(boolean state )// state is false (ALWAYS)

{     if(!apiCom.apiInfoClassIsDefined())

     {     NMsgBox tellNotExtended =

               new NMsgBox(shell.getShellFrame(), "API_Info schema Extension",

                         "The selected NDS tree is not "+

                         "currently extended for API_Info classes",

                         NMsgBox.INFO, null, null);

          tellNotExtended.show();

     }

     else

     {     NMsgBox askUser4Delete =

               new NMsgBox(shell.getShellFrame(), "API_Info NDS Tree Extension",

                            "Are you sure that you want to delete the API_Info"+

                            " schema extensions from this tree?",

                            NMsgBox.WARN, null, null);

          askUser4Delete.show();

          if      (     askUser4Delete.getPressedButton() == NMsgBox.YES )

          {     Frame shellFrame = shell.getShellFrame();

               Cursor oldCursor = shellFrame.getCursor();

               shellFrame.setCursor(new Cursor(Cursor.WAIT_CURSOR));



               if(     removeAPI_InfoExtensions() )

               {     shellFrame.setCursor(oldCursor);

                    NMsgBox tellUserXtnsnDeleted =

                           new NMsgBox(shell.getShellFrame(),

                                           "API_Info NDS Tree Extension",

                                           "API_Info NDS schema extensions are deleted",

                                          NMsgBox.INFO, null, null);

                    tellUserXtnsnDeleted.show();

                    setNDSTreeIsAPI_InfoExtended (false);

               }

               else

               {     shellFrame.setCursor(oldCursor);     }

          }

     }

}



public boolean removeAPI_InfoExtensions( )

1{     boolean extensionRemoved = false;

2     NDSSchemaDefinition schemaDefinition = apiCom.getSchemaDefinition();

3     try

4     {     schemaDefinition.removeClassDefinition(APIInfoCommon.API_INFO_CLASSNAME);

5     schemaDefinition.

6          removeAttributeDefinition(APIInfoCommon.API_INFO_SERVER_ATTRNAME);

7          schemaDefinition

8          .removeClassDefinition(APIInfoCommon.API_INFO_OPRTR_ATTRNAME);

9          extensionRemoved = true;

10     }

11     catch(NamespaceException e)     {  e.printStackTrace()}

12     catch(SPIException e)            {  e.printStackTrace()}

13     catch(PropertyVetoException e)     {  e.printStackTrace()}

14     return(extensionRemoved);

15}



/***********************************************************

  The APIInfoCommon class

***********************************************************/

package com.novell.admin.ndssnapins.classes.shared.apiinfo;

import java.awt.*;

import java.net.*;

import com.novell.admin.common.exceptions.*;

import com.novell.admin.ns.*;

import com.novell.admin.ns.nds.*;

import com.novell.application.console.snapin.*;





public class APIInfoCommon

{

public final static String API_INFO_SERVER_ATTRNAME = "APIINFO:APIInfo Server";

public final static String API_INFO_OPRTR_ATTRNAME  = "APIINFO:APIInfo Operator";

public final static String API_INFO_CLASSNAME       = "APIINFO:APIInfoClass";

public final static

     String IMAGE_PATH= "/com/novell/admin/ndssnapins/classes/shared/apiinfo/images/";

private  Shell  shell               = null;

private  booleanextensionChecked= false;



     //must be instantiated by classes that wish to use its methods

     public APIInfoCommon (Shell theShell)

     {     shell = theShell;     }



     public  boolean apiInfoClassIsDefined()

     {     boolean isDefined = false;

                 if(!extensionChecked)

                 {

               NDSSchemaDefinition schemaDefinition = getSchemaDefinition( );

               isDefined =

               schemaDefinition.isAttributeDefined(API_INFO_SERVER_ATTRNAME);

               extensionChecked = true;

          }

     return isDefined;

     }

     public  NDSSchemaDefinition getSchemaDefinition()

1     {     NDSSchemaDefinition schemaDef = null;

2          ObjectEntry oe = shell.getTreeSelection();

3          NamespaceSnapin nsSnapin = oe.getObjectType().getNamespace();

4          if( nsSnapin instanceof NDSNamespace )

5          {     NDSNamespace ndsNamespace = (NDSNamespace)nsSnapin;

6               try

7               {     schemaDef=(NDSSchemaDefinition)ndsNamespace.getSchemaDefinition(oe);}

8               catch     (     SPIException e)

9               {     NmsgBox nbox = new NMsgBox( shell.getShellFrame(), "SPIException",

10                    "APIInfoCommon.getSchemaDefinition()"+e.toString(),NMsgBox.ERROR );

11                    return null;

12               }

13          }

          return schemaDefinition;

     }

     public  NDSAttributeDefinition getAttributeDefinition(String attributeName )

     {     NDSAttributeDefinition attributeDefinition = null;

     SchemaDefinition schemaService = getSchemaDefinition( );

     if(     schemaService != null )

     {     try

          {     attributeDefinition = (NDSAttributeDefinition)schemaService.

                                          getAttributeDefinition(attributeName);

          }

          catch ( NamespaceException e){   return null;   }

          }

     return attributeDefinition;

     }

     public  NDSClassDefinition getAPIClassDefinition( )

     {     NDSClassDefinition classDefinition = null;

          SchemaDefinition schemaService = getSchemaDefinition( );

          if(     schemaService != null )

          {     try

               {     classDefinition =

                    (NDSClassDefinition)schemaService.

                                       getClassDefinition(API_INFO_CLASSNAME);

               }

               catch ( NamespaceException e) {  return null;   }

          }

          return classDefinition;

     }



     public Image getImage(Object requestor,String path)

     {     Image img=null;

          URL url = requestor.getClass().getResource(path);

          if(url != null)

          {     img = Toolkit.getDefaultToolkit().getImage(url); }

          else

          {     System.err.println("Error loading image!");  }

          MediaTracker tracker = new MediaTracker(shell.getShellFrame());

          tracker.addImage(img,1);

          try

          {     tracker.waitForAll();}

          catch ( InterruptedException e) {return null;}

          return img;

     }

}

General Information About the Source Code Above

Notice that there are three groups of code in the source listing:

APIInfoClassAdder Methods. The "Snapping Your NDS App into ConsoleOne" article in the March issue lists the basic code for the APIInfoClassAdder class. That article described how to extend the ConsoleOne GUI with an "Add APIInfo Class" menu item and a corresponding tool bar item. Selecting either of these controls will cause the class's execute( ) method to be called. In the March article, the execute( ) method was shown as a stub. So, that issue's version of APIInfoClassAdder had no real functionality associated with its added controls.

The first group of methods in this article's source listing shows what should go inside of APIInfoClassAdder's execute( ) method and provides some additional methods that would be needed in order to actually extend the schema for APIInfo.

APIInfoClassRemover Methods. In addition to the APIInfoClassAdder class, the "Snapping Your NDS App into ConsoleOne" article in the March issue also lists the basic code for the APIInfoClassRemover class. Its execute( ) method was also a stub. As in APIInfoClassAdder, that version of APIInfoClassRemover had no real functionality associated with the controls that it added to the ConsoleOne GUI.

The second group of methods in this article's source listing shows what should go inside of APIInfoClassRemover's execute( ) method and provides some additional methods that would be needed in order to actually remove APIInfo's schema extension.

APIInfoCommon Class. Various APIInfo ConsoleOne snap-ins require some common functionality. The APIInfoCommon class serves as a library which provides this functionality to all APIInfo snap-ins.

APIInfoClassAdder's execute( ) Method

APIInfoClassAdder's execute( ) method will be called when the user selects either the "Add APIInfo Class" menu item under the "Tools" menu or its associated tool item (see Figure 1).

The purpose of APIInfoClassAdder's execute( ) method is to modify the selected NDS namespace's (tree's) schema by adding the API_Info class to it. The objects instantiated from this class will be used to contain information that clients can use to help them find the best instance of a API_Info service. Trees that don't have this class cannot instantiate API_Info objects and therefore won't work with the API_Info application.

When APIInfoClassAdder's execute( ) method is called, the first thing it does is to call the apiInfoClassIsDefined( ) method in APIInfoClassAdder's APIInfoCommon instance.

apiInfoClassIsDefined( ) is used here to determine if the selected NDS namespace's schema is already extended. If it is, the user is notified and the method ends.

If the schema is not yet extended, the cursor is changed to a WAIT_CURSOR and APIInfoClassAdder's addAPI_InfoExtensions( ) method is called to extend the schema for APIInfo (described below).

APIInfoClassAdder's addAPI_InfoExtensions( ) Method

NDS schemas establish the kinds of objects that can be added to the NDS database on a given tree. Initially, all trees have the same NDS schema, called the base schema, provided by Novell. However, as you will see, schemas can be modified.

Here are some of the things that you, as a programmer, can do with the NDS schema: add new classes, add attributes to the new classes or add attributes to base classes, delete non-base classes or attributes, get information about a class, get a list of the attributes in a class, get a list of which classes can contain a class, and more. The NDS namespace used for the projects in this series provides functionality to make all of these tasks easier for you.

APIInfoClassAdder's addAPI_InfoExtensions( ) method is called to extend a schema for two special APIInfo attributes and one APIInfo class which uses the two attributes.

Line 2 An NDSSchemaDefinition object contains the methods needed to modify an NDS schema, so one is obtained using the APIInfoCommon method getSchemaDefinition( ).

Lines 5-7 An array of APIInfo's mandatory NDSAttributeDefinitions is created. The APIInfo class is designed to have four mandatory attributes:

  1. Object Class- The object class attribute will contain the name of the object's class. In API_Info's case, the Object Class attribute is needed so that the object can be searched for by its class name. This is how the API_Info client finds all of the instances of the API_Info object when it searches a tree.

  2. Common Name (CN)- The Common Name attribute is needed so that the object can be searched for by the name given to it by the administrator. The API_Info client doesn't use this feature right now, but it could be used in the future.

  3. APIInfo:Server- The APIInfo Server attribute contains the distinguished name of the server running an API_Info NLM. In the APIInfo application, after the client finds an APIInfo object, it can use its APIInfo Server attribute to make its connection to the target server.

  4. APIInfo:Operator- The APIInfo Operator attribute is intended to contain the distinguished name of the user object representing the person responsible for loading the API_Info NLM on the server named in the APIInfo Server attribute. In the APIInfo application, this attribute will be accessed if an attempt to connect with the API_Info NLM on the host server fails for some reason.

For the API_Info class's mandatory attributes array, we specify common name, APIInfo Server, and APIInfo Operator. Recall that API_Info also has the object class mandatory attribute. The reason we don't need to add the Object Class attribute here is because the API_Info class will inherit that attribute from Top (explained later).

The CN attribute comes from the pool of standard NDS attributes so it must already be in the schema. A definition object for the CN attribute is obtained from the namespace using the APIInfoCommon method getAttributeDefinition( ).

The APIInfo Server and Operator attributes are special to APIInfo, so this class's createAPIInfoAttrDef( ) is called to create each (createAPIInfoAttrDef( ) is explained later).

Lines 9-10 Because the APIInfo class requires its special Server and Operator attributes, they must be installed in the schema before the attempt to create an APIInfo class definition. Using putAttributeDefinition( ) method calls, the new attributes are added to the schema. After these calls, the attributes are available to create the new APIInfo class.

Line 11 Because APIInfo's special Server and Operator attributes are now in the schema, an APIInfo class definition can be created in this class's createAPIInfoClassDef( ) method (explained later).

After createAPIInfoClassDef( ), an NDSClassDefinition will have been created for the APIInfo class with APIInfo's two special attributes but the schema will not yet be extended for the class.

Line 14 The created APIInfo class definition object is commited to the NDS tree's schema with the SchemaDefinition object's putClassDefinition( ) method. After putClassDefinition( ), APIInfo objects can be created in the tree.

APIInfoClassAdder's createAPIInfoAttrDef( ) Method

The purpose of the createAPIInfoAttrDef( ) method is to create APIInfo's two special attributes, Server and Operator.

Lines 1-5 First, createAPIInfoAttrDef( ) sets up the flags for the new attributes. We want both of the new attributes to have only a single value and be synchronized immediately with any replicas of the tree. We also want to allow reads of these attributes without the normal NDS security restrictions.

Normally, default NDS security requires that the NDS user object representing the person that obtained ConsoleOne's current authenticated connection to this NDS tree be associated with the target attribute in the target object's access control list (or ACL) before a read operation is allowed. However, putting entries into an object's ACL requires administrator intervention.

So, to avoid putting extra work onto the administrator, we give these attributes the PUBLIC_READ constraint allowing them to be read from an APIInfo object by any other object whether or not the other object is listed in the APIInfo object's ACL.

This will allow any client to read the API_Info Server and Operator attributes in any APIInfo object without special setup by the administrator.

Lines 6-9 Syntaxes are special typedefs created by Novell to be the data types used in attributes. NDS syntaxes can only be created by Novell. Every NDS attribute is built upon a standard syntax which defines the attribute value's data format and the kinds of comparisons that NDS can make to the attribute's value during a search.

The syntax used for the special APIInfo attributes is SYN_DIST_NAME, which specifies a distinguished name. Because these attributes are based on this syntax, when the administrator tries to create an object containing either of the special API_Info attributes, a fully distinguished name complete with the object's context in the tree and its object name will be required for initialization. If the administrator tries to enter any less than that for either of these attributes, NDS will give him an error.

The SYN_DIST_NAME value is passed to an NDSAttributeDefinition constructor to instantiate an NDSAttributeDefinition describing the new attribute.

APIInfoClassAdder's createAPIInfoClassDef( ) Method

The purpose of the createAPIInfoClassDef( ) method is to create APIInfo's special class. An NDS class has multiple categories of information, as shown below.

Class Flags. Classes have certain fixed characteristics that are dictated by its class flags. The following are some class flags:

  • AMBIGUOUS_CONTAINMENT - can be contained by objects from more than one namespace

  • AMBIGUOUS_NAMING - can be named in more than one namespace

  • CONTAINER_CLASS - can be used to contain other object types

  • EFFECTIVE_CLASS - can be instantiated and is therefore not abstract

  • NONREMOVABLE_CLASS - once installed in a schema, cannot be removed

Super Classes. The super classes item in a class definition are intended to specify the classes that the class inherits from. The superclasses entries from all classes collectively establish the structure of the class hierarchy in an NDS schema. NDS supports multiple inheritance, so many class names can be entered into this item. Top is intended to be the topmost class in the NDS class hierarchy so Top has no superclasses.

Containers. The containment item specifies the classes of container objects that can contain objects of this class.

Mandatory Attributes. The entries in the mandatory attributes item specify attributes that must be defined and initialized to appropriate values at the object's instantiation.

Named By Attributes. The "named by" item specifies the attributes in the class that can be used to name objects instantiated from the class. For example, after an administrator creates an API_Info object, the administrator could name it "Larry's API_Info Server" to designate the object for use by Larry. This "named by" attribute could then be accessed whenever the tree is searched for objects with that name or a substring of that name, "Larry" for instance.

Optional Attributes. Optional attributes are not required to have values when the object is instantiated. Values can be added to optional attributes later.

Lines 4-5 The APIInfo class is concerned only with the EFFECTIVE_CLASS flag. Every class definition must specify whether or not an object can be created or instantiated from the class. Non-effective classes are used only to provide an inheritance to their subclasses and are never actually intended to be instantiated into objects. Effective classes can be instantiated as well as provide composition for inheritance. Top class is the only exception. Even though Top class is defined as being an effective class, Top cannot be instantiated.

Lines 7-8 The APIInfo class has only one superclass, Top. This means that APIInfo inherits all of Top's mandatory and optional attributes.

Lines 10-12 The APIInfo class can be contained by "Organization" or "Organizational Unit" container objects.

Lines 14-15 The APIInfo class can be named by the "CN" or common name attribute. The "CN" attribute is a base NDS attribute which is already a part of every NDS schema. This means that an AttributeDefinition describing the pre-existing "CN" attribute can be obtained using the SchemaDefinition object.

Line 17 No specific optional attributes are needed for APIInfo, so we pass null. Also, remember that API_Info will inherit several optional attributes from Top, including the important ACL attribute.

Lines 19-26 The first parameter in the constructor for an NDSClassDefinition is the class name. Schema extensions require unique identification. Two different extensions with the same name would cause NDS a great deal of confusion. Because of this, Novell provides developers with a service for registering their schema extensions. Please contact Novell to register your schema extension before releasing an application using a schema extension.

After the NDSClassDefinition constructor, the classDef variable references an object which describes the APIInfo class in the format required by the NDS namespace, but the class does not yet exist in the tree's schema. An NDS tree's schema is actually extended with this class definition by passing it into the SchemaDefinition method, putClassDefinition( ).

APIInfoClassRemover's execute( ) Method

APIInfoClassRemover's execute( ) method will be called when the user selects either the "Remove APIInfo Class" menu item under the "Tools" menu or its associated tool item (see Figure 1).

The purpose of APIInfoClassRemover's execute( ) method is to remove the APIInfo schema extensions from the selected NDS namespace's (tree's) schema. Trees that don't have this class cannot instantiate API_Info objects and therefore won't work with the API_Info application.

When APIInfoClassRemover's execute( ) method is called, the first thing it does is to call the apiInfoClassIsDefined( ) method in APIInfoClassAdder's APIInfoCommon instance to determine if the selected NDS namespace's schema is already extended. If the schema has not been extended for APIInfo, the user is notified and the method ends.

If the schema has been extended, the cursor is changed to a WAIT_CURSOR and APIInfoClassRemover's removeAPI_InfoExtensions( ) method is called to remove the APIInfo extensions from the schema (described below).

APIInfoClassRemover's removeAPI_InfoExtensions( ) Method

This method removes APIInfo's special class and attributes from an NDS schema.

Line 2 An NDSSchemaDefinition object contains the methods needed to modify an NDS schema, so one is obtained using the APIInfoCommon method getSchemaDefinition( ) (explained later in the APIInfoCommon code descriptions).

Lines 4-8 APIInfo's special attributes are accessed when the class type is removed by the schema. For this reason, the class removal must take place before the attributes are removed.

APIInfoCommon's apiInfoClassIsDefined( ) Method

This method uses a SchemaDefinition object method to check for one of the special APIInfo attributes. The assumption is that the APIInfo schema extensions are always added and removed as a set. So, if one of them exists, all of them must exist. If one of them is missing, (one of APIInfo's special attributes for example), then all of them must be missing.

APIInfoCommon's getSchemaDefinition( ) Method

Lines 2-5 The ObjectEntry returned from the getTreeSelection( ) method is the selected object in the tree navigator pane in the ConsoleOne window. Since this snap-in was registered for the NDS namespace, nsSnapin will be an NDS namespace.

Downloadable Sources

You can obtain the sources for all six of the ConsoleOne snap-ins described in this series at: http://www.novell.com/coolsolutions/tools/index.html


Disclaimer

The origin of this information may be internal or external to Novell. While Novell makes all reasonable efforts to verify this information, Novell does not make explicit or implied claims to its validity.

© Copyright Micro Focus or one of its affiliates