Skip to content

IRSA-581: Expose to public Firefly API table selection info. #423

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 26, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 34 additions & 4 deletions src/firefly/html/demo/ffapi-highlevel-test.html
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,16 @@
<a href='javascript:firefly.getViewer().showTable(tblReq3)'>Open a table</a>
<a href='javascript:firefly.getViewer().showTable(tblReq1)'>Open allwise</a>
<a href='javascript:tblReq1.sortInfo="ASC,ra"; firefly.getViewer().fetchTable(tblReq1)'>Sort allwise by ra</a>
<a href='javascript:launchLC()'>Launch WISE LcViewer</a></div>
<div>
<div id="tables-2" style="display: inline-block; width: 550px; height: 300px; margin: 10px; background-color: white"></div>
<div id="tables-1" style="display: inline-block; width: 550px; height: 300px; margin: 10px; background-color: white; position: absolute"></div>
<a href='javascript:launchLC()'>Launch WISE LcViewer</a>
<div style="display: inline-flex; background-color: white">
<div id="tables-2" style="width: 550px; height: 300px; margin: 10px"></div>
<div id="tables-1" style="width: 550px; height: 300px; margin: 10px"></div>
<div>
<div style="font-size: small">show getSelectedData API call to 2nd table of 2nd tablpanel ('http://web.ip....')</div>
<input type="button" value="show selected" onclick="javascript:loadSelectRows()">
<div id="selectedRows" style="height: 275px; overflow: auto"></div>
</div>
</div>
</div>
<div>XYPlot from API calls:
<a href='javascript:firefly.getViewer().showXYPlot(xyPlotOpsReq3)'>Show XY Plot</a>
Expand Down Expand Up @@ -175,6 +181,30 @@

