001package ca.uhn.fhir.rest.param; 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 ca.uhn.fhir.context.FhirContext; 024import ca.uhn.fhir.i18n.Msg; 025import ca.uhn.fhir.model.api.IQueryParameterOr; 026import ca.uhn.fhir.model.api.TemporalPrecisionEnum; 027import ca.uhn.fhir.model.primitive.BaseDateTimeDt; 028import ca.uhn.fhir.model.primitive.DateDt; 029import ca.uhn.fhir.model.primitive.DateTimeDt; 030import ca.uhn.fhir.rest.api.QualifiedParamList; 031import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; 032import ca.uhn.fhir.util.ValidateUtil; 033import org.apache.commons.lang3.builder.ToStringBuilder; 034import org.apache.commons.lang3.builder.ToStringStyle; 035import org.hl7.fhir.instance.model.api.IPrimitiveType; 036 037import java.util.Collections; 038import java.util.Date; 039import java.util.List; 040import java.util.Objects; 041 042import static org.apache.commons.lang3.StringUtils.isNotBlank; 043 044public class DateParam extends BaseParamWithPrefix<DateParam> implements /*IQueryParameterType , */IQueryParameterOr<DateParam> { 045 046 private static final long serialVersionUID = 1L; 047 048 private final DateParamDateTimeHolder myValue = new DateParamDateTimeHolder(); 049 050 /** 051 * Constructor 052 */ 053 public DateParam() { 054 super(); 055 } 056 057 /** 058 * Constructor 059 */ 060 public DateParam(ParamPrefixEnum thePrefix, Date theDate) { 061 setPrefix(thePrefix); 062 setValue(theDate); 063 } 064 065 /** 066 * Constructor 067 */ 068 public DateParam(ParamPrefixEnum thePrefix, DateTimeDt theDate) { 069 setPrefix(thePrefix); 070 myValue.setValueAsString(theDate != null ? theDate.getValueAsString() : null); 071 } 072 073 /** 074 * Constructor 075 */ 076 public DateParam(ParamPrefixEnum thePrefix, IPrimitiveType<Date> theDate) { 077 setPrefix(thePrefix); 078 myValue.setValueAsString(theDate != null ? theDate.getValueAsString() : null); 079 } 080 081 /** 082 * Constructor 083 */ 084 public DateParam(ParamPrefixEnum thePrefix, long theDate) { 085 ValidateUtil.isGreaterThan(theDate, 0, "theDate must not be 0 or negative"); 086 setPrefix(thePrefix); 087 setValue(new Date(theDate)); 088 } 089 090 /** 091 * Constructor 092 */ 093 public DateParam(ParamPrefixEnum thePrefix, String theDate) { 094 setPrefix(thePrefix); 095 setValueAsString(theDate); 096 } 097 098 099 /** 100 * Constructor which takes a complete [qualifier]{date} string. 101 * 102 * @param theString 103 * The string 104 */ 105 public DateParam(String theString) { 106 setValueAsQueryToken(null, null, null, theString); 107 } 108 109 @Override 110 String doGetQueryParameterQualifier() { 111 return null; 112 } 113 114 @Override 115 String doGetValueAsQueryToken(FhirContext theContext) { 116 StringBuilder b = new StringBuilder(); 117 if (getPrefix() != null) { 118 b.append(ParameterUtil.escapeWithDefault(getPrefix().getValue())); 119 } 120 121 b.append(ParameterUtil.escapeWithDefault(myValue.getValueAsString())); 122 123 return b.toString(); 124 } 125 126 @Override 127 void doSetValueAsQueryToken(FhirContext theContext, String theParamName, String theQualifier, String theValue) { 128 setValueAsString(theValue); 129 } 130 131 public TemporalPrecisionEnum getPrecision() { 132 return myValue.getPrecision(); 133 } 134 135 public Date getValue() { 136 return myValue.getValue(); 137 } 138 139 public String getValueAsString() { 140 return myValue.getValueAsString(); 141 } 142 143 @Override 144 public List<DateParam> getValuesAsQueryTokens() { 145 return Collections.singletonList(this); 146 } 147 148 /** 149 * Returns <code>true</code> if no date/time is specified. Note that this method does not check the comparator, so a 150 * QualifiedDateParam with only a comparator and no date/time is considered empty. 151 */ 152 public boolean isEmpty() { 153 return myValue.isEmpty(); 154 } 155 156 /** 157 * Sets the value of the param to the given date (sets to the {@link TemporalPrecisionEnum#MILLI millisecond} 158 * precision, and will be encoded using the system local time zone). 159 */ 160 public DateParam setValue(Date theValue) { 161 myValue.setValue(theValue, TemporalPrecisionEnum.MILLI); 162 return this; 163 } 164 165 /** 166 * Sets the value using a FHIR Date type, such as a {@link DateDt}, or a DateTimeType. 167 */ 168 public void setValue(IPrimitiveType<Date> theValue) { 169 if (theValue != null) { 170 myValue.setValueAsString(theValue.getValueAsString()); 171 } else { 172 myValue.setValue(null); 173 } 174 } 175 176 /** 177 * Accepts values with or without a prefix (e.g. <code>gt2011-01-01</code> and <code>2011-01-01</code>). 178 * If no prefix is provided in the given value, the {@link #getPrefix() existing prefix} is preserved 179 */ 180 public void setValueAsString(String theDate) { 181 if (isNotBlank(theDate)) { 182 ParamPrefixEnum existingPrefix = getPrefix(); 183 myValue.setValueAsString(super.extractPrefixAndReturnRest(theDate)); 184 if (getPrefix() == null) { 185 setPrefix(existingPrefix); 186 } 187 } else { 188 myValue.setValue(null); 189 } 190 } 191 192 @Override 193 public void setValuesAsQueryTokens(FhirContext theContext, String theParamName, QualifiedParamList theParameters) { 194 setMissing(null); 195 setPrefix(null); 196 setValueAsString(null); 197 198 if (theParameters.size() == 1) { 199 setValueAsString(theParameters.get(0)); 200 } else if (theParameters.size() > 1) { 201 throw new InvalidRequestException(Msg.code(1939) + "This server does not support multi-valued dates for this parameter: " + theParameters); 202 } 203 204 } 205 206 @Override 207 public boolean equals(Object obj) { 208 if (obj == this) { 209 return true; 210 } 211 if (!(obj instanceof DateParam)) { 212 return false; 213 } 214 DateParam other = (DateParam) obj; 215 return Objects.equals(getValue(), other.getValue()) && 216 Objects.equals(getPrefix(), other.getPrefix()); 217 } 218 219 @Override 220 public int hashCode() { 221 return Objects.hash(getValue(), getPrefix()); 222 } 223 224 @Override 225 public String toString() { 226 ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE); 227 b.append("prefix", getPrefix()); 228 b.append("value", getValueAsString()); 229 return b.build(); 230 } 231 232 public static class DateParamDateTimeHolder extends BaseDateTimeDt { 233 234 /** 235 * Constructor 236 */ 237 // LEAVE THIS AS PUBLIC!! 238 @SuppressWarnings("WeakerAccess") 239 public DateParamDateTimeHolder() { 240 super(); 241 } 242 243 @Override 244 protected TemporalPrecisionEnum getDefaultPrecisionForDatatype() { 245 return TemporalPrecisionEnum.SECOND; 246 } 247 248 @Override 249 protected boolean isPrecisionAllowed(TemporalPrecisionEnum thePrecision) { 250 return true; 251 } 252 } 253}