$TXT Created by TOPPENBERG,KEVIN at FAMILY PHYSICANS OF GREENEVILLE (KIDS) on Wednesday, 02/18/09
=============================================================================
Run Date: MAR 31,2010                   Designation: TMG-CPRS-TEXTOBJ-PARAM*1.0*1
Package : TMG - FAMILY PHYSICANS OF GREENEVILLE  Priority: Optional
Version : 1       SEQ #1                       Status: Released
=============================================================================

Associated patches: None

Subject: Patch to passing parameters to TIU text objects, both from CPRS, but also from
         other places within VistA

**NOTICE: This patch will replace the routine TIUSRVD in order to provide a
          custom version of $$BOIL^TIUSRVD.  The first two lines of the new
          routine are below.  Before installing this patch, compare this to
          your particular version of this routine.  **If your routine is newer
          than the one provided, then see instructions below for manually
          inserting new routine, and DO NOT APPLY THIS PATCH.

          TIUSRVD ; SLC/JER - RPC's for document definition ; 09/12/2003 [6/8/05 8:07am]
          ;;1.0;TEXT INTEGRATION UTILITIES;**1,7,22,47,103,100,115,164,112,186,201**;Jun 20, 1997

Category:
  - Routine

Description:
============
  This patch provides new functionality, as described below.

  Expanded Template Functions, including math functions and dynamic text objects
  ------------------------------------------------------------------------------
  * The traditional CPRS template functionality allowed syntax as below.
  This is a test template for |PATIENT NAME|

          Enter value:  {FLD:NUMB1-16}

  * The above template would result in the patient name, pulled from the server, to be placed in the final document.  It would also generate a GUI box with a field that the user can interact with.  In the example below, the field "NUMB1-16" happens to be a drop-down box.  When the user selects a number and presses [OK], the resulting text is inserted into the note.  However, nothing more can be done with the user input inside the template.

  * The new extension allows syntax as below:

     This is a test template for |PATIENT NAME|

     Enter value:  {FLD:NUMB1-16}
     Enter value:  {FLD:NUMB1-16}

     Result 1: {FN: [FLD:1:NUMB1-16] + [FLD:2:NUMB1-16] }

  * The above template would present the user with a GUI box containing two drop-down boxes.  And the output text would evaluated in a math function.  In this case the math function is a simple addition of the two fields.  Notice the syntax of how to identify which field is being referred to.  So [FLD:1:NUMB1-16] refers to the first instance of the field, and [FLD:2:NUMB1-16] is the second instance of this same field.   More details on this syntax below.

  * The following syntax is also allowed.  This will cause a text object (in this example it is the object |PATIENT NAME|).  By itself, the only difference between this and simply including the object directly into the template is that that text object is not resolved (i.e. value obtained from the server) until after the user presses OK on the GUI box.  More below.

     Result 3: {OBJ:PATIENT NAME}

  * If the TMG-CPRS-TEXTOBJ-PARAM patch is installed then one may pass parameters into text objects.  And thus one can also use the value from a field as one of the parameters.  (The server code supporting the custom text objects must be programmed to accept the custom parameter.  Syntax to be detailed further below. ) Examples of syntax:

     This is a sample of a plain text object:  |PATIENT NAME|

     And this is an object with a parameter  |MY TEXT OBJECT{5}|
     or another object with a parameter |MY TEXT OBJECT{Some Text}|

  * And now one may see the value of the {OBJ:... syntax   Below is an example of a text object being passed with user-generated input as a parameter.  The value of the second GUI field is resolved into it's output value, and this is passed as a parameter into the text object.

     Enter value:  {FLD:NUMB1-16}
     Enter value:  {FLD:NUMB1-16}

     {OBJ:MY TEXT OBJECT{[FLD:2:NUMB1-16]}}

    So, if the user selected a value of "1" for the first drop-down box, and "9" for the second drop down box, then the object would be resolved as follows:

     {OBJ:MY TEXT OBJECT{9}}

     And the server code might be written to return a value like this:

     "The user entered: 9"   (or something more clinically useful)

  * The {OBJ:... syntax may also be used in math formulas.  Of course, the output of the text object would have to be text that was only a numeric value.  So, we could have a text object that converted weight into a body-mass-index (BMI).  And this value could then used in a formula. In the example below, the field WEIGHT-LB provides a text box for the user to enter the patient weight in pounds.  (This field would have to be created in CPRS just like all other fields.  See standard CPRS documentation for details.)  And for the example, we will have a custom text object named "PT WEIGHT TO BMI".  (And this text object would have to be defined on the server.  More on this further below).  There is no clinical reason why one would want to subtracting 5 from a patient�s BMI.  But it demonstrates what is possible.

     Enter value:  {FLD:WEIGHT-LB}
     Here is the result of the formula: {FN:[OBJ:PT WEIGHT TO BMI{[FLD:1:WEIGHT-LB]}]-5}

  * Details on referring to fields in functions and text objects.   Consider the example template below:

     Enter value:    {FLD:NUMB1-16}    <--- 1st instance of NUMB1-16
     Enter Units:    {FLD:UNITS}
     Enter location: {FLD:LOCATION}
     Enter value:    {FLD:NUMB1-16}    <--- 2nd instance of NUMB1-16
     Enter Units:    {FLD:UNITS}
     Enter location: {FLD:LOCATION}
     Enter value:    {FLD:NUMB1-16}    <--- 3rd instance of NUMB1-16
     Enter location: {FLD:LOCATION}
     Enter Units:    {FLD:UNITS}

  To refer to the 3rrd instance of the field NUMB1-16, use this syntax:

     [FLD:3:NUMB1-16]

  Notice that this is not the 3rd field on the form (that actually would be the first instance of the LOCATION field).  But it is the 3rd time that NUMB1-16 is used.  So the following rules apply:
   i) Entire reference is enclosed in square brackets ("[", "]")
   ii) Starts with "FLD:", which must be UPPER CASE
   iii) Next is an instance number that refers to a particular field,
      as described above, followed by another ":".
   iv) And lastly is specified the Field name, which must exactly match
      in spelling and case-sensitivity.
   v) Notice the similarity between the declaration and the reference,
      so as not to get confused.

      {FLD:NUMB1-16}    <--- used by CPRS to make a GUI input field for user
      [FLD:3:NUMB1-16]  <--- used, in a FN or OBJ to refer to a field.

  * To refer to an text object in a function, the following syntax rules apply:
   i) Entire reference is enclosed in square brackets ("[", "]")
   ii) Starts with "OBJ:", which must be UPPER CASE
   iii) Next is the name of the text object.  This is the name normally
      placed between "|" characters.  The "|" may be included or left off.

      [OBJ:MY OBJECT]  <---- Correct
      [OBJ:|MY OBJECT|]  <---- Also correct

   iv) If text object supports passing parameters, they must be surrounded by
      curly brackets ("{", "}").  E.g.

      [OBJ:MY OBJECT{123}]

      Only one parameter may be passed.  If one needs to pass more than one
      parameter into a function, one may place then all into one long string,
      separated by some unique character, e.g.

      [OBJ:MY OBJECT{123^ABC}]

      The server-side function would receive this as a parameter and then
      have to separate the parts itself.  It is allowed to use this syntax
      with multiple field entries.  E.g.

      [OBJ:MY OBJECT{[FLD:1:NUMB1-16]^[FLD:3:NUMB1-16]}]

   v) The order of resolution is to first resolve all FLD values, and then resolve
       OBJ items.
   vi) Having a text object as the parameter of another text object is allowed. E.g.

      [OBJ:MY OBJECT{[OBJ:ANOTHER OBJECT]}]

  * The syntax for functions is as follows:
   i) Example function:  {FN:(1+5)*3}
   ii) Entire function is enclosed in curly brackets. ("{", "}").
   iii) Starts with "FN:" which must be UPPER CASE.
   iv) All white space between ":" and closing "}" is not significant, and is removed.
   v) FLD values will be resolved first, then OBJ values, and then the function will
      be evaluated.
   vi) The mathematical expression must follow the following rules:
      (1) The only operators supported are: ^,*,/,+,-
      (2) There must be the same number of begin and end brackets.
      (3) Only the round brackets can be used, i.e. "(", ")"
      (4) All values must be valid constants.  A "valid constant," for this program,
         is defined as a string with:
         (a) No characters besides "0".."9," up to one ".",
         (b) Up to one "-" at the beginning
         (c) The string must be at least one character in length
         (d) Exponential sections are not supported, ie. "3.14E-10"
            is not supported.
   vii) If there is a problem evaluating the mathematical formula, then the output is just
       the text of the formula, inserted into the note text, without being evaluated.

  * Information for creating custom server-side text objects to accept parameters.
   i) On the server, in roll-and-scroll mode, go to menu option:
      TIUF DOCUMENT DEFINITION MGR
   ii) From there, select option  Create Objects [TIUFJ CREATE OBJECTS MGR]
   iii) From here, one can create text objects.  See TIU documentation for details.  The
      key factor is to make an entry into the Object Method field.  This should be a
      function that returns a value for X that will be put into the note in CPRS.
      Below is an example of the traditional way this is done:

      SET X="This is a test", or
      SET X=$$GETOBJ^TMGABC

   iv) To accept the passed parameter, one should change the object function to accept a
      variable X.  X is preloaded with the passed parameter.  E.g.

      SET X=$$GETOBJ^TMGABC(X)

   v) The above requires a custom version of the function $$BOIL^TIUSRVD, which is supplied
      in patch TMG-CPRS-TEXTOBJ-PARAM.  This can be found here:

   https://trac.opensourcevista.net/browser/cprs/branches/tmg-cprs/Server_KIDS

