CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-elasticsearch--elasticsearch-geo

Elasticsearch geometry library providing core geometric shapes and spatial utility classes for geometric computations and operations.

Pending
Overview
Eval results
Files

validation.mddocs/

Validation Framework

The Elasticsearch Geo library provides a pluggable validation framework for ensuring geometric validity. The framework supports different validation strategies including standard geometric validation and geography-specific validation with latitude/longitude bounds checking.

Capabilities

GeometryValidator Interface

The core validation interface that defines the contract for geometry validation.

/**
 * Generic geometry validator interface for verifying geometry validity
 */
public interface GeometryValidator {
    
    /**
     * No-operation validator that performs no validation
     */
    public static final GeometryValidator NOOP = (geometry) -> {};
    
    /**
     * Validates the geometry and throws IllegalArgumentException if invalid
     * @param geometry the geometry to validate
     * @throws IllegalArgumentException if geometry is not valid
     */
    void validate(Geometry geometry);
}

// Usage pattern:
GeometryValidator validator = new SomeValidator();
try {
    validator.validate(geometry);
    // Geometry is valid
} catch (IllegalArgumentException e) {
    // Geometry is invalid, handle error
    System.err.println("Invalid geometry: " + e.getMessage());
}

StandardValidator Implementation

Performs Z-coordinate validation based on the ignoreZValue parameter setting.

/**
 * Standard validator that checks Z-coordinate usage constraints
 * - Validates that Z coordinates are only present when ignoreZValue is true
 * - Ensures consistent Z-dimension handling across geometry processing
 */
public class StandardValidator implements GeometryValidator {
    
    /**
     * Gets a StandardValidator instance with specified Z-value handling
     * @param ignoreZValue whether to allow Z coordinates in geometries
     * @return validator instance (cached for performance)
     */
    public static GeometryValidator instance(boolean ignoreZValue)
    
    /**
     * Validates geometry according to Z-coordinate constraints
     * @param geometry the geometry to validate
     * @throws IllegalArgumentException if geometry has Z values when ignoreZValue is false
     */
    @Override
    public void validate(Geometry geometry)
    
    /**
     * Checks individual Z coordinate values
     * @param zValue the Z coordinate to check
     * @throws IllegalArgumentException if Z value is present and ignoreZValue is false
     */
    protected void checkZ(double zValue)
}

// Validation rules applied by StandardValidator:
// - When ignoreZValue is false: Throws exception if any geometry has Z coordinates
// - When ignoreZValue is true: Allows Z coordinates without validation
// - Uses visitor pattern to recursively check all geometry components
// - Provides static factory method for cached instances

GeographyValidator Implementation

Validates geometries for geographic coordinate systems with latitude/longitude bounds checking.

/**
 * Geography-specific validator that checks coordinate bounds and geographic constraints
 * - Validates latitude values are within [-90, 90] degrees
 * - Validates longitude values are within [-180, 180] degrees  
 * - Validates Z-coordinate usage according to ignoreZValue setting
 * - Applies standard validation rules plus geographic constraints
 */
public class GeographyValidator implements GeometryValidator {
    
    /**
     * Minimum longitude value (inclusive)
     */
    private static final double MIN_LON_INCL = -180.0D;
    
    /**
     * Maximum longitude value (inclusive)  
     */
    private static final double MAX_LON_INCL = 180.0D;
    
    /**
     * Minimum latitude value (inclusive)
     */
    private static final double MIN_LAT_INCL = -90.0D;
    
    /**
     * Maximum latitude value (inclusive)
     */
    private static final double MAX_LAT_INCL = 90.0D;
    
    /**
     * Gets a GeographyValidator instance with specified Z-value handling
     * @param ignoreZValue whether to allow Z coordinates in geometries
     * @return validator instance (cached for performance)
     */
    public static GeometryValidator instance(boolean ignoreZValue)
    
    /**
     * Validates geometry according to geographic coordinate constraints
     * @param geometry the geometry to validate
     * @throws IllegalArgumentException if geometry violates geographic constraints
     */
    @Override
    public void validate(Geometry geometry)
    
    /**
     * Validates latitude value is within standard bounds
     * @param latitude the latitude value to check
     * @throws IllegalArgumentException if latitude is outside [-90, 90] range
     */
    protected void checkLatitude(double latitude)
    
    /**
     * Validates longitude value is within standard bounds
     * @param longitude the longitude value to check
     * @throws IllegalArgumentException if longitude is outside [-180, 180] range
     */
    protected void checkLongitude(double longitude)
    
    /**
     * Validates altitude value according to ignoreZValue setting
     * @param zValue the altitude value to check
     * @throws IllegalArgumentException if altitude is present when ignoreZValue is false
     */
    protected void checkAltitude(double zValue)
}

