/*
* ====================
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2008-2009 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of the Common Development
* and Distribution License("CDDL") (the "License"). You may not use this file
* except in compliance with the License.
*
* You can obtain a copy of the License at
* http://opensource.org/licenses/cddl1.php
* See the License for the specific language governing permissions and limitations
* under the License.
*
* When distributing the Covered Code, include this CDDL Header Notice in each file
* and include the License file at http://opensource.org/licenses/cddl1.php.
* If applicable, add the following below this CDDL Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
* ====================
*/
package org.identityconnectors.framework.common.objects.filter;
import static org.fest.assertions.Assertions.assertThat;
import static org.fest.assertions.Index.atIndex;
import static org.testng.Assert.assertEquals;
import java.util.List;
import org.identityconnectors.framework.common.objects.Attribute;
import org.identityconnectors.framework.common.objects.AttributeBuilder;
import org.testng.annotations.Test;
public class FilterTranslatorTests {
private static class AllFiltersTranslator extends AbstractFilterTranslator<String> {
@Override
protected String createAndExpression(String leftExpression, String rightExpression) {
return "( & " + leftExpression + " " + rightExpression + " )";
}
@Override
protected String createOrExpression(String leftExpression, String rightExpression) {
return "( | " + leftExpression + " " + rightExpression + " )";
}
@Override
protected String createContainsExpression(ContainsFilter filter, boolean not) {
String rv = "( CONTAINS " + filter.getName() + " " + filter.getValue() + " )";
return not(rv, not);
}
@Override
protected String createEndsWithExpression(EndsWithFilter filter, boolean not) {
String rv = "( ENDS-WITH " + filter.getName() + " " + filter.getValue() + " )";
return not(rv, not);
}
@Override
protected String createEqualsExpression(EqualsFilter filter, boolean not) {
String rv =
"( = " + filter.getAttribute().getName() + " "
+ filter.getAttribute().getValue() + " )";
return not(rv, not);
}
@Override
protected String createGreaterThanExpression(GreaterThanFilter filter, boolean not) {
String rv = "( > " + filter.getName() + " " + filter.getValue() + " )";
return not(rv, not);
}
@Override
protected String createGreaterThanOrEqualExpression(GreaterThanOrEqualFilter filter,
boolean not) {
String rv = "( >= " + filter.getName() + " " + filter.getValue() + " )";
return not(rv, not);
}
@Override
protected String createLessThanExpression(LessThanFilter filter, boolean not) {
String rv = "( < " + filter.getName() + " " + filter.getValue() + " )";
return not(rv, not);
}
@Override
protected String createLessThanOrEqualExpression(LessThanOrEqualFilter filter, boolean not) {
String rv = "( <= " + filter.getName() + " " + filter.getValue() + " )";
return not(rv, not);
}
@Override
protected String createStartsWithExpression(StartsWithFilter filter, boolean not) {
String rv = "( STARTS-WITH " + filter.getName() + " " + filter.getValue() + " )";
return not(rv, not);
}
@Override
protected String createContainsAllValuesExpression(ContainsAllValuesFilter filter,
boolean not) {
String rv = "( CONTAINS-ALL-VALUES " + filter.getAttribute() + " )";
return not(rv, not);
}
private String not(String orig, boolean not) {
if (not) {
return "( ! " + orig + " )";
} else {
return orig;
}
}
}
/**
* Everything but Or
*/
private static class NoOrTranslator extends AllFiltersTranslator {
@Override
protected String createOrExpression(String leftExpression, String rightExpression) {
return null;
}
}
/**
* Everything but EndsWith
*/
private static class NoEndsWithTranslator extends AllFiltersTranslator {
@Override
protected String createEndsWithExpression(EndsWithFilter filter, boolean not) {
return null;
}
}
/**
* Everything but EndsWith,Or
*/
private static class NoEndsWithNoOrTranslator extends AllFiltersTranslator {
@Override
protected String createOrExpression(String leftExpression, String rightExpression) {
return null;
}
@Override
protected String createEndsWithExpression(EndsWithFilter filter, boolean not) {
return null;
}
}
/**
* Everything but And
*/
private static class NoAndTranslator extends AllFiltersTranslator {
@Override
protected String createAndExpression(String leftExpression, String rightExpression) {
return null;
}
}
/**
* Everything but And
*/
private static class NoAndNoEndsWithTranslator extends AllFiltersTranslator {
@Override
protected String createAndExpression(String leftExpression, String rightExpression) {
return null;
}
@Override
protected String createEndsWithExpression(EndsWithFilter filter, boolean not) {
return null;
}
}
/**
* Everything but And
*/
private static class NoAndNoOrNoEndsWithTranslator extends AllFiltersTranslator {
@Override
protected String createAndExpression(String leftExpression, String rightExpression) {
return null;
}
@Override
protected String createEndsWithExpression(EndsWithFilter filter, boolean not) {
return null;
}
@Override
protected String createOrExpression(String leftExpression, String rightExpression) {
return null;
}
}
/**
* Test all operations when everything is fully implemented. Test not
* normalization as well.
*/
@Test
public void testBasics() {
Attribute attribute = AttributeBuilder.build("att-name", "att-value");
Attribute attribute2 = AttributeBuilder.build("att-name2", "att-value2");
AllFiltersTranslator translator = new AllFiltersTranslator();
{
Filter filter = FilterBuilder.contains(attribute);
String expected = "( CONTAINS att-name att-value )";
String actual = translateSingle(translator, filter);
assertEquals(actual, expected);
filter = FilterBuilder.not(filter);
expected = "( ! " + expected + " )";
actual = translateSingle(translator, filter);
assertEquals(actual, expected);
}
{
Filter filter = FilterBuilder.endsWith(attribute);
String expected = "( ENDS-WITH att-name att-value )";
String actual = translateSingle(translator, filter);
assertEquals(actual, expected);
filter = FilterBuilder.not(filter);
expected = "( ! " + expected + " )";
actual = translateSingle(translator, filter);
assertEquals(actual, expected);
}
{
Filter filter = FilterBuilder.equalTo(attribute);
String expected = "( = att-name [att-value] )";
String actual = translateSingle(translator, filter);
assertEquals(actual, expected);
filter = FilterBuilder.not(filter);
expected = "( ! " + expected + " )";
actual = translateSingle(translator, filter);
assertEquals(actual, expected);
}
{
Filter filter = FilterBuilder.greaterThan(attribute);
String expected = "( > att-name att-value )";
String actual = translateSingle(translator, filter);
assertEquals(actual, expected);
filter = FilterBuilder.not(filter);
expected = "( ! " + expected + " )";
actual = translateSingle(translator, filter);
assertEquals(actual, expected);
}
{
Filter filter = FilterBuilder.greaterThanOrEqualTo(attribute);
String expected = "( >= att-name att-value )";
String actual = translateSingle(translator, filter);
assertEquals(actual, expected);
filter = FilterBuilder.not(filter);
expected = "( ! " + expected + " )";
actual = translateSingle(translator, filter);
assertEquals(actual, expected);
}
{
Filter filter = FilterBuilder.lessThan(attribute);
String expected = "( < att-name att-value )";
String actual = translateSingle(translator, filter);
assertEquals(actual, expected);
filter = FilterBuilder.not(filter);
expected = "( ! " + expected + " )";
actual = translateSingle(translator, filter);
assertEquals(actual, expected);
}
{
Filter filter = FilterBuilder.lessThanOrEqualTo(attribute);
String expected = "( <= att-name att-value )";
String actual = translateSingle(translator, filter);
assertEquals(actual, expected);
filter = FilterBuilder.not(filter);
expected = "( ! " + expected + " )";
actual = translateSingle(translator, filter);
assertEquals(actual, expected);
}
{
Filter filter = FilterBuilder.startsWith(attribute);
String expected = "( STARTS-WITH att-name att-value )";
String actual = translateSingle(translator, filter);
assertEquals(actual, expected);
filter = FilterBuilder.not(filter);
expected = "( ! " + expected + " )";
actual = translateSingle(translator, filter);
assertEquals(actual, expected);
}
{
Filter filter = FilterBuilder.containsAllValues(attribute);
String expected = "( CONTAINS-ALL-VALUES " + attribute + " )";
String actual = translateSingle(translator, filter);
assertEquals(actual, expected);
filter = FilterBuilder.not(filter);
expected = "( ! " + expected + " )";
actual = translateSingle(translator, filter);
assertEquals(actual, expected);
}
// and
{
Filter left = FilterBuilder.contains(attribute);
Filter right = FilterBuilder.contains(attribute2);
String expectedLeft = "( CONTAINS att-name att-value )";
String expectedRight = "( CONTAINS att-name2 att-value2 )";
Filter filter = FilterBuilder.and(left, right);
String expected = "( & " + expectedLeft + " " + expectedRight + " )";
String actual = translateSingle(translator, filter);
assertEquals(actual, expected);
filter = FilterBuilder.not(filter);
expectedLeft = "( ! " + expectedLeft + " )";
expectedRight = "( ! " + expectedRight + " )";
expected = "( | " + expectedLeft + " " + expectedRight + " )";
actual = translateSingle(translator, filter);
assertEquals(actual, expected);
}
// or
{
Filter left = FilterBuilder.contains(attribute);
Filter right = FilterBuilder.contains(attribute2);
String expectedLeft = "( CONTAINS att-name att-value )";
String expectedRight = "( CONTAINS att-name2 att-value2 )";
Filter filter = FilterBuilder.or(left, right);
String expected = "( | " + expectedLeft + " " + expectedRight + " )";
String actual = translateSingle(translator, filter);
assertEquals(actual, expected);
filter = FilterBuilder.not(filter);
expectedLeft = "( ! " + expectedLeft + " )";
expectedRight = "( ! " + expectedRight + " )";
expected = "( & " + expectedLeft + " " + expectedRight + " )";
actual = translateSingle(translator, filter);
assertEquals(actual, expected);
}
// double-negative
{
Filter filter = FilterBuilder.contains(attribute);
filter = FilterBuilder.not(filter);
filter = FilterBuilder.not(filter);
String expected = "( CONTAINS att-name att-value )";
String actual = translateSingle(translator, filter);
assertEquals(actual, expected);
}
}
/**
* (a OR b) AND ( c OR d) needs to become (a AND c) OR ( a AND d) OR (b AND
* c) OR (b AND d) is OR is not implemented. Otherwise it should stay as-is.
*/
@Test
public void testDistribution() {
Filter a = FilterBuilder.contains(AttributeBuilder.build("a", "a"));
Filter b = FilterBuilder.contains(AttributeBuilder.build("b", "b"));
Filter c = FilterBuilder.contains(AttributeBuilder.build("c", "c"));
Filter d = FilterBuilder.contains(AttributeBuilder.build("d", "d"));
Filter filter = FilterBuilder.and(FilterBuilder.or(a, b), FilterBuilder.or(c, d));
String expected =
"( & ( | ( CONTAINS a a ) ( CONTAINS b b ) ) ( | ( CONTAINS c c ) ( CONTAINS d d ) ) )";
String actual = translateSingle(new AllFiltersTranslator(), filter);
assertEquals(actual, expected);
List<String> results = new NoOrTranslator().translate(filter);
assertThat(results).hasSize(4).contains("( & ( CONTAINS a a ) ( CONTAINS c c ) )",
atIndex(0)).contains("( & ( CONTAINS a a ) ( CONTAINS d d ) )", atIndex(1))
.contains("( & ( CONTAINS b b ) ( CONTAINS c c ) )", atIndex(2)).contains(
"( & ( CONTAINS b b ) ( CONTAINS d d ) )", atIndex(3));
}
// test simplification
// -no leaf
@Test
public void testSimplifyNoLeaf() {
Filter a = FilterBuilder.contains(AttributeBuilder.build("a", "a"));
Filter b = FilterBuilder.contains(AttributeBuilder.build("b", "b"));
Filter c = FilterBuilder.endsWith(AttributeBuilder.build("c", "c"));
Filter d = FilterBuilder.contains(AttributeBuilder.build("d", "d"));
Filter filter = FilterBuilder.and(FilterBuilder.or(a, b), FilterBuilder.or(c, d));
String expected = "( | ( CONTAINS a a ) ( CONTAINS b b ) )";
String actual = translateSingle(new NoEndsWithTranslator(), filter);
assertEquals(actual, expected);
}
// -no leaf + no or
@Test
public void testSimplifyNoLeafNoOr() {
Filter a = FilterBuilder.contains(AttributeBuilder.build("a", "a"));
Filter b = FilterBuilder.contains(AttributeBuilder.build("b", "b"));
Filter c = FilterBuilder.endsWith(AttributeBuilder.build("c", "c"));
Filter d = FilterBuilder.contains(AttributeBuilder.build("d", "d"));
Filter filter = FilterBuilder.and(FilterBuilder.or(a, b), FilterBuilder.or(c, d));
List<String> results = new NoEndsWithNoOrTranslator().translate(filter);
assertThat(results).hasSize(2).contains("( CONTAINS a a )", atIndex(0)).contains(
"( CONTAINS b b )", atIndex(1));
}
// -no and
@Test
public void testSimplifyNoAnd() {
Filter a = FilterBuilder.contains(AttributeBuilder.build("a", "a"));
Filter b = FilterBuilder.contains(AttributeBuilder.build("b", "b"));
Filter c = FilterBuilder.endsWith(AttributeBuilder.build("c", "c"));
Filter d = FilterBuilder.contains(AttributeBuilder.build("d", "d"));
Filter filter = FilterBuilder.and(FilterBuilder.or(a, b), FilterBuilder.or(c, d));
String expected = "( | ( CONTAINS a a ) ( CONTAINS b b ) )";
String actual = translateSingle(new NoAndTranslator(), filter);
assertEquals(actual, expected);
}
// -no and+no leaf
@Test
public void testSimplifyNoAndNoLeaf() {
Filter a = FilterBuilder.contains(AttributeBuilder.build("a", "a"));
Filter b = FilterBuilder.contains(AttributeBuilder.build("b", "b"));
Filter c = FilterBuilder.endsWith(AttributeBuilder.build("c", "c"));
Filter d = FilterBuilder.contains(AttributeBuilder.build("d", "d"));
Filter filter = FilterBuilder.and(FilterBuilder.or(a, b), FilterBuilder.or(c, d));
String expected = "( | ( CONTAINS a a ) ( CONTAINS b b ) )";
String actual = translateSingle(new NoAndNoEndsWithTranslator(), filter);
assertEquals(actual, expected);
a = FilterBuilder.contains(AttributeBuilder.build("a", "a"));
b = FilterBuilder.endsWith(AttributeBuilder.build("b", "b"));
c = FilterBuilder.contains(AttributeBuilder.build("c", "c"));
d = FilterBuilder.contains(AttributeBuilder.build("d", "d"));
filter = FilterBuilder.and(FilterBuilder.or(a, b), FilterBuilder.or(c, d));
expected = "( | ( CONTAINS c c ) ( CONTAINS d d ) )";
actual = translateSingle(new NoAndNoEndsWithTranslator(), filter);
assertEquals(actual, expected);
a = FilterBuilder.contains(AttributeBuilder.build("a", "a"));
b = FilterBuilder.endsWith(AttributeBuilder.build("b", "b"));
c = FilterBuilder.contains(AttributeBuilder.build("c", "c"));
d = FilterBuilder.endsWith(AttributeBuilder.build("d", "d"));
filter = FilterBuilder.and(FilterBuilder.or(a, b), FilterBuilder.or(c, d));
List<String> results = new NoAndNoEndsWithTranslator().translate(filter);
assertThat(results).hasSize(0);
}
// -no and, no or, no leaf
@Test
public void testSimplifyNoAndNoOrNoLeaf() {
Filter a = FilterBuilder.contains(AttributeBuilder.build("a", "a"));
Filter b = FilterBuilder.contains(AttributeBuilder.build("b", "b"));
Filter c = FilterBuilder.endsWith(AttributeBuilder.build("c", "c"));
Filter d = FilterBuilder.contains(AttributeBuilder.build("d", "d"));
Filter filter = FilterBuilder.and(FilterBuilder.or(a, b), FilterBuilder.or(c, d));
List<String> results = new NoAndNoOrNoEndsWithTranslator().translate(filter);
assertThat(results).hasSize(2).contains("( CONTAINS a a )", atIndex(0)).contains(
"( CONTAINS b b )", atIndex(1));
a = FilterBuilder.contains(AttributeBuilder.build("a", "a"));
b = FilterBuilder.endsWith(AttributeBuilder.build("b", "b"));
c = FilterBuilder.contains(AttributeBuilder.build("c", "c"));
d = FilterBuilder.contains(AttributeBuilder.build("d", "d"));
filter = FilterBuilder.and(FilterBuilder.or(a, b), FilterBuilder.or(c, d));
results = new NoAndNoOrNoEndsWithTranslator().translate(filter);
assertThat(results).hasSize(2).contains("( CONTAINS c c )", atIndex(0)).contains(
"( CONTAINS d d )", atIndex(1));
}
private static String translateSingle(AbstractFilterTranslator<String> translator, Filter filter) {
List<String> translated = translator.translate(filter);
assertEquals(translated.size(), 1);
return translated.get(0);
}
}