package nl.ipo.cds.etl.theme.productionfacility;
import static nl.ipo.cds.etl.theme.productionfacility.Message.ATTRIBUTE_CODE_CODESPACE_INVALID;
import static nl.ipo.cds.etl.theme.productionfacility.Message.ATTRIBUTE_CODE_INVALID;
import static nl.ipo.cds.etl.theme.productionfacility.Message.ATTRIBUTE_EMPTY;
import static nl.ipo.cds.etl.theme.productionfacility.Message.ATTRIBUTE_GROUP_INCONSISTENT;
import static nl.ipo.cds.etl.theme.productionfacility.Message.ATTRIBUTE_NULL;
import static nl.ipo.cds.etl.theme.productionfacility.Message.GEOMETRY_DISCONTINUITY;
import static nl.ipo.cds.etl.theme.productionfacility.Message.GEOMETRY_EMPTY_MULTIGEOMETRY;
import static nl.ipo.cds.etl.theme.productionfacility.Message.GEOMETRY_EXTERIOR_RING_CW;
import static nl.ipo.cds.etl.theme.productionfacility.Message.GEOMETRY_INTERIOR_DISCONNECTED;
import static nl.ipo.cds.etl.theme.productionfacility.Message.GEOMETRY_INTERIOR_RINGS_TOUCH;
import static nl.ipo.cds.etl.theme.productionfacility.Message.GEOMETRY_INTERIOR_RINGS_WITHIN;
import static nl.ipo.cds.etl.theme.productionfacility.Message.GEOMETRY_INTERIOR_RING_CCW;
import static nl.ipo.cds.etl.theme.productionfacility.Message.GEOMETRY_INTERIOR_RING_OUTSIDE_EXTERIOR;
import static nl.ipo.cds.etl.theme.productionfacility.Message.GEOMETRY_INTERIOR_RING_TOUCHES_EXTERIOR;
import static nl.ipo.cds.etl.theme.productionfacility.Message.GEOMETRY_ONLY_SURFACE_OR_MULTISURFACE;
import static nl.ipo.cds.etl.theme.productionfacility.Message.GEOMETRY_POINT_DUPLICATION;
import static nl.ipo.cds.etl.theme.productionfacility.Message.GEOMETRY_RING_NOT_CLOSED;
import static nl.ipo.cds.etl.theme.productionfacility.Message.GEOMETRY_RING_SELF_INTERSECTION;
import static nl.ipo.cds.etl.theme.productionfacility.Message.GEOMETRY_SELF_INTERSECTION;
import static nl.ipo.cds.etl.theme.productionfacility.Message.GEOMETRY_SRS_NOT_RD;
import static nl.ipo.cds.etl.theme.productionfacility.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 ProductionFacilityValidator extends AbstractValidator<ProductionFacility, Message, Context> {
private final CodeExpression<Message,Context> inspireIdDatasetCode = code ("inspireIdDatasetCode");
private final AttributeExpression<Message, Context, String> inspireIdLocalId = stringAttr ("inspireIdLocalId");
private final AttributeExpression<Message, Context, String> productionFacilityId = stringAttr ("productionFacilityId");
private final AttributeExpression<Message, Context, String> thematicIdentifier = stringAttr ("thematicIdentifier");
private final AttributeExpression<Message, Context, String> thematicIdentifierScheme = stringAttr ("thematicIdentifierScheme");
private final GeometryExpression<Message, Context, Geometry> geometry = geometry ("geometry");
private final CodeExpression<Message,Context> functionActivity = code ("functionActivity");
private final CodeExpression<Message,Context> functionInput = code ("functionInput");
private final CodeExpression<Message,Context> functionOutput = code ("functionOutput");
private final AttributeExpression<Message, Context, String> functionDescription = stringAttr ("functionDescription");
private final AttributeExpression<Message, Context, String> name = stringAttr ("name");
private final GeometryExpression<Message, Context, Geometry> surfaceGeometry = geometry ("surfaceGeometry");
private final AttributeExpression<Message, Context, String> statusDescription = stringAttr ("statusDescription");
private final CodeExpression<Message,Context> statusType = code ("statusType");
private final Constant<Message, Context, String> inspireIdDatasetCodeSpace = constant ("http://www.inspire-provincies.nl/codeList/DatasetTypeCode/ProductionFacility");
private final Constant<Message, Context, String> functionActivityCodeSpace = constant ("http://inspire.ec.europa.eu/codeList/EconomicActivityNACEValue");
private final Constant<Message, Context, String> functionInputCodeSpace = constant ("http://inspire.ec.europa.eu/codeList/ProductCPAValue");
private final Constant<Message, Context, String> functionOutputCodeSpace = constant ("http://inspire.ec.europa.eu/codeList/ProductCPAValue");
private final Constant<Message, Context, String> statusTypeCodeSpace = constant ("http://inspire.ec.europa.eu/codeList/ConditionOfFacilityValue");
public ProductionFacilityValidator(final Map<Object, Object> validatorMessages) throws CompilerException {
super(Context.class, ProductionFacility.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 (not (isBlank (inspireIdDatasetCode.code()))).message (ATTRIBUTE_EMPTY, constant (inspireIdDatasetCode.name)),
validate (inspireIdDatasetCode.hasCodeSpace (inspireIdDatasetCodeSpace)).message (ATTRIBUTE_CODE_CODESPACE_INVALID, inspireIdDatasetCode.codeSpace(), constant(inspireIdDatasetCode.name), inspireIdDatasetCodeSpace),
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> getProductionFacilityIdValidator () {
return validate (
and(
validate (not (productionFacilityId.isNull ())).message (ATTRIBUTE_NULL, constant(productionFacilityId.name)),
validate (not (isBlank (productionFacilityId))).message (ATTRIBUTE_EMPTY, constant(productionFacilityId.name))
).shortCircuit()
);
}
public Validator<Message, Context> getThematicIdentifierValidator () {
return validate (
and(
ifExp (not (or (thematicIdentifier.isNull (), isBlank (thematicIdentifier))),
and (
validate (not (thematicIdentifierScheme.isNull())).message (ATTRIBUTE_GROUP_INCONSISTENT, constant (thematicIdentifierScheme.name), constant (thematicIdentifier.name)),
validate (not (isBlank (thematicIdentifierScheme))).message (ATTRIBUTE_GROUP_INCONSISTENT, constant (thematicIdentifierScheme.name), constant (thematicIdentifier.name))
).shortCircuit(),
constant(true)
),
ifExp (not (or (thematicIdentifierScheme.isNull (), isBlank (thematicIdentifierScheme))),
and (
validate (not (thematicIdentifier.isNull())).message (ATTRIBUTE_GROUP_INCONSISTENT, constant (thematicIdentifier.name), constant (thematicIdentifierScheme.name)),
validate (not (isBlank (thematicIdentifier))).message (ATTRIBUTE_GROUP_INCONSISTENT, constant (thematicIdentifier.name), constant (thematicIdentifierScheme.name))
).shortCircuit(),
constant(true)
)
)
);
}
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)),
// 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> getFunctionActivityValidator () {
return validate (
and(
validate (not (functionActivity.isNull ())).message (ATTRIBUTE_NULL, constant(functionActivity.name)),
validate (functionActivity.hasCodeSpace (functionActivityCodeSpace)).message (ATTRIBUTE_CODE_CODESPACE_INVALID, functionActivity.codeSpace(), constant(functionActivity.name), functionActivityCodeSpace),
validate (not (isBlank (functionActivity.code()))).message (ATTRIBUTE_EMPTY, constant(functionActivity.name))
// must be deactivated as long as codelist http://inspire.ec.europa.eu/codeList/EconomicActivityNACEValue is empty
// validate (functionActivity.isValid ()).message (ATTRIBUTE_CODE_INVALID, functionActivity.code(), constant(functionActivity.name), functionActivityCodeSpace)
).shortCircuit()
);
}
public Validator<Message, Context> getFunctionInputValidator () {
return validate (
ifExp (
functionInput.isNull (),
constant(true),
and(
validate (functionInput.hasCodeSpace (functionInputCodeSpace)).message (ATTRIBUTE_CODE_CODESPACE_INVALID, functionInput.codeSpace(), constant(functionInput.name), functionInputCodeSpace),
validate (not (isBlank (functionInput.code()))).message (ATTRIBUTE_EMPTY, constant(functionInput.name))
// must be deactivated as long as codelist http://inspire.ec.europa.eu/codeList/ProductCPAValue is empty
// validate (functionInput.isValid ()).message (ATTRIBUTE_CODE_INVALID, functionInput.code(), constant(functionInput.name), functionInputCodeSpace)
).shortCircuit()
)
);
}
public Validator<Message, Context> getFunctionOutputValidator () {
return validate (
ifExp (
functionOutput.isNull (),
constant(true),
and(
validate (functionOutput.hasCodeSpace (functionOutputCodeSpace)).message (ATTRIBUTE_CODE_CODESPACE_INVALID, functionOutput.codeSpace(), constant(functionOutput.name), functionOutputCodeSpace),
validate (not (isBlank (functionOutput.code()))).message (ATTRIBUTE_EMPTY, constant(functionOutput.name))
// must be deactivated as long as codelist http://inspire.ec.europa.eu/codeList/ProductCPAValue is empty
// validate (functionOutput.isValid ()).message (ATTRIBUTE_CODE_INVALID, functionOutput.code(), constant(functionOutput.name), functionOutputCodeSpace)
).shortCircuit()
)
);
}
public Validator<Message, Context> getFunctionDescriptionValidator () {
return validate (
ifExp (
functionDescription.isNull (),
constant(true),
validate (not (isBlank (functionDescription))).message (ATTRIBUTE_EMPTY, constant(functionDescription.name))
)
);
}
public Validator<Message, Context> getNameValidator () {
return validate (
ifExp (
name.isNull (),
constant(true),
validate (not (isBlank (name))).message (ATTRIBUTE_EMPTY, constant(name.name))
)
);
}
public Validator<Message, Context> getSurfaceGeometryValidator () {
return validate (
ifExp(
surfaceGeometry.isNull (),
constant(true),
and (
// The following validations short-circuit, there must be a non-empty, Surface geometry:
validate (not (surfaceGeometry.isEmptyMultiGeometry())).message (GEOMETRY_EMPTY_MULTIGEOMETRY),
validate (surfaceGeometry.isSurfaceOrMultiSurface()).message (GEOMETRY_ONLY_SURFACE_OR_MULTISURFACE),
// Non short-circuited validations:
and (
// Short circuit to prevent the interiorDisconnected validation if
// any of the other validations fail:
and (
and (
validate (not (surfaceGeometry.hasCurveDuplicatePoint ())).message (GEOMETRY_POINT_DUPLICATION, lastLocation ()),
validate (not (surfaceGeometry.hasCurveDiscontinuity ())).message (GEOMETRY_DISCONTINUITY),
validate (not (surfaceGeometry.hasCurveSelfIntersection ())).message (GEOMETRY_SELF_INTERSECTION, lastLocation ()),
validate (not (surfaceGeometry.hasUnclosedRing ())).message (GEOMETRY_RING_NOT_CLOSED),
validate (not (surfaceGeometry.hasRingSelfIntersection ())).message (GEOMETRY_RING_SELF_INTERSECTION, lastLocation ()),
validate (not (surfaceGeometry.hasTouchingInteriorRings ())).message(GEOMETRY_INTERIOR_RINGS_TOUCH, lastLocation ()),
validate (not (surfaceGeometry.hasInteriorRingsWithin ())).message (GEOMETRY_INTERIOR_RINGS_WITHIN)
),
validate (not (surfaceGeometry.isInteriorDisconnected ())).message (GEOMETRY_INTERIOR_DISCONNECTED)
).shortCircuit (),
// Non-blocking validations:
validate (not (surfaceGeometry.hasExteriorRingCW ())).nonBlocking ().message (GEOMETRY_EXTERIOR_RING_CW),
validate (not (surfaceGeometry.hasInteriorRingCCW ())).nonBlocking ().message (GEOMETRY_INTERIOR_RING_CCW),
validate (not (surfaceGeometry.hasInteriorRingTouchingExterior ())).nonBlocking ().message (GEOMETRY_INTERIOR_RING_TOUCHES_EXTERIOR, lastLocation ()),
validate (not (surfaceGeometry.hasInteriorRingOutsideExterior ())).nonBlocking ().message (GEOMETRY_INTERIOR_RING_OUTSIDE_EXTERIOR),
// SRS validations:
and (
validate (surfaceGeometry.hasSrs ()).message (GEOMETRY_SRS_NULL),
validate (surfaceGeometry.isSrs (constant ("28992"))).message (GEOMETRY_SRS_NOT_RD, surfaceGeometry.srsName ())
).shortCircuit()
)
).shortCircuit ()
)
);
}
public Validator<Message, Context> getStatusValidator () {
return validate (
not (
and (
statusType.isNull(),
not (statusDescription.isNull())
)
)
).message (ATTRIBUTE_GROUP_INCONSISTENT, constant(statusType.name), constant(statusDescription.name));
}
public Validator<Message, Context> getStatusDescriptionValidator () {
return validate (
ifExp (
statusDescription.isNull (),
constant(true),
validate (not (isBlank (statusDescription))).message (ATTRIBUTE_EMPTY, constant(statusDescription.name))
)
);
}
public Validator<Message, Context> getStatusTypeValidator () {
return validate (
ifExp (
statusType.isNull (),
constant(true),
and(
validate (statusType.hasCodeSpace (statusTypeCodeSpace)).message (ATTRIBUTE_CODE_CODESPACE_INVALID, statusType.codeSpace(), constant(statusType.name), statusTypeCodeSpace),
validate (not (isBlank (statusType.code()))).message (ATTRIBUTE_EMPTY, constant(statusType.name)),
validate (statusType.isValid ()).message (ATTRIBUTE_CODE_INVALID, statusType.code(), constant(statusType.name), statusTypeCodeSpace)
).shortCircuit()
)
);
}
}