or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-geometry.mdformat-conversion.mdindex.mdmulti-geometry.mdsimplification.mdspatial-utilities.mdvalidation.mdvisitor-pattern.md

validation.mddocs/

0

# Validation Framework

1

2

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.

3

4

## Capabilities

5

6

### GeometryValidator Interface

7

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

8

9

```java { .api }

10

/**

11

* Generic geometry validator interface for verifying geometry validity

12

*/

13

public interface GeometryValidator {

14

15

/**

16

* No-operation validator that performs no validation

17

*/

18

public static final GeometryValidator NOOP = (geometry) -> {};

19

20

/**

21

* Validates the geometry and throws IllegalArgumentException if invalid

22

* @param geometry the geometry to validate

23

* @throws IllegalArgumentException if geometry is not valid

24

*/

25

void validate(Geometry geometry);

26

}

27

28

// Usage pattern:

29

GeometryValidator validator = new SomeValidator();

30

try {

31

validator.validate(geometry);

32

// Geometry is valid

33

} catch (IllegalArgumentException e) {

34

// Geometry is invalid, handle error

35

System.err.println("Invalid geometry: " + e.getMessage());

36

}

37

```

38

39

### StandardValidator Implementation

40

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

41

42

```java { .api }

43

/**

44

* Standard validator that checks Z-coordinate usage constraints

45

* - Validates that Z coordinates are only present when ignoreZValue is true

46

* - Ensures consistent Z-dimension handling across geometry processing

47

*/

48

public class StandardValidator implements GeometryValidator {

49

50

/**

51

* Gets a StandardValidator instance with specified Z-value handling

52

* @param ignoreZValue whether to allow Z coordinates in geometries

53

* @return validator instance (cached for performance)

54

*/

55

public static GeometryValidator instance(boolean ignoreZValue)

56

57

/**

58

* Validates geometry according to Z-coordinate constraints

59

* @param geometry the geometry to validate

60

* @throws IllegalArgumentException if geometry has Z values when ignoreZValue is false

61

*/

62

@Override

63

public void validate(Geometry geometry)

64

65

/**

66

* Checks individual Z coordinate values

67

* @param zValue the Z coordinate to check

68

* @throws IllegalArgumentException if Z value is present and ignoreZValue is false

69

*/

70

protected void checkZ(double zValue)

71

}

72

73

// Validation rules applied by StandardValidator:

74

// - When ignoreZValue is false: Throws exception if any geometry has Z coordinates

75

// - When ignoreZValue is true: Allows Z coordinates without validation

76

// - Uses visitor pattern to recursively check all geometry components

77

// - Provides static factory method for cached instances

78

```

79

80

### GeographyValidator Implementation

81

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

82

83

```java { .api }

84

/**

85

* Geography-specific validator that checks coordinate bounds and geographic constraints

86

* - Validates latitude values are within [-90, 90] degrees

87

* - Validates longitude values are within [-180, 180] degrees

88

* - Validates Z-coordinate usage according to ignoreZValue setting

89

* - Applies standard validation rules plus geographic constraints

90

*/

91

public class GeographyValidator implements GeometryValidator {

92

93

/**

94

* Minimum longitude value (inclusive)

95

*/

96

private static final double MIN_LON_INCL = -180.0D;

97

98

/**

99

* Maximum longitude value (inclusive)

100

*/

101

private static final double MAX_LON_INCL = 180.0D;

102

103

/**

104

* Minimum latitude value (inclusive)

105

*/

106

private static final double MIN_LAT_INCL = -90.0D;

107

108

/**

109

* Maximum latitude value (inclusive)

110

*/

111

private static final double MAX_LAT_INCL = 90.0D;

112

113

/**

114

* Gets a GeographyValidator instance with specified Z-value handling

115

* @param ignoreZValue whether to allow Z coordinates in geometries

116

* @return validator instance (cached for performance)

117

*/

118

public static GeometryValidator instance(boolean ignoreZValue)

119

120

/**

121

* Validates geometry according to geographic coordinate constraints

122

* @param geometry the geometry to validate

123

* @throws IllegalArgumentException if geometry violates geographic constraints

124

*/

125

@Override

126

public void validate(Geometry geometry)

127

128

/**

129

* Validates latitude value is within standard bounds

130

* @param latitude the latitude value to check

131

* @throws IllegalArgumentException if latitude is outside [-90, 90] range

132

*/

133

protected void checkLatitude(double latitude)

134

135

/**

136

* Validates longitude value is within standard bounds

137

* @param longitude the longitude value to check

138

* @throws IllegalArgumentException if longitude is outside [-180, 180] range

139

*/

140

protected void checkLongitude(double longitude)

141

142

/**

143

* Validates altitude value according to ignoreZValue setting

144

* @param zValue the altitude value to check

145

* @throws IllegalArgumentException if altitude is present when ignoreZValue is false

146

*/

147

protected void checkAltitude(double zValue)

148

}

149

150

// Additional validation rules for GeographyValidator:

151

// - Latitude coordinates must be in range [-90.0, 90.0]

152

// - Longitude coordinates must be in range [-180.0, 180.0]

153

// - Altitude values should be reasonable (typically above -11000m, below 9000m)

154

// - Circle radius should be reasonable for geographic scales

155

// - Rectangle bounds should respect geographic coordinate limits

156

```

