Coverage Report - ca.uhn.hl7v2.util.SegmentFinder
 
Classes in this File Line Coverage Branch Coverage Complexity
SegmentFinder
93%
43/46
82%
23/28
3.375
 
 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 "SegmentFinder.java".  Description:
 10  
  * "A tool for getting segments by name within a message or part of a message."
 11  
  *
 12  
  * The Initial Developer of the Original Code is University Health Network. Copyright (C)
 13  
  * 2002.  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  
  */
 27  
 
 28  
 package ca.uhn.hl7v2.util;
 29  
 
 30  
 import ca.uhn.hl7v2.model.*;
 31  
 import ca.uhn.hl7v2.HL7Exception;
 32  
 import java.util.regex.*;
 33  
 
 34  
 /**
 35  
  * A tool for getting segments by name within a message or part of a message.
 36  
  * @author Bryan Tripp
 37  
  */
 38  
 public class SegmentFinder extends MessageNavigator {
 39  
 
 40  5
     private static final Pattern VALID_PATTERN_PATTERN = Pattern.compile("[\\w\\*\\?]*");
 41  5
     private static final Pattern LITERAL_UNBOUNDED = Pattern.compile("\\*");
 42  5
     private static final Pattern LITERAL_OPTIONAL = Pattern.compile("\\?");
 43  
 
 44  
     /**
 45  
      * Creates a new instance of SegmentFinder.
 46  
      * @param root the scope of searches -- may be a whole message or only a branch
 47  
      */
 48  
     public SegmentFinder(Group root) {
 49  10408
         super(root);
 50  10408
     }
 51  
     
 52  
     /**
 53  
      * Returns the first segment with a name that matches the given pattern, in a depth-first search.  
 54  
      * Repeated searches are initiated from the location just AFTER where the last segment was found.
 55  
      * Call reset() is this is not desired.  Note: this means that the current location will not be found.
 56  
      * @param namePattern the name of the segment to find.  The wildcard * means any number
 57  
      *      of arbitrary characters; the wildcard ? one arbitrary character
 58  
      *      (eg "P*" or "*ID" or "???" or "P??" would match on PID).
 59  
      * @param rep the repetition of the segment to return
 60  
      */
 61  
     public Segment findSegment(String namePattern, int rep) throws HL7Exception {
 62  1013
         Structure s = null;
 63  
         do {
 64  1013
             s = findStructure(namePattern, rep);
 65  1013
         } while (!Segment.class.isAssignableFrom(s.getClass()));
 66  1013
         return (Segment) s;
 67  
     }
 68  
     
 69  
     /**
 70  
      * As findSegment(), but will only return a group.
 71  
      */
 72  
     public Group findGroup(String namePattern, int rep) throws HL7Exception {
 73  
         Structure s;
 74  
         do {
 75  440
             s = findStructure(namePattern, rep);
 76  440
         } while (!Group.class.isAssignableFrom(s.getClass()));
 77  440
         return (Group) s;
 78  
     }
 79  
     
 80  
     /**
 81  
      * Returns the first matching structure AFTER the current position
 82  
      */
 83  
     private Structure findStructure(String namePattern, int rep) throws HL7Exception {
 84  1453
         Structure s = null;
 85  
         
 86  9901
         while (s == null) {
 87  8448
             String currentNameInParent = iterate(false, false);
 88  8448
             String currentName = getCurrentStructure(0).getName();
 89  8448
             if (matches(namePattern, currentName) || matches(namePattern, currentNameInParent)) {
 90  1453
                 s = getCurrentStructure(rep);
 91  
             }
 92  8448
         }
 93  1453
         return s;
 94  
     }
 95  
     
 96  
     /**
 97  
      * Returns the first segment with a name matching the given pattern that is a sibling of
 98  
      * the structure at the current location.  Other parts of the message are
 99  
      * not searched (in contrast to findSegment).
 100  
      * As a special case, if the pointer is at the root, the children of the root
 101  
      * are searched.
 102  
      * @param namePattern the name of the segment to get.  The wildcad * means any number
 103  
      *      of arbitrary characters; the wildard ? one arbitrary character
 104  
      *      (eg "P*" or "*ID" or "???" or "P??" would match on PID).
 105  
      * @param rep the repetition of the segment to return
 106  
      */
 107  
     public Segment getSegment(String namePattern, int rep) throws HL7Exception {
 108  18762
         Structure s = getStructure(namePattern, rep);
 109  18752
         if (!Segment.class.isAssignableFrom(s.getClass())) {
 110  0
             throw new HL7Exception(s.getName() + " is not a segment");
 111  
         }
 112  18752
         return (Segment) s;
 113  
     }
 114  
     
 115  
     /**
 116  
      * As getSegment() but will only return a group.
 117  
      */
 118  
     public Group getGroup(String namePattern, int rep) throws HL7Exception {
 119  410
         Structure s = getStructure(namePattern, rep);
 120  410
         if (!Group.class.isAssignableFrom(s.getClass())) {
 121  0
             throw new HL7Exception(s.getName() + " is not a group");
 122  
         }
 123  410
         return (Group) s;
 124  
     }
 125  
     
 126  
     private Structure getStructure(String namePattern, int rep) throws HL7Exception {
 127  19172
         Structure s = null;
 128  
         
 129  19172
         if (getCurrentStructure(0).equals(this.getRoot()))
 130  13359
             drillDown(0);
 131  
         
 132  19172
         String[] names = getCurrentStructure(0).getParent().getNames();
 133  40239
         for (int i = 0; i < names.length && s == null; i++) {
 134  21067
             if (matches(namePattern, names[i])) {
 135  19162
                 toChild(i);
 136  19162
                 s = getCurrentStructure(rep);
 137  
             }
 138  
         }
 139  
         
 140  19172
         if (s == null)
 141  10
             throw new HL7Exception("Can't find " + namePattern + " as a direct child");
 142  
         
 143  19162
         return s;
 144  
     }
 145  
     
 146  
     /**
 147  
      * Tests whether the given name matches the given pattern.
 148  
      */
 149  
     /*private boolean matches(String pattern, String candidate) {
 150  
         boolean matches = false;
 151  
         boolean substring = false;
 152  
         if (pattern.substring(0, 1).equals("*")) {
 153  
             substring = true;
 154  
             pattern = pattern.substring(1);
 155  
         }
 156  
         
 157  
         if (substring && (candidate.indexOf(pattern) >= 0)) {
 158  
             matches = true;
 159  
         } else if (!substring && candidate.equals(pattern)) {
 160  
             matches = true;
 161  
         }
 162  
         return matches;
 163  
     }*/
 164  
     
 165  
     /**
 166  
      * Tests whether the given name matches the given pattern.
 167  
      */
 168  
     private boolean matches(String pattern, String candidate) {
 169  
         //shortcut ...
 170  36515
         if (pattern.equals(candidate)) {
 171  20510
             return true;
 172  
         }
 173  16005
         if (!VALID_PATTERN_PATTERN.matcher(pattern).matches())
 174  0
             throw new IllegalArgumentException("The pattern " + pattern + " is not valid.  Only [\\w\\*\\?]* allowed.");
 175  16005
         pattern = LITERAL_UNBOUNDED.matcher(pattern).replaceAll(".*");
 176  16005
         pattern = LITERAL_OPTIONAL.matcher(pattern).replaceAll(".");
 177  16005
         return Pattern.matches(pattern, candidate);
 178  
     }
 179  
 }