rework ResourceIndexedSearchParamDate constructor to support incoming string values
This commit is contained in:
parent
13cc8b69aa
commit
3ec772b527
|
@ -65,6 +65,8 @@ public final class DateUtils {
|
||||||
@SuppressWarnings("WeakerAccess")
|
@SuppressWarnings("WeakerAccess")
|
||||||
public static final String PATTERN_ASCTIME = "EEE MMM d HH:mm:ss yyyy";
|
public static final String PATTERN_ASCTIME = "EEE MMM d HH:mm:ss yyyy";
|
||||||
|
|
||||||
|
private static final String PATTERN_INTEGER_DATE = "yyyyMMdd";
|
||||||
|
|
||||||
private static final String[] DEFAULT_PATTERNS = new String[]{
|
private static final String[] DEFAULT_PATTERNS = new String[]{
|
||||||
PATTERN_RFC1123,
|
PATTERN_RFC1123,
|
||||||
PATTERN_RFC1036,
|
PATTERN_RFC1036,
|
||||||
|
@ -173,8 +175,11 @@ public final class DateUtils {
|
||||||
public static int convertDatetoDayInteger(final Date theDateValue) {
|
public static int convertDatetoDayInteger(final Date theDateValue) {
|
||||||
notNull(theDateValue, "Date value");
|
notNull(theDateValue, "Date value");
|
||||||
Calendar cal = org.apache.commons.lang3.time.DateUtils.toCalendar(theDateValue);
|
Calendar cal = org.apache.commons.lang3.time.DateUtils.toCalendar(theDateValue);
|
||||||
|
SimpleDateFormat format = new SimpleDateFormat(PATTERN_INTEGER_DATE);
|
||||||
|
String theDateString = format.format(theDateValue);
|
||||||
|
|
||||||
String s = String.valueOf(cal.get(Calendar.YEAR)) + cal.get(Calendar.MONTH) + cal.get(Calendar.DAY_OF_MONTH);
|
String s = String.valueOf(cal.get(Calendar.YEAR)) + cal.get(Calendar.MONTH) + cal.get(Calendar.DAY_OF_MONTH);
|
||||||
return Integer.parseInt(s);
|
return Integer.parseInt(theDateString);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -3960,7 +3960,6 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
|
||||||
assertEquals(1, results.getResources(0, 10).size());
|
assertEquals(1, results.getResources(0, 10).size());
|
||||||
// We expect a new one because we don't cache the search URL for very long search URLs
|
// We expect a new one because we don't cache the search URL for very long search URLs
|
||||||
assertEquals(2, mySearchEntityDao.count());
|
assertEquals(2, mySearchEntityDao.count());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -4094,6 +4093,7 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
|
||||||
obs.setId(theId);
|
obs.setId(theId);
|
||||||
obs.setEffective(new DateTimeType(theEffective));
|
obs.setEffective(new DateTimeType(theEffective));
|
||||||
myObservationDao.update(obs);
|
myObservationDao.update(obs);
|
||||||
|
|
||||||
ourLog.info("Obs {} has time {}", theId, obs.getEffectiveDateTimeType().getValue().toString());
|
ourLog.info("Obs {} has time {}", theId, obs.getEffectiveDateTimeType().getValue().toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,264 @@
|
||||||
|
package ca.uhn.fhir.jpa.migrate.taskdef;
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* #%L
|
||||||
|
* HAPI FHIR JPA Server - Migration
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2014 - 2020 University Health Network
|
||||||
|
* %%
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
|
||||||
|
import ca.uhn.fhir.jpa.migrate.JdbcUtils;
|
||||||
|
import ca.uhn.fhir.util.StopWatch;
|
||||||
|
import ca.uhn.fhir.util.VersionEnum;
|
||||||
|
import com.google.common.collect.ForwardingMap;
|
||||||
|
import org.apache.commons.lang3.Validate;
|
||||||
|
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.jdbc.core.ColumnMapRowMapper;
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
import org.springframework.jdbc.core.RowCallbackHandler;
|
||||||
|
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.*;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public class CalculateOrdinalDateTask extends BaseTableColumnTask<CalculateOrdinalDateTask> {
|
||||||
|
|
||||||
|
private static final Logger ourLog = LoggerFactory.getLogger(CalculateOrdinalDateTask.class);
|
||||||
|
private int myBatchSize = 10000;
|
||||||
|
private Map<String, Function<MandatoryKeyMap<String, Object>, Long>> myCalculators = new HashMap<>();
|
||||||
|
private ThreadPoolExecutor myExecutor;
|
||||||
|
|
||||||
|
public void setBatchSize(int theBatchSize) {
|
||||||
|
myBatchSize = theBatchSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
public CalculateOrdinalDateTask(VersionEnum theRelease, String theVersion) {
|
||||||
|
super(theRelease.toString(), theVersion);
|
||||||
|
setDescription("Calculate resource search parameter index hashes");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void doExecute() throws SQLException {
|
||||||
|
if (isDryRun()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<String> tableNames = JdbcUtils.getTableNames(getConnectionProperties());
|
||||||
|
initializeExecutor();
|
||||||
|
try {
|
||||||
|
|
||||||
|
while(true) {
|
||||||
|
MyRowCallbackHandler rch = new MyRowCallbackHandler();
|
||||||
|
getTxTemplate().execute(t -> {
|
||||||
|
JdbcTemplate jdbcTemplate = newJdbcTemplate();
|
||||||
|
jdbcTemplate.setMaxRows(100000);
|
||||||
|
String sql = "SELECT * FROM " + getTableName() + " WHERE " + getColumnName() + " IS NULL";
|
||||||
|
logInfo(ourLog, "Finding up to {} rows in {} that requires hashes", myBatchSize, getTableName());
|
||||||
|
|
||||||
|
jdbcTemplate.query(sql, rch);
|
||||||
|
rch.done();
|
||||||
|
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
rch.submitNext();
|
||||||
|
List<Future<?>> futures = rch.getFutures();
|
||||||
|
if (futures.isEmpty()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
logInfo(ourLog, "Waiting for {} tasks to complete", futures.size());
|
||||||
|
for (Future<?> next : futures) {
|
||||||
|
try {
|
||||||
|
next.get();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new SQLException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
destroyExecutor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void destroyExecutor() {
|
||||||
|
myExecutor.shutdownNow();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initializeExecutor() {
|
||||||
|
int maximumPoolSize = Runtime.getRuntime().availableProcessors();
|
||||||
|
|
||||||
|
LinkedBlockingQueue<Runnable> executorQueue = new LinkedBlockingQueue<>(maximumPoolSize);
|
||||||
|
BasicThreadFactory threadFactory = new BasicThreadFactory.Builder()
|
||||||
|
.namingPattern("worker-" + "-%d")
|
||||||
|
.daemon(false)
|
||||||
|
.priority(Thread.NORM_PRIORITY)
|
||||||
|
.build();
|
||||||
|
RejectedExecutionHandler rejectedExecutionHandler = new RejectedExecutionHandler() {
|
||||||
|
@Override
|
||||||
|
public void rejectedExecution(Runnable theRunnable, ThreadPoolExecutor theExecutor) {
|
||||||
|
logInfo(ourLog, "Note: Executor queue is full ({} elements), waiting for a slot to become available!", executorQueue.size());
|
||||||
|
StopWatch sw = new StopWatch();
|
||||||
|
try {
|
||||||
|
executorQueue.put(theRunnable);
|
||||||
|
} catch (InterruptedException theE) {
|
||||||
|
throw new RejectedExecutionException("Task " + theRunnable.toString() +
|
||||||
|
" rejected from " + theE.toString());
|
||||||
|
}
|
||||||
|
logInfo(ourLog, "Slot become available after {}ms", sw.getMillis());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
myExecutor = new ThreadPoolExecutor(
|
||||||
|
1,
|
||||||
|
maximumPoolSize,
|
||||||
|
0L,
|
||||||
|
TimeUnit.MILLISECONDS,
|
||||||
|
executorQueue,
|
||||||
|
threadFactory,
|
||||||
|
rejectedExecutionHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Future<?> updateRows(List<Map<String, Object>> theRows) {
|
||||||
|
Runnable task = () -> {
|
||||||
|
StopWatch sw = new StopWatch();
|
||||||
|
getTxTemplate().execute(t -> {
|
||||||
|
|
||||||
|
// Loop through rows
|
||||||
|
assert theRows != null;
|
||||||
|
for (Map<String, Object> nextRow : theRows) {
|
||||||
|
|
||||||
|
Map<String, Long> newValues = new HashMap<>();
|
||||||
|
MandatoryKeyMap<String, Object> nextRowMandatoryKeyMap = new MandatoryKeyMap<>(nextRow);
|
||||||
|
|
||||||
|
// Apply calculators
|
||||||
|
for (Map.Entry<String, Function<MandatoryKeyMap<String, Object>, Long>> nextCalculatorEntry : myCalculators.entrySet()) {
|
||||||
|
String nextColumn = nextCalculatorEntry.getKey();
|
||||||
|
Function<MandatoryKeyMap<String, Object>, Long> nextCalculator = nextCalculatorEntry.getValue();
|
||||||
|
Long value = nextCalculator.apply(nextRowMandatoryKeyMap);
|
||||||
|
newValues.put(nextColumn, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate update SQL
|
||||||
|
StringBuilder sqlBuilder = new StringBuilder();
|
||||||
|
List<Number> arguments = new ArrayList<>();
|
||||||
|
sqlBuilder.append("UPDATE ");
|
||||||
|
sqlBuilder.append(getTableName());
|
||||||
|
sqlBuilder.append(" SET ");
|
||||||
|
for (Map.Entry<String, Long> nextNewValueEntry : newValues.entrySet()) {
|
||||||
|
if (arguments.size() > 0) {
|
||||||
|
sqlBuilder.append(", ");
|
||||||
|
}
|
||||||
|
sqlBuilder.append(nextNewValueEntry.getKey()).append(" = ?");
|
||||||
|
arguments.add(nextNewValueEntry.getValue());
|
||||||
|
}
|
||||||
|
sqlBuilder.append(" WHERE SP_ID = ?");
|
||||||
|
arguments.add((Number) nextRow.get("SP_ID"));
|
||||||
|
|
||||||
|
// Apply update SQL
|
||||||
|
newJdbcTemplate().update(sqlBuilder.toString(), arguments.toArray());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return theRows.size();
|
||||||
|
});
|
||||||
|
logInfo(ourLog, "Updated {} rows on {} in {}", theRows.size(), getTableName(), sw.toString());
|
||||||
|
};
|
||||||
|
return myExecutor.submit(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CalculateOrdinalDateTask addCalculator(String theColumnName, Function<MandatoryKeyMap<String, Object>, Long> theConsumer) {
|
||||||
|
Validate.isTrue(myCalculators.containsKey(theColumnName) == false);
|
||||||
|
myCalculators.put(theColumnName, theConsumer);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class MyRowCallbackHandler implements RowCallbackHandler {
|
||||||
|
|
||||||
|
private List<Map<String, Object>> myRows = new ArrayList<>();
|
||||||
|
private List<Future<?>> myFutures = new ArrayList<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void processRow(ResultSet rs) throws SQLException {
|
||||||
|
Map<String, Object> row = new ColumnMapRowMapper().mapRow(rs, 0);
|
||||||
|
myRows.add(row);
|
||||||
|
|
||||||
|
if (myRows.size() >= myBatchSize) {
|
||||||
|
submitNext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void submitNext() {
|
||||||
|
if (myRows.size() > 0) {
|
||||||
|
myFutures.add(updateRows(myRows));
|
||||||
|
myRows = new ArrayList<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Future<?>> getFutures() {
|
||||||
|
return myFutures;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void done() {
|
||||||
|
if (myRows.size() > 0) {
|
||||||
|
submitNext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class MandatoryKeyMap<K, V> extends ForwardingMap<K, V> {
|
||||||
|
|
||||||
|
private final Map<K, V> myWrap;
|
||||||
|
|
||||||
|
public MandatoryKeyMap(Map<K, V> theWrap) {
|
||||||
|
myWrap = theWrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V get(Object theKey) {
|
||||||
|
if (!containsKey(theKey)) {
|
||||||
|
throw new IllegalArgumentException("No key: " + theKey);
|
||||||
|
}
|
||||||
|
return super.get(theKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getString(String theKey) {
|
||||||
|
return (String) get(theKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Map<K, V> delegate() {
|
||||||
|
return myWrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getResourceType() {
|
||||||
|
return getString("RES_TYPE");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getParamName() {
|
||||||
|
return getString("SP_NAME");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -71,8 +71,14 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks<VersionEnum> {
|
||||||
//
|
//
|
||||||
|
|
||||||
// Add support for integer comparisons during day-granularity date search.
|
// Add support for integer comparisons during day-granularity date search.
|
||||||
version.onTable("HFJ_SPIDX_DATE").addColumn("20200225.1", "SP_VALUE_LOW_DATE_ORDINAL").nullable().type(BaseTableColumnTypeTask.ColumnTypeEnum.INT);
|
Builder.BuilderWithTableName spidxDate = version.onTable("HFJ_SPIDX_DATE");
|
||||||
version.onTable("HFJ_SPIDX_DATE").addColumn("20200225.1", "SP_VALUE_HIGH_DATE_ORDINAL").nullable().type(BaseTableColumnTypeTask.ColumnTypeEnum.INT);
|
spidxDate.addColumn("20200225.1", "SP_VALUE_LOW_DATE_ORDINAL").nullable().type(BaseTableColumnTypeTask.ColumnTypeEnum.INT);
|
||||||
|
spidxDate.addColumn("20200225.2", "SP_VALUE_HIGH_DATE_ORDINAL").nullable().type(BaseTableColumnTypeTask.ColumnTypeEnum.INT);
|
||||||
|
spidxDate.addTask(new CalculateHashesTask(VersionEnum.V4_3_0, "20200225.3")
|
||||||
|
.setColumnName("HASH_IDENTITY")
|
||||||
|
.addCalculator("SP_VALUE_LOW_DATE_ORDINAL", t -> BaseResourceIndexedSearchParam.calculateHashIdentity(t.getResourceType(), t.getString("SP_NAME")))
|
||||||
|
.addCalculator("SP_VALUE_HIGH_DATE_ORDINAL", t -> BaseResourceIndexedSearchParam.calculateHashIdentity(t.getResourceType(), t.getString("SP_NAME")))
|
||||||
|
);
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -88,24 +88,26 @@ public class ResourceIndexedSearchParamDate extends BaseResourceIndexedSearchPar
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
public ResourceIndexedSearchParamDate(String theResourceType, String theParamName, Date theLow, Date theHigh, String theOriginalValue) {
|
public ResourceIndexedSearchParamDate(String theResourceType, String theParamName, Date theLow, String theLowString, Date theHigh, String theHighString, String theOriginalValue) {
|
||||||
setResourceType(theResourceType);
|
setResourceType(theResourceType);
|
||||||
setParamName(theParamName);
|
setParamName(theParamName);
|
||||||
setValueLow(theLow);
|
setValueLow(theLow);
|
||||||
setValueHigh(theHigh);
|
setValueHigh(theHigh);
|
||||||
computeValueHighDateOrdinal(theHigh);
|
computeValueHighDateOrdinal(theHighString);
|
||||||
computeValueLowDateOrdinal(theLow);
|
computeValueLowDateOrdinal(theLowString);
|
||||||
myOriginalValue = theOriginalValue;
|
myOriginalValue = theOriginalValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void computeValueHighDateOrdinal(Date theHigh) {
|
private void computeValueHighDateOrdinal(String theHigh) {
|
||||||
this.myValueHighDateOrdinal = generateOrdinalDateInteger(theHigh);
|
this.myValueHighDateOrdinal = generateOrdinalDateInteger(theHigh);
|
||||||
}
|
}
|
||||||
private int generateOrdinalDateInteger(Date theDate) {
|
private int generateOrdinalDateInteger(String theDateString){
|
||||||
return ca.uhn.fhir.util.DateUtils.convertDatetoDayInteger(theDate);
|
String t = theDateString.substring(0, theDateString.indexOf("T"));
|
||||||
|
t = t.replace("-", "");
|
||||||
|
return Integer.valueOf(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void computeValueLowDateOrdinal(Date theLow) {
|
private void computeValueLowDateOrdinal(String theLow) {
|
||||||
this.myValueLowDateOrdinal = generateOrdinalDateInteger(theLow);
|
this.myValueLowDateOrdinal = generateOrdinalDateInteger(theLow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,8 +35,8 @@ public class ResourceIndexedSearchParamDateTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void equalsIsTrueForMatchingNullDates() {
|
public void equalsIsTrueForMatchingNullDates() {
|
||||||
ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate("Patient", "SomeResource", null, null, "SomeValue");
|
ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate("Patient", "SomeResource", null, null, null, null, "SomeValue");
|
||||||
ResourceIndexedSearchParamDate param2 = new ResourceIndexedSearchParamDate("Patient", "SomeResource", null, null, "SomeValue");
|
ResourceIndexedSearchParamDate param2 = new ResourceIndexedSearchParamDate("Patient", "SomeResource", null, null, null, null, "SomeValue");
|
||||||
|
|
||||||
assertTrue(param.equals(param2));
|
assertTrue(param.equals(param2));
|
||||||
assertTrue(param2.equals(param));
|
assertTrue(param2.equals(param));
|
||||||
|
@ -45,8 +45,8 @@ public class ResourceIndexedSearchParamDateTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void equalsIsTrueForMatchingDates() {
|
public void equalsIsTrueForMatchingDates() {
|
||||||
ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate("Patient", "SomeResource", date1A, date2A, "SomeValue");
|
ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate("Patient", "SomeResource", date1A, date1A.toString(), date2A, date2A.toString(), "SomeValue");
|
||||||
ResourceIndexedSearchParamDate param2 = new ResourceIndexedSearchParamDate("Patient", "SomeResource", date1B, date2B, "SomeValue");
|
ResourceIndexedSearchParamDate param2 = new ResourceIndexedSearchParamDate("Patient", "SomeResource", date1B, date1B.toString(), date2B, date2B.toString(), "SomeValue");
|
||||||
|
|
||||||
assertTrue(param.equals(param2));
|
assertTrue(param.equals(param2));
|
||||||
assertTrue(param2.equals(param));
|
assertTrue(param2.equals(param));
|
||||||
|
@ -55,8 +55,8 @@ public class ResourceIndexedSearchParamDateTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void equalsIsTrueForMatchingTimeStampsThatMatch() {
|
public void equalsIsTrueForMatchingTimeStampsThatMatch() {
|
||||||
ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate("Patient", "SomeResource", timestamp1A, timestamp2A, "SomeValue");
|
ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate("Patient", "SomeResource", timestamp1A, timestamp1A.toString(), timestamp2A, timestamp2A.toString(), "SomeValue");
|
||||||
ResourceIndexedSearchParamDate param2 = new ResourceIndexedSearchParamDate("Patient", "SomeResource", timestamp1B, timestamp2B, "SomeValue");
|
ResourceIndexedSearchParamDate param2 = new ResourceIndexedSearchParamDate("Patient", "SomeResource", timestamp1B, timestamp1B.toString(), timestamp2B, timestamp2B.toString(), "SomeValue");
|
||||||
|
|
||||||
assertTrue(param.equals(param2));
|
assertTrue(param.equals(param2));
|
||||||
assertTrue(param2.equals(param));
|
assertTrue(param2.equals(param));
|
||||||
|
@ -67,8 +67,8 @@ public class ResourceIndexedSearchParamDateTest {
|
||||||
// other will be equivalent but will be a java.sql.Timestamp. Equals should work in both directions.
|
// other will be equivalent but will be a java.sql.Timestamp. Equals should work in both directions.
|
||||||
@Test
|
@Test
|
||||||
public void equalsIsTrueForMixedTimestampsAndDates() {
|
public void equalsIsTrueForMixedTimestampsAndDates() {
|
||||||
ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate("Patient", "SomeResource", date1A, date2A, "SomeValue");
|
ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate("Patient", "SomeResource", date1A, date1A.toString(), date2A, date2A.toString(), "SomeValue");
|
||||||
ResourceIndexedSearchParamDate param2 = new ResourceIndexedSearchParamDate("Patient", "SomeResource", timestamp1A, timestamp2A, "SomeValue");
|
ResourceIndexedSearchParamDate param2 = new ResourceIndexedSearchParamDate("Patient", "SomeResource", timestamp1A, timestamp1A.toString(), timestamp2A, timestamp2A.toString(), "SomeValue");
|
||||||
|
|
||||||
assertTrue(param.equals(param2));
|
assertTrue(param.equals(param2));
|
||||||
assertTrue(param2.equals(param));
|
assertTrue(param2.equals(param));
|
||||||
|
@ -77,8 +77,8 @@ public class ResourceIndexedSearchParamDateTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void equalsIsFalseForNonMatchingDates() {
|
public void equalsIsFalseForNonMatchingDates() {
|
||||||
ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate("Patient", "SomeResource", date1A, date2A, "SomeValue");
|
ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate("Patient", "SomeResource", date1A, date1A.toString(), date2A, date2A.toString(), "SomeValue");
|
||||||
ResourceIndexedSearchParamDate param2 = new ResourceIndexedSearchParamDate("Patient", "SomeResource", date2A, date1A, "SomeValue");
|
ResourceIndexedSearchParamDate param2 = new ResourceIndexedSearchParamDate("Patient", "SomeResource", date2A, date2A.toString(), date1A, date1A.toString(), "SomeValue");
|
||||||
|
|
||||||
assertFalse(param.equals(param2));
|
assertFalse(param.equals(param2));
|
||||||
assertFalse(param2.equals(param));
|
assertFalse(param2.equals(param));
|
||||||
|
@ -87,8 +87,8 @@ public class ResourceIndexedSearchParamDateTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void equalsIsFalseForNonMatchingDatesNullCase() {
|
public void equalsIsFalseForNonMatchingDatesNullCase() {
|
||||||
ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate("Patient", "SomeResource", date1A, date2A, "SomeValue");
|
ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate("Patient", "SomeResource", date1A, date1A.toString(), date2A, date2A.toString(), "SomeValue");
|
||||||
ResourceIndexedSearchParamDate param2 = new ResourceIndexedSearchParamDate("Patient", "SomeResource", null, null, "SomeValue");
|
ResourceIndexedSearchParamDate param2 = new ResourceIndexedSearchParamDate("Patient", "SomeResource", null, null, null, null, "SomeValue");
|
||||||
|
|
||||||
assertFalse(param.equals(param2));
|
assertFalse(param.equals(param2));
|
||||||
assertFalse(param2.equals(param));
|
assertFalse(param2.equals(param));
|
||||||
|
@ -97,8 +97,8 @@ public class ResourceIndexedSearchParamDateTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void equalsIsFalseForNonMatchingTimeStamps() {
|
public void equalsIsFalseForNonMatchingTimeStamps() {
|
||||||
ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate("Patient", "SomeResource", timestamp1A, timestamp2A, "SomeValue");
|
ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate("Patient", "SomeResource", timestamp1A, timestamp1A.toString(), timestamp2A, timestamp2A.toString(), "SomeValue");
|
||||||
ResourceIndexedSearchParamDate param2 = new ResourceIndexedSearchParamDate("Patient", "SomeResource", timestamp2A, timestamp1A, "SomeValue");
|
ResourceIndexedSearchParamDate param2 = new ResourceIndexedSearchParamDate("Patient", "SomeResource", timestamp2A, timestamp2A.toString(), timestamp1A, timestamp1A.toString(), "SomeValue");
|
||||||
|
|
||||||
assertFalse(param.equals(param2));
|
assertFalse(param.equals(param2));
|
||||||
assertFalse(param2.equals(param));
|
assertFalse(param2.equals(param));
|
||||||
|
@ -107,8 +107,8 @@ public class ResourceIndexedSearchParamDateTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void equalsIsFalseForMixedTimestampsAndDatesThatDoNotMatch() {
|
public void equalsIsFalseForMixedTimestampsAndDatesThatDoNotMatch() {
|
||||||
ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate("Patient", "SomeResource", date1A, date2A, "SomeValue");
|
ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate("Patient", "SomeResource", date1A, date1A.toString(), date2A, date2A.toString(), "SomeValue");
|
||||||
ResourceIndexedSearchParamDate param2 = new ResourceIndexedSearchParamDate("Patient", "SomeResource", timestamp2A, timestamp1A, "SomeValue");
|
ResourceIndexedSearchParamDate param2 = new ResourceIndexedSearchParamDate("Patient", "SomeResource", timestamp2A, timestamp2A.toString(), timestamp1A, timestamp1A.toString(), "SomeValue");
|
||||||
|
|
||||||
assertFalse(param.equals(param2));
|
assertFalse(param.equals(param2));
|
||||||
assertFalse(param2.equals(param));
|
assertFalse(param2.equals(param));
|
||||||
|
|
|
@ -605,9 +605,10 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
||||||
Date start = extractValueAsDate(myPeriodStartValueChild, theValue);
|
Date start = extractValueAsDate(myPeriodStartValueChild, theValue);
|
||||||
String startAsString = extractValueAsString(myPeriodStartValueChild, theValue);
|
String startAsString = extractValueAsString(myPeriodStartValueChild, theValue);
|
||||||
Date end = extractValueAsDate(myPeriodEndValueChild, theValue);
|
Date end = extractValueAsDate(myPeriodEndValueChild, theValue);
|
||||||
|
String endAsString = extractValueAsString(myPeriodEndValueChild, theValue);
|
||||||
|
|
||||||
if (start != null || end != null) {
|
if (start != null || end != null) {
|
||||||
ResourceIndexedSearchParamDate nextEntity = new ResourceIndexedSearchParamDate(theResourceType, theSearchParam.getName(), start, end, startAsString);
|
ResourceIndexedSearchParamDate nextEntity = new ResourceIndexedSearchParamDate(theResourceType, theSearchParam.getName(), start, startAsString, end, endAsString, startAsString);
|
||||||
theParams.add(nextEntity);
|
theParams.add(nextEntity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -616,13 +617,17 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
||||||
List<IPrimitiveType<Date>> values = extractValuesAsFhirDates(myTimingEventValueChild, theValue);
|
List<IPrimitiveType<Date>> values = extractValuesAsFhirDates(myTimingEventValueChild, theValue);
|
||||||
|
|
||||||
TreeSet<Date> dates = new TreeSet<>();
|
TreeSet<Date> dates = new TreeSet<>();
|
||||||
|
TreeSet<String> dateStrings = new TreeSet<>();
|
||||||
String firstValue = null;
|
String firstValue = null;
|
||||||
|
String finalValue = null;
|
||||||
for (IPrimitiveType<Date> nextEvent : values) {
|
for (IPrimitiveType<Date> nextEvent : values) {
|
||||||
if (nextEvent.getValue() != null) {
|
if (nextEvent.getValue() != null) {
|
||||||
dates.add(nextEvent.getValue());
|
dates.add(nextEvent.getValue());
|
||||||
|
|
||||||
if (firstValue == null) {
|
if (firstValue == null) {
|
||||||
firstValue = nextEvent.getValueAsString();
|
firstValue = nextEvent.getValueAsString();
|
||||||
}
|
}
|
||||||
|
finalValue = nextEvent.getValueAsString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -634,14 +639,16 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
||||||
if ("Period".equals(boundsType)) {
|
if ("Period".equals(boundsType)) {
|
||||||
Date start = extractValueAsDate(myPeriodStartValueChild, bounds.get());
|
Date start = extractValueAsDate(myPeriodStartValueChild, bounds.get());
|
||||||
Date end = extractValueAsDate(myPeriodEndValueChild, bounds.get());
|
Date end = extractValueAsDate(myPeriodEndValueChild, bounds.get());
|
||||||
|
String endString = extractValueAsString(myPeriodEndValueChild, bounds.get());
|
||||||
dates.add(start);
|
dates.add(start);
|
||||||
dates.add(end);
|
dates.add(end);
|
||||||
|
finalValue = endString;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dates.isEmpty()) {
|
if (!dates.isEmpty()) {
|
||||||
ResourceIndexedSearchParamDate nextEntity = new ResourceIndexedSearchParamDate(theResourceType, theSearchParam.getName(), dates.first(), dates.last(), firstValue);
|
ResourceIndexedSearchParamDate nextEntity = new ResourceIndexedSearchParamDate(theResourceType, theSearchParam.getName(), dates.first(), firstValue, dates.last(), finalValue, firstValue);
|
||||||
theParams.add(nextEntity);
|
theParams.add(nextEntity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -828,7 +835,7 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
||||||
private void addDateTimeTypes(String theResourceType, Set<ResourceIndexedSearchParamDate> theParams, RuntimeSearchParam theSearchParam, IBase theValue) {
|
private void addDateTimeTypes(String theResourceType, Set<ResourceIndexedSearchParamDate> theParams, RuntimeSearchParam theSearchParam, IBase theValue) {
|
||||||
IPrimitiveType<Date> nextBaseDateTime = (IPrimitiveType<Date>) theValue;
|
IPrimitiveType<Date> nextBaseDateTime = (IPrimitiveType<Date>) theValue;
|
||||||
if (nextBaseDateTime.getValue() != null) {
|
if (nextBaseDateTime.getValue() != null) {
|
||||||
ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate(theResourceType, theSearchParam.getName(), nextBaseDateTime.getValue(), nextBaseDateTime.getValue(), nextBaseDateTime.getValueAsString());
|
ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate(theResourceType, theSearchParam.getName(), nextBaseDateTime.getValue(), nextBaseDateTime.getValueAsString(), nextBaseDateTime.getValue(), nextBaseDateTime.getValueAsString(), nextBaseDateTime.getValueAsString());
|
||||||
theParams.add(param);
|
theParams.add(param);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -208,7 +208,7 @@ public class InMemoryResourceMatcherR5Test {
|
||||||
private ResourceIndexedSearchParams extractDateSearchParam(Observation theObservation) {
|
private ResourceIndexedSearchParams extractDateSearchParam(Observation theObservation) {
|
||||||
ResourceIndexedSearchParams retval = new ResourceIndexedSearchParams();
|
ResourceIndexedSearchParams retval = new ResourceIndexedSearchParams();
|
||||||
BaseDateTimeType dateValue = (BaseDateTimeType) theObservation.getEffective();
|
BaseDateTimeType dateValue = (BaseDateTimeType) theObservation.getEffective();
|
||||||
ResourceIndexedSearchParamDate dateParam = new ResourceIndexedSearchParamDate("Patient", "date", dateValue.getValue(), dateValue.getValue(), dateValue.getValueAsString());
|
ResourceIndexedSearchParamDate dateParam = new ResourceIndexedSearchParamDate("Patient", "date", dateValue.getValue(), dateValue.getValueAsString(), dateValue.getValue(), dateValue.getValueAsString(), dateValue.getValueAsString());
|
||||||
retval.myDateParams.add(dateParam);
|
retval.myDateParams.add(dateParam);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue