diff --git a/src/main/java/org/epics/channelfinder/ChannelFinderService.java b/src/main/java/org/epics/channelfinder/ChannelFinderService.java index c48c095..b321ef7 100644 --- a/src/main/java/org/epics/channelfinder/ChannelFinderService.java +++ b/src/main/java/org/epics/channelfinder/ChannelFinderService.java @@ -7,11 +7,15 @@ import static org.elasticsearch.index.query.QueryBuilders.wildcardQuery; import java.io.IOException; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; @@ -89,16 +93,20 @@ public HandlerQuery(PVStructure args, RPCResponseCallback callback) { @Override public void run() { + NTURI uri = NTURI.wrap(args); log.info(Thread.currentThread().getName().toString()); String[] query = uri.getQueryNames(); TransportClient client = ElasticSearchClientManager.getClient(); + try { BoolQueryBuilder qb = boolQuery(); int size = 10000; int from = 0; Optional sortField = Optional.empty(); + final Set filteredColumns = new HashSet<>(); + for (String parameter : query) { String value = uri.getQueryField(PVString.class, parameter).get(); if (value != null && !value.isEmpty()) { @@ -135,6 +143,13 @@ public void run() { log.warning("failed to parse the from: " + value); } break; + case "_filter": + try { + filteredColumns.addAll(Arrays.asList(value.trim().split(","))); + } catch (NumberFormatException e) { + log.warning("failed to parse the from: " + value); + } + break; default: DisMaxQueryBuilder propertyQuery = disMaxQuery(); for (String pattern : value.split("\\|")) { @@ -170,8 +185,6 @@ public void run() { channelTable.put("owner", Arrays.asList(new String[resultSize])); qbResult.getHits().forEach(hit -> { - hit.getFields().entrySet().forEach(System.out::println); - try { XmlChannel ch = channelMapper.readValue(hit.source(), XmlChannel.class); @@ -180,19 +193,25 @@ public void run() { channelTable.get("channelName").set(index, ch.getName()); channelTable.get("owner").set(index, ch.getOwner()); - ch.getTags().stream().forEach(t -> { - if (!channelTagTable.containsKey(t.getName())) { - channelTagTable.put(t.getName(), new boolean[resultSize]); - } - channelTagTable.get(t.getName())[index] = true; - }); - - ch.getProperties().stream().forEach(prop -> { - if (!channelPropertyTable.containsKey(prop.getName())) { - channelPropertyTable.put(prop.getName(), Arrays.asList(new String[resultSize])); - } - channelPropertyTable.get(prop.getName()).set(index, prop.getValue()); - }); + if (!filteredColumns.contains("ALL")) { + ch.getTags().stream().filter((tag) -> { + return filteredColumns.isEmpty() || filteredColumns.contains(tag.getName()); + }).forEach(t -> { + if (!channelTagTable.containsKey(t.getName())) { + channelTagTable.put(t.getName(), new boolean[resultSize]); + } + channelTagTable.get(t.getName())[index] = true; + }); + + ch.getProperties().stream().filter((prop) -> { + return filteredColumns.isEmpty() || filteredColumns.contains(prop.getName()); + }).forEach(prop -> { + if (!channelPropertyTable.containsKey(prop.getName())) { + channelPropertyTable.put(prop.getName(), Arrays.asList(new String[resultSize])); + } + channelPropertyTable.get(prop.getName()).set(index, prop.getValue()); + }); + } } catch (IOException e) { e.printStackTrace(); } @@ -233,7 +252,6 @@ public void run() { } finally { } } - } public void shutdown() { diff --git a/src/test/java/org/epics/channelfinder/CFAdvanceQueryIT.java b/src/test/java/org/epics/channelfinder/CFAdvanceQueryIT.java index d231bdb..26aab2a 100644 --- a/src/test/java/org/epics/channelfinder/CFAdvanceQueryIT.java +++ b/src/test/java/org/epics/channelfinder/CFAdvanceQueryIT.java @@ -5,6 +5,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.stream.Collectors; import org.epics.channelfinder.example.PopulateExampleDb; import org.epics.nt.NTURI; @@ -33,11 +34,55 @@ public class CFAdvanceQueryIT { public static void createDB() { PopulateExampleDb.createDB(1); client = new RPCClientImpl(ChannelFinderService.SERVICE_NAME); - ; } @Test public void filterTest() { + + List resultChannels; + + NTURIBuilder uriBuilder = NTURI.createBuilder() + .addQueryString("_name") + .addQueryString("_size") + .addQueryString("_filter"); + NTURI uri = uriBuilder.create(); + uri.getPVStructure().getStringField("scheme").put("pva"); + uri.getPVStructure().getStringField("path").put("channels"); + uri.getQuery().getStringField("_name").put("*"); + uri.getQuery().getStringField("_size").put("10"); + + try { + // When the _filter is used with ALL then you only get channelNames + uri.getQuery().getStringField("_filter").put("ALL"); + PVStructure result = client.request(uri.getPVStructure(), 3.0); + System.out.println(result); + resultChannels = XmlUtil.parse(result); + assertTrue("Failed to filter the result to only return the channel Names ", resultChannels.stream().allMatch((ch) -> { + return ch.getProperties().isEmpty() && ch.getTags().isEmpty(); + })); + // Check channels only consist of names + + Set filterNames = new HashSet<>(); + filterNames.add("type"); + filterNames.add("cell"); + filterNames.add("family"); + + uri.getQuery().getStringField("_filter").put(filterNames.stream().collect(Collectors.joining(","))); + result = client.request(uri.getPVStructure(), 3.0); + resultChannels = XmlUtil.parse(result); + + assertTrue("Failed to filter the result to only return the channel names and a selecte few properties" + + "expected only the properties type, cell, and family recieved " + result, + resultChannels.stream().allMatch((ch) -> { + return filterNames + .equals(ch.getProperties().stream().map(XmlProperty::getName).collect(Collectors.toSet())) + && + ch.getTags().isEmpty(); + })); + + } catch (Exception e) { + e.printStackTrace(); + } } @Test