hqmf2js 1.0.1 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +5 -10
- data/Gemfile.lock +70 -68
- data/app/assets/javascripts/custom_calculations.js.coffee +72 -0
- data/app/assets/javascripts/hqmf_util.js.coffee +97 -46
- data/app/assets/javascripts/logging_utils.js.coffee +0 -11
- data/app/assets/javascripts/specifics.js.coffee +211 -185
- data/app/assets/javascripts/underscore.js +1200 -0
- data/hqmf2js.gemspec +5 -5
- data/lib/generator/characteristic.js.erb +3 -3
- data/lib/generator/converter.rb +5 -5
- data/lib/generator/data_criteria.js.erb +8 -8
- data/lib/generator/js.rb +25 -5
- data/test/fixtures/codes/codes.xml +6 -0
- data/test/fixtures/patients/larry_vanderman.json +11 -1
- data/test/test_helper.rb +2 -3
- data/test/unit/codes_to_json_test.rb +1 -1
- data/test/unit/custom_calculations_test.rb +74 -0
- data/test/unit/hqmf_from_json_javascript_test.rb +9 -9
- data/test/unit/hqmf_javascript_test.rb +36 -14
- data/test/unit/library_function_test.rb +29 -11
- data/test/unit/specifics_test.rb +200 -82
- metadata +13 -9
- data/test/fixtures/patient_api.js +0 -2823
@@ -85,17 +85,6 @@ class @Logger
|
|
85
85
|
return result;
|
86
86
|
);
|
87
87
|
|
88
|
-
# hQuery.CodedEntry.prototype.includesCodeFrom = _.wrap(hQuery.CodedEntry.prototype.includesCodeFrom, (func, codeSet) ->
|
89
|
-
# func = _.bind(func, this, codeSet)
|
90
|
-
# result = func(codeSet)
|
91
|
-
# matchText = "--- noMatch"
|
92
|
-
# matchText = "+++ validMatch" if result
|
93
|
-
#
|
94
|
-
# Logger.info("#{matchText}: -> #{Logger.classNameFor(this)}:#{this.freeTextType()}:#{this.date()}:#{Logger.codedValuesAsString(this.type())}")
|
95
|
-
#
|
96
|
-
# return result;
|
97
|
-
# );
|
98
|
-
|
99
88
|
@getCodes = _.wrap(@getCodes, (func, oid) ->
|
100
89
|
codes = func(oid)
|
101
90
|
Logger.info("accessed codes: #{oid}")
|
@@ -1,49 +1,4 @@
|
|
1
|
-
|
2
|
-
wrap = (func, wrapper) ->
|
3
|
-
() ->
|
4
|
-
args = [func].concat(Array::slice.call(arguments, 0));
|
5
|
-
wrapper.apply(this, args);
|
6
|
-
|
7
|
-
bind = (func, context) ->
|
8
|
-
|
9
|
-
return Function::bind.apply(func, Array::slice.call(arguments, 1)) if (func.bind == Function::bind && Function::bind)
|
10
|
-
throw new TypeError if (typeof func != "function")
|
11
|
-
args = Array::slice.call(arguments, 2)
|
12
|
-
return bound = ->
|
13
|
-
ctor = ->
|
14
|
-
return func.apply(context, args.concat(Array::slice.call(arguments))) if (!(this instanceof bound))
|
15
|
-
ctor.prototype = func.prototype
|
16
|
-
self = new ctor
|
17
|
-
result = func.apply(self, args.concat(Array::slice.call(arguments)))
|
18
|
-
return result if (Object(result) == result)
|
19
|
-
self
|
20
|
-
|
21
|
-
Array::unique = ->
|
22
|
-
output = {}
|
23
|
-
output[@[key]] = @[key] for key in [0...@length]
|
24
|
-
value for key, value of output
|
25
|
-
|
26
|
-
Array::reduce = (accumulator) ->
|
27
|
-
throw new TypeError("Object is null or undefined") if (this==null or this==undefined)
|
28
|
-
i = 0
|
29
|
-
l = this.length >> 0
|
30
|
-
curr=undefined
|
31
|
-
|
32
|
-
throw new TypeError("First argument is not callable") if(typeof accumulator != "function")
|
33
|
-
|
34
|
-
if(arguments.length < 2)
|
35
|
-
throw new TypeError("Array length is 0 and no second argument") if (l == 0)
|
36
|
-
curr = this[0]
|
37
|
-
i = 1
|
38
|
-
else
|
39
|
-
curr = arguments[1]
|
40
|
-
|
41
|
-
while (i < l)
|
42
|
-
curr = accumulator.call(undefined, curr, this[i], i, this) if(`i in this`)
|
43
|
-
++i
|
44
|
-
|
45
|
-
return curr
|
46
|
-
|
1
|
+
@hqmf ||= {}
|
47
2
|
|
48
3
|
###
|
49
4
|
{
|
@@ -52,43 +7,190 @@ Array::reduce = (accumulator) ->
|
|
52
7
|
[1,7,8],
|
53
8
|
]
|
54
9
|
}
|
10
|
+
|
11
|
+
A singleton class the represents the table of all specific occurrences
|
55
12
|
###
|
56
|
-
class
|
13
|
+
class hqmf.SpecificsManagerSingleton
|
14
|
+
constructor: ->
|
15
|
+
@patient = null
|
16
|
+
@any = '*'
|
17
|
+
|
18
|
+
initialize: (patient, hqmfjs, occurrences...)->
|
19
|
+
@occurrences = occurrences
|
20
|
+
@keyLookup = {}
|
21
|
+
@indexLookup = {}
|
22
|
+
@typeLookup = {}
|
23
|
+
@functionLookup = {}
|
24
|
+
@patient = patient
|
25
|
+
@hqmfjs = hqmfjs
|
26
|
+
for occurrenceKey,i in occurrences
|
27
|
+
@keyLookup[i] = occurrenceKey.id
|
28
|
+
@indexLookup[occurrenceKey.id] = i
|
29
|
+
@functionLookup[i] = occurrenceKey.function
|
30
|
+
@typeLookup[occurrenceKey.type] ||= []
|
31
|
+
@typeLookup[occurrenceKey.type].push(i)
|
32
|
+
|
33
|
+
_generateCartisian: (allValues) ->
|
34
|
+
_.reduce(allValues, (as, bs) ->
|
35
|
+
product = []
|
36
|
+
for a in as
|
37
|
+
for b in bs
|
38
|
+
product.push(a.concat(b))
|
39
|
+
product
|
40
|
+
, [[]])
|
57
41
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
42
|
+
identity: ->
|
43
|
+
new hqmf.SpecificOccurrence([new Row(undefined)])
|
44
|
+
|
45
|
+
getColumnIndex: (occurrenceID) ->
|
46
|
+
columnIndex = @indexLookup[occurrenceID]
|
47
|
+
if typeof columnIndex == "undefined"
|
48
|
+
throw "Unknown occurrence identifier: "+occurrenceID
|
49
|
+
columnIndex
|
50
|
+
|
51
|
+
empty: ->
|
52
|
+
new hqmf.SpecificOccurrence([])
|
53
|
+
|
54
|
+
extractEventsForLeftMost: (rows) ->
|
55
|
+
events = []
|
56
|
+
for row in rows
|
57
|
+
events.push(@extractEvent(row.leftMost, row))
|
58
|
+
events
|
64
59
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
60
|
+
extractEvents: (key, rows) ->
|
61
|
+
events = []
|
62
|
+
for row in rows
|
63
|
+
events.push(@extractEvent(key, row))
|
64
|
+
events
|
65
|
+
|
66
|
+
extractEvent: (key, row) ->
|
67
|
+
index = @indexLookup[key]
|
68
|
+
if index?
|
69
|
+
entry = row.values[index]
|
70
|
+
else
|
71
|
+
entry = row.tempValue
|
72
|
+
entry = new hQuery.CodedEntry(entry.json)
|
73
|
+
entry.specificRow = row
|
74
|
+
entry
|
75
|
+
|
76
|
+
intersectSpecifics: (populations...) ->
|
77
|
+
value = @intersectAll(new Boolean(populations[0].isTrue()), populations)
|
78
|
+
value
|
79
|
+
|
80
|
+
# Returns a count of the unique events that match the criteria for the supplied
|
81
|
+
# specific occurrence. Call after validating that population criteria are met. Returns
|
82
|
+
# 1 if occurrenceID is null, for use with patient based measures.
|
83
|
+
countUnique: (occurrenceIDs, intersectedPopulation) ->
|
84
|
+
if occurrenceIDs?
|
85
|
+
columnIndices = (@getColumnIndex(occurrenceID) for occurrenceID in occurrenceIDs)
|
86
|
+
intersectedPopulation.specificContext.uniqueEvents(columnIndices)
|
87
|
+
else if @validate(intersectedPopulation)
|
88
|
+
1
|
89
|
+
else
|
90
|
+
0
|
91
|
+
|
92
|
+
# remove any rows from initial that have the same event id as a row in exclusions for
|
93
|
+
# the specified occurence id
|
94
|
+
exclude: (occurrenceIDs, initial, exclusions) ->
|
95
|
+
if occurrenceIDs?
|
96
|
+
resultContext = initial.specificContext
|
97
|
+
for occurrenceID in occurrenceIDs
|
98
|
+
columnIndex = @getColumnIndex(occurrenceID)
|
99
|
+
resultContext = resultContext.removeMatchingRows(columnIndex, exclusions.specificContext)
|
100
|
+
result = new Boolean(resultContext.hasRows())
|
101
|
+
result.specificContext = resultContext
|
102
|
+
return result
|
103
|
+
else if @validate(exclusions)
|
104
|
+
return @maintainSpecifics(new Boolean(false), initial)
|
105
|
+
else
|
106
|
+
return initial
|
107
|
+
|
108
|
+
# Returns a boolean indication of whether all of the supplied population criteria are
|
109
|
+
# met
|
110
|
+
validate: (intersectedPopulation) ->
|
111
|
+
intersectedPopulation.isTrue() and intersectedPopulation.specificContext.hasRows()
|
112
|
+
|
113
|
+
intersectAll: (boolVal, values, negate=false) ->
|
114
|
+
result = new hqmf.SpecificOccurrence
|
115
|
+
# add identity row
|
116
|
+
result.addIdentityRow()
|
117
|
+
for value in values
|
118
|
+
if value.specificContext?
|
119
|
+
result = result.intersect(value.specificContext)
|
120
|
+
if negate and (!result.hasRows() or result.hasSpecifics())
|
121
|
+
result = result.negate()
|
122
|
+
result = result.compactReusedEvents()
|
123
|
+
# this is a little odd, but it appears when we have a negation with specifics we can
|
124
|
+
# ignore the logical result of the negation. The reason we do this is because we may
|
125
|
+
# get too many negated values. Values that may be culled later via other specific
|
126
|
+
# occurrences. Thus we do not want to return false out of a negation because the
|
127
|
+
# values we are evaluating as false may be dropped.
|
128
|
+
# we need to verify that we actually have some occurrences
|
129
|
+
boolVal = new Boolean(true) if @occurrences.length > 0
|
130
|
+
boolVal.specificContext = result.compactReusedEvents()
|
131
|
+
boolVal
|
132
|
+
|
133
|
+
unionAll: (boolVal, values,negate=false) ->
|
134
|
+
result = new hqmf.SpecificOccurrence
|
135
|
+
for value in values
|
136
|
+
if value.specificContext? and (value.isTrue() or negate)
|
137
|
+
result = result.union(value.specificContext) if value.specificContext?
|
138
|
+
|
139
|
+
if negate and (!result.hasRows() or result.hasSpecifics())
|
140
|
+
result = result.negate()
|
141
|
+
# this is a little odd, but it appears when we have a negation with specifics we can ignore the logical result of the negation. See comment in intersectAll.
|
142
|
+
# we need to verify that we actually have some occurrences
|
143
|
+
boolVal = new Boolean(true) if @occurrences.length > 0
|
144
|
+
boolVal.specificContext = result
|
145
|
+
boolVal
|
79
146
|
|
147
|
+
# copy the specifics parameters from an existing element onto the new value element
|
148
|
+
maintainSpecifics: (newElement, existingElement) ->
|
149
|
+
newElement.specificContext = existingElement.specificContext
|
150
|
+
newElement.specific_occurrence = existingElement.specific_occurrence
|
151
|
+
newElement
|
152
|
+
|
153
|
+
@hqmf.SpecificsManager = new hqmf.SpecificsManagerSingleton
|
154
|
+
|
155
|
+
class hqmf.SpecificOccurrence
|
80
156
|
constructor: (rows=[])->
|
81
157
|
@rows = rows
|
82
158
|
|
83
159
|
addRows: (rows) ->
|
84
160
|
@rows = @rows.concat(rows)
|
85
161
|
|
162
|
+
# Return a new SpecificOccurrence with any matching rows removed
|
163
|
+
removeMatchingRows: (columnIndex, other) ->
|
164
|
+
removeAll = false
|
165
|
+
idsToRemove = []
|
166
|
+
for row in other.rows
|
167
|
+
if row.values[columnIndex].id?
|
168
|
+
idsToRemove.push(row.values[columnIndex].id)
|
169
|
+
else if row.values[columnIndex] == hqmf.SpecificsManager.any
|
170
|
+
removeAll = true
|
171
|
+
rowsToAdd = []
|
172
|
+
if not removeAll
|
173
|
+
for row in @rows
|
174
|
+
if not (row.values[columnIndex].id in idsToRemove)
|
175
|
+
rowsToAdd.push(row)
|
176
|
+
result = new hqmf.SpecificOccurrence(rowsToAdd)
|
177
|
+
result
|
178
|
+
|
86
179
|
removeDuplicateRows: () ->
|
87
|
-
deduped = new
|
180
|
+
deduped = new hqmf.SpecificOccurrence
|
88
181
|
for row in @rows
|
89
182
|
# this could potentially be hasRow to dump even more rows.
|
90
183
|
deduped.addRows([row]) if !deduped.hasExactRow(row)
|
91
184
|
deduped
|
185
|
+
|
186
|
+
# Returns a count of unique events for a supplied column index
|
187
|
+
uniqueEvents: (columnIndices) ->
|
188
|
+
eventIds = []
|
189
|
+
for columnIndex in columnIndices
|
190
|
+
for row in @rows
|
191
|
+
event = row.values[columnIndex]
|
192
|
+
eventIds.push(event.id) if event != hqmf.SpecificsManager.any and not (event.id in eventIds)
|
193
|
+
eventIds.length
|
92
194
|
|
93
195
|
hasExactRow: (other) ->
|
94
196
|
for row in @rows
|
@@ -96,12 +198,12 @@ class Specifics
|
|
96
198
|
return false
|
97
199
|
|
98
200
|
union: (other) ->
|
99
|
-
value = new
|
201
|
+
value = new hqmf.SpecificOccurrence()
|
100
202
|
value.rows = @rows.concat(other.rows)
|
101
203
|
value.removeDuplicateRows()
|
102
204
|
|
103
205
|
intersect: (other) ->
|
104
|
-
value = new
|
206
|
+
value = new hqmf.SpecificOccurrence()
|
105
207
|
for leftRow in @rows
|
106
208
|
for rightRow in other.rows
|
107
209
|
result = leftRow.intersect(rightRow)
|
@@ -120,38 +222,29 @@ class Specifics
|
|
120
222
|
keys = []
|
121
223
|
allValues = []
|
122
224
|
for index in @specificsWithValues()
|
123
|
-
keys.push(
|
124
|
-
allValues.push(
|
125
|
-
cartesian =
|
225
|
+
keys.push(hqmf.SpecificsManager.keyLookup[index])
|
226
|
+
allValues.push(hqmf.SpecificsManager.hqmfjs[hqmf.SpecificsManager.functionLookup[index]](hqmf.SpecificsManager.patient))
|
227
|
+
cartesian = hqmf.SpecificsManager._generateCartisian(allValues)
|
126
228
|
for values in cartesian
|
127
229
|
occurrences = {}
|
128
230
|
for key, i in keys
|
129
231
|
occurrences[key] = values[i]
|
130
232
|
row = new Row(@getLeftMost(), occurrences)
|
131
233
|
negatedRows.push(row) if !@hasRow(row)
|
132
|
-
(new
|
133
|
-
|
134
|
-
|
135
|
-
Array::reduce.call(allValues, (as, bs) ->
|
136
|
-
product = []
|
137
|
-
for a in as
|
138
|
-
for b in bs
|
139
|
-
product.push(a.concat(b))
|
140
|
-
product
|
141
|
-
, [[]])
|
142
|
-
|
143
|
-
# removes any rows that have the save value for OccurrenceA and OccurrenceB
|
234
|
+
(new hqmf.SpecificOccurrence(negatedRows)).compactReusedEvents()
|
235
|
+
|
236
|
+
# removes any rows that have the same value for OccurrenceA and OccurrenceB
|
144
237
|
compactReusedEvents: ->
|
145
238
|
newRows = []
|
146
239
|
for myRow in @rows
|
147
240
|
goodRow = true
|
148
|
-
for type,indexes of
|
241
|
+
for type,indexes of hqmf.SpecificsManager.typeLookup
|
149
242
|
ids = []
|
150
243
|
for index in indexes
|
151
|
-
ids.push(myRow.values[index].id) if myRow.values[index] !=
|
152
|
-
goodRow &&= ids.length ==
|
244
|
+
ids.push(myRow.values[index].id) if myRow.values[index] != hqmf.SpecificsManager.any
|
245
|
+
goodRow &&= ids.length == _.unique(ids).length
|
153
246
|
newRows.push(myRow) if goodRow
|
154
|
-
new
|
247
|
+
new hqmf.SpecificOccurrence(newRows)
|
155
248
|
|
156
249
|
hasRow: (row) ->
|
157
250
|
found = false
|
@@ -167,7 +260,7 @@ class Specifics
|
|
167
260
|
foundSpecificIndexes = []
|
168
261
|
for row in @rows
|
169
262
|
foundSpecificIndexes = foundSpecificIndexes.concat(row.specificsWithValues())
|
170
|
-
|
263
|
+
_.unique(foundSpecificIndexes)
|
171
264
|
|
172
265
|
hasSpecifics: ->
|
173
266
|
anyHaveSpecifics = false
|
@@ -202,9 +295,9 @@ class Specifics
|
|
202
295
|
resultRows = []
|
203
296
|
groupedRows = @group()
|
204
297
|
for groupKey, group of groupedRows
|
205
|
-
if func(
|
298
|
+
if func(hqmf.SpecificsManager.extractEventsForLeftMost(group), range).isTrue()
|
206
299
|
resultRows = resultRows.concat(group)
|
207
|
-
new
|
300
|
+
new hqmf.SpecificOccurrence(resultRows)
|
208
301
|
|
209
302
|
FIRST: ->
|
210
303
|
@applySubset(FIRST)
|
@@ -232,108 +325,41 @@ class Specifics
|
|
232
325
|
resultRows = []
|
233
326
|
groupedRows = @group()
|
234
327
|
for groupKey, group of groupedRows
|
235
|
-
entries = func(
|
328
|
+
entries = func(hqmf.SpecificsManager.extractEventsForLeftMost(group))
|
236
329
|
if entries.length > 0
|
237
330
|
resultRows.push(entries[0].specificRow)
|
238
|
-
new
|
331
|
+
new hqmf.SpecificOccurrence(resultRows)
|
239
332
|
|
240
333
|
addIdentityRow: ->
|
241
|
-
@addRows(
|
242
|
-
|
243
|
-
@identity: ->
|
244
|
-
new Specifics([new Row(undefined)])
|
245
|
-
|
334
|
+
@addRows(hqmf.SpecificsManager.identity().rows)
|
246
335
|
|
247
|
-
@extractEventsForLeftMost: (rows) ->
|
248
|
-
events = []
|
249
|
-
for row in rows
|
250
|
-
events.push(Specifics.extractEvent(row.leftMost, row))
|
251
|
-
events
|
252
|
-
|
253
|
-
|
254
|
-
@extractEvents: (key, rows) ->
|
255
|
-
events = []
|
256
|
-
for row in rows
|
257
|
-
events.push(Specifics.extractEvent(key, row))
|
258
|
-
events
|
259
|
-
|
260
|
-
@extractEvent: (key, row) ->
|
261
|
-
index = Specifics.INDEX_LOOKUP[key]
|
262
|
-
if index?
|
263
|
-
entry = row.values[index]
|
264
|
-
else
|
265
|
-
entry = row.tempValue
|
266
|
-
entry = new hQuery.CodedEntry(entry.json)
|
267
|
-
entry.specificRow = row
|
268
|
-
entry
|
269
|
-
|
270
|
-
@validate: (populations...) ->
|
271
|
-
value = Specifics.intersectAll(new Boolean(populations[0].isTrue()), populations)
|
272
|
-
value.isTrue() and value.specificContext.hasRows()
|
273
|
-
|
274
|
-
@intersectAll: (boolVal, values, negate=false) ->
|
275
|
-
result = new Specifics()
|
276
|
-
# add identity row
|
277
|
-
result.addIdentityRow()
|
278
|
-
for value in values
|
279
|
-
if value.specificContext?
|
280
|
-
result = result.intersect(value.specificContext)
|
281
|
-
if negate and (!result.hasRows() or result.hasSpecifics())
|
282
|
-
result = result.negate()
|
283
|
-
result = result.compactReusedEvents()
|
284
|
-
# this is a little odd, but it appears when we have a negation with specifics we can ignore the logical result of the negation.
|
285
|
-
# the reason we do this is because we may get too many negated values. Values that may be culled later via other specific occurrences. Thus we do not want to return
|
286
|
-
# false out of a negation because the values we are evaluating as false may be dropped.
|
287
|
-
boolVal = new Boolean(true)
|
288
|
-
boolVal.specificContext = result.compactReusedEvents()
|
289
|
-
boolVal
|
290
336
|
|
291
|
-
@unionAll: (boolVal, values,negate=false) ->
|
292
|
-
result = new Specifics()
|
293
|
-
for value in values
|
294
|
-
if value.specificContext? and (value.isTrue() or negate)
|
295
|
-
result = result.union(value.specificContext) if value.specificContext?
|
296
|
-
|
297
|
-
if negate and result.hasSpecifics()
|
298
|
-
result = result.negate()
|
299
|
-
# this is a little odd, but it appears when we have a negation with specifics we can ignore the logical result of the negation. See comment in intersectAll.
|
300
|
-
boolVal = new Boolean(true)
|
301
|
-
boolVal.specificContext = result
|
302
|
-
boolVal
|
303
|
-
|
304
|
-
# copy the specifics parameters from an existing element onto the new value element
|
305
|
-
@maintainSpecifics: (newElement, existingElement) ->
|
306
|
-
newElement.specificContext = existingElement.specificContext
|
307
|
-
newElement.specific_occurrence = existingElement.specific_occurrence
|
308
|
-
newElement
|
309
|
-
|
310
|
-
@Specifics = Specifics
|
311
337
|
|
312
338
|
class Row
|
313
339
|
# {'OccurrenceAEncounter':1, 'OccurrenceBEncounter'2}
|
314
340
|
constructor: (leftMost, occurrences={}) ->
|
315
341
|
throw "left most key must be a string or undefined was: #{leftMost}" if typeof(leftMost) != 'string' and typeof(leftMost) != 'undefined'
|
316
|
-
@length =
|
342
|
+
@length = hqmf.SpecificsManager.occurrences.length
|
317
343
|
@values = []
|
318
344
|
@leftMost = leftMost
|
319
345
|
@tempValue = occurrences[undefined]
|
320
346
|
for i in [0...@length]
|
321
|
-
key =
|
322
|
-
value = occurrences[key] ||
|
347
|
+
key = hqmf.SpecificsManager.keyLookup[i]
|
348
|
+
value = occurrences[key] || hqmf.SpecificsManager.any
|
323
349
|
@values[i] = value
|
324
350
|
|
325
351
|
hasSpecifics: ->
|
326
|
-
@length =
|
352
|
+
@length = hqmf.SpecificsManager.occurrences.length
|
327
353
|
foundSpecific = false
|
328
354
|
for i in [0...@length]
|
329
|
-
return true if @values[i] !=
|
355
|
+
return true if @values[i] != hqmf.SpecificsManager.any
|
330
356
|
false
|
331
357
|
|
332
358
|
specificsWithValues: ->
|
333
|
-
@length =
|
359
|
+
@length = hqmf.SpecificsManager.occurrences.length
|
334
360
|
foundSpecificIndexes = []
|
335
361
|
for i in [0...@length]
|
336
|
-
foundSpecificIndexes.push(i) if @values[i]? and @values[i] !=
|
362
|
+
foundSpecificIndexes.push(i) if @values[i]? and @values[i] != hqmf.SpecificsManager.any
|
337
363
|
foundSpecificIndexes
|
338
364
|
|
339
365
|
equals: (other) ->
|
@@ -362,9 +388,9 @@ class Row
|
|
362
388
|
groupKey: (key=null) ->
|
363
389
|
keyForGroup = ''
|
364
390
|
for i in [0...@length]
|
365
|
-
value =
|
366
|
-
value = @values[i].id if @values[i] !=
|
367
|
-
if
|
391
|
+
value = hqmf.SpecificsManager.any
|
392
|
+
value = @values[i].id if @values[i] != hqmf.SpecificsManager.any
|
393
|
+
if hqmf.SpecificsManager.keyLookup[i] == key
|
368
394
|
keyForGroup += "X_"
|
369
395
|
else
|
370
396
|
keyForGroup += "#{value}_"
|
@@ -372,8 +398,8 @@ class Row
|
|
372
398
|
|
373
399
|
|
374
400
|
@match: (left, right) ->
|
375
|
-
return right if left ==
|
376
|
-
return left if right ==
|
401
|
+
return right if left == hqmf.SpecificsManager.any
|
402
|
+
return left if right == hqmf.SpecificsManager.any
|
377
403
|
return left if left.id == right.id
|
378
404
|
return undefined
|
379
405
|
|
@@ -381,7 +407,7 @@ class Row
|
|
381
407
|
return true if !left? and !right?
|
382
408
|
return false if !left?
|
383
409
|
return false if !right?
|
384
|
-
return true if left ==
|
410
|
+
return true if left == hqmf.SpecificsManager.any and right == hqmf.SpecificsManager.any
|
385
411
|
return true if left.id == right.id
|
386
412
|
return false
|
387
413
|
|
@@ -410,50 +436,50 @@ class Row
|
|
410
436
|
Wrap methods to maintain specificContext and specific_occurrence
|
411
437
|
###
|
412
438
|
|
413
|
-
hQuery.CodedEntryList::withStatuses = wrap(hQuery.CodedEntryList::withStatuses, (func, statuses, includeUndefined=true) ->
|
439
|
+
hQuery.CodedEntryList::withStatuses = _.wrap(hQuery.CodedEntryList::withStatuses, (func, statuses, includeUndefined=true) ->
|
414
440
|
context = this.specificContext
|
415
441
|
occurrence = this.specific_occurrence
|
416
|
-
func = bind(func, this)
|
442
|
+
func = _.bind(func, this)
|
417
443
|
result = func(statuses,includeUndefined)
|
418
444
|
result.specificContext = context
|
419
445
|
result.specific_occurrence = occurrence
|
420
446
|
return result;
|
421
447
|
);
|
422
448
|
|
423
|
-
hQuery.CodedEntryList::withNegation = wrap(hQuery.CodedEntryList::withNegation, (func, codeSet) ->
|
449
|
+
hQuery.CodedEntryList::withNegation = _.wrap(hQuery.CodedEntryList::withNegation, (func, codeSet) ->
|
424
450
|
context = this.specificContext
|
425
451
|
occurrence = this.specific_occurrence
|
426
|
-
func = bind(func, this)
|
452
|
+
func = _.bind(func, this)
|
427
453
|
result = func(codeSet)
|
428
454
|
result.specificContext = context
|
429
455
|
result.specific_occurrence = occurrence
|
430
456
|
return result;
|
431
457
|
);
|
432
458
|
|
433
|
-
hQuery.CodedEntryList::withoutNegation = wrap(hQuery.CodedEntryList::withoutNegation, (func) ->
|
459
|
+
hQuery.CodedEntryList::withoutNegation = _.wrap(hQuery.CodedEntryList::withoutNegation, (func) ->
|
434
460
|
context = this.specificContext
|
435
461
|
occurrence = this.specific_occurrence
|
436
|
-
func = bind(func, this)
|
462
|
+
func = _.bind(func, this)
|
437
463
|
result = func()
|
438
464
|
result.specificContext = context
|
439
465
|
result.specific_occurrence = occurrence
|
440
466
|
return result;
|
441
467
|
);
|
442
468
|
|
443
|
-
hQuery.CodedEntryList::concat = wrap(hQuery.CodedEntryList::concat, (func, otherEntries) ->
|
469
|
+
hQuery.CodedEntryList::concat = _.wrap(hQuery.CodedEntryList::concat, (func, otherEntries) ->
|
444
470
|
context = this.specificContext
|
445
471
|
occurrence = this.specific_occurrence
|
446
|
-
func = bind(func, this)
|
472
|
+
func = _.bind(func, this)
|
447
473
|
result = func(otherEntries)
|
448
474
|
result.specificContext = context
|
449
475
|
result.specific_occurrence = occurrence
|
450
476
|
return result;
|
451
477
|
);
|
452
478
|
|
453
|
-
hQuery.CodedEntryList::match = wrap(hQuery.CodedEntryList::match, (func, codeSet, start, end, includeNegated=false) ->
|
479
|
+
hQuery.CodedEntryList::match = _.wrap(hQuery.CodedEntryList::match, (func, codeSet, start, end, includeNegated=false) ->
|
454
480
|
context = this.specificContext
|
455
481
|
occurrence = this.specific_occurrence
|
456
|
-
func = bind(func, this)
|
482
|
+
func = _.bind(func, this)
|
457
483
|
result = func(codeSet, start, end, includeNegated)
|
458
484
|
result.specificContext = context
|
459
485
|
result.specific_occurrence = occurrence
|