INSTRUCTIONS FOR MANUALL INSERTING NEW ROUTINE:
==============================================

This patch will replace the routine TIUSRVD in order to provide a custom version of
$$BOIL^TIUSRVD.  The first two lines of the new routine are below.

TIUSRVD ; SLC/JER - RPC's for document definition ; 09/12/2003 [6/8/05 8:07am]
;;1.0;TEXT INTEGRATION UTILITIES;**1,7,22,47,103,100,115,164,112,186,201**;Jun 20, 1997

Before installing this patch, compare this to your particular version of this routine.
**If your routine is newer than the one provided, then see instructions below for manually
inserting new routine, and DO NOT APPLY THIS PATCH.  Otherwise you may **skip this section**.

 1. Open the routine TIUSRVD in an editor.
 2. Search for tag/label BOIL
 3. Rename BOIL to BOIL0 as follows
    BOIL0(LINE,COUNT) ; Execute Boilerplates  ;"//kt original function name was BOIL (mod is below)
 4. Locate the tag/label: CANXEC(TIUODA)
 5. Insert the code below on the line before CANXEC

------Begin Code Copy Section----------
 ;
BOIL(LINE,COUNT) ; Execute Boilerplates  ;"//kt modification
   ;"Purpose: Resolve Text Objects.  Function is modified to allow |TEXT OBJECT{Parameters}|
   ;"Input: LINE -- One line of text that has one or more text objects
   ;"       COUNT -- (not used)
   ;"Results: Returns line of text with text objects resolved.
   ;"NOTE: [Parameter] may itself be a nested text object (arbitrary depth allowed)
   ;"Usage -- in text object definition, code may be like this:
   ;"   S X=$$MYFN^MYMOD(X)
   ;"       The value for X being passed into the object's code will hold the
   ;"       parameter found between { }
   ;"       This is backwards compatible.  If no parameter is specified, then X=""
   N TIUNEWG,TIUNEWR,TIUOLDG,TIUOLDR,TMGX
   N TIUI,DIC,X,Y,TIUFPRIV S TIUFPRIV=1
   S DIC=8925.1,DIC(0)="FMXZ"
   S DIC("S")="I $P($G(^TIU(8925.1,+Y,0)),U,4)=""O"""
   F TIUI=2:2:$L(LINE,"|") D
   . NEW SA,SB
   . SET X=$$MXTRACT(LINE,"|",.SA,.SB)
   . IF X["{" DO
   . . NEW X1,X2
   . . SET TMGX=$$MXTRACT(X,"{",.X1,.X2)
   . . IF TMGX["|" SET TMGX=$$BOIL(TMGX)
   . . SET X=X1_X2
   . ELSE  SET TMGX=""
   . D ^DIC
   . I +Y>0 DO
   . . I $D(^TIU(8925.1,+Y,9)),+$$CANXEC(+Y) DO
   . . . SET X=TMGX  ;"Load passed parameter (or "" if none) into X
   . . . X ^(9)
   . . . S:X["~@" X=$$APPEND(X)
   . . E  S X="The OBJECT "_X_" is INACTIVE...Contact IRM."
   . . I X["~@" D
   . . . I X'["^" D
   . . . . S TIUOLDR=$P(X,"~@",2),TIUNEWR=TIUOLDR_TIUI
   . . . . M @TIUNEWR=@TIUOLDR K @TIUOLDR
   . . . . S $P(X,"~@",2)=TIUNEWR
   . . . I X["^" D
   . . . . S TIUOLDG=$P(X,"~@",2),TIUNEWG="^TMP("_"""TIU201"""_","_$J_","_TIUI_")"
   . . . . M @TIUNEWG=@TIUOLDG K @TIUOLDG
   . . . . S $P(X,"~@",2)=TIUNEWG
   . ELSE  S X="The OBJECT "_X_" was NOT found...Contact IRM."
   . SET LINE=SA_X_SB
   Q LINE
 ;
MXTRACT(S,DIVCH,SA,SB,MAP)  ;"//kst added this function
   ;" Extract matched encapsulators
   ;" NOTE: see TMGSTUTL for a more robust version of function.
   IF '$DATA(MAP) DO MAPMATCH(S,.MAP)
   NEW RESULT SET RESULT=""
   NEW I SET I=0
   FOR  S I=$O(MAP(1,I)) QUIT:(I="")!(RESULT'="")  DO
   . IF DIVCH'=$G(MAP(1,I)) QUIT
   . NEW P,J
   . FOR J=1,2 SET P(J)=+$G(MAP(1,I,"P",J))
   . SET RESULT=$EXTRACT(S,P(1)+1,P(2)-1)
   . SET SA=$EXTRACT(S,1,P(1)-1),SB=$EXTRACT(S,P(2)+1,9999)
   IF RESULT="" SET SA=S,SB=""
   QUIT RESULT
 ;
MAPMATCH(S,MAP) ;"//kst added this function
   ;" Map out a string for matched encapsulators
   ;" NOTE: see TMGSTUTL.m for a more robust version of function.
   N MATCH,DEPTH,I,GRP,CH
   S MATCH("{")="}",MATCH("|")="|"
   K MAP
   S DEPTH=0,GRP=1
   F I=1:1:$L(S) D  Q:(GRP>1)  ;"Only deal with 1st entry
   . S CH=$EXTRACT(S,I)
   . I CH=$G(MAP(GRP,DEPTH,"End")) D  QUIT
   . . S MAP(GRP,DEPTH,"P",2)=I
   . . K MAP(GRP,DEPTH,"End")
   . . S DEPTH=DEPTH-1
   . . I DEPTH=0 S GRP=GRP+1
   . I $D(MATCH(CH))=0 QUIT
   . S DEPTH=DEPTH+1
   . S MAP(GRP,DEPTH)=CH
   . S MAP(GRP,DEPTH,"End")=MATCH(CH)
   . S MAP(GRP,DEPTH,"P",1)=I
   QUIT
 ;
------End Code Copy Section----------

AUTOMATIC INSTALLATION INSTRUCTIONS:
==========================
  This patch should cause minimal impact on live systems, as it provides only 1 routine,
  Installation will take less than 1 minute.  Users  may remain on the system.  Note: the
  follow instructions were copied from another KIDS install and modified.  There may be
  some discrepancies.

  The following are instructions for those using the Packman method:
  ------------------------------------------------------------------
  1.  Use the INSTALL/CHECK MESSAGE option on the PackMan menu.

  2.  Review your mapped set.  If any of the routines listed in the
      ROUTINE SUMMARY section are mapped, they should be removed
      from the mapped set at this time.

  3.  From the Kernel Installation and Distribution System Menu, select
      the Installation menu.

  4.  From this menu, you may elect to use the following options
      (when prompted for INSTALL NAME, enter TMG-CPRS-TEXTOBJ-PARAM*1.0*1:
          a.  Backup a Transport Global
          b.  Compare Transport Global to Current System
          c.  Verify Checksums in Transport Global

  5.  Use the Install Package(s) option and select the package TMG-CPRS-TEXTOBJ-PARAM*1.0*1

  6.  When prompted 'Want KIDS to INHIBIT LOGONs during the install? YES//'
      respond NO.

  7.  When prompted 'Want to DISABLE Scheduled Options, Menu Options, and
      Protocols? YES//', respond NO.

  8.  If routines were unmapped as part of step 2, they should be returned
      to the mapped set once the installation has run to completion.

  9.  (See step 9 below)

  The following are instructions for those loading the patch via Host File System:
  ---------------------------------------------------------------------------------
  1.  Navigate the menu option path to reach the Kernel Installation and Distribution
      System Menu.  Or, the menu option XPD MAIN may be entered directly.

  2.  Next, at the menu displaying:
          Edits and Distribution ...
          Utilities ...
          Installation ...     <---------- pick this one.

  3.  Next, at the menu displaying the options as below, choose each of the options
      in a step-by-step fashion, in numerical order (i.e. 1, 2, 3 etc.)  Step #1 will
      prompt the user to enter the file path on the host file system where the source
      file is stored.  The filename to enter is TMG-CPRS-TEXTOBJ-PARAM-1.0-1.KIDS, but add the
      appropriate path.  E.g. /tmp/TMG-CPRS-TEXTOBJ-PARAM-1.0-1.KIDS

       1      Load a Distribution
       2      Verify Checksums in Transport Global
       3      Print Transport Global
       4      Compare Transport Global to Current System
       5      Backup a Transport Global
       6      Install Package(s)
              Restart Install of Package(s)
              Unload a Distribution

  4.  From this menu, you may elect to use the following options
      (when prompted for INSTALL NAME, enter TMG-CPRS-TEXTOBJ-PARAM*1.0*1
          a.  Backup a Transport Global
          b.  Compare Transport Global to Current System
          c.  Verify Checksums in Transport Global

  5.  Use the Install Package(s) option and select the package TMG-CPRS-TEXTOBJ-PARAM*1.0*1

  6.  When prompted 'Want KIDS to INHIBIT LOGONs during the install? YES//'
      respond NO.

  7.  When prompted 'Want to DISABLE Scheduled Options, Menu Options, and
      Protocols? YES//', respond NO.

  8.  If routines were unmapped as part of step 2, they should be returned
      to the mapped set once the installation has run to completion.


=============================================================================
User Information:
Entered By  : TOPPENBERG,KEVIN            Date Entered : MAR 31,2010
Completed By: TOPPENBERG,KEVIN            Date Completed: MAR 31,2010
Released By : TOPPENBERG,KEVIN            Date Released : MAR 31,2010
=============================================================================

Packman Mail Message:
=====================

$END TXT
