Sample Program

The following is an executable version of the code examples from Using the SAS Java Metadata Interface.
/**
 * Copyright (c) 2011 by SAS Institute Inc., Cary, NC 27513
 */

package com.sas.metadata.remote.test;

import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Collections;
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.Keyword;
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.PrimaryType;
import com.sas.metadata.remote.Tree;


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

   /**
    * The object factory instance.
    */
   private MdFactory _factory = null;

   /**
    * Default constructor
    */
   public MdTesterExamples()
   {
      // Call the factory's constructor.
      initializeFactory();
   }

   private void initializeFactory()
   {
      try
      {
         // Initialize the 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, as shown here.
         _factory = new MdFactoryImpl(false);
         
         // Defines debug logging, but does not turn it on.
         boolean debug = false;
         if (debug)
         {
            _factory.setDebug(false);
            _factory.setLoggingEnabled(false);
            
            // Sets 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);
         }
         
         // To be notified when changes have been persisted to the SAS Metadata Server
         // within this factory (this includes adding objects, updating objects, and 
         // deleting objects), we can add a listener to the factory here.
         // See MdFactory.addMdFactoryListener()
         // A listener is not needed for this example.
      }
      catch (Exception e)
      {
         e.printStackTrace();   
      }
   }
   
   /**
    * The following statements make a connection to the SAS Metadata Server 
    * and check 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)
            {
               // If 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;
   }

   /**
    * The following statements get and display the status and version 
    * of the SAS Metadata Server.
    */
   public void displayServerInformation()
   {
      try
      {
         MdOMRConnection connection = _factory.getConnection();
                  
         // Check the status of the 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 server.
         int version = connection.getPlatformVersion();
         System.out.println("Server version: " + version);         
      }
      catch (MdException e)
      {
         e.printStackTrace();
      }
      catch (RemoteException e)
      {
         e.printStackTrace();
      }
   }
   
   /**
    * The following statements get information about the foundation repository.
    * @return the foundation repository
    */
   public CMetadata getFoundationRepository()
   {
      try
      {
         System.out.println("\nGetting the Foundation repository...");
         
         // The getFoundationRepository method gets the foundation repository.
         return _factory.getOMIUtil().getFoundationRepository();
      }
      catch (MdException e)
      {
         e.printStackTrace();
      }
      catch (RemoteException e)
      {
         e.printStackTrace();
      }
      return null;
   }
   
   /**
    * The following statements list the repositories that are registered
    * on the SAS Metadata Server.
    * @return the list of available repository (list of CMetadata objects)
    */
   public List<CMetadata> getAllRepositories()
   {
      try
      {
         System.out.println("\nThe repositories contained on this SAS Metadata " +
           "Server are:");
         
         // The getRepositories method lists all repositories.
         MdOMIUtil omiUtil = _factory.getOMIUtil();
         List<CMetadata> reposList = omiUtil.getRepositories();
         for (CMetadata repository : reposList)
         {
            // Print the name and id of each repository.
            System.out.println("Repository: " + 
                               repository.getName() 
                               + " (" + repository.getFQID() +")");
         }
         return reposList;
      }
      catch (MdException e)
      {
         e.printStackTrace();
      }
      catch (RemoteException e)
      {
         e.printStackTrace();
      }
      return Collections.emptyList();
   }

   /**
    * The following statements list the metadata types available on the 
    * SAS Metadata Server and their descriptions.
    */
   public void displayMetadataTypes()
   {
      try
      {
         System.out.println("\nThe object types contained on this SAS Metadata " +
                 "Server are:");

         // Metadata types are listed with the getTypes method.
         List<String> nameList = new ArrayList<String>();
         List<String> descList = new ArrayList<String>();
         _factory.getOMIUtil().getTypes(nameList, descList);
         Iterator<String> nameIter = nameList.iterator();
         Iterator<String> descIter = descList.iterator();
         while (nameIter.hasNext() && descIter.hasNext())
         {
            // Print the name and description of each metadata object type.
            String name = nameIter.next();
            String desc = descIter.next();
            System.out.println("Type: " +
                                name +
                                " - Description: " +
                                desc);
         }
      }
      catch (MdException e)
      {
         e.printStackTrace();
      }
      catch (RemoteException e)
      {
         e.printStackTrace();
      }
   }

   /**
    * The following statements create a table, column, and keyword on the column.
    * The objects are created in the user's My Folder folder.
    * @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 getFQID method to get its fully qualified ID.
            String reposFQID = repository.getFQID();

            // We need the short repository ID to create an object.
            String shortReposID = reposFQID.substring(reposFQID.indexOf('.') + 1, 
                                    reposFQID.length());

            // Now we create an object store to hold our objects.  
            // This will be used to maintain a list of objects to persist
            // to the SAS Metadata Server.
            MdObjectStore store = _factory.createObjectStore();
            String tableName = "TableTest";
            String tableType = "Table";
            
            // The getUserHomeFolder method retrieves (or creates, if necessary)
            // the user's My Folder folder.  If the folder does not 
            // exist, the method automatically creates it.
            // This is the folder in which we will create the table.
            Tree myFolder = _factory.getOMIUtil().getUserHomeFolder(store, "", 
                  MdOMIUtil.FOLDERTYPE_MYFOLDER, "", 0, true);
            
            // Before creating any objects, we must verify that the Table does 
            // not already exist within the parent folder.  The table cannot be
            // created if it is not unique within the folder.
            if (!isUnique(myFolder, tableName, tableType))
            {
               // Create a PhysicalTable object named "TableTest".
               PhysicalTable table = (PhysicalTable) _factory.createComplexMetadataObject
                  (store,
                        null,
                        "TableTest",
                        MetadataObjects.PHYSICALTABLE,
                        shortReposID);
   
               // Set the PublicType and UsageVersion attributes for the table.
               table.setPublicType("Table");
               table.setUsageVersion(1000000.0);
               
               // Add the table to the user's "My Folder" location.
               table.getTrees().add(myFolder);
              
               // Create a Column named "ColumnTest".
               Column column = (Column) _factory.createComplexMetadataObject
                  (store,
                        null,
                        "ColumnTest",
                        MetadataObjects.COLUMN,
                        shortReposID);
   
               // Set the attributes of the column, including PublicType and
               // UsageVersion.
               column.setPublicType("Column");
               column.setUsageVersion(1000000.0);
               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 keyword for the column named "KeywordTest".
               Keyword keyword = (Keyword) _factory.createComplexMetadataObject
                  (store,
                        null,
                        "KeywordTest",
                        MetadataObjects.KEYWORD,
                        shortReposID);
   
               // Associate the keyword with the column.
               column.getKeywords().add(keyword);
   
               // Now, persist all of these changes to the server.
               table.updateMetadataAll();
            }
            
            // When finished, clean up the objects in the store if they
            // are no longer being used.
            store.dispose();
         }
         catch (MdException e)
         {
            e.printStackTrace();
         }
         catch (RemoteException e)
         {
            e.printStackTrace();
         }      
      }
   }

   /**
    * isUnique() is a private method that determines whether an object is unique 
    * within a given folder.
    * @param folder is the name of the parent folder
    * @param name is the Name value of the object
    * @param type is the PublicType value of the object
    * @return true if an object with the specified name and type exists within 
    * the folder.
    */
   private boolean isUnique(Tree folder, String name, String type) 
      throws RemoteException, MdException
   {
      // Now, retrieve the objects in the folder and make sure that the folder doesn't 
      // already contain this table. The object's Name and PublicType attribute values
      //  are used to determine if it is unique.
      List members = folder.getMembers();
      for (Iterator iter = members.iterator(); iter.hasNext(); )
      {
         CMetadata meta = (CMetadata) iter.next();
         if (meta instanceof PrimaryType)
         {
            // Verify that the types and object names match
            // A case-insensitive match should be used when comparing the names.
            if (type.equals(((PrimaryType) meta).getPublicType()) &&
                name.equals(meta.getName()))
            {
               // We found a match.
               return true;
            }
         }         
      }
      return false;
   }

   /**
    * The following statements read the newly created objects back from the 
    * SAS Metadata 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 the
            // objects that we will create/read/persist to the server as 
            // one collection.
            MdObjectStore store = _factory.createObjectStore();

            // The following statements define variables used within the 
            // getMetadataObjectsSubset method. These XML strings are used
            // with SAS Open Metadata Interface flags. The <XMLSELECT> element
            // specifies filter criteria. The objects returned are filtered by the 
            // PublicType and Name values. The <TEMPLATES> element specifies the 
            // associations to be expanded for each object.

            String xmlSelect = "<XMLSELECT Search=\"*[@PublicType='Table' and " + 
                                 "@Name='TableTest']\"/>";
            String template = 
               "<Templates>" + 
                  "<PhysicalTable>" +
                    "<Columns/>" +
                  "</PhysicalTable>" +
                  "<Column>" + 
                     "<Keywords/>" + 
                  "</Column>" +
                "</Templates>";
            
            // Add the XMLSELECT and TEMPLATES strings together.
            String sOptions = xmlSelect + template; 

            // The following statements go to the server with a fully-qualified 
            // repository ID and specify the type of object we are searching for 
            // (MetadataObjects.PHYSICALTABLE) using the OMI_XMLSELECT, OMI_TEMPLATE,
            // OMI_ALL_SIMPLE, and OMI_GET_METADATA flags. OMI_ALL_SIMPLE specifies 
            // to get all simple attributes for all objects that are returned. 
            // OMI_GET_METADATA activates the GetMetadata flags in the GetMetadataObjects
            // request. 
            //
            // The table, column, and keyword will be read from the server and created 
            // within the specified object store.
            int flags = MdOMIUtil.OMI_XMLSELECT | MdOMIUtil.OMI_TEMPLATE | 
                           MdOMIUtil.OMI_ALL_SIMPLE | MdOMIUtil.OMI_GET_METADATA;
            List tableList = _factory.getOMIUtil().getMetadataObjectsSubset(store, 
                                                       repository.getFQID(),
                                                       MetadataObjects.PHYSICALTABLE,
                                                       flags,
                                                       sOptions);
            Iterator iter = tableList.iterator();
            while (iter.hasNext())
            {
               // Print the Name, Id, PublicType, UsageVersion, and ObjPath values 
               // of the table returned from the server. ObjPath is the folder location.
               PhysicalTable table = (PhysicalTable) iter.next();
               System.out.println("Found table: " + table.getName() + " (" + 
                                    table.getId() + ")");

               System.out.println("\tType: " + table.getPublicType());
               System.out.println("\tUsage Version: " + table.getUsageVersion());
               System.out.println("\tPath: " + _factory.getOMIUtil().getObjectPath(store, 
                                                   table, false));
               
               // Get the list of columns for this table.
               AssociationList columns = table.getColumns();
               for (int i = 0; i < columns.size(); i++)
               {
                  // Print the Name, Id, PublicType, UsageVersion, Desc, and ColumnName
                  // values for each column associated with the table.
                  Column column = (Column) columns.get(i);
                  System.out.println("Found column: " + column.getName() + " (" + 
                                       column.getId() + ")");
                  
                  System.out.println("\tType: " + column.getPublicType());
                  System.out.println("\tUsage Version: " + column.getUsageVersion());
                  System.out.println("\tDescription: " + column.getDesc());
                  System.out.println("\tColumnName: " + column.getColumnName());
                  
                  // Get the list of keywords associated with the columns.
                  AssociationList keywords = column.getKeywords();
                  for (int j = 0; j < keywords.size(); j++)
                  {
                     // Print the Name and Id values of each keyword associated with
                     // the column.
                     Keyword keyword = (Keyword) keywords.get(j);
                     System.out.println("Found keyword: " + keyword.getName() + " (" + 
                                          keyword.getId() + ")");
                  }
               }
            }

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

   /**
    * The following statements delete the objects that we created.
    * @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 of the objects that need to be deleted
            // from the server.
            List<CMetadata> deleteList = new ArrayList<CMetadata>();
            
            // Query for the table again.
            String xmlSelect = "<XMLSELECT Search=\"*[@PublicType='Table' and " + 
                                 "@Name='TableTest']\"/>";

               // Note: Since the object has a valid PublicType value, the SAS 9.3 
               // Metadata Server automatically deletes all objects associated
               // with the table, such as its Column and Keyword objects, when the table 
               // is deleted. There is no need to specify a template to delete
               // the associated objects.
            
            int flags = MdOMIUtil.OMI_XMLSELECT;
            List tableList = _factory.getOMIUtil().getMetadataObjectsSubset(store, 
                                                       repository.getFQID(),
                                                       MetadataObjects.PHYSICALTABLE,
                                                       flags,
                                                       xmlSelect);
            
            
            // Add the found objects to the delete list.
            Iterator iter = tableList.iterator();
            while (iter.hasNext())
            {
               PhysicalTable table = (PhysicalTable) iter.next();
               deleteList.add(table);
            }

            // Delete everything that is in 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();
         }
      }
   }

   /**
    * The following statements display the PhysicalTable objects in the 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
         // that is returned.
         int flags = MdOMIUtil.OMI_GET_METADATA | MdOMIUtil.OMI_ALL_SIMPLE;
         List tables = _factory.getOMIUtil().getMetadataObjectsSubset
                (store,
                reposID,                         // Repository to search
                MetadataObjects.PHYSICALTABLE,   // Metadata 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 they
         // are no longer being used.
         store.dispose();
      }
      catch (MdException e)
      {
         e.printStackTrace();
      }
      catch (RemoteException e)
      {
         e.printStackTrace();
      }
   }

   /**
    * The following statements retrieve detailed information for a 
    * specific PhysicalTable object.
    * @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 retrieve 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 the table.
         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("  Type = " + table.getPublicType());
         System.out.println("  Usage Version = " + table.getUsageVersion());
         System.out.println("  Path = " + 
               _factory.getOMIUtil().getObjectPath((MdObjectStore) table.getObjectStore(), 
                     table, false));
         
         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 SAS 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
      tester.getAllRepositories();

      // Get the list of metadata types available on the server
      tester.displayMetadataTypes();
      
      // Get the foundation repository
      CMetadata repos = tester.getFoundationRepository();
      if (repos != null)
      {
         // Create a new PhysicalTable object and add it to the 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);      
   }

}