1 package tim.prune.load.json;
3 import java.io.BufferedReader;
5 import java.io.FileReader;
6 import java.io.IOException;
7 import java.util.ArrayList;
8 import java.util.Stack;
11 import tim.prune.data.Field;
12 import tim.prune.data.SourceInfo;
16 * Class to handle the loading of GeoJSON files
18 public class JsonFileLoader
20 /** App for callback of file loading */
21 private App _app = null;
22 /** Stack of blocks */
23 private Stack<JsonBlock> _jsonBlocks = null;
24 /** List of points extracted */
25 private ArrayList<JsonPoint> _jsonPoints = null;
26 private boolean _newSegment = true;
31 * @param inApp App object
33 public JsonFileLoader(App inApp)
36 _jsonBlocks = new Stack<JsonBlock>();
37 _jsonPoints = new ArrayList<JsonPoint>();
41 * Open the selected file
42 * @param inFile File to open
44 public void openFile(File inFile)
46 BufferedReader reader = null;
49 reader = new BufferedReader(new FileReader(inFile));
50 String currLine = reader.readLine();
51 while (currLine != null)
53 processTokensInLine(currLine);
54 // Read next line, if any
55 currLine = reader.readLine();
58 catch (IOException ioe) {
59 _app.showErrorMessage("error.load.dialogtitle", "error.load.noread");
63 // close file ignoring errors
65 if (reader != null) reader.close();
67 catch (Exception e) {}
69 if (_jsonPoints.size() > 0)
71 Field[] fields = {Field.LATITUDE, Field.LONGITUDE, Field.ALTITUDE,
73 _app.informDataLoaded(fields, makeDataArray(),
74 null, new SourceInfo(inFile, SourceInfo.FILE_TYPE.JSON), null);
76 // TODO: Show message if nothing was found?
79 /** Split the given line from the json into tokens
80 * and process them one by one */
81 private void processTokensInLine(String inLine)
83 if (inLine == null) {return;}
84 String line = inLine.strip();
85 StringBuilder currToken = new StringBuilder();
86 boolean insideQuotes = false;
87 boolean previousSlash = false;
88 for (char x : line.toCharArray())
90 if (insideQuotes || x=='"') {
95 if (" :,".indexOf(x) >= 0) {
96 processToken(currToken.toString());
97 currToken.setLength(0);
99 else if ("[{".indexOf(x) >= 0) {
100 // start of a new block
101 _jsonBlocks.add(new JsonBlock());
103 else if ("]}".indexOf(x) >= 0)
105 processToken(currToken.toString());
106 currToken.setLength(0);
107 // end of the current block
108 processBlock(_jsonBlocks.pop());
114 if (x == '"' && !previousSlash) {insideQuotes = !insideQuotes;}
115 previousSlash = (x == '\\') && !previousSlash;
117 processToken(currToken.toString());
120 private void processToken(String inToken)
122 if (inToken == null || inToken.isBlank()) {return;}
123 if (inToken.equals("\"coordinates\"")) {
126 _jsonBlocks.peek().addToken(inToken);
129 /** Process the end of the given block */
130 private void processBlock(JsonBlock inBlock)
132 if (inBlock.areFieldsValid())
134 _jsonPoints.add(inBlock.createSinglePoint(_newSegment));
137 else if (inBlock.areSingleCoordsValid())
139 // block contains a single point - pass to parent list
140 _jsonBlocks.peek().addSingleCoordsFrom(inBlock);
142 else if (inBlock.isCoordListValid())
144 // block contains a list of point coords
145 _jsonBlocks.peek().addCoordListFrom(inBlock);
147 else if (inBlock.hasValidCoordList())
149 for (int i=0; i<inBlock.getNumPoints(); i++)
151 _jsonPoints.add(inBlock.createPointFromList(i));
158 * Make an object array from the data list
159 * @return object array for loading
161 private Object[][] makeDataArray()
163 Object[][] result = new Object[_jsonPoints.size()][];
164 for (int i=0; i<_jsonPoints.size(); i++) {
165 JsonPoint point = _jsonPoints.get(i);
166 result[i] = new String[] {point._latitude, point._longitude, point._altitude, point._newSegment?"1":"0"};