157

158

### No-Operation Validator

159

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

160

161

```java { .api }

162

// Built-in no-op validator constant

163

GeometryValidator noopValidator = GeometryValidator.NOOP;

164

165

// No validation is performed - geometry is assumed to be valid

166

noopValidator.validate(anyGeometry); // Never throws exceptions

167

168

// Useful for:

169

// - Performance-critical applications where validation overhead is unacceptable

170

// - Processing trusted geometry data that is known to be valid

171

// - Testing scenarios where validation behavior should be bypassed

172

```

173

174

## Validation Integration

175

176

### WKT Parsing with Validation

177

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

178

179

```java { .api }

180

import org.elasticsearch.geometry.utils.WellKnownText;

181

182

// Parse WKT with validation

183

GeometryValidator validator = new StandardValidator();

184

String wkt = "POINT(-73.935242 40.730610)";

185

186

try {

187

Geometry geometry = WellKnownText.fromWKT(validator, false, wkt);

188

// Geometry is valid and ready to use

189

} catch (IllegalArgumentException e) {

190

// Invalid geometry or validation failure

191

System.err.println("Validation failed: " + e.getMessage());

192

} catch (IOException | ParseException e) {

193

// WKT parsing error

194

System.err.println("Parse error: " + e.getMessage());

195

}

196

197

// Parse with coercion and validation

198

try {

199

// Coercion attempts to fix minor issues (e.g., auto-close polygons)

200

Geometry coerced = WellKnownText.fromWKT(validator, true, wkt);

201

} catch (Exception e) {

202

System.err.println("Coercion and validation failed: " + e.getMessage());

203

}

204

```

205

206

### Custom Validator Implementation

207

Create custom validators for specific application requirements.

208

209

```java { .api }

210

/**

211

* Example custom validator that enforces application-specific constraints

212

*/

213

public class ApplicationValidator implements GeometryValidator {

214

215

private final double maxAllowedRadius;

216

private final Rectangle allowedBounds;

217

private final GeometryValidator baseValidator;

218

219

public ApplicationValidator(double maxRadius, Rectangle bounds) {

220

this.maxAllowedRadius = maxRadius;

221

this.allowedBounds = bounds;

222

this.baseValidator = new StandardValidator();

223

}

224

225

@Override

226

public void validate(Geometry geometry) {

227

// First apply standard validation

228

baseValidator.validate(geometry);

229

230

// Then apply custom rules using visitor pattern

231

geometry.visit(new GeometryVisitor<Void, IllegalArgumentException>() {

232

233

@Override

234

public Void visit(Circle circle) {

235

if (circle.getRadiusMeters() > maxAllowedRadius) {

236

throw new IllegalArgumentException(

237

"Circle radius " + circle.getRadiusMeters() +

238

" exceeds maximum allowed " + maxAllowedRadius);

239

}

240

validateWithinBounds(circle.getX(), circle.getY());

241

return null;

242

}

243

244

@Override

245

public Void visit(Point point) {

246

validateWithinBounds(point.getX(), point.getY());

247

return null;

248

}

249

250

@Override

251

public Void visit(Rectangle rectangle) {

252

validateWithinBounds(rectangle.getMinX(), rectangle.getMinY());

253

validateWithinBounds(rectangle.getMaxX(), rectangle.getMaxY());

254

return null;

255

}

256

257

// ... implement other visit methods

258

259

private void validateWithinBounds(double x, double y) {

260

if (x < allowedBounds.getMinX() || x > allowedBounds.getMaxX() ||

261

y < allowedBounds.getMinY() || y > allowedBounds.getMaxY()) {

262

throw new IllegalArgumentException(

263

"Coordinate (" + x + ", " + y + ") is outside allowed bounds");

264

}

265

}

266

});

267

}

268

}

269

```

270

271

## Validation Strategies

272

273

### Strict Validation Strategy

274

Use comprehensive validation for data integrity in critical applications.

275

276

```java { .api }

277

// Strict validation with geographic constraints

278

GeometryValidator strictValidator = new GeographyValidator();

279

280

// Validate all geometries before processing

281

public void processGeometry(Geometry geometry) {

282

strictValidator.validate(geometry);

283

284

// Proceed with processing - geometry is guaranteed valid

285

String wkt = WellKnownText.toWKT(geometry);

286

// ... additional processing

287

}

288

289

// Chain validators for multiple validation levels

290

public class ChainedValidator implements GeometryValidator {

291

private final List<GeometryValidator> validators;

292

293

public ChainedValidator(GeometryValidator... validators) {

294

this.validators = Arrays.asList(validators);

295

}

296

297

@Override

298

public void validate(Geometry geometry) {

299

for (GeometryValidator validator : validators) {

300

validator.validate(geometry);

301

}

302

}

303

}

304

305

// Use chained validation

306

GeometryValidator chainedValidator = new ChainedValidator(

307

StandardValidator.instance(true),

308

new GeographyValidator(),

309

new ApplicationValidator(10000.0, worldBounds)

310

);

311

```

