HAPI FHIR介紹 === 本文主要根據James Agnew - Introduction to HAPI | DevDays 2023 Amsterdam的演講內容並參考HAPI官網內容做快速整理。 https://www.youtube.com/watch?v=d6aAXi38Kow&list=PLKuZNI94tzWY1J988TdEGhJ69r4DnTiAN&index=111&t=1560s Working with Resource --- 每一個Resource都有對應的Class,透過各自的getter/setter function來設定與讀取該Resource所對應的properties。 ``` Observation obs = new Observation(); // 以下三種寫法,其結果相同 obs.setIssuedElement(new InstantType(new Date())); obs.setIssuedElement(new InstantType(new Date(), TemporalPrecisionEnum.MILLI)); obs.setIssued(new Date()); ``` Childe Clasee: 多數的getter function會自動產生child class, ``` Observation observation = new Observation(); // None of these calls will not return null, but instead create their respective child elements. List<Identifier> identifierList = observation.getIdentifier(); CodeableConcept code = observation.getCode(); StringType textElement = observation.getCode().getTextElement(); ``` 代碼處理 ``` Patient patient = new Patient(); //直接寫入(若代碼值為已知) patient.getGenderElement().setValueAsString("male"); //使用Java Enumerated types patient.setGender(Enumerations.AdministrativeGender.MALE); //直接讀取 String String genderString = Patient.getGenderElement().getValueAsString(); //讀取Java Enumerated types Enumerations.AdministrativeGender genderEnum = patient.getGenderElement().getValue(); ``` Chain ``` Patient pat = new Patient() // 建立"name" Element HumanName name = pat.addName(); name.setFamily("Simpson").addGiven("Homer").addGiven("J"); //直接使用Chained pat.addIdentifier().setSystem("http://acme.org/MRNs").setValue("12345"); ``` Working with Data Type --- FHIR定義了所有的基本資料型態,不使用Java既定的data type。主要原因是因為FHIR允許Extension,使用Java既定的data type會受到限制。 ``` BooleanType active = new BooleanType(); active.setValue(true); active.setValueAS("true"); ``` The HAPI FHIR Context --- FhirContect Class是所有FHIR API的進入點,由於相當耗資源,因此必須為唯一(Singleton ?)。 Using the Parser --- ``` // Create a FHIR context FhirContext ctx = FhirContext.forR4(); // The following example is a simple serialized Patient resource to parse String input = "{" + "\"resourceType\" : \"Patient\"," + " \"name\" : [{" + " \"family\": \"Simpson\"" + " }]" + "}"; // Instantiate a new parser IParser parser = ctx.newJsonParser(); // Parse it Patient pat = parser.parseResource(Patient.class, input); String encode = parser.encodeResourceToSting(pat); ``` Using the HAPI FHIR Client --- Client可以從FhirContext產生,可以執行CRUD等相關資料操作。 ``` // We're connecting to a DSTU1 compliant server in this example FhirContext ctx = FhirContext.forR4(); String serverBase = "http://fhirtest.uhn.ca/baseR4"; IGenericClient client = ctx.newRestfulGenericClient(serverBase); // Perform a search Bundle results = client.search() .forResource(Patient.class) .where(Patient.FAMILY.matches().value("duck")) .returnBundle(Bundle.class) .execute(); System.out.println("Found " + results.getEntry().size() + " patients named 'duck'"); ``` Exception Handling --- BaseServerResponseException Package提供完整清單 https://hapifhir.io/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/server/exceptions/BaseServerResponseException.html HAPI FHIR Server --- 共計三種:Plain Server(Facase Layer,可與醫院既有資料庫結合)、JPA Server、JAX-RS(不討論) - JPA Server 相關資料可參考 https://github.com/hapifhir/hapi-fhir-jpaserver-starter 相關的設定、Docker Compose、application.yml等都可以找到相關參考資料。 - JPA Server Features 主要功能包含:Subsciptions、Bulk Import/Export、Partitioning、MDM、IPS、Terminology Services等。 Interceptors --- 在HTTP Request/Response的過程中,透過Hook將處理邏輯內嵌進去,在Client收到回傳資料之前,對input/output做再處理。目前HAPI FHIR Built-in的Interceptors包括: - LoggingInterceptor - CorsInterceptor - RequestValidatingInterceptor - ResponseValidatingInterceptor - ResponseHighlighterInterceptor - OpenApiInterceptor Security --- 1. Authentication(在HAPI FHIR並未實作,必須與其他平台整合) 2. Authorization:使用AuthorizationInterceptor和ConsentInterceptor 3. Consent:使用ConsentInterceptor,結合FHIR Resource(Consent/Questionnaire/QuestionnaireResponse),可以整合客製化的Interceptor 4. Audit:使用BalpAuditCaptureInterceptor Validation --- 包含兩種Validation: * Parser Error Handler:針對JSON檔案結構檢查。 * Validator:Semantic validation,可以跟IG結合,確認資料是否符合IG的規則。