4 Understanding the PCM API and the PIN Library

This chapter introduces two libraries that you need to understand if you are customizing the Oracle Communications Billing and Revenue Management (BRM) system:

  • The PIN (Portal Information Network) libraries, which you use to handle errors and to manipulate flists, POIDs, fields, strings, and decimal data types.

  • The Portal Communication Module (PCM) Application Programming Interface (API), which you use to interact with the BRM database.

Before you read this document, read the following documents in BRM Concepts to familiarize yourself with the basic concepts and components of BRM:

BRM provides several Software Development Kits (SDKs) and APIs that you use to create custom client applications for BRM. For information on those SDKs and APIs and how to use them, see "About the BRM Client Access Libraries".

About the PIN Library

The PIN library contains macros and functions that manipulate flists, fields, and data types. These functions are different from PCM operations in that they are implemented locally in the programs; they do not pass data over the communication channel. The PIN library is required to build custom applications and FMs.

The PIN library contains macros and functions that you use to perform the following tasks:

About the PCM API

All access to the data in the BRM database is through the PCM API. Client applications as well as custom Facilities Modules (FMs) use this library to manipulate objects in the database.

The API consists of three classes of functions:

  • Context management. You use context management opcodes to control communication channels to the database.

  • Basic object manipulation. You use base opcodes to create, search for, delete, and modify objects in the database.

  • FM object manipulation. You use FM opcodes to implement business policies and processes

You make BRM API calls by using a macro interface instead of directly through functions. When an API macro is called, the macro records the file name and line number of the source code where the API was called. If an error occurs, the macro logs a message including the file name and source code line number, making it easy to locate and correct the error.

For details on the return status of PCM functions and the error messages returned, see "Understanding API Error Handling and Logging".

The API definitions are independent of the underlying storage model. The C data structures are opaque, and the opcodes are designed to appear much like object methods.

Header Files

Each set of related opcodes has a corresponding header file. Your custom code and applications must include the header files that correspond to the opcodes you use.

Context management opcodes use the pcm.h header file. Always include this file in your applications.

Header files for base opcodes and Facilities Module (FM) opcodes are located in the include/ops directory. To include one of these header files, use this syntax:

#include "ops/file.h"
  

Where file is the name of the header file.

For example, if your application calls PCM_OP_CUST_COMMMIT_CUSTOMER, you must include the ops/cust.h header file.

Opcode Input and Output Specifications

Each PCM opcode requires certain data to successfully perform its operation. The opcodes take input and output data in the form of field lists (flists), which are lists of field name and value pairs. (For more information on flists, see "About Flists".)

Each opcode requires its input flist to contain certain fields to perform the operation. For example, to create an object, the PCM_OP_CREATE_OBJECT() opcode requires an input flist that includes all the fields that an object of that class requires.

The information for each opcode in BRM Developer's Reference includes the input and output flist specifications, defining the following parameters for each field in the flist:

  • The mnemonic field names used by applications to reference the field

  • The data type and size for the field

  • The permissions, which specify if a field is mandatory (M) or optional (O) for the opcode. See the next section, "Field Permissions", for more information.

The flist specifications use the following syntax to define each field in an flist:

class depth field (
   type = data_type
   perms = permission permission ...,
);
  

Where class specifies whether it is a field, array, or a substruct, depth contains an asterisk for each nesting level of the field, and field specifies the name of the field.

Examples:

field PIN_FLD_NAME (
      type    =    PIN_FLDT_STR(255),
      perms   =    M,
);
array * PIN_FLD_INHERITED_INFO (
        type    =               PIN_FLDT_ARRAY,
        perms   =               O,
);

Field Permissions

For fields in opcode input and output flists, the flist specifications specify if a field is mandatory or optional.

About Opcode Usage

Recommended: opcodes are designed specifically for you to call from your custom applications. They are not expected to change from release to release.

Limited: opcodes should only be called in special cases. They may change from release to release.

Last Resort: opcodes should only be called if absolutely necessary. Calling these opcodes means that you are either on the wrong track or rewriting major portions of code. BRM will change these opcodes as necessary.

About Transaction Usage

Each opcode uses one of the following types of transaction handling:

Transaction Handling: Required

The transaction for this opcode can be wrapped in a transaction opened by another opcode.

