Coverage Report - ca.uhn.hl7v2.model.AbstractSegment
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractSegment
57%
106/184
54%
36/66
3.821
 
 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 "AbstractSegment.java".  Description: 
 10  
 "Provides common functionality needed by implementers of the Segment interface.
 11  
   Implementing classes should define all the fields for the segment they represent 
 12  
   in their constructor" 
 13  
 
 14  
 The Initial Developer of the Original Code is University Health Network. Copyright (C) 
 15  
 2001.  All Rights Reserved. 
 16  
 
 17  
 Contributor(s): ______________________________________. 
 18  
 
 19  
 Alternatively, the contents of this file may be used under the terms of the 
 20  
 GNU General Public License (the  �GPL�), in which case the provisions of the GPL are 
 21  
 applicable instead of those above.  If you wish to allow use of your version of this 
 22  
 file only under the terms of the GPL and not to allow others to use your version 
 23  
 of this file under the MPL, indicate your decision by deleting  the provisions above 
 24  
 and replace  them with the notice and other provisions required by the GPL License.  
 25  
 If you do not delete the provisions above, a recipient may use your version of 
 26  
 this file under either the MPL or the GPL. 
 27  
 
 28  
  */
 29  
 
 30  
 package ca.uhn.hl7v2.model;
 31  
 
 32  
 import java.lang.reflect.InvocationTargetException;
 33  
 import java.util.ArrayList;
 34  
 import java.util.List;
 35  
 
 36  
 import ca.uhn.hl7v2.HL7Exception;
 37  
 import ca.uhn.hl7v2.Location;
 38  
 import ca.uhn.hl7v2.parser.EncodingCharacters;
 39  
 import ca.uhn.hl7v2.parser.ModelClassFactory;
 40  
 
 41  
 /**
 42  
  * <p>
 43  
  * Provides common functionality needed by implementers of the Segment
 44  
  * interface.
 45  
  * </p>
 46  
  * <p>
 47  
  * Implementing classes should define all the fields for the segment they
 48  
  * represent in their constructor. The add() method is useful for this purpose.
 49  
  * </p>
 50  
  * <p>
 51  
  * For example the constructor for an MSA segment might contain the following
 52  
  * code:<br>
 53  
  * <code>this.add(new ID(), true, 2, null);<br>
 54  
  * this.add(new ST(), true, 20, null);<br>...</code>
 55  
  * </p>
 56  
  * 
 57  
  * @author Bryan Tripp (bryan_tripp@sourceforge.net)
 58  
  */
 59  
 public abstract class AbstractSegment extends AbstractStructure implements
 60  
                 Segment {
 61  
 
 62  
         /**
 63  
          * Do not use
 64  
          */
 65  
         static final String ERROR_MSH_1_OR_2_NOT_SET = "Can not invoke parse(String) on a segment if the encoding characters (MSH-1 and MSH-2) are not already correctly set on the message";
 66  
 
 67  
         private static final long serialVersionUID = -6686329916234746948L;
 68  
         
 69  
         private List<List<Type>> fields;
 70  
         private List<Class<? extends Type>> types;
 71  
         private List<Boolean> required;
 72  
         private List<Integer> length;
 73  
         private List<Object> args;
 74  
         private List<Integer> maxReps;
 75  
         private List<String> names;
 76  
 
 77  
         /**
 78  
          * Calls the abstract init() method to create the fields in this segment.
 79  
          * 
 80  
          * @param parent
 81  
          *            parent group
 82  
          * @param factory
 83  
          *            all implementors need a model class factory to find datatype
 84  
          *            classes, so we include it as an arg here to emphasize that
 85  
          *            fact ... AbstractSegment doesn't actually use it though
 86  
          */
 87  
         public AbstractSegment(Group parent, ModelClassFactory factory) {
 88  186906
                 super(parent);
 89  186906
                 this.fields = new ArrayList<List<Type>>();
 90  186906
                 this.types = new ArrayList<Class<? extends Type>>();
 91  186906
                 this.required = new ArrayList<Boolean>();
 92  186906
                 this.length = new ArrayList<Integer>();
 93  186906
                 this.args = new ArrayList<Object>();
 94  186906
                 this.maxReps = new ArrayList<Integer>();
 95  186906
                 this.names = new ArrayList<String>();
 96  186906
         }
 97  
 
 98  
     /**
 99  
      * Iterates over the contained fields and calls the visitor for each
 100  
      * of them.
 101  
      *
 102  
      * @param visitor MessageVisitor instance to be called back.
 103  
      * @param location location of the group
 104  
      * @return true if visiting shall continue, false if not
 105  
      * @throws HL7Exception
 106  
      */
 107  
     public boolean accept(MessageVisitor visitor, Location location) throws HL7Exception {
 108  80
         if (visitor.start(this, location)) {
 109  80
             String[] names = getNames();
 110  1935
             for (int i = 1; i <= names.length; i++) {
 111  1855
                 Field f = new Field(getField(i), getMaxCardinality(i));
 112  1855
                 Location nextLocation = f.provideLocation(location, i, -1);
 113  1855
                 if (!f.accept(visitor, nextLocation))
 114  0
                     break;
 115  
             }
 116  
         }
 117  80
         return visitor.end(this, location);
 118  
     }
 119  
 
 120  
         public Location provideLocation(Location location, int index, int repetition) {
 121  160
         return new Location(location)
 122  80
             .withSegmentName(getName())
 123  80
             .withSegmentRepetition(repetition);
 124  
     }
 125  
 
 126  
     /**
 127  
          * Returns an array of Field objects at the specified location in the
 128  
          * segment. In the case of non-repeating fields the array will be of length
 129  
          * one. Fields are numbered from 1.
 130  
          */
 131  
         public Type[] getField(int number) throws HL7Exception {
 132  333152
                 List<Type> retVal = getFieldAsList(number);
 133  333152
                 return retVal.toArray(new Type[retVal.size()]); // note: fields are
 134  
                                                                                                                 // numbered from 1 from
 135  
                                                                                                                 // the user's
 136  
                                                                                                                 // perspective
 137  
         }
 138  
 
 139  
         /**
 140  
          * @see ca.uhn.hl7v2.model.Segment#isEmpty()
 141  
          */
 142  
         public boolean isEmpty() throws HL7Exception {
 143  3870
                 for (int i = 1; i <= numFields(); i++) {
 144  3800
                         Type[] types = getField(i);
 145  3800
                         for (Type type : types) {
 146  695
                                 if (!type.isEmpty()) return false;
 147  
                         }
 148  
                 }
 149  70
                 return true;
 150  
         }
 151  
 
 152  
         /**
 153  
          * Returns an array of a specific type class
 154  
          */
 155  
         protected <T extends Type> T[] getTypedField(int number, T[] array) {
 156  
                 try {
 157  40
             List<Type> retVal = getFieldAsList(number);
 158  
                         @SuppressWarnings("unchecked")
 159  40
                         List<T> cast = (List<T>) retVal;
 160  40
                         return cast.toArray(array);
 161  0
         } catch (ClassCastException cce) {
 162  0
             log.error("Unexpected problem obtaining field value.  This is a bug.", cce);
 163  0
             throw new RuntimeException(cce);
 164  0
         } catch (HL7Exception he) {
 165  0
             log.error("Unexpected problem obtaining field value.  This is a bug.", he);
 166  0
             throw new RuntimeException(he);
 167  
         }
 168  
         }
 169  
                 
 170  
         
 171  
     protected int getReps(int number) { 
 172  
         try { 
 173  15
             return getFieldAsList(number).size();
 174  0
         } catch (HL7Exception he) {
 175  0
             log.error("Unexpected problem obtaining field value.  This is a bug.", he);
 176  0
             throw new RuntimeException(he);
 177  
         }           
 178  
     }        
 179  
 
 180  
         private List<Type> getFieldAsList(int number) throws HL7Exception {
 181  333207
                 ensureEnoughFields(number);
 182  
 
 183  333207
                 if (number < 1 || number > fields.size()) {
 184  0
                         throw new HL7Exception("Can't retrieve field " + number
 185  0
                                         + " from segment " + this.getClass().getName()
 186  0
                                         + " - there are only " + fields.size() + " fields.");
 187  
                 }
 188  
 
 189  333207
                 return fields.get(number - 1);
 190  
 
 191  
         }
 192  
 
 193  
         /**
 194  
          * Returns a specific repetition of field at the specified index. If there
 195  
          * exist fewer repetitions than are required, the number of repetitions can
 196  
          * be increased by specifying the lowest repetition that does not yet exist.
 197  
          * For example if there are two repetitions but three are needed, the third
 198  
          * can be created and accessed using the following code: <br>
 199  
          * <code>Type t = getField(x, 3);</code>
 200  
          * 
 201  
          * @param number
 202  
          *            the field number (starting at 1)
 203  
          * @param rep
 204  
          *            the repetition number (starting at 0)
 205  
          * @throws HL7Exception
 206  
          *             if field index is out of range, if the specified repetition
 207  
          *             is greater than the maximum allowed, or if the specified
 208  
          *             repetition is more than 1 greater than the existing # of
 209  
          *             repetitions.
 210  
          */
 211  
         public Type getField(int number, int rep) throws HL7Exception {
 212  
 
 213  158849
                 ensureEnoughFields(number);
 214  
 
 215  158849
                 if (number < 1 || number > fields.size()) {
 216  0
                         throw new HL7Exception("Can't get field " + number + " in segment "
 217  0
                                         + getName() + " - there are currently only "
 218  0
                                         + fields.size() + " reps.");
 219  
                 }
 220  
 
 221  158849
                 List<Type> arr = fields.get(number - 1);
 222  
 
 223  
                 // check if out of range ...
 224  158849
                 if (rep > arr.size())
 225  0
                         throw new HL7Exception("Can't get repetition " + rep
 226  
                                         + " from field " + number + " - there are currently only "
 227  0
                                         + arr.size() + " reps.");
 228  
 
 229  
                 // add a rep if necessary ...
 230  158849
                 if (rep == arr.size()) {
 231  102484
                         Type newType = createNewType(number);
 232  102484
                         arr.add(newType);
 233  
                 }
 234  
 
 235  158849
                 return arr.get(rep);
 236  
         }
 237  
 
 238  
         /**
 239  
          * Returns a specific repetition of field with concrete type at the specified index
 240  
          */
 241  
         protected <T extends Type> T getTypedField(int number, int rep) {
 242  
                 try {
 243  2210
                         @SuppressWarnings("unchecked") T retVal = (T)getField(number, rep);
 244  2210
                         return retVal;
 245  0
         } catch (ClassCastException cce) {
 246  0
             log.error("Unexpected problem obtaining field value.  This is a bug.", cce);
 247  0
             throw new RuntimeException(cce);
 248  0
         } catch (HL7Exception he) {
 249  0
             log.error("Unexpected problem obtaining field value.  This is a bug.", he);
 250  0
             throw new RuntimeException(he);
 251  
         }
 252  
         }
 253  
         
 254  
         /**
 255  
          * <p>
 256  
          * Attempts to create an instance of a field type without using reflection.
 257  
          * </p>
 258  
          * <p>
 259  
          * Note that the default implementation just returns <code>null</code>, and
 260  
          * it is not neccesary to override this method to provide any particular
 261  
          * behaviour. When a new field instance is needed within a segment, this
 262  
          * method is tried first, and if it returns <code>null</code>, reflection is
 263  
          * used instead. Implementations of this method is auto-generated by the
 264  
          * source generator module.
 265  
          * </p>
 266  
          * 
 267  
          * @return Returns a newly instantiated type, or <code>null</code> if not
 268  
          *         possible
 269  
          * @param field
 270  
          *            Field number - Note that this is zero indexed!
 271  
          */
 272  
         protected Type createNewTypeWithoutReflection(int field) {
 273  0
                 return null;
 274  
         }
 275  
 
 276  
         /**
 277  
          * Creates a new instance of the Type at the given field number in this
 278  
          * segment.
 279  
          */
 280  
         private Type createNewType(int field) throws HL7Exception {
 281  102494
                 Type retVal = createNewTypeWithoutReflection(field - 1);
 282  102494
                 if (retVal != null) {
 283  101914
                         return retVal;
 284  
                 }
 285  
 
 286  580
                 int number = field - 1;
 287  580
                 Class<? extends Type> c = this.types.get(number);
 288  
 
 289  
                 Type newType;
 290  
                 try {
 291  580
                         Object[] args = getArgs(number);
 292  580
                         Class<?>[] argClasses = new Class[args.length];
 293  1160
                         for (int i = 0; i < args.length; i++) {
 294  580
                                 if (args[i] instanceof Message) {
 295  580
                                         argClasses[i] = Message.class;
 296  
                                 } else {
 297  0
                                         argClasses[i] = args[i].getClass();
 298  
                                 }
 299  
                         }
 300  580
                         newType = c.getConstructor(argClasses).newInstance(args);
 301  0
                 } catch (IllegalAccessException iae) {
 302  0
                         throw new HL7Exception("Can't access class " + c.getName() + " ("
 303  0
                                         + iae.getClass().getName() + "): " + iae.getMessage());
 304  0
                 } catch (InstantiationException ie) {
 305  0
                         throw new HL7Exception("Can't instantiate class " + c.getName()
 306  0
                                         + " (" + ie.getClass().getName() + "): " + ie.getMessage());
 307  0
                 } catch (InvocationTargetException ite) {
 308  0
                         throw new HL7Exception("Can't instantiate class " + c.getName()
 309  0
                                         + " (" + ite.getClass().getName() + "): "
 310  0
                                         + ite.getMessage());
 311  0
                 } catch (NoSuchMethodException nme) {
 312  0
                         throw new HL7Exception("Can't instantiate class " + c.getName()
 313  0
                                         + " (" + nme.getClass().getName() + "): "
 314  0
                                         + nme.getMessage());
 315  580
                 }
 316  580
                 return newType;
 317  
         }
 318  
 
 319  
         // defaults to {this.getMessage}
 320  
         private Object[] getArgs(int fieldNum) {
 321  
                 Object[] result;
 322  
 
 323  580
                 Object o = this.args.get(fieldNum);
 324  580
                 if (o != null && o instanceof Object[]) {
 325  20
                         result = (Object[]) o;
 326  
                 } else {
 327  560
                         result = new Object[] { getMessage() };
 328  
                 }
 329  
 
 330  580
                 return result;
 331  
         }
 332  
 
 333  
         /**
 334  
          * Returns true if the given field is required in this segment - fields are
 335  
          * numbered from 1.
 336  
          * 
 337  
          * @throws HL7Exception
 338  
          *             if field index is out of range.
 339  
          */
 340  
         public boolean isRequired(int number) throws HL7Exception {
 341  0
                 if (number < 1 || number > required.size()) {
 342  0
                         throw new HL7Exception("Can't retrieve optionality of field "
 343  0
                                         + number + " from segment " + this.getClass().getName()
 344  0
                                         + " - there are only " + fields.size() + " fields.");
 345  
                 }
 346  
 
 347  
                 try {
 348  0
                         return required.get(number - 1);
 349  0
                 } catch (Exception e) {
 350  0
                         throw new HL7Exception("Can't retrieve optionality of field "
 351  0
                                         + number + ": " + e.getMessage());
 352  
                 }
 353  
         }
 354  
 
 355  
         /**
 356  
          * Returns the maximum length of the field at the given index, in characters
 357  
          * - fields are numbered from 1.
 358  
          * 
 359  
          * @throws HL7Exception
 360  
          *             if field index is out of range.
 361  
          */
 362  
         public int getLength(int number) throws HL7Exception {
 363  0
                 if (number < 1 || number > length.size()) {
 364  0
                         throw new HL7Exception("Can't retrieve max length of field "
 365  0
                                         + number + " from segment " + this.getClass().getName()
 366  0
                                         + " - there are only " + fields.size() + " fields.");
 367  
                 }
 368  
 
 369  
                 try {
 370  0
                         return length.get(number - 1); // fields #d from 1 to user
 371  0
                 } catch (Exception e) {
 372  0
                         throw new HL7Exception("Can't retrieve max length of field "
 373  0
                                         + number + ": " + e.getMessage());
 374  
                 }
 375  
 
 376  
         }
 377  
 
 378  
         /**
 379  
          * Returns the number of repetitions of this field that are allowed.
 380  
          * 
 381  
          * @throws HL7Exception
 382  
          *             if field index is out of range.
 383  
          */
 384  
         public int getMaxCardinality(int number) throws HL7Exception {
 385  1855
                 if (number < 1 || number > length.size()) {
 386  0
                         throw new HL7Exception("Can't retrieve cardinality of field "
 387  0
                                         + number + " from segment " + this.getClass().getName()
 388  0
                                         + " - there are only " + fields.size() + " fields.");
 389  
                 }
 390  
 
 391  
                 try {
 392  1855
                         return maxReps.get(number - 1); // fields #d from 1 to user
 393  0
                 } catch (Exception e) {
 394  0
                         throw new HL7Exception("Can't retrieve max repetitions of field "
 395  0
                                         + number + ": " + e.getMessage());
 396  
                 }
 397  
         }
 398  
 
 399  
         /**
 400  
          * @deprecated Use {@link #add(Class, boolean, int, int, Object[], String)}
 401  
          */
 402  
         protected void add(Class<? extends Type> c, boolean required, int maxReps,
 403  
                         int length, Object[] constructorArgs) throws HL7Exception {
 404  12285
                 add(c, required, maxReps, length, constructorArgs, null);
 405  12285
         }
 406  
 
 407  
         /**
 408  
          * Adds a field to the segment. The field is initially empty (zero
 409  
          * repetitions). The field number is sequential depending on previous add()
 410  
          * calls. Implementing classes should use the add() method in their
 411  
          * constructor in order to define fields in their segment.
 412  
          * 
 413  
          * @param c
 414  
          *            the class of the datatype for the field - this should inherit
 415  
          *            from {@link Type}
 416  
          * @param required
 417  
          *            whether a value for the field is required in order for the
 418  
          *            segment to be valid
 419  
          * @param maxReps
 420  
          *            The maximum number of repetitions for the field. Note that 0 implies that there is no
 421  
          *            limit, and 1 implies that the field may not repeat.
 422  
          * @param length
 423  
          *            the maximum length of each repetition of the field (in
 424  
          *            characters)
 425  
          * @param constructorArgs
 426  
          *            This parameter provides an array of objects that will be used 
 427  
          *            as constructor arguments
 428  
          *            if new instances of this class are created (use null for
 429  
          *            zero-arg constructor). To determine the appropriate value for
 430  
          *            this parameter, consult the javadoc for the specific datatype class
 431  
          *            passed to the first argument of this method, and provide an array
 432  
          *            which satisfies the requirements of its constructor. For example, most
 433  
          *            datatypes take a single {@link Message} argument in their constructor. 
 434  
          *            In that case, the appropriate value for this argument is as follows:
 435  
          *            <code>new Object[]{ getMessage() }</code>
 436  
          * @param name
 437  
          *            A textual description of the name of the field
 438  
          * @throws HL7Exception
 439  
          *             if the given class does not inherit from Type or if it can
 440  
          *             not be instantiated.
 441  
          */
 442  
         protected void add(Class<? extends Type> c, boolean required, int maxReps,
 443  
                         int length, Object[] constructorArgs, String name)
 444  
                         throws HL7Exception {
 445  3654667
                 List<Type> arr = new ArrayList<Type>();
 446  3654667
                 this.types.add(c);
 447  3654667
                 this.fields.add(arr);
 448  3654667
                 this.required.add(required);
 449  3654667
                 this.length.add(length);
 450  3654667
                 this.args.add(constructorArgs);
 451  3654667
                 this.maxReps.add(maxReps);
 452  3654667
                 this.names.add(name);
 453  3654667
         }
 454  
 
 455  
         /**
 456  
          * Called from getField(...) methods. If a field has been requested that
 457  
          * doesn't exist (eg getField(15) when only 10 fields in segment) adds
 458  
          * Varies fields to the end of the segment up to the required number.
 459  
          */
 460  
         private void ensureEnoughFields(int fieldRequested) {
 461  492056
                 int fieldsToAdd = fieldRequested - this.numFields();
 462  492056
                 if (fieldsToAdd < 0) {
 463  468559
                         fieldsToAdd = 0;
 464  
                 }
 465  
 
 466  
                 try {
 467  504341
                         for (int i = 0; i < fieldsToAdd; i++) {
 468  12285
                                 this.add(Varies.class, false, 0, 65536, null); // using 65536
 469  
                                                                                                                                 // following
 470  
                                                                                                                                 // example of
 471  
                                                                                                                                 // OBX-5
 472  
                         }
 473  0
                 } catch (HL7Exception e) {
 474  0
                         log.error(
 475  
                                         "Can't create additional generic fields to handle request for field "
 476  
                                                         + fieldRequested, e);
 477  492056
                 }
 478  492056
         }
 479  
 
 480  
         public static void main(String[] args) {
 481  
                 /*
 482  
                  * try { Message mess = new TestMessage(); MSH msh = new MSH(mess);
 483  
                  * 
 484  
                  * //get empty array Type[] ts = msh.getField(1);
 485  
                  * System.out.println("Got Type array of length " + ts.length);
 486  
                  * 
 487  
                  * //get first field Type t = msh.getField(1, 0);
 488  
                  * System.out.println("Got a Type of class " + t.getClass().getName());
 489  
                  * 
 490  
                  * //get array now Type[] ts2 = msh.getField(1);
 491  
                  * System.out.println("Got Type array of length " + ts2.length);
 492  
                  * 
 493  
                  * //set a value ST str = (ST)t; str.setValue("hello");
 494  
                  * 
 495  
                  * //get first field Type t2 = msh.getField(1, 0);
 496  
                  * System.out.println("Got a Type of class " + t.getClass().getName());
 497  
                  * System.out.println("It's value is " + ((ST)t2).getValue());
 498  
                  * 
 499  
                  * msh.getFieldSeparator().setValue("thing");
 500  
                  * System.out.println("Field Sep: " +
 501  
                  * msh.getFieldSeparator().getValue());
 502  
                  * 
 503  
                  * msh.getConformanceStatementID(0).setValue("ID 1");
 504  
                  * msh.getConformanceStatementID(1).setValue("ID 2");
 505  
                  * System.out.println("Conf ID #2: " +
 506  
                  * msh.getConformanceStatementID(1).getValue());
 507  
                  * 
 508  
                  * ID[] cid = msh.getConformanceStatementID();
 509  
                  * System.out.println("CID: " + cid); for (int i = 0; i < cid.length;
 510  
                  * i++) { System.out.println("Conf ID element: " + i + ": " +
 511  
                  * cid[i].getValue()); }
 512  
                  * msh.getConformanceStatementID(3).setValue("this should fail");
 513  
                  * 
 514  
                  * 
 515  
                  * } catch (HL7Exception e) { e.printStackTrace(); }
 516  
                  */
 517  0
         }
 518  
 
 519  
         /**
 520  
          * Returns the number of fields defined by this segment (repeating fields
 521  
          * are not counted multiple times).
 522  
          */
 523  
         public int numFields() {
 524  515493
                 return this.fields.size();
 525  
         }
 526  
 
 527  
         /**
 528  
          * Returns the class name (excluding package).
 529  
          * 
 530  
          * @see Structure#getName()
 531  
          */
 532  
         public String getName() {
 533  317393
                 String fullName = this.getClass().getName();
 534  634786
                 return fullName.substring(fullName.lastIndexOf('.') + 1,
 535  317393
                                 fullName.length());
 536  
         }
 537  
 
 538  
         /**
 539  
          * Sets the segment name. This would normally be called by a Parser.
 540  
          */
 541  
         /*
 542  
          * public void setName(String name) { this.name = name; }
 543  
          */
 544  
 
 545  
         /**
 546  
          * {@inheritDoc}
 547  
          */
 548  
         public String[] getNames() {
 549  80
                 return names.toArray(new String[names.size()]);
 550  
         }
 551  
 
 552  
         /**
 553  
          * {@inheritDoc }
 554  
          * 
 555  
          * <p>
 556  
          * <b>Note that this method will not currently work to parse an MSH segment
 557  
          * if the encoding characters are not already set. This limitation should be
 558  
          * resolved in a future version</b>
 559  
          * </p>
 560  
          */
 561  
         public void parse(String string) throws HL7Exception {
 562  2020
                 if (string == null) {
 563  5
                         throw new NullPointerException("String can not be null");
 564  
                 }
 565  
                 
 566  
                 EncodingCharacters encodingCharacters;
 567  
                 try {
 568  2015
                         encodingCharacters = EncodingCharacters.getInstance(getMessage());
 569  5
                 } catch (HL7Exception e) {
 570  5
                         throw new HL7Exception(ERROR_MSH_1_OR_2_NOT_SET);
 571  2010
                 }
 572  2010
                 clear();
 573  2010
                 getMessage().getParser().parse(this, string, encodingCharacters);
 574  2010
         }
 575  
 
 576  
         /**
 577  
          * {@inheritDoc }
 578  
          */
 579  
         public String encode() throws HL7Exception {
 580  3910
                 return getMessage().getParser().doEncode(this,
 581  1955
                                 EncodingCharacters.getInstance(getMessage()));
 582  
         }
 583  
 
 584  
         /**
 585  
          * Removes a repetition of a given field by name. For example, if a PID
 586  
          * segment contains 10 repetitions a "Patient Identifier List" field and
 587  
          * "Patient Identifier List" is supplied with an index of 2, then this call
 588  
          * would remove the 3rd repetition.
 589  
          * 
 590  
          * @return The removed structure
 591  
          * @throws HL7Exception
 592  
          *             if the named Structure is not part of this Group.
 593  
          */
 594  
     public Type removeRepetition(int fieldNum, int index)
 595  
                         throws HL7Exception {
 596  0
                 if (fieldNum < 1 || fieldNum > fields.size()) {
 597  0
                         throw new HL7Exception("The field " + fieldNum
 598  
                                         + " does not exist in the segment "
 599  0
                                         + this.getClass().getName());
 600  
                 }
 601  
 
 602  0
                 String name = names.get(fieldNum - 1);
 603  0
                 List<Type> list = fields.get(fieldNum - 1);
 604  0
                 if (list.size() == 0) {
 605  0
                         throw new HL7Exception("Invalid index: " + index + ", structure "
 606  
                                         + name + " has no repetitions");
 607  
                 }
 608  0
                 if (list.size() <= index) {
 609  0
                         throw new HL7Exception("Invalid index: " + index + ", structure "
 610  0
                                         + name + " must be between 0 and " + (list.size() - 1));
 611  
                 }
 612  
 
 613  0
                 return list.remove(index);
 614  
         }
 615  
 
 616  
         /**
 617  
          * Inserts a repetition of a given Field into repetitions of that field by
 618  
          * name.
 619  
          * 
 620  
          * @return The newly created and inserted field
 621  
          * @throws HL7Exception
 622  
          *             if the named Structure is not part of this Group.
 623  
          */
 624  
         public Type insertRepetition(int fieldNum, int index)
 625  
                         throws HL7Exception {
 626  10
                 if (fieldNum < 1 || fieldNum > fields.size()) {
 627  0
                         throw new HL7Exception("The field " + fieldNum
 628  
                                         + " does not exist in the segment "
 629  0
                                         + this.getClass().getName());
 630  
                 }
 631  
 
 632  10
                 List<Type> list = fields.get(fieldNum - 1);
 633  10
                 Type newType = createNewType(fieldNum);
 634  
 
 635  10
                 list.add(index, newType);
 636  
 
 637  10
                 return newType;
 638  
         }
 639  
 
 640  
         /**
 641  
          * Clears all data from this segment
 642  
          */
 643  
         public void clear() {
 644  2010
                 for (List<Type> next : fields) {
 645  45530
                         next.clear();
 646  45530
                 }
 647  2010
         }
 648  
 
 649  
 }