X-Git-Url: https://gitweb.fperrin.net/?p=GpsPrune.git;a=blobdiff_plain;f=src%2Ftim%2Fprune%2Fload%2Fjson%2FJsonFileLoader.java;fp=src%2Ftim%2Fprune%2Fload%2Fjson%2FJsonFileLoader.java;h=e1df6665fa20c1239057c783b0a16a3617669398;hp=0000000000000000000000000000000000000000;hb=cd5dd0c207b676067e85e0885b90f05445b7e229;hpb=1db53356139320890a8d10e982865a1899e11b81 diff --git a/src/tim/prune/load/json/JsonFileLoader.java b/src/tim/prune/load/json/JsonFileLoader.java new file mode 100644 index 0000000..e1df666 --- /dev/null +++ b/src/tim/prune/load/json/JsonFileLoader.java @@ -0,0 +1,170 @@ +package tim.prune.load.json; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Stack; + +import tim.prune.App; +import tim.prune.data.Field; +import tim.prune.data.SourceInfo; + + +/** + * Class to handle the loading of GeoJSON files + */ +public class JsonFileLoader +{ + /** App for callback of file loading */ + private App _app = null; + /** Stack of blocks */ + private Stack _jsonBlocks = null; + /** List of points extracted */ + private ArrayList _jsonPoints = null; + private boolean _newSegment = true; + + + /** + * Constructor + * @param inApp App object + */ + public JsonFileLoader(App inApp) + { + _app = inApp; + _jsonBlocks = new Stack(); + _jsonPoints = new ArrayList(); + } + + /** + * Open the selected file + * @param inFile File to open + */ + public void openFile(File inFile) + { + BufferedReader reader = null; + try + { + reader = new BufferedReader(new FileReader(inFile)); + String currLine = reader.readLine(); + while (currLine != null) + { + processTokensInLine(currLine); + // Read next line, if any + currLine = reader.readLine(); + } + } + catch (IOException ioe) { + _app.showErrorMessage("error.load.dialogtitle", "error.load.noread"); + } + finally + { + // close file ignoring errors + try { + if (reader != null) reader.close(); + } + catch (Exception e) {} + } + if (_jsonPoints.size() > 0) + { + Field[] fields = {Field.LATITUDE, Field.LONGITUDE, Field.ALTITUDE, + Field.NEW_SEGMENT}; + _app.informDataLoaded(fields, makeDataArray(), + null, new SourceInfo(inFile, SourceInfo.FILE_TYPE.JSON), null); + } + // TODO: Show message if nothing was found? + } + + /** Split the given line from the json into tokens + * and process them one by one */ + private void processTokensInLine(String inLine) + { + if (inLine == null) {return;} + String line = inLine.strip(); + StringBuilder currToken = new StringBuilder(); + boolean insideQuotes = false; + boolean previousSlash = false; + for (char x : line.toCharArray()) + { + if (insideQuotes || x=='"') { + currToken.append(x); + } + else + { + if (" :,".indexOf(x) >= 0) { + processToken(currToken.toString()); + currToken.setLength(0); + } + else if ("[{".indexOf(x) >= 0) { + // start of a new block + _jsonBlocks.add(new JsonBlock()); + } + else if ("]}".indexOf(x) >= 0) + { + processToken(currToken.toString()); + currToken.setLength(0); + // end of the current block + processBlock(_jsonBlocks.pop()); + } + else { + currToken.append(x); + } + } + if (x == '"' && !previousSlash) {insideQuotes = !insideQuotes;} + previousSlash = (x == '\\') && !previousSlash; + } + processToken(currToken.toString()); + } + + private void processToken(String inToken) + { + if (inToken == null || inToken.isBlank()) {return;} + if (inToken.equals("\"coordinates\"")) { + _newSegment = true; + } + _jsonBlocks.peek().addToken(inToken); + } + + /** Process the end of the given block */ + private void processBlock(JsonBlock inBlock) + { + if (inBlock.areFieldsValid()) + { + _jsonPoints.add(inBlock.createSinglePoint(_newSegment)); + _newSegment = false; + } + else if (inBlock.areSingleCoordsValid()) + { + // block contains a single point - pass to parent list + _jsonBlocks.peek().addSingleCoordsFrom(inBlock); + } + else if (inBlock.isCoordListValid()) + { + // block contains a list of point coords + _jsonBlocks.peek().addCoordListFrom(inBlock); + } + else if (inBlock.hasValidCoordList()) + { + for (int i=0; i