If a read-write transaction is already open when this opcode is executed, all data modifications take place within the open transaction. The modifications are committed or aborted along with all other changes when the transaction is committed or aborted.

If no transaction is open when the opcode is called, a read-write transaction is opened. All actions are performed within this transaction, ensuring that the entire operation is performed atomically. If an error occurs during the execution of the opcode, all changes are aborted when the transaction is aborted. If no error occurs, the transaction is committed at the end of the operation.

This opcode requires a read-write transaction. It is therefore an error to have a read-only transaction open when this opcode is called.

Transaction Handling: Requires New

This opcode manages transactions internally to ensure absolute integrity of the database. A transaction for this opcode cannot be wrapped in another transaction.

If no transaction is open when the opcode is called, a read-write transaction is automatically opened and all actions are performed within this transaction.

If a transaction is already open when the opcode is called, an error occurs.

Transaction Handling: Supports

This opcode does not modify object data. If it is called while a transaction is not already open, the operation is executed without transactional control.

If a read-write or read-only transaction is already open when this opcode is called, the opcode is executed as part of the transaction and reads the in-process state of the data.

If the opcode is called when a separate, unrelated transaction is taking place, it reads the last saved state of the database.

Calling PCM Opcodes

You call the base and FM opcodes by using PCM_OP. You pass the opcode you want to call as one of the input parameters. PCM_OP() executes the opcode in its input parameters list in an open communication channel or a context.

You use the following parameters and flags with PCM_OP():

pcm_ctxp

  • Pointer to an open PCM context.

opcode

  • Name of the opcode you want to call.

flags

  • (int32)NULL

    No flags specified. Use only when there are no flags defined for this operation.

  • PCM_OPFLG_READ_RESULT

    Returns all the fields in the storable object from the output flist, not just the POID. Valid only for opcodes that create storable objects.

  • PCM_OPFLG_CALC_ONLY

    Calculate only. Valid only for opcodes that create storable objects. No fields in the database are changed and the storable object is not actually created. Instead, fields that would have been used to create the storable object are returned to the caller on the output flist.

in_flistp

  • An input flist specification for the opcode defining the required and optional input fields for the opcode to function properly. Each opcode has an input flist specification that you must use to create the input. See the input flist specification in an individual opcode description for details.

ret_flistpp

  • An output flist specification defining what you expect the opcode to return. Each opcode has an output flist specification that you must use to create the input. You must explicitly destroy the return flist to free memory. See the output flist specification in an individual opcode description for details.

ebufp

  • Pointer to an error buffer. Used to pass status information back to the caller.

The following example shows how to call the policy opcode PCM_OP_CUST_POL_GET_PLANS to get pricing plans:

/*Declarations*/
pin_errbuf_t *ebufp
input_flistp = PIN_FLIST_CREATE(ebufp); 
return_flistp = PIN_FLIST_CREATE(ebufp); 
  
PCM_OP(ctxp, PCM_OP_CUST_POL_GET_PLANS, 0, input_flistp, &return_flistp, ebufp); 

Manipulating Objects in Custom Applications

There are three basic steps to manipulating objects in a custom application or module:

  1. Open a context by calling PCM_CONTEXT_OPEN or PCM_CONNECT in an application.

  2. Call opcodes with PCM_OP.

  3. Close the context by using PCM_CONTEXT_CLOSE.

Context Management Opcodes

The context management opcodes open and close a communication channel to the BRM database by opening and closing a context to the Connection Manager (CM). The context structure is opaque to the application. It contains state data used by the PCM library to manage the communication channel.

The context management opcodes include functions for synchronous and asynchronous transactions. All transactions must follow these rules:

  • Each application can connect to only one CM at a time.

  • Only one connection can be open to a DM at a time.

  • All object manipulation functions performed within a transaction must apply to the same BRM database schema.

When a context is opened, you can call additional functions to open, close, and commit or abort transactions within the open context.

When you open a PCM context, a connection is established between your application and the BRM server. This connection adds significant overhead to the system because of the security and auditing checks performed by BRM. Therefore, to maximize performance, make sure your application keeps the context open until all the operations are performed. If your application opens and closes contexts frequently, performance will be affected.

If you are writing applications, such as Web-based Active Server Pages or CGI scripts, that cannot maintain an open context for a long time, use CM Proxy. CM Proxy allows your application to access the database with a pre-authorized connection and avoid the system overhead of a login for each connection.

