Skip to content

Commit 3a32408

Browse files
committed
Changed how locations are handled
1 parent 4de7070 commit 3a32408

14 files changed

Lines changed: 124 additions & 157 deletions

File tree

FROST-Server.Core/src/main/java/de/fraunhofer/iosb/ilt/frostserver/json/deserialize/custom/CustomEntityDeserializer.java

Lines changed: 6 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,6 @@ public Entity deserialize(JsonParser parser, DeserializationContext ctxt) throws
114114

115115
boolean failOnUnknown = ctxt.isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
116116

117-
DelayedField delayedField = null;
118117
JsonToken currentToken = parser.nextToken();
119118
while (currentToken == JsonToken.FIELD_NAME) {
120119
String fieldName = parser.getCurrentName();
@@ -128,32 +127,20 @@ public Entity deserialize(JsonParser parser, DeserializationContext ctxt) throws
128127
parser.readValueAsTree();
129128
}
130129
} else {
131-
delayedField = deserializeProperty(parser, ctxt, result, propertyData, delayedField);
130+
deserializeProperty(parser, ctxt, result, propertyData);
132131
}
133132
currentToken = parser.nextToken();
134133
}
135134

136-
if (delayedField != null) {
137-
EntityPropertyMain entityPropertyMain = delayedField.entityPropertyMain;
138-
Object encodingType = result.getProperty(ModelRegistry.EP_ENCODINGTYPE);
139-
if (encodingType == null) {
140-
entityPropertyMain.setOn(result, delayedField.tempValue);
141-
} else {
142-
CustomDeserializer deserializer = CustomDeserializationManager.getInstance().getDeserializer(encodingType.toString());
143-
Object value = deserializer.deserialize(delayedField.tempValue);
144-
entityPropertyMain.setOn(result, value);
145-
}
146-
}
147135
return result;
148136
}
149137

