001package org.hl7.fhir.dstu2016may.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
033import java.io.Externalizable;
034import java.io.IOException;
035import java.io.ObjectInput;
036import java.io.ObjectOutput;
037
038import org.apache.commons.lang3.StringUtils;
039import org.apache.commons.lang3.builder.EqualsBuilder;
040import org.apache.commons.lang3.builder.HashCodeBuilder;
041import org.hl7.fhir.instance.model.api.IBaseHasExtensions;
042import org.hl7.fhir.instance.model.api.IPrimitiveType;
043
044import ca.uhn.fhir.model.api.IElement;
045
046public abstract class PrimitiveType<T> extends Type implements IPrimitiveType<T>, IBaseHasExtensions, IElement, Externalizable {
047
048  private static final long serialVersionUID = 3L;
049
050  private T myCoercedValue;
051  private String myStringValue;
052
053  public String asStringValue() {
054    return myStringValue;
055  }
056
057  public abstract Type copy();
058
059  /**
060   * Subclasses must override to convert a "coerced" value into an encoded 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 String encode(T theValue);
067
068  @Override
069  public boolean equalsDeep(Base obj) {
070    if (!super.equalsDeep(obj))
071      return false;
072    if (obj == null) {
073      return false;
074    }
075    if (!(obj.getClass() == getClass())) {
076      return false;
077    }
078
079    PrimitiveType<?> o = (PrimitiveType<?>) obj;
080
081    EqualsBuilder b = new EqualsBuilder();
082    b.append(getValue(), o.getValue());
083    return b.isEquals();
084  }
085
086  @Override
087  public boolean equalsShallow(Base obj) {
088    if (obj == null) {
089      return false;
090    }
091    if (!(obj.getClass() == getClass())) {
092      return false;
093    }
094
095    PrimitiveType<?> o = (PrimitiveType<?>) obj;
096
097    EqualsBuilder b = new EqualsBuilder();
098    b.append(getValue(), o.getValue());
099    return b.isEquals();
100  }
101
102  public void fromStringValue(String theValue) {
103    myStringValue = theValue;
104    if (theValue == null) {
105      myCoercedValue = null;
106    } else {
107      // NB this might be null
108      myCoercedValue = parse(theValue);
109    }
110  }
111
112  public T getValue() {
113    return myCoercedValue;
114  }
115
116  public String getValueAsString() {
117    return asStringValue();
118  }
119
120  @Override
121  public int hashCode() {
122    return new HashCodeBuilder().append(getValue()).toHashCode();
123  }
124
125  public boolean hasValue() {
126    return !StringUtils.isBlank(getValueAsString());
127  }
128
129  @Override
130  public boolean isEmpty() {
131    return super.isEmpty() && StringUtils.isBlank(getValueAsString());
132  }
133
134  public boolean isPrimitive() {
135    return true;
136  }
137
138  /**
139   * Subclasses must override to convert an encoded representation of this datatype into a "coerced" one
140   *
141   * @param theValue
142   *            Will not be null
143   * @return May return null if the value does not correspond to anything
144   */
145  protected abstract T parse(String theValue);
146
147  public String primitiveValue() {
148    return asStringValue();
149  }
150
151  @Override
152  public void readExternal(ObjectInput theIn) throws IOException, ClassNotFoundException {
153    String object = (String) theIn.readObject();
154    setValueAsString(object);
155  }
156
157  public PrimitiveType<T> setValue(T theValue) {
158    myCoercedValue = theValue;
159    updateStringValue();
160    return this;
161  }
162
163  public void setValueAsString(String theValue) {
164    fromStringValue(theValue);
165  }
166
167  @Override
168  public String toString() {
169    return getClass().getSimpleName() + "[" + asStringValue() + "]";
170  }
171
172  protected Type typedCopy() {
173    return copy();
174  }
175
176  protected void updateStringValue() {
177    if (myCoercedValue == null) {
178      myStringValue = null;
179    } else {
180      // NB this might be null
181      myStringValue = encode(myCoercedValue);
182    }
183  }
184
185  @Override
186  public void writeExternal(ObjectOutput theOut) throws IOException {
187    theOut.writeObject(getValueAsString());
188  }
189
190}