Skip to content

Commit d36fbe1

Browse files
author
Grahame Grieve
committed
Adds support for regex filters on property values
1 parent d8eb6aa commit d36fbe1

1 file changed

Lines changed: 82 additions & 51 deletions

File tree

library/ftx/fhir_codesystem_service.pas

Lines changed: 82 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -210,8 +210,9 @@ TFhirCodeSystemProvider = class (TCodeSystemProvider)
210210
function hasPropForCode(code : String) : boolean;
211211
function conceptHasProperty(concept : TFhirCodeSystemConceptW; url : String; value : string) : boolean;
212212
procedure iterateConceptsByProperty(src : TFhirCodeSystemConceptListW; pp : TFhirCodeSystemPropertyW; values: TStringArray; list: TFhirCodeSystemProviderFilterContext; include : boolean);
213+
procedure iterateConceptsByPropertyRegex(src : TFhirCodeSystemConceptListW; pp : TFhirCodeSystemPropertyW; regex: TRegularExpression; list: TFhirCodeSystemProviderFilterContext; include : boolean);
213214
procedure iterateConceptsByKnownProperty(src : TFhirCodeSystemConceptListW; code : String; values: TStringArray; List: TFhirCodeSystemProviderFilterContext; include : boolean);
214-
procedure iterateConceptsByRegex(src : TFhirCodeSystemConceptListW; regex: string; list: TFhirCodeSystemProviderFilterContext);
215+
procedure iterateConceptsByRegex(src : TFhirCodeSystemConceptListW; regex: TRegularExpression; list: TFhirCodeSystemProviderFilterContext);
215216
procedure iterateConceptsByEquality(positive : boolean; src : TFhirCodeSystemConceptListW; code: string; list: TFhirCodeSystemProviderFilterContext);
216217

