Skip to content

Commit

Permalink
Changed how locations are handled
Browse files Browse the repository at this point in the history
  • Loading branch information
hylkevds committed Nov 15, 2023
1 parent 4de7070 commit 3a32408
Show file tree
Hide file tree
Showing 14 changed files with 124 additions and 157 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,6 @@ public Entity deserialize(JsonParser parser, DeserializationContext ctxt) throws

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

DelayedField delayedField = null;
JsonToken currentToken = parser.nextToken();
while (currentToken == JsonToken.FIELD_NAME) {
String fieldName = parser.getCurrentName();
Expand All @@ -128,32 +127,20 @@ public Entity deserialize(JsonParser parser, DeserializationContext ctxt) throws
parser.readValueAsTree();
}
} else {
delayedField = deserializeProperty(parser, ctxt, result, propertyData, delayedField);
deserializeProperty(parser, ctxt, result, propertyData);
}
currentToken = parser.nextToken();
}

if (delayedField != null) {
EntityPropertyMain entityPropertyMain = delayedField.entityPropertyMain;
Object encodingType = result.getProperty(ModelRegistry.EP_ENCODINGTYPE);
if (encodingType == null) {
entityPropertyMain.setOn(result, delayedField.tempValue);
} else {
CustomDeserializer deserializer = CustomDeserializationManager.getInstance().getDeserializer(encodingType.toString());
Object value = deserializer.deserialize(delayedField.tempValue);
entityPropertyMain.setOn(result, value);
}
}
return result;
}

