File: JsonFileLoader.java

package info (click to toggle)
gpsprune 26.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 5,824 kB
  • sloc: java: 52,154; sh: 25; makefile: 21; python: 15
file content (176 lines) | stat: -rw-r--r-- 4,440 bytes parent folder | download | duplicates (4)
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;
	}
}