For more information on CM Proxy, see "Using CM Proxy to Allow Unauthenticated Log On" in BRM System Administrator's Guide.

For a list of context management opcodes, including links to the documentation for each opcode, see "Context Management Opcodes" in BRM Developer's Reference.

Base Opcodes

You use base opcodes to perform operations such as creating and manipulating objects, searching, and transaction handling. Base opcodes are implemented in the Data Manager, unlike the other opcodes, which are implemented in the Connection Manager.

Base opcodes require an open communication context and an input flist as parameters. The input flist specifies the input field arguments, and is not modified during execution.

You call the object manipulation opcodes with PCM_OP. The opcode you want to call is an input parameter.

Base opcodes pass back a return flist as a parameter. The return flist contains the result field arguments. The memory for the return flist is dynamically allocated.

You can run basic object manipulation macros in any combination within a transaction, depending on the resources available.

Search and Global Search Opcodes

Some base opcodes are used for searching in BRM. "Searching" in this context means looking in your BRM database for objects that meet a criteria that you specify. That is, you want the POIDs of all the classes that share certain characteristics. The PCM_OP_SEARCH_* and PCM_OP_GLOBAL_SEARCH_* opcodes are designed for this purpose. They search single or multiple database schemas for accounts that match the criteria you specify and return the POIDs of those accounts.

After you know the POIDs of accounts, you can call other base opcodes designed to read or change data, such as PCM_OP_READ_OBJ, PCM_OP_WRITE_OBJ, or PCM_OP_DELETE_OBJ.

See "Searching for Objects in the BRM Database" for a discussion of searching and a list of the SEARCH opcodes. This document explains the BRM searching strategy, including the types of searching that BRM does by default and what you need to know if you are writing custom applications to use on the BRM database.

When you write a custom DM, depending on your needs, you implement opcodes from the following set:

FM Opcodes

FMs (Facilities Modules) are shared libraries that implement higher-level opcodes. Each FM implements a set of opcodes to perform operations specific to that module. FMs create online accounts, manage customer-related information, charge customers for resource usage, and allow third-party systems to be integrated with BRM. In the billing FM, for example, opcodes perform advanced billing-related operations on user accounts.

You call the FM opcodes using PCM_OP, with the FM opcode you are calling as the input parameter.

FM opcodes are divided into the following types:

  • Standard FM opcodes perform specific BRM operations. You cannot change the standard opcodes. However, if you want to add new functionality, you can write new opcodes.

    For more information, see "Writing a Custom Facilities Module".

  • Policy FM opcodes contain the BRM business logic. You can modify the default behavior of policy opcodes to suit your business needs. BRM includes the source code for all the policy opcodes.

    For example, you can bill customers on their anniversary date or on the first day of each month by modifying the default implementation of the PCM_OP_CUST_POL_PREP_ACTINFO policy opcode.

    For more information on customizing policy opcodes, see "Adding and Modifying Policy Facilities Modules".

BRM includes a set of policy opcodes, including source code, as hooks for you to add your code. These opcodes do not have a default implementation.

Standard FMs that use business logic to process requests have policy FMs associated with them. A few FMs, such as the SDK FM and the Group FM, which are internal to BRM and do not need business logic for processing data, do not have associated policy FMs.

Each of the BRM optional managers has its own FM. See the appropriate optional manager documentation for more information.

About the PREP and VALID Opcodes

Many opcodes, for example, PCM_OP_CUST_SET_LOGIN and PCM_OP_CUST_PREP_CUSTOMER, call policy PREP and VALID opcodes, such as PCM_OP_CUST_POL_PREP_PASSWD and PCM_OP_CUST_POL_VALID_PASSWD. You can use PREP and VALID opcodes to customize how data is processed.

  • Use the PREP opcodes to process data before it is validated. Typical processing includes adding missing fields whose values are derived or generated by the PREP operation, and forcing fields to predefined values independent of what the customer specified. PREP opcodes are given a set of customer-specified fields on the input flist, and return the processed version of the same data on the output flist.

    If a PREP opcode cannot derive all the necessary fields because the customer-specified values used in the derivation are incorrect, no error is returned. Instead, the derived fields are put on the output flist with a default value, and the corresponding VALID call detects the incorrect data and returns the validation error to the calling application. This approach allows the calling application to see the details of the validation error rather than receiving a less precise ebuf error passed up from the PREP opcode.

    If a PREP opcode cannot generate a necessary field or some other internal problem is encountered, an ebuf error is returned.

  • Use the VALID opcodes to validate field values. Typical checks include formatting tests for data integrity, tests for illegal values and tests for required information that is missing. VALID opcodes are given a set of related fields and values on the input flist, and return a list of fields that failed the validation tests on the output flist. The VALID opcodes cannot alter the value of a field that is not suitable, that is the purpose of the PREP opcodes.

    If one or more fields fail the validation tests, they are returned using the PIN_FLD_FIELDS array on the output flist. This array is structured to allow fields nested within arrays or substructs to be accurately represented. All fields that failed validation are returned by the operation, so the caller can correct all errors at once and retry the operation.