<script type="text/javascript">
{
function loadSelectRows() {
firefly.util.table.getSelectedData(tblReq3.tbl_id, ['crval1', 'crval2'])
.then( function (tableModel) {
var rowCnt = tableModel.totalRows;
var cell = firefly.util.table.getCellValue;
var cnames = firefly.util.table.getColumns(tableModel).map(function (c) {return c.name});

var txt = "<table border='1'><tr>"
cnames.forEach( function(col) {
txt += "<td>" + col + "</td>";
});
txt += "</tr>";
for (var idx =0; idx < rowCnt; idx++) {
txt += "<tr>";
cnames.forEach( function(col) {
txt += "<td>" + cell(tableModel, idx, col) + "</td>";
});
txt += "</tr>";
}
txt += "</table>"
document.getElementById("selectedRows").innerHTML = txt;
});
}

function launchLC(req) {
var req = firefly.util.table.makeFileRequest(null, 'http://web.ipac.caltech.edu/staff/ejoliet/demo/WISE-mep-2764p772_ac51-010204.tbl',null,
{ tbl_id: 'raw_table',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@
import edu.caltech.ipac.firefly.server.rpc.SearchServicesImpl;
import edu.caltech.ipac.firefly.server.util.QueryUtil;
import edu.caltech.ipac.firefly.server.util.ipactable.DataGroupPart;
import edu.caltech.ipac.firefly.server.util.ipactable.IpacTableParser;
import edu.caltech.ipac.firefly.server.util.ipactable.JsonTableUtil;
import edu.caltech.ipac.firefly.server.SrvParam;
import edu.caltech.ipac.util.CollectionUtil;
import edu.caltech.ipac.util.DataGroup;
import edu.caltech.ipac.util.DataObject;
import edu.caltech.ipac.util.StringUtils;
import org.json.simple.JSONObject;
Expand Down Expand Up @@ -70,12 +72,16 @@ public String doCommand(SrvParam params) throws Exception {
String filePath = params.getRequired("filePath");
try {
String selRows = params.getRequired("selectedRows");
String columnName = params.getRequired("columnName");
List<String> columnNames = StringUtils.asList(params.getRequired("columnNames"), ",");
List<Integer> rows = StringUtils.convertToListInteger(selRows, ",");
List<String> values = new SearchManager().getDataFileValues(ServerContext.convertToFile(filePath), rows, columnName);
Map<String, List<String>> rval = new HashMap<>(1);
rval.put("values", values);
return QueryUtil.toJsonObject(rval).toJSONString();
File file = ServerContext.convertToFile(filePath);

if (!file.canRead() ||
!file.getAbsolutePath().startsWith(ServerContext.getWorkingDir().getAbsolutePath())) {
throw new DataAccessException("Unable to access this file:" + file.getAbsolutePath());
}
DataGroup data = IpacTableParser.getSelectedData(file, rows, columnNames.toArray(new String[0]));
return JsonTableUtil.toJsonTableModel(new DataGroupPart(null, data, 0, data.size()), null).toJSONString();
} catch (IOException e) {
throw new DataAccessException("Unable to resolve a search processor for this request. SelectedValues aborted.");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

import edu.caltech.ipac.util.DataGroup;
import edu.caltech.ipac.util.DataObject;
import edu.caltech.ipac.util.DataType;
import edu.caltech.ipac.util.FileUtil;
import edu.caltech.ipac.util.IpacTableUtil;

import java.io.File;
Expand All @@ -17,6 +19,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
* Date: May 14, 2009
Expand All @@ -26,6 +29,68 @@
*/
public class IpacTableParser {

public static DataGroup getSelectedData(File inf, Collection<Integer> indices, String... colNames) throws IOException {

Arrays.sort(colNames);

TableDef meta = IpacTableUtil.getMetaInfo(inf);

List<DataType> selCols;
if (colNames.length == 0) {
selCols = meta.getCols().stream().map(DataType::copyOf).collect(Collectors.toList());
} else {
selCols = Arrays.stream(colNames).map( (s -> {
if (s.equals(DataGroup.ROWID_NAME)) {
return new DataType(s, Long.class);
} else {
DataType dt = meta.getColByName(s);
return dt != null ? dt.copyOf() : new DataType(s, String.class);
}
})).collect(Collectors.toList());
}

DataGroup results = new DataGroup(inf.getName(), selCols);
results.setAttributes(meta.getAttributes());

RandomAccessFile reader = new RandomAccessFile(inf,"r");
try {
ArrayList<Integer> sortedIndices = new ArrayList<Integer>(indices);
Collections.sort(sortedIndices);

DataGroup dg = new DataGroup("dummy", meta.getCols());
boolean hasRowid = dg.containsKey(DataGroup.ROWID_NAME);
long cidx = 0, pidx = -1;
for(int idx : sortedIndices) {
cidx = idx;
advanceReaderToNextIdx(pidx, cidx, meta, reader);
String line = reader.readLine();
if (line != null) {
DataObject row = IpacTableUtil.parseRow(dg, line);
DataObject resRow = new DataObject(results);
for (String s : colNames) {
Object val = null;
if (s.equals(DataGroup.ROWID_NAME) && !hasRowid) {
val = cidx;
} else if (dg.containsKey(s)) {
val = row.getDataElement(s);
}
if (val != null) {
resRow.setDataElement(results.getDataDefintion(s), val);
}
}
results.add(resRow);
}
pidx = idx;
}

} finally {
FileUtil.silentClose(reader);
}

return results;
}


public static MappedData getData(File inf, Collection<Integer> indices, String... colNames) throws IOException {

MappedData results = new MappedData();
Expand All @@ -44,17 +109,7 @@ public static MappedData getData(File inf, Collection<Integer> indices, String..
long cidx = 0, pidx = -1;
for(int idx : sortedIndices) {
cidx = idx;
if (pidx == -1) {
long skip = (cidx * (long)meta.getLineWidth()) + (long)meta.getRowStartOffset();
reader.seek(skip);
} else if (cidx - pidx == 1) {
// next line.. no skipping
} else if (cidx - pidx > 10) {
long skip = (cidx * (long)meta.getLineWidth()) + (long)meta.getRowStartOffset();
reader.seek(skip);
} else {
reader.skipBytes((int) ((cidx-pidx-1) * meta.getLineWidth()));
}
advanceReaderToNextIdx(pidx, cidx, meta, reader);
String line = reader.readLine();
if (line != null) {
DataObject row = IpacTableUtil.parseRow(dg, line);
Expand Down Expand Up @@ -159,4 +214,19 @@ private String makeKey(int idx, String colName) {
}

}

private static void advanceReaderToNextIdx(long pidx, long cidx, TableDef meta, RandomAccessFile reader) throws IOException {
if (pidx == -1) {
long skip = (cidx * (long)meta.getLineWidth()) + (long)meta.getRowStartOffset();
reader.seek(skip);
} else if (cidx - pidx == 1) {
// next line.. no skipping
} else if (cidx - pidx > 10) {
long skip = (cidx * (long)meta.getLineWidth()) + (long)meta.getRowStartOffset();
reader.seek(skip);
} else {
reader.skipBytes((int) ((cidx-pidx-1) * meta.getLineWidth()));
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ public class JsonTableUtil {
*/
public static JSONObject toJsonTableModel(DataGroupPart page, TableServerRequest request) throws IOException {

TableDef meta = page.getTableDef().clone();
TableDef meta = mergeAttributes(page.getTableDef(), page.getData());

if (request != null && request.getMeta() != null) {
for (String key : request.getMeta().keySet()) {
meta.setAttribute(key, request.getMeta(key));
Expand All @@ -52,7 +53,7 @@ public static JSONObject toJsonTableModel(DataGroupPart page, TableServerRequest
tableModel.put("totalRows", page.getRowCount());

if (page.getData() != null ) {
tableModel.put("tableData", toJsonTableData(page.getData(), page.getTableDef()));
tableModel.put("tableData", toJsonTableData(page.getData(), meta));
}


Expand Down Expand Up @@ -96,6 +97,22 @@ public static JSONObject toJsonTableRequest(TableServerRequest req) {
return treq;
}

private static TableDef mergeAttributes(TableDef tblDef, DataGroup data) {
if (tblDef == null) {
tblDef = new TableDef();
}

List<DataGroup.Attribute> dataAttributes = data.getKeywords();
if (dataAttributes != null) {
for (DataGroup.Attribute a : dataAttributes) {
if (!tblDef.contains(a.getKey())) {
tblDef.setAttribute(a.getKey(), a.getValue());
}
}
}
return tblDef;
}

/**
* convert to JSON TableData
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,14 @@ public List<DataType> getCols() {
return cols;
}

public DataType getColByName(String name) {
name = name == null ? "" : name;
for(DataType dt : cols) {
if (dt.getKeyName().equals(name)) return dt;
}
return null;
}

public void setCols(List<DataType> cols) { this.cols = cols; }

/**
Expand Down
12 changes: 12 additions & 0 deletions src/firefly/java/edu/caltech/ipac/util/DataType.java
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,18 @@ public Object clone() throws CloneNotSupportedException {
return dt;
}

/**
* this is similar to clone without having to deal with exception and casting.
* @return
*/
public DataType copyOf() {
try {
return (DataType) clone();
} catch (CloneNotSupportedException e) {
return null; // should not happen;
}
}

/**
* FormatInfo defines the formatting behavior of this DataType.
* This includes column width, column header alignment, column data alignment,
Expand Down
4 changes: 3 additions & 1 deletion src/firefly/java/edu/caltech/ipac/util/StringUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*/
package edu.caltech.ipac.util;

import javax.validation.constraints.NotNull;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
Expand Down Expand Up @@ -129,8 +130,9 @@ public static int[] convertToArrayInt(String str, String regExp) throws NumberFo
return intAry;
}

@NotNull
public static List<Integer> convertToListInteger(String str, String regExp) throws NumberFormatException {
if (isEmpty(str)) return null;
if (isEmpty(str)) return new ArrayList<>();
String[] reqkeys = str.split(regExp);
ArrayList<Integer> list = new ArrayList<Integer>(reqkeys.length);
for (int i = 0; i < reqkeys.length; i++) {
Expand Down
9 changes: 7 additions & 2 deletions src/firefly/js/api/ApiUtilTable.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,10 @@
* License information at https://github.com/Caltech-IPAC/firefly/blob/master/License.txt
*/

export {getTblInfo, getActiveTableId, getTblById, uniqueTblId, getTableSourceUrl, getTableUiByTblId,
makeTblRequest, makeFileRequest, makeIrsaCatalogRequest} from '../tables/TableUtil.js';
export {getTblInfo, getActiveTableId, getTblById, getTableUiByTblId, getTblInfoById,
getTableGroup, findGroupByTblId, getTblIdsByGroup,
uniqueTblId, getTableSourceUrl, onTableLoaded,
makeTblRequest, makeFileRequest, makeIrsaCatalogRequest,
cloneRequest, doFetchTable, getTblRowAsObj,
getColumnIdx, getColumn, getColumns, getCellValue,
getColumnValues, getRowValues, getSelectedData} from '../tables/TableUtil.js';
33 changes: 9 additions & 24 deletions src/firefly/js/rpc/SearchServicesJson.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,19 +84,19 @@ export function findTableIndex(tableRequest, filterInfo) {
}

/**
* returns the values of the data from the given parameters
* returns the table data for the given parameters
* @param {Object} p parameters object
* @param {string} p.columnName name of the column
* @param {string[]} p.columnNames an array of column names
* @param {string} p.filePath location of the file on the server
* @param {string} p.selectedRows a comma-separated string of indices of the rows to get the data from
* @return {Promise}
* @return {Promise<TableModel>}
*/
export const selectedValues = function({columnName, filePath, selectedRows}) {
return doJsonRequest(ServerParams.SELECTED_VALUES, {columnName, filePath, selectedRows})
.then((data) => {
// JsonUtil may not interpret array values correctly due to error-checking.
// returning array as a prop 'values' inside an object instead.
return get(data, 'values');
export const selectedValues = function({columnNames, filePath, selectedRows}) {
columnNames = Array.isArray(columnNames) ? columnNames.join() : String(columnNames);
selectedRows = Array.isArray(selectedRows) ? selectedRows.join() : String(selectedRows);
return doJsonRequest(ServerParams.SELECTED_VALUES, {columnNames, filePath, selectedRows})
.then((tableModel) => {
return tableModel;
});
};

Expand Down Expand Up @@ -193,21 +193,6 @@ export const cancel= function(id) {
).then( () => true);
};

/**
*
* @param {string} id background id
* @return {Promise}
* @deprecated
*/
export const addIDToPushCriteria= function(id) {
// not used in converted code.

// var paramList = [];
// paramList.push({name: ServerParams.ID, value: id});
// return doJsonRequest(ServerParams.ADD_ID_TO_CRITERIA, paramList
// ).then( () => true);
};

/**
*
* @param {string} fileKey
Expand Down
1 change: 0 additions & 1 deletion src/firefly/js/tables/TableConnector.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {isEmpty, omitBy, isUndefined, cloneDeep, get, set} from 'lodash';
import * as TblCntlr from './TablesCntlr.js';
import * as TblUtil from './TableUtil.js';
import {SelectInfo} from './SelectInfo.js';
import {selectedValues} from '../rpc/SearchServicesJson.js';

export class TableConnector {

Expand Down
Loading