View Javadoc
1   /*
2    * Copyright 2017 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  package org.openehealth.ipf.commons.audit.marshal.dicom;
17  
18  import org.jdom2.Content;
19  import org.jdom2.Document;
20  import org.jdom2.Element;
21  import org.jdom2.output.Format;
22  import org.jdom2.output.XMLOutputter;
23  import org.openehealth.ipf.commons.audit.marshal.SerializationStrategy;
24  import org.openehealth.ipf.commons.audit.model.*;
25  import org.openehealth.ipf.commons.audit.types.AuditSource;
26  import org.openehealth.ipf.commons.audit.types.CodedValueType;
27  import org.openehealth.ipf.commons.audit.types.EnumeratedValueSet;
28  
29  import java.io.IOException;
30  import java.io.Writer;
31  import java.nio.charset.StandardCharsets;
32  
33  /**
34   * @author Christian Ohr
35   * @since 3.5
36   */
37  public class DICOM2016a implements SerializationStrategy {
38  
39      // Omit XML declaration, because this is done as part of the RFC5424Protocol
40      private static final XMLOutputter PRETTY = new XMLOutputter(Format.getPrettyFormat().setOmitDeclaration(true));
41      private static final XMLOutputter COMPACT = new XMLOutputter(Format.getCompactFormat().setOmitDeclaration(true));
42  
43  
44      @Override
45      public void marshal(AuditMessage auditMessage, Writer writer, boolean pretty) throws IOException {
46          serialize(auditMessage, writer, pretty ? PRETTY : COMPACT);
47      }
48  
49      private void serialize(AuditMessage auditMessage, Writer writer, XMLOutputter outputter) throws IOException {
50          Element element = new Element("AuditMessage");
51          element.addContent(eventIdentification(auditMessage.getEventIdentification()));
52  
53          auditMessage.getActiveParticipants().stream()
54                  .map(this::activeParticipant)
55                  .forEach(element::addContent);
56  
57          element.addContent(auditSourceIdentification(auditMessage.getAuditSourceIdentification()));
58  
59          auditMessage.getParticipantObjectIdentifications().stream()
60                  .map(this::participantObjectIdentification)
61                  .forEach(element::addContent);
62  
63          outputter.output(new Document(element), writer);
64      }
65  
66      protected Content activeParticipant(ActiveParticipantType activeParticipant) {
67          Element element = new Element("ActiveParticipant");
68          element.setAttribute("UserID", activeParticipant.getUserID());
69          conditionallyAddAttribute(element, "AlternativeUserID", activeParticipant.getAlternativeUserID());
70          conditionallyAddAttribute(element, "UserName", activeParticipant.getUserName());
71          element.setAttribute("UserIsRequestor", Boolean.toString(activeParticipant.isUserIsRequestor()));
72          conditionallyAddAttribute(element, "NetworkAccessPointID", activeParticipant.getNetworkAccessPointID());
73          conditionallyAddAttribute(element, "NetworkAccessPointTypeCode", activeParticipant.getNetworkAccessPointTypeCode());
74          if (activeParticipant.getMediaType() != null) {
75              element.addContent(
76                      new Element("MediaIdentifier")
77                              .addContent(codedValueType("MediaType", activeParticipant.getMediaType())));
78          }
79          if (activeParticipant.getRoleIDCodes() != null) {
80              activeParticipant.getRoleIDCodes().stream()
81                      .map(roleIdCode -> codedValueType("RoleIDCode", roleIdCode))
82                      .forEach(element::addContent);
83          }
84          return element;
85      }
86  
87      protected Element eventIdentification(EventIdentificationType eventIdentification) {
88          Element element = new Element("EventIdentification");
89          if (eventIdentification != null) {
90              element.setAttribute("EventActionCode", eventIdentification.getEventActionCode().getValue());
91              element.setAttribute("EventDateTime", eventIdentification.getEventDateTime().toString());
92              element.setAttribute("EventOutcomeIndicator", eventIdentification.getEventOutcomeIndicator().getValue().toString());
93              if (eventIdentification.getEventID() != null) {
94                  element.addContent(codedValueType("EventID", eventIdentification.getEventID()));
95              }
96              eventIdentification.getEventTypeCode().stream()
97                      .map(eventTypeCode -> codedValueType("EventTypeCode", eventTypeCode))
98                      .forEach(element::addContent);
99              if (eventIdentification.getEventOutcomeDescription() != null) {
100                 element.addContent(
101                         new Element("EventOutcomeDescription")
102                                 .addContent(eventIdentification.getEventOutcomeDescription()));
103             }
104             eventIdentification.getPurposesOfUse().stream()
105                     .map(purposeOfUse -> codedValueType("PurposeOfUse", purposeOfUse))
106                     .forEach(element::addContent);
107         }
108         return element;
109     }
110 
111     protected Element participantObjectIdentification(ParticipantObjectIdentificationType poi) {
112         Element element = new Element("ParticipantObjectIdentification");
113         if (poi != null) {
114             conditionallyAddAttribute(element, "ParticipantObjectID", poi.getParticipantObjectID());
115             conditionallyAddAttribute(element, "ParticipantObjectTypeCode", poi.getParticipantObjectTypeCode().getValue().toString());
116             conditionallyAddAttribute(element, "ParticipantObjectTypeCodeRole", poi.getParticipantObjectTypeCodeRole());
117             conditionallyAddAttribute(element, "ParticipantObjectDataLifeCycle", poi.getParticipantObjectDataLifeCycle());
118             conditionallyAddAttribute(element, "ParticipantObjectSensitivity", poi.getParticipantObjectSensitivity());
119             if (poi.getParticipantObjectIDTypeCode() != null) {
120                 element.addContent(codedValueType("ParticipantObjectIDTypeCode", poi.getParticipantObjectIDTypeCode()));
121             }
122             if (poi.getParticipantObjectName() != null) {
123                 element.addContent(new Element("ParticipantObjectName")
124                         .addContent(poi.getParticipantObjectName()));
125             }
126             if (poi.getParticipantObjectQuery() != null) {
127                 element.addContent(new Element("ParticipantObjectQuery")
128                         .addContent(new String(poi.getParticipantObjectQuery(), StandardCharsets.UTF_8)));
129             }
130             poi.getParticipantObjectDetails().stream()
131                     .map(participantObjectDetail -> typeValuePairType("ParticipantObjectDetail", participantObjectDetail))
132                     .forEach(element::addContent);
133 
134             poi.getParticipantObjectDescriptions().stream()
135                     .map(this::dicomObjectDescription)
136                     .forEach(element::addContent);
137         }
138         return element;
139     }
140 
141     protected Element auditSourceIdentification(AuditSourceIdentificationType auditSourceIdentification) {
142         Element element = new Element("AuditSourceIdentification");
143         if (auditSourceIdentification != null) {
144             conditionallyAddAttribute(element, "AuditEnterpriseSiteID", auditSourceIdentification.getAuditEnterpriseSiteID());
145             conditionallyAddAttribute(element, "AuditSourceID", auditSourceIdentification.getAuditSourceID());
146 
147             auditSourceIdentification.getAuditSourceType().stream()
148                     .map(this::auditSourceType)
149                     .forEach(element::addContent);
150         }
151         return element;
152     }
153 
154     protected Element auditSourceType(AuditSource auditSourceType) {
155         return new Element("AuditSourceTypeCode").addContent(auditSourceType.getCode());
156     }
157 
158     protected Element codedValueType(String tagName, CodedValueType codedValue) {
159         Element element = new Element(tagName);
160         element.setAttribute("csd-code", codedValue.getCode());
161         conditionallyAddAttribute(element, "codeSystemName", codedValue.getCodeSystemName());
162         conditionallyAddAttribute(element, "displayName", codedValue.getDisplayName());
163         conditionallyAddAttribute(element, "originalText", codedValue.getOriginalText());
164         return element;
165     }
166 
167     protected Element typeValuePairType(String tagName, TypeValuePairType typeValuePair) {
168         Element element = new Element(tagName);
169         element.setAttribute("type", typeValuePair.getType());
170         element.setAttribute("value", new String(typeValuePair.getValue(), StandardCharsets.UTF_8));
171         return element;
172     }
173 
174     protected Element dicomObjectDescription(DicomObjectDescriptionType dicomObjectDescription) {
175         Element pod = new Element("ParticipantObjectDescription");
176         dicomObjectDescription.getMPPS().forEach(mpps ->
177                 pod.addContent(new Element("MPPS").setAttribute("UID", mpps)));
178         dicomObjectDescription.getAccession().forEach(accession ->
179                 pod.addContent(new Element("Accession").setAttribute("Number", accession)));
180         dicomObjectDescription.getSOPClasses().forEach(sop -> {
181             Element sopClass = new Element("SOPClass")
182                     .setAttribute("NumberOfInstances", String.valueOf(sop.getNumberOfInstances()));
183             conditionallyAddAttribute(sopClass, "UID", sop.getUid());
184             sop.getInstanceUids().forEach(uid ->
185                     sopClass.addContent(new Element("Instance").setAttribute("UID", uid)));
186             pod.addContent(sopClass);
187         });
188         if (!dicomObjectDescription.getStudyIDs().isEmpty()) {
189             Element participantObjectContainsStudy = new Element("ParticipantObjectContainsStudy ");
190             dicomObjectDescription.getStudyIDs().forEach(studyID ->
191                     participantObjectContainsStudy.addContent(
192                             new Element("StudyIDs ")
193                                     .setAttribute("UID", studyID)));
194             pod.addContent(participantObjectContainsStudy);
195         }
196         if (dicomObjectDescription.getEncrypted() != null) {
197             pod.addContent(
198                     new Element("Encrypted")
199                             .addContent(String.valueOf(dicomObjectDescription.getEncrypted())));
200         }
201         if (dicomObjectDescription.getAnonymized() != null) {
202             pod.addContent(
203                     new Element("Anonymized")
204                             .addContent(String.valueOf(dicomObjectDescription.getAnonymized())));
205         }
206         return pod;
207     }
208 
209     protected void conditionallyAddAttribute(Element element, String attributeName, String value) {
210         if (value != null) {
211             element.setAttribute(attributeName, value);
212         }
213     }
214 
215     protected void conditionallyAddAttribute(Element element, String attributeName, EnumeratedValueSet<?> value) {
216         if (value != null) {
217             element.setAttribute(attributeName, value.getValue().toString());
218         }
219     }
220 
221 }