Validating Fields by Using Field Validation Editor

To validate the field validations that you specify in the Field Validation Editor, use PCM_OP_CUST_VALID_FLD.

Supporting an Older Version of BRM

The PIN_FLD_VERSION flag on the PCM_OP_CUST_COMMIT_CUSTOMER input flist specifies whether the flist complies with the current version of BRM. If it doesn't, new BRM objects are created. This supports backward compatibility. The current version is this version of BRM.

Possible flag values are:

  • PIN_PORTAL_VERSION_CURRENT (a value of 0) specifies this version of BRM.

  • PIN_PORTAL_VERSION_LEGACY (a value of 1) specifies a legacy version of BRM. This is the default. If PIN_PORTAL_VERSION_LEGACY is specified, the input flist is converted to the current version and all necessary objects, including the /billinfo, /balance_group, and /payinfo objects are created for the account.

Creating Customization Interfaces

You can create or customize features without programming:

Accessing pin.conf Files in Custom Code

You can use the PCM C++ PinConf class to enable your code to read values from a pin.conf file. For example, this code is from the policy source file fm_rate_pol_tax_loc.c. This code gets the value of the customer's tax locale from the Connection Manager (CM) pin.conf file:

/***********************************************************
 * Look up the ISP city from pin.conf
 ***********************************************************/
  
pin_conf("fm_rate_pol", "provider_loc", PIN_FLDT_STR, 
(caddr_t *)&locale, &perr);
  

The entry in the pin.conf file looks like this:

#======================================================================
# provider_loc
#
# City, state, ZIP code, and country where you provide services to
# your customers.
#
# This information is used to determine tax rates.
#======================================================================
- fm_rate_pol provider_loc Cupertino, CA 95014 USA
  

In the following example, this code in the fm_subscription_pol_spec_cancel.c policy source code file gets a value (0 or 1) from an entry in the CM pin.conf file:

/* * For all products without a provisioning tag cancel and
 * delete product from table.
 */
  
if (pin_conf_keep_cancelled_products_or_discounts == 0){
    PIN_FLIST_FLD_SET(p_arrayp, PIN_FLD_ACTION,
    PIN_BILL_CANCEL_PRODUCT_ACTION_CANCEL_DELETE, ebufp);
} else {
    PIN_FLIST_FLD_SET(p_arrayp, PIN_FLD_ACTION,
    PIN_BILL_CANCEL_PRODUCT_ACTION_CANCEL_ONLY, ebufp);
}
  

The following example shows the entry in the pin.conf file.

#========================================================================
# keep_cancelled_products_or_discounts
#
# Specifies whether to keep canceled products and discounts in the 
#  accounts products and discounts array. 
#
# The value for this entry can be: 
# 0 = (Default) Deletes the canceled products or discounts from 
# the accounts products and discounts array.
# 1 = Keep the deleted products or discounts in the accounts 
# products and discounts array 
#
#========================================================================
- fm_subscription_pol keep_cancelled_products_or_discounts 1
  

In addition to retrieving a value from a pin.conf file, you can hard code a default value that is used if the entry is not present in the pin.conf file.

For information about the PinConf class, see "Accessing Configuration Values by Using pin.conf".

Using /config/business_params Objects

You can customize BRM by adding new business parameters to control various aspects of BRM operations and calling these business parameters from policy opcodes. You can also add completely new business parameter classes to BRM.

Adding and Loading New Parameters

Adding parameters is useful if you are customizing existing functionality; for example, to expand the criteria used to determine whether a payment should be suspended. To do this, you customize PCM_OP_PYMT_POL_VALIDATE_PAYMENT, the policy opcode that validates payments, to filter any payments below a specified amount.

