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