// Additional validation rules for GeographyValidator:
// - Latitude coordinates must be in range [-90.0, 90.0]
// - Longitude coordinates must be in range [-180.0, 180.0]
// - Altitude values should be reasonable (typically above -11000m, below 9000m)
// - Circle radius should be reasonable for geographic scales
// - Rectangle bounds should respect geographic coordinate limits

No-Operation Validator

A validator that performs no validation, useful for performance-critical scenarios or trusted data.

// Built-in no-op validator constant
GeometryValidator noopValidator = GeometryValidator.NOOP;

// No validation is performed - geometry is assumed to be valid
noopValidator.validate(anyGeometry); // Never throws exceptions

// Useful for:
// - Performance-critical applications where validation overhead is unacceptable
// - Processing trusted geometry data that is known to be valid
// - Testing scenarios where validation behavior should be bypassed

Validation Integration

WKT Parsing with Validation

The WKT parser integrates with the validation framework to ensure parsed geometries are valid.

import org.elasticsearch.geometry.utils.WellKnownText;

// Parse WKT with validation
GeometryValidator validator = new StandardValidator();
String wkt = "POINT(-73.935242 40.730610)";

try {
    Geometry geometry = WellKnownText.fromWKT(validator, false, wkt);
    // Geometry is valid and ready to use
} catch (IllegalArgumentException e) {
    // Invalid geometry or validation failure
    System.err.println("Validation failed: " + e.getMessage());
} catch (IOException | ParseException e) {
    // WKT parsing error
    System.err.println("Parse error: " + e.getMessage());
}

// Parse with coercion and validation
try {
    // Coercion attempts to fix minor issues (e.g., auto-close polygons)
    Geometry coerced = WellKnownText.fromWKT(validator, true, wkt);
} catch (Exception e) {
    System.err.println("Coercion and validation failed: " + e.getMessage());
}

Custom Validator Implementation

Create custom validators for specific application requirements.

/**
 * Example custom validator that enforces application-specific constraints
 */
public class ApplicationValidator implements GeometryValidator {
    
    private final double maxAllowedRadius;
    private final Rectangle allowedBounds;
    private final GeometryValidator baseValidator;
    
    public ApplicationValidator(double maxRadius, Rectangle bounds) {
        this.maxAllowedRadius = maxRadius;
        this.allowedBounds = bounds;
        this.baseValidator = new StandardValidator();
    }
    
    @Override
    public void validate(Geometry geometry) {
        // First apply standard validation
        baseValidator.validate(geometry);
        
        // Then apply custom rules using visitor pattern
        geometry.visit(new GeometryVisitor<Void, IllegalArgumentException>() {
            
            @Override
            public Void visit(Circle circle) {
                if (circle.getRadiusMeters() > maxAllowedRadius) {
                    throw new IllegalArgumentException(
                        "Circle radius " + circle.getRadiusMeters() + 
                        " exceeds maximum allowed " + maxAllowedRadius);
                }
                validateWithinBounds(circle.getX(), circle.getY());
                return null;
            }
            
            @Override
            public Void visit(Point point) {
                validateWithinBounds(point.getX(), point.getY());
                return null;
            }
            
            @Override
            public Void visit(Rectangle rectangle) {
                validateWithinBounds(rectangle.getMinX(), rectangle.getMinY());
                validateWithinBounds(rectangle.getMaxX(), rectangle.getMaxY());
                return null;
            }
            
            // ... implement other visit methods
            
            private void validateWithinBounds(double x, double y) {
                if (x < allowedBounds.getMinX() || x > allowedBounds.getMaxX() ||
                    y < allowedBounds.getMinY() || y > allowedBounds.getMaxY()) {
                    throw new IllegalArgumentException(
                        "Coordinate (" + x + ", " + y + ") is outside allowed bounds");
                }
            }
        });
    }
}

Validation Strategies

Strict Validation Strategy

Use comprehensive validation for data integrity in critical applications.

// Strict validation with geographic constraints
GeometryValidator strictValidator = new GeographyValidator();

// Validate all geometries before processing
public void processGeometry(Geometry geometry) {
    strictValidator.validate(geometry);
    
    // Proceed with processing - geometry is guaranteed valid
    String wkt = WellKnownText.toWKT(geometry);
    // ... additional processing
}

// Chain validators for multiple validation levels
public class ChainedValidator implements GeometryValidator {
    private final List<GeometryValidator> validators;
    
    public ChainedValidator(GeometryValidator... validators) {
        this.validators = Arrays.asList(validators);
    }
    
    @Override
    public void validate(Geometry geometry) {
        for (GeometryValidator validator : validators) {
            validator.validate(geometry);
        }
    }
}

