# 修正 HAPI FHIR ValueSet 無法正常 Expand 特殊符號的 Code 以下是筆者當時遇到的情境,在 ValueSet 當中的 Code 都是擁有括號的 QW 數值 QW(x),但在進行 Expansion 之後,會變成只有一個 QW 的結果 ![Magic ValueSet Expansion Result](https://hackmd.io/_uploads/rJaJ0uRByx.png) ## 問題的主要原因 - HAPI FHIR 的 free text index 使用 simple query string 進行搜尋,若是文字使用以下符號,將有可能導致 query 不到所想要的結果 ### Elastic Search query string syntax - +, |, -, ", *, (, ), ~ ![Elastic Search Simple query string syntax](https://hackmd.io/_uploads/SyKzC_CBJl.png) ### [Lucene escaping special characters](https://lucene.apache.org/core/2_9_4/queryparsersyntax.html) - Lucene supports escaping special characters that are part of the query syntax. The current list special characters are - &, |, !, (, ), {, }, ^, ", ~, *, ?, :, \ ### 程式碼來源 - TermReadSvcImpl.java@buildExpansionPredicate ![TermReadSvcImpl.java@buildExpansionPredicate](https://hackmd.io/_uploads/By6vCOArJx.png) ## 更改 hapi-fhir 原始碼 - 筆者在看過 HAPI FHIR 的 Code 發現程式碼其實很單純,所以決定自己手動修改看看 ### 下載專案 - 使用 git 下載專案 ```bash!= git clone https://github.com/hapifhir/hapi-fhir.git ``` ### 更改 Expand 的邏輯 - 進到`src/main/java/ca/uhn/fhir/jpa/term/TermReadSvcImpl.java`檔案 - 找到 `buildExpansionPredicate` function - 更改成以下程式碼 ```java!= /** * Helper method which builds a predicate for the expansion */ private PredicateFinalStep buildExpansionPredicate(List<String> theCodes, SearchPredicateFactory thePredicate) { assert !theCodes.isEmpty(); List<String> escapedCodes; if (myHibernatePropertiesProvider.getHibernateSearchBackend().equalsIgnoreCase("lucene")) { escapedCodes = theCodes.stream().map(this::escapeLucene).collect(Collectors.toList()); } else if (myHibernatePropertiesProvider.getHibernateSearchBackend().equalsIgnoreCase("elasticsearch")) { escapedCodes = theCodes.stream().map(this::escapeElasticsearch).collect(Collectors.toList()); } else { escapedCodes = theCodes; } return thePredicate.simpleQueryString().field("myCode").matching(String.join(" | ", escapedCodes)); } private String escapeLucene(String code) { return code.replaceAll("([+\\-&|!(){}^\"~*?:\\\\])", "\\\\$1"); } private String escapeElasticsearch(String code) { return code.replaceAll("([+\\-|\"*()~])", "\\\\\\\\$1"); } ``` > 這段程式碼主要是透過 myHibernatePropertiesProvider檢查 hiebernate 所使用的引擎,並根據 lucene 或 elasticsearch 進行字串的處理,以修正部分代碼擁有特殊符號導致無法正常展開的問題 ## 打包成 jar 檔 更改完程式碼後,我們需要進行 jar 檔的打包,讓 hapi fhir jpaserver starter 可以使用我們修改後的 jar 檔 - 在 idea 上對 HAPI FHIR JPA Server 點擊 package ![package jar](https://hackmd.io/_uploads/r1BJkYRrye.png) ## 使用 local JAR 檔 接下來,我們就要把打包後的 jar 檔丟到 hapi fhir jpserver starter 使用啦! - 在專案根目錄的 `pom.xml`檔案加入 local repository ```xml!= <repositories> <repository> <id>oss-snapshots</id> <snapshots> <enabled>true</enabled> </snapshots> <url>https://oss.sonatype.org/content/repositories/snapshots/</url> </repository> <repository> <id>localLibs</id> <name>localLibs</name> <url>file:///${basedir}/libs</url> </repository> </repositories> ``` - 在專案根目錄創建 libs 資料夾 - 根據想要新增的 JAR 檔的 groupId 與 artifactId 創建資料夾 - 在這裡為 `ca/uhn/hapi/fhir/hapi-fhir-jpaserver-base` ![folder for jar](https://hackmd.io/_uploads/HkUH1tCrJg.png) - 把更改好的 `hapi-fhir-jpaserver-base-7.4.0.jar` 放入 `libs/ca/uhn/hapi/fhir/hapi-fhir-jpaserver-base` 當中 - 創建 `hapi-fhir-jpaserver-base-7.4.0.pom` 檔案,內容如下 ```xml!= <?xml version="1.0" encoding="UTF-8"?> <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <modelVersion>4.0.0</modelVersion> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir-jpaserver-base</artifactId> <version>7.4.0</version> <description>POM was created from install:install-file</description> </project> ``` - 先進行依賴安裝 ```bash!= mvn -ntp dependency:go-offline ``` - 安裝完畢後,在執行以下指令覆蓋原本的 jar 檔 ```bash!= mvn install:install-file -Dfile=libs/ca/uhn/hapi/fhir/hapi-fhir-jpaserver-base/hapi-fhir-jpaserver-base-7.4.0.jar -DgroupId=ca.uhn.hapi.fhir -DartifactId=hapi-fhir-jpaserver-base -Dversion=7.4.0 -Dpackaging=jar ``` ## 測試 上面的步驟都做完後,最大的項目,就是進行測試啦 - 從 idea 直接執行 hapi fhir jpaserver starter 專案 - 透過 postman 把 CodeSystem 與 ValueSet 上傳 - 對 ValueSet 進行展開 ($expand),看到展開的 Code 數量與 IG 上的一樣就代表成功囉! ## 參考資料 - https://chengjhan.github.io/p/%E5%9C%A8-maven-%E5%B0%88%E6%A1%88%E6%96%B0%E5%A2%9E%E7%A7%81%E6%9C%89%E7%9A%84-jar-%E6%AA%94/ - [出錯的 ValueSet](https://twcore.mohw.gov.tw/ig/pas/ValueSet-medication-frequency-hl7-nhi.html) - 若你還想要優化驗證(validation)的速度,可以看 https://github.com/hapifhir/hapi-fhir/issues/6252 - 此修改已在 hapi-fhir 7.6.0 套用 - 個人修改版的 github: https://github.com/Chinlinlee/hapi-fhir/tree/v7.4.0 ## Support Me 文件創作花費了很多心血製作,如果你覺得很有幫助 不妨贊助我一下喝杯咖啡唄,[Support Me](https://portaly.cc/Li070/support)