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