001/** 002The contents of this file are subject to the Mozilla Public License Version 1.1 003(the "License"); you may not use this file except in compliance with the License. 004You may obtain a copy of the License at http://www.mozilla.org/MPL/ 005Software distributed under the License is distributed on an "AS IS" basis, 006WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the 007specific language governing rights and limitations under the License. 008 009The Original Code is "ConformanceProfileRule.java". Description: 010"A MessageRule that checks conformance to message profiles." 011 012The Initial Developer of the Original Code is University Health Network. Copyright (C) 0132005. All Rights Reserved. 014 015Contributor(s): ______________________________________. 016 017Alternatively, the contents of this file may be used under the terms of the 018GNU General Public License (the "GPL"), in which case the provisions of the GPL are 019applicable instead of those above. If you wish to allow use of your version of this 020file only under the terms of the GPL and not to allow others to use your version 021of this file under the MPL, indicate your decision by deleting the provisions above 022and replace them with the notice and other provisions required by the GPL License. 023If you do not delete the provisions above, a recipient may use your version of 024this file under either the MPL or the GPL. 025*/ 026package ca.uhn.hl7v2.validation.impl; 027 028import java.io.IOException; 029import java.util.ArrayList; 030import java.util.Arrays; 031import java.util.List; 032 033import org.slf4j.Logger; 034import org.slf4j.LoggerFactory; 035 036import ca.uhn.hl7v2.HL7Exception; 037import ca.uhn.hl7v2.conf.ProfileException; 038import ca.uhn.hl7v2.conf.check.DefaultValidator; 039import ca.uhn.hl7v2.conf.parser.ProfileParser; 040import ca.uhn.hl7v2.conf.spec.RuntimeProfile; 041import ca.uhn.hl7v2.conf.store.ProfileStoreFactory; 042import ca.uhn.hl7v2.model.Message; 043import ca.uhn.hl7v2.util.Terser; 044import ca.uhn.hl7v2.validation.MessageRule; 045import ca.uhn.hl7v2.validation.ValidationException; 046 047/** 048 * A MessageRule that checks conformance to message profiles. Messges can either be tested 049 * agaist the profiles they declare, or against a pre-defined profile. If you want both, 050 * use two <code>ConformanceProfileRule</code>s. 051 * 052 * @author <a href="mailto:bryan.tripp@uhn.on.ca">Bryan Tripp</a> 053 * @version $Revision: 1.1 $ updated on $Date: 2007-02-19 02:24:40 $ by $Author: jamesagnew $ 054 */ 055@SuppressWarnings("serial") 056public class ConformanceProfileRule implements MessageRule { 057 058 private static final Logger log = LoggerFactory.getLogger(ConformanceProfileRule.class); 059 060 private String myProfileID; 061 062 /** 063 * Creates an instance that tests messages against whatever profiles they declare in 064 * MSH-21. 065 */ 066 public ConformanceProfileRule() { 067 } 068 069 /** 070 * @param theProfileID the ID of a constant profile against which to test all messages 071 * (instead of the profiles they declare in MSH-21) 072 */ 073 public ConformanceProfileRule(String theProfileID) { 074 myProfileID = theProfileID; 075 } 076 077 078 /** 079 * @see ca.uhn.hl7v2.validation.MessageRule#test(ca.uhn.hl7v2.model.Message) 080 */ 081 public ValidationException[] test(Message msg) { 082 List<ValidationException> problems = new ArrayList<ValidationException>(20); 083 String[] ids = {myProfileID}; 084 085 try { 086 if (myProfileID == null) { 087 ids = getDeclaredProfileIDs(msg); 088 } 089 090 for (int i = 0; i < ids.length; i++) { 091 log.debug("Testing message against profile: {}", ids[i]); 092 try { 093 ValidationException[] shortList = testAgainstProfile(msg, ids[i]); 094 log.debug("{} non-conformances", shortList.length); 095 problems.addAll(Arrays.asList(shortList)); 096 } catch (ProfileException e) { 097 problems.add(new ValidationException("Can't validate", e)); 098 } 099 } 100 } catch (HL7Exception e) { 101 problems.add(new ValidationException("Can't validate", e)); 102 } 103 104 return (ValidationException[]) problems.toArray(new ValidationException[0]); 105 } 106 107 private String[] getDeclaredProfileIDs(Message theMessage) throws HL7Exception { 108 Terser t = new Terser(theMessage); 109 boolean noMore = false; 110 int c = 0; 111 List<String> declaredProfiles = new ArrayList<String>(8); 112 while (!noMore) { 113 String path = "MSH-21(" + c++ + ")"; 114 String idRep = t.get(path); 115 //FIXME fails if empty rep precedes full rep ... should add getAll() to Terser and use that 116 if (idRep == null || idRep.equals("")) { 117 noMore = true; 118 } else { 119 declaredProfiles.add(idRep); 120 } 121 } 122 return declaredProfiles.toArray(new String[0]); 123 } 124 125 private ValidationException[] testAgainstProfile(Message message, String id) throws ProfileException, HL7Exception { 126 HL7Exception[] exceptions = null; 127 DefaultValidator val = new DefaultValidator(); 128 try { 129 String profileString = ProfileStoreFactory.getProfileStore().getProfile(id); 130 if (profileString != null) { 131 ProfileParser profParser = new ProfileParser(true); 132 RuntimeProfile profile = profParser.parse(profileString); 133 134 exceptions = val.validate(message, profile.getMessage()); 135 } else { 136 throw new ProfileException("Unable to find the profile " + id); 137 } 138 } catch (IOException e) { 139 throw new ProfileException("Error retreiving profile " + id, e); 140 } 141 142 ValidationException[] result = new ValidationException[exceptions.length]; 143 for (int i = 0; i < exceptions.length; i++) { 144 result[i] = new ValidationException(exceptions[i].getMessage(), exceptions[i]); 145 } 146 return result; 147 } 148 149 150 /** 151 * @see ca.uhn.hl7v2.validation.Rule#getDescription() 152 */ 153 public String getDescription() { 154 return "Checks conformance to declared or predefined message profiles"; 155 } 156 157 /** 158 * @see ca.uhn.hl7v2.validation.Rule#getSectionReference() 159 */ 160 public String getSectionReference() { 161 return "HL7 2.5 section 2.12"; 162 } 163 164}