For added flexibility, you may also want the ability to turn off this filter at certain times. One way to do this is to add a parameter to the /config/business_params object for the ar parameter class and have PYMT_POL_VALIDATE_PAYMENT check that parameter.

To implement the /config/business_params part of this process, you create a new parameter that you enable or disable depending on whether you want to filter payments below a specified amount so that these payments do not get suspended. This parameter will be called payment_suspense_amount_filter in the /config/business_params object and PaymentSuspenseAmntFilter in the supporting XML file set. You add the parameter as follows:

  1. Modify the bus_params_AR.xsd file in the BRM_Home/sys/data/config/ directory to add the new parameter. (BRM_Home is the directory in which you installed BRM components.)

    <xs:element name="PaymentSuspenseAmntFilter" type="switch">
      <xs:annotation>
        <xs:documentation>Enable/Disable filtering 
        of payment suspense based on payment amount. The parameter
        values can be 0 (disabled) or 1 (enabled). The default is 0
        (disabled).</xs:documentation> 
      </xs:annotation>
    </xs:element>
      
    
  2. Modify the bus_params_AR.xsl file in the BRM_Home/sys/data/config/ directory to add the new parameter:

    <xsl:template match="bc:PaymentSuspenseAmntFilter">
      <xsl:element name="Param">
        <xsl:element name="Name">
          <xsl:text>payment_suspense_amount_filter</xsl:text> 
        </xsl:element>
        <xsl:element name="Desc">
          Enable/Disable filtering of payment suspense based on 
          payment amount. The parameter values can be 0 (disabled)
          or 1 (enabled). The default is 0(disabled).
        </xsl:element> 
        <xsl:element name="Type">INT</xsl:element> 
        <xsl:element name="Value">
          <xsl:choose>
            <xsl:when test="text() = 'enabled'">
              <xsl:text>1</xsl:text> 
            </xsl:when>
            <xsl:otherwise>
              <xsl:text>0</xsl:text> 
            </xsl:otherwise>
          </xsl:choose>
        </xsl:element>
      </xsl:element>
    </xsl:template>
      
    
  3. Modify the bus_params_to_AR.xsl file in the BRM_Home/sys/data/config/ directory to add the new parameter:

    <xsl:when test="$name = 'payment_suspense_amount_filter'">
      <xsl:element name="PaymentSuspenseAmntFilter">
        <xsl:choose>
          <xsl:when test="$value = '1'">
            <xsl:text>enabled</xsl:text> 
          </xsl:when>
          <xsl:when test="$value = '0'">
            <xsl:text>disabled</xsl:text> 
          </xsl:when>
        </xsl:choose>
      </xsl:element>
    </xsl:when>
      
    
  4. Use the pin_bus_params utility to retrieve the ar instance of the /config/business_params object:

    pin_bus_params -r BusParamsAR bus_params_AR.xml
      
    
  5. Modify the resulting XML file to add the new parameter:

    <PaymentSuspenseAmntFilter>disabled</PaymentSuspenseAmntFilter>
      
    
  6. Use the pin_bus_params utility to load the object from the modified XML file:

    pin_bus_params bus_params_AR.xml
      
    

For information on using the pin_bus_params utility, see pin_bus_params.

Adding and Loading New Parameter Classes

Adding parameter classes is useful if you are creating entirely new BRM features or customizing existing functionality that has no associated parameter class. For example, there are a number of ways that you could customize BRM to control whether or not certain types of resources are eligible for resource reservation. Typically, these implementations require that you customize one of more Resource Reservation policy opcodes.

If you want the ability to switch back and forth between resources when BRM makes this decision, you could call a business parameter from the customized policy opcode. Because BRM doesn't have a parameter class dedicated to resource reservation, you create a new /config/business_params object for this parameter class. You name the parameter class resource-res.

To support this new parameter class, you create a set of four files:

  • bus_params_reservation.xml: Contains the parameter settings from the /config/business_params object for resource-res. Parameter settings in this file are loaded into the object by using the pin_bus_params utility.

  • bus_params_reservation.xsd: Validates the contents of the bus_params_reservation.xml file when loading the object.

  • bus_params_reservation.xsl: Translates the contents of the bus_params_reservation.xml file into the correct format for the /config/business_params object. The pin_bus_params utility calls this file when loading the object.

  • bus_params_to_reservation.xsl: Translates the contents of the /config/business_params object into XML format during object retrieval.

