001/* ***** BEGIN LICENSE BLOCK ***** 002 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 003 * 004 * The contents of this file are subject to the Mozilla Public License Version 005 * 1.1 (the "License"); you may not use this file except in compliance with 006 * the License. You may obtain a copy of the License at 007 * http://www.mozilla.org/MPL/ 008 * 009 * Software distributed under the License is distributed on an "AS IS" basis, 010 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 011 * for the specific language governing rights and limitations under the 012 * License. 013 * 014 * The Original Code is part of dcm4che, an implementation of DICOM(TM) in 015 * Java(TM), hosted at https://github.com/gunterze/dcm4che. 016 * 017 * The Initial Developer of the Original Code is 018 * Agfa Healthcare. 019 * Portions created by the Initial Developer are Copyright (C) 2013 020 * the Initial Developer. All Rights Reserved. 021 * 022 * Contributor(s): 023 * See @authors listed below 024 * 025 * Alternatively, the contents of this file may be used under the terms of 026 * either the GNU General Public License Version 2 or later (the "GPL"), or 027 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 028 * in which case the provisions of the GPL or the LGPL are applicable instead 029 * of those above. If you wish to allow use of your version of this file only 030 * under the terms of either the GPL or the LGPL, and not to allow others to 031 * use your version of this file under the terms of the MPL, indicate your 032 * decision by deleting the provisions above and replace them with the notice 033 * and other provisions required by the GPL or the LGPL. If you do not delete 034 * the provisions above, a recipient may use your version of this file under 035 * the terms of any one of the MPL, the GPL or the LGPL. 036 * 037 * ***** END LICENSE BLOCK ***** */ 038 039package org.dcm4che3.net.audit; 040 041import java.util.List; 042 043import org.dcm4che3.audit.ActiveParticipant; 044import org.dcm4che3.audit.AuditMessage; 045import org.dcm4che3.audit.EventID; 046import org.dcm4che3.audit.EventIdentification; 047import org.dcm4che3.audit.EventTypeCode; 048import org.dcm4che3.audit.RoleIDCode; 049import org.dcm4che3.conf.core.api.ConfigurableClass; 050import org.dcm4che3.conf.core.api.ConfigurableProperty; 051import org.dcm4che3.conf.core.api.LDAP; 052import org.dcm4che3.data.Code; 053 054/** 055 * Specifies criteria for {@link EventIdentification} and optional also for 056 * {@link ActiveParticipant}s of {@link AuditMessage}s which shall be suppressed. 057 * 058 * Only Audit Messages which match all specified criteria will be suppressed. 059 * 060 * Audit Messages without any {@code ActiveParticipant} will only match an 061 * {@code AuditSuppressCriteria} with does not specify criteria for 062 * {@code ActiveParticipant}s. 063 * 064 * Audit Messages with multiple {@code ActiveParticipants} will match if one 065 * of the {@code ActiveParticipants} match all {@code ActiveParticipant} 066 * specific criteria. 067 * 068 * @author Gunter Zeilinger <gunterze@gmail.com> 069 * 070 */ 071@LDAP(objectClasses = "dcmAuditSuppressCriteria") 072@ConfigurableClass 073public class AuditSuppressCriteria { 074 075 @ConfigurableProperty(name="cn") 076 private String commonName; 077 078 @ConfigurableProperty(name="dcmAuditEventID") 079 private EventID[] eventIDs = {}; 080 081 @ConfigurableProperty(name="dcmAuditEventTypeCode") 082 private EventTypeCode[] eventTypeCodes = {}; 083 084 @ConfigurableProperty(name="dcmAuditEventActionCode") 085 private String eventActionCodes[] = {}; 086 087 @ConfigurableProperty(name="dcmAuditEventOutcomeIndicator") 088 private String[] eventOutcomeIndicators = {}; 089 090 @ConfigurableProperty(name="dcmAuditUserID") 091 private String[] userIDs = {}; 092 093 @ConfigurableProperty(name="dcmAuditAlternativeUserID") 094 private String[] alternativeUserIDs = {}; 095 096 @ConfigurableProperty(name="dcmAuditUserRoleIDCode") 097 private RoleIDCode[] roleIDCodes = {}; 098 099 @ConfigurableProperty(name="dcmAuditNetworkAccessPointID") 100 private String[] networkAccessPointIDs = {}; 101 102 @ConfigurableProperty(name="dcmAuditUserIsRequestor") 103 private Boolean userIsRequestor; 104 105 public AuditSuppressCriteria() { 106 } 107 108 public void setCommonName(String commonName) { 109 this.commonName = commonName; 110 } 111 112 public AuditSuppressCriteria(String cn) { 113 if (cn.isEmpty()) 114 throw new IllegalArgumentException("cn must not be empty"); 115 this.commonName = cn; 116 } 117 118 public String getCommonName() { 119 return commonName; 120 } 121 122 public EventID[] getEventIDs() { 123 return eventIDs; 124 } 125 126 /** Specifies values of {@link EventID} of the {@link EventIdentification} 127 * of messages which shall be suppressed. 128 * 129 * If no value is specified, the {@link EventID} of the {@link EventIdentification} 130 * of a message will not be concerned by this {@code AuditSuppressCriteria}. 131 * 132 * @param eventIDs values of {@code EventID} of the {@code EventIdentification} 133 * of messages which shall be suppressed. 134 */ 135 public void setEventIDs(EventID... eventIDs) { 136 this.eventIDs = eventIDs; 137 } 138 139 public String[] getEventIDsAsStringArray() { 140 return toStringArray(eventIDs); 141 } 142 143 public void setEventIDsAsStringArray(String[] ss) { 144 setEventIDs(toEventIDArray(ss)); 145 } 146 147 public EventTypeCode[] getEventTypeCodes() { 148 return eventTypeCodes; 149 } 150 151 /** Specifies values of {@link EventTypeCode} of the {@link EventIdentification} 152 * of messages which shall be suppressed. 153 * 154 * If no value is specified, the {@link EventTypeCode} of the {@link EventIdentification} 155 * of a message will not be concerned by this {@code AuditSuppressCriteria}. 156 * 157 * If values are specified, Audit Messages without {@code EventTypeCode}s 158 * will not match this {@code AuditSuppressCriteria}. 159 * 160 * Audit Messages with multiple {@code EventTypeCode}s will match if one 161 * of the {@code EventTypeCode} match one of the specified values. 162 * 163 * @param eventTypeCodes values of {@link EventTypeCode} of the {@link EventIdentification} 164 * of messages which shall be suppressed. 165 */ 166 public void setEventTypeCodes(EventTypeCode... eventTypeCodes) { 167 this.eventTypeCodes = eventTypeCodes; 168 } 169 170 public String[] getEventTypeCodesAsStringArray() { 171 return toStringArray(eventTypeCodes); 172 } 173 174 public void setEventTypeCodesAsStringArray(String... ss) { 175 setEventTypeCodes(toEventTypeCodeArray(ss)); 176 } 177 178 public String[] getEventActionCodes() { 179 return eventActionCodes; 180 } 181 182 /** Specifies values of {@code EventActionCode} of the {@link EventIdentification} 183 * of messages which shall be suppressed. 184 * 185 * If no value is specified, the {@code EventActionCode} of the {@link EventIdentification} 186 * of a message will not be concerned by this {@code AuditSuppressCriteria}. 187 * 188 * If values are specified, Audit Messages without {@code EventActionCode} 189 * will not match this {@code AuditSuppressCriteria}. 190 * 191 * @param eventActionCodes values of {@code EventActionCode} of the {@link EventIdentification} 192 * of messages which shall be suppressed. 193 */ 194 public void setEventActionCodes(String... eventActionCodes) { 195 this.eventActionCodes = eventActionCodes; 196 } 197 198 public String[] getEventOutcomeIndicators() { 199 return eventOutcomeIndicators; 200 } 201 202 /** Specifies values of {@code EventOutcomeIndicator} of the {@link EventIdentification} 203 * of messages which shall be suppressed. 204 * 205 * If no value is specified, the {@code EventOutcomeIndicator} of the {@link EventIdentification} 206 * of a message will not be concerned by this {@code AuditSuppressCriteria}. 207 * 208 * @param eventOutcomeIndicators values of {@code EventOutcomeIndicator} of the {@link EventIdentification} 209 * of messages which shall be suppressed. 210 */ 211 public void setEventOutcomeIndicators(String... eventOutcomeIndicators) { 212 this.eventOutcomeIndicators = eventOutcomeIndicators; 213 } 214 215 public String[] getUserIDs() { 216 return userIDs; 217 } 218 219 /** Specifies values of {@code UserID} of {@link ActiveParticipant}s of 220 * messages which shall be suppressed. 221 * 222 * If no value is specified, the {@code UserID} of {@link ActiveParticipant}s 223 * of a message will not be concerned by this {@code AuditSuppressCriteria}. 224 * 225 * @param userIDs values of {@code UserID} of the {@link ActiveParticipant}s 226 * of messages which shall be suppressed. 227 */ 228 public void setUserIDs(String... userIDs) { 229 this.userIDs = userIDs; 230 } 231 232 public String[] getAlternativeUserIDs() { 233 return alternativeUserIDs; 234 } 235 236 /** Specifies values of {@code AlternativeUserID} of {@link ActiveParticipant}s of 237 * messages which shall be suppressed. 238 * 239 * {@code ActiveParticipant}s with multiple {@code EventTypeCode}s will match if one 240 * of the {@code EventTypeCode} match one of the specified values. 241 * 242 * If no value is specified, the {@code AlternativeUserID} of {@code ActiveParticipant}s 243 * of a message will not be concerned by this {@code AuditSuppressCriteria}. 244 * 245 * If values are specified, {@code ActiveParticipant}s without {@code AlternativeUserID} 246 * will not match this {@code AuditSuppressCriteria}. 247 * 248 * @param altUserID values of {@code AlternativeUserID} of the {@link ActiveParticipant}s 249 * of messages which shall be suppressed. 250 */ 251 public void setAlternativeUserIDs(String... altUserID) { 252 this.alternativeUserIDs = altUserID; 253 } 254 255 public RoleIDCode[] getUserRoleIDCodes() { 256 return roleIDCodes; 257 } 258 259 /** Specifies values of {@link RoleIDCode} of {@link ActiveParticipant}s of 260 * messages which shall be suppressed. 261 * 262 * If no value is specified, the {@code RoleIDCode} of {@link ActiveParticipant}s 263 * of a message will not be concerned by this {@code AuditSuppressCriteria}. 264 * 265 * If values are specified, {@code ActiveParticipant}s without {@code RoleIDCode}s 266 * will not match this {@code AuditSuppressCriteria}. 267 * 268 * {@code ActiveParticipant}s with multiple {@code RoleIDCode}s will match if one 269 * of the {@code RoleIDCode} match one of the specified values. 270 * 271 * @param roleIDCodes values of {@code RoleIDCode} of the {@link ActiveParticipant}s 272 * of messages which shall be suppressed. 273 */ 274 public void setUserRoleIDCodes(RoleIDCode... roleIDCodes) { 275 this.roleIDCodes = roleIDCodes; 276 } 277 278 public String[] getUserRoleIDCodesAsStringArray() { 279 return toStringArray(roleIDCodes); 280 } 281 282 public void setUserRoleIDCodesAsStringArray(String... ss) { 283 setUserRoleIDCodes(toRoleIDCodeArray(ss)); 284 } 285 286 public String[] getNetworkAccessPointIDs() { 287 return networkAccessPointIDs; 288 } 289 290 /** Specifies values of {@code NetworkAccessPointID} of {@link ActiveParticipant}s of 291 * messages which shall be suppressed. 292 * 293 * If no value is specified, the {@code NetworkAccessPointID} of {@link ActiveParticipant}s 294 * of a message will not be concerned by this {@code AuditSuppressCriteria}. 295 * 296 * If values are specified, {@code ActiveParticipant}s without {@code NetworkAccessPointID}s 297 * will not match this {@code AuditSuppressCriteria}. 298 * 299 * @param networkAccessPointIDs values of {@code NetworkAccessPointID} of the {@link ActiveParticipant}s 300 * of messages which shall be suppressed. 301 */ 302 public void setNetworkAccessPointIDs(String... networkAccessPointIDs) { 303 this.networkAccessPointIDs = networkAccessPointIDs; 304 } 305 306 public Boolean getUserIsRequestor() { 307 return userIsRequestor; 308 } 309 310 /** Specifies value of {@code UserIsRequestor} of {@link ActiveParticipant}s of 311 * messages which shall be suppressed. 312 * 313 * If {@code null} is specified, the value of {@code UserIsRequestor} of {@link ActiveParticipant}s 314 * of a message will not be concerned by this {@code AuditSuppressCriteria}. 315 * 316 * @param userIsRequestor value of {@code UserIsRequestor} of the {@link ActiveParticipant}s 317 * of messages which shall be suppressed or {@code null}. 318 */ 319 public void setUserIsRequestor(Boolean userIsRequestor) { 320 this.userIsRequestor = userIsRequestor; 321 } 322 323 public boolean match(AuditMessage msg) { 324 if (!match(msg.getEventIdentification())) 325 return false; 326 327 if (!match(msg.getActiveParticipant())) 328 return false; 329 330 return true; 331 } 332 333 private boolean match(EventIdentification eventIdentification) { 334 if (!matchEventID(eventIdentification.getEventID())) 335 return false; 336 337 if (!matchEventTypeCodes(eventIdentification.getEventTypeCode())) 338 return false; 339 340 if (!isEmptyOrContains(eventActionCodes, 341 eventIdentification.getEventActionCode())) 342 return false; 343 344 if (!isEmptyOrContains(eventOutcomeIndicators, 345 eventIdentification.getEventOutcomeIndicator())) 346 return false; 347 348 return true; 349 } 350 351 private boolean matchEventID(EventID o) { 352 if (eventIDs.length == 0) 353 return true; 354 355 for (EventID eventyID : eventIDs) { 356 if (eventyID.getCode().equals(o.getCode()) 357 && equals(eventyID.getCodeSystemName(), o.getCodeSystemName())) 358 return true; 359 } 360 return false; 361 } 362 363 private boolean equals(Object o1, Object o2) { 364 return o1 != null ? o1.equals(o2) : o2 == null; 365 } 366 367 private boolean matchEventTypeCodes(List<EventTypeCode> list) { 368 if (eventTypeCodes.length == 0) 369 return true; 370 371 for (EventTypeCode o : list) { 372 for (EventTypeCode eventTypeCode : eventTypeCodes) { 373 if (eventTypeCode.getCode().equals(o.getCode()) 374 && equals(eventTypeCode.getCodeSystemName(), o.getCodeSystemName())) 375 return true; 376 } 377 } 378 379 return false; 380 } 381 382 private boolean match(List<ActiveParticipant> aps) { 383 if (!containsActiveParticipantCriteria()) 384 return true; 385 386 for (ActiveParticipant ap : aps) { 387 if (match(ap)) 388 return true; 389 } 390 return false; 391 } 392 393 private boolean match(ActiveParticipant ap) { 394 if (!isEmptyOrContains(userIDs, ap.getUserID())) 395 return false; 396 397 if (!isEmptyOrContains(alternativeUserIDs, 398 ap.getAlternativeUserID())) 399 return false; 400 401 if (!isEmptyOrContains(networkAccessPointIDs, 402 ap.getNetworkAccessPointID())) 403 return false; 404 405 if (!matchRoleIDCodes(ap.getRoleIDCode())) 406 return false; 407 408 return userIsRequestor == null 409 || ap.isUserIsRequestor() == userIsRequestor.booleanValue(); 410 } 411 412 private boolean matchRoleIDCodes(List<RoleIDCode> list) { 413 if (roleIDCodes.length == 0) 414 return true; 415 416 for (RoleIDCode o : list) { 417 for (RoleIDCode roleIDCode : roleIDCodes) { 418 if (roleIDCode.getCode().equals(o.getCode()) 419 && equals(roleIDCode.getCodeSystemName(), o.getCodeSystemName())) 420 return true; 421 } 422 } 423 424 return false; 425 } 426 427 public boolean containsActiveParticipantCriteria() { 428 return userIDs.length == 0 429 && alternativeUserIDs.length == 0 430 && roleIDCodes.length == 0 431 && networkAccessPointIDs.length == 0 432 && userIsRequestor == null; 433 } 434 435 private boolean isEmptyOrContains(String[] ss, String o) { 436 if (ss.length == 0) 437 return true; 438 439 if (o == null) 440 return false; 441 442 for (String s : ss) 443 if (o.equals(s)) 444 return true; 445 446 return false; 447 } 448 449 private static String[] toStringArray(EventID... a) { 450 String[] ss = new String[a.length]; 451 for (int i = 0; i < a.length; i++) { 452 ss[i] = new Code( 453 a[i].getCode(), 454 a[i].getCodeSystemName(), 455 null, 456 a[i].getOriginalText()) 457 .toString(); 458 } 459 return ss; 460 } 461 462 private static String[] toStringArray(EventTypeCode... a) { 463 String[] ss = new String[a.length]; 464 for (int i = 0; i < a.length; i++) { 465 ss[i] = new Code( 466 a[i].getCode(), 467 a[i].getCodeSystemName(), 468 null, 469 a[i].getOriginalText()) 470 .toString(); 471 } 472 return ss; 473 } 474 475 private static String[] toStringArray(RoleIDCode... a) { 476 String[] ss = new String[a.length]; 477 for (int i = 0; i < a.length; i++) { 478 ss[i] = new Code( 479 a[i].getCode(), 480 a[i].getCodeSystemName(), 481 null, 482 a[i].getOriginalText()) 483 .toString(); 484 } 485 return ss; 486 } 487 488 private static EventID[] toEventIDArray(String... ss) { 489 EventID[] a = new EventID[ss.length]; 490 for (int i = 0; i < ss.length; i++) { 491 Code code = new Code(ss[i]); 492 a[i] = new EventID(); 493 a[i].setCode(code.getCodeValue()); 494 a[i].setCodeSystemName(code.getCodingSchemeDesignator()); 495 a[i].setOriginalText(code.getCodeMeaning()); 496 } 497 return a; 498 } 499 500 private static EventTypeCode[] toEventTypeCodeArray(String... ss) { 501 EventTypeCode[] a = new EventTypeCode[ss.length]; 502 for (int i = 0; i < ss.length; i++) { 503 Code code = new Code(ss[i]); 504 a[i] = new EventTypeCode(); 505 a[i].setCode(code.getCodeValue()); 506 a[i].setCodeSystemName(code.getCodingSchemeDesignator()); 507 a[i].setOriginalText(code.getCodeMeaning()); 508 } 509 return a; 510 } 511 512 private static RoleIDCode[] toRoleIDCodeArray(String... ss) { 513 RoleIDCode[] a = new RoleIDCode[ss.length]; 514 for (int i = 0; i < ss.length; i++) { 515 Code code = new Code(ss[i]); 516 a[i] = new RoleIDCode(); 517 a[i].setCode(code.getCodeValue()); 518 a[i].setCodeSystemName(code.getCodingSchemeDesignator()); 519 a[i].setOriginalText(code.getCodeMeaning()); 520 } 521 return a; 522 } 523}