217218
procedure listChildrenByProperty(opContext : TTxOperationContext; op : String; code : String; list, children : TFhirCodeSystemConceptListW);
@@ -1522,58 +1523,80 @@ procedure TFhirCodeSystemProvider.iterateCodes(opContext : TTxOperationContext;
15221523
procedure TFhirCodeSystemProvider.iterateConceptsByProperty(src : TFhirCodeSystemConceptListW; pp: TFhirCodeSystemPropertyW; values: TStringArray; list: TFhirCodeSystemProviderFilterContext; include : boolean);
15231524
var
15241525
c, cc : TFhirCodeSystemConceptW;
1525-
concepts : TFhirCodeSystemConceptListW;
15261526
css : TFhirCodeSystemW;
15271527
cp : TFhirCodeSystemConceptPropertyW;
15281528
ok, val : boolean;
15291529
coding : TFHIRCodingW;
15301530
begin
1531-
concepts := TFhirCodeSystemConceptListW.Create;
1532-
try
1533-
for c in src do
1531+
for c in src do
1532+
begin
1533+
ok := not include;
1534+
val := false;
1535+
for cp in cc.properties.forEnum do
15341536
begin
1535-
concepts.Clear;
1536-
concepts.Add(c.Link);
1537-
for css in FCs.Supplements do
1537+
if (ok <> include) and (cp.code = pp.code) then
15381538
begin
1539-
cc := locCode(css.conceptList, c.code, css.propertyCode('http://hl7.org/fhir/concept-properties#alternateCode'), nil);
1540-
if (cc <> nil) then
1541-
concepts.Add(cc.Link);
1539+
val := true;
1540+
case pp.type_ of
1541+
cptCode, cptString, cptInteger, cptBoolean, cptDateTime, cptDecimal:
1542+
begin
1543+
ok := StringArrayExistsSensitive(values, cp.value.primitiveValue) = include;
1544+
end;
1545+
cptCoding:
1546+
begin
1547+
coding := FFactory.wrapCoding(cp.value.Link);
1548+
try
1549+
ok := StringArrayExistsSensitive(values, coding.code) = include;
1550+
finally
1551+
coding.free;
1552+
end;
1553+
end;
1554+
end;
15421555
end;
1543-
for cc in concepts do
1556+
end;
1557+
if ok then
1558+
list.Add(c.Link, 0);
1559+
end;
1560+
if (c.hasConcepts) then
1561+
iterateConceptsByProperty(c.conceptList, pp, values, list, include);
1562+
end;
1563+
1564+
procedure TFhirCodeSystemProvider.iterateConceptsByPropertyRegex(src: TFhirCodeSystemConceptListW; pp: TFhirCodeSystemPropertyW; regex: TRegularExpression; list: TFhirCodeSystemProviderFilterContext; include: boolean);
1565+
var
1566+
c, cc : TFhirCodeSystemConceptW;
1567+
css : TFhirCodeSystemW;
1568+
cp : TFhirCodeSystemConceptPropertyW;
1569+
ok, val : boolean;
1570+
coding : TFHIRCodingW;
1571+
begin
1572+
for c in src do
1573+
begin
1574+
ok := not include;
1575+
val := false;
1576+
for cp in c.properties.forEnum do
1577+
begin
1578+
if (ok <> include) and (cp.code = pp.code) then
15441579
begin
1545-
ok := not include;
1546-
val := false;
1547-
for cp in cc.properties.forEnum do
1548-
begin
1549-
if (ok <> include) and (cp.code = pp.code) then
1550-
begin
1551-
val := true;
1552-
case pp.type_ of
1553-
cptCode, cptString, cptInteger, cptBoolean, cptDateTime, cptDecimal:
1554-
begin
1555-
ok := StringArrayExistsSensitive(values, cp.value.primitiveValue) = include;
1556-
end;
1557-
cptCoding:
1558-
begin
1559-
coding := FFactory.wrapCoding(cp.value.Link);
1560-
try
1561-
ok := StringArrayExistsSensitive(values, coding.code) = include;
1562-
finally
1563-
coding.free;
1564-
end;
1565-
end;
1580+
val := true;
1581+
case pp.type_ of
1582+
cptCode, cptString, cptInteger, cptBoolean, cptDateTime, cptDecimal:
1583+
ok := regex.isMatch(cp.value.primitiveValue) = include;
1584+
cptCoding:
1585+
begin
1586+
coding := FFactory.wrapCoding(cp.value.Link);
1587+
try
1588+
ok := regex.isMatch(coding.code) = include;
1589+
finally
1590+
coding.free;
1591+
end;
15661592
end;
1567-
end;
15681593
end;
1569-
if ok then
1570-
list.Add(c.Link, 0);
15711594
end;
1572-
if (c.hasConcepts) then
1573-
iterateConceptsByProperty(c.conceptList, pp, values, list, include);
15741595
end;
1575-
finally
1576-
concepts.free;
1596+
if ok then
1597+
list.Add(c.Link, 0);
1598+
if (c.hasConcepts) then
1599+
iterateConceptsByPropertyRegex(c.conceptList, pp, regex, list, include);
15771600
end;
15781601
end;
15791602

@@ -1636,21 +1659,15 @@ procedure TFhirCodeSystemProvider.iterateConceptsByKnownProperty(
16361659
end;
16371660
end;
16381661

1639-
procedure TFhirCodeSystemProvider.iterateConceptsByRegex(src: TFhirCodeSystemConceptListW; regex: string; list: TFhirCodeSystemProviderFilterContext);
1662+
procedure TFhirCodeSystemProvider.iterateConceptsByRegex(src: TFhirCodeSystemConceptListW; regex: TRegularExpression; list: TFhirCodeSystemProviderFilterContext);
16401663
var
16411664
c : TFhirCodeSystemConceptW;
16421665
ok : boolean;
16431666
rx: TRegularExpression;
16441667
begin
16451668
for c in src do
16461669
begin
1647-
rx := TRegularExpression.create('^'+regex+'$');
1648-
try
1649-
ok := rx.isMatch(c.code);
1650-
finally
1651-
rx.free;
1652-
end;
1653-
//ok := c.code.length = 5;
1670+
ok := regex.isMatch(c.code);
16541671
if ok then
16551672
list.Add(c.Link, 0);
16561673
iterateConceptsByRegex(c.conceptList, regex, list);
@@ -1694,6 +1711,7 @@ function TFhirCodeSystemProvider.filter(opContext : TTxOperationContext; forExpa
16941711
pp : TFhirCodeSystemPropertyW;
16951712
cc : TFhirCodeSystemConceptW;
16961713
includeRoot : boolean;
1714+
regex : TRegularExpression;
16971715
begin
16981716
SetThreadStatus(ClassName+'.filter('+prop+CODES_TFhirFilterOperator[op]+value+')');
16991717
if (op in [foIsA, foDescendentOf]) and ((prop = 'concept') or (prop = 'code')) then
@@ -1795,13 +1813,14 @@ function TFhirCodeSystemProvider.filter(opContext : TTxOperationContext; forExpa
17951813
else if (op = foRegex) and (prop = 'code') then
17961814
begin
17971815
result := TFhirCodeSystemProviderFilterContext.Create;
1816+
regex := TRegularExpression.create('^'+value+'$');
17981817
try
1799-
iterateConceptsByRegex(FCs.CodeSystem.conceptList, value, result as TFhirCodeSystemProviderFilterContext);
1818+
iterateConceptsByRegex(FCs.CodeSystem.conceptList, regex, result as TFhirCodeSystemProviderFilterContext);
18001819
result.link;
18011820
finally
1821+
regex.free;
18021822
result.free;
18031823
end;
1804-
18051824
end
18061825
else
18071826
begin
@@ -1826,7 +1845,19 @@ function TFhirCodeSystemProvider.filter(opContext : TTxOperationContext; forExpa
18261845
finally
18271846
result.free;
18281847
end;
1829-
end
1848+
end
1849+
else if (pp <> nil) and (op = foRegex) then
1850+
begin
1851+
result := TFhirCodeSystemProviderFilterContext.Create;
1852+
regex := TRegularExpression.create('^'+value+'$');
1853+
try
1854+
iterateConceptsByPropertyRegex(FCs.CodeSystem.conceptList, pp, regex, result as TFhirCodeSystemProviderFilterContext, true);
1855+
result.link;
1856+
finally
1857+
regex.free;
1858+
result.free;
1859+
end;
1860+
end
18301861
else if (pp <> nil) and (op = foNotIn) then
18311862
begin
18321863
result := TFhirCodeSystemProviderFilterContext.Create;

0 commit comments

Comments
 (0)