## Note:

Extension of the classes in this package is prohibited unless otherwise documented. Similarly, extension or implementation of the interfaces in this package is prohibited except as documented.

# Package com.sas.services.storedprocess.metadata

@CodeSet("sas.platform") @SASScope("ALL") package com.sas.services.storedprocess.metadata
Create and modify stored process metadata and obtain stored process service objects from metadata.

## Overview

This package houses the Stored Process smart object, the stored process alert and associated helper objects. Functions typically performed by elements of this package are:

- Obtain a service object from a smart object.
- Create metadata for a stored process.
- Access metadata of an existing stored process.
- Convert stored processes from one version to another.

The version of the stored processes metadata format introduced in 9.2 was version 1 and the version introduced in 9.3 was version 2. Hence 9.2 stored processes are also known as version 1 stored processes and 9.3 stored processes may be called version 2 stored processes. Both version 1 and version 2 stored processes can be present in a 9.3 metadata repository.

### Create metadata for a stored process

What follows are two code fragments which show how to create metadata for a stored process. The first one creates a version 2 stored process and the second one creates one in the older version 1 format. What are shown are code fragments and not complete programs. It is assumed that the Foundation Services have been deployed, the Information Service has been "discovered" and that a UserContextInterface representing the user is available.

Version 2 stored process:

            import com.sas.prompts.definitions.TextDefinition;
            import com.sas.prompts.groups.PromptGroupInterface;
            import com.sas.services.ServiceException;
            import com.sas.services.information.Filter;
            import com.sas.services.information.FilterComponent;
            import com.sas.services.information.RepositoryInterface;
            import com.sas.services.information.metadata.DirectoryInterface;
            import com.sas.services.information.metadata.FolderInterface;
            import com.sas.services.information.metadata.PathUrl;
            import com.sas.services.information.metadata.PhysicalTableInterface;
            import com.sas.services.information.metadata.ServerContextInterface;
            import com.sas.services.information.metadata.prompt.OMRPromptGroupInterface;
            import com.sas.services.information.metadata.prompt.PromptsPersistUtil;
            import com.sas.services.information.util.SmartTypes;
            import com.sas.services.storedprocess.metadata.DataSourceOrTarget;
            import com.sas.services.storedprocess.metadata.DataTable;
            import com.sas.services.storedprocess.metadata.GenericStream;
            import com.sas.services.storedprocess.metadata.OutputParameter;
            import com.sas.services.storedprocess.metadata.SourceCodeRepositoryUtil;
            import com.sas.services.storedprocess.metadata.StoredProcessInterface;
            import com.sas.services.storedprocess.metadata.XMLStream;
            import com.sas.services.storedprocess.metadata.StoredProcessInterface.SourceCodeLocation;
            import java.util.ArrayList;
            import java.util.List;
            ...
            // lets first obtain the location of the folder to contain the stored process
            PathUrl path = new PathUrl("SBIP://METASERVER/Users/sasdemo/My Folder/CreateTest(Folder)");
            FolderInterface folder = (FolderInterface)_informationService.getObjectByPath(_userContext, path);
            RepositoryInterface ri = folder.getRepository();

            // next find the logical server the stored process is going to run on - in this case a Stored Process server
            String serverContextName = "SASApp";
            Filter filter = new Filter();
            FilterComponent comp1 = new FilterComponent("PublicType", FilterComponent.EQUALS, "ApplicationServer");
            FilterComponent comp2 = new FilterComponent("Name", FilterComponent.EQUALS, serverContextName);
            comp1.addComponent(comp2);
            comp1.setAggregation(FilterComponent.ALL_OF);
            filter.setFilterComponent(comp1);
            List servers = _informationService.search(_userMe, filter);
            ServerContextInterface serverContext = servers.get(0);

            // now the actual creation of the stored process - we'll name it "Test_Stored_Process"
            StoredProcessInterface spmi = (StoredProcessInterface)_informationService.newMetadataInFolder(folder, ri, SmartTypes.TYPE_STOREDPROCESS, "Test_Stored_Process");
            // by default a 9.2 stored process is created; since we're creating a 9.3 one, the very
            // first operation should be to convert the "empty" stored process to the 9.3 version
            spmi.convertToVersion(StoredProcessInterface.NINETHREE_VERSION);
            // we could have used CURRENT_VERSION instead (as shown on the next line) if we always want the latest version
            //spmi.convertToVersion(StoredProcessInterface.CURRENT_VERSION);

            // set General tab values
            spmi.setDescription("Some words describing the Stored Process.");
            ArrayList keywords = new ArrayList();
            keywords.add("Keyword1");
            keywords.add("Keyword2");
            spmi.setKeywords(keywords);

            // set Execution tab values
            spmi.setServerContext(serverContext);
            // lets say the source code is in the file system
            SourceCodeRepositoryUtil scru = new SourceCodeRepositoryUtil(serverContext);
            DirectoryInterface di = scru.locateSourceCodeRepository("C:\\Users\\sasdemo\\tests");
            if (di == null)
                    di = scru.createSourceCodeRepository("C:\\Users\\sasdemo\\tests", "Stored process demo test directory");
            spmi.setSourceCodeRepository(di);
            spmi.setSourceFileName("source.sas");
            // if we want source code in metadata we could use the following commented out code
            //String sasCode =
            //      "data _null_;\nfile _webout;\n" +
            //      "rc = stpsrv_header('Content-encoding','utf8');\n" +
            //      "put '<HTML>';\nput '<HEAD><TITLE>Hello World!</TITLE></HEAD>';\n" +
            //  "put '<BODY>';\nput '<H1>Hello World!</H1>';\nput '</BODY>';\nput '</HTML>';\nrun;";
            //spmi.setSourceCodeLocation(SourceCodeLocation.METADATA);
            //spmi.setSourceCode(sasCode);

            // next set result capabilities
            spmi.setResultCapabilities(false, true);

            // set Parameter tab values

            // first get the prompt smart object
            OMRPromptGroupInterface omrpgi = (OMRPromptGroupInterface)spmi.getPrompt();
            // then get the root ("Parameters") prompt group object from the smart object
            PromptGroupInterface pgi = omrpgi.getPromptGroup();
            // add prompts / groups as needed
            TextDefinition pyear = new TextDefinition("pyear");
            pyear.setDefaultValue("1993");
            pgi.addPromptDefinition(pyear);
            TextDefinition pcountry = new TextDefinition("pcountry");
            pgi.addPromptDefinition(pcountry);
            // notify the prompt smart object that changes have been made
            PromptsPersistUtil.updateGroupSmartObject(pgi, _userMe, omrpgi, null);
            // the prompt smart object is now updated with the changes
            // and will be written to the server when the store is flushed
            // or any object in the store is updated

            // creating two String output parameters
            ArrayList oplist = new ArrayList();
            OutputParameter op = new OutputParameter();
            op.setName("NTLD");
            op.setType(OutputParameter.TYPE_STRING);
            op.setLabel("Label NTLD");
            op.setDescription("Output Parm with Name, Type (String), Label and Description");
            oplist.add(op);
            op = new OutputParameter();
            op.setName("NTL");
            op.setType(OutputParameter.TYPE_STRING);
            op.setLabel("Label NTL");
            oplist.add(op);
            spmi.setOutputParameters(oplist);

            // set Data tab values
            // some streams and data tables with fake values for illustration purposes
            ArrayList dsotList = new ArrayList();
            GenericStream genStrm = new GenericStream();
            genStrm.setFileref("GenS");
            genStrm.setDescription("Desc for Gen Source");
            genStrm.setLabel("Label for GenS");
            genStrm.setExpectedContentType("Content type for GenS");
            dsotList.add(genStrm);
            xmlStrm = new XMLStream();
            xmlStrm.setFileref("XSchTR");
            xmlStrm.setIsSchemaAvailable(true);
            xmlStrm.setSchemaURI("Schema URI TR");
            xmlStrm.setReferenceNameSpace("NameSpace TR");
            xmlStrm.setReferenceName("RefName TR");
            xmlStrm.setIsReferenceTypeForSchemaElement(true);
            xmlStrm.setIsSchemaToBeEmbeddedInWSDL(false);
            dsotList.add(xmlStrm);
            DataTable dts = new DataTable();
            dts.setSource(true);
            dts.setLabel("Label for dts");
            dts.setDescription("Description for dts");
            dts.setParameterName("DTS");
            // the template table is optional ... here for illustration purposes we'll find one
            // and set it
            PhysicalTableInterface table1, table2;
            path = new PathUrl("SBIP://METASERVER/Shared Data/CARS(Table)");
            table1 = (PhysicalTableInterface)_informationService.getObjectByPath(_userMe, path);
            dts.setTemplateTable(table1);
            dsotList.add(dts);
            spmi.setDataSourcesAndTargets(dsotList);

            // after all the setters are called update() is called which internally
            // calls validate() before writing the stored process to the metadata server
            spmi.update();

