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