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}