1 | TMGRPC1C ;TMG/kst-RPC Functions for CPRS for Search functionality ;4/28/10 ; 5/18/10 12:57pm
|
---|
2 | ;;1.0;TMG-LIB;**1**;4/28/10
|
---|
3 | ;
|
---|
4 | ;"TMG RPC FUNCTIONS
|
---|
5 | ;
|
---|
6 | ;"Copyright Kevin Toppenberg MD 4/28/10
|
---|
7 | ;"Released under GNU General Public License (GPL)
|
---|
8 | ;"
|
---|
9 | ;"=======================================================================
|
---|
10 | ;" RPC -- Public Functions.
|
---|
11 | ;"=======================================================================
|
---|
12 | ;"SRCH(OUT,FILENUM,STR) --A search function, to support calls by RPC from CPRS
|
---|
13 | ;"=======================================================================
|
---|
14 | ;"PRIVATE API FUNCTIONS
|
---|
15 | ;"=======================================================================
|
---|
16 | ;
|
---|
17 | ;"=======================================================================
|
---|
18 | ;"=======================================================================
|
---|
19 | ;"Dependencies:
|
---|
20 | ;" DIC, TMGDEBUG
|
---|
21 | ;"=======================================================================
|
---|
22 | ;"=======================================================================
|
---|
23 | ;
|
---|
24 | ;
|
---|
25 | ;
|
---|
26 | SRCH(OUT,FILENUM,STR) ;
|
---|
27 | ;"Purpose: A search function, to support calls by RPC from CPRS
|
---|
28 | ;"Input: OUT-- Pass by reference. AN OUT PARAMETER.
|
---|
29 | ;" FILENUM -- The target file number that resulting IENs will be in
|
---|
30 | ;" STR -- This is a logic string for searching. See details below.
|
---|
31 | ;"Results: OUT is filled in. Format:
|
---|
32 | ;" OUT(0)=1 for success, or -1^Error Message
|
---|
33 | ;" OUT(IEN)=""
|
---|
34 | ;" OUT(IEN)=""
|
---|
35 | ;"Search string examples:
|
---|
36 | ;" 8925:.02(.01="SMITH,JOHN")
|
---|
37 | ;" 1234:.01(.03in"32..55") <-- this is a range test
|
---|
38 | ;" 1234:.99((.01="SMITH,JOHN") OR (.01="SMITH,BILL")) AND 4567:.01(.02'="4/2/10") NOT (1["HAPPY")
|
---|
39 | ;" -- File specifier. To specify searching in a file OTHER THAN target filenumber, an optional
|
---|
40 | ;" FILENUM:FLD[:FLD[:FLD...]] may be specified. However, ultimately, this must point back
|
---|
41 | ;" to the target filenumber. E.g. Search in file 8925, but for each entry found, use the IEN
|
---|
42 | ;" specified by FLD (or FLDA:FLDB or FLDA:FLDB:FLDC:...)
|
---|
43 | ;" FILENUM:(...)
|
---|
44 | ;" The logic is read from left to right, honoring parentheses. If a filenumber
|
---|
45 | ;" is not specified, then the last specified filenumber is used.
|
---|
46 | ;" E.g. 1234:.01( LogicA ) OR 234:.99( LogicB ) AND ( LogicC )
|
---|
47 | ;" LogicA fields refer to file 1234:.01.
|
---|
48 | ;" LogicB fields refer to file 234:.99
|
---|
49 | ;" LogicA fields refer to file 234:.99 (last specified file number)
|
---|
50 | ;" E.g. 5678:.01( (LogicA1) OR 5432:.88(LogicA2) NOT (LogicA3) ) or (LogicB)
|
---|
51 | ;" LogicA1 fields refer to file 5678:.01
|
---|
52 | ;" LogicA2 fields refer to file 5432:.88
|
---|
53 | ;" LogicA3 fields refer to file 5432:.88 (last specified file number inside parentheses)
|
---|
54 | ;" LogicB fields refer to file 5678 (last specified file number at same parentheses level)
|
---|
55 | ;" -- Each individual search term must be enclosed in parentheses, and may contain sub-terms
|
---|
56 | ;" enclosed in nested parentheses
|
---|
57 | ;" -- Each individual search term is comprised of:
|
---|
58 | ;" FIELD then COMPARATOR then VALUE
|
---|
59 | ;" 1. FIELDS -- can be name or number. This is for currently active file (see below)
|
---|
60 | ;" may also be FIELDA:FIELDB:... when FIELDA is a pointer, then FIELDB
|
---|
61 | ;" is taken from the pointed-to field.
|
---|
62 | ;" 2. COMPARATOR -- can be:
|
---|
63 | ;" "=" -- means exact match
|
---|
64 | ;" "'=", "!=", "<>", -- any of these means 'Does not equal'
|
---|
65 | ;" ">=", "'<" -- means greater-than-or-equal-to (same as not-less-than)
|
---|
66 | ;" "<=", "'>" -- means less-than-or-equal-to (same sa not-greater-than)
|
---|
67 | ;" "in","IN","In" -- means field is in specified rage (see Value below)
|
---|
68 | ;" "[" -- means 'contains'. Interpreted as follows:
|
---|
69 | ;" -- For Word processor (WP) fields, this means that any line in the entire field
|
---|
70 | ;" can contain search term, to be matched positive.
|
---|
71 | ;" -- For free text field, then just text of field is searched.
|
---|
72 | ;" -- For Date fields .... (FINISH THIS...)
|
---|
73 | ;" -- For Sets ... (FINISH THIS...)
|
---|
74 | ;" 3. VALUE -- The search term to search for. Should be in quotes.
|
---|
75 | ;" Note: if comparator is "IN", then syntax is "Value1..Value2"
|
---|
76 | ;" There should be a ".." between the two values.
|
---|
77 | ;" -- Logical combiners of separate search terms allowed are:
|
---|
78 | ;" "OR" or "|" or "||"
|
---|
79 | ;" "AND" or "&" or "&&"
|
---|
80 | ;" "NOT" or "!" or "'" or "ANDNOT"
|
---|
81 | ;" -- Logic short-circuiting is applied. The algorhythm will try to identify the elements
|
---|
82 | ;" of the search that will be the fastest, and then work from that set, to make the overall
|
---|
83 | ;" search better.
|
---|
84 | ;" -- Searching of subfiles is not currently supported. IMPLEMENT LATER....
|
---|
85 | ;"Results: None
|
---|
86 | ;"
|
---|
87 | NEW ARRAY,RESULT
|
---|
88 | SET FILENUM=$GET(FILENUM)
|
---|
89 | SET ARRAY("FILE")=FILENUM
|
---|
90 | SET OUT(0)=1 ;"Default to success
|
---|
91 | SET RESULT=$$PARSESTR(FILENUM,STR,.ARRAY)
|
---|
92 | ZWR ARRAY
|
---|
93 | DO PressToCont^TMGUSRIF
|
---|
94 | quit
|
---|
95 | IF +RESULT=-1 SET OUT(0)=RESULT GOTO SRCHDN
|
---|
96 | SET RESULT=$$OPTIMIZ(.ARRAY)
|
---|
97 | IF +RESULT=-1 SET OUT(0)=RESULT GOTO SRCHDN
|
---|
98 | SET RESULT=$$DOSRCH(.ARRAY,.OUT)
|
---|
99 | IF +RESULT=-1 SET OUT(0)=RESULT GOTO SRCHDN
|
---|
100 | SRCHDN QUIT
|
---|
101 | ;
|
---|
102 | ;
|
---|
103 | PARSESTR(FILENUM,STR,ARRAY,FNUMPTR) ;
|
---|
104 | ;"Purpose: To take user input, validate it, and parse into an formatted array
|
---|
105 | ;"Input: STR: This is the user input string. Format as documented in SRCH() above.
|
---|
106 | ;" ARRAY -- PASS BY REFERENCE. An OUT PARAMETER. Format as follows.
|
---|
107 | ;" ARRAY(1,"FNUMPTR")= FNUM:FLDA[:FLDB[:FLDC...]] FNUM is filenumber that
|
---|
108 | ;" contain search field, and then fields used to point
|
---|
109 | ;" back to *TARGET* FILENUM for entire search
|
---|
110 | ;" ARRAY(1,"FLD")=Fieldnumber to search
|
---|
111 | ;" ARRAY(1,"COMP")=Comparator, will be "=", "'=", "'<", or "'>", "["
|
---|
112 | ;" ARRAY(1,"SRCH")=The value of to be used in search.
|
---|
113 | ;" ARRAY(2,...) The second search term.
|
---|
114 | ;" ARRAY(3,...) The third search term (which is comprised of sub terms)
|
---|
115 | ;" ARRAY(3,1,... The first subterm (same format as higher level)
|
---|
116 | ;" ARRAY(3,2,... The second subterm (same format as higher level)
|
---|
117 | ;" ARRAY(n,...) The N'th search term.
|
---|
118 | ;" ARRAY("SETCOMP",i)= NumA^Combiner^NumB
|
---|
119 | ;" NumA and NumB refer to seach term number (e.g. 1, 2, ... n above)
|
---|
120 | ;" If NumA="#", then it means 'the resulting set of results so far'
|
---|
121 | ;" Combiner will be "AND", "OR", or "NOT"
|
---|
122 | ;" i is the index variable, and logic should be evaluated in numerical order
|
---|
123 | ;" FNUMPTR: Will be used when calling self reiteratively. Leave blank in first call.
|
---|
124 | ;" DON'T pass by reference. This is 'FileNum:FLD[:FLD[:FLD...]] specifier
|
---|
125 | ;"Results: 1 if OK, or -1^Message if error during processing.
|
---|
126 | ;
|
---|
127 | NEW SUBSTRA,SUBSTRB,POS
|
---|
128 | NEW RESULT SET RESULT=1 ;"default to success
|
---|
129 | NEW TERMNUM SET TERMNUM=0
|
---|
130 | SET FNUMPTR=$GET(FNUMPTR,FILENUM)
|
---|
131 | NEW LOGICNUM SET LOGICNUM=0
|
---|
132 | NEW DONE SET DONE=0
|
---|
133 | FOR DO QUIT:(DONE=1)!(+RESULT=-1)
|
---|
134 | . NEW TEMPARRAY
|
---|
135 | . SET TERMNUM=TERMNUM+1
|
---|
136 | . ;"--- Get file number, if any
|
---|
137 | . SET STR=$$TRIM^XLFSTR(STR)
|
---|
138 | . IF +$PIECE(STR,"(",1)>0 DO QUIT:(+RESULT=-1)
|
---|
139 | . . SET FNUMPTR=$PIECE(STR,"(",1) ;"Convert 1234:.01:.02:(...) --> 1234:.01:.02:
|
---|
140 | . . IF $EXTRACT(FNUMPTR,$LENGTH(FNUMPTR))=":" SET FNUMPTR=$EXTRACT(FNUMPTR,1,$LENGTH(FNUMPTR)-1)
|
---|
141 | . . IF $$FNPTR(FNUMPTR)'=FILENUM DO QUIT
|
---|
142 | . . . SET RESULT="-1^'"_FNUMPTR_"' points to file #"_$$FNPTR(FNUMPTR)_", not file #"_FILENUM_" as expected"
|
---|
143 | . ;"Split STR --> SUBSTRA + SUBSTRB
|
---|
144 | . SET SUBSTRA=$$MATCHXTR^TMGSTUTL(STR,"(")
|
---|
145 | . IF SUBSTRA="" SET DONE=1 QUIT
|
---|
146 | . SET POS=$FIND(STR,SUBSTRA) ;"Return pos of following character
|
---|
147 | . SET SUBSTRB=$EXTRACT(STR,POS+1,9999) ;"Should be " [LOGICTERM] [SearchTerm]..."
|
---|
148 | . ;"Process SUBSTRA, either directly if single term, or recursively if compound term.
|
---|
149 | . IF $$HNQTSUB^TMGSTUTL(SUBSTRA,"(") DO
|
---|
150 | . . SET RESULT=$$PARSESTR(FILENUM,SUBSTRA,.TEMPARRAY,FNUMPTR)
|
---|
151 | . ELSE DO
|
---|
152 | . . SET RESULT=$$PARSE1(FILENUM,SUBSTRA,FNUMPTR,.TEMPARRAY)
|
---|
153 | . IF +RESULT=-1 QUIT
|
---|
154 | . MERGE ARRAY(TERMNUM)=TEMPARRAY
|
---|
155 | . ;"Now get Logic term connecting this to next term (if any)
|
---|
156 | . SET SUBSTRB=$$TRIM^XLFSTR(SUBSTRB) ;"Remove opening (and closing) spaces
|
---|
157 | . NEW LOGICTERM SET LOGICTERM=$$UP^XLFSTR($PIECE(SUBSTRB," ",1))
|
---|
158 | . IF LOGICTERM="" SET DONE=1 QUIT
|
---|
159 | . IF (LOGICTERM="|")!(LOGICTERM="||") SET LOGICTERM="OR"
|
---|
160 | . ELSE IF (LOGICTERM="&")!(LOGICTERM="&&") SET LOGICTERM="AND"
|
---|
161 | . ELSE IF (LOGICTERM="!")!(LOGICTERM="'")!(LOGICTERM="ANDNOT") SET LOGICTERM="NOT"
|
---|
162 | . IF (LOGICTERM="AND")!(LOGICTERM="OR")!(LOGICTERM="NOT") DO
|
---|
163 | . . NEW CURSET SET CURSET=$SELECT(TERMNUM=1:"1",1:"#")
|
---|
164 | . . SET LOGICNUM=LOGICNUM+1
|
---|
165 | . . SET ARRAY("SETCOMP",LOGICNUM)=CURSET_"^"_LOGICTERM_"^"_(TERMNUM+1) ;"will check later that TERMNUM+1 is supplied
|
---|
166 | . ELSE DO QUIT
|
---|
167 | . . SET RESULT="-1^Bad logic term. Expect 'AND', 'OR', or 'NOT'. Found: ["_LOGICTERM_"]"
|
---|
168 | . SET STR=$PIECE(SUBSTRB," ",2,999)
|
---|
169 | QUIT RESULT
|
---|
170 | ;
|
---|
171 | ;
|
---|
172 | FNPTR(FNUMPTR) ;
|
---|
173 | ;"Puprose: To resolve a FNUMPTR, finding ultimate target file
|
---|
174 | ;"Input: FNUMPTR: Format: FNUM:FLDA[:FLDB[:FLDC...]] FNUM is filenumber that
|
---|
175 | ;" contain search field, and then fields used to point to *TARGET* FILENUM
|
---|
176 | ;"Results: -1^Error message if error, otherwise returns pointed to file
|
---|
177 | NEW RESULT,FILE,FLD,I,DONE
|
---|
178 | SET FILE=+$GET(FNUMPTR)
|
---|
179 | SET RESULT=0
|
---|
180 | SET DONE=0
|
---|
181 | FOR I=2:1:999 DO QUIT:(+RESULT=-1)!(DONE=1)
|
---|
182 | . SET FLD=$PIECE(FNUMPTR,":",I)
|
---|
183 | . IF FLD="" SET DONE=1 QUIT
|
---|
184 | . IF $DATA(^DD(FILE,FLD,0))=0 DO QUIT
|
---|
185 | . . SET RESULT="-1^Field ["_FLD_"] was not found in file ["_FILE_"]"
|
---|
186 | . NEW FLDTYPE SET FLDTYPE=$PIECE(^DD(+FILE,+FLD,0),"^",2)
|
---|
187 | . IF FLDTYPE'["P" DO QUIT
|
---|
188 | . . SET RESULT="-1^Field ["_FLD_"] does not point to another file."
|
---|
189 | . SET FILE=+$PIECE(FLDTYPE,"P",2)
|
---|
190 | SET RESULT=FILE
|
---|
191 | QUIT RESULT
|
---|
192 | ;
|
---|
193 | PARSE1(FILENUM,STR,FNUMPTR,ARRAY) ;
|
---|
194 | ;"Purpose: Parse a simple search term (e.g. .01="SMITH,JOHN"). Also validate that field exists in file.
|
---|
195 | ;"Input: FILENUM -- The TARGET filenumber that the entire search is referencing.
|
---|
196 | ;" STR: This is part of the user input string to parse
|
---|
197 | ;" FNUMPTR: FNUM:FLDA[:FLDB[:FLDC...]] FNUM is filenumber that contain search field, and then
|
---|
198 | ;" fields used to point back to *TARGET* FILENUM for entire search
|
---|
199 | ;" ARRAY -- PASS BY REFERENCE. An OUT PARAMETER. Format as follows.
|
---|
200 | ;" ARRAY("FNUMPTR")=Filenumber that contains field)
|
---|
201 | ;" ARRAY("FLD")=Fieldnumber to search
|
---|
202 | ;" ARRAY("COMP")=Comparator, will be "=", "'=", "'<", or "'>", "[","IN"
|
---|
203 | ;" ARRAY("SRCH")=The value of to be used in search.
|
---|
204 | ;"NOTE: If field specifies a DATE, then the search value will be converted to FileMan format
|
---|
205 | ;"Results: 1 if OK, or -1^Message if error during processing.
|
---|
206 | ;"
|
---|
207 | NEW RESULT SET RESULT=1 ;"default to success
|
---|
208 | NEW SAV SET SAV=STR
|
---|
209 | SET STR=$$TRIM^XLFSTR($GET(STR))
|
---|
210 | SET ARRAY("FNUMPTR")=FNUMPTR
|
---|
211 | NEW FLD SET FLD=+STR
|
---|
212 | IF $DATA(^DD(+FNUMPTR,FLD,0))=0 DO GOTO PS1DN
|
---|
213 | . SET RESULT="-1^Field ["_FLD_"] was not found in file ["_+FNUMPTR_"]"
|
---|
214 | FOR DO QUIT:(+STR=0)
|
---|
215 | . SET STR=$EXTRACT(STR,$LENGTH(+STR)+1,9999) ;"Strip off field number
|
---|
216 | . IF $EXTRACT(STR,1)=":" DO ;"Handle '.02:.99:.01' format, as Fileman does.
|
---|
217 | . . SET STR=$$TrimL^TMGSTUTL(STR,":")
|
---|
218 | . . IF +STR>0 SET FLD=FLD_":"_+STR
|
---|
219 | SET ARRAY("FLD")=FLD
|
---|
220 | NEW FLDTYPE SET FLDTYPE=$PIECE(^DD(+FNUMPTR,+FLD,0),"^",2)
|
---|
221 | IF (FLD[":"),(FLDTYPE'["P") DO GOTO PS1DN
|
---|
222 | . SET RESULT="-1^Found fields ["_FLD_"], however field "_+FLD_" is not a pointer in file "_FILENUM
|
---|
223 | IF FLDTYPE["M" DO GOTO PS1DN
|
---|
224 | . SET RESULT="-1^Searches in fields that are MULTIPLES not supported"
|
---|
225 | NEW COMP SET COMP=$PIECE(STR,"""",1)
|
---|
226 | SET COMP=$$UP^XLFSTR($$TRIM^XLFSTR(COMP))
|
---|
227 | IF (COMP="!=")!(COMP="<>") SET COMP="'="
|
---|
228 | ELSE IF (COMP=">=") SET COMP="'<"
|
---|
229 | ELSE IF (COMP="<=") SET COMP="'>"
|
---|
230 | NEW NOT SET NOT=$EXTRACT(COMP,1) IF NOT'="'" SET NOT=""
|
---|
231 | IF (COMP="=")!(COMP="[")!(COMP="IN")!(COMP="<")!(COMP=">") DO
|
---|
232 | . SET ARRAY("COMP")=NOT_COMP
|
---|
233 | ELSE DO GOTO PS1DN
|
---|
234 | . SET RESULT="-1^Comparator ["_COMP_"] is not valid"
|
---|
235 | NEW SRCH SET SRCH=$PIECE(STR,"""",2,999) ;"Will strip off opening quotes
|
---|
236 | IF $EXTRACT(SRCH,$LENGTH(SRCH))="""" SET SRCH=$EXTRACT(SRCH,1,$LENGTH(SRCH)-1) ;"Strip closing quote
|
---|
237 | IF FLDTYPE["D" DO ;"Convert search value into a FM date (internal format)
|
---|
238 | . NEW ADATE SET ADATE=SRCH
|
---|
239 | . NEW TEMPRSLT SET TEMPRSLT=""
|
---|
240 | . FOR QUIT:(ADATE="")!(+RESULT=-1) DO
|
---|
241 | . . NEW X,Y,%DT
|
---|
242 | . . SET %DT="T"
|
---|
243 | . . SET X=$PIECE(ADATE,"..",1)
|
---|
244 | . . SET ADATE=$PIECE(ADATE,"..",2)
|
---|
245 | . . DO ^%DT
|
---|
246 | . . IF Y=-1 DO QUIT
|
---|
247 | . . . SET RESULT="-1^Invalid date: ["_X_"]"
|
---|
248 | . . . SET SRCH="",ADATE=""
|
---|
249 | . . IF TEMPRSLT'="" SET TEMPRSLT=TEMPRSLT_".."
|
---|
250 | . . SET TEMPRSLT=TEMPRSLT_Y
|
---|
251 | . SET SRCH=TEMPRSLT
|
---|
252 | ELSE IF FLDTYPE["S" DO ;"Convert FM SET type into internal format
|
---|
253 | . NEW OUT,TMGMSG
|
---|
254 | . DO VAL^DIE(+FNUMPTR,"+1,",FLD,"E",SRCH,.OUT,,"TMGMSG")
|
---|
255 | . SET SRCH=$GET(OUT)
|
---|
256 | IF SRCH'="" SET ARRAY("SRCH")=SRCH
|
---|
257 | ELSE DO GOTO PS1DN
|
---|
258 | . SET RESULT="-1^Search value is invalid"
|
---|
259 | ;
|
---|
260 | PS1DN IF +RESULT=-1 SET RESULT=RESULT_", found in ["_SAV_"]"
|
---|
261 | QUIT RESULT
|
---|
262 | ;
|
---|
263 | SRCHSUB(RESULT,TERMS) ;
|
---|
264 | ;"Purpose: A search function, to support calls by RPC from CPRS
|
---|
265 | ;"Input: RESULT-- Pass by reference. AN OUT PARAMETER.
|
---|
266 | ;" TERMS -- Pass by reference. Contains search terms. Format
|
---|
267 | ;" TERMS("FILE")=FileNumber
|
---|
268 | ;" TERMS(Field)=Comparator^SearchValue
|
---|
269 | ;" TERMS(Field)=Comparator^SearchValue
|
---|
270 | ;" -- Allowed Comparators: "=","[","<",
|
---|
271 | ;"Results: RESULT is filled in. Format:
|
---|
272 | ;" RESULT(0)=1 for success, or -1^Error Message
|
---|
273 | ;" RESULT(IEN)=""
|
---|
274 | ;" RESULT(IEN)=""
|
---|
275 | ;"NOTE: When multiple fields are specfied, then search results will combine terms
|
---|
276 | ;" in an AND fashion. I.e. results only returned that match ALL specified terms.
|
---|
277 | ;
|
---|
278 | QUIT
|
---|