1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
|
package tim.prune.load.json;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import javax.swing.JOptionPane;
import tim.prune.App;
import tim.prune.data.Altitude;
import tim.prune.data.DataPoint;
import tim.prune.data.FileType;
import tim.prune.data.Latitude;
import tim.prune.data.Longitude;
import tim.prune.data.SourceInfo;
import tim.prune.data.UnitSetLibrary;
import tim.prune.load.FileToBeLoaded;
import tim.prune.load.FileTypeLoader;
/**
* Class to handle the loading of GeoJSON files
*/
public class JsonFileLoader extends FileTypeLoader
{
/** Stack of blocks */
private final Stack<JsonBlock> _jsonBlocks;
/** List of points extracted */
private final ArrayList<JsonPoint> _jsonPoints;
private boolean _newSegment = true;
/**
* Constructor
* @param inApp App object
*/
public JsonFileLoader(App inApp)
{
super(inApp);
_jsonBlocks = new Stack<JsonBlock>();
_jsonPoints = new ArrayList<JsonPoint>();
}
/**
* Open the selected file
* @param inFileLock File to open
* @param inAutoAppend true to automatically append
*/
public void openFile(FileToBeLoaded inFileLock, boolean inAutoAppend)
{
try (BufferedReader reader = new BufferedReader(new FileReader(inFileLock.getFile())))
{
String currLine = reader.readLine();
while (currLine != null)
{
processTokensInLine(currLine);
// Read next line, if any
currLine = reader.readLine();
}
}
catch (IOException ioe) {
getApp().showErrorMessage("error.load.dialogtitle", "error.load.noread");
}
if (!_jsonPoints.isEmpty())
{
int appendOption = getAppendOption(inAutoAppend);
if (appendOption == JOptionPane.CANCEL_OPTION) {
return;
}
loadData(makePointList(), new SourceInfo(inFileLock.getFile(), FileType.JSON),
appendOption == JOptionPane.YES_OPTION);
}
// 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.trim();
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<inBlock.getNumPoints(); i++) {
_jsonPoints.add(inBlock.createPointFromList(i));
}
_newSegment = true;
}
}
/**
* @return list of points to load
*/
private List<DataPoint> makePointList()
{
ArrayList<DataPoint> points = new ArrayList<>();
for (JsonPoint jsonPoint : _jsonPoints)
{
DataPoint point = new DataPoint(Latitude.make(jsonPoint._latitude),
Longitude.make(jsonPoint._longitude),
new Altitude(jsonPoint._altitude, UnitSetLibrary.UNITS_METRES));
if (point.isValid())
{
point.setSegmentStart(jsonPoint._newSegment);
points.add(point);
}
}
return points;
}
}
|