This parameter class you create will be called BusParamsReservation in XML. The class will include one parameter to control which resource is eligible for resource reservation-US dollars or free minutes. This parameter will be called reserve-currency-noncurrency in the /config/business_params object and ReserveCurrencyNoncurrency in the supporting XML file set.

To implement the /config/business_params part of this process:

  1. Copy one of the bus_params_ParameterClassName.xsd sample files in BRM_Home/sys/data/config/ and save it as bus_params_reservation.xsd. Modify the file as follows:

    <?xml version="1.0" encoding="UTF-8" ?> 
      
    <xs:schema   targetNamespace="http://www.portal.com/schemas/BusinessConfig"
      xmlns:businessConfig="http://www.portal.com/schemas/
        BusinessConfig" 
      xmlns:xs="http://www.w3.org/2001/XMLSchema"
      elementFormDefault="qualified"
      attributeFormDefault="unqualified">
      
      <xs:annotation>
        <xs:documentation
        </xs:documentation> 
      </xs:annotation>
      
      <xs:complexType name="BusParamsReservationType">
        <xs:sequence>
          <xs:element name="ReserveCurrencyNoncurrency" type="switch">
            <xs:annotation>
              <xs:documentation>
                The resource to reserve. The parameter values can be 
                0 (USdollars) or 1 (FreeMinutes). The default is 
                1 (USdollars).
              </xs:documentation> 
            </xs:annotation>
            <xs:simpleType name="resoption">
              <xs:restriction base="xs:string">
                <xs:enumeration value="USdollars" /> 
                <xs:enumeration value="FreeMinutes" /> 
                <xs:whiteSpace value="collapse" /> 
              </xs:restriction>
            </xs:simpleType>
          </xs:element>
        </xs:sequence>
      </xs:complexType>
      
    </xs:schema>
      
    
  2. Copy one of the bus_params_ParameterClassName.xsl sample files in BRM_Home/sys/data/config/ and save it as bus_params_reservation.xsl. Modify the file as follows:

    <?xml version="1.0" encoding="UTF-8" ?> 
      
    <xsl:stylesheet 
      version="1.0"   xmlns="http://www.portal.com/schemas/BusinessConfig"   xmlns:bc="http://www.portal.com/schemas/BusinessConfig"   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"   exclude-result-prefixes="bc">
      
      <xsl:output method="xml" indent="yes" /> 
      
      <xsl:template match="/">
        <BusinessConfiguration       xmlns="http://www.portal.com/schemas/BusinessConfig"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xsi:schemaLocation="http://www.portal.com/schemas/
            BusinessConfig business_configuration.xsd">
          <BusParamConfiguration>
          <BusParamConfigurationList>
            <ParamClass desc="Business logic parameters for Resource           Reservation" name="resource-res">
              <xsl:apply-templates             select="/bc:BusinessConfiguration/
                bc:BusParamConfigurationClass/
                bc:BusParamsReservationType/bc:*" />
            </ParamClass>
          </BusParamConfigurationList>
          </BusParamConfiguration>
        </BusinessConfiguration>
      </xsl:template>
      
      <xsl:template match="bc:ReserveCurrencyNoncurrency">
        <xsl:element name="Param">
          <xsl:element name="Name">
            <xsl:text>reserve_currency_noncurrency</xsl:text> 
          </xsl:element>
          <xsl:element name="Desc">
            The resource to reserve. The parameter values can be 
            0 (USdollars) or 1 (FreeMinutes). The default is 
            1 (USdollars).
          </xsl:element> 
          <xsl:element name="Type">INT</xsl:element> 
          <xsl:element name="Value">
            <xsl:choose>
              <xsl:when test="text() = 'FreeMinutes'">
                <xsl:text>1</xsl:text> 
              </xsl:when>
              <xsl:otherwise>
                <xsl:text>0</xsl:text> 
              </xsl:otherwise>
            </xsl:choose>
          </xsl:element>
        </xsl:element>
      </xsl:template>
      
    </xsl:stylesheet>
      
    
  3. Copy one of the bus_params_to_ParameterClassName.xsl sample files in BRM_Home/sys/data/config/ and save it as bus_params_to_reservation.xsl. Modify the file as follows:

    <?xml version="1.0" encoding="UTF-8" ?> 
      
    <xsl:stylesheet 
      version="1.0"   xmlns="http://www.portal.com/schemas/BusinessConfig"   xmlns:bc="http://www.portal.com/schemas/BusinessConfig"   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"   exclude-result-prefixes="bc">
      
      <xsl:output method="xml" indent="yes" /> 
      
      <xsl:template match="/">
        <BusinessConfiguration       xmlns="http://www.portal.com/schemas/BusinessConfig"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xsi:schemaLocation="http://www.portal.com/schemas/
            BusinessConfig business_configuration.xsd">
          <BusParamConfigurationClass>
            <BusParamsReservation>
              <xsl:apply-templates             select="/bc:BusinessConfiguration/
                bc:BusParamConfiguration/bc:BusParamConfigurationList/
                bc:ParamClass/bc:Param" /> 
            </BusParamsReservation>
          </BusParamConfigurationClass>
        </BusinessConfiguration>
      </xsl:template>
      
      <xsl:template match="//bc:Param">
        <xsl:variable name="name">
          <xsl:value-of select="bc:Name/text()" /> 
        </xsl:variable>
        <xsl:variable name="value">
          <xsl:value-of select="bc:Value/text()" /> 
        </xsl:variable>
        <xsl:choose>
          <xsl:when test="$name = 'reserve_currency_noncurrency'">
            <xsl:element name="ReserveCurrencyNoncurrency">
              <xsl:choose>
                <xsl:when test="$value = '1'">
                  <xsl:text>FreeMinutes</xsl:text> 
                </xsl:when>
                <xsl:when test="$value = '0'">
                  <xsl:text>USdollars</xsl:text> 
                </xsl:when>
              </xsl:choose>
            </xsl:element>
          </xsl:when>
        </xsl:choose>
      </xsl:template>
      
    </xsl:stylesheet>
      
    
  4. Copy one of the bus_params_ParameterClassName.xml sample files in BRM_Home/sys/data/config/ and save it as bus_params_reservation.xml. Modify the file as follows:

    <?xml version="1.0" encoding="UTF-8" standalone="no" ?>
      
    <BusinessConfiguration      xmlns="http://www.portal.com/schemas/BusinessConfig"      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xsi:schemaLocation="http:2www.portal.com/schemas/Business
         Config business_configuration.xsd">
      
      <BusParamConfigurationClass>
        <BusParamsReservation>
          <ReserveCurrencyNoncurrency>
            USdollars
          </ReserveCurrencyNoncurrency>
        </BusParamsReservation>
      </BusParamConfigurationClass>
      
    </BusinessConfiguration>
      
    
  5. Modify the bus_params_conf.xsd file in the BRM_Home/xsd directory to add the new parameter class.

    1. Add the following line to the schema location segment of the file:

      <xs:include schemaLocation="bus_params_reservation.xsd"/>
        
      
    2. Add the following line to the parameter class selection segment of the file:

      <xs:element name="BusParamsReservation" type="BusParamsReservationType"/>
        
      
  6. Use the pin_bus_params utility to load this file, creating a new resource-res parameter instance of the /config/business_params object:

    pin_bus_params bus_params_reservation.xml
      
    

