/* * Copyright (c) 2010-2014 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.scripting.expressions; import com.evolveum.midpoint.model.api.ScriptExecutionException; import com.evolveum.midpoint.model.impl.scripting.Data; import com.evolveum.midpoint.model.impl.scripting.ExecutionContext; import com.evolveum.midpoint.model.impl.scripting.helpers.ExpressionHelper; import com.evolveum.midpoint.model.impl.scripting.helpers.OperationsHelper; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.marshaller.QueryConvertor; 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.schema.ResultHandler; import com.evolveum.midpoint.schema.constants.ObjectTypes; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.util.exception.*; import com.evolveum.midpoint.util.logging.LoggingUtils; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ScriptingExpressionType; import com.evolveum.midpoint.xml.ns._public.model.scripting_3.SearchExpressionType; import org.apache.commons.lang.Validate; import org.apache.commons.lang.mutable.MutableBoolean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.xml.bind.JAXBElement; /** * @author mederly */ @Component public class SearchEvaluator extends BaseExpressionEvaluator { private static final Trace LOGGER = TraceManager.getTrace(SearchEvaluator.class); @Autowired private ExpressionHelper expressionHelper; @Autowired private OperationsHelper operationsHelper; private static final String PARAM_NO_FETCH = "noFetch"; public <T extends ObjectType> Data evaluate(final SearchExpressionType searchExpression, Data input, final ExecutionContext context, final OperationResult result) throws ScriptExecutionException { Validate.notNull(searchExpression.getType()); boolean noFetch = expressionHelper.getArgumentAsBoolean(searchExpression.getParameter(), PARAM_NO_FETCH, input, context, false, "search", result); Class<T> objectClass = (Class) ObjectTypes.getObjectTypeFromTypeQName(searchExpression.getType()).getClassDefinition(); ObjectQuery objectQuery = null; if (searchExpression.getQuery() != null) { try { objectQuery = QueryJaxbConvertor.createObjectQuery(objectClass, searchExpression.getQuery(), prismContext); } catch (SchemaException e) { throw new ScriptExecutionException("Couldn't parse object query due to schema exception", e); } } else if (searchExpression.getSearchFilter() != null) { // todo resolve variable references in the filter objectQuery = new ObjectQuery(); try { ObjectFilter filter = QueryConvertor.parseFilter(searchExpression.getSearchFilter(), objectClass, prismContext); objectQuery.setFilter(filter); } catch (SchemaException e) { throw new ScriptExecutionException("Couldn't parse object filter due to schema exception", e); } } final String variableName = searchExpression.getVariable(); Data oldVariableValue = null; if (variableName != null) { oldVariableValue = context.getVariable(variableName); } final Data outputData = Data.createEmpty(); final MutableBoolean atLeastOne = new MutableBoolean(false); ResultHandler<T> handler = new ResultHandler<T>() { @Override public boolean handle(PrismObject<T> object, OperationResult parentResult) { context.checkTaskStop(); atLeastOne.setValue(true); if (searchExpression.getScriptingExpression() != null) { if (variableName != null) { context.setVariable(variableName, object); } JAXBElement<?> childExpression = searchExpression.getScriptingExpression(); try { outputData.addAllFrom(scriptingExpressionEvaluator.evaluateExpression((ScriptingExpressionType) childExpression.getValue(), Data.create(object), context, result)); result.setSummarizeSuccesses(true); result.summarize(); } catch (ScriptExecutionException e) { // todo think about this if (context.isContinueOnAnyError()) { LoggingUtils.logUnexpectedException(LOGGER, "Exception when evaluating item from search result list.", e); } else { throw new SystemException(e); } } } else { outputData.addItem(object); } return true; } }; try { modelService.searchObjectsIterative(objectClass, objectQuery, handler, operationsHelper.createGetOptions(noFetch), context.getTask(), result); } catch (SchemaException | ObjectNotFoundException | SecurityViolationException | CommunicationException | ConfigurationException e) { // TODO continue on any error? throw new ScriptExecutionException("Couldn't execute searchObjects operation: " + e.getMessage(), e); } if (atLeastOne.isFalse()) { String matching; if (objectQuery != null) { matching = "matching "; } else { matching = ""; } context.println("Warning: no " + matching + searchExpression.getType().getLocalPart() + " object found"); // temporary hack, this will be configurable } if (variableName != null) { context.setVariable(variableName, oldVariableValue); } return outputData; } }