private DelayedField deserializeProperty(JsonParser parser, DeserializationContext ctxt, Entity result, PropertyData propertyData, DelayedField delayedField) throws IOException {
private void deserializeProperty(JsonParser parser, DeserializationContext ctxt, Entity result, PropertyData propertyData) throws IOException {
if (propertyData.property instanceof EntityPropertyMain) {
delayedField = deserializeEntityProperty(parser, ctxt, propertyData, result, delayedField);
deserializeEntityProperty(parser, propertyData, result);
} else if (propertyData.property instanceof NavigationPropertyMain) {
deserializeNavigationProperty(propertyData, result, parser, ctxt);
}
return delayedField;
}

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

private DelayedField deserializeEntityProperty(JsonParser parser, DeserializationContext ctxt, PropertyData propertyData, Entity result, DelayedField delayedField) throws IOException {
private void deserializeEntityProperty(JsonParser parser, PropertyData propertyData, Entity result) throws IOException {
parser.nextValue();
EntityPropertyMain entityPropertyMain = (EntityPropertyMain) propertyData.property;
if (propertyData.valueTypeRef == null) {
Object encodingType = ModelRegistry.EP_ENCODINGTYPE.getFrom(result);
if (encodingType == null) {
delayedField = new DelayedField(entityPropertyMain, parser.readValueAsTree());
} else {
CustomDeserializer deserializer = CustomDeserializationManager.getInstance().getDeserializer(encodingType.toString());
Object value = deserializer.deserialize(parser, ctxt);
entityPropertyMain.setOn(result, value);
}
TreeNode value = parser.readValueAsTree();
entityPropertyMain.setOn(result, value);
} else if (propertyData.property == entityType.getPrimaryKey()) {
Object value = parser.readValueAs(propertyData.valueTypeRef);
entityPropertyMain.setOn(result, ParserUtils.idFromObject(value));
} else {
Object value = parser.readValueAs(propertyData.valueTypeRef);
entityPropertyMain.setOn(result, value);
}
return delayedField;
}

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

private static class DelayedField {

public final EntityPropertyMain entityPropertyMain;
public final TreeNode tempValue;

public DelayedField(EntityPropertyMain entityPropertyMain, TreeNode tempValue) {
this.entityPropertyMain = entityPropertyMain;
this.tempValue = tempValue;
}

}

private static class PropertyData {

final Property property;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
import static de.fraunhofer.iosb.ilt.frostserver.util.ParserUtils.idFromObject;

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

/**
* Sets both the geometry and location in the clause.
* Sets both the geometry and location in the clause. The geometry will be
* flattened to 2D.
*
* @param clause The insert or update clause to add to.
* @param locationPath The path to the location column.
* @param geomPath The path to the geometry column.
* @param encodingType The encoding type.
* @param location The location.
*/
public static void insertGeometry(Map<Field, Object> clause, Field<String> locationPath, Field<? extends Object> geomPath, String encodingType, final Object location) {
if (encodingType == null && location instanceof GeoJsonObject) {
encodingType = GeoJsonDeserializier.APPLICATION_GEOJSON;
}
if (encodingType != null && GeoJsonDeserializier.ENCODINGS.contains(encodingType.toLowerCase())) {
insertGeometryKnownEncoding(location, clause, geomPath, locationPath);
public static void insertGeometry(Map<Field, Object> clause, Field<String> locationPath, Field<? extends Object> geomPath, String encodingType, Object location) {
if (location instanceof JsonNode jn) {
insertGeometry(clause, locationPath, geomPath, encodingType, jn, true);
} else {
String json;
json = objectToJson(location);
clause.put(geomPath, NULL_FIELD);
if (locationPath != null) {
clause.put(locationPath, json);
}
throw new IllegalArgumentException("Unknown location object type");
}
}

public static void insertGeometryNoTransform(Map<Field, Object> clause, Field<String> locationPath, Field<? extends Object> geomPath, String encodingType, final Object location) {
if (encodingType == null && location instanceof GeoJsonObject) {
encodingType = GeoJsonDeserializier.APPLICATION_GEOJSON;
}
if (encodingType != null && GeoJsonDeserializier.ENCODINGS.contains(encodingType.toLowerCase())) {
insertGeometryKnownEncodingNoTransform(location, clause, geomPath, locationPath);
/**
* Sets both the geometry and location in the clause.
*
* @param clause The insert or update clause to add to.
* @param locationPath The path to the location column.
* @param geomPath The path to the geometry column.
* @param encodingType The encoding type.
* @param location The location.
* @param flatten If the GEOM column should be transformed and flattened.
*/
public static void insertGeometry(Map<Field, Object> clause, Field<String> locationPath, Field<? extends Object> geomPath, String encodingType, Object location, boolean flatten) {
if (location instanceof JsonNode jn) {
insertGeometry(clause, locationPath, geomPath, encodingType, jn, flatten);
} else {
String json;
json = objectToJson(location);
clause.put(geomPath, NULL_FIELD);
if (locationPath != null) {
clause.put(locationPath, json);
}
throw new IllegalArgumentException("Unknown location object type");
}
}

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

// Postgres does not support Feature.
Object geoLocation = location;
if (location instanceof Feature) {
geoLocation = ((Feature) location).getGeometry();
}
// Ensure the geoJson has a crs, otherwise Postgres complains.
if (geoLocation instanceof GeoJsonObject) {
GeoJsonObject geoJsonObject = (GeoJsonObject) geoLocation;
Crs crs = geoJsonObject.getCrs();
if (crs == null) {
crs = new Crs();
crs.setType(CrsType.name);
crs.getProperties().put("name", "EPSG:4326");
geoJsonObject.setCrs(crs);
}
}
String geoJson;
try {
geoJson = new GeoJsonSerializer().serialize(geoLocation);
} catch (JsonProcessingException ex) {
LOGGER.error("Failed to store.", ex);
throw new IllegalArgumentException("encoding specifies geoJson, but location not parsable as such.");
if (locationParsed instanceof GeoJsonObject locationGeoJson) {
insertGeoJson(clause, geomPath, locationPath, location, locationGeoJson, flatten);
return;
}

try {
// geojson.jackson allows invalid polygons, geolatte catches those.
Utils.getGeoJsonMapper().fromJson(geoJson, Geometry.class);
} catch (JsonException ex) {
throw new IllegalArgumentException("Invalid geoJson: " + ex.getMessage());
}
final String template = "ST_Force2D(ST_Transform(ST_GeomFromGeoJSON({0}), 4326))";
clause.put(geomPath, DSL.field(template, Object.class, geoJson));
String json;
json = objectToJson(location);
clause.put(geomPath, NULL_FIELD);
if (locationPath != null) {
clause.put(locationPath, locJson);
clause.put(locationPath, json);
}
}

private static void insertGeometryKnownEncodingNoTransform(final Object location, Map<Field, Object> clause, Field<? extends Object> geomPath, Field<String> locationPath) {
String locJson;
try {
locJson = new GeoJsonSerializer().serialize(location);
} catch (JsonProcessingException ex) {
LOGGER.error("Failed to store.", ex);
throw new IllegalArgumentException("encoding specifies geoJson, but location not parsable as such.");
}

private static void insertGeoJson(Map<Field, Object> clause, Field<? extends Object> geomPath, Field<String> locationPath, JsonNode locationSource, GeoJsonObject locationParsed, boolean flatten) {
// Postgres does not support Feature.
Object geoLocation = location;
if (location instanceof Feature) {
geoLocation = ((Feature) location).getGeometry();
Object geoLocation = locationParsed;
if (locationParsed instanceof Feature feature) {
geoLocation = feature.getGeometry();
}
// Ensure the geoJson has a crs, otherwise Postgres complains.
if (geoLocation instanceof GeoJsonObject) {
Expand All @@ -327,6 +295,7 @@ private static void insertGeometryKnownEncodingNoTransform(final Object location
geoJsonObject.setCrs(crs);
}
}

String geoJson;
try {
geoJson = new GeoJsonSerializer().serialize(geoLocation);
Expand All @@ -341,18 +310,19 @@ private static void insertGeometryKnownEncodingNoTransform(final Object location
} catch (JsonException ex) {
throw new IllegalArgumentException("Invalid geoJson: " + ex.getMessage());
}
final String template = "ST_GeomFromGeoJSON({0})";

final String template;
if (flatten) {
template = "ST_Force2D(ST_Transform(ST_GeomFromGeoJSON({0}), 4326))";
} else {
template = "ST_GeomFromGeoJSON({0})";
}
clause.put(geomPath, DSL.field(template, Object.class, geoJson));
if (locationPath != null) {
clause.put(locationPath, locJson);
clause.put(locationPath, objectToJson(locationSource));
}
}

public static Object reParseGeometry(String encodingType, Object object) {
String json = objectToJson(object);
return Utils.locationFromEncoding(encodingType, json);
}

public static String objectToJson(JsonValue jsonValue) {
return objectToJson(jsonValue.getValue());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

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

public static Object locationFromEncoding(String encodingType, String locationString) {
if (locationString == null || locationString.isEmpty()) {
public static Object locationFromEncoding(String encodingType, JsonNode location) {
if (location == null || location.isEmpty()) {
return null;
}
if (encodingType == null) {
return locationUnknownEncoding(locationString);
return locationUnknownEncoding(location);
}
if (GeoJsonDeserializier.ENCODINGS.contains(encodingType.toLowerCase())) {
try {
return new GeoJsonDeserializier().deserialize(locationString);
return new GeoJsonDeserializier().deserialize(location);
} catch (IOException ex) {
LOGGER.error("Failed to deserialise geoJson.", ex);
}
return locationString;
return location;
}
try {
return jsonToObject(locationString, Object.class);
} catch (Exception ex) {
LOGGER.trace("Not a map.", ex);
}
return locationString;
return location;
}

public static Object locationUnknownEncoding(String locationString) {
public static Object locationUnknownEncoding(JsonNode locationString) {
if (locationString == null) {
return null;
}
Expand All @@ -151,12 +147,19 @@ public static Object locationUnknownEncoding(String locationString) {
} catch (IOException ex) {
LOGGER.trace("Not geoJson.", ex);
}
return locationString;
}

public static JsonNode jsonToTreeOrString(String json) {
if (json == null) {
return null;
}

try {
return jsonToObject(locationString, Map.class);
} catch (Exception ex) {
LOGGER.trace("Not a map.", ex);
return SimpleJsonMapper.getSimpleObjectMapper().readTree(json);
} catch (IOException ex) {
return new TextNode(json);
}
return locationString;
}

public static JsonNode jsonToTree(String json) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public <T extends StaMainTable<T>> void registerMapping(JooqPersistenceManager p
DSL.field("ST_AsGeoJSON(?)", String.class, t.field(idxGeom, SQLDataType.CLOB)).as(fieldGeom));
}
dataSize.increase(locationString == null ? 0 : locationString.length());
entity.setProperty(property, Utils.locationUnknownEncoding(locationString));
entity.setProperty(property, Utils.jsonToTreeOrString(locationString));
},
(t, entity, insertFields) -> {
Object feature = entity.getProperty(property);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,15 +94,15 @@ public <T extends StaMainTable<T>> void registerMapping(JooqPersistenceManager p
DSL.field("ST_AsGeoJSON(?)", String.class, t.field(idxGeom, SQLDataType.CLOB)).as(fieldGeom));
}
dataSize.increase(locationString == null ? 0 : locationString.length());
entity.setProperty(property, Utils.locationUnknownEncoding(locationString));
entity.setProperty(property, Utils.jsonToTreeOrString(locationString));
},
(t, entity, insertFields) -> {
Object feature = entity.getProperty(property);
EntityFactories.insertGeometryNoTransform(insertFields, t.field(idxLocation, SQLDataType.CLOB), t.field(idxGeom), null, feature);
EntityFactories.insertGeometry(insertFields, t.field(idxLocation, SQLDataType.CLOB), t.field(idxGeom), null, feature, false);
},
(t, entity, updateFields, message) -> {
Object feature = entity.getProperty(property);
EntityFactories.insertGeometryNoTransform(updateFields, t.field(idxLocation, SQLDataType.CLOB), t.field(idxGeom), null, feature);
EntityFactories.insertGeometry(updateFields, t.field(idxLocation, SQLDataType.CLOB), t.field(idxGeom), null, feature, false);
message.addField(property);
}),
sourcePfr);
Expand Down
Loading

0 comments on commit 3a32408

Please sign in to comment.