blob: 3b967ae842d8692c98d1a3ed86ef5ebf86fae62e [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.olingo.client.core.serialization;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.apache.olingo.commons.api.Constants;
import org.apache.olingo.commons.api.data.GeoUtils;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
import org.apache.olingo.commons.api.edm.geo.Geospatial;
import org.apache.olingo.commons.api.edm.geo.GeospatialCollection;
import org.apache.olingo.commons.api.edm.geo.LineString;
import org.apache.olingo.commons.api.edm.geo.MultiLineString;
import org.apache.olingo.commons.api.edm.geo.MultiPoint;
import org.apache.olingo.commons.api.edm.geo.MultiPolygon;
import org.apache.olingo.commons.api.edm.geo.Point;
import org.apache.olingo.commons.api.edm.geo.Polygon;
import org.apache.olingo.commons.api.edm.geo.SRID;
import org.apache.olingo.commons.core.edm.EdmTypeInfo;
import org.apache.olingo.commons.core.edm.primitivetype.EdmDouble;
import com.fasterxml.jackson.databind.JsonNode;
class JsonGeoValueDeserializer {
private Point point(final Iterator<JsonNode> itor, final EdmPrimitiveTypeKind type, final SRID srid) {
Point point = null;
if (itor.hasNext()) {
point = new Point(GeoUtils.getDimension(type), srid);
try {
point.setX(EdmDouble.getInstance().valueOfString(itor.next().asText(), null, null,
Constants.DEFAULT_PRECISION, Constants.DEFAULT_SCALE, null, Double.class));
point.setY(EdmDouble.getInstance().valueOfString(itor.next().asText(), null, null,
Constants.DEFAULT_PRECISION, Constants.DEFAULT_SCALE, null, Double.class));
} catch (EdmPrimitiveTypeException e) {
throw new IllegalArgumentException("While deserializing point coordinates as double", e);
}
}
return point;
}
private MultiPoint multipoint(final Iterator<JsonNode> itor, final EdmPrimitiveTypeKind type, final SRID srid) {
final MultiPoint multiPoint;
if (itor.hasNext()) {
final List<Point> points = new ArrayList<Point>();
while (itor.hasNext()) {
final Iterator<JsonNode> mpItor = itor.next().elements();
points.add(point(mpItor, type, srid));
}
multiPoint = new MultiPoint(GeoUtils.getDimension(type), srid, points);
} else {
multiPoint = new MultiPoint(GeoUtils.getDimension(type), srid, Collections.<Point> emptyList());
}
return multiPoint;
}
private LineString lineString(final Iterator<JsonNode> itor, final EdmPrimitiveTypeKind type, final SRID srid) {
final LineString lineString;
if (itor.hasNext()) {
final List<Point> points = new ArrayList<Point>();
while (itor.hasNext()) {
final Iterator<JsonNode> mpItor = itor.next().elements();
points.add(point(mpItor, type, srid));
}
lineString = new LineString(GeoUtils.getDimension(type), srid, points);
} else {
lineString = new LineString(GeoUtils.getDimension(type), srid, Collections.<Point> emptyList());
}
return lineString;
}
private MultiLineString multiLineString(final Iterator<JsonNode> itor, final EdmPrimitiveTypeKind type,
final SRID srid) {
final MultiLineString multiLineString;
if (itor.hasNext()) {
final List<LineString> lineStrings = new ArrayList<LineString>();
while (itor.hasNext()) {
final Iterator<JsonNode> mlsItor = itor.next().elements();
lineStrings.add(lineString(mlsItor, type, srid));
}
multiLineString = new MultiLineString(GeoUtils.getDimension(type), srid, lineStrings);
} else {
multiLineString = new MultiLineString(GeoUtils.getDimension(type), srid, Collections.<LineString> emptyList());
}
return multiLineString;
}
private Polygon polygon(final Iterator<JsonNode> itor, final EdmPrimitiveTypeKind type, final SRID srid) {
List<Point> extPoints = null;
if (itor.hasNext()) {
final Iterator<JsonNode> extItor = itor.next().elements();
if (extItor.hasNext()) {
extPoints = new ArrayList<Point>();
while (extItor.hasNext()) {
final Iterator<JsonNode> mpItor = extItor.next().elements();
extPoints.add(point(mpItor, type, srid));
}
}
}
List<LineString> intRings = new ArrayList<LineString>();
while (itor.hasNext()) {
final Iterator<JsonNode> intItor = itor.next().elements();
if (intItor.hasNext()) {
List<Point> intPoints = new ArrayList<Point>();
while (intItor.hasNext()) {
final Iterator<JsonNode> mpItor = intItor.next().elements();
intPoints.add(point(mpItor, type, srid));
}
intRings.add(new LineString(GeoUtils.getDimension(type), srid, intPoints));
}
}
LineString exterior = new LineString(GeoUtils.getDimension(type), srid, extPoints);
return new Polygon(GeoUtils.getDimension(type), srid, intRings, exterior);
}
private MultiPolygon multiPolygon(final Iterator<JsonNode> itor, final EdmPrimitiveTypeKind type, final SRID srid) {
final MultiPolygon multiPolygon;
if (itor.hasNext()) {
final List<Polygon> polygons = new ArrayList<Polygon>();
while (itor.hasNext()) {
final Iterator<JsonNode> mpItor = itor.next().elements();
polygons.add(polygon(mpItor, type, srid));
}
multiPolygon = new MultiPolygon(GeoUtils.getDimension(type), srid, polygons);
} else {
multiPolygon = new MultiPolygon(GeoUtils.getDimension(type), srid, Collections.<Polygon> emptyList());
}
return multiPolygon;
}
private GeospatialCollection collection(final Iterator<JsonNode> itor, final EdmPrimitiveTypeKind type,
final SRID srid) {
final GeospatialCollection collection;
if (itor.hasNext()) {
final List<Geospatial> geospatials = new ArrayList<Geospatial>();
while (itor.hasNext()) {
final JsonNode geo = itor.next();
final String collItemType = geo.get(Constants.ATTR_TYPE).asText();
final String callAsType;
if (EdmPrimitiveTypeKind.GeographyCollection.name().equals(collItemType)
|| EdmPrimitiveTypeKind.GeometryCollection.name().equals(collItemType)) {
callAsType = collItemType;
} else {
callAsType = (type == EdmPrimitiveTypeKind.GeographyCollection ? "Geography" : "Geometry")
+ collItemType;
}
geospatials.add(deserialize(geo, new EdmTypeInfo.Builder().setTypeExpression(callAsType).build()));
}
collection = new GeospatialCollection(GeoUtils.getDimension(type), srid, geospatials);
} else {
collection = new GeospatialCollection(GeoUtils.getDimension(type), srid, Collections.<Geospatial> emptyList());
}
return collection;
}
public Geospatial deserialize(final JsonNode node, final EdmTypeInfo typeInfo) {
final EdmPrimitiveTypeKind actualType;
if ((typeInfo.getPrimitiveTypeKind() == EdmPrimitiveTypeKind.Geography
|| typeInfo.getPrimitiveTypeKind() == EdmPrimitiveTypeKind.Geometry)
&& node.has(Constants.ATTR_TYPE)) {
String nodeType = node.get(Constants.ATTR_TYPE).asText();
if (nodeType.startsWith("Geo")) {
final int yIdx = nodeType.indexOf('y');
nodeType = nodeType.substring(yIdx + 1);
}
actualType = EdmPrimitiveTypeKind.valueOfFQN(typeInfo.getFullQualifiedName().toString() + nodeType);
} else {
actualType = typeInfo.getPrimitiveTypeKind();
}
final Iterator<JsonNode> cooItor = node.has(Constants.JSON_COORDINATES)
? node.get(Constants.JSON_COORDINATES).elements()
: Collections.<JsonNode> emptyList().iterator();
SRID srid = null;
if (node.has(Constants.JSON_CRS)) {
srid = SRID.valueOf(
node.get(Constants.JSON_CRS).get(Constants.PROPERTIES).get(Constants.JSON_NAME).asText().split(":")[1]);
}
Geospatial value = null;
switch (actualType) {
case GeographyPoint:
case GeometryPoint:
value = point(cooItor, actualType, srid);
break;
case GeographyMultiPoint:
case GeometryMultiPoint:
value = multipoint(cooItor, actualType, srid);
break;
case GeographyLineString:
case GeometryLineString:
value = lineString(cooItor, actualType, srid);
break;
case GeographyMultiLineString:
case GeometryMultiLineString:
value = multiLineString(cooItor, actualType, srid);
break;
case GeographyPolygon:
case GeometryPolygon:
value = polygon(cooItor, actualType, srid);
break;
case GeographyMultiPolygon:
case GeometryMultiPolygon:
value = multiPolygon(cooItor, actualType, srid);
break;
case GeographyCollection:
case GeometryCollection:
value = collection(node.get(Constants.JSON_GEOMETRIES).elements(), actualType, srid);
break;
default:
}
return value;
}
}