150-
private DelayedField deserializeProperty(JsonParser parser, DeserializationContext ctxt, Entity result, PropertyData propertyData, DelayedField delayedField) throws IOException {
138+
private void deserializeProperty(JsonParser parser, DeserializationContext ctxt, Entity result, PropertyData propertyData) throws IOException {
151139
if (propertyData.property instanceof EntityPropertyMain) {
152-
delayedField = deserializeEntityProperty(parser, ctxt, propertyData, result, delayedField);
140+
deserializeEntityProperty(parser, propertyData, result);
153141
} else if (propertyData.property instanceof NavigationPropertyMain) {
154142
deserializeNavigationProperty(propertyData, result, parser, ctxt);
155143
}
156-
return delayedField;
157144
}
158145

159146
private void deserializeNavigationProperty(PropertyData propertyData, Entity result, JsonParser parser, DeserializationContext ctxt) throws IOException {
@@ -173,26 +160,19 @@ private void deserializeNavigationProperty(PropertyData propertyData, Entity res
173160
}
174161
}
175162

176-
private DelayedField deserializeEntityProperty(JsonParser parser, DeserializationContext ctxt, PropertyData propertyData, Entity result, DelayedField delayedField) throws IOException {
163+
private void deserializeEntityProperty(JsonParser parser, PropertyData propertyData, Entity result) throws IOException {
177164
parser.nextValue();
178165
EntityPropertyMain entityPropertyMain = (EntityPropertyMain) propertyData.property;
179166
if (propertyData.valueTypeRef == null) {
180-
Object encodingType = ModelRegistry.EP_ENCODINGTYPE.getFrom(result);
181-
if (encodingType == null) {
182-
delayedField = new DelayedField(entityPropertyMain, parser.readValueAsTree());
183-
} else {
184-
CustomDeserializer deserializer = CustomDeserializationManager.getInstance().getDeserializer(encodingType.toString());
185-
Object value = deserializer.deserialize(parser, ctxt);
186-
entityPropertyMain.setOn(result, value);
187-
}
167+
TreeNode value = parser.readValueAsTree();
168+
entityPropertyMain.setOn(result, value);
188169
} else if (propertyData.property == entityType.getPrimaryKey()) {
189170
Object value = parser.readValueAs(propertyData.valueTypeRef);
190171
entityPropertyMain.setOn(result, ParserUtils.idFromObject(value));
191172
} else {
192173
Object value = parser.readValueAs(propertyData.valueTypeRef);
193174
entityPropertyMain.setOn(result, value);
194175
}
195-
return delayedField;
196176
}
197177

198178
private void deserialiseEntitySet(JsonParser parser, DeserializationContext ctxt, NavigationPropertyEntitySet navPropertyMain, Entity result) throws IOException {
@@ -216,18 +196,6 @@ private void deserialiseEntitySet(JsonParser parser, DeserializationContext ctxt
216196
}
217197
}
218198

219-
private static class DelayedField {
220-
221-
public final EntityPropertyMain entityPropertyMain;
222-
public final TreeNode tempValue;
223-
224-
public DelayedField(EntityPropertyMain entityPropertyMain, TreeNode tempValue) {
225-
this.entityPropertyMain = entityPropertyMain;
226-
this.tempValue = tempValue;
227-
}
228-
229-
}
230-
231199
private static class PropertyData {
232200

233201
final Property property;

FROST-Server.SQLjooq/src/main/java/de/fraunhofer/iosb/ilt/frostserver/persistence/pgjooq/factories/EntityFactories.java

Lines changed: 54 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121
import static de.fraunhofer.iosb.ilt.frostserver.util.ParserUtils.idFromObject;
2222

2323
import com.fasterxml.jackson.core.JsonProcessingException;
24+
import com.fasterxml.jackson.databind.JsonNode;
2425
import com.fasterxml.jackson.databind.ObjectMapper;
25-
import de.fraunhofer.iosb.ilt.frostserver.json.deserialize.custom.GeoJsonDeserializier;
2626
import de.fraunhofer.iosb.ilt.frostserver.json.serialize.GeoJsonSerializer;
2727
import de.fraunhofer.iosb.ilt.frostserver.model.DefaultEntity;
2828
import de.fraunhofer.iosb.ilt.frostserver.model.EntityType;
@@ -120,6 +120,7 @@ public void insertUserDefinedId(JooqPersistenceManager pm, Map<Field, Object> cl
120120
*
121121
* @param pm the persistenceManager
122122
* @param e The Entity to check.
123+
* @param updateMode The update mode to use.
123124
* @throws NoSuchEntityException If the entity has an id, but does not
124125
* exist.
125126
* @throws IncompleteEntityException If the entity has no id, but is not
@@ -216,105 +217,72 @@ public static void insertTimeInterval(Map<Field, Object> clause, Field<Moment> s
216217
}
217218

218219
/**
219-
* Sets both the geometry and location in the clause.
220+
* Sets both the geometry and location in the clause. The geometry will be
221+
* flattened to 2D.
220222
*
221223
* @param clause The insert or update clause to add to.
222224
* @param locationPath The path to the location column.
223225
* @param geomPath The path to the geometry column.
224226
* @param encodingType The encoding type.
225227
* @param location The location.
226228
*/
227-
public static void insertGeometry(Map<Field, Object> clause, Field<String> locationPath, Field<? extends Object> geomPath, String encodingType, final Object location) {
228-
if (encodingType == null && location instanceof GeoJsonObject) {
229-
encodingType = GeoJsonDeserializier.APPLICATION_GEOJSON;
230-
}
231-
if (encodingType != null && GeoJsonDeserializier.ENCODINGS.contains(encodingType.toLowerCase())) {
232-
insertGeometryKnownEncoding(location, clause, geomPath, locationPath);
229+
public static void insertGeometry(Map<Field, Object> clause, Field<String> locationPath, Field<? extends Object> geomPath, String encodingType, Object location) {
230+
if (location instanceof JsonNode jn) {
231+
insertGeometry(clause, locationPath, geomPath, encodingType, jn, true);
233232
} else {
234-
String json;
235-
json = objectToJson(location);
236-
clause.put(geomPath, NULL_FIELD);
237-
if (locationPath != null) {
238-
clause.put(locationPath, json);
239-
}
233+
throw new IllegalArgumentException("Unknown location object type");
240234
}
241235
}
242236

243-
public static void insertGeometryNoTransform(Map<Field, Object> clause, Field<String> locationPath, Field<? extends Object> geomPath, String encodingType, final Object location) {
244-
if (encodingType == null && location instanceof GeoJsonObject) {
245-
encodingType = GeoJsonDeserializier.APPLICATION_GEOJSON;
246-
}
247-
if (encodingType != null && GeoJsonDeserializier.ENCODINGS.contains(encodingType.toLowerCase())) {
248-
insertGeometryKnownEncodingNoTransform(location, clause, geomPath, locationPath);
237+
/**
238+
* Sets both the geometry and location in the clause.
239+
*
240+
* @param clause The insert or update clause to add to.
241+
* @param locationPath The path to the location column.
242+
* @param geomPath The path to the geometry column.
243+
* @param encodingType The encoding type.
244+
* @param location The location.
245+
* @param flatten If the GEOM column should be transformed and flattened.
246+
*/
247+
public static void insertGeometry(Map<Field, Object> clause, Field<String> locationPath, Field<? extends Object> geomPath, String encodingType, Object location, boolean flatten) {
248+
if (location instanceof JsonNode jn) {
249+
insertGeometry(clause, locationPath, geomPath, encodingType, jn, flatten);
249250
} else {
250-
String json;
251-
json = objectToJson(location);
252-
clause.put(geomPath, NULL_FIELD);
253-
if (locationPath != null) {
254-
clause.put(locationPath, json);
255-
}
251+
throw new IllegalArgumentException("Unknown location object type");
256252
}
257253
}
258254

259-
private static void insertGeometryKnownEncoding(final Object location, Map<Field, Object> clause, Field<? extends Object> geomPath, Field<String> locationPath) {
260-
String locJson;
261-
try {
262-
locJson = new GeoJsonSerializer().serialize(location);
263-
} catch (JsonProcessingException ex) {
264-
LOGGER.error("Failed to store.", ex);
265-
throw new IllegalArgumentException("encoding specifies geoJson, but location not parsable as such.");
266-
}
255+
/**
256+
* Sets both the geometry and location in the clause.
257+
*
258+
* @param clause The insert or update clause to add to.
259+
* @param locationPath The path to the location column.
260+
* @param geomPath The path to the geometry column.
261+
* @param encodingType The encoding type.
262+
* @param location The location.
263+
* @param flatten If the GEOM column should be transformed and flattened.
264+
*/
265+
public static void insertGeometry(Map<Field, Object> clause, Field<String> locationPath, Field<? extends Object> geomPath, String encodingType, JsonNode location, boolean flatten) {
266+
Object locationParsed = Utils.locationFromEncoding(encodingType, location);
267267

268-
// Postgres does not support Feature.
269-
Object geoLocation = location;
270-
if (location instanceof Feature) {
271-
geoLocation = ((Feature) location).getGeometry();
272-
}
273-
// Ensure the geoJson has a crs, otherwise Postgres complains.
274-
if (geoLocation instanceof GeoJsonObject) {
275-
GeoJsonObject geoJsonObject = (GeoJsonObject) geoLocation;
276-
Crs crs = geoJsonObject.getCrs();
277-
if (crs == null) {
278-
crs = new Crs();
279-
crs.setType(CrsType.name);
280-
crs.getProperties().put("name", "EPSG:4326");
281-
geoJsonObject.setCrs(crs);
282-
}
283-
}
284-
String geoJson;
285-
try {
286-
geoJson = new GeoJsonSerializer().serialize(geoLocation);
287-
} catch (JsonProcessingException ex) {
288-
LOGGER.error("Failed to store.", ex);
289-
throw new IllegalArgumentException("encoding specifies geoJson, but location not parsable as such.");
268+
if (locationParsed instanceof GeoJsonObject locationGeoJson) {
269+
insertGeoJson(clause, geomPath, locationPath, location, locationGeoJson, flatten);
270+
return;
290271
}
291272

292-
try {
293-
// geojson.jackson allows invalid polygons, geolatte catches those.
294-
Utils.getGeoJsonMapper().fromJson(geoJson, Geometry.class);
295-
} catch (JsonException ex) {
296-
throw new IllegalArgumentException("Invalid geoJson: " + ex.getMessage());
297-
}
298-
final String template = "ST_Force2D(ST_Transform(ST_GeomFromGeoJSON({0}), 4326))";
299-
clause.put(geomPath, DSL.field(template, Object.class, geoJson));
273+
String json;
274+
json = objectToJson(location);
275+
clause.put(geomPath, NULL_FIELD);
300276
if (locationPath != null) {
301-
clause.put(locationPath, locJson);
277+
clause.put(locationPath, json);
302278
}
303279
}
304280

305-
private static void insertGeometryKnownEncodingNoTransform(final Object location, Map<Field, Object> clause, Field<? extends Object> geomPath, Field<String> locationPath) {
306-
String locJson;
307-
try {
308-
locJson = new GeoJsonSerializer().serialize(location);
309-
} catch (JsonProcessingException ex) {
310-
LOGGER.error("Failed to store.", ex);
311-
throw new IllegalArgumentException("encoding specifies geoJson, but location not parsable as such.");
312-
}
313-
281+
private static void insertGeoJson(Map<Field, Object> clause, Field<? extends Object> geomPath, Field<String> locationPath, JsonNode locationSource, GeoJsonObject locationParsed, boolean flatten) {
314282
// Postgres does not support Feature.
315-
Object geoLocation = location;
316-
if (location instanceof Feature) {
317-
geoLocation = ((Feature) location).getGeometry();
283+
Object geoLocation = locationParsed;
284+
if (locationParsed instanceof Feature feature) {
285+
geoLocation = feature.getGeometry();
318286
}
319287
// Ensure the geoJson has a crs, otherwise Postgres complains.
320288
if (geoLocation instanceof GeoJsonObject) {
@@ -327,6 +295,7 @@ private static void insertGeometryKnownEncodingNoTransform(final Object location
327295
geoJsonObject.setCrs(crs);
328296
}
329297
}
298+
330299
String geoJson;
331300
try {
332301
geoJson = new GeoJsonSerializer().serialize(geoLocation);
@@ -341,18 +310,19 @@ private static void insertGeometryKnownEncodingNoTransform(final Object location
341310
} catch (JsonException ex) {
342311
throw new IllegalArgumentException("Invalid geoJson: " + ex.getMessage());
343312
}
344-
final String template = "ST_GeomFromGeoJSON({0})";
313+
314+
final String template;
315+
if (flatten) {
316+
template = "ST_Force2D(ST_Transform(ST_GeomFromGeoJSON({0}), 4326))";
317+
} else {
318+
template = "ST_GeomFromGeoJSON({0})";
319+
}
345320
clause.put(geomPath, DSL.field(template, Object.class, geoJson));
346321
if (locationPath != null) {
347-
clause.put(locationPath, locJson);
322+
clause.put(locationPath, objectToJson(locationSource));
348323
}
349324
}
350325

351-
public static Object reParseGeometry(String encodingType, Object object) {
352-
String json = objectToJson(object);
353-
return Utils.locationFromEncoding(encodingType, json);
354-
}
355-
356326
public static String objectToJson(JsonValue jsonValue) {
357327
return objectToJson(jsonValue.getValue());
358328
}

FROST-Server.SQLjooq/src/main/java/de/fraunhofer/iosb/ilt/frostserver/persistence/pgjooq/utils/Utils.java

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
import com.fasterxml.jackson.core.type.TypeReference;
2424
import com.fasterxml.jackson.databind.JsonNode;
25+
import com.fasterxml.jackson.databind.node.TextNode;
2526
import de.fraunhofer.iosb.ilt.frostserver.json.deserialize.custom.GeoJsonDeserializier;
2627
import de.fraunhofer.iosb.ilt.frostserver.model.ext.TimeInstant;
2728
import de.fraunhofer.iosb.ilt.frostserver.model.ext.TimeInterval;
@@ -118,30 +119,25 @@ public static TimeValue valueFromTimes(Moment timeStart, Moment timeEnd) {
118119
return new TimeValue(intervalFromTimes(timeStart, timeEnd));
119120
}
120121

121-
public static Object locationFromEncoding(String encodingType, String locationString) {
122-
if (locationString == null || locationString.isEmpty()) {
122+
public static Object locationFromEncoding(String encodingType, JsonNode location) {
123+
if (location == null || location.isEmpty()) {
123124
return null;
124125
}
125126
if (encodingType == null) {
126-
return locationUnknownEncoding(locationString);
127+
return locationUnknownEncoding(location);
127128
}
128129
if (GeoJsonDeserializier.ENCODINGS.contains(encodingType.toLowerCase())) {
129130
try {
130-
return new GeoJsonDeserializier().deserialize(locationString);
131+
return new GeoJsonDeserializier().deserialize(location);
131132
} catch (IOException ex) {
132133
LOGGER.error("Failed to deserialise geoJson.", ex);
133134
}
134-
return locationString;
135+
return location;
135136
}
136-
try {
137-
return jsonToObject(locationString, Object.class);
138-
} catch (Exception ex) {
139-
LOGGER.trace("Not a map.", ex);
140-
}
141-
return locationString;
137+
return location;
142138
}
143139

144-
public static Object locationUnknownEncoding(String locationString) {
140+
public static Object locationUnknownEncoding(JsonNode locationString) {
145141
if (locationString == null) {
146142
return null;
147143
}
@@ -151,12 +147,19 @@ public static Object locationUnknownEncoding(String locationString) {
151147
} catch (IOException ex) {
152148
LOGGER.trace("Not geoJson.", ex);
153149
}
150+
return locationString;
151+
}
152+
153+
public static JsonNode jsonToTreeOrString(String json) {
154+
if (json == null) {
155+
return null;
156+
}
157+
154158
try {
155-
return jsonToObject(locationString, Map.class);
156-
} catch (Exception ex) {
157-
LOGGER.trace("Not a map.", ex);
159+
return SimpleJsonMapper.getSimpleObjectMapper().readTree(json);
160+
} catch (IOException ex) {
161+
return new TextNode(json);
158162
}
159-
return locationString;
160163
}
161164

162165
public static JsonNode jsonToTree(String json) {

FROST-Server.SQLjooq/src/main/java/de/fraunhofer/iosb/ilt/frostserver/persistence/pgjooq/utils/fieldmapper/FieldMapperGeometry.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ public <T extends StaMainTable<T>> void registerMapping(JooqPersistenceManager p
9494
DSL.field("ST_AsGeoJSON(?)", String.class, t.field(idxGeom, SQLDataType.CLOB)).as(fieldGeom));
9595
}
9696
dataSize.increase(locationString == null ? 0 : locationString.length());
97-
entity.setProperty(property, Utils.locationUnknownEncoding(locationString));
97+
entity.setProperty(property, Utils.jsonToTreeOrString(locationString));
9898
},
9999
(t, entity, insertFields) -> {
100100
Object feature = entity.getProperty(property);

FROST-Server.SQLjooq/src/main/java/de/fraunhofer/iosb/ilt/frostserver/persistence/pgjooq/utils/fieldmapper/FieldMapperGeometryMariadb.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,15 +94,15 @@ public <T extends StaMainTable<T>> void registerMapping(JooqPersistenceManager p
9494
DSL.field("ST_AsGeoJSON(?)", String.class, t.field(idxGeom, SQLDataType.CLOB)).as(fieldGeom));
9595
}
9696
dataSize.increase(locationString == null ? 0 : locationString.length());
97-
entity.setProperty(property, Utils.locationUnknownEncoding(locationString));
97+
entity.setProperty(property, Utils.jsonToTreeOrString(locationString));
9898
},
9999
(t, entity, insertFields) -> {
100100
Object feature = entity.getProperty(property);
101-
EntityFactories.insertGeometryNoTransform(insertFields, t.field(idxLocation, SQLDataType.CLOB), t.field(idxGeom), null, feature);
101+
EntityFactories.insertGeometry(insertFields, t.field(idxLocation, SQLDataType.CLOB), t.field(idxGeom), null, feature, false);
102102
},
103103
(t, entity, updateFields, message) -> {
104104
Object feature = entity.getProperty(property);
105-
EntityFactories.insertGeometryNoTransform(updateFields, t.field(idxLocation, SQLDataType.CLOB), t.field(idxGeom), null, feature);
105+
EntityFactories.insertGeometry(updateFields, t.field(idxLocation, SQLDataType.CLOB), t.field(idxGeom), null, feature, false);
106106
message.addField(property);
107107
}),
108108
sourcePfr);

0 commit comments

Comments
 (0)