diff --git a/sensorhub-core/src/main/java/org/sensorhub/utils/DataComponentChecks.java b/sensorhub-core/src/main/java/org/sensorhub/utils/DataComponentChecks.java index d80ea2444..2c3d4b7a7 100644 --- a/sensorhub-core/src/main/java/org/sensorhub/utils/DataComponentChecks.java +++ b/sensorhub-core/src/main/java/org/sensorhub/utils/DataComponentChecks.java @@ -14,6 +14,7 @@ package org.sensorhub.utils; +import java.nio.charset.StandardCharsets; import org.vast.data.DataIterator; import org.vast.swe.SWEUtils; import org.vast.util.Asserts; @@ -25,6 +26,7 @@ import net.opengis.swe.v20.BlockComponent; import net.opengis.swe.v20.DataComponent; import net.opengis.swe.v20.DataEncoding; +import net.opengis.swe.v20.JSONEncoding; /** @@ -38,6 +40,8 @@ public class DataComponentChecks { static HashFunction hf = Hashing.goodFastHash(32); + private static final byte[] JSON_ENCODING_HASH_MARKER = + "SWE/2.0/JSONEncoding".getBytes(StandardCharsets.UTF_8); /** @@ -161,7 +165,7 @@ public static HashCode getEncodingEqualsHashCode(DataEncoding enc) try { var hashOs = new HashingOutputStream(hf, ByteStreams.nullOutputStream()); - new SWEUtils(SWEUtils.V2_0).writeEncoding(hashOs, enc, false); + writeEncodingForHash(hashOs, enc); return hashOs.hash(); } catch (Exception e) @@ -177,7 +181,7 @@ public static HashCode getStructEqualsHashCode(DataComponent root, DataEncoding { var hashOs = new HashingOutputStream(hf, ByteStreams.nullOutputStream()); new SWEUtils(SWEUtils.V2_0).writeComponent(hashOs, root, false, false); - new SWEUtils(SWEUtils.V2_0).writeEncoding(hashOs, enc, false); + writeEncodingForHash(hashOs, enc); return hashOs.hash(); } catch (Exception e) @@ -185,6 +189,23 @@ public static HashCode getStructEqualsHashCode(DataComponent root, DataEncoding throw new IllegalArgumentException("Error computing hashcode. Invalid data component"); } } + + + private static void writeEncodingForHash(HashingOutputStream hashOs, DataEncoding enc) + throws Exception + { + if (enc instanceof JSONEncoding) + { + // JSONEncoding has no SWE JSON binding properties and no SWE XML + // representation. Use a delimited family marker so equality + // remains deterministic without changing other encodings. + hashOs.write(0); + hashOs.write(JSON_ENCODING_HASH_MARKER); + hashOs.write(0); + } + else + new SWEUtils(SWEUtils.V2_0).writeEncoding(hashOs, enc, false); + } private static String getComponentType(Class c) diff --git a/sensorhub-core/src/test/java/org/sensorhub/utils/TestDataComponentChecks.java b/sensorhub-core/src/test/java/org/sensorhub/utils/TestDataComponentChecks.java index b1c5884eb..6e770e763 100644 --- a/sensorhub-core/src/test/java/org/sensorhub/utils/TestDataComponentChecks.java +++ b/sensorhub-core/src/test/java/org/sensorhub/utils/TestDataComponentChecks.java @@ -16,6 +16,8 @@ import static org.junit.Assert.*; import org.junit.Test; +import org.vast.data.JSONEncodingImpl; +import org.vast.data.TextEncodingImpl; import org.vast.swe.helper.GeoPosHelper; import org.vast.swe.helper.RasterHelper; import net.opengis.swe.v20.DataComponent; @@ -111,4 +113,37 @@ public void testCheckCompatibleVarSizeArrays() assertTrue(DataComponentChecks.checkStructCompatible(rec1, rec2)); } + + @Test + public void testCheckEqualJsonEncodings() + { + var enc1 = new JSONEncodingImpl(); + var enc2 = new JSONEncodingImpl(); + + assertTrue(DataComponentChecks.checkEncodingEquals(enc1, enc2)); + assertEquals( + DataComponentChecks.getEncodingEqualsHashCode(enc1), + DataComponentChecks.getEncodingEqualsHashCode(enc2)); + } + + + @Test + public void testCheckJsonAndTextEncodingsDiffer() + { + var json = new JSONEncodingImpl(); + var text = new TextEncodingImpl(",", "\n"); + + assertFalse(DataComponentChecks.checkEncodingEquals(json, text)); + } + + + @Test + public void testCombinedHashSupportsJsonEncoding() + { + DataComponent record = geoHelper.newLocationVectorLatLon("test"); + + assertNotNull( + DataComponentChecks.getStructEqualsHashCode(record, new JSONEncodingImpl())); + } + }