Skip to content

FIREFLY-148: Refactor file analysis to make it more general #834

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 4 commits into from
Jul 18, 2019
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
14 changes: 14 additions & 0 deletions src/firefly/html/css/global.css
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,20 @@ div.rootStyle>img, div.rootStyle > html {
font-weight: bold;
}


.keyword-label {
font-weight: bold;
margin-right: 3px;
}

.keyword-value {
color: maroon;
margin-right: 10px;
text-overflow: ellipsis;
}



/*-------------------< loading mask ---------------------*/
.loading-mask {
position: absolute;
Expand Down
207 changes: 207 additions & 0 deletions src/firefly/java/edu/caltech/ipac/firefly/core/FileAnalysis.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
/*
* License information at https://github.com/Caltech-IPAC/firefly/blob/master/License.txt
*/

package edu.caltech.ipac.firefly.core;

import edu.caltech.ipac.firefly.messaging.JsonHelper;
import edu.caltech.ipac.table.DataGroup;
import edu.caltech.ipac.table.JsonTableUtil;
import edu.caltech.ipac.table.TableUtil;
import edu.caltech.ipac.table.TableUtil.Format;
import edu.caltech.ipac.table.io.DsvTableIO;
import edu.caltech.ipac.table.io.IpacTableReader;
import edu.caltech.ipac.table.io.VoTableReader;
import edu.caltech.ipac.util.FitsHDUUtil;
import edu.caltech.ipac.util.StringUtils;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

import static edu.caltech.ipac.util.StringUtils.isEmpty;

/**
* Date: 2019-06-27
*
* @author loi
* @version $Id: $
*/
public class FileAnalysis {
public enum ReportType {Brief, // expect to only get a report with one part without details
Normal, // a report with all parts populated, but not details
Details} // a full report with details
public enum Type {Image, Table, Spectrum, HeaderOnly, Unknown}


public static Report analyze(File infile, ReportType type) throws Exception {

ReportType mtype = type == ReportType.Brief ? ReportType.Normal : type;

Format format = TableUtil.guessFormat(infile);
Report report;
switch (format) {
case VO_TABLE:
report = VoTableReader.analyze(infile, mtype);
break;
case FITS:
report = FitsHDUUtil.analyze(infile, mtype);
break;
case IPACTABLE:
report = IpacTableReader.analyze(infile, mtype);
break;
case CSV:
case TSV:
report = DsvTableIO.analyze(infile, format.type, mtype);
break;
default:
report = new Report(type, Format.UNKNOWN.name(), infile.length(), infile.getAbsolutePath());
}

if (type == ReportType.Brief) {
report.makeBrief();
}
return report;
};

public static String toJsonString(Report report) {
JsonHelper helper = new JsonHelper();
helper.setValue(report.filePath, "filePath");
helper.setValue(report.fileName, "fileName");
helper.setValue(report.fileSize, "fileSize");
helper.setValue(report.type.name(), "type");
helper.setValue(report.fileFormat, "fileFormat");
helper.setValue(report.getDataType(), "dataTypes");
if (report.getParts() != null) {
for(int i = 0; i < report.getParts().size(); i++) {
Part p = report.getParts().get(i);
helper.setValue(p.index, "parts", i+"", "index");
helper.setValue(p.type.name(), "parts", i+"", "type");
helper.setValue(p.desc, "parts", i+"", "desc");
if (!isEmpty(p.getDetails())) {
helper.setValue(JsonTableUtil.toJsonDataGroup(p.getDetails()), "parts", i+"", "details");
}
}
}
return helper.toJson();
}


//====================================================================
//
//====================================================================

public static class Report {
private ReportType type;
private long fileSize;
private String filePath;
private String fileName;
private String fileFormat;
private List<Part> parts;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We talked about putting the file format type here as well

private String dataType;

public Report(ReportType type, String fileFormat, long fileSize, String filePath) {
this.type = type;
this.fileFormat = fileFormat;
this.fileSize = fileSize;
this.filePath = filePath;
}

public ReportType getType() {
return type;
}

public String getFormat() { return fileFormat; }

public long getFileSize() {
return fileSize;
}

public String getFilePath() {
return filePath;
}

public List<Part> getParts() {
return parts;
}

public String getFileName() { return fileName; }

public void setFileName(String fileName) { this.fileName = fileName; }

public void addPart(Part part) {
if (parts == null) parts = new ArrayList<>();
parts.add(part);
}

public String getDataType() {
if (dataType == null) {
if (parts != null) {
if (parts.size() == 1) {
dataType = parts.get(0).type.name();
} else {
List<String> types = parts.stream().map(part -> part.type.name()).distinct().collect(Collectors.toList());
dataType = StringUtils.toString(types);
}
} else {
dataType = "";
}
}
return dataType;
}

/**
* convert this report into a Brief version.
*/
void makeBrief() {
if (type == ReportType.Brief) return; // nothing to do
getDataType(); // init dataType
if (parts != null) {
// keep only the first part with data.
Part first = parts.stream()
.filter(p -> !Arrays.asList(Type.HeaderOnly, Type.Unknown).contains(p.getType()))
.findFirst()
.orElse(null);
if (first != null) {
parts = Collections.singletonList(first);
}
}
}
}

public static class Part {
private Type type;
private int index;
private String desc;
private DataGroup details;

public Part(Type type) {
this.type = type;
}

public Part(Type type, int index, String desc) {
this.type = type;
this.index = index;
this.desc = desc;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there could be a detailed description here that we could start using in certain use cases.

}

public Type getType() { return type; }
public void setType(Type type) { this.type = type; }

public int getIndex() { return index; }
public void setIndex(int index) { this.index = index; }

public String getDesc() { return desc;}
public void setDesc(String desc) { this.desc = desc; }

public DataGroup getDetails() {
return details;
}
public void setDetails(DataGroup details) {
this.details = details;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -187,5 +187,6 @@ public class ServerParams {
public static final String WS_CREATE_FOLDER = "wsParent";
public static final String SOURCE_FROM = "sourceFrom";
public static final String IS_WS = "isWs";
public static final String FILE_ANALYSIS = "fileAnalysis";
}

Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,12 @@ private Consumer getContainer(String[] paths) {
}

private Object ensureCont(Object cont, String key) {
if (cont != null) return cont;
int idx = getInt(key, -1);
return idx == -1 ? new HashMap() : ensureList(new ArrayList(), idx);
if (cont == null) {
cont = idx == -1 ? new HashMap() :new ArrayList();
}
if (idx >= 0 && cont instanceof List) cont = ensureList((List) cont, idx);
return cont;
}

private Object getCont(Object source, String key, String nkey) {
Expand All @@ -130,6 +133,8 @@ private Object getCont(Object source, String key, String nkey) {
if (cont == null) {
cont = ensureCont(cont, nkey);
clist.set(idx, cont);
} else {
cont = ensureCont(cont, nkey);
}
return cont;
} else if (source instanceof Map) {
Expand All @@ -138,6 +143,8 @@ private Object getCont(Object source, String key, String nkey) {
if (cont == null) {
cont = ensureCont(cont, nkey);
cmap.put(key, cont);
} else {
cont = ensureCont(cont, nkey);
}
return cont;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ private static void initCommand() {
_cmdMap.put(ServerParams.CREATE_DOWNLOAD_SCRIPT, new SearchServerCommands.CreateDownloadScript());
_cmdMap.put(ServerParams.PACKAGE_REQUEST, new SearchServerCommands.PackageRequest());
_cmdMap.put(ServerParams.TABLE_SEARCH, new SearchServerCommands.TableSearch());
_cmdMap.put(ServerParams.QUERY_TABLE, new SearchServerCommands.QueryTable());
_cmdMap.put(ServerParams.QUERY_TABLE, new SearchServerCommands.QueryTable());
_cmdMap.put(ServerParams.SELECTED_VALUES, new SearchServerCommands.SelectedValues());
_cmdMap.put(ServerParams.JSON_SEARCH, new SearchServerCommands.JsonSearch());

Expand All @@ -98,6 +98,8 @@ private static void initCommand() {

_cmdMap.put(ServerParams.RESOLVE_NAME, new ResolveServerCommands.ResolveName());
_cmdMap.put(ServerParams.RESOLVE_NAIFID, new ResolveServerCommands.ResolveNaifidName());
_cmdMap.put(ServerParams.FILE_ANALYSIS, new ResolveServerCommands.FileAnalysisCmd());

_cmdMap.put(ServerParams.VIS_PUSH_ALIVE_CHECK, new PushCommands.PushAliveCheck());
_cmdMap.put(ServerParams.VIS_PUSH_ALIVE_COUNT, new PushCommands.PushAliveCount());
_cmdMap.put(ServerParams.VIS_PUSH_ACTION, new PushCommands.PushAction());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ public static SrvParam makeSrvParamSimpleMap(Map<String, String> map) {
return new SrvParam(targetMap);
}

public void setParam(String key, String value) {
paramMap.put(key, new String[] {value});
}

public void addParams(Map<String, String> map) {
for( Map.Entry<String,String> entry : map.entrySet()) {
if (!paramMap.containsKey(entry.getKey())) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import edu.caltech.ipac.table.DataType;
import edu.caltech.ipac.util.StringUtils;
import org.apache.commons.codec.digest.DigestUtils;
import org.json.simple.JSONObject;
import org.springframework.core.NestedRuntimeException;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
Expand Down Expand Up @@ -239,6 +240,8 @@ protected FileInfo ingestDataIntoDb(TableServerRequest req, File dbFile) throws
DataGroup dg = fetchDataGroup(req);
StopWatch.getInstance().stop("fetchDataGroup: " + req.getRequestId()).printLog("fetchDataGroup: " + req.getRequestId());

if (dg == null) throw new DataAccessException("Failed to retrieve data");

prepareTableMeta(dg.getTableMeta(), Arrays.asList(dg.getDataDefinitions()), req);
TableUtil.consumeColumnMeta(dg, null); // META-INFO in the request should only be pass-along and not persist.

Expand Down Expand Up @@ -563,8 +566,10 @@ private static void enumeratedValuesCheckBG(File dbFile, DataGroupPart results,
enumeratedValuesCheck(dbFile, results, treq);
DataGroup updates = new DataGroup(null, results.getData().getDataDefinitions());
updates.getTableMeta().setTblId(results.getData().getTableMeta().getTblId());
JSONObject changes = JsonTableUtil.toJsonDataGroup(updates);
changes.remove("totalRows"); //changes contains only the columns with 0 rows.. we don't want to update totalRows

FluxAction action = new FluxAction(FluxAction.TBL_UPDATE, JsonTableUtil.toJsonDataGroup(updates));
FluxAction action = new FluxAction(FluxAction.TBL_UPDATE, changes);
ServerEventManager.fireAction(action, target);
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@

import edu.caltech.ipac.astro.net.HorizonsEphPairs;
import edu.caltech.ipac.astro.net.Resolver;
import edu.caltech.ipac.firefly.core.FileAnalysis;
import edu.caltech.ipac.firefly.data.ServerParams;
import edu.caltech.ipac.firefly.server.ServCommand;
import edu.caltech.ipac.firefly.server.SrvParam;
import edu.caltech.ipac.util.StringUtils;
import edu.caltech.ipac.visualize.plot.ResolvedWorldPt;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

Expand Down Expand Up @@ -76,5 +79,25 @@ public String doCommand(SrvParam sp) throws Exception {

public boolean getCanCreateJson() { return true; }
}


public static class FileAnalysisCmd extends ServCommand {


public String doCommand(SrvParam sp) throws Exception {

String infile = null;
try {
infile = sp.getRequired("filePath");
String rtype = sp.getOptional("reportType");
FileAnalysis.ReportType reportType = StringUtils.isEmpty(rtype) ? FileAnalysis.ReportType.Brief : FileAnalysis.ReportType.valueOf(rtype); // defaults to Brief
FileAnalysis.Report report = FileAnalysis.analyze(new File(infile), reportType);
return FileAnalysis.toJsonString(report);
}catch (Exception e){
throw new Exception("Fail to analyze file: "+ infile);
}
}
}

}

Loading