diff --git a/service/src/main/java/edu/harvard/hms/dbmi/avillach/hpds/service/PicSureService.java b/service/src/main/java/edu/harvard/hms/dbmi/avillach/hpds/service/PicSureService.java index a0606f0a..7a850dd2 100644 --- a/service/src/main/java/edu/harvard/hms/dbmi/avillach/hpds/service/PicSureService.java +++ b/service/src/main/java/edu/harvard/hms/dbmi/avillach/hpds/service/PicSureService.java @@ -12,9 +12,8 @@ import javax.ws.rs.core.Response.Status; import edu.harvard.hms.dbmi.avillach.hpds.service.filesharing.FileSharingService; -import edu.harvard.hms.dbmi.avillach.hpds.service.filesharing.FileSystemService; import edu.harvard.hms.dbmi.avillach.hpds.service.util.Paginator; -import edu.harvard.hms.dbmi.avillach.hpds.service.util.QueryUUIDGen; +import edu.harvard.hms.dbmi.avillach.hpds.service.util.QueryDecorator; import org.apache.http.entity.ContentType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -30,7 +29,6 @@ import edu.harvard.dbmi.avillach.domain.*; import edu.harvard.dbmi.avillach.service.IResourceRS; -import edu.harvard.dbmi.avillach.util.UUIDv5; import edu.harvard.hms.dbmi.avillach.hpds.crypto.Crypto; import edu.harvard.hms.dbmi.avillach.hpds.data.genotype.FileBackedByteIndexedInfoStore; import edu.harvard.hms.dbmi.avillach.hpds.data.phenotype.ColumnMeta; @@ -47,7 +45,7 @@ public class PicSureService implements IResourceRS { @Autowired public PicSureService(QueryService queryService, TimelineProcessor timelineProcessor, CountProcessor countProcessor, VariantListProcessor variantListProcessor, AbstractProcessor abstractProcessor, - Paginator paginator, FileSharingService fileSystemService, QueryUUIDGen queryUUIDGen + Paginator paginator, FileSharingService fileSystemService, QueryDecorator queryDecorator ) { this.queryService = queryService; this.timelineProcessor = timelineProcessor; @@ -56,7 +54,7 @@ public PicSureService(QueryService queryService, TimelineProcessor timelineProce this.abstractProcessor = abstractProcessor; this.paginator = paginator; this.fileSystemService = fileSystemService; - this.queryUUIDGen = queryUUIDGen; + this.queryDecorator = queryDecorator; Crypto.loadDefaultKey(); } @@ -78,7 +76,7 @@ public PicSureService(QueryService queryService, TimelineProcessor timelineProce private final FileSharingService fileSystemService; - private final QueryUUIDGen queryUUIDGen; + private final QueryDecorator queryDecorator; private static final String QUERY_METADATA_FIELD = "queryMetadata"; private static final int RESPONSE_CACHE_SIZE = 50; @@ -228,7 +226,7 @@ private QueryStatus convertToQueryStatus(AsyncResult entity) { status.setStatus(entity.status.toPicSureStatus()); Map metadata = new HashMap(); - queryUUIDGen.setId(entity.query); + queryDecorator.setId(entity.query); metadata.put("picsureQueryId", entity.query.getId()); status.setResultMetadata(metadata); return status; @@ -271,7 +269,7 @@ public Response writeQueryResult( // query IDs within HPDS are a different concept that query IDs in PIC-SURE // Generally, equivalent queries with different PIC-SURE query IDs will have the SAME // HPDS query ID. - queryUUIDGen.setId(query); + queryDecorator.setId(query); AsyncResult result = queryService.getResultFor(query.getId()); // the queryResult has this DIY retry logic that blocks a system thread. // I'm not going to do that here. If the service can't find it, you get a 404. @@ -433,7 +431,7 @@ private Response _querySync(QueryRequest resultRequest) throws IOException { } private ResponseBuilder queryOkResponse(Object obj, Query incomingQuery) { - queryUUIDGen.setId(incomingQuery); + queryDecorator.setId(incomingQuery); return Response.ok(obj).header(QUERY_METADATA_FIELD, incomingQuery.getId()); } } diff --git a/service/src/main/java/edu/harvard/hms/dbmi/avillach/hpds/service/QueryService.java b/service/src/main/java/edu/harvard/hms/dbmi/avillach/hpds/service/QueryService.java index 7d3ec69f..2940b1b8 100644 --- a/service/src/main/java/edu/harvard/hms/dbmi/avillach/hpds/service/QueryService.java +++ b/service/src/main/java/edu/harvard/hms/dbmi/avillach/hpds/service/QueryService.java @@ -7,13 +7,10 @@ import java.util.function.Predicate; import java.util.stream.Collectors; -import edu.harvard.hms.dbmi.avillach.hpds.service.util.QueryUUIDGen; +import edu.harvard.hms.dbmi.avillach.hpds.service.util.QueryDecorator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.common.collect.ImmutableMap; - -import edu.harvard.dbmi.avillach.util.UUIDv5; import edu.harvard.hms.dbmi.avillach.hpds.data.query.Query; import edu.harvard.hms.dbmi.avillach.hpds.processing.*; import edu.harvard.hms.dbmi.avillach.hpds.processing.AsyncResult.Status; @@ -42,7 +39,7 @@ public class QueryService { private final QueryProcessor queryProcessor; private final TimeseriesProcessor timeseriesProcessor; private final CountProcessor countProcessor; - private final QueryUUIDGen queryUUIDGen; + private final QueryDecorator queryDecorator; HashMap results = new HashMap<>(); @@ -50,13 +47,13 @@ public class QueryService { @Autowired public QueryService ( AbstractProcessor abstractProcessor, QueryProcessor queryProcessor, TimeseriesProcessor timeseriesProcessor, - CountProcessor countProcessor, QueryUUIDGen queryUUIDGen + CountProcessor countProcessor, QueryDecorator queryDecorator ) { this.abstractProcessor = abstractProcessor; this.queryProcessor = queryProcessor; this.timeseriesProcessor = timeseriesProcessor; this.countProcessor = countProcessor; - this.queryUUIDGen = queryUUIDGen; + this.queryDecorator = queryDecorator; SMALL_JOB_LIMIT = getIntProp("SMALL_JOB_LIMIT"); SMALL_TASK_THREADS = getIntProp("SMALL_TASK_THREADS"); @@ -75,7 +72,6 @@ public QueryService ( public AsyncResult runQuery(Query query) throws ClassNotFoundException, IOException { // Merging fields from filters into selected fields for user validation of results - mergeFilterFieldsIntoSelectedFields(query); Collections.sort(query.getFields()); @@ -126,38 +122,13 @@ private AsyncResult initializeResult(Query query) throws ClassNotFoundException, AsyncResult result = new AsyncResult(query, p.getHeaderRow(query)); result.status = AsyncResult.Status.PENDING; result.queuedTime = System.currentTimeMillis(); - queryUUIDGen.setId(query); + queryDecorator.setId(query); result.id = query.getId(); result.processor = p; - queryUUIDGen.setId(query); + queryDecorator.setId(query); results.put(result.id, result); return result; } - - - private void mergeFilterFieldsIntoSelectedFields(Query query) { - LinkedHashSet fields = new LinkedHashSet<>(); - fields.addAll(query.getFields()); - if(!query.getCategoryFilters().isEmpty()) { - Set categoryFilters = new TreeSet(query.getCategoryFilters().keySet()); - Set toBeRemoved = new TreeSet(); - for(String categoryFilter : categoryFilters) { - System.out.println("In : " + categoryFilter); - if(VariantUtils.pathIsVariantSpec(categoryFilter)) { - toBeRemoved.add(categoryFilter); - } - } - categoryFilters.removeAll(toBeRemoved); - for(String categoryFilter : categoryFilters) { - System.out.println("Out : " + categoryFilter); - } - fields.addAll(categoryFilters); - } - fields.addAll(query.getAnyRecordOf()); - fields.addAll(query.getRequiredFields()); - fields.addAll(query.getNumericFilters().keySet()); - query.setFields(fields); - } private boolean ensureAllFieldsExist(Query query) { TreeSet allFields = new TreeSet<>(); diff --git a/service/src/main/java/edu/harvard/hms/dbmi/avillach/hpds/service/util/QueryDecorator.java b/service/src/main/java/edu/harvard/hms/dbmi/avillach/hpds/service/util/QueryDecorator.java new file mode 100644 index 00000000..cb1d4ece --- /dev/null +++ b/service/src/main/java/edu/harvard/hms/dbmi/avillach/hpds/service/util/QueryDecorator.java @@ -0,0 +1,55 @@ +package edu.harvard.hms.dbmi.avillach.hpds.service.util; + +import edu.harvard.dbmi.avillach.util.UUIDv5; +import edu.harvard.hms.dbmi.avillach.hpds.data.query.Query; +import edu.harvard.hms.dbmi.avillach.hpds.processing.VariantUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.util.LinkedHashSet; +import java.util.Set; +import java.util.TreeSet; + +@Component +public class QueryDecorator { + private static final Logger LOG = LoggerFactory.getLogger(QueryDecorator.class); + + public void setId(Query query) { + query.setId(""); // the id is included in the toString + // I clear it here to keep the ID setting stable for any query + // of identical structure and content + + // Some places where we call toString, we call mergeFilterFieldsIntoSelectedFields + // first. This can mutate the query, resulting in shifting UUIDs + // To stabilize things, we're always going to call that, and shift the logic here + mergeFilterFieldsIntoSelectedFields(query); + + String id = UUIDv5.UUIDFromString(query.toString()).toString(); + query.setId(id); + } + + public void mergeFilterFieldsIntoSelectedFields(Query query) { + LinkedHashSet fields = new LinkedHashSet<>(query.getFields()); + + if(!query.getCategoryFilters().isEmpty()) { + Set categoryFilters = new TreeSet<>(query.getCategoryFilters().keySet()); + Set toBeRemoved = new TreeSet<>(); + for(String categoryFilter : categoryFilters) { + LOG.debug("In : {}", categoryFilter); + if(VariantUtils.pathIsVariantSpec(categoryFilter)) { + toBeRemoved.add(categoryFilter); + } + } + categoryFilters.removeAll(toBeRemoved); + for(String categoryFilter : categoryFilters) { + LOG.debug("Out : {}", categoryFilter); + } + fields.addAll(categoryFilters); + } + fields.addAll(query.getAnyRecordOf()); + fields.addAll(query.getRequiredFields()); + fields.addAll(query.getNumericFilters().keySet()); + query.setFields(fields); + } +} diff --git a/service/src/main/java/edu/harvard/hms/dbmi/avillach/hpds/service/util/QueryUUIDGen.java b/service/src/main/java/edu/harvard/hms/dbmi/avillach/hpds/service/util/QueryUUIDGen.java deleted file mode 100644 index aa888097..00000000 --- a/service/src/main/java/edu/harvard/hms/dbmi/avillach/hpds/service/util/QueryUUIDGen.java +++ /dev/null @@ -1,16 +0,0 @@ -package edu.harvard.hms.dbmi.avillach.hpds.service.util; - -import edu.harvard.dbmi.avillach.util.UUIDv5; -import edu.harvard.hms.dbmi.avillach.hpds.data.query.Query; -import org.springframework.stereotype.Component; - -@Component -public class QueryUUIDGen { - public void setId(Query query) { - query.setId(""); // the id is included in the toString - // I clear it here to keep the ID setting stable for any query - // of identical structure and content - String id = UUIDv5.UUIDFromString(query.toString()).toString(); - query.setId(id); - } -}