Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<relativePath />
</parent>
<artifactId>type-utils</artifactId>
<version>1.12-SNAPSHOT</version>
<version>1.13-SNAPSHOT</version>
<url>https://code.nsa.gov/datawave-type-utils</url>
<licenses>
<license>
Expand All @@ -28,7 +28,7 @@
<version.commons-lang3>3.9</version.commons-lang3>
<version.commons-net>3.6</version.commons-net>
<version.geowave>1.1.0</version.geowave>
<version.hadoop>2.6.0-cdh5.9.1</version.hadoop>
<version.hadoop>3.1.1.7.2.15.0-147</version.hadoop>
<version.jts>1.19.0</version.jts>
<version.protostuff>1.6.2</version.protostuff>
<version.slf4j>1.7.29</version.slf4j>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public abstract class AbstractGeometryNormalizer<T extends datawave.data.type.ut
geoParsers.add(geoParser);
}

// NOTE: If we change the index strategy, then we will need to update the validHash method appropriately.
abstract protected NumericIndexStrategy getIndexStrategy();

abstract protected Index getIndex();
Expand All @@ -49,6 +50,9 @@ public abstract class AbstractGeometryNormalizer<T extends datawave.data.type.ut
*/
@Override
public String normalize(String geoString) throws IllegalArgumentException {
if (validHash(geoString)) {
return geoString;
}
return normalizeDelegateType(createDatawaveGeometry((G) parseGeometry(geoString)));
}

Expand Down Expand Up @@ -175,4 +179,55 @@ private String adjustHexRangeBigInteger(String hexValue, String format, boolean
return String.format(format, new BigInteger(hexValue, 16).subtract(BigInteger.ONE));
}

/**
* This is used to determine if we have a valid geo hash (tier + position). NOTE: If we change the index strategy, then we will need to update this method
* appropriately.
*
* @param value
* @return true if valid
*/
public boolean validHash(String value) {
try {
short tier = getTier(value);
if (validTier(tier) && validLength(tier, value)) {
return validPosition(tier, getPosition(value));
}
} catch (NumberFormatException e) {
// not a valid hex string in the first place
}
return false;
}

public short getTier(String value) {
return Short.parseShort(value.substring(0, 2), 16);
}

public long getPosition(String value) {
if (value.length() == 2) {
return 0;
}
return Long.parseLong(value.substring(2), 16);
}

public boolean validTier(short tier) {
return tier >= 0 && tier <= 0x1f;
}

public boolean validLength(short tier, String value) {
// determine the length of the position in hex characters
// ceil(tier/4) will get the number of bytes
int bytes = (tier >> 2) + ((tier & 0x3) == 0 ? 0 : 1);

// multiply by 2 to get the number of hex digits
int posLen = 2 * bytes;
// length is the tier length plus the position length
return value.length() == (2 + posLen);
}

public boolean validPosition(short tier, long value) {
// The maximum value must be less than pow(2, tier*2)
long max = 1L << (tier * 2);
return value >= 0 && value < max;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@
/**
* A normalizer that, given a parseable geometry string representing an arbitrary geometry, will perform GeoWave indexing with a multi-tiered spatial geowave
* index configuration
*
*/
public class GeometryNormalizer extends AbstractGeometryNormalizer<Geometry,org.locationtech.jts.geom.Geometry> implements OneToManyNormalizer<Geometry> {
private static final long serialVersionUID = 171360806347433135L;

// NOTE: If we change the index strategy, then we will need to update the validHash method appropriately.
// @formatter:off
public static final NumericIndexStrategy indexStrategy = TieredSFCIndexFactory.createFullIncrementalTieredStrategy(
new NumericDimensionDefinition[]{
Expand All @@ -40,6 +40,7 @@ public class GeometryNormalizer extends AbstractGeometryNormalizer<Geometry,org.
public static final Index index = new CustomNameIndex(indexStrategy, null, "geometryIndex");

protected NumericIndexStrategy getIndexStrategy() {
// NOTE: If we change the index strategy, then we will need to update the validHash method appropriately.
return GeometryNormalizer.indexStrategy;
}

Expand All @@ -49,6 +50,9 @@ protected Index getIndex() {

@Override
public List<String> normalizeToMany(String geoString) throws IllegalArgumentException {
if (validHash(geoString)) {
return Lists.newArrayList(geoString);
}
return normalizeDelegateTypeToMany(createDatawaveGeometry(parseGeometry(geoString)));
}

Expand All @@ -64,4 +68,5 @@ public List<String> normalizeDelegateTypeToMany(Geometry geometry) {
protected datawave.data.type.util.Geometry createDatawaveGeometry(org.locationtech.jts.geom.Geometry geometry) {
return new datawave.data.type.util.Geometry(geometry);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@
/**
* A normalizer that, given a parseable geometry string representing a point geometry will perform GeoWave indexing with a single-tier spatial geowave index
* configuration
*
*/
public class PointNormalizer extends AbstractGeometryNormalizer<Point,org.locationtech.jts.geom.Point> {
private static final long serialVersionUID = 171360806347433135L;

// NOTE: If we change the index strategy, then we will need to update the validHash method appropriately.
// @formatter:off
public static final NumericIndexStrategy indexStrategy = TieredSFCIndexFactory.createSingleTierStrategy(
new NumericDimensionDefinition[]{
Expand All @@ -37,6 +37,7 @@ public class PointNormalizer extends AbstractGeometryNormalizer<Point,org.locati
public static final Index index = new CustomNameIndex(indexStrategy, null, "pointIndex");

protected NumericIndexStrategy getIndexStrategy() {
// NOTE: If we change the index strategy, then we will need to update the validHash method appropriately.
return PointNormalizer.indexStrategy;
}

Expand All @@ -47,4 +48,10 @@ protected Index getIndex() {
protected Point createDatawaveGeometry(org.locationtech.jts.geom.Point geometry) {
return new Point(geometry);
}

@Override
public boolean validTier(short tier) {
return tier == 0x1f;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;

public class GeometryNormalizerTest {

Expand Down Expand Up @@ -106,4 +107,24 @@ public void testQueryRanges() throws Exception {

assertEquals(expected, result.toString());
}

@Test
public void testHash() {
String[] validHashes = new String[] {"00", "0100", "020d", "031b", "04df", "05031e", "0604ff", "0713ff", "08c7fe", "09023fff", "0a04ffff", "0b0dffff",
"0c8fffff", "0d01c00000", "0e0b000000", "0f0dfffffe", "1037ffffff", "11023fffffff", "1208ffffffff", "131c00000000", "1437ffffffff",
"15023fffffffff", "16070000000000", "1723ffffffffff", "188fffffffffff", "19013fffffffffff", "1a08ffffffffffff", "1b1c000000000000",
"1c4fffffffffffff", "1d01c0000000000000", "1e0700000000000000", "1f0dffffffffffffff"};
String[] invalidHashes = new String[] {"0", "0001", "01", "1fffffffffffffffff", "200dffffffffffffff", "1c4fffffffffffffff"};
for (String hash : validHashes) {
assertEquals(hash, normalizer.normalize(hash));
}
for (String hash : invalidHashes) {
try {
normalizer.normalize(hash);
fail("Should have failed to normalize " + hash);
} catch (Exception e) {
// this is expected
}
}
}
}