Need to call namespace or tclproc globally – Cloverleaf 6.1.

Homepage Clovertech Forums Read Only Archives Cloverleaf Cloverleaf Need to call namespace or tclproc globally – Cloverleaf 6.1.

  • Creator
    Topic
  • #55457
    Bill Pitts
    Participant

    Hi

    I have a namespace that checks an internal 6-digit provider number against an npi number lookup table.  The lookup table is valued nightly by a sql query.  The namespace is contained in multiple tclprocs in multiple sites.

    Is there a way to set this namespace up globally so that it can be called/referenced from a central location?

    We just set up a master site on our test server.

    Also not really that familiar with the concept of packages and/or how to set those up correctly.

    We’re on Cloverleaf 6.1.2  , Unix AIX 7.1.0.0

    ###              NAMESPACE CODE BELOW             ###

    namespace eval NPIDoctorNumberLogic {

    #NPIdoctor_number_logic  – pull the doctor data out of passed in doctor field

    #

    # Called:

    #        NPIdoctor_number_logic {DoctorCheckList doctor StripMDflag}#            DoctorCheckList = keyed list of user fields

    #      doctor =  data from HL7 doctor field – format “id^ln, fn” or “id^ln^fn”

    #

    # Notes:

    #   Can be used for any doctor number on the HL7 transaction

    #   Queries doctor against sms_npi.tbl , pulls back npi if found, defaults ‘9999999999’ if not found

    #               sms_npi.tbl updated nightly from values in Tufts Provider Directory

    #

    # Returns:

    #            doctor info (modified or original, depending on logic checks)

    #              

      ###############################################

      #    For checking doctor id against sms_npi.tbl and returning corresponding npi value

       proc NPIdoctor_number_logic {doctor} {

                 

                             # break apart the doctor field that Softlab sends

                              catch [set doctorList [split $doctor ~]]

                             # Run through doctorList to parse info for multiple iterations

                              foreach doctorItem $doctorList {

                                  catch [set doctorList [split $doctorItem ^]]

                             

                                 catch [set doctor_ID [lindex $doctorList 0]]

                                 catch [set doctor_IDlen [string length $doctor_ID]]

                             

                   

                          if {$doctor_IDlen > 5} {

                               catch [set npi [tbllookup sms_npi.tbl $doctor_ID]]

                               catch [set doctorList [lreplace $doctorList 0 0 $npi]]

                               catch [set doctorList [lreplace $doctorList 5 5 $doctor_ID]]

                               catch [set doctorList [join $doctorList ^]]

                               catch [set doctor $doctorList]

                               

                                lappend DoctorCheckList $doctor

                                catch [set DoctorCheckList [join $DoctorCheckList ~]]

                          }

                   }

               

                               

               

              # Return data list

              return $DoctorCheckList

             

             }

      }

