Create embeddable spreadsheets, and use that on the AFE Job Detail tab. Signed-off-by: James Ren <[email protected]>
--- autotest/apache/conf/all-directives 2010-05-27 14:44:25.000000000 -0700 +++ autotest/apache/conf/all-directives 2010-05-27 14:44:25.000000000 -0700 @@ -8,5 +8,6 @@ Include "/usr/local/autotest/apache/conf/tko-directives" Include "/usr/local/autotest/apache/conf/new-tko-directives" Include "/usr/local/autotest/apache/conf/embedded-tko-directives" +Include "/usr/local/autotest/apache/conf/embedded-spreadsheet-directives" Include "/usr/local/autotest/apache/conf/planner-directives" Include "/usr/local/autotest/apache/conf/site-directives" --- /dev/null 2009-12-17 12:29:38.000000000 -0800 +++ autotest/apache/conf/embedded-spreadsheet-directives 2010-05-27 14:44:25.000000000 -0700 @@ -0,0 +1 @@ +Alias /embedded_spreadsheet "/usr/local/autotest/frontend/client/www/autotest.EmbeddedSpreadsheetClient" --- /dev/null 2009-12-17 12:29:38.000000000 -0800 +++ autotest/frontend/client/EmbeddedSpreadsheetClient.launch 2010-05-27 14:44:25.000000000 -0700 @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication"> +<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"> +<listEntry value="/AfeClient"/> +</listAttribute> +<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"> +<listEntry value="4"/> +</listAttribute> +<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/> +<listAttribute key="org.eclipse.jdt.launching.CLASSPATH"> +<listEntry value="<?xml version="1.0" encoding="UTF-8"?> <runtimeClasspathEntry containerPath="org.eclipse.jdt.launching.JRE_CONTAINER" javaProject="AfeClient" path="1" type="4"/> "/> +<listEntry value="<?xml version="1.0" encoding="UTF-8"?> <runtimeClasspathEntry internalArchive="/AfeClient/src" path="3" type="2"/> "/> +<listEntry value="<?xml version="1.0" encoding="UTF-8"?> <runtimeClasspathEntry id="org.eclipse.jdt.launching.classpathentry.defaultClasspath"> <memento project="AfeClient"/> </runtimeClasspathEntry> "/> +<listEntry value="<?xml version="1.0" encoding="UTF-8"?> <runtimeClasspathEntry externalArchive="/usr/local/lib/gwt/gwt-dev.jar" path="3" type="2"/> "/> +<listEntry value="<?xml version="1.0" encoding="UTF-8"?> <runtimeClasspathEntry externalArchive="/usr/local/lib/gwt/gwt-incubator.jar" path="3" type="2"/> "/> +</listAttribute> +<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/> +<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.DevMode"/> +<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-startupUrl http://localhost:8000/new_tko/server/autotest.EmbeddedSpreadsheetClient/EmbeddedSpreadsheetClient.html autotest.EmbeddedSpreadsheetClient"/> +<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="AfeClient"/> +<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx512M -ea"/> +</launchConfiguration> --- /dev/null 2009-12-17 12:29:38.000000000 -0800 +++ autotest/frontend/client/src/autotest/EmbeddedSpreadsheetClient.gwt.xml 2010-05-27 14:44:25.000000000 -0700 @@ -0,0 +1,15 @@ +<module> + <inherits name='com.google.gwt.user.User'/> + <inherits name='com.google.gwt.json.JSON'/> + <inherits name='com.google.gwt.http.HTTP'/> + + <source path="tko"/> + <source path="common"/> + <entry-point class='autotest.tko.EmbeddedSpreadsheetClient'/> + + <stylesheet src='common.css'/> + <stylesheet src='standard.css'/> + <stylesheet src='afeclient.css'/> + <stylesheet src='tkoclient.css'/> + +</module> --- autotest/frontend/client/src/autotest/afe/JobDetailView.java 2010-05-27 14:44:25.000000000 -0700 +++ autotest/frontend/client/src/autotest/afe/JobDetailView.java 2010-05-27 14:44:25.000000000 -0700 @@ -18,13 +18,9 @@ import autotest.common.ui.NotifyManager; import autotest.common.ui.TableActionsPanel.TableActionsListener; +import com.google.gwt.dom.client.Element; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; -import com.google.gwt.http.client.Request; -import com.google.gwt.http.client.RequestBuilder; -import com.google.gwt.http.client.RequestCallback; -import com.google.gwt.http.client.RequestException; -import com.google.gwt.http.client.Response; import com.google.gwt.json.client.JSONArray; import com.google.gwt.json.client.JSONBoolean; import com.google.gwt.json.client.JSONNumber; @@ -34,31 +30,35 @@ import com.google.gwt.user.client.Command; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.DisclosurePanel; +import com.google.gwt.user.client.ui.Frame; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.Label; -import com.google.gwt.user.client.ui.ScrollPanel; import com.google.gwt.user.client.ui.Widget; import java.util.Set; public class JobDetailView extends DetailView implements TableWidgetFactory, TableActionsListener { private static final String[][] JOB_HOSTS_COLUMNS = { - {DataTable.CLICKABLE_WIDGET_COLUMN, ""}, // selection checkbox - {"hostname", "Host"}, {"full_status", "Status"}, + {DataTable.CLICKABLE_WIDGET_COLUMN, ""}, // selection checkbox + {"hostname", "Host"}, {"full_status", "Status"}, {"host_status", "Host Status"}, {"host_locked", "Host Locked"}, // columns for status log and debug log links - {DataTable.CLICKABLE_WIDGET_COLUMN, ""}, {DataTable.CLICKABLE_WIDGET_COLUMN, ""} + {DataTable.CLICKABLE_WIDGET_COLUMN, ""}, {DataTable.CLICKABLE_WIDGET_COLUMN, ""} }; public static final String NO_URL = "about:blank"; public static final int NO_JOB_ID = -1; public static final int HOSTS_PER_PAGE = 30; - + public static final String RESULTS_MAX_WIDTH = "700px"; + public static final String RESULTS_MAX_HEIGHT = "500px"; + public static final String EMBEDDED_SPREADSHEET_URL = + "/embedded_spreadsheet/EmbeddedSpreadsheetClient.html"; + public interface JobDetailListener { public void onHostSelected(String hostname); public void onCloneJob(JSONValue result); public void onCreateRecurringJob(int id); } - + protected int jobId = NO_JOB_ID; private JobStatusDataSource jobStatusDataSource = new JobStatusDataSource(); @@ -68,18 +68,37 @@ protected Button abortButton = new Button("Abort job"); protected Button cloneButton = new Button("Clone job"); protected Button recurringButton = new Button("Create recurring job"); - protected HTML tkoResultsHtml = new HTML(); - protected ScrollPanel tkoResultsScroller = new ScrollPanel(tkoResultsHtml); + protected Frame tkoResultsFrame = new Frame(EMBEDDED_SPREADSHEET_URL); + protected JobDetailListener listener; private SelectionManager selectionManager; - + private Label controlFile = new Label(); private DisclosurePanel controlFilePanel = new DisclosurePanel(""); - + protected StaticDataRepository staticData = StaticDataRepository.getRepository(); - + public JobDetailView(JobDetailListener listener) { this.listener = listener; + setupSpreadsheetListener(Utils.getBaseUrl()); + } + + private native void setupSpreadsheetListener(String baseUrl) /*-{ + var ins = this; + $wnd.onSpreadsheetLoad = function(event) { + if (event.origin !== baseUrl) { + return; + } + [email protected]::resizeResultsFrame(Ljava/lang/String;)(event.data); + } + + $wnd.addEventListener("message", $wnd.onSpreadsheetLoad, false); + }-*/; + + @SuppressWarnings("unused") // called from native + private void resizeResultsFrame(String message) { + String[] parts = message.split(" "); + tkoResultsFrame.setSize(parts[0], parts[1]); } @Override @@ -101,7 +120,7 @@ } String name = Utils.jsonToString(jobObject.get("name")); String runVerify = Utils.jsonToString(jobObject.get("run_verify")); - + showText(name, "view_label"); showField(jobObject, "owner", "view_owner"); showField(jobObject, "priority", "view_priority"); @@ -115,27 +134,27 @@ showField(jobObject, "parse_failed_repair", "view_parse_failed_repair"); showField(jobObject, "synch_count", "view_synch_count"); showField(jobObject, "dependencies", "view_dependencies"); - + if (staticData.getData("drone_sets_enabled").isBoolean().booleanValue()) { showField(jobObject, "drone_set", "view_drone_set"); } - + String header = Utils.jsonToString(jobObject.get("control_type")) + " control file"; controlFilePanel.getHeaderTextAccessor().setText(header); controlFile.setText(Utils.jsonToString(jobObject.get("control_file"))); - + JSONObject counts = jobObject.get("status_counts").isObject(); String countString = AfeUtils.formatStatusCounts(counts, ", "); showText(countString, "view_status"); abortButton.setVisible(isAnyEntryAbortable(counts)); - + String jobTag = AfeUtils.getJobTag(jobObject); - pointToResults(getResultsURL(jobId), getLogsURL(jobTag), + pointToResults(getResultsURL(jobId), getLogsURL(jobTag), getOldResultsUrl(jobId), getTriageUrl(jobId)); - + String jobTitle = "Job: " + name + " (" + jobTag + ")"; displayObjectData(jobTitle); - + jobFilter.setParameter("job", new JSONNumber(jobId)); hostsTable.refresh(); } @@ -148,11 +167,11 @@ } }); } - + protected boolean isAnyEntryAbortable(JSONObject statusCounts) { Set<String> statuses = statusCounts.keySet(); for (String status : statuses) { - if (!(status.equals("Completed") || + if (!(status.equals("Completed") || status.equals("Failed") || status.equals("Stopped") || status.startsWith("Aborted"))) { @@ -161,13 +180,13 @@ } return false; } - + @Override public void initialize() { super.initialize(); - + idInput.setVisibleLength(5); - + hostsTable.setRowsPerPage(HOSTS_PER_PAGE); hostsTable.setClickable(true); hostsTable.addListener(new DynamicTableListener() { @@ -186,54 +205,54 @@ selectionManager = tableDecorator.addSelectionManager(false); tableDecorator.addTableActionsPanel(this, true); addWidget(tableDecorator, "job_hosts_table"); - + abortButton.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { abortJob(); } }); addWidget(abortButton, "view_abort"); - + cloneButton.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { cloneJob(); - } + } }); addWidget(cloneButton, "view_clone"); - + recurringButton.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { createRecurringJob(); - } + } }); addWidget(recurringButton, "view_recurring"); - - tkoResultsScroller.setStyleName("results-frame"); - addWidget(tkoResultsScroller, "tko_results"); - + + tkoResultsFrame.getElement().setAttribute("scrolling", "no"); + addWidget(tkoResultsFrame, "tko_results"); + controlFile.addStyleName("code"); controlFilePanel.setContent(controlFile); addWidget(controlFilePanel, "view_control_file"); - + if (!staticData.getData("drone_sets_enabled").isBoolean().booleanValue()) { AfeUtils.removeElement("view_drone_set_wrapper"); } } - + protected void addTableFilters() { hostsTable.addFilter(jobFilter); - + SearchFilter hostnameFilter = new SearchFilter("host__hostname", true); ListFilter statusFilter = new ListFilter("status"); StaticDataRepository staticData = StaticDataRepository.getRepository(); JSONArray statuses = staticData.getData("job_statuses").isArray(); statusFilter.setChoices(Utils.JSONtoStrings(statuses)); - + tableDecorator.addFilter("Hostname", hostnameFilter); tableDecorator.addFilter("Status", statusFilter); } - + private void abortJob() { JSONObject params = new JSONObject(); params.put("job__id", new JSONNumber(jobId)); @@ -269,32 +288,32 @@ JSONObject queueEntryFilterData = new JSONObject(); String sql = "(status = 'Failed' OR aborted = TRUE OR " + "(host_id IS NULL AND meta_host IS NULL))"; - + queueEntryFilterData.put("extra_where", new JSONString(sql)); cloneJob(true, queueEntryFilterData); } }); - - menu.showAt(cloneButton.getAbsoluteLeft(), + + menu.showAt(cloneButton.getAbsoluteLeft(), cloneButton.getAbsoluteTop() + cloneButton.getOffsetHeight()); } - + private void cloneJobOnSelectedHosts() { Set<JSONObject> hostsQueueEntries = selectionManager.getSelectedObjects(); JSONArray queueEntryIds = new JSONArray(); for (JSONObject queueEntry : hostsQueueEntries) { queueEntryIds.set(queueEntryIds.size(), queueEntry.get("id")); } - + JSONObject queueEntryFilterData = new JSONObject(); queueEntryFilterData.put("id__in", queueEntryIds); cloneJob(true, queueEntryFilterData); } - + private void cloneJob(boolean preserveMetahosts) { cloneJob(preserveMetahosts, new JSONObject()); } - + private void cloneJob(boolean preserveMetahosts, JSONObject queueEntryFilterData) { JSONObject params = new JSONObject(); params.put("id", new JSONNumber(jobId)); @@ -312,35 +331,35 @@ private void createRecurringJob() { listener.onCreateRecurringJob(jobId); } - + private String getResultsURL(int jobId) { return "/new_tko/#tab_id=spreadsheet_view&row=hostname&column=test_name&" + "condition=afe_job_id+%253d+" + Integer.toString(jobId) + "&" + "show_incomplete=true"; } - + private String getOldResultsUrl(int jobId) { return "/tko/compose_query.cgi?" + - "columns=test&rows=hostname&condition=tag%7E%27" + + "columns=test&rows=hostname&condition=tag%7E%27" + Integer.toString(jobId) + "-%25%27&title=Report"; } - + private String getTriageUrl(int jobId) { /* * Having a hard-coded path like this is very unfortunate, but there's no simple way * in the current design to generate this link by code. - * + * * TODO: Redesign the system so that we can generate these links by code. - * + * * Idea: Be able to instantiate a TableView object, ask it to set up to triage this job ID, * and then ask it for the history URL. */ - + return "/new_tko/#tab_id=table_view&columns=test_name%252Cstatus%252Cgroup_count%252C" + "reason&sort=test_name%252Cstatus%252Creason&condition=afe_job_id+%253D+" + jobId + "+AND+status+%253C%253E+%2527GOOD%2527&show_invalid=false"; } - + /** * Get the path for a job's raw result files. * @param jobLogsId id-owner, e.g. "172-showard" @@ -348,52 +367,40 @@ protected String getLogsURL(String jobLogsId) { return Utils.getRetrieveLogsUrl(jobLogsId); } - + protected void pointToResults(String resultsUrl, String logsUrl, String oldResultsUrl, String triageUrl) { getElementById("results_link").setAttribute("href", resultsUrl); getElementById("old_results_link").setAttribute("href", oldResultsUrl); getElementById("raw_results_link").setAttribute("href", logsUrl); getElementById("triage_failures_link").setAttribute("href", triageUrl); - if (resultsUrl.equals(NO_URL)) { - tkoResultsHtml.setHTML(""); - return; - } - RequestBuilder requestBuilder = - new RequestBuilder(RequestBuilder.GET, oldResultsUrl + "&brief=1"); - try { - requestBuilder.sendRequest("", new RequestCallback() { - public void onError(Request request, Throwable exception) { - tkoResultsHtml.setHTML(""); - NotifyManager.getInstance().showError( - exception.getLocalizedMessage()); - } - public void onResponseReceived(Request request, - Response response) { - tkoResultsHtml.setHTML(response.getText()); - } - }); - } catch (RequestException ex) { - NotifyManager.getInstance().showError(ex.getLocalizedMessage()); + tkoResultsFrame.setSize(RESULTS_MAX_WIDTH, RESULTS_MAX_HEIGHT); + if (!resultsUrl.equals(NO_URL)) { + updateResultsFrame(tkoResultsFrame.getElement(), + String.valueOf(jobId), Utils.getBaseUrl()); } } - + + private native void updateResultsFrame(Element frame, String jobId, String baseUrl) /*-{ + frame.contentWindow.postMessage(jobId, baseUrl); + }-*/; + @Override protected String getNoObjectText() { return "No job selected"; } - + @Override protected String getFetchControlsElementId() { return "job_id_fetch_controls"; } - + @Override protected String getDataElementId() { return "view_data"; } - + @Override protected String getTitleElementId() { return "view_title"; @@ -401,11 +408,12 @@ @Override protected String getObjectId() { - if (jobId == NO_JOB_ID) + if (jobId == NO_JOB_ID) { return NO_OBJECT; + } return Integer.toString(jobId); } - + @Override public String getElementId() { return "view_job"; @@ -422,7 +430,7 @@ } this.jobId = newJobId; } - + public Widget createWidget(int row, int cell, JSONObject hostQueueEntry) { if (cell == 0) { return selectionManager.createWidget(row, cell, hostQueueEntry); @@ -452,19 +460,19 @@ public ContextMenu getActionMenu() { ContextMenu menu = new ContextMenu(); - + menu.addItem("Abort hosts", new Command() { public void execute() { abortSelectedHosts(); } }); - + menu.addItem("Clone job on selected hosts", new Command() { public void execute() { cloneJobOnSelectedHosts(); } }); - + return menu; } } --- autotest/frontend/client/src/autotest/common/Utils.java 2010-05-27 14:44:25.000000000 -0700 +++ autotest/frontend/client/src/autotest/common/Utils.java 2010-05-27 14:44:25.000000000 -0700 @@ -314,4 +314,8 @@ } return list; } + + public static String getBaseUrl() { + return Window.Location.getProtocol() + "//" + Window.Location.getHost(); + } } --- /dev/null 2009-12-17 12:29:38.000000000 -0800 +++ autotest/frontend/client/src/autotest/public/EmbeddedSpreadsheetClient.html 2010-05-27 14:44:25.000000000 -0700 @@ -0,0 +1,9 @@ +<!DOCTYPE html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> + <title>Embedded Spreadsheet</title> + <script type='text/javascript' + src='autotest.EmbeddedSpreadsheetClient.nocache.js'> + </script> +</head> +<body></body> --- autotest/frontend/client/src/autotest/public/afeclient.css 2010-05-27 14:44:25.000000000 -0700 +++ autotest/frontend/client/src/autotest/public/afeclient.css 2010-05-27 14:44:25.000000000 -0700 @@ -134,13 +134,6 @@ margin: 0.2em; } -.results-frame { - max-width: 700px; - max-height: 500px; - margin-bottom: 0.2em; - border: 2px solid gray; -} - .gwt-DialogBox { background: white; border: 2px solid #f4f4f4; --- /dev/null 2009-12-17 12:29:38.000000000 -0800 +++ autotest/frontend/client/src/autotest/tko/EmbeddedSpreadsheetClient.java 2010-05-27 14:44:25.000000000 -0700 @@ -0,0 +1,79 @@ +package autotest.tko; + +import autotest.common.JsonRpcProxy; +import autotest.common.spreadsheet.Spreadsheet; + +import com.google.gwt.core.client.EntryPoint; +import com.google.gwt.json.client.JSONNumber; +import com.google.gwt.json.client.JSONObject; +import com.google.gwt.user.client.Command; +import com.google.gwt.user.client.ui.RootPanel; + +import java.util.Collections; + +public class EmbeddedSpreadsheetClient implements EntryPoint { + private static class SimpleHeaderField extends HeaderField { + protected SimpleHeaderField(String name) { + super(name, name); + } + + @Override + public String getSqlCondition(String value) { + throw new UnsupportedOperationException("No SQL condition"); + } + } + + public static final String ROW_HEADER = "hostname"; + public static final String COLUMN_HEADER = "test_name"; + + private Spreadsheet spreadsheet = new Spreadsheet(); + private SpreadsheetDataProcessor spreadsheetProcessor = + new SpreadsheetDataProcessor(spreadsheet); + + @Override + public void onModuleLoad() { + JsonRpcProxy.setDefaultBaseUrl(JsonRpcProxy.TKO_BASE_URL); + setupListener(); + + spreadsheetProcessor.setDataSource(TestGroupDataSource.getStatusCountDataSource()); + spreadsheetProcessor.setHeaders( + Collections.singletonList(new SimpleHeaderField(ROW_HEADER)), + Collections.singletonList(new SimpleHeaderField(COLUMN_HEADER)), + new JSONObject()); + + RootPanel.get().add(spreadsheet); + } + + private native void setupListener() /*-{ + var instance = this; + $wnd.onGotJobId = function(event) { + var jobId = parseInt(event.data); + [email protected]::createSpreadsheet(I)(jobId); + } + + $wnd.addEventListener("message", $wnd.onGotJobId, false); + }-*/; + + @SuppressWarnings("unused") // called from native + private void createSpreadsheet(int afeJobId) { + spreadsheet.clear(); + final JSONObject condition = getFilterCondition(afeJobId); + spreadsheetProcessor.refresh(condition, new Command() { + public void execute() { + condition.put("extra_info", null); + notifyParent(spreadsheet.getElement().getClientWidth(), + spreadsheet.getElement().getClientHeight()); + } + }); + } + + private JSONObject getFilterCondition(int afeJobId) { + JSONObject condition = new JSONObject(); + condition.put("afe_job_id", new JSONNumber(afeJobId)); + return condition; + } + + private native void notifyParent(int width, int height) /*-{ + $wnd.parent.postMessage(width + 'px ' + height + 'px', '*'); + }-*/; +} --- autotest/frontend/client/src/autotest/tko/SpreadsheetDataProcessor.java 2010-05-27 14:44:25.000000000 -0700 +++ autotest/frontend/client/src/autotest/tko/SpreadsheetDataProcessor.java 2010-05-27 14:44:25.000000000 -0700 @@ -187,7 +187,8 @@ onFinished.execute(); } - public void setHeaders(List<HeaderField> rowFields, List<HeaderField> columnFields, + public void setHeaders(List<? extends HeaderField> rowFields, + List<? extends HeaderField> columnFields, JSONObject queryParameters) { this.rowFields = getHeaderSqlNames(rowFields); this.columnFields = getHeaderSqlNames(columnFields); @@ -199,7 +200,7 @@ dataSource.setQueryParameters(queryParameters); } - private Header getHeaderSqlNames(List<HeaderField> fields) { + private Header getHeaderSqlNames(List<? extends HeaderField> fields) { Header header = new HeaderImpl(); for (HeaderField field : fields) { header.add(field.getSqlName()); --- autotest/frontend/client/src/autotest/tko/TestGroupDataSource.java 2010-05-27 14:44:25.000000000 -0700 +++ autotest/frontend/client/src/autotest/tko/TestGroupDataSource.java 2010-05-27 14:44:25.000000000 -0700 @@ -22,24 +22,24 @@ public static final String PASS_COUNT_FIELD = "pass_count"; public static final String COMPLETE_COUNT_FIELD = "complete_count"; public static final String INCOMPLETE_COUNT_FIELD = "incomplete_count"; - + private JSONArray groupByFields; private JSONArray headerGroups; private JSONArray headerGroupValues; private JSONObject queryParameters; - + public static TestGroupDataSource getTestGroupDataSource() { return new TestGroupDataSource(GROUP_COUNTS_RPC); } - + public static TestGroupDataSource getStatusCountDataSource() { return new TestGroupDataSource(STATUS_COUNTS_RPC); } - + public static TestGroupDataSource getLatestTestsDataSource() { return new TestGroupDataSource(LATEST_TESTS_RPC); } - + // force construction to go through above factory methods private TestGroupDataSource(String dataMethodName) { super(dataMethodName, NUM_GROUPS_RPC); @@ -69,7 +69,7 @@ headerGroupValues = resultObject.get("header_values").isArray(); return new JSONArrayList<JSONObject>(resultObject.get("groups").isArray()); } - + public void setGroupColumns(String[] columns) { groupByFields = new JSONArray(); for (String field : columns) { @@ -77,7 +77,7 @@ } headerGroups = null; } - + public void setHeaderGroups(List<List<String>> headerFieldGroups) { groupByFields = new JSONArray(); headerGroups = new JSONArray(); @@ -88,9 +88,9 @@ } } } - + /** - * Get a list of values for the header group with the given index, as specified to + * Get a list of values for the header group with the given index, as specified to * setHeaderGroups(). */ public List<List<String>> getHeaderGroupValues(int groupIndex) { _______________________________________________ Autotest mailing list [email protected] http://test.kernel.org/cgi-bin/mailman/listinfo/autotest
