/* * The MIT License (MIT) * * Copyright (c) 2015 Reinventing Geospatial, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package com.rgi.geopackage.features.geometry.xy; import com.rgi.geopackage.features.ByteOutputStream; import com.rgi.geopackage.features.GeometryType; import com.rgi.geopackage.features.WellKnownBinaryFormatException; import com.rgi.geopackage.features.geometry.Geometry; import com.rgi.geopackage.features.geometry.GeometryFactory; import com.rgi.geopackage.features.geometry.zm.WkbGeometryZM; import com.rgi.geopackage.features.geometry.zm.WkbPointZM; import org.junit.BeforeClass; import org.junit.Test; import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.Map; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; /** * @author Luke Lambert */ @SuppressWarnings("JavaDoc") public class WkbGeometryCollectionTest { @BeforeClass public static void setUp() { GEOMETRY_FACTORIES.put(WkbGeometryZM.GeometryTypeDimensionalityBase + GeometryType.Point.getCode(), WkbPointZM::readWellKnownBinary); GEOMETRY_FACTORIES.put(GeometryType.GeometryCollection.getCode(), (byteBuffer) -> WkbGeometryCollection.readWellKnownBinary(WkbGeometryCollectionTest::createGeometry, byteBuffer)); } /** * Test the ellipsis constructor */ @Test @SuppressWarnings("JUnitTestMethodWithNoAssertions") public void ellipsisConstructor() { new WkbGeometryCollection<>(new WkbPoint(1.0, 1.0), new WkbLineString()); } /** * Test the collection constructor */ @Test @SuppressWarnings("JUnitTestMethodWithNoAssertions") public void collectionConstructor() { new WkbGeometryCollection<>(Arrays.asList(new WkbPoint(1.0, 1.0), new WkbLineString())); } /** * Test the collection constructor with a null collection */ @Test(expected = IllegalArgumentException.class) public void collectionConstructorWithNull() { //noinspection CastToConcreteClass new WkbGeometryCollection<>((Collection<WkbGeometry>)null); } /** * Test the collection constructor with a null geometry */ @Test(expected = IllegalArgumentException.class) public void collectionConstructorWithNullGeometry() { //noinspection CastToConcreteClass new WkbGeometryCollection<>(Arrays.asList((WkbPoint)null)); } /** * Test equals with the same object */ @Test public void testEqualsSameObject() { final WkbGeometryCollection<WkbPoint> collection = new WkbGeometryCollection<>(new WkbPoint(0.0, 0.0), new WkbPoint(0.0, 0.0), new WkbPoint(0.0, 0.0)); //noinspection EqualsWithItself,SimplifiableJUnitAssertion assertTrue("equals returned false for testing an object against itself", collection.equals(collection)); } /** * Test equals with null */ @Test public void testEqualsWithNull() { final WkbGeometryCollection<WkbPoint> collection = new WkbGeometryCollection<>(new WkbPoint(0.0, 0.0), new WkbPoint(0.0, 0.0), new WkbPoint(0.0, 0.0)); //noinspection SimplifiableJUnitAssertion,ObjectEqualsNull assertFalse("equals returned true for testing against null", collection.equals(null)); } /** * Test equals with a different type */ @Test public void testEqualsWithDifferentType() { final WkbGeometryCollection<WkbPoint> collection = new WkbGeometryCollection<>(new WkbPoint(0.0, 0.0), new WkbPoint(0.0, 0.0), new WkbPoint(0.0, 0.0)); //noinspection UnnecessaryBoxing,EqualsBetweenInconvertibleTypes assertFalse("equals returned true for testing with an inconvertible type", collection.equals(Integer.valueOf(0))); } /** * Test equals */ @Test public void testEquals() { final WkbGeometryCollection<WkbPoint> collection1 = new WkbGeometryCollection<>(new WkbPoint(0.0, 0.0), new WkbPoint(0.0, 0.0), new WkbPoint(0.0, 0.0)); final WkbGeometryCollection<WkbPoint> collection2 = new WkbGeometryCollection<>(new WkbPoint(0.0, 0.0), new WkbPoint(0.0, 0.0), new WkbPoint(0.0, 0.0)); assertEquals("equals returned false for testing equivalent objects", collection1, collection2); } /** * Test hashCode() */ @Test public void testHashCode() { assertEquals("hashCode returned the wrong value", 29791, new WkbGeometryCollection<>(new WkbPoint(0.0, 0.0), new WkbPoint(0.0, 0.0), new WkbPoint(0.0, 0.0)).hashCode()); } /** * Test getTypeCode() */ @Test public void getTypeCode() { assertEquals("getTypeCode() returned the wrong value", GeometryType.GeometryCollection.getCode(), new WkbGeometryCollection<>().getTypeCode()); } /** * Test getGeometryTypeName() */ @Test public void getGeometryTypeName() { assertEquals("getGeometryTypeName() returned the wrong value", GeometryType.GeometryCollection.toString(), new WkbGeometryCollection<>().getGeometryTypeName()); } /** * Test isEmpty() */ @Test public void testIsEmpty() { assertTrue("isEmpty() should have returned true", new WkbGeometryCollection<>().isEmpty()); assertFalse("isEmpty() should have returned false", new WkbGeometryCollection<>(new WkbPoint(0.0, 0.0), new WkbPoint(0.0, 0.0), new WkbPoint(0.0, 0.0)).isEmpty()); } /** * Test the serialization of write/read well known binary */ @Test public void writeReadWellKnownBinary() throws WellKnownBinaryFormatException { final WkbGeometryCollection<WkbPoint> collection = new WkbGeometryCollection<>(new WkbPoint(0.0, 0.0), new WkbPoint(0.0, 0.0), new WkbPoint(0.0, 0.0)); try(final ByteOutputStream output = new ByteOutputStream()) { collection.writeWellKnownBinary(output); final WkbGeometryCollection<WkbGeometry> foundCollection = WkbGeometryCollection.readWellKnownBinary(WkbPoint::readWellKnownBinary, ByteBuffer.wrap(output.array())); assertEquals("error in well known binary (WKB) reading/writing", collection, foundCollection); } } /** * Test the serialization of write/read well known binary with a geometry with a geometry with incorrect * dimensionality */ @Test(expected = WellKnownBinaryFormatException.class) public void writeReadWellKnownBinaryWithBadGeometry() throws WellKnownBinaryFormatException { try(final ByteOutputStream output = new ByteOutputStream()) { //noinspection NumericCastThatLosesPrecision output.write((byte)(output.getByteOrder().equals(ByteOrder.BIG_ENDIAN) ? 0 : 1)); //noinspection NumericCastThatLosesPrecision output.write((int)(new WkbGeometryCollection<>().getTypeCode())); output.write(1); // number of contained geometries new WkbPointZM(0.0, 0.0, 0.0, 0.0).writeWellKnownBinary(output); // Geometry with the wrong dimensionality createGeometry(ByteBuffer.wrap(output.array())); } } /** * Test createEnvelope() */ @Test public void createEnvelope() { @SuppressWarnings("CastToConcreteClass") final Envelope emptyEnvelope = (Envelope)new WkbGeometryCollection<>().createEnvelope(); assertTrue("envelope minimum x value is wrong", Double.isNaN(emptyEnvelope.getMinimumX())); assertTrue("envelope minimum y value is wrong", Double.isNaN(emptyEnvelope.getMinimumY())); assertTrue("envelope maximum x value is wrong", Double.isNaN(emptyEnvelope.getMaximumX())); assertTrue("envelope maximum y value is wrong", Double.isNaN(emptyEnvelope.getMaximumY())); final double min = 0.0; final double max = 1.0; final Envelope envelope = new WkbGeometryCollection<>(new WkbPoint(min, min), new WkbPoint(max, max)).createEnvelope(); assertEquals("combine() picked the wrong minimum x value", min, envelope.getMinimumX(), 0.0); assertEquals("combine() picked the wrong minimum y value", min, envelope.getMinimumY(), 0.0); assertEquals("combine() picked the wrong maximum x value", max, envelope.getMaximumX(), 0.0); assertEquals("combine() picked the wrong maximum y value", max, envelope.getMaximumY(), 0.0); } private static Geometry createGeometry(final ByteBuffer wkbByteBuffer) throws WellKnownBinaryFormatException { try { wkbByteBuffer.mark(); // Save the buffer position (.mark()) before we read the well known binary header. final ByteOrder byteOrder = wkbByteBuffer.get() == 0 ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN; wkbByteBuffer.order(byteOrder); // Read 4 bytes as an /unsigned/ int final long geometryType = Integer.toUnsignedLong(wkbByteBuffer.getInt()); wkbByteBuffer.reset(); // This will reset the position to before the well known binary header. return GEOMETRY_FACTORIES.get(geometryType) .create(wkbByteBuffer); } catch(final BufferUnderflowException bufferUnderflowException) { throw new WellKnownBinaryFormatException(bufferUnderflowException); } } private static final Map<Long, GeometryFactory> GEOMETRY_FACTORIES = new HashMap<>(); }