From 08ddfcd73105d6116983d9c905d7d9450213fd96 Mon Sep 17 00:00:00 2001 From: Andrew Raines Date: Mon, 23 Dec 2013 12:14:25 -0600 Subject: [PATCH] Add associative lookup of columns for arbitrary (and more intuitive) ordering. % curl 'localhost:9200/_cat/nodes?v&headers=jdk,ip,name' jdk ip name 1.7.0_40 127.0.0.1 Mordo, Karl Closes #4433. --- .../java/org/elasticsearch/common/Table.java | 47 +++++++++-- .../rest/action/support/RestTable.java | 83 +++++++++---------- 2 files changed, 82 insertions(+), 48 deletions(-) diff --git a/src/main/java/org/elasticsearch/common/Table.java b/src/main/java/org/elasticsearch/common/Table.java index 34c0e3476da..24956db9672 100644 --- a/src/main/java/org/elasticsearch/common/Table.java +++ b/src/main/java/org/elasticsearch/common/Table.java @@ -20,12 +20,10 @@ package org.elasticsearch.common; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; import org.elasticsearch.ElasticSearchIllegalArgumentException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; /** */ @@ -34,6 +32,8 @@ public class Table { protected List headers = new ArrayList(); protected List> rows = new ArrayList>(); + protected Map> map = Maps.newHashMap(); + protected List currentCells; protected boolean inHeaders = false; @@ -48,6 +48,18 @@ public class Table { inHeaders = false; headers = currentCells; currentCells = null; + + /* Create associative structure for columns that + * contain the same cells as the rows: + * + * header1 => [Cell, Cell, ...] + * header2 => [Cell, Cell, ...] + * header3 => [Cell, Cell, ...] + */ + for (Cell header : headers) { + map.put((String) header.value, new ArrayList()); + } + return this; } @@ -75,6 +87,13 @@ public class Table { public Table addCell(Cell cell) { currentCells.add(cell); + + // If we're in a value row, also populate the named column. + if (!inHeaders) { + String hdr = (String) headers.get(currentCells.indexOf(cell)).value; + map.get(hdr).add(cell); + } + return this; } @@ -111,7 +130,7 @@ public class Table { mAttr.put(sAttr.substring(0, idx), sAttr.substring(idx + 1)); } } - currentCells.add(new Cell(value, mAttr)); + addCell(new Cell(value, mAttr)); return this; } @@ -119,7 +138,9 @@ public class Table { return this.headers; } - public Iterable> getRows() { + public Iterable> rowIterator() { return rows; } + + public List> getRows() { return rows; } @@ -127,6 +148,20 @@ public class Table { return (List[]) rows.toArray(); } + public Map> getAsMap() { return this.map; } + + public List getHeadersFromNames(List headerNames) { + List hdrs = new ArrayList(); + for (String hdrToFind : headerNames) { + for (Cell header : headers) { + if (((String) header.value).equalsIgnoreCase(hdrToFind)) { + hdrs.add(header); + } + } + } + return hdrs; + } + public Table addTable(Table t2) { Table t1 = this; Table t = new Table(); diff --git a/src/main/java/org/elasticsearch/rest/action/support/RestTable.java b/src/main/java/org/elasticsearch/rest/action/support/RestTable.java index 6c45ed126be..28e8e919be1 100644 --- a/src/main/java/org/elasticsearch/rest/action/support/RestTable.java +++ b/src/main/java/org/elasticsearch/rest/action/support/RestTable.java @@ -29,9 +29,7 @@ import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.rest.*; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; /** */ @@ -47,19 +45,16 @@ public class RestTable { public static RestResponse buildXContentBuilder(Table table, RestRequest request, RestChannel channel) throws Exception { XContentBuilder builder = RestXContentBuilder.restContentBuilder(request); - Set displayHeaders = buildDisplayHeaders(table, request); + List displayHeaders = buildDisplayHeaders(table, request); - List headers = table.getHeaders(); builder.startArray(); - for (List row : table.getRows()) { + for (int row = 0; row < table.getRows().size(); row++) { builder.startObject(); - for (int i = 0; i < headers.size(); i++) { - String headerName = headers.get(i).value.toString(); - if (displayHeaders.contains(headerName)) { - builder.field(headerName, renderValue(request, row.get(i).value)); - } + for (String header : displayHeaders) { + builder.field(header, renderValue(request, table.getAsMap().get(header).get(row).value)); } builder.endObject(); + } builder.endArray(); return new XContentRestResponse(request, RestStatus.OK, builder); @@ -81,28 +76,25 @@ public class RestTable { return new StringRestResponse(RestStatus.OK, out.toString()); } - int[] width = buildWidths(table, request, verbose); - Set displayHeaders = buildDisplayHeaders(table, request); + List displayHeaders = buildDisplayHeaders(table, request); + int[] width = buildWidths(table, request, verbose, displayHeaders); + int col = 0; StringBuilder out = new StringBuilder(); if (verbose) { // print the headers - for (int i = 0; i < width.length; i++) { - String headerName = table.getHeaders().get(i).value.toString(); - if (displayHeaders.contains(headerName)) { - pad(table.getHeaders().get(i), width[i], request, out); - out.append(" "); - } + for (Table.Cell header : table.getHeadersFromNames(displayHeaders)) { + pad(header, width[col], request, out); + out.append(" "); + col++; } out.append("\n"); } - for (List row : table.getRows()) { - for (int i = 0; i < width.length; i++) { - String headerName = table.getHeaders().get(i).value.toString(); - if (displayHeaders.contains(headerName)) { - pad(row.get(i), width[i], request, out); - out.append(" "); - } + + for (int row = 0; row < table.getRows().size(); row++) { + for (String header : displayHeaders) { + pad(table.getAsMap().get(header).get(row), width[displayHeaders.indexOf(header)], request, out); + out.append(" "); } out.append("\n"); } @@ -110,13 +102,16 @@ public class RestTable { return new StringRestResponse(RestStatus.OK, out.toString()); } - private static Set buildDisplayHeaders(Table table, RestRequest request) { + private static List buildDisplayHeaders(Table table, RestRequest request) { String pHeaders = request.param("headers"); - Set display; + List display = new ArrayList(); if (pHeaders != null) { - display = Strings.commaDelimitedListToSet(pHeaders); + for (String possibility : Arrays.asList(Strings.splitStringByCommaToArray(pHeaders))) { + if (table.getAsMap().containsKey(possibility)) { + display.add(possibility); + } + } } else { - display = new HashSet(); for (Table.Cell cell : table.getHeaders()) { String d = cell.attr.get("default"); if (Booleans.parseBoolean(d, true)) { @@ -145,27 +140,31 @@ public class RestTable { return width; } - private static int[] buildWidths(Table table, RestRequest request, boolean verbose) { - int[] width = new int[table.getHeaders().size()]; + private static int[] buildWidths(Table table, RestRequest request, boolean verbose, List headers) { + int[] width = new int[headers.size()]; + int i; if (verbose) { - for (int col = 0; col < width.length; col++) { - String v = renderValue(request, table.getHeaders().get(col).value); - int vWidth = v == null ? 0 : v.length(); - if (width[col] < vWidth) { - width[col] = vWidth; + i = 0; + for (String hdr : headers) { + int vWidth = hdr.length(); + if (width[i] < vWidth) { + width[i] = vWidth; } + i++; } } - for (List row : table.getRows()) { - for (int col = 0; col < width.length; col++) { - String v = renderValue(request, row.get(col).value); + i = 0; + for (String hdr : headers) { + for (Table.Cell cell : table.getAsMap().get(hdr)) { + String v = renderValue(request, cell.value); int vWidth = v == null ? 0 : v.length(); - if (width[col] < vWidth) { - width[col] = vWidth; + if (width[i] < vWidth) { + width[i] = vWidth; } } + i++; } return width; }