Skip to content

Commit

Permalink
Add format continuous endpoint
Browse files Browse the repository at this point in the history
This commit includes refactors that simplify the data returned from the vis resource in response to continuous or categorical request.
  • Loading branch information
Gcolon021 committed Jul 14, 2023
1 parent b312d41 commit a3d0133
Show file tree
Hide file tree
Showing 8 changed files with 88 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ public Response querySync(QueryRequest queryRequest) {
return Response.status(Response.Status.BAD_REQUEST).build();
}

HttpResponse response = getHttpResponse(queryRequest, resourceUUID);
HttpResponse response = getHttpResponse(queryRequest, resourceUUID, "/query/sync");

HttpEntity entity = response.getEntity();
String entityString = EntityUtils.toString(entity, "UTF-8");
Expand All @@ -267,10 +267,13 @@ public Response querySync(QueryRequest queryRequest) {
}
}

private HttpResponse getHttpResponse(QueryRequest queryRequest, UUID resourceUUID) throws JsonProcessingException {
private HttpResponse getHttpResponse(QueryRequest queryRequest, UUID resourceUUID, String pathName) throws JsonProcessingException {
String targetPicsureUrl = properties.getTargetPicsureUrl();
String queryString = objectMapper.writeValueAsString(queryRequest);
String pathName = "/query/sync";
return doHttpRequest(resourceUUID, targetPicsureUrl, queryString, pathName);
}

private HttpResponse doHttpRequest(UUID resourceUUID, String targetPicsureUrl, String queryString, String pathName) {
String composedURL = composeURL(targetPicsureUrl, pathName);
logger.debug("Aggregate Data Sharing Resource, sending query: " + queryString + ", to: " + composedURL);
HttpResponse response = retrievePostResponse(composedURL, headers, queryString);
Expand All @@ -297,7 +300,7 @@ private HttpResponse getHttpResponse(QueryRequest queryRequest, UUID resourceUUI
* @return String The response that will be returned
* @throws JsonProcessingException If there is an error processing the response
*/
private String getExpectedResponse(String expectedResultType, String entityString, String responseString, QueryRequest queryRequest) throws IOException {
private String getExpectedResponse(String expectedResultType, String entityString, String responseString, QueryRequest queryRequest) throws IOException, JsonProcessingException {
String crossCountResponse;
switch (expectedResultType) {
case "COUNT":
Expand Down Expand Up @@ -333,7 +336,7 @@ private String getExpectedResponse(String expectedResultType, String entityStrin
private String getCrossCountForQuery(QueryRequest queryRequest) throws IOException {
logger.debug("Calling Aggregate Data Sharing Resource getCrossCountForQuery()");

HttpResponse response = getHttpResponse(changeQueryToOpenCrossCount(queryRequest), queryRequest.getResourceUUID());
HttpResponse response = getHttpResponse(changeQueryToOpenCrossCount(queryRequest), queryRequest.getResourceUUID(), "/query/sync");
HttpEntity entity = response.getEntity();
return EntityUtils.toString(entity, "UTF-8");
}
Expand Down Expand Up @@ -508,15 +511,32 @@ private int generateVarianceWithCrossCounts(Map<String, String> crossCounts) {
return generateRequestVariance(crossCountsString.toString());
}

protected String processContinuousCrossCounts(String entityString, String crossCountResponse) throws JsonProcessingException {
protected String processContinuousCrossCounts(String continuousCrossCountResponse, String crossCountResponse) throws IOException {
logger.info("Processing continuous cross counts");
logger.info("Entity string: {}", entityString);
logger.info("Cross count response: {} ", crossCountResponse);
logger.info("Continuous count response: {}", continuousCrossCountResponse);

// convert continuousCrossCountResponse to a map
Map<String, Map<String, Integer>> continuousCrossCounts = objectMapper.convertValue(continuousCrossCountResponse, new TypeReference<>() {});

// I want to call the binning endpoint from the visualization service
QueryRequest queryRequest = new QueryRequest();
queryRequest.setResourceUUID(properties.getVisualizationResourceId());
queryRequest.setQuery(continuousCrossCounts);

// call the binning endpoint
HttpResponse httpResponse = getHttpResponse(queryRequest, properties.getVisualizationResourceId(), "/format/continuous");

if (entityString == null || crossCountResponse == null) {
HttpEntity entity = httpResponse.getEntity();
String responseString = EntityUtils.toString(entity, "UTF-8");

logger.info("Response from binning endpoint: {}", responseString);

if (continuousCrossCountResponse == null || crossCountResponse == null) {
return null;
}

return entityString;
return continuousCrossCountResponse;
}

/**
Expand Down Expand Up @@ -555,19 +575,11 @@ protected String processCategoricalCrossCounts(String categoricalEntityString, S
}
}

// If we don't need to obfuscate we can just return the entity string.
if (!mustObfuscate) {
return categoricalEntityString;
}

Map<String, Map<String, Object>> categoricalCrossCount;
try {
categoricalCrossCount = objectMapper.readValue(categoricalEntityString, new TypeReference<>(){});
} catch (Exception e) {
logger.error("Error processing categorical cross counts: {}", e.getMessage());
throw new JsonProcessingException(e.getMessage()) {};
}

Map<String, Map<String, Object>> categoricalCrossCount = objectMapper.readValue(categoricalEntityString, new TypeReference<>(){});
if (categoricalCrossCount == null) {
return categoricalEntityString;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public class ApplicationProperties implements Serializable {
private int targetPicsureObfuscationThreshold;
private int targetPicsureObfuscationVariance;
private String targetPicsureObfuscationSalt;
private UUID visualizationResourceId;

public static final int DEFAULT_OBFUSCATION_THRESHOLD = 10;
public static final int DEFAULT_OBFUSCATION_VARIANCE = 3;
Expand Down Expand Up @@ -60,6 +61,10 @@ public String getTargetPicsureObfuscationSalt() {
return targetPicsureObfuscationSalt;
}

public UUID getVisualizationResourceId() {
return visualizationResourceId;
}

public void init(String contextPath) {
logger.info("initializing aggregate Resource properties");

Expand Down Expand Up @@ -89,6 +94,11 @@ public void init(String contextPath) {
throw new PicsureQueryException("target.picsure.token property must be set.");
}

visualizationResourceId = UUID.fromString(properties.getProperty("visualization.resource.id"));
logger.debug("visualizationResourceId: " + visualizationResourceId);
if (visualizationResourceId == null)
throw new PicsureQueryException("visualization.resource.id property must be set.");

targetPicsureObfuscationThreshold = Optional.ofNullable(properties.getProperty("target.picsure.obfuscation_threshold"))
.map(Integer::parseInt)
.orElse(DEFAULT_OBFUSCATION_THRESHOLD);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ public void testMinimumThreshold() throws IOException {
}

@Test
public void testProcessContinuousCrossCounts() throws JsonProcessingException {
public void testProcessContinuousCrossCounts() throws IOException {
assertNull(objectUnderTest.processContinuousCrossCounts(null, null));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public class VisualizationResource implements IResourceRS {
public ResourceInfo info(QueryRequest infoRequest) {
ResourceInfo info = new ResourceInfo();
info.setName("Pic-Sure Visualization Resource");
// info.setId(properties.getVisualizationResourceId());
info.setId(properties.getVisualizationResourceId());
QueryFormat queryFormat = new QueryFormat();
queryFormat.setName("Pic-Sure Query Format");
info.getQueryFormats().add(queryFormat);
Expand Down Expand Up @@ -101,4 +101,10 @@ public Response queryFormat(QueryRequest resultRequest) {
return Response.serverError().entity("An error occurred formatting the query for display: " + e.getLocalizedMessage()).build();
}
}

@POST
@Path("/format/continuous")
public Response generateContinuousBin(QueryRequest continuousData) {
return visualizationService.generateContinuousBin(continuousData);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
@EqualsAndHashCode(callSuper = false)
public class CategoricalData extends edu.harvard.hms.dbmi.avillach.resource.visualization.model.VisualizationData {
Map<String, Integer> categoricalMap;
Map<String, Boolean> categoricalObfuscatedMap;


public CategoricalData(String title, Map<String, Integer> categoricalMap) {
super();
Expand All @@ -24,14 +22,15 @@ public CategoricalData(String title, Map<String, Integer> categoricalMap, String
this.categoricalMap = categoricalMap;
this.setXAxisName(xAxisLabel);
this.setYAxisName(yAxisLabel);
this.isObfuscated = false;
}

public CategoricalData(String title, Map<String, Integer> categoricalMap, Map<String, Boolean> categoricalObfuscatedMap, String xAxisLabel, String yAxisLabel) {
public CategoricalData(String title, Map<String, Integer> categoricalMap, String xAxisLabel, String yAxisLabel, boolean isObfuscated) {
super();
this.setTitle(title);
this.categoricalMap = categoricalMap;
this.categoricalObfuscatedMap = categoricalObfuscatedMap;
this.setXAxisName(xAxisLabel);
this.setYAxisName(yAxisLabel);
this.isObfuscated = isObfuscated;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public class VisualizationData {
private String yAxisName;
Integer chartWidth;
Integer chartHeight;
boolean isObfuscated;

public int getChartHeight() {
if (this.chartHeight == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,25 +48,14 @@ public DataProcessingService() {
* @return List<CategoricalData> - result of query
*/
public List<CategoricalData> getCategoricalData(Map<String, Map<String, Integer>> crossCountsMap) {
List<CategoricalData> categoricalDataList = new ArrayList<>();

for (Map.Entry<String, Map<String, Integer>> entry : crossCountsMap.entrySet()) {
if (skipKey(entry)) continue;
Map<String, Integer> axisMap = processResults(entry.getValue());
return handleGetCategoricalData(crossCountsMap, false);
}

String title = getChartTitle(entry.getKey());
categoricalDataList.add(new CategoricalData(
title,
new LinkedHashMap<>(axisMap),
createXAxisLabel(title),
"Number of Participants"
));
}
logger.debug("Finished Categorical Data with " + categoricalDataList.size() + " results");
return categoricalDataList;
public List<CategoricalData> getCategoricalData(Map<String, Map<String, Integer>> crossCountsMap, boolean isObfuscated) {
return handleGetCategoricalData(crossCountsMap, isObfuscated);
}

public List<CategoricalData> getCategoricalData(Map<String, Map<String, Integer>> crossCountsMap, Map<String, Map<String, Boolean>> obfuscationMap) {
private List<CategoricalData> handleGetCategoricalData(Map<String, Map<String, Integer>> crossCountsMap, boolean isObfuscated) {
List<CategoricalData> categoricalDataList = new ArrayList<>();

for (Map.Entry<String, Map<String, Integer>> entry : crossCountsMap.entrySet()) {
Expand All @@ -77,9 +66,9 @@ public List<CategoricalData> getCategoricalData(Map<String, Map<String, Integer>
categoricalDataList.add(new CategoricalData(
title,
new LinkedHashMap<>(axisMap),
obfuscationMap.get(entry.getKey()),
createXAxisLabel(title),
"Number of Participants"
"Number of Participants",
isObfuscated
));
}
logger.debug("Finished Categorical Data with " + categoricalDataList.size() + " results");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package edu.harvard.hms.dbmi.avillach.resource.visualization.service;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import edu.harvard.dbmi.avillach.domain.QueryRequest;
import edu.harvard.hms.dbmi.avillach.resource.visualization.ApplicationProperties;
import edu.harvard.hms.dbmi.avillach.resource.visualization.model.ContinuousData;
import edu.harvard.hms.dbmi.avillach.resource.visualization.model.ProcessedCrossCountsResponse;
import edu.harvard.hms.dbmi.avillach.resource.visualization.model.domain.Query;
import edu.harvard.hms.dbmi.avillach.resource.visualization.model.domain.ResultType;
Expand All @@ -13,6 +15,7 @@
import javax.inject.Inject;
import javax.ws.rs.core.Response;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Stateless
Expand Down Expand Up @@ -87,10 +90,10 @@ private Response getOpenProcessedCrossCountResponse(Map<String, Map<String, Stri
if ((categroyCrossCountsMap == null || categroyCrossCountsMap.isEmpty()))
return Response.ok().build();

Map<String, Map<String, Boolean>> obfuscationMap = generateObfuscationMap(categroyCrossCountsMap);
boolean isCategoricalObfuscated = isObfuscated(categroyCrossCountsMap);
Map<String, Map<String, Integer>> cleanedCategoricalData = cleanCategoricalData(categroyCrossCountsMap);

ProcessedCrossCountsResponse response = buildOpenProcessedCrossCountsResponse(cleanedCategoricalData, obfuscationMap);
ProcessedCrossCountsResponse response = buildOpenProcessedCrossCountsResponse(cleanedCategoricalData, isCategoricalObfuscated);
return Response.ok(response).build();
}

Expand Down Expand Up @@ -128,7 +131,6 @@ private Map<String, Map<String, Boolean>> generateObfuscationMap(Map<String, Map
} else {
tempObf.put(subKey, false);
}

});

crossCountsObfuscationMap.put(key, tempObf);
Expand All @@ -137,11 +139,28 @@ private Map<String, Map<String, Boolean>> generateObfuscationMap(Map<String, Map
return crossCountsObfuscationMap;
}

private boolean isObfuscated(Map<String, Map<String, String>> categroyCrossCountsMap) {
boolean isObfuscated = false;
for (Map.Entry<String, Map<String, String>> e : categroyCrossCountsMap.entrySet()) {
Map<String, String> value = e.getValue();

for (Map.Entry<String, String> entry : value.entrySet()) {
String subValue = entry.getValue();
if (subValue.contains(threshold) || subValue.contains(variance)) {
isObfuscated = true;
break;
}
}
}

return isObfuscated;
}

private ProcessedCrossCountsResponse buildOpenProcessedCrossCountsResponse(Map<String, Map<String, Integer>> categroyCrossCountsMap,
Map<String, Map<String, Boolean>> categoryCrossCountsObfuscationMap) {
boolean isObfuscated) {

ProcessedCrossCountsResponse response = new ProcessedCrossCountsResponse();
response.getCategoricalData().addAll(dataProcessingServices.getCategoricalData(categroyCrossCountsMap, categoryCrossCountsObfuscationMap));
response.getCategoricalData().addAll(dataProcessingServices.getCategoricalData(categroyCrossCountsMap, isObfuscated));
return response;
}

Expand Down Expand Up @@ -185,4 +204,9 @@ private Map<String, Map<String, String>> getOpenCrossCounts(QueryRequest query,
return crossCountsMap;
}

public Response generateContinuousBin(QueryRequest continuousData) {
Map<String, Map<String, Integer>> continuousDataMap = mapper.convertValue(continuousData.getQuery(), new TypeReference<>() {});
List<ContinuousData> continuousData1 = dataProcessingServices.getContinuousData(continuousDataMap);
return Response.ok(continuousData1).build();
}
}

0 comments on commit a3d0133

Please sign in to comment.