/******************************************************************************* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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 org.apache.ofbiz.service.eca; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.ofbiz.base.util.Debug; import org.apache.ofbiz.base.util.UtilMisc; import org.apache.ofbiz.base.util.UtilValidate; import org.apache.ofbiz.base.util.UtilXml; import org.apache.ofbiz.service.DispatchContext; import org.apache.ofbiz.service.GenericServiceException; import org.w3c.dom.Element; /** * ServiceEcaRule */ @SuppressWarnings("serial") public final class ServiceEcaRule implements java.io.Serializable { public static final String module = ServiceEcaRule.class.getName(); protected final String serviceName; protected final String eventName; protected final boolean runOnFailure; protected final boolean runOnError; protected final List<ServiceEcaCondition> conditions = new ArrayList<ServiceEcaCondition>(); protected final List<Object> actionsAndSets = new ArrayList<Object>(); protected boolean enabled = true; protected final String definitionLocation; public ServiceEcaRule(Element eca, String definitionLocation) { this.definitionLocation = definitionLocation; this.serviceName = eca.getAttribute("service"); this.eventName = eca.getAttribute("event"); this.runOnFailure = "true".equals(eca.getAttribute("run-on-failure")); this.runOnError = "true".equals(eca.getAttribute("run-on-error")); for (Element element: UtilXml.childElementList(eca, "condition")) { conditions.add(new ServiceEcaCondition(element, true, false)); } for (Element element: UtilXml.childElementList(eca, "condition-field")) { conditions.add(new ServiceEcaCondition(element, false, false)); } for (Element element: UtilXml.childElementList(eca, "condition-service")) { conditions.add(new ServiceEcaCondition(element, false, true)); } if (Debug.verboseOn()) { Debug.logVerbose("Conditions: " + conditions, module); } Set<String> nameSet = UtilMisc.toSet("set", "action"); for (Element actionOrSetElement: UtilXml.childElementList(eca, nameSet)) { if ("action".equals(actionOrSetElement.getNodeName())) { this.actionsAndSets.add(new ServiceEcaAction(actionOrSetElement, this.eventName)); } else { this.actionsAndSets.add(new ServiceEcaSetField(actionOrSetElement)); } } if (Debug.verboseOn()) { Debug.logVerbose("actions and sets (intermixed): " + actionsAndSets, module); } } public String getShortDisplayName() { return this.serviceName + ":" + this.eventName; } public String getServiceName() { return this.serviceName; } public String getEventName() { return this.eventName; } public String getDefinitionLocation() { return this.definitionLocation; } public List<ServiceEcaAction> getEcaActionList() { List<ServiceEcaAction> actionList = new LinkedList<ServiceEcaAction>(); for (Object actionOrSet: this.actionsAndSets) { if (actionOrSet instanceof ServiceEcaAction) { actionList.add((ServiceEcaAction) actionOrSet); } } return actionList; } public List<ServiceEcaCondition> getEcaConditionList() { List<ServiceEcaCondition> condList = new LinkedList<ServiceEcaCondition>(); condList.addAll(this.conditions); return condList; } public void eval(String serviceName, DispatchContext dctx, Map<String, Object> context, Map<String, Object> result, boolean isError, boolean isFailure, Set<String> actionsRun) throws GenericServiceException { if (!enabled) { Debug.logInfo("Service ECA [" + this.serviceName + "] on [" + this.eventName + "] is disabled; not running.", module); return; } if (isFailure && !this.runOnFailure) { return; } if (isError && !this.runOnError) { return; } boolean allCondTrue = true; for (ServiceEcaCondition ec: conditions) { if (!ec.eval(serviceName, dctx, context)) { if (Debug.infoOn()) { Debug.logInfo("For Service ECA [" + this.serviceName + "] on [" + this.eventName + "] got false for condition: " + ec, module); } allCondTrue = false; break; } else { if (Debug.verboseOn()) { Debug.logVerbose("For Service ECA [" + this.serviceName + "] on [" + this.eventName + "] got true for condition: " + ec, module); } } } // if all conditions are true if (allCondTrue) { for (Object setOrAction: actionsAndSets) { if (setOrAction instanceof ServiceEcaAction) { ServiceEcaAction ea = (ServiceEcaAction) setOrAction; // in order to enable OR logic without multiple calls to the given service, // only execute a given service name once per service call phase if (!actionsRun.contains(ea.serviceName)) { if (Debug.infoOn()) { Debug.logInfo("Running Service ECA Service: " + ea.serviceName + ", triggered by rule on Service: " + serviceName, module); } if (ea.runAction(serviceName, dctx, context, result)) { actionsRun.add(ea.serviceName); } } } else { ServiceEcaSetField sf = (ServiceEcaSetField) setOrAction; sf.eval(context); } } } } public void setEnabled(boolean enabled) { this.enabled = enabled; } public boolean isEnabled() { return this.enabled; } @Override public boolean equals(Object obj) { if (obj instanceof ServiceEcaRule) { ServiceEcaRule other = (ServiceEcaRule) obj; if (!UtilValidate.areEqual(this.serviceName, other.serviceName)) { return false; } if (!UtilValidate.areEqual(this.eventName, other.eventName)) { return false; } if (!this.conditions.equals(other.conditions)) { return false; } if (!this.actionsAndSets.equals(other.actionsAndSets)) { return false; } if (this.runOnFailure != other.runOnFailure) { return false; } if (this.runOnError != other.runOnError) { return false; } if (this.enabled != other.enabled) { return false; } return true; } else { return false; } } @Override public String toString() { return "ServiceEcaRule:" + this.serviceName + ":" + this.eventName + ":runOnError=" + this.runOnError + ":runOnFailure=" + this.runOnFailure + ":enabled=" + this.enabled + ":conditions=" + this.conditions + ":actionsAndSets=" + this.actionsAndSets; } }