File: JsonBlock.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 (227 lines) | stat: -rw-r--r-- 6,211 bytes parent folder | download | duplicates (5)
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
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
package tim.prune.load.json;

import java.util.ArrayList;

/**
 * Structure to hold the contents of a Json block during parsing.
 * This will be held within the current [] or {} block
 */
public class JsonBlock
{
	private String _latitude = null;
	private String _longitude = null;
	private String _altitude = null;

	private Expectation _nextField = Expectation.NONE;
	private BlockType _type = BlockType.NONE;
	private boolean _hasNonNumbers = false;
	private ArrayList<String> _pointCoords = null;
	private ArrayList<ArrayList<String>> _coordList = null;


	private enum BlockType {
		NONE, FIELDS, POINTCOORDS, ISPOINTLIST, HASPOINTLIST
	}
	private enum Expectation {
		NONE, LATITUDE, LONGITUDE, ALTITUDE, COORDS
	}

	/** Internal method to remove quotes and NaNs from altitude strings */
	private String modifyAltitudeString(String inAlt)
	{
		if (inAlt == null || inAlt.equals("") || inAlt.equals("\"\"")) {
			return null;
		}
		String result = inAlt;
		if (inAlt.length() > 2 && inAlt.startsWith("\"") && inAlt.endsWith("\""))
		{
			result = inAlt.substring(1, inAlt.length()-1);
		}
		if (result.equals("NaN")) {return null;}
		return result;
	}

	/**
	 * Receive a token to this block
	 * @param inToken token from Json source
	 */
	public void addToken(String inToken)
	{
		if (inToken == null || inToken.isEmpty()) {return;}
		if (!_hasNonNumbers && !looksLikeNumber(inToken)) {
			_hasNonNumbers = true;
		}
		if (inToken.equals("\"latitude\"")) {
			_nextField = Expectation.LATITUDE;
		}
		else if (inToken.equals("\"longitude\"")) {
			_nextField = Expectation.LONGITUDE;
		}
		else if (inToken.equals("\"altitude\"")) {
			_nextField = Expectation.ALTITUDE;
		}
		else if (inToken.equals("\"coordinates\"")) {
			_nextField = Expectation.COORDS;
		}
		else
		{
			switch (_nextField)
			{
				case LATITUDE:
					_latitude = inToken;
					_type = BlockType.FIELDS;
					break;
				case LONGITUDE:
					_longitude = inToken;
					_type = BlockType.FIELDS;
					break;
				case ALTITUDE:
					_altitude = modifyAltitudeString(inToken);
					_type = BlockType.FIELDS;
					break;
				default:
					if (!_hasNonNumbers && looksLikeNumber(inToken))
					{
						if (_pointCoords == null) {
							_pointCoords = new ArrayList<String>();
						}
						_pointCoords.add(inToken);
						_type = BlockType.POINTCOORDS;
					}
					break;
			}
			_nextField = Expectation.NONE;
		}
	}

	/** @return true if String can be parsed as a double */
	private static boolean looksLikeNumber(String inToken)
	{
		double value = Double.NaN;
		try {
			value = Double.parseDouble(inToken);
		}
		catch (NumberFormatException nfe) {}
		return !Double.isNaN(value);
	}

	/** @return true if named fields are valid */
	public boolean areFieldsValid() {
		return _type == BlockType.FIELDS && _latitude != null && _longitude != null;
	}

	/** @return true if list of 2 or 3 doubles for a single point is valid */
	public boolean areSingleCoordsValid()
	{
		return !_hasNonNumbers && _pointCoords != null
			&& _pointCoords.size() >= 2 && _pointCoords.size() <= 3;
	}

	/**
	 * @param inNewSegment new segment flag
	 * @return created point
	 */
	public JsonPoint createSinglePoint(boolean inNewSegment)
	{
		return new JsonPoint(_latitude, _longitude, _altitude, inNewSegment);
	}

	/**
	 * Child block has finished processing a single set of point coordinates
	 * @param inChild child block
	 */
	public void addSingleCoordsFrom(JsonBlock inChild)
	{
		if (_type == BlockType.NONE && _nextField == Expectation.COORDS
			&& inChild._type == BlockType.POINTCOORDS)
		{
			// Named coordinates field
			_type = BlockType.FIELDS;
			_longitude = inChild.getSinglePointCoords(0);
			_latitude = inChild.getSinglePointCoords(1);
			_altitude = inChild.getSinglePointCoords(2);
		}
		else if ((_type == BlockType.NONE || _type == BlockType.ISPOINTLIST)
			&& !_hasNonNumbers && _nextField == Expectation.NONE
			&& inChild._type == BlockType.POINTCOORDS)
		{
			// add coordinates to list
			_type = BlockType.ISPOINTLIST;
			if (_coordList == null) {
				_coordList = new ArrayList<ArrayList<String>>();
			}
			_coordList.add(inChild._pointCoords);
		}
	}

	/** @return point coordinate for given index, or null if not present */
	private String getSinglePointCoords(int inIndex)
	{
		if (_pointCoords == null || inIndex < 0 || inIndex >= _pointCoords.size()) {
			return null;
		}
		return _pointCoords.get(inIndex);
	}

	/** @return true if list of point coords is valid */
	public boolean isCoordListValid()
	{
		return !_hasNonNumbers && _type == BlockType.ISPOINTLIST
			&& _coordList != null;
	}

	/** @return true if this block has a valid list of point coords */
	public boolean hasValidCoordList()
	{
		return _type == BlockType.HASPOINTLIST && _coordList != null;
	}

	/**
	 * Child block has finished processing a list of point coordinates
	 * @param inChild child block
	 */
	public void addCoordListFrom(JsonBlock inChild)
	{
		if (_type == BlockType.NONE && _nextField == Expectation.COORDS
			&& inChild._type == BlockType.ISPOINTLIST)
		{
			_coordList = inChild._coordList;
			_type = BlockType.HASPOINTLIST;
		}
		else if ((_type == BlockType.NONE || _type == BlockType.ISPOINTLIST)
			&& !_hasNonNumbers && inChild._type == BlockType.ISPOINTLIST)
		{
			if (_coordList == null) {
				_coordList = new ArrayList<ArrayList<String>>();
			}
			_coordList.addAll(inChild._coordList);
			_type = BlockType.ISPOINTLIST;
		}
	}

	/**
	 * @return number of points in the list, if this block has a list
	 */
	public int getNumPoints()
	{
		if (hasValidCoordList()) {
			return _coordList.size();
		}
		return 0;
	}

	/**
	 * @param inIndex point index within list
	 * @return created point for specified index
	 */
	public JsonPoint createPointFromList(int inIndex)
	{
		if (inIndex < 0 || inIndex >= getNumPoints()) {return null;}
		ArrayList<String> pointCoords = _coordList.get(inIndex);
		if (pointCoords.size() < 2 || pointCoords.size() > 3) {return null;}
		final String longitude = pointCoords.get(0);
		final String latitude = pointCoords.get(1);
		final String altitude = ((pointCoords.size() == 3) ? pointCoords.get(2) : null);
		return new JsonPoint(latitude, longitude, altitude, inIndex == 0);
	}
}