312

313

### Performance-Optimized Strategy

314

Skip validation for performance-critical scenarios with trusted data.

315

316

```java { .api }

317

// No validation for maximum performance

318

GeometryValidator noValidation = GeometryValidator.NOOP;

319

320

// High-performance batch processing

321

public void processBatch(List<Geometry> geometries) {

322

for (Geometry geometry : geometries) {

323

// Skip validation for trusted data

324

noValidation.validate(geometry); // No-op

325

326

// Direct processing

327

processGeometryDirectly(geometry);

328

}

329

}

330

331

// Conditional validation based on data source

332

public void processGeometry(Geometry geometry, boolean trusted) {

333

GeometryValidator validator = trusted ?

334

GeometryValidator.NOOP :

335

StandardValidator.instance(true);

336

337

validator.validate(geometry);

338

// ... process geometry

339

}

340

```

341

342

## Usage Examples

343

344

### Basic Validation Example

345

346

```java

347

import org.elasticsearch.geometry.*;

348

import org.elasticsearch.geometry.utils.*;

349

350

// Create geometries

351

Point validPoint = new Point(-73.935242, 40.730610);

352

Point invalidLatPoint = new Point(-73.935242, 95.0); // Invalid latitude > 90

353

Circle negativeRadius = new Circle(-73.935242, 40.730610, -100.0); // Invalid negative radius

354

355

// Standard validation

356

GeometryValidator standardValidator = StandardValidator.instance(false);

357

358

try {

359

standardValidator.validate(validPoint); // Passes

360

System.out.println("Point is valid");

361

} catch (IllegalArgumentException e) {

362

System.err.println("Point validation failed: " + e.getMessage());

363

}

364

365

try {

366

standardValidator.validate(negativeRadius); // Fails - negative radius

367

} catch (IllegalArgumentException e) {

368

System.err.println("Circle validation failed: " + e.getMessage());

369

}

370

371

// Geography validation

372

GeometryValidator geoValidator = new GeographyValidator();

373

374

try {

375

geoValidator.validate(invalidLatPoint); // Fails - latitude out of bounds

376

} catch (IllegalArgumentException e) {

377

System.err.println("Geography validation failed: " + e.getMessage());

378

}

379

```

380

381

### WKT Parsing with Validation

382

383

```java

384

import org.elasticsearch.geometry.utils.WellKnownText;

385

386

GeometryValidator validator = StandardValidator.instance(true);

387

388

// Valid WKT

389

String validWkt = "POINT(-73.935242 40.730610)";

390

try {

391

Geometry geometry = WellKnownText.fromWKT(validator, false, validWkt);

392

System.out.println("Parsed valid geometry: " + geometry.type());

393

} catch (Exception e) {

394

System.err.println("Failed to parse: " + e.getMessage());

395

}

396

397

// Invalid WKT (unclosed polygon)

398

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

399

400

try {

401

// Without coercion - should fail

402

Geometry geometry = WellKnownText.fromWKT(validator, false, invalidWkt);

403

} catch (Exception e) {

404

System.err.println("Validation failed: " + e.getMessage());

405

}

406

407

try {

408

// With coercion - attempts to fix by auto-closing

409

Geometry geometry = WellKnownText.fromWKT(validator, true, invalidWkt);

410

System.out.println("Coerced geometry is valid");

411

} catch (Exception e) {

412

System.err.println("Coercion failed: " + e.getMessage());

413

}

414

```

415

416

### Custom Application Validator

417

418

```java

419

// Define application bounds (e.g., continental US)

420

Rectangle usBounds = new Rectangle(-125.0, -66.0, 49.0, 24.0);

421

422

// Create custom validator with application constraints

423

ApplicationValidator appValidator = new ApplicationValidator(50000.0, usBounds);

424

425

// Test geometries

426

Point validUSPoint = new Point(-100.0, 40.0); // Inside US bounds

427

Point invalidUSPoint = new Point(0.0, 0.0); // Outside US bounds (null island)

428

Circle largeCirle = new Circle(-100.0, 40.0, 100000.0); // Too large radius

429

430

try {

431

appValidator.validate(validUSPoint); // Passes

432

System.out.println("US point is valid");

433

} catch (IllegalArgumentException e) {

434

System.err.println("US validation failed: " + e.getMessage());

435

}

436

437

try {

438

appValidator.validate(invalidUSPoint); // Fails - outside bounds

439

} catch (IllegalArgumentException e) {

440

System.err.println("Point outside US bounds: " + e.getMessage());

441

}

442

443

try {

444

appValidator.validate(largeCirle); // Fails - radius too large

445

} catch (IllegalArgumentException e) {

446

System.err.println("Circle too large: " + e.getMessage());

447

}

448

```