Version 1 stored process:

            import com.sas.prompts.definitions.TextDefinition;
            import com.sas.prompts.groups.PromptGroupInterface;
            import com.sas.services.ServiceException;
            import com.sas.services.information.RepositoryInterface;
            import com.sas.services.information.metadata.DirectoryInterface;
            import com.sas.services.information.metadata.FolderInterface;
            import com.sas.services.information.metadata.LogicalServerFilter;
            import com.sas.services.information.metadata.LogicalServerInterface;
            import com.sas.services.information.metadata.PathUrl;
            import com.sas.services.information.metadata.prompt.OMRPromptGroupInterface;
            import com.sas.services.information.metadata.prompt.PromptsPersistUtil;
            import com.sas.services.information.util.SmartTypes;
            import com.sas.services.storedprocess.metadata.GenericStream;
            import com.sas.services.storedprocess.metadata.OutputParameter;
            import com.sas.services.storedprocess.metadata.SourceCodeRepositoryUtil;
            import com.sas.services.storedprocess.metadata.StoredProcessInterface;
            import com.sas.services.storedprocess.metadata.XMLStream;
            import java.util.ArrayList;
            ...
            // lets first obtain the location of the folder to contain the stored process
            PathUrl path = new PathUrl("SBIP://METASERVER/Users/sasdemo/My Folder/CreateTest(Folder)");
            FolderInterface folder = (FolderInterface)_informationService.getObjectByPath(_userContext, path);
            RepositoryInterface ri = folder.getRepository();

            // next find the logical server the stored process is going to run on - in this case a Stored Process server
            String serverNameSps = "SASApp - Logical Stored Process Server";
            filter = new LogicalServerFilter("Name", com.sas.services.information.FilterComponent.EQUALS, serverNameSps);
            servers = _informationService.search(_userMe, filter);
            LogicalServerInterface logicalServerSps = servers.get(0);
            // now the actual creation of the stored process - we'll name it "Test_Stored_Process"
            StoredProcessInterface spmi = (StoredProcessInterface)_informationService.newMetadataInFolder(folder, ri, SmartTypes.TYPE_STOREDPROCESS, "Test_Stored_Process");
            // set General tab values
            spmi.setDescription("Description for Stored Process.");
            ArrayList keywords = new ArrayList();
            keywords.add("Keyword1");
            keywords.add("Keyword2");
            spmi.setKeywords(keywords);

            // set Execution tab values
            spmi.setServer(logicalServerSps);
            SourceCodeRepositoryUtil scru = new SourceCodeRepositoryUtil(logicalServerSps);
            DirectoryInterface di = scru.locateSourceCodeRepository("C:\\Users\\sasdemo\\tests");
            if (di == null)
                    di = scru.createSourceCodeRepository("C:\\Users\\sasdemo\\tests", "Stored process demo test directory");
            spmi.setSourceCodeRepository(di);
            spmi.setSourceFileName("source.sas");
            spmi.setResultCapabilities(true, true);

            // set Parameter tab values

            // first get the prompt smart object
            OMRPromptGroupInterface omrpgi = (OMRPromptGroupInterface)spmi.getPrompt();
            // then get the root ("Parameters") prompt group object from the smart object
            PromptGroupInterface pgi = omrpgi.getPromptGroup();
            // add prompts / groups as needed
            TextDefinition pyear = new TextDefinition("pyear");
            pyear.setDefaultValue("1993");
            pgi.addPromptDefinition(pyear);
            TextDefinition pcountry = new TextDefinition("pcountry");
            pgi.addPromptDefinition(pcountry);
            // notify the prompt smart object that things have changed
            PromptsPersistUtil.updateGroupSmartObject(pgi, _userMe, omrpgi, null);
            // the prompt smart object is now updated with the changes
            // and will be written to the server when the store is flushed
            // or any object in the store is updated
            // creating two String output parameters
            ArrayList oplist = new ArrayList();
            OutputParameter op = new OutputParameter();
            op.setName("NTLD");
            op.setType(OutputParameter.TYPE_STRING);
            op.setLabel("Label NTLD");
            op.setDescription("Output Parm with Name, Type (String), Label and Description");
            oplist.add(op);
            op = new OutputParameter();
            op.setName("NTL");
            op.setType(OutputParameter.TYPE_STRING);
            op.setLabel("Label NTL");
            oplist.add(op);
            spmi.setOutputParameters(oplist);

            // set Data tab values
            // some streams with fake values for illustration purposes
            ArrayList strmList = new ArrayList();
            GenericStream genStrm = new GenericStream();
            genStrm.setFileref("GenS");
            genStrm.setDescription("Desc for Gen Source");
            genStrm.setLabel("Label for GenS");
            genStrm.setExpectedContentType("Content type for GenS");
            strmList.add(genStrm);
            xmlStrm = new XMLStream();
            xmlStrm.setFileref("XSchTR");
            xmlStrm.setIsSchemaAvailable(true);
            xmlStrm.setSchemaURI("Schema URI TR");
            xmlStrm.setReferenceNameSpace("NameSpace TR");
            xmlStrm.setReferenceName("RefName TR");
            xmlStrm.setIsReferenceTypeForSchemaElement(true);
            xmlStrm.setIsSchemaToBeEmbeddedInWSDL(false);
            strmList.add(xmlStrm);
            spmi.setStreams(strmList);

            // after all the setters are called update() is called which internally
            // calls validate() before writing the stored process to the metadata server
            spmi.update();

