/*
* Copyright (c) 2010-2015 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.evolveum.midpoint.model.impl.expr;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertTrue;
import static com.evolveum.midpoint.test.IntegrationTestTools.display;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.xml.namespace.QName;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.testng.AssertJUnit;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.Test;
import org.xml.sax.SAXException;
import com.evolveum.midpoint.model.common.expression.ExpressionFactory;
import com.evolveum.midpoint.model.common.expression.ExpressionUtil;
import com.evolveum.midpoint.model.common.expression.ExpressionVariables;
import com.evolveum.midpoint.model.impl.AbstractInternalModelIntegrationTest;
import com.evolveum.midpoint.prism.PrismContext;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.PrismPropertyValue;
import com.evolveum.midpoint.prism.query.AllFilter;
import com.evolveum.midpoint.prism.query.EqualFilter;
import com.evolveum.midpoint.prism.query.NoneFilter;
import com.evolveum.midpoint.prism.query.ObjectFilter;
import com.evolveum.midpoint.prism.query.ObjectQuery;
import com.evolveum.midpoint.prism.query.QueryJaxbConvertor;
import com.evolveum.midpoint.prism.query.RefFilter;
import com.evolveum.midpoint.prism.query.UndefinedFilter;
import com.evolveum.midpoint.prism.util.PrismAsserts;
import com.evolveum.midpoint.prism.util.PrismTestUtil;
import com.evolveum.midpoint.schema.MidPointPrismContextFactory;
import com.evolveum.midpoint.schema.SearchResultList;
import com.evolveum.midpoint.schema.constants.ExpressionConstants;
import com.evolveum.midpoint.schema.constants.MidPointConstants;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.task.api.TaskManager;
import com.evolveum.midpoint.test.util.TestUtil;
import com.evolveum.midpoint.util.PrettyPrinter;
import com.evolveum.midpoint.util.exception.CommunicationException;
import com.evolveum.midpoint.util.exception.ConfigurationException;
import com.evolveum.midpoint.util.exception.ExpressionEvaluationException;
import com.evolveum.midpoint.util.exception.ObjectNotFoundException;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.util.exception.SecurityViolationException;
import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType;
import com.evolveum.prism.xml.ns._public.query_3.SearchFilterType;
@ContextConfiguration(locations = { "classpath:ctx-model-test-main.xml" })
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
public class TestFilterExpression extends AbstractInternalModelIntegrationTest {
private static final String TEST_DIR = "src/test/resources/expr";
@Autowired(required = true)
private ExpressionFactory expressionFactory;
@Autowired(required = true)
private TaskManager taskManager;
@BeforeSuite
public void setup() throws SchemaException, SAXException, IOException {
PrettyPrinter.setDefaultNamespacePrefix(MidPointConstants.NS_MIDPOINT_PUBLIC_PREFIX);
PrismTestUtil.resetPrismContext(MidPointPrismContextFactory.FACTORY);
}
@Test
public void test100EvaluateExpressionEmployeeTypeUndefinedFilter() throws Exception {
final String TEST_NAME = "testEvaluateExpressionEmployeeTypeUndefinedFilter";
TestUtil.displayTestTile(TEST_NAME);
// GIVEN
OperationResult result = new OperationResult(TestFilterExpression.class.getName() + "." + TEST_NAME);
Task task = taskManager.createTaskInstance(TEST_NAME);
ObjectFilter filter = evaluateExpressionAssertFilter("expression-employeeType-undefined-filter.xml",
null, UndefinedFilter.class, task, result);
executeFilter(filter, 5, task, result);
}
@Test
public void test110EvaluateExpressionEmployeeTypeNoneFilter() throws Exception {
final String TEST_NAME = "testEvaluateExpressionEmployeeTypeNoneFilter";
TestUtil.displayTestTile(TEST_NAME);
// GIVEN
OperationResult result = new OperationResult(TestFilterExpression.class.getName() + "." + TEST_NAME);
Task task = taskManager.createTaskInstance(TEST_NAME);
ObjectFilter filter = evaluateExpressionAssertFilter("expression-employeeType-none-filter.xml",
null, NoneFilter.class, task, result);
executeFilter(filter, 0, task, result);
}
@Test
public void test120EvaluateExpressionEmployeeTypeAllFilter() throws Exception {
final String TEST_NAME = "testEvaluateExpressionEmployeeTypeAllFilter";
TestUtil.displayTestTile(TEST_NAME);
// GIVEN
OperationResult result = new OperationResult(TestFilterExpression.class.getName() + "." + TEST_NAME);
Task task = taskManager.createTaskInstance(TEST_NAME);
ObjectFilter filter = evaluateExpressionAssertFilter("expression-employeeType-all-filter.xml",
null, AllFilter.class, task, result);
executeFilter(filter, 5, task, result);
}
@Test
public void test130EvaluateExpressionEmployeeTypeError() throws Exception {
final String TEST_NAME = "testEvaluateExpressionEmployeeTypeError";
TestUtil.displayTestTile(TEST_NAME);
// GIVEN
OperationResult result = new OperationResult(TestFilterExpression.class.getName() + "." + TEST_NAME);
Task task = taskManager.createTaskInstance(TEST_NAME);
try {
evaluateExpressionAssertFilter("expression-employeeType-error.xml",
null, NoneFilter.class, task, result);
AssertJUnit.fail("Unexpected success");
} catch (ExpressionEvaluationException e) {
// this is expected
assertTrue("Unexpected exception message: "+e.getMessage(), e.getMessage().contains("evaluated to no value"));
}
}
@Test
public void test140EvaluateExpressionEmployeeTypeEmptyFilter() throws Exception {
final String TEST_NAME = "testEvaluateExpressionEmployeeTypeEmptyFilter";
TestUtil.displayTestTile(TEST_NAME);
// GIVEN
OperationResult result = new OperationResult(TestFilterExpression.class.getName() + "." + TEST_NAME);
Task task = taskManager.createTaskInstance(TEST_NAME);
ObjectFilter filter = evaluateExpressionAssertFilter("expression-employeeType-empty-filter.xml",
null, EqualFilter.class, task, result);
EqualFilter equalFilter = (EqualFilter) filter;
AssertJUnit.assertNull("Expected NO values in filter, but found " + equalFilter.getValues(), equalFilter.getValues());
executeFilter(filter, 4, task, result);
}
@Test
public void test150EvaluateExpressionEmployeeTypeDefaultsNull() throws Exception {
final String TEST_NAME = "test150EvaluateExpressionEmployeeTypeDefaultsNull";
TestUtil.displayTestTile(TEST_NAME);
// GIVEN
OperationResult result = new OperationResult(TestFilterExpression.class.getName() + "." + TEST_NAME);
Task task = taskManager.createTaskInstance(TEST_NAME);
ObjectFilter filter = evaluateExpressionAssertFilter("expression-employeeType-filter-defaults.xml",
null, EqualFilter.class, task, result);
EqualFilter equalFilter = (EqualFilter) filter;
AssertJUnit.assertNull("Expected NO values in filter, but found " + equalFilter.getValues(), equalFilter.getValues());
executeFilter(filter, 4, task, result);
}
@Test
public void test152EvaluateExpressionEmployeeTypeDefaultsCaptain() throws Exception {
final String TEST_NAME = "test152EvaluateExpressionEmployeeTypeDefaultsCaptain";
TestUtil.displayTestTile(TEST_NAME);
// GIVEN
OperationResult result = new OperationResult(TestFilterExpression.class.getName() + "." + TEST_NAME);
Task task = taskManager.createTaskInstance(TEST_NAME);
ObjectFilter filter = evaluateExpressionAssertFilter("expression-employeeType-filter-defaults.xml",
"CAPTAIN", EqualFilter.class, task, result);
EqualFilter equalFilter = (EqualFilter) filter;
PrismAsserts.assertValues("Wrong values in filter", equalFilter.getValues(), "CAPTAIN");
executeFilter(filter, 1, task, result);
}
@Test
public void test200EvaluateExpressionLinkRefDefaultsNull() throws Exception {
final String TEST_NAME = "test200EvaluateExpressionLinkRefDefaultsNull";
TestUtil.displayTestTile(TEST_NAME);
// GIVEN
OperationResult result = new OperationResult(TestFilterExpression.class.getName() + "." + TEST_NAME);
Task task = taskManager.createTaskInstance(TEST_NAME);
ObjectFilter filter = evaluateExpressionAssertFilter("expression-linkref-filter-defaults.xml",
null, RefFilter.class, task, result);
RefFilter refFilter = (RefFilter) filter;
AssertJUnit.assertNull("Expected NO values in filter, but found " + refFilter.getValues(), refFilter.getValues());
executeFilter(filter, 2, task, result);
}
@Test
public void test202EvaluateExpressionLinkRefObjectReferenceTypeDefaultsNull() throws Exception {
final String TEST_NAME = "test202EvaluateExpressionLinkRefObjectReferenceTypeDefaultsNull";
TestUtil.displayTestTile(TEST_NAME);
// GIVEN
OperationResult result = new OperationResult(TestFilterExpression.class.getName() + "." + TEST_NAME);
Task task = taskManager.createTaskInstance(TEST_NAME);
ObjectFilter filter = evaluateExpressionAssertFilter("expression-linkref-object-reference-type-filter-defaults.xml",
null, RefFilter.class, task, result);
RefFilter refFilter = (RefFilter) filter;
AssertJUnit.assertNull("Expected NO values in filter, but found " + refFilter.getValues(), refFilter.getValues());
executeFilter(filter, 2, task, result);
}
@Test
public void test210EvaluateExpressionLinkRefDefaultsVal() throws Exception {
final String TEST_NAME = "test210EvaluateExpressionLinkRefDefaultsVal";
TestUtil.displayTestTile(TEST_NAME);
// GIVEN
OperationResult result = new OperationResult(TestFilterExpression.class.getName() + "." + TEST_NAME);
Task task = taskManager.createTaskInstance(TEST_NAME);
ObjectFilter filter = evaluateExpressionAssertFilter("expression-linkref-filter-defaults.xml",
ACCOUNT_SHADOW_GUYBRUSH_OID, RefFilter.class, task, result);
RefFilter refFilter = (RefFilter) filter;
assertEquals("Wrong number of values in filter: " + refFilter.getValues(), 1, refFilter.getValues().size());
executeFilter(filter, 1, task, result);
}
@Test
public void test212EvaluateExpressionLinkRefObjectReferenceTypeDefaultsVal() throws Exception {
final String TEST_NAME = "test212EvaluateExpressionLinkRefObjectReferenceTypeDefaultsVal";
TestUtil.displayTestTile(TEST_NAME);
// GIVEN
OperationResult result = new OperationResult(TestFilterExpression.class.getName() + "." + TEST_NAME);
Task task = taskManager.createTaskInstance(TEST_NAME);
ObjectFilter filter = evaluateExpressionAssertFilter("expression-linkref-object-reference-type-filter-defaults.xml",
ACCOUNT_SHADOW_GUYBRUSH_OID, RefFilter.class, task, result);
RefFilter refFilter = (RefFilter) filter;
assertEquals("Wrong number of values in filter: " + refFilter.getValues(), 1, refFilter.getValues().size());
executeFilter(filter, 1, task, result);
}
private ObjectFilter evaluateExpressionAssertFilter(String filename,
String input, Class<? extends ObjectFilter> expectedType,
Task task, OperationResult result) throws SchemaException, IOException, ObjectNotFoundException, ExpressionEvaluationException {
PrismContext prismContext = PrismTestUtil.getPrismContext();
SearchFilterType filterType = PrismTestUtil.parseAtomicValue(new File(TEST_DIR, filename), SearchFilterType.COMPLEX_TYPE);
ObjectFilter filter = QueryJaxbConvertor.createObjectFilter(UserType.class, filterType, prismContext);
Map<QName, Object> params = new HashMap<>();
PrismPropertyValue<String> pval = null;
if (input != null) {
pval = new PrismPropertyValue<String>(input);
}
params.put(ExpressionConstants.VAR_INPUT, pval);
ExpressionVariables variables = new ExpressionVariables();
variables.addVariableDefinitions(params);
// WHEN
ObjectFilter evaluatedFilter = ExpressionUtil.evaluateFilterExpressions(filter, variables, expressionFactory, prismContext,
"evaluating filter with null value not allowed", task, result);
// THEN
display("Evaluated filter", evaluatedFilter);
AssertJUnit.assertTrue("Expression should be evaluated to "+expectedType+", but was "+evaluatedFilter, expectedType.isAssignableFrom(evaluatedFilter.getClass()));
return evaluatedFilter;
}
private void executeFilter(ObjectFilter filter, int expectedNumberOfResults, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, SecurityViolationException, CommunicationException, ConfigurationException {
ObjectQuery query = ObjectQuery.createObjectQuery(filter);
SearchResultList<PrismObject<UserType>> objects = modelService.searchObjects(UserType.class, query, null, task, result);
display("Found objects", objects);
assertEquals("Wrong number of results (found: "+objects+")", expectedNumberOfResults, objects.size());
}
}