View Javadoc
1   /*
2    * Copyright 2018 the original author or authors.
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *         http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   */
16  
17  package org.openehealth.ipf.commons.ihe.fhir.support.audit.marshal;
18  
19  import ca.uhn.fhir.context.FhirContext;
20  import ca.uhn.fhir.parser.IParser;
21  import org.hl7.fhir.dstu3.model.AuditEvent;
22  import org.hl7.fhir.dstu3.model.CodeableConcept;
23  import org.hl7.fhir.dstu3.model.Coding;
24  import org.hl7.fhir.dstu3.model.Identifier;
25  import org.hl7.fhir.exceptions.FHIRException;
26  import org.openehealth.ipf.commons.audit.AuditException;
27  import org.openehealth.ipf.commons.audit.codes.EventActionCode;
28  import org.openehealth.ipf.commons.audit.codes.EventOutcomeIndicator;
29  import org.openehealth.ipf.commons.audit.codes.NetworkAccessPointTypeCode;
30  import org.openehealth.ipf.commons.audit.marshal.SerializationStrategy;
31  import org.openehealth.ipf.commons.audit.model.*;
32  import org.openehealth.ipf.commons.audit.types.CodedValueType;
33  
34  import java.io.IOException;
35  import java.io.Writer;
36  import java.sql.Date;
37  
38  /**
39   * @author Christian Ohr
40   */
41  abstract class AbstractFhirAuditEvent implements SerializationStrategy {
42  
43      private final FhirContext fhirContext;
44  
45      public AbstractFhirAuditEvent() {
46          this(FhirContext.forDstu3());
47      }
48  
49      public AbstractFhirAuditEvent(FhirContext fhirContext) {
50          this.fhirContext = fhirContext;
51      }
52  
53      @Override
54      public void marshal(AuditMessage auditMessage, Writer writer, boolean pretty) throws IOException {
55          getParser(fhirContext)
56                  .setPrettyPrint(pretty)
57                  .encodeResourceToWriter(translate(auditMessage), writer);
58      }
59  
60      protected abstract IParser getParser(FhirContext fhirContext);
61  
62      protected AuditEvent translate(AuditMessage auditMessage) {
63          EventIdentificationType eit = auditMessage.getEventIdentification();
64          AuditEvent auditEvent = new AuditEvent()
65                  .setType(codedValueTypeToCoding(eit.getEventID()))
66                  .setAction(getAuditEventAction(eit.getEventActionCode()))
67                  .setRecorded(Date.from(eit.getEventDateTime()))
68                  .setOutcome(getAuditEventOutcome(eit.getEventOutcomeIndicator()))
69                  .setOutcomeDesc(eit.getEventOutcomeDescription());
70          eit.getEventTypeCode().forEach(etc ->
71                  auditEvent.addSubtype(codedValueTypeToCoding(etc)));
72          eit.getPurposesOfUse().forEach(pou ->
73                  auditEvent.addPurposeOfEvent(codedValueTypeToCodeableConcept(pou)));
74  
75          auditMessage.getActiveParticipants().forEach(ap ->
76                  auditEvent.addAgent(activeParticipantToAgent(ap)));
77  
78          auditEvent.setSource(auditSourceIdentificationToEventSource(auditMessage.getAuditSourceIdentification()));
79  
80          auditMessage.getParticipantObjectIdentifications().forEach(poit ->
81                  auditEvent.addEntity(participantObjectIdentificationToEntity(poit)));
82          return auditEvent;
83      }
84  
85      protected AuditEvent.AuditEventEntityComponent participantObjectIdentificationToEntity(ParticipantObjectIdentificationType poit) {
86          AuditEvent.AuditEventEntityComponent entity = new AuditEvent.AuditEventEntityComponent()
87                  .setIdentifier(new Identifier()
88                          .setValue(poit.getParticipantObjectID()))
89                  // poit.getParticipantObjectIDTypeCode())) not used here
90                  .setType(new Coding()
91                          .setCode(String.valueOf(poit.getParticipantObjectTypeCode().getValue()))
92                          .setSystem("http://hl7.org/fhir/audit-entity-type"))
93                  .setRole(new Coding()
94                          .setCode(String.valueOf(poit.getParticipantObjectTypeCodeRole().getValue()))
95                          .setSystem("http://hl7.org/fhir/object-role"))
96                  .setLifecycle(new Coding()
97                          .setCode(String.valueOf(poit.getParticipantObjectDataLifeCycle().getValue()))
98                          .setSystem("http://hl7.org/fhir/dicom-audit-lifecycle"))
99                  .addSecurityLabel(new Coding()
100                         .setCode(poit.getParticipantObjectSensitivity()))
101                 .setName(poit.getParticipantObjectName())
102                 // poit.getParticipantObjectDescription) not mappable here
103                 .setQuery(poit.getParticipantObjectQuery());
104 
105         poit.getParticipantObjectDetails().forEach(tvp ->
106                 entity.addDetail(new AuditEvent.AuditEventEntityDetailComponent()
107                         .setType(tvp.getType())
108                         .setValue(tvp.getValue())));
109 
110         return entity;
111 
112     }
113 
114     protected AuditEvent.AuditEventSourceComponent auditSourceIdentificationToEventSource(AuditSourceIdentificationType asit) {
115         AuditEvent.AuditEventSourceComponent source = new AuditEvent.AuditEventSourceComponent()
116                 .setSite(asit.getAuditEnterpriseSiteID())
117                 .setIdentifier(new Identifier().setValue(asit.getAuditSourceID()));
118         asit.getAuditSourceType().forEach(ast ->
119                 source.addType(codedValueTypeToCoding(ast)));
120         return source;
121     }
122 
123     protected AuditEvent.AuditEventAgentComponent activeParticipantToAgent(ActiveParticipantType ap) {
124         AuditEvent.AuditEventAgentComponent agent = new AuditEvent.AuditEventAgentComponent()
125                 .setUserId(new Identifier().setValue(ap.getUserID()))
126                 .setAltId(ap.getAlternativeUserID())
127                 .setName(ap.getUserName())
128                 .setRequestor(ap.isUserIsRequestor())
129                 .setMedia(codedValueTypeToCoding(ap.getMediaType()))
130                 .setNetwork(new AuditEvent.AuditEventAgentNetworkComponent()
131                         .setAddress(ap.getNetworkAccessPointID())
132                         .setType(auditEventNetworkType(ap.getNetworkAccessPointTypeCode())));
133         ap.getRoleIDCodes().forEach(roleID ->
134                 agent.addPolicy(roleID.getCode()));
135         return agent;
136     }
137 
138     protected AuditEvent.AuditEventAgentNetworkType auditEventNetworkType(NetworkAccessPointTypeCode naptc) {
139         try {
140             return AuditEvent.AuditEventAgentNetworkType.fromCode(String.valueOf(naptc.getValue()));
141         } catch (FHIRException e) {
142             // should never happen
143             throw new AuditException(e);
144         }
145     }
146 
147 
148     protected AuditEvent.AuditEventOutcome getAuditEventOutcome(EventOutcomeIndicator eventOutcomeIndicator) {
149         try {
150             return AuditEvent.AuditEventOutcome.fromCode(String.valueOf(eventOutcomeIndicator.getValue()));
151         } catch (FHIRException e) {
152             // should never happen
153             throw new AuditException(e);
154         }
155     }
156 
157     protected AuditEvent.AuditEventAction getAuditEventAction(EventActionCode eventActionCode) {
158         try {
159             return AuditEvent.AuditEventAction.fromCode(eventActionCode.getValue());
160         } catch (FHIRException e) {
161             // should never happen
162             throw new AuditException(e);
163         }
164     }
165 
166 
167     protected Coding codedValueTypeToCoding(CodedValueType cvt) {
168         return cvt != null ?
169                 new Coding(cvt.getCodeSystemName(),
170                         cvt.getCode(),
171                         cvt.getOriginalText()) :
172                 null;
173     }
174 
175     protected CodeableConcept codedValueTypeToCodeableConcept(CodedValueType cvt) {
176         return cvt != null ?
177                 new CodeableConcept().addCoding(codedValueTypeToCoding(cvt)) :
178                 null;
179     }
180 }