package nl.ipo.cds.etl.theme.areamanagement;
import static nl.ipo.cds.etl.theme.areamanagement.Message.ATTRIBUTE_CODE_CODESPACE_INVALID;
import static nl.ipo.cds.etl.theme.areamanagement.Message.ATTRIBUTE_CODE_INVALID;
import static nl.ipo.cds.etl.theme.areamanagement.Message.ATTRIBUTE_EMPTY;
import static nl.ipo.cds.etl.theme.areamanagement.Message.ATTRIBUTE_GROUP_INCONSISTENT;
import static nl.ipo.cds.etl.theme.areamanagement.Message.ATTRIBUTE_NOT_URL;
import static nl.ipo.cds.etl.theme.areamanagement.Message.ATTRIBUTE_NULL;
import static nl.ipo.cds.etl.theme.areamanagement.Message.ATTRIBUTE_VALUE_TOO_HIGH;
import static nl.ipo.cds.etl.theme.areamanagement.Message.ATTRIBUTE_VALUE_TOO_LOW;
import static nl.ipo.cds.etl.theme.areamanagement.Message.GEOMETRY_DISCONTINUITY;
import static nl.ipo.cds.etl.theme.areamanagement.Message.GEOMETRY_EXTERIOR_RING_CW;
import static nl.ipo.cds.etl.theme.areamanagement.Message.GEOMETRY_INTERIOR_DISCONNECTED;
import static nl.ipo.cds.etl.theme.areamanagement.Message.GEOMETRY_INTERIOR_RINGS_TOUCH;
import static nl.ipo.cds.etl.theme.areamanagement.Message.GEOMETRY_INTERIOR_RINGS_WITHIN;
import static nl.ipo.cds.etl.theme.areamanagement.Message.GEOMETRY_INTERIOR_RING_CCW;
import static nl.ipo.cds.etl.theme.areamanagement.Message.GEOMETRY_INTERIOR_RING_OUTSIDE_EXTERIOR;
import static nl.ipo.cds.etl.theme.areamanagement.Message.GEOMETRY_INTERIOR_RING_TOUCHES_EXTERIOR;
import static nl.ipo.cds.etl.theme.areamanagement.Message.GEOMETRY_POINT_DUPLICATION;
import static nl.ipo.cds.etl.theme.areamanagement.Message.GEOMETRY_RING_NOT_CLOSED;
import static nl.ipo.cds.etl.theme.areamanagement.Message.GEOMETRY_RING_SELF_INTERSECTION;
import static nl.ipo.cds.etl.theme.areamanagement.Message.GEOMETRY_SELF_INTERSECTION;
import static nl.ipo.cds.etl.theme.areamanagement.Message.GEOMETRY_SRS_NOT_RD;
import static nl.ipo.cds.etl.theme.areamanagement.Message.GEOMETRY_SRS_NULL;
import java.util.Map;
import nl.ipo.cds.domain.EtlJob;
import nl.ipo.cds.etl.AbstractValidator;
import nl.ipo.cds.validation.AttributeExpression;
import nl.ipo.cds.validation.ValidationReporter;
import nl.ipo.cds.validation.Validator;
import nl.ipo.cds.validation.constants.Constant;
import nl.ipo.cds.validation.execute.CompilerException;
import nl.ipo.cds.validation.geometry.GeometryExpression;
import nl.ipo.cds.validation.gml.CodeExpression;
import nl.ipo.cds.validation.gml.codelists.CodeListFactory;
import org.deegree.geometry.Geometry;
public class AreaManagementValidator extends AbstractValidator<AreaManagement, Message, Context> {
private final CodeExpression<Message,Context> inspireIdDatasetCode = code ("inspireIdDatasetCode");
private final AttributeExpression<Message, Context, String> inspireIdLocalId = stringAttr ("inspireIdLocalId");
private final GeometryExpression<Message, Context, Geometry> geometry = geometry ("geometry");
private final CodeExpression<Message,Context> zoneTypeCode = code ("zoneTypeCode");
private final CodeExpression<Message,Context> environmentalDomainCode = code ("environmentalDomainCode");
private final AttributeExpression<Message, Context, String> thematicIdIdentifier = stringAttr ("thematicIdIdentifier");
private final AttributeExpression<Message, Context, String> thematicIdIdentifierScheme = stringAttr ("thematicIdIdentifierScheme");
private final AttributeExpression<Message, Context, String> legalBasisName = stringAttr ("legalBasisName");
private final AttributeExpression<Message, Context, String> legalBasisLink = stringAttr ("legalBasisLink");
private final CodeExpression<Message, Context> specialisedZoneTypeCode = code ("specialisedZoneTypeCode");
private final AttributeExpression<Message, Context, Double> noiseLowValue = doubleAttr("noiseLowValue");
private final AttributeExpression<Message, Context, Double> noiseHighValue = doubleAttr("noiseHighValue");
private final Constant<Message, Context, String> inspireIdDatasetCodeSpace = constant ("http://www.inspire-provincies.nl/codeList/DatasetTypeCode/AreaManagement");
private final Constant<Message, Context, String> zoneTypeCodeSpace = constant ("http://inspire.ec.europa.eu/codeList/ZoneTypeCode");
private final Constant<Message, Context, String> environmentalDomainCodeSpace = constant ("http://inspire.ec.europa.eu/codeList/EnvironmentalDomain");
public AreaManagementValidator(final Map<Object, Object> validatorMessages) throws CompilerException {
super(Context.class, AreaManagement.class, validatorMessages);
compile();
}
@Override
public Context beforeJob(final EtlJob job, final CodeListFactory codeListFactory,
final ValidationReporter<Message, Context> reporter) {
return new Context(codeListFactory, reporter);
}
public Validator<Message, Context> getInspireIdDatasetCodeValidator () {
return validate (
and(
validate (not (inspireIdDatasetCode.isNull ())).message (ATTRIBUTE_NULL, constant (inspireIdDatasetCode.name)),
validate (inspireIdDatasetCode.hasCodeSpace (inspireIdDatasetCodeSpace)).message (ATTRIBUTE_CODE_CODESPACE_INVALID, inspireIdDatasetCode.codeSpace(), constant(inspireIdDatasetCode.name), inspireIdDatasetCodeSpace),
validate (not (isBlank (inspireIdDatasetCode.code()))).message (ATTRIBUTE_EMPTY, constant (inspireIdDatasetCode.name)),
validate (inspireIdDatasetCode.isValid ()).message (ATTRIBUTE_CODE_INVALID, inspireIdDatasetCode.code(), constant (inspireIdDatasetCode.name), inspireIdDatasetCodeSpace)
).shortCircuit()
);
}
public Validator<Message, Context> getInspireIdLocalIdValidator () {
return validate (
and(
validate (not (inspireIdLocalId.isNull ())).message (ATTRIBUTE_NULL, constant(inspireIdLocalId.name)),
validate (not (isBlank (inspireIdLocalId))).message (ATTRIBUTE_EMPTY, constant(inspireIdLocalId.name))
).shortCircuit()
);
}
public Validator<Message, Context> getGeometryValidator () {
return validate (
and (
// The following validations short-circuit, there must be a non-null and non-empty, non-point geometry:
validate (not (geometry.isNull ())).message (ATTRIBUTE_NULL, constant (geometry.name)),
validate (not (geometry.isEmptyMultiGeometry ())).message (ATTRIBUTE_NULL, constant (geometry.name)),
// Non short-circuited validations:
and (
// Short circuit to prevent the interiorDisconnected validation if
// any of the other validations fail:
and (
and (
validate (not (geometry.hasCurveDuplicatePoint ())).message (GEOMETRY_POINT_DUPLICATION, lastLocation ()),
validate (not (geometry.hasCurveDiscontinuity ())).message (GEOMETRY_DISCONTINUITY),
validate (not (geometry.hasCurveSelfIntersection ())).message (GEOMETRY_SELF_INTERSECTION, lastLocation ()),
validate (not (geometry.hasUnclosedRing ())).message (GEOMETRY_RING_NOT_CLOSED),
validate (not (geometry.hasRingSelfIntersection ())).message (GEOMETRY_RING_SELF_INTERSECTION, lastLocation ()),
validate (not (geometry.hasTouchingInteriorRings ())).message(GEOMETRY_INTERIOR_RINGS_TOUCH, lastLocation ()),
validate (not (geometry.hasInteriorRingsWithin ())).message (GEOMETRY_INTERIOR_RINGS_WITHIN)
),
validate (not (geometry.isInteriorDisconnected ())).message (GEOMETRY_INTERIOR_DISCONNECTED)
).shortCircuit (),
// Non-blocking validations:
validate (not (geometry.hasExteriorRingCW ())).nonBlocking ().message (GEOMETRY_EXTERIOR_RING_CW),
validate (not (geometry.hasInteriorRingCCW ())).nonBlocking ().message (GEOMETRY_INTERIOR_RING_CCW),
validate (not (geometry.hasInteriorRingTouchingExterior ())).nonBlocking ().message (GEOMETRY_INTERIOR_RING_TOUCHES_EXTERIOR, lastLocation ()),
validate (not (geometry.hasInteriorRingOutsideExterior ())).nonBlocking ().message (GEOMETRY_INTERIOR_RING_OUTSIDE_EXTERIOR),
// SRS validations:
and (
validate (geometry.hasSrs ()).message (GEOMETRY_SRS_NULL),
validate (geometry.isSrs (constant ("28992"))).message (GEOMETRY_SRS_NOT_RD, geometry.srsName ())
).shortCircuit()
)
).shortCircuit ()
);
}
public Validator<Message, Context> getZoneTypeCodeValidator () {
return validate (
and(
validate (not (zoneTypeCode.isNull ())).message (ATTRIBUTE_NULL, constant(zoneTypeCode.name)),
validate (zoneTypeCode.hasCodeSpace (zoneTypeCodeSpace)).message (ATTRIBUTE_CODE_CODESPACE_INVALID, zoneTypeCode.codeSpace(), constant(zoneTypeCode.name), zoneTypeCodeSpace),
validate (not (isBlank (zoneTypeCode.code()))).message (ATTRIBUTE_EMPTY, constant(zoneTypeCode.name)),
validate (zoneTypeCode.isValid ()).message (ATTRIBUTE_CODE_INVALID, zoneTypeCode.code(), constant(zoneTypeCode.name), zoneTypeCodeSpace)
).shortCircuit()
);
}
public Validator<Message, Context> getEnvironmentalDomainCodeValidator () {
return validate (
and(
validate (not (environmentalDomainCode.isNull ())).message (ATTRIBUTE_NULL, constant(environmentalDomainCode.name)),
validate (environmentalDomainCode.hasCodeSpace (environmentalDomainCodeSpace)).message (ATTRIBUTE_CODE_CODESPACE_INVALID, environmentalDomainCode.codeSpace(), constant(environmentalDomainCode.name), constant (environmentalDomainCodeSpace.value)),
validate (not (isBlank (environmentalDomainCode.code()))).message (ATTRIBUTE_EMPTY, constant(environmentalDomainCode.name)),
validate (environmentalDomainCode.isValid ()).message (ATTRIBUTE_CODE_INVALID, environmentalDomainCode.code(), constant(environmentalDomainCode.name), environmentalDomainCodeSpace)
).shortCircuit()
);
}
public Validator<Message, Context> getThematicIdIdentifierValidator () {
return validate (
and(
ifExp (not (or (thematicIdIdentifier.isNull (), isBlank (thematicIdIdentifier))),
and (
validate (not (thematicIdIdentifierScheme.isNull())).message (ATTRIBUTE_GROUP_INCONSISTENT, constant (thematicIdIdentifierScheme.name), constant (thematicIdIdentifier.name)),
validate (not (isBlank (thematicIdIdentifierScheme))).message (ATTRIBUTE_GROUP_INCONSISTENT, constant (thematicIdIdentifierScheme.name), constant (thematicIdIdentifier.name))
).shortCircuit(),
constant(true)
),
ifExp (not (or (thematicIdIdentifierScheme.isNull (), isBlank (thematicIdIdentifierScheme))),
and (
validate (not (thematicIdIdentifier.isNull())).message (ATTRIBUTE_GROUP_INCONSISTENT, constant (thematicIdIdentifier.name), constant (thematicIdIdentifierScheme.name)),
validate (not (isBlank (thematicIdIdentifier))).message (ATTRIBUTE_GROUP_INCONSISTENT, constant (thematicIdIdentifier.name), constant (thematicIdIdentifierScheme.name))
).shortCircuit(),
constant(true)
)
)
);
}
public Validator<Message, Context> getLegalBasisNameValidator () {
return validate (
ifExp (
legalBasisName.isNull(),
constant(true),
validate (not (isBlank (legalBasisName))).message (ATTRIBUTE_EMPTY, constant(legalBasisName.name))
)
);
}
public Validator<Message, Context> getLegalBasisLinkValidator () {
return validate (
or(
legalBasisLink.isNull (),
and (
not (isBlank(legalBasisLink)),
isUrl(legalBasisLink)
).shortCircuit()
)
).message(ATTRIBUTE_NOT_URL, legalBasisLink, constant (legalBasisLink.name));
}
public Validator<Message, Context> getSpecialisedZoneTypeCodeValidator () {
return validate (
ifExp (
specialisedZoneTypeCode.isNull(),
constant(true),
validate (not (isBlank (specialisedZoneTypeCode.code()))).message (ATTRIBUTE_EMPTY, constant (specialisedZoneTypeCode.name))
)
);
}
public Validator<Message, Context> getNoiseLowValueValidator () {
return validate (
ifExp (
noiseLowValue.isNull(),
constant(true),
and (
validate (gte(noiseLowValue, constant(0.0))).message (ATTRIBUTE_VALUE_TOO_LOW, noiseLowValue, constant (noiseLowValue.name), constant(0.0)),
validate (lte(noiseLowValue, constant(150.0))).message (ATTRIBUTE_VALUE_TOO_HIGH, noiseLowValue, constant (noiseLowValue.name), constant(150.0))
)
)
);
}
public Validator<Message, Context> getNoiseHighValueValidator () {
return validate (
ifExp (
noiseHighValue.isNull(),
constant(true),
and (
validate (gte(noiseHighValue, constant(0.0))).message (ATTRIBUTE_VALUE_TOO_LOW, noiseHighValue, constant (noiseHighValue.name), constant(0.0)),
validate (lte(noiseHighValue, constant(150.0))).message (ATTRIBUTE_VALUE_TOO_HIGH, noiseHighValue, constant (noiseHighValue.name), constant(150.0))
)
)
);
}
}