Viewing 11 reply threads
  • Author
    Replies
    • #85397
      Charlie Bursell
      Participant

      The easy answer is no.

      In order to use the namespace it must be inside the same interpreter.

      There is an interpreter for IB, Xlate and OB.  So if you have several procs in an IB thread they could all share the same namespace.

    • #85398
      Jeff Dinsmore
      Participant

      We just drop these into the tclprocs directory in our master site.

      They are then available globally and can be called from any Tcl proc in any site.

      I haven’t tried a global table, but I would assume if the table is in the master site as well that it would be available from anywhere the proc is called.

      Jeff Dinsmore
      Chesapeake Regional Healthcare

    • #85399
      Bill Pitts
      Participant

      Hi Jeff

      Are there any ‘gotchas’ or specifics that need to be setup in the tcl/namespace in the master site?

      Also- any specific syntax for calling from the individual sites?

      Examples would be helpful if you have any.

      Also – we just set some tables up in our master site.  They can be called/reference from the individual sites.  We’ve tested that out successfully.  We’re on Clover 6.1.2

      Thanks

      Bill

    • #85400
      Jeff Dinsmore
      Participant

      Just like any other Tcl proc, place it in your master site tclprocs directory, then run mktclindex.

      It will then be available in any tcl proc in any site/process.

      Jeff Dinsmore
      Chesapeake Regional Healthcare

    • #85401
      Charlie Bursell
      Participant

      Jeff:

      Not entirely true.  The Tcl procs will be available to all sites and can be called from any of them.  The namespaces, if any, within the procs will not be available unless the proc is loaded (called),  The namespace must reside within the interpreter to be called.  I think Bill was asking about making namespaces available globally, not procs.

      Bill:

      If you really want global namespaces, put them inside a package then in any proc that wants to use them simply do a package require command prior to using the namespace.

    • #85402
      Jeff Dinsmore
      Participant

      Charlie:

      I’m assuming you mis-typed your third sentence.  Namespaces are not contained in procs, rather procs are contained in namespaces.

      And, while I suppose it’s possible, I guess I don’t see much value in namespaces without procs. The whole point of namespaces is to build logical containers to hold a related group of procedures and associated data.

      A procedure that lives in a namespace can’t exist without the namespace.  

      You can substantiate that statement by pasting this code into an Tcl interpreter:

      Code:

      proc bob::fred { } {
       puts “this is bob::fred”
      }

      It will produce the following error:

      Quote:

      Error: can’t create procedure “bob::fred”: unknown namespace

      So, the namespace must exist before the procedure can be created inside of it.

      As long as the interpreter knows where to find a procedure – as with procedures indexed by the mktclindex command – it can be invoked directly.  It is loaded automatically when called.  When a procedure in a namespace is called, the namespace is automatically loaded as well – along with any other procedures contained in the same file.

      Example:

      Quote:

      hcitcl>info procs crmcSqliteUtils::*

      hcitcl>crmcSqliteUtils::dirPath

      Error: wrong # args: should be “crmcSqliteUtils::dirPath dbName dirType”

      hcitcl>info procs crmcSqliteUtils::*

      ::crmcSqliteUtils::closeDb ::crmcSqliteUtils::openDb ::crmcSqliteUtils::dirPath ::crmcSqliteUtils::randomWait ::crmcSqliteUtils::subSingleQuote ::crmcSqliteUtils::initDirs ::crmcSqliteUtils::log ::crmcSqliteUtils::dbFileLastChangeSec ::crmcSqliteUtils::masterDir

      The package command is just another organization tool that gives you code revision capability.  All it does when you execute “package require” is to check the version if it’s specified, then loads the code contained in that package into your interpreter.

      And, don’t get me wrong, Tcl packages are a great thing… they’re just not required to use namespaces.

      Jeff Dinsmore
      Chesapeake Regional Healthcare

    • #85403
      Charlie Bursell
      Participant

      I never said, or meant to say that namespaces live in procs.  I said that in order for the namespace to be used, it must reside within the interpreter.  It can get there by being part of a sourced file or loaded via the package command

      There is always one namespace in the interpreter and that is the global namespace. That is why, rather than someting like:  “global HciSiteDir” and then later, “echo $HciSiteDir” you can do simply “echo $::HciSiteDir”.  I always use the latter paradigm.

      I think the original question by the OP was about having namespaces that he could use globally anywhere in the site.  I mentioned packages since using them would allow global access with the package require command.

      BTW, a namespace is not required to have procs to be usefull.  On many occcasions I have used namespaces as a repository for variables and constants.  The advantage is in itialization.  If a namespace exists within a sourced file it is executed first, even before the start mode in the engine.

      You made a lot of valid points and if my dyslectic fingers mis-spoke I apologize.

    • #85404
      Jeff Dinsmore
      Participant

      Bill’s original post referenced namespace a bit loosely, I think.

      If you look at what his included code is doing, it’s a namespace (NPIDoctorNumberLogic) that contains a procedure (NPIdoctor_number_logic ) that validates a provider ID against a Cloverelaf table.

      Upon closer inspection, I see it doesn’t set any namspace variables at all.  The variables are all local to the procedure which returns a list of provider info.

      What I’m reading is that Bill has multiple copies of this namespace/procedure (in the tclprocs directory of multiple sites) and that he’d rather have a single copy that’s available across all sites.

      He can accomplish this a couple of different ways.

      The simplest is to just put a single copy of it in the tclprocs directory of his master site, run mktclindex there, remove the copies from the non-master sites’ tclprocs and run mktclindex in each of them to remove the reference to the procedure in their indexes.  Any processes that reference the procedure would then need to be bounced to pick up the procedure from the new master site location.

      We store all of our Tcl code in our master site.

      Alternatvely, he could put it into an external location that’s in the Tcl interpreter’s search path – perhaps TCL_LIBRARY – but would want to be sure it’s in a location that won’t be overwritten by an upgrade.  From my viewpoint, this would be a good application for a package.

      Charlie – Out of curiosity, where do you generally store “packaged” Tcl code?

      Jeff Dinsmore
      Chesapeake Regional Healthcare

    • #85405
      Bill Pitts
      Participant

      Hi

      Trying to set this up with the tcl/namespace in a pkg

      Created tcl file with namespace code in file

      entered package provide  and namespace eval statements to beginning of script

      Created a packages directory in our master_t site under the tclprocs directory

      (/hci/cis6.1/integrator/master_t/tclprocs/packages)

      When I go to run the mkpkgindex command I get an error that “No .pkg files found”

      I copied and renamed the DoctorNPIlookup.tcl to DoctorNPIlookup.pkg and reran the mkpkgindex file and got same error.

      Tried with fullpath after mkpkgindex as well; same error.

      Missing something — any thoughts?

      FYI:  DoctorNPIlookup.tcl code below

      ######################################################################

      # Name:        DoctorNPIlookup.tcl

      # Purpose:    Checks DoctorID, usually 6-digit SMS Dr ID, against sms_npi.tbl  

      #             Set as package with namespace for use globally in multiple sites

      #        

      #  NOTE:  

      #  

      # Ver 1.0.0    08/24/2017 – Bill Pitts

      #    

      # UPoC type:    tps

      # Args:     tps keyedlist containing the following keys:

      #           MODE    run mode (“start”, “run” or “time”)

      #           MSGID   message handle

      #           ARGS    user-supplied arguments:

      #                  

      #

      # Returns: tps disposition list:

      #          

      #

      #


      #                      MODIFICATIONS

      #

      #

      #


      package provide DoctorNPIlookup

             

      ##################################################################################################################

      ###                                                                                                            ###

      ###                                      NAMESPACE CODE BELOW                                                  ###

      ###                                                                                                            ###

      ##################################################################################################################

      namespace eval NPIDoctorNumberLogic {

               

        #########################################################################################################

        # NPIdoctor_number_logic  – pull the doctor data out of passed in doctor field

        #

        # Called:

        #        NPIdoctor_number_logic {DoctorCheckList doctor StripMDflag}

        #            DoctorCheckList = keyed list of user fields

        #                           doctor =  data from HL7 doctor field – format “id^ln, fn” or “id^ln^fn”

        #                          

        #                          

        #

        # Notes:

        #               Can be used for any doctor number on the HL7 transaction

        #               Queries doctor against sms_npi.tbl , pulls back npi if found, defaults ‘9999999999’ if not found

        #               sms_npi.tbl updated nightly from values in Tufts Provider Directory

        #

        # Returns:

        #            doctor info (modified or original, depending on logic checks)

        #              

        ##############################################################################################################

        #    For checking doctor id against sms_npi.tbl and returning corresponding npi value

         proc NPIdoctor_number_logic {doctor} {

                     

                               # break apart the doctor field that Softlab sends

                                catch [set doctorList [split $doctor ~]]

                               # Run through doctorList to parse info for multiple iterations

                                foreach doctorItem $doctorList {

                                    catch [set doctorList [split $doctorItem ^]]

                                    catch [set doctorListLen [llength $doctorList]]

                               

                                   catch [set doctor_ID [lindex $doctorList 0]]

                                   catch [set doctor_IDlen [string length $doctor_ID]]

                               

                     

                            if {$doctor_IDlen > 5} {

                                 catch [set npi [tbllookup sms_npi.tbl $doctor_ID]]

                                 catch [set doctorList [lreplace $doctorList 0 0 $npi]]

                                 if {$doctorListLen > 3} {

                                 catch [set doctorList [lreplace $doctorList 5 5 $doctor_ID]]

                                 }

                                 

                                 catch [set doctorList [join $doctorList ^]]

                                 catch [set doctor $doctorList]

                                 

                                  lappend DoctorCheckList $doctor

                                  catch [set DoctorCheckList [join $DoctorCheckList ~]]

                            }

                     }

                 

                                 

                 

                # Return data list

                return $DoctorCheckList

               

               }

        }

    • #85406
      Bill Pitts
      Participant

      Looks like I got the pkIndex set correctly.

      Ran the following:

      From /hci/cis6.1/integrator/master_t/tclprocs/packages

      hcitcl>pkg_mkIndex

    • #85407
      Charlie Bursell
      Participant

      When you run mkpkgindex it is the same as mktclindex except the default files it looks for is *.pkg instead of *.tcl.   The script was copied from mktclindex.   You can call either script with an argument which is a path to package or Tcl file.  Otherwise it looks in current directory.

      You can name the package anything you like.  When I wrote this script I wrote it to assume .pkg so you could tell what it was by looking at the name.

      Once made, package require will find it as long as it in the Tcl path (auto_path) or one directory level deeper.

      It allows for cool things like your own personal directory for packages.  Simply append to auto_path prior to the package require.  For example suppose I put the package under /home/charlie/mylib.

      If I lappend to the global variable auto_path (It is a list)  like:

                  lappend ::auto_path /home/charlie

      the package would be found with the package require command

    • #85408
      Bill Pitts
      Participant

      Hi

      Just a follow up;  this is working fine

      Steps:

      1)  created location for packages off master site

          /hci/cis6.1/integrator/master_t/tclprocs/packages

      2)  Wrote script for namespace code; script to be used as the package

          Code referenced in 8/24/17 12:07 post  (DoctorNPIlookup.tcl)

      3)   ran hcitcl>pkg_MkIndex command to create pkIndex file

           Referenced in 8/24 12:30 post

      4)  put “package require” command in tclprocs that call the package

          e.g.  ” package require DoctorNPIlookup “

      5)  Recycled process, etc as appropriate

      ************************************************

      Thanks to Jeff Dinsmore and Charlie Bursell for their input and guidance on this!

Viewing 11 reply threads
  • The forum ‘Cloverleaf’ is closed to new topics and replies.

Forum Statistics

Registered Users
5,115
Forums
28
Topics
9,290
Replies
34,422
Topic Tags
286
Empty Topic Tags
10