package nl.ipo.cds.etl.filtering;
import static org.junit.Assert.*;
import static nl.ipo.cds.etl.filtering.FilterExpressionFactory.*;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import nl.idgis.commons.jobexecutor.Job;
import nl.idgis.commons.jobexecutor.JobLogger.LogLevel;
import nl.ipo.cds.domain.AttributeType;
import nl.ipo.cds.domain.Dataset;
import nl.ipo.cds.domain.DatasetFilter;
import nl.ipo.cds.domain.FeatureType;
import nl.ipo.cds.domain.FeatureTypeAttribute;
import nl.ipo.cds.domain.FilterExpression;
import nl.ipo.cds.domain.OperatorExpression.OperatorType;
import nl.ipo.cds.domain.QName;
import nl.ipo.cds.domain.ValidateJob;
import nl.ipo.cds.etl.filtering.FilterExpressionValidator.MessageKey;
import nl.ipo.cds.etl.log.EventLogger;
import org.junit.Before;
import org.junit.Test;
public class FilterExpressionValidatorTest {
private FeatureType featureType;
private FilterExpressionValidator validator;
private Logger logger;
@Before
public void createValidator () {
featureType = createFeatureType ();
logger = new Logger ();
validator = new FilterExpressionValidator (featureType, logger);
}
@Test
public void testNoFilter () {
assertFalse (validator.isValid (new ValidateJob (), null));
assertTrue (logger.hasMessage (MessageKey.DATASET_FILTER_MISSING, 1));
}
@Test
public void testNoDatasetRootExpression () {
final DatasetFilter filter = new DatasetFilter ();
assertFalse (validator.isValid (new ValidateJob (), filter));
assertTrue (logger.hasMessage (MessageKey.DATASET_FILTER_NO_DATASET, 1));
assertTrue (logger.hasMessage (MessageKey.DATASET_FILTER_NO_ROOT_EXPRESSION, 1));
}
/*
DATASET_FILTER_LOGICAL_OPERATOR_WITHOUT_INPUTS, // Logical operator must have at least one input.
DATASET_FILTER_LOGICAL_OPERATOR_MISSING_INPUT, // Logical operator has a missing (null) input.
DATASET_FILTER_LOGICAL_OPERATOR_WRONG_TYPE, // Logical operator input is not of type OperatorExpression.
DATASET_FILTER_OPERATOR_NO_ATTRIBUTE,// Comparison operator must have an attribute.
DATASET_FILTER_OPERATOR_NO_VALUE, // Comparison operator has no value.
DATASET_FILTER_OPERATOR_INCOMPATIBLE_TYPES, // Incompatible types in comparison operator.
DATASET_FILTER_OPERATOR_INPUT_COUNT, // Operator must have exactly two inputs.
DATASET_FILTER_MISSING_ATTRIBUTE, // An attribute is missing from the feature type.
*/
@Test
public void testLogicalOperatorWithoutInputs () {
assertValidationMessage (MessageKey.DATASET_FILTER_LOGICAL_OPERATOR_WITHOUT_INPUTS, 1, and ());
}
@Test
public void testLogicalOperatorMissingInput () {
assertValidationMessage (MessageKey.DATASET_FILTER_LOGICAL_OPERATOR_MISSING_INPUT, 2, and (null, null, like (attribute ("a", AttributeType.STRING), "*a*")));
}
@Test
public void testLogicalOperatorWrongType () {
assertValidationMessage (MessageKey.DATASET_FILTER_LOGICAL_OPERATOR_WRONG_TYPE, 2, operatorExpression (
OperatorType.AND,
attribute ("a", AttributeType.STRING),
stringValue ("b")
));
}
@Test
public void testOperatorNoAttribute () {
assertValidationMessage (MessageKey.DATASET_FILTER_OPERATOR_NO_ATTRIBUTE, 1, equal (null, stringValue ("Hello, world!")));
}
@Test
public void testOperatorNoValue () {
assertValidationMessage (MessageKey.DATASET_FILTER_OPERATOR_NO_VALUE, 1, operatorExpression (OperatorType.EQUALS, attribute ("a", AttributeType.STRING), and ()));
}
@Test
public void testOperatorIncompatibleTypes () {
assertValidationMessage (MessageKey.DATASET_FILTER_OPERATOR_INCOMPATIBLE_TYPES, 1, equal (attribute ("a", AttributeType.STRING), integerValue (123)));
}
@Test
public void testOperatorInputCount () {
assertValidationMessage (MessageKey.DATASET_FILTER_OPERATOR_INPUT_COUNT, 1, equal (null, null));
}
@Test
public void testOperatorMissingAttribute () {
assertValidationMessage (MessageKey.DATASET_FILTER_OPERATOR_MISSING_ATTRIBUTE, 1, equal (attribute ("b", AttributeType.STRING), stringValue ("bla")));
assertNoValidationMessage (equal (attribute ("a/operationName", AttributeType.STRING), stringValue ("bla")));
}
private void assertNoValidationMessage (final FilterExpression filterExpression) {
final Job job = new ValidateJob ();
final Dataset dataset = new Dataset ();
final DatasetFilter filter = new DatasetFilter ();
filter.setDataset (dataset);
filter.setRootExpression (filterExpression);
assertTrue (validator.isValid (job, filter));
}
private void assertValidationMessage (final MessageKey messageKey, int count, final FilterExpression filterExpression) {
final Job job = new ValidateJob ();
final Dataset dataset = new Dataset ();
final DatasetFilter filter = new DatasetFilter ();
filter.setDataset (dataset);
filter.setRootExpression (filterExpression);
assertFalse ("Validation has to fail", validator.isValid (job, filter));
assertTrue (String.format ("Must have message %s, found: %s", messageKey, logger.getMessageKeys ()), logger.hasMessage (messageKey, count));
}
private static class Logger implements EventLogger<MessageKey> {
private final Map<MessageKey, Integer> messageKeys = new HashMap<FilterExpressionValidator.MessageKey, Integer> ();
@Override
public String logEvent (final Job job, final MessageKey messageKey, final LogLevel logLevel, final String... messageValues) {
if (messageKeys.containsKey (messageKey)) {
}
messageKeys.put (messageKey, messageKeys.containsKey (messageKey) ? messageKeys.get (messageKey) + 1 : 1);
return "";
}
@Override
public String logEvent (final Job job, final MessageKey messageKey, final LogLevel logLevel, final double x, final double y, final String gmlId, final String... messageValues) {
return logEvent (job, messageKey, logLevel, messageValues);
}
@Override
public String logEvent (final Job job, final MessageKey messageKey, final LogLevel logLevel, final Map<String, Object> context, final String... messageValues) {
return logEvent (job, messageKey, logLevel, messageValues);
}
public boolean hasMessage (final MessageKey messageKey, final int count) {
if (count > 0) {
return messageKeys.containsKey (messageKey) && messageKeys.get (messageKey) == count;
} else {
return messageKeys.containsKey (messageKey) && messageKeys.get (messageKey) > 0;
}
}
public String getMessageKeys () {
final StringBuilder builder = new StringBuilder ();
for (final Map.Entry<MessageKey, Integer> entry: messageKeys.entrySet ()) {
if (builder.length () > 0) {
builder.append (",");
}
builder.append (String.format ("%s(%d)", entry.getKey (), entry.getValue ()));
}
return builder.toString ();
}
}
private FeatureType createFeatureType () {
return new FeatureType() {
@Override
public QName getName () {
return new QName () {
@Override
public int compareTo (final QName o) {
return getLocalPart ().compareTo (o.getLocalPart ());
}
@Override
public String getNamespace () {
return "http://www.idgis.nl/test";
}
@Override
public String getLocalPart () {
return "TestFeatureType";
}
};
}
@Override
public Set<FeatureTypeAttribute> getAttributes () {
return new HashSet<FeatureTypeAttribute>() {
private static final long serialVersionUID = 1L;
{
add (new FeatureTypeAttribute () {
@Override
public int compareTo (final FeatureTypeAttribute o) {
return getName ().compareTo (o.getName ());
}
@Override
public AttributeType getType () {
return AttributeType.STRING;
}
@Override
public QName getName () {
return new QName () {
@Override
public int compareTo (final QName o) {
return getLocalPart ().compareTo (o.getLocalPart ());
}
@Override
public String getNamespace () {
return "http://www.idgis.nl/test";
}
@Override
public String getLocalPart () {
return "a";
}
};
}
});
add (new FeatureTypeAttribute () {
@Override
public int compareTo (final FeatureTypeAttribute o) {
return getName ().compareTo (o.getName ());
}
@Override
public AttributeType getType () {
return AttributeType.INTEGER;
}
@Override
public QName getName () {
return new QName () {
@Override
public int compareTo (final QName o) {
return getLocalPart ().compareTo (o.getLocalPart ());
}
@Override
public String getNamespace () {
return "http://www.idgis.nl/test";
}
@Override
public String getLocalPart () {
return "b";
}
};
}
});
}
};
}
};
}
}