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