# How to Use the SAS Java Metadata Interface

- Package Description
- Example 1: Server Connection
- Example 2: Get Repositories
- Example 3: Get Metadata Types
- Example 4: Create Objects
- Example 5: Read Objects
- Example 6: Delete Objects
- Example 7: Get all objects of a particular type
- Example 8: Get an existing object
- Sample Program

## Sample Program

The following is a sample program that illustrates how to connect to a metadata server, create new objects, and read existing objects.

    import java.rmi.RemoteException;
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;

    import com.sas.metadata.remote.AssociationList;
    import com.sas.metadata.remote.CMetadata;
    import com.sas.metadata.remote.Column;
    import com.sas.metadata.remote.MdException;
    import com.sas.metadata.remote.MdFactory;
    import com.sas.metadata.remote.MdFactoryImpl;
    import com.sas.metadata.remote.MdOMIUtil;
    import com.sas.metadata.remote.MdOMRConnection;
    import com.sas.metadata.remote.MdObjectStore;
    import com.sas.metadata.remote.MetadataObjects;
    import com.sas.metadata.remote.PhysicalTable;
    import com.sas.metadata.remote.TextStore;

    /**
     * This is a test class that contains the examples for SAS Java Metadata Interface.
     */
    public class MdTesterExamples
    {

       /**
        * This is the object factory used to create objects.
        */
       private MdFactory _factory = null;

       /**
        * Default constructor
        */
       public MdTesterExamples()
       {
          //intialize the factory
          initializeFactory();
       }

       private void initializeFactory()
       {
          try
          {
             // Construct a new factory.  The boolean parameter is used to determine if
             // the application is running in a remote or local environment.  If the
             // data does not need to be accessible across remote JVMs, then
             // "false" can be used.
             _factory = new MdFactoryImpl(false);

             // Intialize debug logging if necessary
             boolean debug = false;
             if (debug)
             {
                _factory.setDebug(true);
                _factory.setLoggingEnabled(true);

                // Set the output streams for logging.  The logging output can be
                // directed to any OutputStream, including a file.
                _factory.getUtil().setOutputStream(System.out);
                _factory.getUtil().setLogStream(System.out);
             }
             else
             {
                _factory.setDebug(false);
                _factory.setLoggingEnabled(false);
             }

             // To be notified when changes have been persisted to the metadata server
             // within this factory (this includes adding objects, updating objects, and
             // deleting objects), we can add a listener to the factory.
             //
             // See MdFactory.addMdFactoryListener()
          }
          catch (Exception e)
          {
             e.printStackTrace();
          }
       }

       /**
        * This example makes a connection to the metadata server and checks
        * exceptions if there is an error connecting.  The server name, port,
        * user, and password variables must be substituted with actual values.
        * @return true if the connection was successful
        */
       public boolean connectToServer()
       {
          String serverName = "MACHINE_NAME";
          String serverPort = "8561";
          String serverUser = "USERNAME";
          String serverPass = "PASSWORD";

          try
          {
             MdOMRConnection connection = _factory.getConnection();

             // this statement makes the connection to the server
             connection.makeOMRConnection(serverName, serverPort, serverUser, serverPass);

             // the following statements define error handling and error
             // reporting messages.
          }
          catch (MdException e)
          {
             Throwable t = e.getCause();
             if (t != null)
             {
                String ErrorType = e.getSASMessageSeverity();
                String ErrorMsg = e.getSASMessage();
                if (ErrorType == null)
                {
                   // if there is no SAS server message, write a Java/CORBA message.
                }
                else
                {
                   // if there is a message from the server:
                   System.out.println(ErrorType + ": " + ErrorMsg);
                }
                if (t instanceof org.omg.CORBA.COMM_FAILURE)
                {
                   // if there is an invalid port number or host name:
                   System.out.println(e.getLocalizedMessage());
                }
                else if (t instanceof org.omg.CORBA.NO_PERMISSION)
                {
                   // is there is an invalid user ID or password:
                   System.out.println(e.getLocalizedMessage());
                }
             }
             else
             {
                // if we cannot find a nested exception, get message and print.
                System.out.println(e.getLocalizedMessage());
             }
             // if there is an error, print the entire stack trace.
             e.printStackTrace();
             return false;
          }
          catch (RemoteException e)
          {
             //unknown exception.
             e.printStackTrace();
             return false;
          }
          // If no errors occur, then a connection is made.
          return true;
       }

       /**
        * This example displays the status of the metadata server.
        */
       public void displayServerInformation()
       {
          try
          {
             MdOMRConnection connection = _factory.getConnection();

             // Check the status of the metadata server
             System.out.println("\nGetting server status...");
             int status = connection.getServerStatus();
             switch (status)
             {
                case MdOMRConnection.SERVER_STATUS_OK:
                   System.out.println("Server is running");
                   break;
                case MdOMRConnection.SERVER_STATUS_PAUSED:
                   System.out.println("Server is paused");
                   break;
                case MdOMRConnection.SERVER_STATUS_ERROR:
                   System.out.println("Server is not running");
                   break;
             }

             // Check the version of the metadata server
             int version = connection.getPlatformVersion();
             System.out.println("Server version: " + version);
          }
          catch (MdException e)
          {
             e.printStackTrace();
          }
          catch (RemoteException e)
          {
             e.printStackTrace();
          }
       }

       /**
        * This example retrieves a list of the repositories registered on the server.
        * @return the list of available repository (list of CMetadata objects)
        */
       public List getRepositories()
       {
          try
          {
             // Get a list of repositories.
             System.out.println("\nThe repositories contained on this server are: ");

             MdOMIUtil omiUtil = _factory.getOMIUtil();
             List reposList = omiUtil.getRepositories();
             Iterator iter = reposList.iterator();
             while (iter.hasNext())
             {
                //print the name and id of each repository
                CMetadata repository = (CMetadata) iter.next();
                System.out.println("Repository: " +
                                   repository.getName()
                                   + " (" + repository.getFQID() +")");
             }
             return reposList;
          }
          catch (MdException e)
          {
             e.printStackTrace();
          }
          catch (RemoteException e)
          {
             e.printStackTrace();
          }
          return new ArrayList();
       }

       /**
        * This example lists the metadata types available on the metadata server
        * and their descriptions.
        */
       public void displayMetadataTypes()
       {
          try
          {
             // Get a list of metadata types available on the server.
             System.out.println("\nThe object types contained on this metadata server are: ");
             List nameList = new ArrayList(100);
             List descList = new ArrayList(100);
             _factory.getOMIUtil().getTypes(nameList, descList);
             Iterator iter1 = nameList.iterator();
             Iterator iter2 = descList.iterator();
             while (iter1.hasNext() && iter2.hasNext())
             {
                //print the name and description of each metadata object type
                String name = (String) iter1.next();
                String desc = (String) iter2.next();
                System.out.println("Type: " +
                                    name +
                                    ", desc: " +
                                    desc);
             }
          }
          catch (MdException e)
          {
             e.printStackTrace();
          }
          catch (RemoteException e)
          {
             e.printStackTrace();
          }
       }

       /**
        * This method creates a table, column, and note on the column, using
        * the store methods. It is a good example of how a wizard-style user interface
        * would utilize the MdFactory class.
        * @param Repository CMetadata object with id of form:  A0000001.A5KHUI98
        */
       public void createTable(CMetadata repository)
       {
          if (repository != null)
          {
             try
             {
                System.out.println("\nCreating objects on the server...");

                // We have a repository object.
                // We use the reposFQID method to get its fully qualified ID.
                String reposFQID = repository.getFQID();

                // We need the short Repository ID to create an object.
                // we use the ReposId method to get the short ID.
                String shortReposID = reposFQID.substring(reposFQID.indexOf('.') + 1,
                                        reposFQID.length());

                // Now we create an object store to hold all our objects.
                // This will be used to maintain a list of objects to persist
                // to the server.
                MdObjectStore store = _factory.createObjectStore();

                // Create a PhysicalTable object named "TableTest".
                PhysicalTable table = (PhysicalTable) _factory.createComplexMetadataObject
                   (store,
                         null,
                         "TableTest",
                         MetadataObjects.PHYSICALTABLE,
                         shortReposID);

                // Create a Column named "ColumnTest".
                Column column = (Column) _factory.createComplexMetadataObject
                   (store,
                         null,
                         "ColumnTest",
                         MetadataObjects.COLUMN,
                         shortReposID);

                // Set the attributes of the column.
                column.setColumnName("MyTestColumnName");
                column.setSASColumnName("MyTestSASColumnName");
                column.setDesc("This is a description of a column");

                // Use the get"AssociationName"() method to associate the column with
                // the table. This method creates an AssociationList object for the table
                // object. The inverse association will be created automatically.
                // The add(MetadataObject) method adds myColumn to the AssociationList.
                table.getColumns().add(column);

                // Create a note for the column named "NoteTest".
                TextStore note = (TextStore) _factory.createComplexMetadataObject
                   (store,
                         null,
                         "NoteTest",
                         MetadataObjects.TEXTSTORE,
                         shortReposID);

                // Set the stored text attribute for the note
                note.setStoredText("Information about the note");

                // Associate the note with the column.
                column.getNotes().add(note);

                // Now, perist all of these changes to the server
                table.updateMetadataAll();

                // When finished, clean up the objects in the store if it is no longer
                // being used
                store.dispose();
             }
             catch (MdException e)
             {
                e.printStackTrace();
             }
             catch (RemoteException e)
             {
                e.printStackTrace();
             }
          }
       }

       /**
        * This method reads the newly created objects back from the server.
        * @param repository identifies the repository from which to read our objects.
        */
       public void readTable(CMetadata repository)
       {
          if(repository != null)
          {
             try
             {
                System.out.println("\nReading objects from the server...");

                // First we create an MdObjectStore as a container for all of the objects
                // we will create/read/persist to the server as one collection.
                MdObjectStore store = _factory.createObjectStore();

                // The following statements define GetMetadataObjectsSubset options strings.
                // These XML strings are used in conjunction with SAS Open Metadata Interface
                // flags. The <XMLSELECT> element specifies filter criteria. The
                // element specifies the metadata properties to be returned for each object
                // from the server.
                String xmlSelect = "<XMLSELECT Search=\"@Name='TableTest'\"/>";
                String template =
                   "<Templates>" +
                      "<PhysicalTable Id=\"\" Name=\"\" Desc=\"\">" +
                        "<Columns/>" +
                      "</PhysicalTable>" +
                      "<Column Id=\"\" Name=\"\" Desc=\"\" ColumnName=\"\">" +
                         "<Notes/>" +
                      "</Column>" +
                      "<TextStore Id=\"\" Name=\"\" Desc=\"\" StoredText=\"\"/>" +
                    "</Templates>";

                // Add the xml select and template strings together
                String sOptions = xmlSelect + template;

                // The following statements go to the server with a fully-qualified
                // repository ID, specify the type of object we are searching for
                // (MdObjectFactory.PHYSICALTABLE), utilizing the OMI_XMLSELECT, OMI_TEMPLATE,
                // and OMI_GET_METADATA flags. OMI_GET_METADATA tells the server to get all of
                // the attributes specified in the template for each object that is returned.
                //
                // The table, column, and note will be read from the server and created within
                // the specified object store.
                int flags = MdOMIUtil.OMI_XMLSELECT | MdOMIUtil.OMI_TEMPLATE |
                               MdOMIUtil.OMI_GET_METADATA;
                List tableList = _factory.getOMIUtil().getMetadataObjectsSubset(store,
                                                           repository.getFQID(),
                                                           MetadataObjects.PHYSICALTABLE,
                                                           flags,
                                                           sOptions);
                Iterator iter = tableList.iterator();
                while (iter.hasNext())
                {
                   // The table returned from the server
                   PhysicalTable table = (PhysicalTable) iter.next();
                   System.out.println("Found table: " + table.getName() + " (" +
                                        table.getId() + ")");

                   // Get the list of columns for this table.
                   AssociationList columns = table.getColumns();
                   for (int i = 0; i < columns.size(); i++)
                   {
                      // The column associated to the table
                      Column column = (Column) columns.get(i);
                      System.out.println("Found column: " + column.getName() + " (" +
                                           column.getId() + ")");
                      System.out.println("\tDescription: " + column.getDesc());
                      System.out.println("\tColumnName: " + column.getColumnName());

                      // We now have a column, and request to get its notes.
                      AssociationList notes = column.getNotes();
                      for (int j = 0; j < notes.size(); j++)
                      {
                         // The note associated to the column
                         TextStore note = (TextStore) notes.get(j);
                         System.out.println("Found textstore: " + note.getName() + " (" +
                                              note.getId() + ")");
                         System.out.println("\tStoredText: " + note.getStoredText());
                      }
                   }
                }

                // When finished, clean up the objects in the store if it is no longer
                // being used
                store.dispose();
             }
             catch (MdException e)
             {
                e.printStackTrace();
             }
             catch (RemoteException e)
             {
                e.printStackTrace();
             }
          }
       }

       /**
        * This method deletes the objects we created in repository
        * @param repository
        */
       public void deleteTable(CMetadata repository)
       {
          if(repository != null)
          {
             try
             {
                System.out.println("\nDeleting the objects from the server...");
                MdObjectStore store = _factory.createObjectStore();

                // Create a list containing all of the objects that need to be deleted
                // from the server.
                List deleteList = new ArrayList();

                // Query for the table again
                String xmlSelect = "<XMLSELECT Search=\"@Name='TableTest'\"/>";
                String template = "<Templates>" +
                                     "<PhysicalTable>" +
                                       "<Columns/>" +
                                     "</PhysicalTable>" +
                                     "<Column>" +
                                        "<Notes/>" +
                                     "</Column>" +
                                   "</Templates>";

                // Add the xml select and template strings together
                String sOptions = xmlSelect + template;

                int flags = MdOMIUtil.OMI_XMLSELECT | MdOMIUtil.OMI_TEMPLATE |
                               MdOMIUtil.OMI_GET_METADATA;
                List tableList = _factory.getOMIUtil().getMetadataObjectsSubset(store,
                                                           repository.getFQID(),
                                                           MetadataObjects.PHYSICALTABLE,
                                                           flags,
                                                           sOptions);

                // Now that we have the objects, we need to add them to the delete list
                Iterator iter = tableList.iterator();
                while (iter.hasNext())
                {
                   PhysicalTable table = (PhysicalTable) iter.next();
                   deleteList.add(table);

                   // Get the columns
                   AssociationList columns = table.getColumns();
                   for (int i = 0; i < columns.size(); i++)
                   {
                      Column column = (Column) columns.get(i);
                      deleteList.add(column);

                      // Get the notes
                      AssociationList notes = column.getNotes();
                      for (int j = 0; j < notes.size(); j++)
                      {
                         TextStore note = (TextStore) notes.get(j);
                         deleteList.add(note);
                      }
                   }
                }

                // Delete everything added to the delete list
                if (deleteList.size() > 0)
                {
                   System.out.println("Deleting " + deleteList.size() + " objects");
                   _factory.deleteMetadataObjects(deleteList);
                }

                // When finished, clean up the objects in the store if it is no longer
                // being used
                store.dispose();
             }
             catch (MdException e)
             {
                e.printStackTrace();
             }
             catch (RemoteException e)
             {
                e.printStackTrace();
             }
          }
       }

       /**
        * This method displays the PhysicalTable objects contained in repository
        * @param repository CMetadata identifies the repository from which to read
        * the objects.
        */
       public void displayAllTables(CMetadata repository)
       {
          try
          {
             // Print a descriptive message about the request.
             System.out.println("\nRetrieving all PhysicalTable objects contained in " +
                   " repository " + repository.getName());

             // Use the short Repository ID to pass in the method.
             String reposID = repository.getFQID();

             // We get a list of "PhysicalTable" objects.
             MdObjectStore store = _factory.createObjectStore();

             // Use the OMI_ALL_SIMPLE flag to get all attributes for each table returned
             int flags = MdOMIUtil.OMI_GET_METADATA | MdOMIUtil.OMI_ALL_SIMPLE;
             List tables = _factory.getOMIUtil().getMetadataObjectsSubset
                    (store,
                    reposID,                         // Repository to Search
                    MetadataObjects.PHYSICALTABLE,   // Type to search for
                    flags,
                    "" );

             // Print information about them.
             Iterator iter = tables.iterator();
             while( iter.hasNext())
             {
                PhysicalTable ptable = (PhysicalTable)iter.next();
                System.out.println("PhysicalTable: " +
                                   ptable.getName() +
                                   ", " +
                                   ptable.getFQID() +
                                   ", " +
                                   ptable.getDesc());
             }

             // When finished, clean up the objects in the store if it is no longer
             // being used
             store.dispose();
          }
          catch (MdException e)
          {
             e.printStackTrace();
          }
          catch (RemoteException e)
          {
             e.printStackTrace();
          }
       }

       /**
        * This method retrieves detailed information for a specific PhysicalTable
        * @param table the table to retrieve
        */
       public void getTableInformation(PhysicalTable table)
       {
          try
          {
             // Print a descriptive message about the request.
             System.out.println("\nRetrieving information for a specific PhysicalTable");

             // Create a template to retreive detailed information for this table
             String template = "<Templates>" +
                                  "<PhysicalTable>" +
                                    "<Columns/>" +
                                    "<Notes/>" +
                                    "<Keywords/>" +
                                  "</PhysicalTable>" +
                                "</Templates>";

             // Use the OMI_ALL_SIMPLE flag to get all attributes for each table returned
             int flags = MdOMIUtil.OMI_GET_METADATA | MdOMIUtil.OMI_ALL_SIMPLE |
                            MdOMIUtil.OMI_TEMPLATE;
             table = (PhysicalTable) _factory.getOMIUtil().getMetadataAllDepths
                    (table,
                     null,
                     null,
                     template,
                     flags);

             // Print information about the table
             System.out.println("Table attributes: ");
             System.out.println("  Name = " + table.getName());
             System.out.println("  Id = " + table.getId());
             System.out.println("  Description = " + table.getDesc());
             System.out.println("  Created Date = " + table.getMetadataCreated());
             System.out.println("Table associations: ");
             System.out.println("  Number of Columns = " + table.getColumns().size());
             System.out.println("  Number of Keywords = " + table.getKeywords().size());
             System.out.println("  Number of Notes = " + table.getNotes().size());
          }
          catch (MdException e)
          {
             e.printStackTrace();
          }
          catch (RemoteException e)
          {
             e.printStackTrace();
          }
       }

       /**
        * The main method for the class
        */
       public static void main(String[] args)
       {
          MdTesterExamples tester = new MdTesterExamples();

          // connect to the metadata server
          boolean connected = tester.connectToServer();
          if(connected)
          {
             System.out.println("Connected...");
          }
          else
          {
             System.out.println("Error Connecting...");
             return;
          }

          // now that we are connected, check the status of the server
          tester.displayServerInformation();

          // get the list of repositories on the server
          List repositories = tester.getRepositories();
          CMetadata repos = (CMetadata) repositories.get(0);

          // get the list of metadata types available on the server
          tester.displayMetadataTypes();

          // create a new PhysicalTable object and add it to the metadata server
          tester.createTable(repos);

          // query for the PhysicalTable just added to the metadata server
          tester.readTable(repos);

          // delete the PhysicalTable
          tester.deleteTable(repos);

          System.exit(1);
       }

    }