/** * 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); } }