About the Validate Query TriggerThis section provides background details about the validate query trigger. The trigger is fired from the Find or Find Like windows in both the desktop and Web versions of ENOVIA Matrix Navigator, where wide-open query definitions are allowed, as well as on specific queries in MQL or ENOVIA Studio Customization Toolkit programs. The Validate Query trigger has two main purposes:
In addition, you can create customized error and notice messages. For example, for a blocked query, the program could display a message indicating the reason for blocking it, such as more information is required. The validate query trigger is different from other triggers. It executes a single program that works as a combined check and override trigger, and is designed as a way to modify the current query (via the RPE). Enabling the Validate Query TriggerThe validate query trigger is enabled in the desktop application by default, as long as a program object named ValidateQuery exists in the database. Because it makes an additional call to the database, performance can be affected. To enable Query triggers for use in the Web version of ENOVIA Matrix Navigator, add the following to the HTML page that starts it: document.writeln("<param name='QueryTrigger' value='True'>"); If you will use custom applets, your pages may use the straight HTML syntax: <PARAM name="QueryTrigger" value="True"> In MQL, the evaluate query and temp query commands can include the querytrigger clause, which will cause the ValidateQuery program execute (if it exists) For example: <mql> temp query bus * * * querytrigger vault v1; <mql> evaluate query q1 querytrigger; Even with triggers turned off, when querytrigger is included in a query command, the ValidateQuery program executes. Program objects that perform queries are not affected by default in either the desktop or Web version of ENOVIA Matrix Navigator. If required, the querytrigger flag must be included in the program code. Using the Validate Query Trigger in Studio Customization Toolkit ProgramENOVIA Studio Customization Toolkit methods are available to set and get the query trigger flag. By default the flag is set to false. The methods are: public setQueryTrigger(boolean queryTrigger) public boolean getQueryTrigger () The following example performs a temporary query and the validate query trigger fires as long as the program object exists: Query myQuery = new Query(""); myQuery.setType("*"); myQuery.setName("*"); myQuery.setRevision("*"); myQuery.setVault("*"); myQuery.setQueryTrigger(true); myQuery.evaluate(getContext())); ... Writing the ValidateQuery ProgramThe validate query trigger fires before the query is evaluated. The program should check the query patterns specified as described in Query Event Macros. If the ValidateQuery program is a JPO, no macros are available as input arguments. As a workaround, the ValidateQuery program should be a Tcl program that calls the JPO to do the actual work. When changing query patterns, use global variables. For example, to change the vault pattern in the background if only a wildcard is provided, you could use: tcl; eval { set sVault [mql get env VAULT_PATTERN ] if { $sVault=="*" } { set sVault "vault1,vault2,vault3" } mql set env global VAULT_PATTERN exit 0 } As is the case with other event triggers, the exit code determines if the event is blocked or overridden. If the exit code is a zero, the query is performed; the global query pattern RPE variables are read and used by the query, which allows the program code to change them before the query is evaluated. (Remember, the validate query trigger is really a combination of a check and an override trigger.) If the exit code is a non-zero value, a soft block occurs. In this case the query as entered is not executed; the query event is overridden and the transaction is committed, closing the Find or Find Like window. It is up to the trigger program code that overrides the query to generate a message to inform the user that the query did not get executed. While overriding the query code with other events is possible, the main purpose of a query trigger is to block unqualified queries and modify the query patterns via RPE variables. If overriding the query code, query performance, Tcl limitations (such as the fact that Tcl is single threaded) and recursive queries must be considered. The query is a fundamental part of ENOVIA Live Collaboration and overwriting the code must be done carefully. To return business objects to the current window in the desktop or Web version of ENOVIA Matrix Navigator, the MQL commands, appl icons and appl details can be used to populate the window with business objects. Validate Query Use CaseThe validate query trigger can ensure that user-defined queries satisfy some pre-defined requirements. For example, the program below is one solution for ensuring that:
The ValidateQuery program to satisfy above: tcl; eval { eval [ mql print program utList.tcl select code dump ] ############################################################### proc tclListToMxList {tclList} { set mxList "" foreach i $tclList { append mxList $i append mxList "," } set length [expr [string length $mxList] - 2 ] set mxList [ string range $mxList 0 $length ] return $mxList } ############################################################### proc mxListToTclList {mxList} { set tclList [ split $mxList "," ] return $tclList } ############################################################### proc MatchingVaults {sPattern tclVaultList} { set lVaultsToBeSearched "" set firstIndex [ lsearch $tclVaultList $sPattern ] while { $firstIndex != -1 } { lappend lVaultsToBeSearched [ lindex $tclVaultList $firstIndex] set index [expr $firstIndex + 1 ] set tclVaultList [lrange $tclVaultList $index end] set firstIndex [ lsearch $tclVaultList $sPattern ] } return $lVaultsToBeSearched } ############################################################### proc onlyWildcardsInString {sString} { set wildcard "*" set bReturn FALSE set iFirstIndex [string first $wildcard $sString] if {$iFirstIndex != -1 } { # To discover many stars (ex ***) set bReturn TRUE for {set i 0} {$i < [string length $sString]} {incr i} { if { [string index $sString $i] != $wildcard } { set bReturn FALSE break } } } return $bReturn } ############################################################### # # Variable definition # ############################################################### # Default values set iExit 0 set sErrorMessage "" # Get all vaults from Matrix set sAllVaultsList [ mql list vault ] set lAllVaultsList [ split $sAllVaultsList \n ] # Defined adaplets set lAdapletVaults {a1 a2} set lRemoteVaults {r1 r2} # Local vaults set lLocalVaults [ utListSubtract $lAllVaultsList [ concat $lAdapletVaults $lRemoteVaults ] ] # Get query env set sVault [mql get env VAULT_PATTERN ] set sType [mql get env TYPE_PATTERN ] set sName [mql get env NAME_PATTERN ] set sRevision [mql get env REVISION_PATTERN ] set sOwner [mql get env OWNER_PATTERN ] set lVaultsToBeSearched {} ############################################################### # # Find out which vault(s)are going to be queried # ############################################################### # If vault pattern is a wildcard change the vault to only search local vaults if { [onlyWildcardsInString $sVault] } { set sVault [ tclListToMxList $lLocalVaults ] } mql set env global VAULT_PATTERN $sVault # if vault pattern is a comma separated list of vaults if { [string match *,* $sVault] == 1} { set lVaultList [ split $sVault "," ] foreach v $lVaultList { set lVaultsToBeSearched [ concat $lVaultsToBeSearched [MatchingVaults $v $lAllVaultsList ]] } # not a list of vaults } else { set lVaultsToBeSearched [MatchingVaults $sVault $lAllVaultsList ] } ############################################################### # # Go through the vaults that are going to be searched and # check if all criteria are satisfied # ############################################################### set bGeneralCheck FALSE foreach v $lVaultsToBeSearched { # Foreign vault a1 is not allowed to have * only ? is allowed if { $v == "a1" } { if { ([string first * $sType] != -1) && ([string first * $sName] != -1)} { set iExit 1 append sErrorMessage "Query not allowed. When searching in Vault $v, none of the query patterns type and name is allowed include a wildcard (*). Use one or many question marks (?) for unknown characters instead\n\n" } } elseif {$v == "a2"} { if { [string first * $sName] != -1 } { set iExit 1 append sErrorMessage "Query not allowed. When searching in Vault $v, the query patterns type is allowed include a wildcard (*). Use one or many question marks (?) for unknown characters instead\n\n" } } else { set bGeneralCheck TRUE } } if {$bGeneralCheck} { set iAllowedWildards 3 set iCurrent 0 if { [onlyWildcardsInString $sType] } { incr iCurrent } if { [onlyWildcardsInString $sName]} { incr iCurrent } if { [onlyWildcardsInString $sRevision]} { incr iCurrent } if { [onlyWildcardsInString $sOwner]} { incr iCurrent } if {$iCurrent > $iAllowedWildards } { set iExit 1 append sErrorMessage "Query not allowed. One of the query patterns type, name, revision or owner must be more qualified than a wildcard (*)\n\n" } } # # Pop up error message if needed # if {$iExit == 1} { mql error $sErrorMessage } exit $iExit } |