/**
* Copyright (c) 1997, 2015 by ProSyst Software GmbH and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.smarthome.automation.core.internal.composite;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import org.eclipse.smarthome.automation.Trigger;
import org.eclipse.smarthome.automation.core.internal.ReferenceResolverUtil;
import org.eclipse.smarthome.automation.handler.RuleEngineCallback;
import org.eclipse.smarthome.automation.handler.TriggerHandler;
import org.eclipse.smarthome.automation.type.CompositeTriggerType;
import org.eclipse.smarthome.automation.type.Output;
/**
* This class is a handler implementation for {@link CompositeTriggerType}. The trigger which has
* {@link CompositeTriggerType} has to be notified by the handlers of child triggers and it will be triggered when some
* of them is triggered. The handler has to put outputs of the trigger, base on the outputs of the child triggers, into
* rule context. The outputs of the child triggers are not visible out of context of the trigger.
*
* @author Yordan Mihaylov - Initial Contribution
*
*/
public class CompositeTriggerHandler
extends AbstractCompositeModuleHandler<Trigger, CompositeTriggerType, TriggerHandler>
implements TriggerHandler, RuleEngineCallback {
private RuleEngineCallback ruleCallback;
/**
* Constructor of this system handler.
*
* @param trigger trigger of composite type (parent trigger).
* @param mt module type of parent trigger
* @param mapModuleToHandler map of pairs child triggers to their handlers
* @param ruleUID UID of rule where the parent trigger is part of
*/
public CompositeTriggerHandler(Trigger trigger, CompositeTriggerType mt,
LinkedHashMap<Trigger, TriggerHandler> mapModuleToHandler, String ruleUID) {
super(trigger, mt, mapModuleToHandler);
}
/**
* This method is called by the child triggers defined by the {@link CompositeTriggerType} of parent trigger.
* The method goes through the outputs of the parent trigger and fill them base on the ouput's reference value.
* The ouput's reference value can contain more then one references to the child outputs separated by comma. In this
* case the method will try to fill the output value in sequence defined in the reference value. The letter
* reference can be overwritten by the previous ones.
*
* @see org.eclipse.smarthome.automation.handler.RuleEngineCallback#triggered(org.eclipse.smarthome.automation.Trigger,
* java.util.Map)
*/
@Override
public void triggered(Trigger trigger, Map<String, ?> context) {
if (ruleCallback != null) {
List<Output> outputs = moduleType.getOutputs();
Map<String, Object> result = new HashMap<String, Object>(11);
for (Output output : outputs) {
String refs = output.getReference();
if (refs != null) {
String ref;
StringTokenizer st = new StringTokenizer(refs, ",");
while (st.hasMoreTokens()) {
ref = st.nextToken().trim();
int i = ref.indexOf('.');
if (i != -1) {
String childModuleId = ref.substring(0, i);
if (trigger.getId().equals(childModuleId)) {
ref = ref.substring(i + 1);
}
}
Object value = null;
int idx = ReferenceResolverUtil.getNextRefToken(ref, 1);
if (idx < ref.length()) {
String outputId = ref.substring(0, idx);
value = ReferenceResolverUtil.getValue(context.get(outputId), ref.substring(idx + 1));
} else {
value = context.get(ref);
}
if (value != null) {
result.put(output.getName(), value);
}
}
}
}
ruleCallback.triggered(module, result);
}
}
/**
* The {@link CompositeTriggerHandler} sets itself as callback to the child triggers and store the callback to the
* rule engine. In this way the trigger of composite type will be notified always when some of the child triggers
* are triggered and has an opportunity to set the outputs of parent trigger to the rule context.
*
* @see org.eclipse.smarthome.automation.handler.TriggerHandler#setRuleEngineCallback(org.eclipse.smarthome.automation.handler.RuleEngineCallback)
*/
@Override
public void setRuleEngineCallback(RuleEngineCallback ruleCallback) {
this.ruleCallback = ruleCallback;
if (ruleCallback != null) {// could be called with 'null' from dispose
List<Trigger> children = getChildren();
for (Trigger child : children) {
TriggerHandler handler = moduleHandlerMap.get(child);
handler.setRuleEngineCallback(this);
}
}
}
@Override
public void dispose() {
setRuleEngineCallback(null);
super.dispose();
}
@Override
protected List<Trigger> getChildren() {
return moduleType.getChildren();
}
}