For information on using the pin_bus_params utility, see pin_bus_params.

Examples of Accessing Business Parameters in Custom Code

Opcodes read configuration values from /config/business_params objects to determine whether to execute various functions. The following examples show how several BRM policy opcodes call values from /config/business_params objects.

Calling Business Parameters from PCM_OP_PYMT_POL_VALIDATE_PAYMENT

In its default implementation, the PCM_OP_PYMT_POL_VALIDATE_PAYMENT policy opcode checks whether payment suspense management is enabled. If so, it places payments that could not be validated into suspense.

This code in the fm_pymt_pol_validate_payment.c policy source file determines whether to suspend payments that can't be validated. To make this determination, BRM calls the psiu_bparams_get_int() function and uses the psiu_business_params.h header file to retrieve specific parameters from the appropriate /config/business_params object. This information is used to determine whether payment suspense management is enabled (PSIU_BPARAMS_AR_PYMT_SUSPENSE_ENABLED):

/*************************************************************
* Check if Payment Suspense Management feature is enabled
*************************************************************/
pymt_suspense_flag = psiu_bparams_get_int(ctxp, PSIU_BPARAMS_AR_PARAMS,
     PSIU_BPARAMS_AR_PYMT_SUSPENSE_ENABLE, ebufp);
if ((pymt_suspense_flag != PSIU_BPARAMS_AR_PYMT_SUSPENSE_ENABLED)&&
     (pymt_suspense_flag != PSIU_BPARAMS_AR_PYMT_SUSPENSE_DISABLED)) 
     {
       pin_set_err(ebufp, PIN_ERRLOC_FM,
         PIN_ERRCLASS_SYSTEM_DETERMINATE,
         PIN_ERR_INVALID_CONF, 0, 0, 0);
       PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR,
       "bad param value for \"payment_suspense_enable\" in /config/business_params",
         ebufp);
     }
  

