001package org.hl7.fhir.dstu3.model; 002 003/* 004 Copyright (c) 2011+, HL7, Inc. 005 All rights reserved. 006 007 Redistribution and use in source and binary forms, with or without modification, 008 are permitted provided that the following conditions are met: 009 010 * Redistributions of source code must retain the above copyright notice, this 011 list of conditions and the following disclaimer. 012 * Redistributions in binary form must reproduce the above copyright notice, 013 this list of conditions and the following disclaimer in the documentation 014 and/or other materials provided with the distribution. 015 * Neither the name of HL7 nor the names of its contributors may be used to 016 endorse or promote products derived from this software without specific 017 prior written permission. 018 019 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 020 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 021 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 022 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 023 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 024 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 025 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 026 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 027 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 028 POSSIBILITY OF SUCH DAMAGE. 029 030 */ 031 032 033 034import java.io.Externalizable; 035import java.io.IOException; 036import java.io.ObjectInput; 037import java.io.ObjectOutput; 038 039import org.apache.commons.lang3.StringUtils; 040import org.apache.commons.lang3.builder.EqualsBuilder; 041import org.apache.commons.lang3.builder.HashCodeBuilder; 042import org.hl7.fhir.exceptions.FHIRException; 043import org.hl7.fhir.instance.model.api.IBaseHasExtensions; 044import org.hl7.fhir.instance.model.api.IPrimitiveType; 045 046import ca.uhn.fhir.model.api.IElement; 047 048public abstract class PrimitiveType<T> extends Type implements IPrimitiveType<T>, IBaseHasExtensions, IElement, Externalizable { 049 050 private static final long serialVersionUID = 3L; 051 052 private T myCoercedValue; 053 private String myStringValue; 054 055 public String asStringValue() { 056 return myStringValue; 057 } 058 059 public abstract Type copy(); 060 061 /** 062 * Subclasses must override to convert a "coerced" value into an encoded one. 063 * 064 * @param theValue 065 * Will not be null 066 * @return May return null if the value does not correspond to anything 067 */ 068 protected abstract String encode(T theValue); 069 070 @Override 071 public boolean equalsDeep(Base obj) { 072 if (!super.equalsDeep(obj)) 073 return false; 074 if (obj == null) { 075 return false; 076 } 077 if (!(obj.getClass() == getClass())) { 078 return false; 079 } 080 081 PrimitiveType<?> o = (PrimitiveType<?>) obj; 082 083 EqualsBuilder b = new EqualsBuilder(); 084 b.append(getValue(), o.getValue()); 085 return b.isEquals(); 086 } 087 088 @Override 089 public boolean equalsShallow(Base obj) { 090 if (obj == null) { 091 return false; 092 } 093 if (!(obj.getClass() == getClass())) { 094 return false; 095 } 096 097 PrimitiveType<?> o = (PrimitiveType<?>) obj; 098 099 EqualsBuilder b = new EqualsBuilder(); 100 b.append(getValue(), o.getValue()); 101 return b.isEquals(); 102 } 103 104 public void fromStringValue(String theValue) { 105 myStringValue = theValue; 106 if (theValue == null) { 107 myCoercedValue = null; 108 } else { 109 // NB this might be null 110 myCoercedValue = parse(theValue); 111 } 112 } 113 114 public T getValue() { 115 return myCoercedValue; 116 } 117 118 public String getValueAsString() { 119 return asStringValue(); 120 } 121 122 @Override 123 public int hashCode() { 124 return new HashCodeBuilder().append(getValue()).toHashCode(); 125 } 126 127 public boolean hasValue() { 128 return !StringUtils.isBlank(getValueAsString()); 129 } 130 131 @Override 132 public boolean isEmpty() { 133 return super.isEmpty() && StringUtils.isBlank(getValueAsString()); 134 } 135 136 public boolean isPrimitive() { 137 return true; 138 } 139 140 /** 141 * Subclasses must override to convert an encoded representation of this datatype into a "coerced" one 142 * 143 * @param theValue 144 * Will not be null 145 * @return May return null if the value does not correspond to anything 146 */ 147 protected abstract T parse(String theValue); 148 149 public String primitiveValue() { 150 return asStringValue(); 151 } 152 153 @Override 154 public void readExternal(ObjectInput theIn) throws IOException, ClassNotFoundException { 155 String object = (String) theIn.readObject(); 156 setValueAsString(object); 157 } 158 159 public PrimitiveType<T> setValue(T theValue) { 160 myCoercedValue = theValue; 161 updateStringValue(); 162 return this; 163 } 164 165 public void setValueAsString(String theValue) { 166 fromStringValue(theValue); 167 } 168 169 @Override 170 public String toString() { 171 return getClass().getSimpleName() + "[" + asStringValue() + "]"; 172 } 173 174 protected Type typedCopy() { 175 return copy(); 176 } 177 178 protected void updateStringValue() { 179 if (myCoercedValue == null) { 180 myStringValue = null; 181 } else { 182 // NB this might be null 183 myStringValue = encode(myCoercedValue); 184 } 185 } 186 187 @Override 188 public void writeExternal(ObjectOutput theOut) throws IOException { 189 theOut.writeObject(getValueAsString()); 190 } 191 192 @Override 193 public Base setProperty(int hash, String name, Base value) throws FHIRException { 194 switch (hash) { 195 case 111972721: // value 196 setValueAsString(value.toString()); 197 return value; 198 default: return super.setProperty(hash, name, value); 199 } 200 201 } 202 203 @Override 204 public Base setProperty(String name, Base value) throws FHIRException { 205 if (name.equals("value")) 206 setValueAsString(value.toString()); 207 else 208 return super.setProperty(name, value); 209 return value; 210 } 211 212 @Override 213 public Base[] getProperty(int hash, String name, boolean checkValid) throws FHIRException { 214 if (hash == 111972721) { 215 Base[] b = new Base[1]; 216 b[0] = new StringType(getValueAsString()); 217 return b; 218 } else 219 return super.getProperty(hash, name, checkValid); 220 } 221 @Override 222 public boolean hasPrimitiveValue() { 223 return StringUtils.isNotBlank(getValueAsString()); 224 } 225 226}