Coverage Report - ca.uhn.hl7v2.validation.AbstractValidator
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractValidator
38%
35/90
32%
18/56
3.667
 
 1  
 /**
 2  
 The contents of this file are subject to the Mozilla Public License Version 1.1 
 3  
 (the "License"); you may not use this file except in compliance with the License. 
 4  
 You may obtain a copy of the License at http://www.mozilla.org/MPL/ 
 5  
 Software distributed under the License is distributed on an "AS IS" basis, 
 6  
 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the 
 7  
 specific language governing rights and limitations under the License. 
 8  
 
 9  
 The Original Code is "AbstractValidator.java".  Description: 
 10  
 "Abstract implementation of a message validator." 
 11  
 
 12  
 The Initial Developer of the Original Code is University Health Network. Copyright (C) 
 13  
 2012.  All Rights Reserved. 
 14  
 
 15  
 Contributor(s): ______________________________________. 
 16  
 
 17  
 Alternatively, the contents of this file may be used under the terms of the 
 18  
 GNU General Public License (the "GPL"), in which case the provisions of the GPL are 
 19  
 applicable instead of those above.  If you wish to allow use of your version of this 
 20  
 file only under the terms of the GPL and not to allow others to use your version 
 21  
 of this file under the MPL, indicate your decision by deleting  the provisions above 
 22  
 and replace  them with the notice and other provisions required by the GPL License.  
 23  
 If you do not delete the provisions above, a recipient may use your version of 
 24  
 this file under either the MPL or the GPL. 
 25  
  */
 26  
 package ca.uhn.hl7v2.validation;
 27  
 
 28  
 import java.util.ArrayList;
 29  
 import java.util.Iterator;
 30  
 import java.util.List;
 31  
 
 32  
 import org.slf4j.Logger;
 33  
 import org.slf4j.LoggerFactory;
 34  
 
 35  
 import ca.uhn.hl7v2.HL7Exception;
 36  
 import ca.uhn.hl7v2.Location;
 37  
 import ca.uhn.hl7v2.model.Composite;
 38  
 import ca.uhn.hl7v2.model.Message;
 39  
 import ca.uhn.hl7v2.model.Primitive;
 40  
 import ca.uhn.hl7v2.model.Segment;
 41  
 import ca.uhn.hl7v2.model.Structure;
 42  
 import ca.uhn.hl7v2.model.Type;
 43  
 import ca.uhn.hl7v2.model.Varies;
 44  
 import ca.uhn.hl7v2.util.ReadOnlyMessageIterator;
 45  
 import ca.uhn.hl7v2.util.Terser;
 46  
 
 47  
 /**
 48  
  * Abstract implementation of a message validator.
 49  
  * 
 50  
  * @param <R> The type parameter R denotes the result type of the validation
 51  
  *            process.
 52  
  * 
 53  
  * @author Christian Ohr
 54  
  */
 55  190
 public abstract class AbstractValidator<R> implements Validator<R> {
 56  
 
 57  1
         private static final Logger LOG = LoggerFactory.getLogger(AbstractValidator.class);
 58  
 
 59  
         /**
 60  
          * Calls {@link #initializeHandler()} to obtain a default instance of a
 61  
          * {@link ValidationExceptionHandler} before starting the validation.
 62  
          * 
 63  
          * @see ca.uhn.hl7v2.validation.Validator#validate(ca.uhn.hl7v2.model.Message)
 64  
          */
 65  
         public R validate(Message message) throws HL7Exception {
 66  4
                 return validate(message, initializeHandler());
 67  
         }
 68  
 
 69  
         /**
 70  
          * @see ca.uhn.hl7v2.validation.Validator#validate(ca.uhn.hl7v2.model.Message,
 71  
          *      ca.uhn.hl7v2.validation.ValidationExceptionHandler)
 72  
          */
 73  
         public R validate(Message message, ValidationExceptionHandler<R> handler) throws HL7Exception {
 74  1000
                 if (message == null) {
 75  0
                         throw new NullPointerException("Message may not be null");
 76  
                 }
 77  1000
                 if (handler == null) {
 78  0
                         throw new NullPointerException("ValidationExceptionHandler may not be null");
 79  
                 }
 80  1000
                 handler.setValidationSubject(message);
 81  
                 // testPrimitiveRules(message, handler); TODO this slows down parser 3x
 82  1000
                 testMessageRules(message, handler);
 83  999
                 return handler.result();
 84  
         }
 85  
 
 86  
         private void testMessageRules(Message message, ValidationExceptionHandler<R> handler)
 87  
                         throws HL7Exception {
 88  1000
                 Terser t = new Terser(message);
 89  1000
                 String messageType = t.get("MSH-9-1");
 90  1000
                 String triggerEvent = t.get("MSH-9-2");
 91  1000
                 List<MessageRule> rules = new ArrayList<MessageRule>();
 92  1000
                 if (getValidationContext() != null) {
 93  1000
                         rules.addAll(getValidationContext().getMessageRules(message.getVersion(), messageType,
 94  
                                         triggerEvent));
 95  
                 }
 96  999
                 LOG.debug("Validating message against {} message rules", rules.size());
 97  999
                 for (MessageRule rule : rules) {
 98  1806
                         ValidationException[] ex = rule.apply(message);
 99  1806
                         if (ex != null && ex.length > 0) {
 100  7
                                 handler.onExceptions(ex);
 101  
                         }
 102  1806
                 }
 103  999
         }
 104  
 
 105  
         private void testPrimitiveRules(Message message, ValidationExceptionHandler<R> handler)
 106  
                         throws HL7Exception {
 107  0
                 LOG.debug("Validating message against primitive type rules");
 108  0
                 for (Iterator<Structure> iter = ReadOnlyMessageIterator
 109  0
                                 .createPopulatedSegmentIterator(message); iter.hasNext();) {
 110  0
                         Segment s = (Segment) iter.next();
 111  0
                         for (int field = 1; field <= s.numFields(); field++) {
 112  0
                                 Type[] t = s.getField(field);
 113  0
                                 for (int rep = 0; rep < t.length; rep++) {
 114  0
                                         Location location = new Location();
 115  0
                                         location.setSegmentName(s.getName());
 116  0
                                         location.setField(field);
 117  0
                                         location.setFieldRepetition(rep);
 118  0
                                         testType(t[rep], handler, location);
 119  
                                 }
 120  
                         }
 121  0
                 }
 122  0
         }
 123  
 
 124  
         private void testType(Type type, ValidationExceptionHandler<R> handler, Location l) {
 125  0
                 if (type instanceof Composite) {
 126  0
                         Type[] components = ((Composite) type).getComponents();
 127  0
                         for (int comp = 0; comp < components.length; comp++) {
 128  0
                                 Location location = new Location(l);
 129  0
                                 location.setComponent(comp + 1);
 130  0
                                 testComponent(components[comp], handler, location);
 131  
                         }
 132  0
                 } else if (type instanceof Varies) {
 133  0
                         testType(((Varies) type).getData(), handler, l);
 134  
                 } else {
 135  0
                         testPrimitive((Primitive) type, handler, l);
 136  
                 }
 137  0
         }
 138  
 
 139  
         private void testComponent(Type type, ValidationExceptionHandler<R> handler, Location l) {
 140  0
                 if (type instanceof Composite) {
 141  0
                         Type[] component = ((Composite) type).getComponents();
 142  0
                         for (int sub = 0; sub < component.length; sub++) {
 143  0
                                 Location location = new Location(l);
 144  0
                                 location.setSubcomponent(sub + 1);
 145  0
                                 testSubComponent(component[sub], handler, location);
 146  
                         }
 147  0
                 } else if (type instanceof Varies) {
 148  0
                         testComponent(((Varies) type).getData(), handler, l);
 149  
                 } else {
 150  0
                         testPrimitive((Primitive) type, handler, l);
 151  
                 }
 152  0
         }
 153  
 
 154  
         private void testSubComponent(Type type, ValidationExceptionHandler<R> handler, Location l) {
 155  0
                 if (type instanceof Primitive) {
 156  0
                         testPrimitive((Primitive) type, handler, l);
 157  0
                 } else if (type instanceof Varies) {
 158  0
                         testSubComponent(((Varies) type).getData(), handler, l);
 159  
                 }
 160  0
         }
 161  
 
 162  
         private void testPrimitive(Primitive p, ValidationExceptionHandler<R> handler, Location l) {
 163  0
                 List<PrimitiveTypeRule> rules = new ArrayList<PrimitiveTypeRule>();
 164  0
                 Message m = p.getMessage();
 165  0
                 if (getValidationContext() != null) {
 166  0
                         rules.addAll(getValidationContext().getPrimitiveRules(m.getVersion(), p.getName(), p));
 167  
                 }
 168  0
                 for (PrimitiveTypeRule rule : rules) {
 169  0
                         ValidationException[] exceptions = rule.apply(p.getValue());
 170  0
                         for (ValidationException ve : exceptions) {
 171  0
                 ve.setLocation(l);
 172  
                         }
 173  0
                         if (exceptions.length > 0) {
 174  0
                                 handler.onExceptions(exceptions);
 175  
                         }
 176  0
                 }
 177  0
         }
 178  
 
 179  
         /**
 180  
          * Calls {@link #initializeHandler()} to obtain a default instance of a
 181  
          * {@link ValidationExceptionHandler} before starting the validation.
 182  
          * 
 183  
          * @see ca.uhn.hl7v2.validation.Validator#validate(Message,
 184  
          *      ValidationExceptionHandler)
 185  
          */
 186  
         public R validate(String message, boolean isXML, String version) throws HL7Exception {
 187  2
                 return validate(message, isXML, version, initializeHandler());
 188  
         }
 189  
 
 190  
         /**
 191  
          * @see ca.uhn.hl7v2.validation.Validator#validate(java.lang.String,
 192  
          *      boolean, java.lang.String,
 193  
          *      ca.uhn.hl7v2.validation.ValidationExceptionHandler)
 194  
          */
 195  
         public R validate(String message, boolean isXML, String version,
 196  
                         ValidationExceptionHandler<R> handler) throws HL7Exception {
 197  1004
                 if (message == null) {
 198  0
                         throw new NullPointerException("Message may not be null");
 199  
                 }
 200  1004
                 if (handler == null) {
 201  0
                         throw new NullPointerException("ValidationExceptionHandler may not be null");
 202  
                 }
 203  1004
                 handler.setValidationSubject(message);
 204  1004
                 List<EncodingRule> rules = new ArrayList<EncodingRule>();
 205  1004
                 if (getValidationContext() != null) {
 206  1004
                         rules.addAll(getValidationContext().getEncodingRules(version, isXML ? "XML" : "ER7"));
 207  
                 }
 208  1004
                 LOG.debug("Validating message against {} encoding rules", rules.size());
 209  1004
                 for (EncodingRule rule : rules) {
 210  6
                         ValidationException[] ex = rule.apply(message);
 211  6
                         if (ex != null && ex.length > 0) {
 212  3
                                 handler.onExceptions(ex);
 213  
                         }
 214  6
                 }
 215  1004
                 return handler.result();
 216  
         }
 217  
 
 218  
         protected abstract ValidationContext getValidationContext();
 219  
 
 220  
         protected abstract ValidationExceptionHandler<R> initializeHandler();
 221  
 
 222  
 }