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 "Varies.java". Description: 010 "Varies is a Type used as a placeholder for another Type in cases where 011 the appropriate Type is not known until run-time (e.g" 012 013 The Initial Developer of the Original Code is University Health Network. Copyright (C) 014 2001. All Rights Reserved. 015 016 Contributor(s): ______________________________________. 017 018 Alternatively, the contents of this file may be used under the terms of the 019 GNU General Public License (the "GPL"), in which case the provisions of the GPL are 020 applicable instead of those above. If you wish to allow use of your version of this 021 file only under the terms of the GPL and not to allow others to use your version 022 of this file under the MPL, indicate your decision by deleting the provisions above 023 and replace them with the notice and other provisions required by the GPL License. 024 If you do not delete the provisions above, a recipient may use your version of 025 this file under either the MPL or the GPL. 026 027 */ 028 029 package ca.uhn.hl7v2.model; 030 031 import ca.uhn.hl7v2.HL7Exception; 032 import ca.uhn.hl7v2.parser.EncodingCharacters; 033 import ca.uhn.hl7v2.parser.ModelClassFactory; 034 import ca.uhn.log.HapiLog; 035 import ca.uhn.log.HapiLogFactory; 036 037 /** 038 * <p>Varies is a Type used as a placeholder for another Type in cases where 039 * the appropriate Type is not known until run-time (e.g. OBX-5). 040 * Parsers and validators may have logic that enforces restrictions on the 041 * Type based on other features of a segment.</p> 042 * <p>If you want to set both the type and the values of a Varies object, you should 043 * set the type first by calling setData(Type t), keeping a reference to your Type, 044 * and then set values by calling methods on the Type. Here is an example:</p> 045 * <p><code>CN cn = new CN();<br> 046 * variesObject.setData(cn);<br> 047 * cn.getIDNumber().setValue("foo");</code></p> 048 * 049 * @author Bryan Tripp (bryan_tripp@users.sourceforge.net) 050 * @author Andy Pardue 051 * 052 */ 053 public class Varies implements Type { 054 055 /** 056 * System property key. The value may be set to provide a default 057 * datatype ("ST", "NM", etc) for an OBX segment with a missing 058 * OBX-2 value. 059 */ 060 public static final String DEFAULT_OBX2_TYPE_PROP = "ca.uhn.hl7v2.model.varies.default_obx2_type"; 061 062 private static final HapiLog log = HapiLogFactory.getHapiLog(Varies.class); 063 064 private Type data; 065 private Message message; 066 067 /** 068 * Creates new Varies. 069 * 070 * @param message message to which this type belongs 071 */ 072 public Varies(Message message) { 073 data = new GenericPrimitive(message); 074 this.message = message; 075 } 076 077 /** 078 * Returns the data contained by this instance of Varies. Returns a GenericPrimitive unless 079 * setData() has been called. 080 */ 081 public Type getData() { 082 return this.data; 083 } 084 085 /** @see Type#getName */ 086 public String getName() { 087 String name = "*"; 088 if (this.data != null) { 089 name = this.data.getName(); 090 } 091 return name; 092 } 093 094 /** 095 * Sets the data contained by this instance of Varies. If a data object already exists, 096 * then its values are copied to the incoming data object before the old one is replaced. 097 * For example, if getData() returns an ST with the value "19901012" and you call 098 * setData(new DT()), then subsequent calls to getData() will return the same DT, with the value 099 * set to "19901012". 100 */ 101 public void setData(Type data) throws DataTypeException { 102 if (this.data != null) { 103 if (!(this.data instanceof Primitive) || ((Primitive) this.data).getValue() != null) { 104 ca.uhn.hl7v2.util.DeepCopy.copy(this.data, data); 105 } 106 } 107 this.data = data; 108 } 109 110 /** Returns extra components from the underlying Type */ 111 public ExtraComponents getExtraComponents() { 112 return this.data.getExtraComponents(); 113 } 114 115 /** 116 * @return the message to which this Type belongs 117 */ 118 public Message getMessage() { 119 return message; 120 } 121 122 /** 123 * Sets the data type of field 5 in the given OBX segment to the value of OBX-2. The argument 124 * is a Segment as opposed to a particular OBX because it is meant to work with any version. 125 */ 126 public static void fixOBX5(Segment segment, ModelClassFactory factory) throws HL7Exception { 127 try { 128 //get unqualified class name 129 Primitive obx2 = (Primitive) segment.getField(2, 0); 130 Type[] reps = segment.getField(5); 131 for (int i = 0; i < reps.length; i++) { 132 Varies v = (Varies)reps[i]; 133 134 // If we don't have a value for OBX-2, a default 135 // can be supplied via a System property 136 if (obx2.getValue() == null) { 137 String defaultOBX2Type = System.getProperty(DEFAULT_OBX2_TYPE_PROP); 138 if (defaultOBX2Type != null) { 139 log.debug("setting default obx2 type to " + defaultOBX2Type); 140 obx2.setValue(defaultOBX2Type); 141 } 142 } // if 143 144 if (obx2.getValue() == null) { 145 if (v.getData() != null) { 146 if (!(v.getData() instanceof Primitive) || ((Primitive) v.getData()).getValue() != null) { 147 throw new HL7Exception( 148 "OBX-5 is valued, but OBX-2 is not. A datatype for OBX-5 must be specified using OBX-2.", 149 HL7Exception.REQUIRED_FIELD_MISSING); 150 } 151 } 152 } 153 else { 154 //set class 155 String version = segment.getMessage().getVersion(); 156 String obx2Value = obx2.getValue(); 157 Class c = factory.getTypeClass(obx2Value, version); 158 // Class c = ca.uhn.hl7v2.parser.Parser.findClass(obx2.getValue(), 159 // segment.getMessage().getVersion(), 160 // "datatype"); 161 if (c == null) { 162 Primitive obx1 = (Primitive) segment.getField(1, 0); 163 HL7Exception h = new HL7Exception("\'" + 164 obx2.getValue() + "\' in record " + 165 obx1.getValue() + " is invalid for version " + version, 166 HL7Exception.DATA_TYPE_ERROR); 167 h.setSegmentName("OBX"); 168 h.setFieldPosition(2); 169 throw h; 170 } 171 v.setData((Type) c.getConstructor(new Class[]{Message.class}) 172 .newInstance(new Object[]{v.getMessage()})); 173 } 174 175 } // for reps 176 177 } 178 catch (HL7Exception e) { 179 throw e; 180 } 181 catch (Exception e) { 182 throw new HL7Exception( 183 e.getClass().getName() + " trying to set data type of OBX-5", 184 HL7Exception.APPLICATION_INTERNAL_ERROR, 185 e); 186 } 187 } 188 189 190 /** 191 * {@inheritDoc } 192 */ 193 public void parse(String string) throws HL7Exception { 194 getMessage().getParser().parse(this, string, EncodingCharacters.getInstance(getMessage())); 195 } 196 197 198 /** 199 * {@inheritDoc } 200 */ 201 public String encode() throws HL7Exception { 202 return getMessage().getParser().doEncode(this, EncodingCharacters.getInstance(getMessage())); 203 } 204 205 206 /** 207 * {@inheritDoc } 208 */ 209 public void clear() { 210 data.clear(); 211 } 212 213 }