001package ca.uhn.fhir.mdm.model;
002
003/*-
004 * #%L
005 * HAPI FHIR - Master Data Management
006 * %%
007 * Copyright (C) 2014 - 2022 Smile CDR, Inc.
008 * %%
009 * Licensed under the Apache License, Version 2.0 (the "License");
010 * you may not use this file except in compliance with the License.
011 * You may obtain a copy of the License at
012 *
013 *      http://www.apache.org/licenses/LICENSE-2.0
014 *
015 * Unless required by applicable law or agreed to in writing, software
016 * distributed under the License is distributed on an "AS IS" BASIS,
017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
018 * See the License for the specific language governing permissions and
019 * limitations under the License.
020 * #L%
021 */
022
023import ca.uhn.fhir.context.FhirContext;
024import ca.uhn.fhir.fhirpath.IFhirPath;
025import org.hl7.fhir.instance.model.api.IBase;
026import org.hl7.fhir.instance.model.api.IBaseResource;
027import org.hl7.fhir.instance.model.api.IPrimitiveType;
028import org.hl7.fhir.r4.model.Identifier;
029
030import java.util.List;
031import java.util.Objects;
032import java.util.stream.Collectors;
033
034public class CanonicalEID {
035
036        private String mySystem;
037        private String myUse;
038        private String myValue;
039
040        public CanonicalEID(String theSystem, String theValue, String theUse){
041                mySystem = theSystem;
042                myUse = theUse;
043                myValue = theValue;
044        }
045
046        /**
047         * Constructor is private as we expect you to use the factory method.
048         */
049        @SuppressWarnings("rawtypes")
050        private CanonicalEID(IFhirPath theFhirPath, IBase theIBase) {
051                List<IPrimitiveType> value = theFhirPath.evaluate(theIBase, "value", IPrimitiveType.class);
052                List<IPrimitiveType> system = theFhirPath.evaluate(theIBase, "system", IPrimitiveType.class);
053                List<IPrimitiveType> use = theFhirPath.evaluate(theIBase, "use", IPrimitiveType.class);
054
055                myUse = use.isEmpty() ? null : use.get(0).getValueAsString();
056                myValue = value.isEmpty() ? null : value.get(0).getValueAsString();
057                mySystem = system.isEmpty() ? null : system.get(0).getValueAsString();
058        }
059
060        /**
061         * Get the appropriate FHIRPath expression to extract the EID identifier value, regardless of resource type.
062         * e.g. if theBaseResource is a patient, and the MDM EID system is test-system, this will return
063         *
064         * Patient.identifier.where(system='test-system').value
065         *
066         */
067        private static String buildEidFhirPath(FhirContext theFhirContext, String theEidSystem, IBaseResource theBaseResource) {
068                return theFhirContext.getResourceType(theBaseResource)
069                        + ".identifier.where(system='"
070                        + theEidSystem
071                        + "')";
072        }
073
074        public Identifier toR4() {
075                return new Identifier()
076                        .setUse(Identifier.IdentifierUse.fromCode(myUse))
077                        .setSystem(mySystem)
078                        .setValue(myValue);
079        }
080
081        public org.hl7.fhir.dstu3.model.Identifier toDSTU3(){
082                return new org.hl7.fhir.dstu3.model.Identifier()
083                        .setUse(org.hl7.fhir.dstu3.model.Identifier.IdentifierUse.fromCode(myUse))
084                        .setSystem(mySystem)
085                        .setValue(myValue);
086        }
087
088        public  String getSystem() {
089                return mySystem;
090        }
091
092        public  String getUse() {
093                return myUse;
094        }
095
096        public  String getValue() {
097                return myValue;
098        }
099
100        public void setSystem(String theSystem) {
101                mySystem = theSystem;
102        }
103
104        public void setUse(String theUse) {
105                myUse = theUse;
106        }
107
108        private void setValue(String theValue) {
109                myValue = theValue;
110        }
111
112        @Override
113        public String toString() {
114                return "CanonicalEID{" +
115                        "mySystem='" + mySystem + '\'' +
116                        ", myUse='" + myUse + '\'' +
117                        ", myValue='" + myValue + '\'' +
118                        '}';
119        }
120
121
122        /**
123         * A Factory method to generate a {@link CanonicalEID} object from an incoming resource.
124         *
125         * @param theFhirContext the {@link FhirContext} of the application, used to generate a FHIRPath parser.
126         * @param theEidSystem the enterprise identifier system URI used by this instance.
127         * @param theBaseResource the {@link IBaseResource} from which you would like to extract EIDs.
128         *
129         * @return an optional {@link CanonicalEID} object, representing a resource identifier that matched the given eidSystem.
130         */
131        public static List<CanonicalEID> extractFromResource(FhirContext theFhirContext, String theEidSystem, IBaseResource theBaseResource) {
132                IFhirPath fhirPath = theFhirContext.newFhirPath();
133                String eidPath = buildEidFhirPath(theFhirContext, theEidSystem, theBaseResource);
134                List<IBase> evaluate = fhirPath.evaluate(theBaseResource, eidPath, IBase.class);
135
136                return evaluate.stream()
137                        .map(ibase -> new CanonicalEID(fhirPath, ibase))
138                        .collect(Collectors.toList());
139        }
140
141        @Override
142        public boolean equals(Object o) {
143                if (!(o instanceof CanonicalEID)) {
144                        return false;
145                }
146                CanonicalEID otherEid = (CanonicalEID)o;
147                return Objects.equals(otherEid.getSystem(), this.getSystem())
148                        && Objects.equals(otherEid.getValue(), this.getValue())
149                        && Objects.equals(otherEid.getUse(), this.getUse());
150        }
151
152        @Override
153        public int hashCode() {
154                return Objects.hash(mySystem, myValue, myUse);
155        }
156}