Skip to content

Commit

Permalink
[GEOS-9181] Add back data type information in complex GeoJSON output
Browse files Browse the repository at this point in the history
  • Loading branch information
aaime committed Apr 15, 2019
1 parent 8e5446c commit 95c7e89
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ public void testGetGeoJsonResponseWfs11() throws Exception {
getAsJSON(
"wfs?request=GetFeature&version=1.1.0"
+ "&typename=st_gml31:Station_gml31&outputFormat=application/json");
print(response);
// validate the obtained response
checkStation1Exists(response);
}
Expand Down Expand Up @@ -106,7 +107,7 @@ private void checkStation1Exists(JSON geoJson) {
assertThat(name.get("@code"), is("st1"));
// validate the station contact
JSONObject contact = station.getJSONObject("contact");
assertThat(contact.size(), is(2));
assertThat(contact.size(), is(3));
assertThat(contact.get("@mail"), is("st1@stations.org"));
JSONObject phone = contact.getJSONObject("phone");
assertThat(phone.size(), is(2));
Expand All @@ -116,10 +117,10 @@ private void checkStation1Exists(JSON geoJson) {
JSONArray measurements = station.getJSONArray("measurements");
assertThat(measurements.size(), is(2));
assertThat(
measurements.getJSONObject(0).getString("href"),
measurements.getJSONObject(0).getString("@href"),
containsString("http://www.stations.org/ms."));
assertThat(
measurements.getJSONObject(1).getString("href"),
measurements.getJSONObject(1).getString("@href"),
containsString("http://www.stations.org/ms."));
}

Expand Down Expand Up @@ -172,6 +173,11 @@ public void testNestedFeatureEncoding() throws Exception {
print(json);
JSONObject properties = getFeaturePropertiesById(json, "BOREHOLE.WTB5");
assertThat(properties, is(notNullValue()));

// check the featureType attribute is there
assertEquals("Borehole", properties.getString("@featureType"));

// get the nested feature
JSONObject collar = getNestedObject(properties, "collarLocation");
assertEquals("BOREHOLE.COLLAR.WTB5", collar.getString("id"));
assertEquals("Feature", collar.getString("type"));
Expand All @@ -180,5 +186,23 @@ public void testNestedFeatureEncoding() throws Exception {
assertThat(coordinates.size(), is(2));
assertEquals(-28.4139, coordinates.getDouble(0), 0.1);
assertEquals(121.142, coordinates.getDouble(1), 0.1);

JSONObject collarProperties = collar.getJSONObject("properties");
assertEquals("BoreholeCollar", collarProperties.getString("@featureType"));
JSONObject indexData = properties.getJSONObject("indexData");
assertEquals("BoreholeDetails", indexData.getString("@dataType"));
assertEquals(
"BoundingShape", indexData.getJSONObject("coredInterval").getString("@dataType"));

// get the sampled feature, which is a linked one
JSONArray sampledFeatures = properties.getJSONArray("sampledFeature");
assertEquals(1, sampledFeatures.size());
JSONObject sampledFeature = sampledFeatures.getJSONObject(0);
assertEquals(
"http://www.opengis.net/def/nil/OGC/0/unknown", sampledFeature.getString("@href"));
assertEquals(
"http://www.geosciml.org/geosciml/2.0/doc/GeoSciML/GeologicUnit/GeologicUnit.html",
sampledFeature.getString("@role"));
assertEquals("unknown", sampledFeature.getString("@title"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"geometry": null,
"id": "cc.1",
"properties": {
"@featureType": "firstParentFeature",
"nestedFeature": [
{
"someAttribute": "string_one"
Expand All @@ -19,25 +20,25 @@
{
"geometry": null,
"id": "cc.2",
"properties": {},
"properties": {"@featureType": "firstParentFeature"},
"type": "Feature"
},
{
"geometry": null,
"id": "cc.3",
"properties": {},
"properties": {"@featureType": "firstParentFeature"},
"type": "Feature"
},
{
"geometry": null,
"id": "cc.4",
"properties": {},
"properties": {"@featureType": "firstParentFeature"},
"type": "Feature"
},
{
"geometry": null,
"id": "cc.5",
"properties": {},
"properties": {"@featureType": "firstParentFeature"},
"type": "Feature"
}
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"geometry": null,
"id": "sc.1",
"properties": {
"@featureType": "parentFeature",
"nestedFeature": [
{
"nestedValue": "1GRAV"
Expand All @@ -24,6 +25,7 @@
"geometry": null,
"id": "sc.2",
"properties": {
"@featureType": "parentFeature",
"nestedFeature": [
{
"nestedValue": "1GRAV"
Expand All @@ -43,6 +45,7 @@
"geometry": null,
"id": "sc.3",
"properties": {
"@featureType": "parentFeature",
"nestedFeature": [
{
"nestedValue": "1GRAV"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,21 +37,13 @@
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.xml.sax.Attributes;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/** GeoJSON writer capable of handling complex features. */
class ComplexGeoJsonWriter {

static final Logger LOGGER = Logging.getLogger(ComplexGeoJsonWriter.class);

private static Class NON_FEATURE_TYPE_PROXY;
private static final String DATATYPE = "@dataType";

static {
try {
Expand Down Expand Up @@ -121,6 +113,7 @@ protected void encodeFeature(Feature feature) {
// start the JSON object that will contain all the others properties
jsonWriter.key("properties");
jsonWriter.object();
jsonWriter.key("@featureType").value(getSimplifiedTypeName(feature.getType().getName()));
// encode object properties, we pass the geometry attribute to avoid duplicate encodings
encodeProperties(geometryAttribute, feature.getType(), feature.getProperties());
// close the feature JSON object
Expand All @@ -129,6 +122,24 @@ protected void encodeFeature(Feature feature) {
jsonWriter.endObject();
}

/**
* Returns the simplified type name, e.g., if the name is BoreCollarType the method will return
* "BoreCollar" (to remove yet another GML convention)
*
* @param name
* @return
*/
private String getSimplifiedTypeName(Name name) {
String localName = name.getLocalPart();
if (localName.endsWith("_Type")) {
return localName.substring(0, localName.length() - "_Type".length());
}
if (localName.endsWith("Type")) {
return localName.substring(0, localName.length() - "Type".length());
}
return localName;
}

/**
* Encode feature geometry attribute which may not exist or be NULL. Returns the geometry
* attribute name for the provided feature, NULL will be returned if the provided feature has no
Expand Down Expand Up @@ -241,7 +252,7 @@ private void encodeLinkedFeatures(
jsonWriter.array();
// encode each linked feature
for (Map<NameImpl, String> feature : linkedFeatures) {
encodeAttributesArray(feature);
encodeAttributesAsObject(feature);
}
// end the linked features JSON array
jsonWriter.endArray();
Expand Down Expand Up @@ -549,16 +560,17 @@ private Object getSimpleContent(ComplexAttribute property) {

/** Encode a complex attribute as a JSON object. */
private void encodeComplexAttribute(
ComplexAttribute attribute, Map<NameImpl, String> attributes) {
String name = attribute.getName().getLocalPart();
String name, ComplexAttribute attribute, Map<NameImpl, String> attributes) {
if (isFullFeature(attribute)) {
jsonWriter.key(name);
encodeFeature((Feature) attribute);
} else {
// get the attribute name and start a JSON object

jsonWriter.key(name);
jsonWriter.object();
// encode the datatype
jsonWriter.key(DATATYPE);
jsonWriter.value(getSimplifiedTypeName(attribute.getType().getName()));
// let's see if we have actually some properties to encode
if (attribute.getProperties() != null && !attribute.getProperties().isEmpty()) {
// encode the object properties, since this is not a top feature or a
Expand Down Expand Up @@ -621,20 +633,19 @@ private void encodeAttributes(Map<NameImpl, String> attributes) {
}

/**
* Utility method that encode an attributes map as an array of objects, each one having a single
* key (based on the attribute name local part ) and value . Attributes with a NULL value will
* not be encoded. This method assumes that it is already in an array context.
* Utility method that encode an attributes map as properties of an object, each one using the
* attribute name local part and value . Attributes with a NULL value will not be encoded.
*/
private void encodeAttributesArray(Map<NameImpl, String> attributes) {
private void encodeAttributesAsObject(Map<NameImpl, String> attributes) {
jsonWriter.object();
attributes.forEach(
(name, value) -> {
if (value != null) {
// encode attribute, we don't take namespace into account
jsonWriter.object();
jsonWriter.key(name.getLocalPart()).value(value);
jsonWriter.endObject();
jsonWriter.key("@" + name.getLocalPart()).value(value);
}
});
jsonWriter.endObject();
}

/** Return TRUE if a geometry was found during the features collections encoding. */
Expand Down

0 comments on commit 95c7e89

Please sign in to comment.