001/* 002 * #%L 003 * HAPI FHIR - Core Library 004 * %% 005 * Copyright (C) 2014 - 2024 Smile CDR, Inc. 006 * %% 007 * Licensed under the Apache License, Version 2.0 (the "License"); 008 * you may not use this file except in compliance with the License. 009 * You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 * #L% 019 */ 020package ca.uhn.fhir.model.api; 021 022import ca.uhn.fhir.parser.DataFormatException; 023import org.apache.commons.lang3.StringUtils; 024import org.apache.commons.lang3.builder.EqualsBuilder; 025import org.apache.commons.lang3.builder.HashCodeBuilder; 026 027import java.io.Externalizable; 028import java.io.IOException; 029import java.io.ObjectInput; 030import java.io.ObjectOutput; 031 032public abstract class BasePrimitive<T> extends BaseIdentifiableElement 033 implements IPrimitiveDatatype<T>, Externalizable { 034 035 private T myCoercedValue; 036 private String myStringValue; 037 038 /** 039 * Subclasses must override to convert a "coerced" value into an encoded one. 040 * 041 * @param theValue 042 * Will not be null 043 * @return May return null if the value does not correspond to anything 044 */ 045 protected abstract String encode(T theValue); 046 047 @Override 048 public boolean equals(Object theObj) { 049 if (theObj == null) { 050 return false; 051 } 052 if (!(theObj.getClass() == getClass())) { 053 return false; 054 } 055 056 BasePrimitive<?> o = (BasePrimitive<?>) theObj; 057 058 EqualsBuilder b = new EqualsBuilder(); 059 b.append(getValue(), o.getValue()); 060 return b.isEquals(); 061 } 062 063 @Override 064 public T getValue() { 065 return myCoercedValue; 066 } 067 068 @Override 069 public String getValueAsString() throws DataFormatException { 070 return myStringValue; 071 } 072 073 @Override 074 public int hashCode() { 075 return new HashCodeBuilder().append(getValue()).toHashCode(); 076 } 077 078 @Override 079 public boolean isEmpty() { 080 return super.isBaseEmpty() && getValue() == null; 081 } 082 083 /** 084 * Subclasses must override to convert an encoded representation of this datatype into a "coerced" one 085 * 086 * @param theValue 087 * Will not be null 088 * @return May return null if the value does not correspond to anything 089 */ 090 protected abstract T parse(String theValue); 091 092 @Override 093 public void readExternal(ObjectInput theIn) throws IOException, ClassNotFoundException { 094 String object = (String) theIn.readObject(); 095 setValueAsString(object); 096 } 097 098 @Override 099 public BasePrimitive<T> setValue(T theValue) throws DataFormatException { 100 myCoercedValue = theValue; 101 updateStringValue(); 102 return this; 103 } 104 105 @Override 106 public void setValueAsString(String theValue) throws DataFormatException { 107 if (theValue == null) { 108 myCoercedValue = null; 109 } else { 110 // NB this might be null 111 myCoercedValue = parse(theValue); 112 } 113 myStringValue = theValue; 114 } 115 116 @Override 117 public String toString() { 118 return getClass().getSimpleName() + "[" + getValueAsString() + "]"; 119 } 120 121 protected void updateStringValue() { 122 if (myCoercedValue == null) { 123 myStringValue = null; 124 } else { 125 // NB this might be null 126 myStringValue = encode(myCoercedValue); 127 } 128 } 129 130 @Override 131 public void writeExternal(ObjectOutput theOut) throws IOException { 132 theOut.writeObject(getValueAsString()); 133 } 134 135 @Override 136 public boolean hasValue() { 137 return !StringUtils.isBlank(getValueAsString()); 138 } 139}