001package org.hl7.fhir.dstu3.model; 002 003import java.io.Externalizable; 004import java.io.IOException; 005import java.io.ObjectInput; 006import java.io.ObjectOutput; 007 008import org.apache.commons.lang3.StringUtils; 009import org.apache.commons.lang3.builder.EqualsBuilder; 010import org.apache.commons.lang3.builder.HashCodeBuilder; 011import org.hl7.fhir.instance.model.api.IBaseHasExtensions; 012import org.hl7.fhir.instance.model.api.IPrimitiveType; 013 014import ca.uhn.fhir.model.api.IElement; 015 016public abstract class PrimitiveType<T> extends Type implements IPrimitiveType<T>, IBaseHasExtensions, IElement, Externalizable { 017 018 private static final long serialVersionUID = 3L; 019 020 private T myCoercedValue; 021 private String myStringValue; 022 023 public String asStringValue() { 024 return myStringValue; 025 } 026 027 public abstract Type copy(); 028 029 /** 030 * Subclasses must override to convert a "coerced" value into an encoded one. 031 * 032 * @param theValue 033 * Will not be null 034 * @return May return null if the value does not correspond to anything 035 */ 036 protected abstract String encode(T theValue); 037 038 @Override 039 public boolean equalsDeep(Base obj) { 040 if (!super.equalsDeep(obj)) 041 return false; 042 if (obj == null) { 043 return false; 044 } 045 if (!(obj.getClass() == getClass())) { 046 return false; 047 } 048 049 PrimitiveType<?> o = (PrimitiveType<?>) obj; 050 051 EqualsBuilder b = new EqualsBuilder(); 052 b.append(getValue(), o.getValue()); 053 return b.isEquals(); 054 } 055 056 @Override 057 public boolean equalsShallow(Base obj) { 058 if (obj == null) { 059 return false; 060 } 061 if (!(obj.getClass() == getClass())) { 062 return false; 063 } 064 065 PrimitiveType<?> o = (PrimitiveType<?>) obj; 066 067 EqualsBuilder b = new EqualsBuilder(); 068 b.append(getValue(), o.getValue()); 069 return b.isEquals(); 070 } 071 072 public void fromStringValue(String theValue) { 073 myStringValue = theValue; 074 if (theValue == null) { 075 myCoercedValue = null; 076 } else { 077 // NB this might be null 078 myCoercedValue = parse(theValue); 079 } 080 } 081 082 public T getValue() { 083 return myCoercedValue; 084 } 085 086 public String getValueAsString() { 087 return asStringValue(); 088 } 089 090 @Override 091 public int hashCode() { 092 return new HashCodeBuilder().append(getValue()).toHashCode(); 093 } 094 095 public boolean hasValue() { 096 return !StringUtils.isBlank(getValueAsString()); 097 } 098 099 @Override 100 public boolean isEmpty() { 101 return super.isEmpty() && StringUtils.isBlank(getValueAsString()); 102 } 103 104 public boolean isPrimitive() { 105 return true; 106 } 107 108 /** 109 * Subclasses must override to convert an encoded representation of this datatype into a "coerced" one 110 * 111 * @param theValue 112 * Will not be null 113 * @return May return null if the value does not correspond to anything 114 */ 115 protected abstract T parse(String theValue); 116 117 public String primitiveValue() { 118 return asStringValue(); 119 } 120 121 @Override 122 public void readExternal(ObjectInput theIn) throws IOException, ClassNotFoundException { 123 String object = (String) theIn.readObject(); 124 setValueAsString(object); 125 } 126 127 public PrimitiveType<T> setValue(T theValue) { 128 myCoercedValue = theValue; 129 updateStringValue(); 130 return this; 131 } 132 133 public void setValueAsString(String theValue) { 134 fromStringValue(theValue); 135 } 136 137 @Override 138 public String toString() { 139 return getClass().getSimpleName() + "[" + asStringValue() + "]"; 140 } 141 142 protected Type typedCopy() { 143 return copy(); 144 } 145 146 protected void updateStringValue() { 147 if (myCoercedValue == null) { 148 myStringValue = null; 149 } else { 150 // NB this might be null 151 myStringValue = encode(myCoercedValue); 152 } 153 } 154 155 @Override 156 public void writeExternal(ObjectOutput theOut) throws IOException { 157 theOut.writeObject(getValueAsString()); 158 } 159 160}