OLINGO-1294 adding polygon support for multiple interior rings

This commit is contained in:
shawkins 2018-09-21 17:36:02 -04:00
parent 8cbe468c2a
commit ebdf0d3e3a
10 changed files with 147 additions and 69 deletions

View File

@ -113,8 +113,8 @@ class AtomGeoValueDeserializer {
private Polygon polygon(final XMLEventReader reader, final StartElement start, private Polygon polygon(final XMLEventReader reader, final StartElement start,
final EdmPrimitiveTypeKind type, final SRID srid) throws XMLStreamException { final EdmPrimitiveTypeKind type, final SRID srid) throws XMLStreamException {
List<Point> extPoints = null; LineString extPoints = null;
List<Point> intPoints = null; List<LineString> intRings = new ArrayList<LineString>();
boolean foundEndProperty = false; boolean foundEndProperty = false;
while (reader.hasNext() && !foundEndProperty) { while (reader.hasNext() && !foundEndProperty) {
@ -122,10 +122,12 @@ class AtomGeoValueDeserializer {
if (event.isStartElement()) { if (event.isStartElement()) {
if (event.asStartElement().getName().equals(Constants.QNAME_POLYGON_EXTERIOR)) { if (event.asStartElement().getName().equals(Constants.QNAME_POLYGON_EXTERIOR)) {
extPoints = points(reader, event.asStartElement(), type, null); List<Point> points = points(reader, event.asStartElement(), type, null);
extPoints = new LineString(GeoUtils.getDimension(type), srid, points);
} }
if (event.asStartElement().getName().equals(Constants.QNAME_POLYGON_INTERIOR)) { if (event.asStartElement().getName().equals(Constants.QNAME_POLYGON_INTERIOR)) {
intPoints = points(reader, event.asStartElement(), type, null); List<Point> points = points(reader, event.asStartElement(), type, null);
intRings.add(new LineString(GeoUtils.getDimension(type), srid, points));
} }
} }
@ -134,7 +136,7 @@ class AtomGeoValueDeserializer {
} }
} }
return new Polygon(GeoUtils.getDimension(type), srid, intPoints, extPoints); return new Polygon(GeoUtils.getDimension(type), srid, intRings, extPoints);
} }
private MultiLineString multiLineString(final XMLEventReader reader, final StartElement start, private MultiLineString multiLineString(final XMLEventReader reader, final StartElement start,

View File

@ -103,11 +103,11 @@ class AtomGeoValueSerializer {
writer.writeEndElement(); writer.writeEndElement();
writer.writeEndElement(); writer.writeEndElement();
} }
if (!polygon.getInterior().isEmpty()) { for (int i = 0; i < polygon.getNumberOfInteriorRings(); i++) {
writer.writeStartElement(Constants.PREFIX_GML, Constants.ELEM_POLYGON_INTERIOR, Constants.NS_GML); writer.writeStartElement(Constants.PREFIX_GML, Constants.ELEM_POLYGON_INTERIOR, Constants.NS_GML);
writer.writeStartElement(Constants.PREFIX_GML, Constants.ELEM_POLYGON_LINEARRING, Constants.NS_GML); writer.writeStartElement(Constants.PREFIX_GML, Constants.ELEM_POLYGON_LINEARRING, Constants.NS_GML);
points(writer, polygon.getInterior().iterator(), false); points(writer, polygon.getInterior(i).iterator(), false);
writer.writeEndElement(); writer.writeEndElement();
writer.writeEndElement(); writer.writeEndElement();

View File

@ -127,19 +127,21 @@ class JsonGeoValueDeserializer {
} }
} }
List<Point> intPoints = null; List<LineString> intRings = new ArrayList<LineString>();
if (itor.hasNext()) { while (itor.hasNext()) {
final Iterator<JsonNode> intItor = itor.next().elements(); final Iterator<JsonNode> intItor = itor.next().elements();
if (intItor.hasNext()) { if (intItor.hasNext()) {
intPoints = new ArrayList<Point>(); List<Point> intPoints = new ArrayList<Point>();
while (intItor.hasNext()) { while (intItor.hasNext()) {
final Iterator<JsonNode> mpItor = intItor.next().elements(); final Iterator<JsonNode> mpItor = intItor.next().elements();
intPoints.add(point(mpItor, type, srid)); intPoints.add(point(mpItor, type, srid));
} }
intRings.add(new LineString(GeoUtils.getDimension(type), srid, intPoints));
} }
} }
return new Polygon(GeoUtils.getDimension(type), srid, intPoints, extPoints); 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) { private MultiPolygon multiPolygon(final Iterator<JsonNode> itor, final EdmPrimitiveTypeKind type, final SRID srid) {

View File

@ -84,14 +84,12 @@ class JsonGeoValueSerializer {
} }
private void polygon(final JsonGenerator jgen, final Polygon polygon) throws IOException { private void polygon(final JsonGenerator jgen, final Polygon polygon) throws IOException {
if (!polygon.getExterior().isEmpty()) {
jgen.writeStartArray(); jgen.writeStartArray();
lineString(jgen, polygon.getExterior()); lineString(jgen, polygon.getExterior());
jgen.writeEndArray(); jgen.writeEndArray();
} for (int i = 0; i < polygon.getNumberOfInteriorRings(); i++) {
if (!polygon.getInterior().isEmpty()) {
jgen.writeStartArray(); jgen.writeStartArray();
lineString(jgen, polygon.getInterior()); lineString(jgen, polygon.getInterior(i));
jgen.writeEndArray(); jgen.writeEndArray();
} }
} }

View File

@ -18,6 +18,7 @@
*/ */
package org.apache.olingo.commons.api.edm.geo; package org.apache.olingo.commons.api.edm.geo;
import java.util.Arrays;
import java.util.List; import java.util.List;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind; import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
@ -27,7 +28,7 @@ import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
*/ */
public class Polygon extends Geospatial { public class Polygon extends Geospatial {
final ComposedGeospatial<Point> interior; final ComposedGeospatial<LineString> interiorRings;
final ComposedGeospatial<Point> exterior; final ComposedGeospatial<Point> exterior;
/** /**
@ -37,28 +38,78 @@ public class Polygon extends Geospatial {
* @param srid SRID values * @param srid SRID values
* @param interior List of interior points * @param interior List of interior points
* @param exterior List of exterior point * @param exterior List of exterior point
* @deprecated
*/ */
public Polygon(final Dimension dimension, final SRID srid, public Polygon(final Dimension dimension, final SRID srid,
final List<Point> interior, final List<Point> exterior) { final List<Point> interior, final List<Point> exterior) {
super(dimension, Type.POLYGON, srid); super(dimension, Type.POLYGON, srid);
this.interior = new MultiPoint(dimension, srid, interior); if (interior != null) {
this.exterior = new MultiPoint(dimension, srid, exterior); LineString lineString = new LineString(dimension, srid, interior);
this.interiorRings = new MultiLineString(dimension, srid, Arrays.asList(lineString));
} else {
this.interiorRings = null;
}
this.exterior = new LineString(dimension, srid, exterior);
} }
/**
* Creates a new polygon.
*
* @param dimension Dimension of the polygon
* @param srid SRID values
* @param interiors List of interior rings
* @param exterior Ring of exterior point
*/
public Polygon(final Dimension dimension, final SRID srid,
final List<LineString> interiors, LineString exterior) {
super(dimension, Type.POLYGON, srid);
if (interiors != null) {
this.interiorRings = new MultiLineString(dimension, srid, interiors);
} else {
this.interiorRings = null;
}
this.exterior = exterior;
}
/** /**
* Gets interior points. * Gets interior points.
* *
* @return interior points. * @return interior points.
* @deprecated
* @see #getInterior(int)
*/ */
public ComposedGeospatial<Point> getInterior() { public ComposedGeospatial<Point> getInterior() {
return interior; if (interiorRings == null || interiorRings.geospatials.isEmpty()) {
return null;
}
return getInterior(0);
}
/**
* Get the number of interior rings
* @return number of interior rings
*/
public int getNumberOfInteriorRings() {
if (interiorRings == null) {
return 0;
}
return interiorRings.geospatials.size();
}
/**
* Gets the nth interior ring
* @param n
* @return the ring or an exception if no such ring exists
*/
public ComposedGeospatial<Point> getInterior(int n) {
return interiorRings.geospatials.get(n);
} }
/** /**
* Gets exterior points. * Gets exterior points.
* *
* @return exterior points.I * @return exterior points.
*/ */
public ComposedGeospatial<Point> getExterior() { public ComposedGeospatial<Point> getExterior() {
return exterior; return exterior;
@ -83,7 +134,7 @@ public class Polygon extends Geospatial {
final Polygon polygon = (Polygon) o; final Polygon polygon = (Polygon) o;
return dimension == polygon.dimension return dimension == polygon.dimension
&& (srid == null ? polygon.srid == null : srid.equals(polygon.srid)) && (srid == null ? polygon.srid == null : srid.equals(polygon.srid))
&& (interior == null ? polygon.interior == null : interior.equals(polygon.interior)) && (interiorRings == null ? polygon.interiorRings == null : interiorRings.equals(polygon.interiorRings))
&& (exterior == null ? polygon.exterior == null : exterior.equals(polygon.exterior)); && (exterior == null ? polygon.exterior == null : exterior.equals(polygon.exterior));
} }
@ -91,7 +142,7 @@ public class Polygon extends Geospatial {
public int hashCode() { public int hashCode() {
int result = dimension == null ? 0 : dimension.hashCode(); int result = dimension == null ? 0 : dimension.hashCode();
result = 31 * result + (srid == null ? 0 : srid.hashCode()); result = 31 * result + (srid == null ? 0 : srid.hashCode());
result = 31 * result + (interior == null ? 0 : interior.hashCode()); result = 31 * result + (interiorRings == null ? 0 : interiorRings.hashCode());
result = 31 * result + (exterior == null ? 0 : exterior.hashCode()); result = 31 * result + (exterior == null ? 0 : exterior.hashCode());
return result; return result;
} }

View File

@ -26,6 +26,7 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException; import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
import org.apache.olingo.commons.api.edm.geo.ComposedGeospatial;
import org.apache.olingo.commons.api.edm.geo.Geospatial; import org.apache.olingo.commons.api.edm.geo.Geospatial;
import org.apache.olingo.commons.api.edm.geo.Geospatial.Dimension; import org.apache.olingo.commons.api.edm.geo.Geospatial.Dimension;
import org.apache.olingo.commons.api.edm.geo.Geospatial.Type; import org.apache.olingo.commons.api.edm.geo.Geospatial.Type;
@ -176,16 +177,20 @@ public abstract class AbstractGeospatialType<T extends Geospatial> extends Singl
final String[] first = polygon.split("\\),\\("); final String[] first = polygon.split("\\),\\(");
final List<Point> interior = new ArrayList<Point>(); final List<LineString> interiorRings = new ArrayList<LineString>();
for (final String pointCoo : split(first[0].substring(1, first[0].length()), ',')) { for (int i = 0; i < first.length -1; i++) {
List<Point> interior = new ArrayList<Point>();
for (final String pointCoo : split(first[i].substring(i==0?1:0, first[i].length()), ',')) {
interior.add(newPoint(null, pointCoo, isNullable, maxLength, precision, scale, isUnicode)); interior.add(newPoint(null, pointCoo, isNullable, maxLength, precision, scale, isUnicode));
} }
interiorRings.add(new LineString(dimension, srid, interior));
}
final List<Point> exterior = new ArrayList<Point>(); final List<Point> exterior = new ArrayList<Point>();
for (final String pointCoo : split(first[1].substring(0, first[1].length() - 1), ',')) { for (final String pointCoo : split(first[first.length -1].substring(0, first[first.length -1].length() - 1), ',')) {
exterior.add(newPoint(null, pointCoo, isNullable, maxLength, precision, scale, isUnicode)); exterior.add(newPoint(null, pointCoo, isNullable, maxLength, precision, scale, isUnicode));
} }
return new Polygon(dimension, srid, interior, exterior); return new Polygon(dimension, srid, interiorRings, new LineString(dimension, srid, exterior));
} }
protected Polygon stringToPolygon(final String value, final Boolean isNullable, final Integer maxLength, protected Polygon stringToPolygon(final String value, final Boolean isNullable, final Integer maxLength,
@ -343,21 +348,17 @@ public abstract class AbstractGeospatialType<T extends Geospatial> extends Singl
return result.append(")'").toString(); return result.append(")'").toString();
} }
private String lineString(final LineString lineString, final Boolean isNullable, private StringBuilder appendPoints(final ComposedGeospatial<Point> points, final Boolean isNullable,
final Integer maxLength, final Integer precision, final Integer scale, final Boolean isUnicode) final Integer maxLength, final Integer precision, final Integer scale, final Boolean isUnicode,
throws EdmPrimitiveTypeException { final StringBuilder result) throws EdmPrimitiveTypeException {
for (final Iterator<Point> itor = points.iterator(); itor.hasNext();) {
final StringBuilder result = new StringBuilder();
for (final Iterator<Point> itor = lineString.iterator(); itor.hasNext();) {
result.append(point(itor.next(), isNullable, maxLength, precision, scale, isUnicode)); result.append(point(itor.next(), isNullable, maxLength, precision, scale, isUnicode));
if (itor.hasNext()) { if (itor.hasNext()) {
result.append(','); result.append(',');
} }
} }
return result;
return result.toString(); }
}
protected String toString(final LineString lineString, final Boolean isNullable, final Integer maxLength, protected String toString(final LineString lineString, final Boolean isNullable, final Integer maxLength,
final Integer precision, final Integer scale, final Boolean isUnicode) throws EdmPrimitiveTypeException { final Integer precision, final Integer scale, final Boolean isUnicode) throws EdmPrimitiveTypeException {
@ -366,10 +367,10 @@ public abstract class AbstractGeospatialType<T extends Geospatial> extends Singl
throw new EdmPrimitiveTypeException("The value '" + lineString + "' is not valid."); throw new EdmPrimitiveTypeException("The value '" + lineString + "' is not valid.");
} }
return toStringBuilder(lineString.getSrid()). StringBuilder builder = toStringBuilder(lineString.getSrid()).
append(reference.getSimpleName()). append(reference.getSimpleName()).
append('('). append('(');
append(lineString(lineString, isNullable, maxLength, precision, scale, isUnicode)). return appendPoints(lineString, isNullable, maxLength, precision, scale, isUnicode, builder).
append(")'").toString(); append(")'").toString();
} }
@ -385,8 +386,8 @@ public abstract class AbstractGeospatialType<T extends Geospatial> extends Singl
append('('); append('(');
for (final Iterator<LineString> itor = multiLineString.iterator(); itor.hasNext();) { for (final Iterator<LineString> itor = multiLineString.iterator(); itor.hasNext();) {
result.append('('). result.append('(');
append(lineString(itor.next(), isNullable, maxLength, precision, scale, isUnicode)). appendPoints(itor.next(), isNullable, maxLength, precision, scale, isUnicode, result).
append(')'); append(')');
if (itor.hasNext()) { if (itor.hasNext()) {
result.append(','); result.append(',');
@ -402,21 +403,15 @@ public abstract class AbstractGeospatialType<T extends Geospatial> extends Singl
final StringBuilder result = new StringBuilder(); final StringBuilder result = new StringBuilder();
for (int i = 0; i < polygon.getNumberOfInteriorRings(); i++) {
result.append('('); result.append('(');
for (final Iterator<Point> itor = polygon.getInterior().iterator(); itor.hasNext();) { appendPoints(polygon.getInterior(i), isNullable, maxLength, precision, scale, isUnicode, result);
result.append(point(itor.next(), isNullable, maxLength, precision, scale, isUnicode)); result.append("),");
if (itor.hasNext()) {
result.append(',');
}
}
result.append("),(");
for (final Iterator<Point> itor = polygon.getExterior().iterator(); itor.hasNext();) {
result.append(point(itor.next(), isNullable, maxLength, precision, scale, isUnicode));
if (itor.hasNext()) {
result.append(',');
}
} }
result.append('(');
appendPoints(polygon.getExterior(), isNullable, maxLength, precision, scale, isUnicode, result);
return result.append(')').toString(); return result.append(')').toString();
} }
@ -490,14 +485,14 @@ public abstract class AbstractGeospatialType<T extends Geospatial> extends Singl
case GeographyLineString: case GeographyLineString:
case GeometryLineString: case GeometryLineString:
result.append(lineString((LineString) item, isNullable, maxLength, precision, scale, isUnicode)); appendPoints((LineString) item, isNullable, maxLength, precision, scale, isUnicode, result);
break; break;
case GeographyMultiLineString: case GeographyMultiLineString:
case GeometryMultiLineString: case GeometryMultiLineString:
for (final Iterator<LineString> itor = ((MultiLineString) item).iterator(); itor.hasNext();) { for (final Iterator<LineString> itor = ((MultiLineString) item).iterator(); itor.hasNext();) {
result.append('('). result.append('(');
append(lineString(itor.next(), isNullable, maxLength, precision, scale, isUnicode)). appendPoints(itor.next(), isNullable, maxLength, precision, scale, isUnicode, result).
append(')'); append(')');
if (itor.hasNext()) { if (itor.hasNext()) {
result.append(','); result.append(',');

View File

@ -120,7 +120,7 @@ public class EdmGeoTest extends PrimitiveTypeBaseTest {
valueOfString(input, null, null, null, null, null, Polygon.class); valueOfString(input, null, null, null, null, null, Polygon.class);
assertNotNull(polygon); assertNotNull(polygon);
assertEquals("0", polygon.getSrid().toString()); assertEquals("0", polygon.getSrid().toString());
Iterator<Point> itor = polygon.getInterior().iterator(); Iterator<Point> itor = polygon.getInterior(0).iterator();
assertEquals(1, itor.next().getX(), 0); assertEquals(1, itor.next().getX(), 0);
assertEquals(1, itor.next().getY(), 0); assertEquals(1, itor.next().getY(), 0);
itor = polygon.getExterior().iterator(); itor = polygon.getExterior().iterator();
@ -131,6 +131,31 @@ public class EdmGeoTest extends PrimitiveTypeBaseTest {
assertEquals(input, EdmGeographyPolygon.getInstance().valueToString(polygon, null, null, null, null, null)); assertEquals(input, EdmGeographyPolygon.getInstance().valueToString(polygon, null, null, null, null, null));
} }
@Test
public void polygonMultipleHoles() throws EdmPrimitiveTypeException {
final String input = "geography'SRID=4326;Polygon((1.0 1.0,1.0 1.0),(2.0 2.0,2.0 2.0)"
+ ",(1.0 1.0,2.0 2.0,3.0 3.0,1.0 1.0))'";
expectContentErrorInValueOfString(EdmGeometryPolygon.getInstance(), input);
final Polygon polygon = EdmGeographyPolygon.getInstance().
valueOfString(input, null, null, null, null, null, Polygon.class);
assertNotNull(polygon);
assertEquals("4326", polygon.getSrid().toString());
Iterator<Point> itor = polygon.getInterior(0).iterator();
assertEquals(1, itor.next().getX(), 0);
assertEquals(1, itor.next().getY(), 0);
itor = polygon.getInterior(1).iterator();
assertEquals(2, itor.next().getX(), 0);
assertEquals(2, itor.next().getY(), 0);
itor = polygon.getExterior().iterator();
itor.next();
assertEquals(2, itor.next().getX(), 0);
assertEquals(3, itor.next().getY(), 0);
assertEquals(input, EdmGeographyPolygon.getInstance().valueToString(polygon, null, null, null, null, null));
}
@Test @Test
public void multiPolygon() throws EdmPrimitiveTypeException { public void multiPolygon() throws EdmPrimitiveTypeException {
final String input = "geometry'SRID=0;MultiPolygon(" final String input = "geometry'SRID=0;MultiPolygon("
@ -145,8 +170,8 @@ public class EdmGeoTest extends PrimitiveTypeBaseTest {
assertNotNull(multiPolygon); assertNotNull(multiPolygon);
assertEquals("0", multiPolygon.getSrid().toString()); assertEquals("0", multiPolygon.getSrid().toString());
final Iterator<Polygon> itor = multiPolygon.iterator(); final Iterator<Polygon> itor = multiPolygon.iterator();
assertEquals(1, itor.next().getInterior().iterator().next().getX(), 0); assertEquals(1, itor.next().getInterior(0).iterator().next().getX(), 0);
assertEquals(1, itor.next().getInterior().iterator().next().getX(), 0); assertEquals(1, itor.next().getInterior(0).iterator().next().getX(), 0);
assertEquals(input, EdmGeometryMultiPolygon.getInstance(). assertEquals(input, EdmGeometryMultiPolygon.getInstance().
valueToString(multiPolygon, null, null, null, null, null)); valueToString(multiPolygon, null, null, null, null, null));

View File

@ -1060,9 +1060,9 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
json.writeStartArray(); json.writeStartArray();
writeGeoPoints(json, polygon.getExterior()); writeGeoPoints(json, polygon.getExterior());
json.writeEndArray(); json.writeEndArray();
if (!polygon.getInterior().isEmpty()) { for (int i = 0; i < polygon.getNumberOfInteriorRings(); i++) {
json.writeStartArray(); json.writeStartArray();
writeGeoPoints(json, polygon.getInterior()); writeGeoPoints(json, polygon.getInterior(i));
json.writeEndArray(); json.writeEndArray();
} }
} }

View File

@ -603,6 +603,11 @@ public class UriTokenizerTest {
public void geoPolygon() { public void geoPolygon() {
assertTrue(new UriTokenizer("geography'SRID=4326;Polygon((0 0,1 0,0 1,0 0))'").next(TokenKind.GeographyPolygon)); assertTrue(new UriTokenizer("geography'SRID=4326;Polygon((0 0,1 0,0 1,0 0))'").next(TokenKind.GeographyPolygon));
assertTrue(new UriTokenizer("geometry'SRID=0;Polygon((0 0,1 0,0 1,0 0))'").next(TokenKind.GeometryPolygon)); assertTrue(new UriTokenizer("geometry'SRID=0;Polygon((0 0,1 0,0 1,0 0))'").next(TokenKind.GeometryPolygon));
assertTrue(new UriTokenizer("geometry'SRID=0;Polygon((1 1,2 1,2 2,1 2,1 1),(0 0,4 0,4 4,0 4,0 0))'")
.next(TokenKind.GeometryPolygon));
assertTrue(new UriTokenizer(
"geometry'SRID=0;Polygon((0 0,1 1,2 2,0 0),(1 1,2 1,2 2,1 2,1 1),(0 0,4 0,4 4,0 4,0 0))'")
.next(TokenKind.GeometryPolygon));
wrongToken(TokenKind.GeometryPolygon, wrongToken(TokenKind.GeometryPolygon,
"geometry'SRID=0;Polygon((0 0,4 0,4 4,0 4,0 0),(1 1,2 1,2 2,1 2,1 1))'", "geometry'SRID=0;Polygon((0 0,4 0,4 4,0 4,0 0),(1 1,2 1,2 2,1 2,1 1))'",
'x'); 'x');

View File

@ -1036,13 +1036,13 @@ public class ODataJsonDeserializerEntityTest extends AbstractODataDeserializerTe
Polygon polygon = (Polygon) entity.getProperties().get(0).getValue(); Polygon polygon = (Polygon) entity.getProperties().get(0).getValue();
assertEquals(Geospatial.Dimension.GEOMETRY, polygon.getDimension()); assertEquals(Geospatial.Dimension.GEOMETRY, polygon.getDimension());
assertEquals(0, polygon.getExterior().iterator().next().getX(), 0); assertEquals(0, polygon.getExterior().iterator().next().getX(), 0);
assertEquals(1, polygon.getInterior().iterator().next().getY(), 0); assertEquals(1, polygon.getInterior(0).iterator().next().getY(), 0);
entity = deserialize("{\"" + entityType.getPropertyNames().get(0) + "\":{" entity = deserialize("{\"" + entityType.getPropertyNames().get(0) + "\":{"
+ "\"type\":\"Polygon\",\"coordinates\":[[[0,0],[3,0],[3,3],[0,3],[0,0]]]}}", + "\"type\":\"Polygon\",\"coordinates\":[[[0,0],[3,0],[3,3],[0,3],[0,0]]]}}",
entityType); entityType);
polygon = (Polygon) entity.getProperties().get(0).getValue(); polygon = (Polygon) entity.getProperties().get(0).getValue();
assertTrue(polygon.getInterior().isEmpty()); assertEquals(0, polygon.getNumberOfInteriorRings());
expectException("{\"" + entityType.getPropertyNames().get(0) + "\":{" expectException("{\"" + entityType.getPropertyNames().get(0) + "\":{"
+ "\"type\":\"Polygon\",\"coordinates\":{\"ext\":[[0,0],[3,0],[0,3],[0,0]]}}}", entityType, + "\"type\":\"Polygon\",\"coordinates\":{\"ext\":[[0,0],[3,0],[0,3],[0,0]]}}}", entityType,
@ -1070,7 +1070,7 @@ public class ODataJsonDeserializerEntityTest extends AbstractODataDeserializerTe
+ "[[[0.0,0.0],[30.0,0.0],[0.0,30.0],[0.0,0.0]]]]}}", + "[[[0.0,0.0],[30.0,0.0],[0.0,30.0],[0.0,0.0]]]]}}",
entityType); entityType);
final MultiPolygon multiPolygon = (MultiPolygon) entity.getProperties().get(0).getValue(); final MultiPolygon multiPolygon = (MultiPolygon) entity.getProperties().get(0).getValue();
assertEquals(1, multiPolygon.iterator().next().getInterior().iterator().next().getX(), 0); assertEquals(1, multiPolygon.iterator().next().getInterior(0).iterator().next().getX(), 0);
expectException("{\"" + entityType.getPropertyNames().get(0) + "\":{" expectException("{\"" + entityType.getPropertyNames().get(0) + "\":{"
+ "\"type\":\"MultiPolygon\",\"coordinates\":[{\"first\":[[[0,0],[3,0],[3,3],[0,3],[0,0]]]}]}}", entityType, + "\"type\":\"MultiPolygon\",\"coordinates\":[{\"first\":[[[0,0],[3,0],[3,3],[0,3],[0,0]]]}]}}", entityType,