### Convert stored processes from one version to another

The convertToVersion() method can be used to convert between version 1 stored processes and version 2 stored processes. All well-formed version 1 stored processes can be converted to version 2; however, if a version 2 stored process uses a feature not present in version 1, conversion to version 1 will not be possible.

#### Prompt handling during conversion

Prompts are not affected during conversion with the following exception: A version 1 stored process running on a workspace server is considered to create a "permanent file package" if it has a prompt named _archive_path and the value of _result is "PACKAGE_TO_REQUESTER". It will be successfully converted if _result is not a shared prompt. The value of _result will be changed to "PACKAGE_TO_ARCHIVE". A version 2 stored process running on a workspace server is considered to create a "permanent file package" if it has an _archive_name prompt and the value of _result is "PACKAGE_TO_ARCHIVE". It will be successfully converted if _result is not a shared prompt. The value of _result will be changed to "PACKAGE_TO_REQUESTER".

#### *ProcessBody binding

Version 2 Workspace server stored processes ignore the *ProcessBody directive. Binding of incoming macro values to the macros functions in the same way as version 1 and version 2 stored processes running on the Stored Process server. In other words, only version 1 stored processes running on a Workspace server bind values to macros at the location of the *ProcessBody directive. The conversion code does not examine source code and it is up to the client to ensure that there is no negative impact as a result of a conversion.

- Related Packages
  Package
  Description
  com.sas.services.storedprocess
  Execute stored processes.
- Class
  Description
  DataTable
  Describes a design time Data Table object.
  GenericStream
  Describes a design time GenericStream data source or target object.
  OutputParameter
  Design time output parameter.
  SourceCodeRepositoryUtil
  A utility class that provides methods to manipulate source code repositories.
  StoredProcessAlertItem
  This class represents a sas stored process alert item, which keeps track of the results of a stored process.
  StoredProcessAlertItemInterface
  This class represents a sas stored process alert item, which keeps track of the results of a stored process.
  StoredProcessFilter
  Stored Process Filter.
  StoredProcessInterface
  This is a generic interface for interacting with a repository entry that represents a SAS stored process object.
  StoredProcessOptions
  Options object used to control the type and behavior of the Stored Process service object.
  XMLStream
  Design time XMLStream data source or target.