]> gitweb.fperrin.net Git - GpsPrune.git/blob - src/tim/prune/load/json/JsonFileLoader.java
Version 20.4, May 2021
[GpsPrune.git] / src / tim / prune / load / json / JsonFileLoader.java
1 package tim.prune.load.json;
2
3 import java.io.BufferedReader;
4 import java.io.File;
5 import java.io.FileReader;
6 import java.io.IOException;
7 import java.util.ArrayList;
8 import java.util.Stack;
9
10 import tim.prune.App;
11 import tim.prune.data.Field;
12 import tim.prune.data.SourceInfo;
13
14
15 /**
16  * Class to handle the loading of GeoJSON files
17  */
18 public class JsonFileLoader
19 {
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;
27
28
29         /**
30          * Constructor
31          * @param inApp App object
32          */
33         public JsonFileLoader(App inApp)
34         {
35                 _app = inApp;
36                 _jsonBlocks = new Stack<JsonBlock>();
37                 _jsonPoints = new ArrayList<JsonPoint>();
38         }
39
40         /**
41          * Open the selected file
42          * @param inFile File to open
43          */
44         public void openFile(File inFile)
45         {
46                 BufferedReader reader = null;
47                 try
48                 {
49                         reader = new BufferedReader(new FileReader(inFile));
50                         String currLine = reader.readLine();
51                         while (currLine != null)
52                         {
53                                 processTokensInLine(currLine);
54                                 // Read next line, if any
55                                 currLine = reader.readLine();
56                         }
57                 }
58                 catch (IOException ioe) {
59                         _app.showErrorMessage("error.load.dialogtitle", "error.load.noread");
60                 }
61                 finally
62                 {
63                         // close file ignoring errors
64                         try {
65                                 if (reader != null) reader.close();
66                         }
67                         catch (Exception e) {}
68                 }
69                 if (_jsonPoints.size() > 0)
70                 {
71                         Field[] fields = {Field.LATITUDE, Field.LONGITUDE, Field.ALTITUDE,
72                                 Field.NEW_SEGMENT};
73                         _app.informDataLoaded(fields, makeDataArray(),
74                                 null, new SourceInfo(inFile, SourceInfo.FILE_TYPE.JSON), null);
75                 }
76                 // TODO: Show message if nothing was found?
77         }
78
79         /** Split the given line from the json into tokens
80          *  and process them one by one */
81         private void processTokensInLine(String inLine)
82         {
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())
89                 {
90                         if (insideQuotes || x=='"') {
91                                 currToken.append(x);
92                         }
93                         else
94                         {
95                                 if (" :,".indexOf(x) >= 0) {
96                                         processToken(currToken.toString());
97                                         currToken.setLength(0);
98                                 }
99                                 else if ("[{".indexOf(x) >= 0) {
100                                         // start of a new block
101                                         _jsonBlocks.add(new JsonBlock());
102                                 }
103                                 else if ("]}".indexOf(x) >= 0)
104                                 {
105                                         processToken(currToken.toString());
106                                         currToken.setLength(0);
107                                         // end of the current block
108                                         processBlock(_jsonBlocks.pop());
109                                 }
110                                 else {
111                                         currToken.append(x);
112                                 }
113                         }
114                         if (x == '"' && !previousSlash) {insideQuotes = !insideQuotes;}
115                         previousSlash = (x == '\\') && !previousSlash;
116                 }
117                 processToken(currToken.toString());
118         }
119
120         private void processToken(String inToken)
121         {
122                 if (inToken == null || inToken.isBlank()) {return;}
123                 if (inToken.equals("\"coordinates\"")) {
124                         _newSegment = true;
125                 }
126                 _jsonBlocks.peek().addToken(inToken);
127         }
128
129         /** Process the end of the given block */
130         private void processBlock(JsonBlock inBlock)
131         {
132                 if (inBlock.areFieldsValid())
133                 {
134                         _jsonPoints.add(inBlock.createSinglePoint(_newSegment));
135                         _newSegment = false;
136                 }
137                 else if (inBlock.areSingleCoordsValid())
138                 {
139                         // block contains a single point - pass to parent list
140                         _jsonBlocks.peek().addSingleCoordsFrom(inBlock);
141                 }
142                 else if (inBlock.isCoordListValid())
143                 {
144                         // block contains a list of point coords
145                         _jsonBlocks.peek().addCoordListFrom(inBlock);
146                 }
147                 else if (inBlock.hasValidCoordList())
148                 {
149                         for (int i=0; i<inBlock.getNumPoints(); i++)
150                         {
151                                 _jsonPoints.add(inBlock.createPointFromList(i));
152                         }
153                         _newSegment = true;
154                 }
155         }
156
157         /**
158          * Make an object array from the data list
159          * @return object array for loading
160          */
161         private Object[][] makeDataArray()
162         {
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"};
167                 }
168                 return result;
169         }
170 }