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