The segment that enables payment suspense management in the /config/business_params object looks like this:

0 PIN_FLD_PARAMS          ARRAY [2] allocated 4, used 4
1    PIN_FLD_DESCR          STR [0] "Enable/Disable payment suspense management. 
                                     The parameter values can be 0 (disabled), 
                                     1 (enabled). Default is 0 (disabled)."
1    PIN_FLD_PARAM_NAME     STR [0] "payment_suspense_enable"
1    PIN_FLD_PARAM_TYPE     INT [0] 1
1    PIN_FLD_PARAM_VALUE    STR [0] "1"
  

Calling Business Parameters from PCM_OP_BILL_POL_REVERSE_PAYMENT

In its default implementation, the PCM_OP_BILL_POL_REVERSE_PAYMENT policy opcode reverses payments applied to accounts that were written off; it does not reverse the payment if the write-off reversal was anything other than an account-level write-off.

This code in the fm_bill_pol_reverse_payment.c policy source code determines whether the write-off was at the account level. To make this determination, BRM calls the psiu_bparams_get_str() function and uses the psiu_business_params.h header file to retrieve specific parameters from the appropriate /config/business_params object. This information is used to determine whether write-off level is PSIU_BPARAMS_AR_PYMT_SUSPENSE_ENABLED. If so, it reverses the payment, again writing off the account:

/**************************************************************
* Verify if write off level set to "a" (account) in 
* /config/business_params and Call PCM_OP_AR_ACCOUNT_WRITEOFF
**************************************************************/
  
psiu_bparams_get_str(ctxp, PSIU_BPARAMS_AR_PARAMS, 
PSIU_BPARAMS_AR_WRITEOFF_LEVEL, writeoff_rev_level, 2, ebufp); 
  
if ( status_flag && ( *status_flag == PIN_PYMT_WRITEOFF_SUCCESS ) && 
     writeoff_rev_level && 
     !strcmp(writeoff_rev_level, PIN_WRITEOFF_REV_LEVEL_ACCOUNT) )
     { 
       i_flistp = PIN_FLIST_CREATE(ebufp);
  
       vp = PIN_FLIST_FLD_GET(in_flistp, PIN_FLD_POID, 0, ebufp);
       PIN_FLIST_FLD_SET(i_flistp, PIN_FLD_POID, vp, ebufp);
  
       vp = PIN_FLIST_FLD_GET(in_flistp, PIN_FLD_PROGRAM_NAME, 0, ebufp);
       PIN_FLIST_FLD_SET(i_flistp, PIN_FLD_PROGRAM_NAME, vp, ebufp);
       vp = PIN_FLIST_FLD_GET(in_flistp, PIN_FLD_START_T, 1, ebufp);
       if (vp) 
       {
         PIN_FLIST_FLD_SET(i_flistp, PIN_FLD_START_T,
         (void *) vp, ebufp);
       }
  

The segment that determines the write-off level in the /config/business_params object looks like this:

0 PIN_FLD_PARAMS          ARRAY [2] allocated 4, used 4
1    PIN_FLD_DESCR          STR [0] "Selection of level of writeoff to be tracked for the
                                     purpose of writeoff reversal. Values can be a(Account),
                                     b(Bill), i(Item), *(Any)."
1    PIN_FLD_PARAM_NAME     STR [0] "writeoff_level"
1    PIN_FLD_PARAM_TYPE     INT [0] 5
1    PIN_FLD_PARAM_VALUE    STR [0] "a"
  

For information about the /config/business_params object, see /config/business_params and pin_bus_params.