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