// Use chained validation
GeometryValidator chainedValidator = new ChainedValidator(
    StandardValidator.instance(true),
    new GeographyValidator(),
    new ApplicationValidator(10000.0, worldBounds)
);

Performance-Optimized Strategy

Skip validation for performance-critical scenarios with trusted data.

// No validation for maximum performance
GeometryValidator noValidation = GeometryValidator.NOOP;

// High-performance batch processing
public void processBatch(List<Geometry> geometries) {
    for (Geometry geometry : geometries) {
        // Skip validation for trusted data
        noValidation.validate(geometry); // No-op
        
        // Direct processing
        processGeometryDirectly(geometry);
    }
}

// Conditional validation based on data source
public void processGeometry(Geometry geometry, boolean trusted) {
    GeometryValidator validator = trusted ? 
        GeometryValidator.NOOP : 
        StandardValidator.instance(true);
        
    validator.validate(geometry);
    // ... process geometry
}

Usage Examples

Basic Validation Example

import org.elasticsearch.geometry.*;
import org.elasticsearch.geometry.utils.*;

// Create geometries
Point validPoint = new Point(-73.935242, 40.730610);
Point invalidLatPoint = new Point(-73.935242, 95.0); // Invalid latitude > 90
Circle negativeRadius = new Circle(-73.935242, 40.730610, -100.0); // Invalid negative radius

// Standard validation
GeometryValidator standardValidator = StandardValidator.instance(false);

try {
    standardValidator.validate(validPoint); // Passes
    System.out.println("Point is valid");
} catch (IllegalArgumentException e) {
    System.err.println("Point validation failed: " + e.getMessage());
}

try {
    standardValidator.validate(negativeRadius); // Fails - negative radius
} catch (IllegalArgumentException e) {
    System.err.println("Circle validation failed: " + e.getMessage());
}

// Geography validation
GeometryValidator geoValidator = new GeographyValidator();

try {
    geoValidator.validate(invalidLatPoint); // Fails - latitude out of bounds
} catch (IllegalArgumentException e) {
    System.err.println("Geography validation failed: " + e.getMessage());
}

WKT Parsing with Validation

import org.elasticsearch.geometry.utils.WellKnownText;

GeometryValidator validator = StandardValidator.instance(true);

// Valid WKT
String validWkt = "POINT(-73.935242 40.730610)";
try {
    Geometry geometry = WellKnownText.fromWKT(validator, false, validWkt);
    System.out.println("Parsed valid geometry: " + geometry.type());
} catch (Exception e) {
    System.err.println("Failed to parse: " + e.getMessage());
}

// Invalid WKT (unclosed polygon)
String invalidWkt = "POLYGON((-74.0 40.7,-73.9 40.7,-73.9 40.8))"; // Missing closing point

try {
    // Without coercion - should fail
    Geometry geometry = WellKnownText.fromWKT(validator, false, invalidWkt);
} catch (Exception e) {
    System.err.println("Validation failed: " + e.getMessage());
}

try {
    // With coercion - attempts to fix by auto-closing
    Geometry geometry = WellKnownText.fromWKT(validator, true, invalidWkt);
    System.out.println("Coerced geometry is valid");
} catch (Exception e) {
    System.err.println("Coercion failed: " + e.getMessage());
}

Custom Application Validator

// Define application bounds (e.g., continental US)
Rectangle usBounds = new Rectangle(-125.0, -66.0, 49.0, 24.0);

// Create custom validator with application constraints
ApplicationValidator appValidator = new ApplicationValidator(50000.0, usBounds);

// Test geometries
Point validUSPoint = new Point(-100.0, 40.0); // Inside US bounds
Point invalidUSPoint = new Point(0.0, 0.0); // Outside US bounds (null island)
Circle largeCirle = new Circle(-100.0, 40.0, 100000.0); // Too large radius

try {
    appValidator.validate(validUSPoint); // Passes
    System.out.println("US point is valid");
} catch (IllegalArgumentException e) {
    System.err.println("US validation failed: " + e.getMessage());
}

try {
    appValidator.validate(invalidUSPoint); // Fails - outside bounds
} catch (IllegalArgumentException e) {
    System.err.println("Point outside US bounds: " + e.getMessage());
}

try {
    appValidator.validate(largeCirle); // Fails - radius too large
} catch (IllegalArgumentException e) {
    System.err.println("Circle too large: " + e.getMessage());
}

Install with Tessl CLI

npx tessl i tessl/maven-org-elasticsearch--elasticsearch-geo

docs

core-geometry.md

format-conversion.md

index.md

multi-geometry.md

simplification.md

spatial-utilities.md

validation.md

visitor-pattern.md

tile.json