Merge pull request #317 from marinmitev/automation-component-impl

Initial implementation of the automation component
This commit is contained in:
Kai Kreuzer 2015-12-08 16:52:16 +01:00
Родитель 876d10e6aa 3d2b6e6453
Коммит 2a1c9d7a08
345 изменённых файлов: 24409 добавлений и 3351 удалений

Просмотреть файл

@ -4,20 +4,28 @@ Bundle-Name: Eclipse SmartHome Automation API
Bundle-SymbolicName: org.eclipse.smarthome.automation.api
Bundle-Version: 0.8.0.qualifier
Bundle-Vendor: Eclipse.org/SmartHome
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Import-Package:
com.google.gson.annotations;resolution:=optional,
org.eclipse.smarthome.automation,
org.eclipse.smarthome.automation.handler,
org.eclipse.smarthome.automation.template,
org.eclipse.smarthome.automation.type,
org.eclipse.smarthome.automation.events,
org.eclipse.smarthome.automation.parser,
org.eclipse.smarthome.config.core,
org.eclipse.smarthome.core.common.registry,
org.eclipse.smarthome.core.events,
org.eclipse.smarthome.core.storage,
org.osgi.framework,
org.osgi.service.cm,
org.osgi.service.component,
org.osgi.util.tracker,
org.slf4j
Export-Package: org.eclipse.smarthome.automation,
Export-Package:
org.eclipse.smarthome.automation,
org.eclipse.smarthome.automation.handler,
org.eclipse.smarthome.automation.type,
org.eclipse.smarthome.automation.template
org.eclipse.smarthome.automation.events,
org.eclipse.smarthome.automation.parser,
org.eclipse.smarthome.automation.template,
org.eclipse.smarthome.automation.type
Bundle-RequiredExecutionEnvironment: JavaSE-1.7

Просмотреть файл

Просмотреть файл

@ -0,0 +1,28 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
<title>About</title>
</head>
<body lang="EN-US">
<h2>About This Content</h2>
<p>June 5, 2006</p>
<h3>License</h3>
<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;). Unless otherwise
indicated below, the Content is provided to you under the terms and conditions of the
Eclipse Public License Version 1.0 (&quot;EPL&quot;). A copy of the EPL is available
at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
apply to your use of any object code in the Content. Check the Redistributor's license that was
provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
indicated below, the terms and conditions of the EPL still apply to any source code in the Content
and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
</body>
</html>

Просмотреть файл

@ -1,4 +1,5 @@
output.. = target/classes/
bin.includes = META-INF/,\
.
.,\
about.html
source.. = src/main/java/

Просмотреть файл

@ -1,17 +1,14 @@
/*******************************************************************************
* Copyright (c) 1997, 2015 by ProSyst Software GmbH
* http://www.prosyst.com
/**
* 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
*
* Contributors:
* ProSyst Software GmbH - initial API and implementation
*******************************************************************************/
*/
package org.eclipse.smarthome.automation;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import org.eclipse.smarthome.automation.type.ActionType;
@ -27,24 +24,50 @@ import org.eclipse.smarthome.config.core.ConfigDescriptionParameter;
* {@link Input}s and {@link Output}s) are
* defined by {@link ActionType}
*
* @author Yordan Mihaylov, Ana Dimova, Vasil Ilchev - Initial Contribution
* @author Yordan Mihaylov - Initial Contribution
* @author Ana Dimova - Initial Contribution
* @author Vasil Ilchev - Initial Contribution
*/
public interface Action extends Module {
public class Action extends Module {
private Map<String, String> inputs;
public Action() {
}
/**
* Constructor of Action object.
*
* @param UID action unique id.
* @param typeUID module type unique id.
* @param configuration map of configuration values.
* @param inputs set of connections to other modules (triggers and other actions).
*/
public Action(String UID, String typeUID, Map<String, ?> configuration, Map<String, String> inputs) {
super(UID, typeUID, configuration);
setInputs(inputs);
}
/**
* This method is used to get input connections of the Action. The connections
* are links between {@link Input}s of the {@link Module} and {@link Output}s
* of other {@link Module}s.
*
* @return a {@link Set} of input {@link Connection}s.
* @return a {@link Set} of input {@link Input}s.
*/
public Set<Connection> getConnections();
public Map<String, String> getInputs() {
return inputs != null ? inputs : Collections.<String, String> emptyMap();
}
/**
* This method is used to connect {@link Input}s of the action to {@link Output}s of other {@link Module}s.
*
* @param connections a {@link Set} of input {@link Connection}s.
* @param connections a {@link Set} of input {@link Input}s.
*/
public void setConnections(Set<Connection> connections);
public void setInputs(Map<String, String> inputs) {
if (inputs != null) {
this.inputs = inputs;
}
}
}

Просмотреть файл

@ -1,17 +1,14 @@
/*******************************************************************************
* Copyright (c) 1997, 2015 by ProSyst Software GmbH
* http://www.prosyst.com
/**
* 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
*
* Contributors:
* ProSyst Software GmbH - initial API and implementation
*******************************************************************************/
*/
package org.eclipse.smarthome.automation;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import org.eclipse.smarthome.automation.type.ConditionType;
@ -27,22 +24,47 @@ import org.eclipse.smarthome.config.core.ConfigDescriptionParameter;
*
* @author Yordan Mihaylov - Initial Contribution
*/
public interface Condition extends Module {
public class Condition extends Module {
private Map<String, String> inputs;
public Condition() {
super();
}
/**
* Constructor of {@link Condition} module object.
*
* @param id id of the module.
* @param typeUID unique module type id.
* @param configuration configuration values of the {@link Condition} module.
* @param inputs set of {@link Input}s used by this module.
*/
public Condition(String id, String typeUID, Map<String, ?> configuration, Map<String, String> inputs) {
super(id, typeUID, configuration);
setInputs(inputs);
}
/**
* This method is used to get input connections of the Condition. The
* connections are links between {@link Input}s of the current {@link Module} and {@link Output}s of other
* {@link Module}s.
*
* @return a {@link Set} of input {@link Connection}s.
* @return a {@link Map} of input connections.
*/
public Set<Connection> getConnections();
public Map<String, String> getInputs() {
return inputs != null ? inputs : Collections.<String, String> emptyMap();
}
/**
* This method is used to connect {@link Input}s of the Condition to {@link Output}s of other {@link Module}s.
*
* @param connections a {@link Set} of input {@link Connection}s.
* @param connections a {@link Set} of input {@link Input}s.
*/
public void setConnections(Set<Connection> connections);
public void setInputs(Map<String, String> inputs) {
if (inputs != null) {
this.inputs = inputs;
}
}
}

Просмотреть файл

@ -1,93 +0,0 @@
/*******************************************************************************
* Copyright (c) 1997, 2015 by ProSyst Software GmbH
* http://www.prosyst.com
* 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
*
* Contributors:
* ProSyst Software GmbH - initial API and implementation
*******************************************************************************/
package org.eclipse.smarthome.automation;
import org.eclipse.smarthome.automation.type.Input;
import org.eclipse.smarthome.automation.type.Output;
/**
* This class defines connection between {@link Input} of the current {@link Module} and {@link Output} of the external
* one. The current module is
* the module containing {@link Connection} instance and the external one is the
* module where the current is connected to. <br>
* The input of the current module is defined by name of the {@link Input}. The {@link Output} of the external module is
* defined by id of the module and name
* of the output.
*
* @author Yordan Mihaylov
*/
public class Connection {
private String ouputModuleId;
private String outputName;
private String inputName;
public Connection(String inputName, String ouputModuleId, String outputName) {
validate("inputName", inputName);
validate("ouputModuleId", ouputModuleId);
validate("outputName", outputName);
this.inputName = inputName;
this.ouputModuleId = ouputModuleId;
this.outputName = outputName;
}
/**
* This method is used to get id of external {@link Module} of this
* connection.
*
* @return id of external {@link Module}
*/
public String getOuputModuleId() {
return ouputModuleId;
}
/**
* This method is used to get output name of external {@link Module} of this
* connection.
*
* @return name of {@link Output} of external {@link Module}
*/
public String getOutputName() {
return outputName;
}
/**
* This method is used to get input name of current {@link Module} of this
* connection.
*
* @return name {@link Input} of the current {@link Module}
*/
public String getInputName() {
return inputName;
}
@Override
public boolean equals(Object obj) {
return (inputName != null && obj instanceof Connection) && inputName.equals(((Connection) obj).getInputName());
};
@Override
public int hashCode() {
return inputName.hashCode();
};
/**
* @param inputName2
*/
private void validate(String field, String id) {
if (id == null || id.length() == 0) {
throw new IllegalArgumentException("Invalid identifier for " + field);
}
}
}

Просмотреть файл

@ -1,17 +1,13 @@
/*******************************************************************************
* Copyright (c) 1997, 2015 by ProSyst Software GmbH
* http://www.prosyst.com
/**
* 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
*
* Contributors:
* ProSyst Software GmbH - initial API and implementation
*******************************************************************************/
*/
package org.eclipse.smarthome.automation;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.smarthome.automation.type.Input;
@ -23,15 +19,62 @@ import org.eclipse.smarthome.config.core.ConfigDescriptionParameter;
* Modules are building components of the {@link Rule}s. Each Module is
* identified by id, which is unique in scope of the {@link Rule}. It also has a {@link ModuleType} which provides meta
* data of the module. The meta data
* defines {@link Input}s, {@link Output}s and {@link ConfigDescriptionParameter}s parameters of the {@link Module}. <br>
* defines {@link Input}s, {@link Output}s and {@link ConfigDescriptionParameter}s parameters of the {@link Module}.
* <br>
* Setters of the module don't have immediate effect on the Rule. To apply the
* changes, they should be set on the {@link Rule} and the Rule has to be
* updated by {@link RuleRegistry}
* updated by RuleManager
*
* @author Yordan Mihaylov - Initial Contribution
*
*/
public interface Module {
public abstract class Module {
/**
* Id of the Module. It is mandatory and unique identifier in scope of the {@link Rule}. The id of the
* {@link Module} is used to identify the module
* in the {@link Rule}.
*/
protected String id;
/**
* The label is a short, user friendly name of the {@link Module} defined by
* this descriptor.
*/
protected String label;
/**
* The description is a long, user friendly description of the {@link Module} defined by this descriptor.
*/
protected String description;
/**
* Configuration values of the Module.
*
* @see {@link ConfigDescriptionParameter}.
*/
protected Map<String, Object> configuration;
/**
* Unique type id of this module.
*/
protected String type;
/**
* Constructor of the module.
*
* @param id the module id.
* @param typeUID unique id of the module type.
* @param configuration configuration values of the module.
*/
public Module(String id, String typeUID, Map<String, ?> configuration) {
this.id = id;
this.type = typeUID;
setConfiguration(configuration);
}
public Module() {
}
/**
* This method is used for getting the id of the {@link Module}. It is unique
@ -39,7 +82,9 @@ public interface Module {
*
* @return module id
*/
public String getId();
public String getId() {
return id;
}
/**
* This method is used for getting the reference to {@link ModuleType} of this
@ -48,54 +93,74 @@ public interface Module {
*
* @return unique id of the {@link ModuleType} of this {@link Module}.
*/
public String getTypeUID();
public String getTypeUID() {
return type;
}
/**
* This method is used for getting the label of the Module. The label is a
* short, user friendly name of the Module.
*
* @return the label of the module.
* @return the label of the module or null.
*/
public String getLabel();
public String getLabel() {
return label;
}
/**
* This method is used for setting the label of the Module.
*
* @param label of the module.
*/
public void setLabel(String label);
public void setLabel(String label) {
this.label = label;
}
/**
* This method is used for getting the description of the Module. The
* description is a long, user friendly description of the Module.
*
* @return the description of the module.
* @return the description of the module or null.
*/
public String getDescription();
public String getDescription() {
return description;
}
/**
* This method is used for setting the description of the Module.
*
* @param description of the module.
*/
public void setDescription(String description);
public void setDescription(String description) {
this.description = description;
}
/**
* This method is used for getting configuration values of the {@link Module}.
* The key is id of the {@link ConfigDescriptionParameter} and the value is
* the configuration value.
*
* @return current configuration values
* @return current configuration values or null.
*/
public Map<String, Object> getConfiguration();
public Map<String, Object> getConfiguration() {
if (configuration == null) {
configuration = new HashMap<String, Object>(11);
}
return configuration;
}
/**
* This method is used for setting the Map with configuration values of the {@link Module}. Key - id of the
* {@link ConfigDescriptionParameter} Value -
* the value of the corresponding property
*
* @param configurations new configuration values.
* @param configuration new configuration values.
*/
public void setConfiguration(Map<String, ?> configurations);
public void setConfiguration(Map<String, ?> configuration) {
if (configuration != null) {
this.configuration = new HashMap<String, Object>(configuration);
}
}
}

Просмотреть файл

@ -1,17 +1,16 @@
/*******************************************************************************
* Copyright (c) 1997, 2015 by ProSyst Software GmbH
* http://www.prosyst.com
/**
* 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
*
* Contributors:
* ProSyst Software GmbH - initial API and implementation
*******************************************************************************/
*/
package org.eclipse.smarthome.automation;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@ -31,25 +30,148 @@ import org.eclipse.smarthome.config.core.ConfigDescriptionParameter;
* describing them. They help for classifying the items and allow them to be
* found.
*
* @author Yordan Mihaylov, Ana Dimova, Vasil Ilchev - Initial Contribution
* @author Yordan Mihaylov - Initial Contribution
* @author Ana Dimova - Initial Contribution
* @author Vasil Ilchev - Initial Contribution
*/
public interface Rule {
public class Rule {
protected List<Trigger> triggers;
protected List<Condition> conditions;
protected List<Action> actions;
protected String scopeId;
protected Map<String, ?> config;
protected List<ConfigDescriptionParameter> configDescriptions;
protected String ruleTemplateUID;
protected String uid;
protected String name;
protected Set<String> tags;
protected Visibility visibility;
protected String description;
public Rule() {
}
/**
* This method is used for getting the unique identifier of the Rule. This
* property is set by the RuleEngine when the {@link Rule} is added.
* This constructor is used to create a rule with specified rule uid.
*
* @param uid is the unique identifier of the rule provided by its creator.
* @param triggers
* @param conditions
* @param actions
* @param configDescriptions
* @param configurations are values of the configuration parameters that are needed for configuring the rule,
* represented as pairs key-value, where the key is the name of the configuration parameter and the value
* is its value.
*/
public Rule(String uid, List<Trigger> triggers, //
List<Condition> conditions, //
List<Action> actions, List<ConfigDescriptionParameter> configDescriptions, //
Map<String, ?> configurations, Visibility visibility) {
this.triggers = triggers;
this.actions = actions;
this.conditions = conditions;
this.configDescriptions = configDescriptions;
setConfiguration(configurations);
this.uid = uid;
this.visibility = visibility;
}
/**
* Utility constructor which creates a rule with uid and default {@link Visibility} = {@link Visibility#VISIBLE}.
*
* @param uid is the unique identifier of the rule provided by its creator.
* @param triggers
* @param conditions
* @param actions
* @param configDescriptions
* @param configurations are values of the configuration parameters that are needed for configuring the rule,
* represented as pairs key-value, where the key is the name of the configuration parameter and the value
* is its value.
*/
public Rule(String uid, List<Trigger> triggers, //
List<Condition> conditions, //
List<Action> actions, List<ConfigDescriptionParameter> configDescriptions, //
Map<String, ?> configurations) {
this(uid, triggers, conditions, actions, configDescriptions, configurations, Visibility.VISIBLE);
}
/**
* This constructor is used to create a rule from template when the does not have defined uid in template.
*
* @param ruleTemplateUID is the unique identifier of the template, used for creation of the rule.
* @param are values of the configuration parameters that are needed for configuring the rule, represented as pairs
* key-value, where the key is the name of the configuration parameter and the value is its value.
*/
public Rule(String ruleTemplateUID, Map<String, ?> configurations) {
this(null, ruleTemplateUID, configurations);
}
/**
* This constructor is used to create a rule from template.
*
* @param uid is the unique identifier of the rule provided by its creator.
* @param ruleTemplateUID is the unique identifier of the template, used for creation of the rule.
* @param configurations are values of the configuration parameters that are needed for configuring the rule,
* represented as pairs key-value, where the key is the name of the configuration parameter and the value
* is its value.
*/
public Rule(String uid, String ruleTemplateUID, Map<String, ?> configurations) {
this.uid = uid;
this.ruleTemplateUID = ruleTemplateUID;
setConfiguration(configurations);
}
/**
* This constructor is used to create a rule from template.
*
* @param uid is the unique identifier of the rule provided by its creator.
* @param triggers
* @param conditions
* @param actions
* @param configDescriptions
* @param configurations are values of the configuration parameters that are needed for configuring the rule,
* represented as pairs key-value, where the key is the name of the configuration parameter and the value
* is its value.
* @param templateUID the unique identifier of the RuleTemplate
* @param visibility visibility of rule
*/
public Rule(String uid, List<Trigger> triggers, //
List<Condition> conditions, //
List<Action> actions, List<ConfigDescriptionParameter> configDescriptions, //
Map<String, ?> configurations, String templateUID, Visibility visibility) {
this(uid, triggers, conditions, actions, configDescriptions, configurations, visibility);
this.ruleTemplateUID = templateUID;
}
/**
* This method is used for getting the unique identifier of the Rule. This property is set by the RuleEngine when
* the {@link Rule} is added. It's optional property.
*
* @return unique id of this {@link Rule}
*/
public String getUID();
public String getUID() {
return uid;
}
/**
* This method is used for getting the user friendly name of the {@link Rule}.
* It's optional property.
* This method is used for getting the unique identifier of the RuleTemplate. This property is set by the RuleEngine
* when the {@link Rule} is added and it is created from template. It's optional property.
*
* @return unique id of this {@link Rule}
*/
public String getTemplateUID() {
return ruleTemplateUID;
}
/**
* This method is used for getting the user friendly name of the {@link Rule}. It's optional property.
*
* @return the name of rule or null.
*/
public String getName();
public String getName() {
return name;
}
/**
* This method is used for setting a friendly name of the Rule. This property
@ -58,18 +180,24 @@ public interface Rule {
* @param ruleName a new name.
* @throws IllegalStateException when the rule is in active state
*/
public void setName(String ruleName) throws IllegalStateException;
public void setName(String ruleName) throws IllegalStateException {
name = ruleName;
}
/**
* Rules can have <li><code>tags</code> - non-hierarchical keywords or terms for describing them. This method is
* Rules can have
* <li><code>tags</code> - non-hierarchical keywords or terms for describing them. This method is
* used for getting the tags assign to this Rule. The tags are used to filter the rules.
*
* @return a list of tags
*/
public Set<String> getTags();
public Set<String> getTags() {
return tags;
}
/**
* Rules can have <li><code>tags</code> - non-hierarchical keywords or terms for describing them. This method is
* Rules can have
* <li><code>tags</code> - non-hierarchical keywords or terms for describing them. This method is
* used for setting the tags to this rule. This property can be changed only when the Rule is not in active state.
* The tags are used to filter the rules.
*
@ -77,7 +205,9 @@ public interface Rule {
* @throws IllegalStateException IllegalStateException when the rule is in
* active state.
*/
public void setTags(Set<String> ruleTags) throws IllegalStateException;
public void setTags(Set<String> ruleTags) throws IllegalStateException {
tags = ruleTags;
}
/**
* This method is used for getting the description of the Rule. The
@ -86,7 +216,9 @@ public interface Rule {
*
* @return the description of the Rule.
*/
public String getDescription();
public String getDescription() {
return description;
}
/**
* This method is used for setting the description of the Rule. The
@ -95,7 +227,21 @@ public interface Rule {
*
* @param ruleDescription of the Rule.
*/
public void setDescription(String ruleDescription);
public void setDescription(String ruleDescription) {
description = ruleDescription;
}
/**
* This method is used to show visibility of the Rule
*
* @return visibility of rule
*/
public Visibility getVisibility() {
if (visibility == null) {
return Visibility.VISIBLE;
}
return visibility;
}
/**
* This method is used for getting the Set with {@link ConfigDescriptionParameter}s defining meta info for
@ -104,7 +250,12 @@ public interface Rule {
*
* @return a {@link Set} of {@link ConfigDescriptionParameter}s.
*/
public Set<ConfigDescriptionParameter> getConfigurationDescriptions();
public List<ConfigDescriptionParameter> getConfigurationDescriptions() {
if (configDescriptions == null) {
configDescriptions = new ArrayList<ConfigDescriptionParameter>(3);
}
return configDescriptions;
}
/**
* This method is used for getting Map with configuration values of the {@link Rule} Key -id of the
@ -113,7 +264,12 @@ public interface Rule {
*
* @return current configuration values
*/
public Map<String, Object> getConfiguration();
public Map<String, ?> getConfiguration() {
if (config == null) {
config = new HashMap<String, Object>(3);
}
return config;
}
/**
* This method is used for setting the Map with configuration values of the {@link Rule}. Key - id of the
@ -122,7 +278,32 @@ public interface Rule {
*
* @param ruleConfiguration new configuration values.
*/
public void setConfiguration(Map<String, ?> ruleConfiguration);
public void setConfiguration(Map<String, ?> ruleConfiguration) {
if (ruleConfiguration != null) {
config = ruleConfiguration;
}
}
public List<Condition> getConditions() {
if (conditions == null) {
conditions = new ArrayList<Condition>(3);
}
return conditions;
}
public List<Action> getActions() {
if (actions == null) {
actions = new ArrayList<Action>(3);
}
return actions;
}
public List<Trigger> getTriggers() {
if (triggers == null) {
triggers = new ArrayList<Trigger>(3);
}
return triggers;
}
/**
* This method is used to get a module participating in Rule
@ -130,7 +311,34 @@ public interface Rule {
* @param moduleId unique id of the module in this rule.
* @return module with specified id or null when it does not exist.
*/
public <T extends Module> T getModule(String moduleId);
public Module getModule(String moduleId) {
Module module = getModule(moduleId, triggers);
if (module != null) {
return module;
}
module = getModule(moduleId, conditions);
if (module != null) {
return module;
}
module = getModule(moduleId, actions);
if (module != null) {
return module;
}
return null;
}
private <T extends Module> T getModule(String moduleUID, List<T> modules) {
if (modules != null) {
for (T module : modules) {
if (module.getId().equals(moduleUID)) {
return module;
}
}
}
return null;
}
/**
* This method is used to return a group of module of this rule
@ -140,7 +348,23 @@ public interface Rule {
* @return list of modules of defined type or all modules when the type is not
* specified.
*/
public <T extends Module> List<T> getModules(Class<T> moduleClazz);
@SuppressWarnings("unchecked")
public <T extends Module> List<T> getModules(Class<T> moduleClazz) {
List<T> result = null;
if (moduleClazz == null) {
result = new ArrayList<T>();
result.addAll((Collection<? extends T>) getTriggers());
result.addAll((Collection<? extends T>) getConditions());
result.addAll((Collection<? extends T>) getActions());
} else if (Trigger.class == moduleClazz) {
result = (List<T>) getTriggers();
} else if (Condition.class == moduleClazz) {
result = (List<T>) getConditions();
} else if (Action.class == moduleClazz) {
result = (List<T>) getActions();
}
return result != null ? result : Collections.<T> emptyList();
}
/**
* This method is used to get the identity scope of this Rule. The identity
@ -150,6 +374,39 @@ public interface Rule {
*
* @return Rule's identity.
*/
public String getScopeIdentifier();
public String getScopeIdentifier() {
return scopeId;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((ruleTemplateUID == null) ? 0 : ruleTemplateUID.hashCode());
result = prime * result + ((uid == null) ? 0 : uid.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Rule other = (Rule) obj;
if (ruleTemplateUID == null) {
if (other.ruleTemplateUID != null)
return false;
} else if (!ruleTemplateUID.equals(other.ruleTemplateUID))
return false;
if (uid == null) {
if (other.uid != null)
return false;
} else if (!uid.equals(other.uid))
return false;
return true;
}
}

Просмотреть файл

@ -0,0 +1,19 @@
/**
* 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;
import org.eclipse.smarthome.core.common.registry.Provider;
/**
* A {@link RuleProvider} is responsible for providing rules.
*
* @author Kai Kreuzer - Initial contribution
*/
public interface RuleProvider extends Provider<Rule> {
}

Просмотреть файл

@ -1,18 +1,14 @@
/*******************************************************************************
* Copyright (c) 1997, 2015 by ProSyst Software GmbH
* http://www.prosyst.com
/**
* 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
*
* Contributors:
* ProSyst Software GmbH - initial API and implementation
*******************************************************************************/
*/
package org.eclipse.smarthome.automation;
import java.util.Collection;
import java.util.Set;
import org.eclipse.smarthome.core.common.registry.Registry;
@ -33,6 +29,14 @@ public interface RuleRegistry extends Registry<Rule, String> {
*/
public Collection<Rule> getByTag(String tag);
/**
* This method is used to get collection of Rules which has specified tags.
*
* @param tags set of rule's tags
* @return collection of {@link Rule}s having specified tags.
*/
public Collection<Rule> getByTags(Set<String> tags);
/**
* This method is used for changing enable state of the Rule.
*
@ -42,20 +46,19 @@ public interface RuleRegistry extends Registry<Rule, String> {
public void setEnabled(String uid, boolean isEnabled);
/**
* This method is used for checking active state of the Rule. Only inactive Rules can change their properties.
* This method gets status of specified rule.
*
* @param uid unique identifier of the rule
* @return true when the rule is active.
* @param ruleUID uid of rule
* @return {@link RuleStatusInfo} object containing status of looking rule.
*/
public boolean isEnabled(String uid);
public RuleStatusInfo getStatus(String ruleUID);
/**
* This method is used for checking the running state of the Rule.
* The Rule is running if it is triggered and execution of its actions are not finished.
* This method gets enable status for a rule.
*
* @param uid unique identifier of the rule
* @return true when the Rule is running.
* @param ruleUID uid of rule
* @return true when the rule is enabled, false when it is disabled and null when it is not available.
*/
public boolean isRunning(String uid);
public Boolean isEnabled(String ruleUID);
}

Просмотреть файл

@ -0,0 +1,36 @@
/**
* 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;
/**
* This enum is used to present the main status of a rule.
*
* @author Yordan Mihaylov - Initial contribution
* @author Kai Kreuzer - Refactored to match ThingStatus implementation
*/
public enum RuleStatus {
DISABLED(0),
NOT_INITIALIZED(1),
IDLE(2),
RUNNING(3);
private final int value;
private RuleStatus(final int newValue) {
value = newValue;
}
/**
* Gets the value of a rule status.
*
* @return the value
*/
public int getValue() {
return value;
}
}

Просмотреть файл

@ -0,0 +1,37 @@
/**
* 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;
/**
* This enum is used to present status detail of rule, which can be considered as a sub-status.
*
* @author Yordan Mihaylov - Initial contribution
* @author Kai Kreuzer - Refactored to match ThingStatusDetail implementation
*/
public enum RuleStatusDetail {
NONE(0),
HANDLER_MISSING_ERROR(1),
HANDLER_INITIALIZING_ERROR(2),
CONFIGURATION_ERROR(3),
TEMPLATE_MISSING_ERROR(4);
private final int value;
private RuleStatusDetail(final int newValue) {
value = newValue;
}
/**
* Gets the value of a thing status detail.
*
* @return the value
*/
public int getValue() {
return value;
}
}

Просмотреть файл

@ -0,0 +1,132 @@
/**
* 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;
/**
* This class is used to present status of rule. The status consists out of three parts:
* The main status, a status detail and a string description.
*
* @author Yordan Mihaylov - Initial contribution
* @author Kai Kreuzer - Refactored to match ThingStatusInfo implementation
*/
public class RuleStatusInfo {
private RuleStatus status;
private RuleStatusDetail statusDetail;
private String description;
/**
* Constructs a status info.
*
* @param status the status (must not be null)
*
* @throws IllegalArgumentException if status is null
*/
public RuleStatusInfo(RuleStatus status) throws IllegalArgumentException {
this(status, RuleStatusDetail.NONE);
}
/**
* Constructs a status info.
*
* @param status the status (must not be null)
* @param statusDetail the detail of the status (must not be null)
*
* @throws IllegalArgumentException if status or status detail is null
*/
public RuleStatusInfo(RuleStatus status, RuleStatusDetail statusDetail) throws IllegalArgumentException {
this(status, statusDetail, null);
}
/**
* Constructs a status info.
*
* @param status the status (must not be null)
* @param statusDetail the detail of the status (must not be null)
* @param description the description of the status
*
* @throws IllegalArgumentException if status or status detail is null
*/
public RuleStatusInfo(RuleStatus status, RuleStatusDetail statusDetail, String description)
throws IllegalArgumentException {
if (status == null) {
throw new IllegalArgumentException("Thing status must not be null");
}
if (statusDetail == null) {
throw new IllegalArgumentException("Thing status detail must not be null");
}
this.status = status;
this.statusDetail = statusDetail;
this.description = description;
}
/**
* Gets the status itself.
*
* @return the status (not null)
*/
public RuleStatus getStatus() {
return status;
}
/**
* Gets the detail of the status.
*
* @return the status detail (not null)
*/
public RuleStatusDetail getStatusDetail() {
return statusDetail;
}
/**
* Gets the description of the status.
*
* @return the description
*/
public String getDescription() {
return description;
}
@Override
public String toString() {
boolean hasDescription = getDescription() != null && !getDescription().isEmpty();
return getStatus() + (getStatusDetail() == RuleStatusDetail.NONE ? "" : " (" + getStatusDetail() + ")")
+ (hasDescription ? ": " + getDescription() : "");
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((description == null) ? 0 : description.hashCode());
result = prime * result + ((status == null) ? 0 : status.hashCode());
result = prime * result + ((statusDetail == null) ? 0 : statusDetail.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
RuleStatusInfo other = (RuleStatusInfo) obj;
if (description == null) {
if (other.description != null)
return false;
} else if (!description.equals(other.description))
return false;
if (status != other.status)
return false;
if (statusDetail != other.statusDetail)
return false;
return true;
}
}

Просмотреть файл

@ -0,0 +1,24 @@
/**
* 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;
/**
* This interface is used by {@link RuleRegistry} implementation to be notified of changes related to statuses of rules.
*
* @author Yordan Mihaylov - initial contribution
*/
public interface StatusInfoCallback {
/**
* The method is called when the rule has update of its status.
*
* @param ruleUID UID of the {@link Rule}
* @param statusInfo new status info releated to the {@link Rule}
*/
void statusInfoChanged(String ruleUID, RuleStatusInfo statusInfo);
}

Просмотреть файл

@ -1,17 +1,14 @@
/*******************************************************************************
* Copyright (c) 1997, 2015 by ProSyst Software GmbH
* http://www.prosyst.com
/**
* 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
*
* Contributors:
* ProSyst Software GmbH - initial API and implementation
*******************************************************************************/
*/
package org.eclipse.smarthome.automation;
import java.util.Map;
import org.eclipse.smarthome.automation.type.Input;
import org.eclipse.smarthome.automation.type.Output;
import org.eclipse.smarthome.automation.type.TriggerType;
@ -25,6 +22,13 @@ import org.eclipse.smarthome.config.core.ConfigDescriptionParameter;
*
* @author Yordan Mihaylov - Initial Contribution
*/
public interface Trigger extends Module {
public class Trigger extends Module {
public Trigger() {
}
public Trigger(String id, String typeUID, Map<String, ?> configuration) {
super(id, typeUID, configuration);
}
}

Просмотреть файл

@ -0,0 +1,35 @@
/**
* 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;
import org.eclipse.smarthome.automation.template.Template;
import org.eclipse.smarthome.automation.type.ModuleType;
/**
* Defines visibility values of {@link ModuleType}s and {@link Template}s
*
* @author Yordan Mihaylov - Initial Contribution
*
*/
public enum Visibility {
/**
* The UI has to show this object.
*/
VISIBLE,
/**
* The UI has to hide this object.
*/
HIDDEN,
/**
* The UI has to show this object only to experts.
*/
EXPERT
}

Просмотреть файл

@ -0,0 +1,45 @@
/**
* 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.events;
import org.eclipse.smarthome.automation.Rule;
import org.eclipse.smarthome.core.events.AbstractEvent;
/**
* abstract class for rule events
*
* @author Benedikt Niehues - initial contribution
*
*/
public abstract class AbstractRuleRegistryEvent extends AbstractEvent {
private final Rule rule;
/**
* Must be called in subclass constructor to create a new rule registry event.
*
* @param topic
* @param payload
* @param source
* @param ruleDTO
*/
public AbstractRuleRegistryEvent(String topic, String payload, String source, Rule rule) {
super(topic, payload, source);
this.rule = rule;
}
/**
* returns the RuleDTO which caused the Event
*
* @return
*/
public Rule getRule() {
return this.rule;
}
}

Просмотреть файл

@ -0,0 +1,45 @@
/**
* 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.events;
import org.eclipse.smarthome.automation.Rule;
/**
* An {@link RuleAddedEvent} notifies subscribers that an item has been added.
* Rule added events must be created with the {@link RuleEventFactory}.
*
* @author Benedikt Niehues - initial contribution
*
*/
public class RuleAddedEvent extends AbstractRuleRegistryEvent {
public static final String TYPE = RuleAddedEvent.class.getSimpleName();
/**
* constructs a new rule added event
*
* @param topic
* @param payload
* @param source
* @param ruleDTO
*/
public RuleAddedEvent(String topic, String payload, String source, Rule ruleDTO) {
super(topic, payload, source, ruleDTO);
}
@Override
public String getType() {
return TYPE;
}
@Override
public String toString() {
return "Rule '" + getRule().getUID() + "' has been added.";
}
}

Просмотреть файл

@ -0,0 +1,166 @@
/**
* 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.events;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import org.eclipse.smarthome.automation.Rule;
import org.eclipse.smarthome.automation.RuleStatusInfo;
import org.eclipse.smarthome.core.events.AbstractEventFactory;
import org.eclipse.smarthome.core.events.Event;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* this is a factory to create Rule Events
*
* @author Benedikt Niehues - initial contribution
*
*/
public class RuleEventFactory extends AbstractEventFactory {
private final Logger logger = LoggerFactory.getLogger(RuleEventFactory.class);
private static final String RULE_STATE_EVENT_TOPIC = "smarthome/rules/{ruleID}/state";
private static final String RULE_ADDED_EVENT_TOPIC = "smarthome/rules/{ruleID}/added";
private static final String RULE_REMOVED_EVENT_TOPIC = "smarthome/rules/{ruleID}/removed";
private static final String RULE_UPDATED_EVENT_TOPIC = "smarthome/rules/{ruleID}/updated";
private static final Set<String> SUPPORTED_TYPES = new HashSet<String>();
static {
SUPPORTED_TYPES.add(RuleAddedEvent.TYPE);
SUPPORTED_TYPES.add(RuleRemovedEvent.TYPE);
SUPPORTED_TYPES.add(RuleStatusInfoEvent.TYPE);
SUPPORTED_TYPES.add(RuleUpdatedEvent.TYPE);
}
public RuleEventFactory() {
super(SUPPORTED_TYPES);
}
@Override
protected Event createEventByType(String eventType, String topic, String payload, String source) throws Exception {
logger.trace("creating ruleEvent of type: {}", eventType);
if (eventType == null) {
return null;
}
if (eventType.equals(RuleAddedEvent.TYPE)) {
return createRuleAddedEvent(topic, payload, source);
} else if (eventType.equals(RuleRemovedEvent.TYPE)) {
return createRuleRemovedEvent(topic, payload, source);
} else if (eventType.equals(RuleStatusInfoEvent.TYPE)) {
return createRuleStatusInfoEvent(topic, payload, source);
} else if (eventType.equals(RuleUpdatedEvent.TYPE)) {
return createRuleUpdatedEvent(topic, payload, source);
}
return null;
}
private Event createRuleUpdatedEvent(String topic, String payload, String source) {
Rule[] ruleDTO = deserializePayload(payload, Rule[].class);
if (ruleDTO.length != 2) {
throw new IllegalArgumentException("Creation of RuleUpdatedEvent failed: invalid payload: " + payload);
}
return new RuleUpdatedEvent(topic, payload, source, ruleDTO[0], ruleDTO[1]);
}
private Event createRuleStatusInfoEvent(String topic, String payload, String source) {
RuleStatusInfo statusInfo = deserializePayload(payload, RuleStatusInfo.class);
return new RuleStatusInfoEvent(topic, payload, source, statusInfo, getRuleId(topic));
}
private Event createRuleRemovedEvent(String topic, String payload, String source) {
Rule ruleDTO = deserializePayload(payload, Rule.class);
return new RuleRemovedEvent(topic, payload, source, ruleDTO);
}
private Event createRuleAddedEvent(String topic, String payload, String source) {
Rule ruleDTO = deserializePayload(payload, Rule.class);
return new RuleAddedEvent(topic, payload, source, ruleDTO);
}
private String getRuleId(String topic) {
String[] topicElements = getTopicElements(topic);
if (topicElements.length != 4)
throw new IllegalArgumentException("Event creation failed, invalid topic: " + topic);
return topicElements[2];
}
/**
* creates a rule updated event
*
* @param rule the updated rule
* @param oldRule the old rule
* @param source
* @return
*/
public static RuleUpdatedEvent createRuleUpdatedEvent(Rule rule, Rule oldRule, String source) {
String topic = buildTopic(RULE_UPDATED_EVENT_TOPIC, rule);
List<Rule> rules = new LinkedList<Rule>();
rules.add(rule);
rules.add(oldRule);
String payload = serializePayload(rules);
return new RuleUpdatedEvent(topic, payload, source, rule, oldRule);
}
/**
* creates a rule status info event
*
* @param statusInfo
* @param rule
* @param source
* @return
*/
public static RuleStatusInfoEvent createRuleStatusInfoEvent(RuleStatusInfo statusInfo, String ruleUID,
String source) {
String topic = buildTopic(RULE_STATE_EVENT_TOPIC, ruleUID);
String payload = serializePayload(statusInfo);
return new RuleStatusInfoEvent(topic, payload, source, statusInfo, ruleUID);
}
/**
* creates a rule removed event
*
* @param rule
* @param source
* @return
*/
public static RuleRemovedEvent createRuleRemovedEvent(Rule rule, String source) {
String topic = buildTopic(RULE_REMOVED_EVENT_TOPIC, rule);
String payload = serializePayload(rule);
return new RuleRemovedEvent(topic, payload, source, rule);
}
/**
* creates a rule added event
*
* @param rule
* @param source
* @return
*/
public static RuleAddedEvent createRuleAddedEvent(Rule rule, String source) {
String topic = buildTopic(RULE_ADDED_EVENT_TOPIC, rule);
String payload = serializePayload(rule);
return new RuleAddedEvent(topic, payload, source, rule);
}
private static String buildTopic(String topic, String ruleUID) {
return topic.replace("{ruleID}", ruleUID);
}
private static String buildTopic(String topic, Rule rule) {
return buildTopic(topic, rule.getUID());
}
}

Просмотреть файл

@ -0,0 +1,45 @@
/**
* 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.events;
import org.eclipse.smarthome.automation.Rule;
/**
* An {@link RuleRemovedEvent} notifies subscribers that an item has been added.
* Rule added events must be created with the {@link RuleEventFactory}.
*
* @author Benedikt Niehues - initial contribution
*
*/
public class RuleRemovedEvent extends AbstractRuleRegistryEvent {
public static final String TYPE = RuleRemovedEvent.class.getSimpleName();
/**
* constructs a new rule removed event
*
* @param topic
* @param payload
* @param source
* @param ruleDTO
*/
public RuleRemovedEvent(String topic, String payload, String source, Rule ruleDTO) {
super(topic, payload, source, ruleDTO);
}
@Override
public String getType() {
return TYPE;
}
@Override
public String toString() {
return "Rule '" + getRule().getUID() + "' has been removed.";
}
}

Просмотреть файл

@ -0,0 +1,66 @@
/**
* 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.events;
import org.eclipse.smarthome.automation.RuleStatusInfo;
import org.eclipse.smarthome.core.events.AbstractEvent;
/**
* An {@link RuleStatusInfoEvent} notifies subscribers that an item has been
* added. Rule added events must be created with the {@link RuleEventFactory}.
*
* @author Benedikt Niehues - initial contribution
* @author Kai Kreuzer - added toString method
*
*/
public class RuleStatusInfoEvent extends AbstractEvent {
public static final String TYPE = RuleStatusInfoEvent.class.getSimpleName();
private RuleStatusInfo statusInfo;
private String ruleId;
/**
* constructs a new rule status event
*
* @param topic
* @param payload
* @param source
* @param ruleDTO
*/
public RuleStatusInfoEvent(String topic, String payload, String source, RuleStatusInfo statusInfo, String ruleId) {
super(topic, payload, source);
this.statusInfo = statusInfo;
this.ruleId = ruleId;
}
@Override
public String getType() {
return TYPE;
}
/**
* @return the statusInfo
*/
public RuleStatusInfo getStatusInfo() {
return statusInfo;
}
/**
* @return the ruleId
*/
public String getRuleId() {
return ruleId;
}
@Override
public String toString() {
return ruleId + " updated: " + statusInfo.toString();
}
}

Просмотреть файл

@ -0,0 +1,55 @@
/**
* 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.events;
import org.eclipse.smarthome.automation.Rule;
/**
* An {@link RuleUpdatedEvent} notifies subscribers that an item has been added.
* Rule added events must be created with the {@link RuleEventFactory}.
*
* @author Benedikt Niehues - initial contribution
*
*/
public class RuleUpdatedEvent extends AbstractRuleRegistryEvent {
public static final String TYPE = RuleUpdatedEvent.class.getSimpleName();
private Rule oldRule;
/**
* constructs a new rule updated event
*
* @param topic
* @param payload
* @param source
* @param ruleDTO
*/
public RuleUpdatedEvent(String topic, String payload, String source, Rule rule, Rule oldRule) {
super(topic, payload, source, rule);
this.oldRule = oldRule;
}
@Override
public String getType() {
return TYPE;
}
/**
* @return the oldRuleDTO
*/
public Rule getOldRule() {
return oldRule;
}
@Override
public String toString() {
return "Rule '" + getRule().getUID() + "' has been updated.";
}
}

Просмотреть файл

@ -1,15 +1,10 @@
/*******************************************************************************
* Copyright (c) 1997, 2015 by ProSyst Software GmbH
* http://www.prosyst.com
/**
* 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
*
* Contributors:
* ProSyst Software GmbH - initial API and implementation
*******************************************************************************/
*/
package org.eclipse.smarthome.automation.handler;
import java.util.Map;
@ -20,6 +15,10 @@ import org.eclipse.smarthome.automation.Rule;
/**
* This interface is implemented by external modules which are called by the
* RuleEngine to execute {@link Action}s of the {@link Rule}s.
*
* @author Yordan Mihaylov - Initial Contribution
* @author Ana Dimova - Initial Contribution
* @author Vasil Ilchev - Initial Contribution
*/
public interface ActionHandler extends ModuleHandler {
@ -27,9 +26,10 @@ public interface ActionHandler extends ModuleHandler {
* The Method is called by the RuleEngine to execute a {@link Rule} {@link Action}.
*
*
* @param inputs input values of the Action
* @param context contains action input values and snapshot of all module output values. The output ids are defined
* in form: ModuleId.outputId
* @return values map of values which must be set to outputs of the {@link Action}.
*/
public Map<String, Object> execute(Map<String, ?> inputs);
public Map<String, Object> execute(Map<String, ?> context);
}

Просмотреть файл

@ -0,0 +1,30 @@
/**
* 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.handler;
import org.eclipse.smarthome.automation.Module;
/**
* This is a base class that can be used by any ModuleHandler implementation
*
* @author Kai Kreuzer - Initial Contribution
*/
public class BaseModuleHandler<T extends Module> implements ModuleHandler {
protected T module;
public BaseModuleHandler(T module) {
this.module = module;
}
@Override
public void dispose() {
// can be overridden
}
}

Просмотреть файл

@ -0,0 +1,67 @@
/**
* 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.handler;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.smarthome.automation.Module;
import org.osgi.framework.BundleContext;
/**
* This is a base class that can be used by any ModuleHandlerFactory implementation
*
* @author Kai Kreuzer - Initial Contribution
* @author Benedikt Niehues - change behavior for unregistering ModuleHandler
*/
abstract public class BaseModuleHandlerFactory implements ModuleHandlerFactory {
protected Map<String, ModuleHandler> handlers;
protected BundleContext bundleContext;
public BaseModuleHandlerFactory(BundleContext bundleContext) {
if (bundleContext == null) {
throw new IllegalArgumentException("BundleContext must not be null.");
}
this.bundleContext = bundleContext;
handlers = new HashMap<String, ModuleHandler>();
}
@Override
public ModuleHandler getHandler(Module module, String ruleUID) {
ModuleHandler handler = internalCreate(module, ruleUID);
if (handler != null) {
handlers.put(ruleUID + module.getId(), handler);
}
return handler;
}
abstract protected ModuleHandler internalCreate(Module module, String ruleUID);
public void dispose() {
for (ModuleHandler handler : handlers.values()) {
if (handler != null) {
handler.dispose();
}
}
handlers.clear();
}
@Override
public void ungetHandler(Module module, String ruleUID, ModuleHandler hdlr) {
ModuleHandler handler = handlers.get(ruleUID + module.getId());
if (handler != null) {
this.handlers.remove(ruleUID + module.getId());
if (!this.handlers.containsValue(hdlr)) {
handler.dispose();
handler = null;
}
}
}
}

Просмотреть файл

@ -1,15 +1,10 @@
/*******************************************************************************
* Copyright (c) 1997, 2015 by ProSyst Software GmbH
* http://www.prosyst.com
/**
* 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
*
* Contributors:
* ProSyst Software GmbH - initial API and implementation
*******************************************************************************/
*/
package org.eclipse.smarthome.automation.handler;
import java.util.Map;
@ -21,15 +16,19 @@ import org.eclipse.smarthome.automation.Condition;
* RuleEngine, when it has to check if the {@link Condition} is satisfied or
* not.
*
* @author Yordan Mihaylov - Initial Contribution
* @author Ana Dimova - Initial Contribution
* @author Vasil Ilchev - Initial Contribution
*/
public interface ConditionHandler extends ModuleHandler {
/**
* Method that states if the Condition is satisfied or not
*
* @param inputs the values of condition inputs.
* @param context contains condition input values and snapshot of all module output values. The output ids are
* defined in form: ModuleId.outputId
* @return true if Condition is satisfied, false otherwise
*/
public boolean isSatisfied(Map<String, ?> inputs);
public boolean isSatisfied(Map<String, ?> context);
}

Просмотреть файл

@ -1,23 +1,14 @@
/*******************************************************************************
* Copyright (c) 1997, 2015 by ProSyst Software GmbH
* http://www.prosyst.com
/**
* 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
*
* Contributors:
* ProSyst Software GmbH - initial API and implementation
*******************************************************************************/
*/
package org.eclipse.smarthome.automation.handler;
import java.util.Map;
import org.eclipse.smarthome.automation.Module;
/**
* A common interface for all module handler interfaces. The handler interfaces are
* A common interface for all module Handler interfaces. The Handler interfaces are
* bridge between RuleEngine and external modules used by the RuleEngine.
*
* @author Yordan Mihaylov - Initial Contribution
@ -25,15 +16,9 @@ import org.eclipse.smarthome.automation.Module;
*/
public interface ModuleHandler {
/**
* This method update configuration values set to corresponding of {@link Module} instance
*
* @param configuration updated configuration values of {@link Module} instance
*/
public void setConfiguration(Map<String, ?> configuration);
/**
* The method is called by RuleEngine to free resources when {@link ModuleHandler} is released.
*/
public void dispose();
}

Просмотреть файл

@ -1,15 +1,10 @@
/*******************************************************************************
* Copyright (c) 1997, 2015 by ProSyst Software GmbH
* http://www.prosyst.com
/**
* 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
*
* Contributors:
* ProSyst Software GmbH - initial API and implementation
*******************************************************************************/
*/
package org.eclipse.smarthome.automation.handler;
import java.util.Collection;
@ -25,6 +20,7 @@ import org.eclipse.smarthome.automation.Module;
* instance.
*
* @author Yordan Mihaylov - Initial Contribution
* @author Benedikt Niehues - change behavior for unregistering ModuleHandler
*/
public interface ModuleHandlerFactory {
@ -36,7 +32,7 @@ public interface ModuleHandlerFactory {
public Collection<String> getTypes();
/**
* This method is used to create ModuleHandler instance for the passed module
* This method is used to get a ModuleHandler instance for the passed module
* instance
*
* @param module module instance for which the {@link ModuleHandler} instance is
@ -44,6 +40,14 @@ public interface ModuleHandlerFactory {
*
* @return ModuleHandler instance.
*/
public <T extends ModuleHandler> T create(Module module);
public ModuleHandler getHandler(Module module, String ruleUID);
/**
* This method signalizes the Factory that a ModuleHandler for the passed module is not needed anymore. Implementors
* must take care of invalidating caches and disposing the Handlers.
*
* @param module
*/
public void ungetHandler(Module module, String ruleUID, ModuleHandler handler);
}

Просмотреть файл

@ -1,15 +1,10 @@
/*******************************************************************************
* Copyright (c) 1997, 2015 by ProSyst Software GmbH
* http://www.prosyst.com
/**
* 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
*
* Contributors:
* ProSyst Software GmbH - initial API and implementation
*******************************************************************************/
*/
package org.eclipse.smarthome.automation.handler;
import java.util.Map;
@ -35,12 +30,12 @@ public interface RuleEngineCallback {
* @param trigger instance of trigger which was fired. When one TriggerHandler
* serve more then one {@link Trigger} instances, this parameter
* defines which trigger was fired.
* @param outputs is a {@link Map} of output values of the triggered {@link Trigger}. Each entry of the map
* @param context is a {@link Map} of output values of the triggered {@link Trigger}. Each entry of the map
* contains:
* <ul>
* <li><code>key</code> - the id of the {@link Output} ,
* <li><code>value</code> - represents output value of the {@link Trigger}'s {@link Output}
* </ul>
*/
public void triggered(Trigger trigger, Map<String, ?> outputs);
public void triggered(Trigger trigger, Map<String, ?> context);
}

Просмотреть файл

@ -1,22 +1,20 @@
/*******************************************************************************
* Copyright (c) 1997, 2015 by ProSyst Software GmbH
* http://www.prosyst.com
/**
* 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
*
* Contributors:
* ProSyst Software GmbH - initial API and implementation
*******************************************************************************/
*/
package org.eclipse.smarthome.automation.handler;
/**
* This SPI interface is used by the RuleEngine to set a callback interface to
* This Handler interface is used by the RuleEngine to set a callback interface to
* itself. The callback has to implemented {@link RuleEngineCallback} interface
* and it is used to notify the RuleEngine when {@link TriggerHandler} was triggered
*
* @author Yordan Mihaylov - Initial Contribution
* @author Ana Dimova - Initial Contribution
* @author Vasil Ilchev - Initial Contribution
*/
public interface TriggerHandler extends ModuleHandler {

Просмотреть файл

@ -0,0 +1,71 @@
/**
* 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.parser;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Set;
/**
* This interface provides opportunity to plug different parsers, for example JSON, GSON or other.
*
* @author Ana Dimova - Initial Contribution
*
*/
public interface Parser<T> {
/**
* This constant can be used to specify the type of the parser.
* <p>
* Example : "parser.type" = "parser.module.type";
* It is used as registration property of the corresponding service.
*/
public static String PARSER_TYPE = "parser.type";
/**
* Following constants are representing the possible values of property {@link #PARSER_TYPE}
*/
public static String PARSER_MODULE_TYPE = "parser.module.type";
public static String PARSER_TEMPLATE = "parser.template";
public static String PARSER_RULE = "parser.rule";
/**
* This constant can be used for recognition of which file format is supported by the parser.
* <p>
* Example : "format" = "json";
* It is used as registration property of the corresponding service.
*/
public static String FORMAT = "format";
/**
* Following constant representing the possible value of property {@link #FORMAT} It means that the parser supports
* json format.
*/
public static String FORMAT_JSON = "json";
/**
* This method is used for loading file with some particular format and parse it to the automation objects.
*
* @param reader {@link InputStreamReader} which reads from a file containing automation object representations.
* @return a set of automation objects. Each object represents the result of parsing of one object.
* @throws ParsingException is thrown when json format is wrong or there is a semantic error in description of
* the automation objects.
*/
public Set<T> parse(InputStreamReader reader) throws ParsingException;
/**
* This method is used to record automation objects in a file with some particular format.
*
* @param dataObjects provides an objects for export.
* @param writer is {@link OutputStreamWriter} used to write the automation objects in a file.
* @throws Exception is thrown when I/O operation has failed or has been interrupted or generating of the text fails
* for some reasons.
*/
public void serialize(Set<T> dataObjects, OutputStreamWriter writer) throws Exception;
}

Просмотреть файл

@ -0,0 +1,73 @@
/**
* 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.parser;
import java.util.ArrayList;
import java.util.List;
/**
* This class extends the {@link Exception} class functionality with functionality serving to accumulate the all
* exceptions during the parsing process.
*
* @author Ana Dimova - Initial Contribution
*/
@SuppressWarnings("serial")
public class ParsingException extends Exception {
/**
* This field keeps all accumulated exceptions.
*/
List<ParsingNestedException> exceptions;
/**
* This constructor creates the holder for one exception during the parsing process.
*
* @param e is an exception during the parsing process.
*/
public ParsingException(ParsingNestedException e) {
exceptions = new ArrayList<ParsingNestedException>();
exceptions.add(e);
}
/**
* This constructor creates a holder for several exceptions during the parsing process.
*
* @param exceptions is a list with exceptions during the parsing process.
*/
public ParsingException(List<ParsingNestedException> exceptions) {
this.exceptions = exceptions;
}
@Override
public String getMessage() {
StringBuilder writer = new StringBuilder();
for (ParsingNestedException e : exceptions) {
writer.append(e.getMessage() + "\n");
}
return writer.toString();
}
@Override
public StackTraceElement[] getStackTrace() {
int size = 0;
for (ParsingNestedException e : exceptions) {
size = size + e.getStackTrace().length;
}
int index = 0;
StackTraceElement[] st = new StackTraceElement[size];
for (int n = 0; n < exceptions.size(); n++) {
StackTraceElement[] ste = exceptions.get(n).getStackTrace();
for (int i = 0; i < ste.length; i++) {
st[index] = ste[i];
index++;
}
}
return st;
}
}

Просмотреть файл

@ -0,0 +1,83 @@
/**
* 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.parser;
/**
* This class extends the {@link Exception} class functionality with keeping additional information about reasons for
* exception during the parsing process.
*
* @author Ana Dimova - Initial Contribution
*/
@SuppressWarnings("serial")
public class ParsingNestedException extends Exception {
public static final int MODULE_TYPE = 1;
public static final int TEMPLATE = 2;
public static final int RULE = 3;
/**
* This field keeps information about the UID of the automation object for parsing - module type, template or rule.
*/
private String id;
/**
* This field keeps information about the type of the automation object for parsing - module type, template or rule.
*/
private int type;
/**
* This constructor creates an exception based on exception thrown the parsing plus information about the type of
* the automation object, its UID and additional message with additional information about the parsing process.
*
* @param type is the type of the automation object for parsing.
* @param id is the UID of the automation object for parsing.
* @param msg is the additional message with additional information about the parsing process.
* @param t is the exception thrown during the parsing.
*/
public ParsingNestedException(int type, String id, String msg, Throwable t) {
super(msg, t);
this.id = id;
this.type = type;
}
/**
* This constructor creates an exception based on exception thrown during the parsing plus information about the
* type of the automation object and its UID.
*
* @param type is the type of the automation object for parsing.
* @param id is the UID of the automation object for parsing.
* @param t is the exception thrown during the parsing.
*/
public ParsingNestedException(int type, String id, Throwable t) {
super(t);
this.id = id;
this.type = type;
}
@Override
public String getMessage() {
StringBuilder sb = new StringBuilder();
switch (type) {
case MODULE_TYPE:
sb.append("[Module Type");
break;
case TEMPLATE:
sb.append("[Template");
break;
case RULE:
sb.append("[Rule");
break;
default:
break;
}
if (id != null)
sb.append(" " + id);
sb.append("] " + super.getMessage());
return sb.toString();
}
}

Просмотреть файл

@ -1,17 +1,15 @@
/*******************************************************************************
* Copyright (c) 1997, 2015 by ProSyst Software GmbH
* http://www.prosyst.com
/**
* 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
*
* Contributors:
* ProSyst Software GmbH - initial API and implementation
*******************************************************************************/
*/
package org.eclipse.smarthome.automation.template;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@ -21,6 +19,7 @@ import org.eclipse.smarthome.automation.Condition;
import org.eclipse.smarthome.automation.Module;
import org.eclipse.smarthome.automation.Rule;
import org.eclipse.smarthome.automation.Trigger;
import org.eclipse.smarthome.automation.Visibility;
import org.eclipse.smarthome.config.core.ConfigDescriptionParameter;
/**
@ -33,102 +32,122 @@ import org.eclipse.smarthome.config.core.ConfigDescriptionParameter;
* <p>
* Templates can have <code>tags</code> - non-hierarchical keywords or terms for describing them.
*
* @author Yordan Mihaylov, Ana Dimova, Vasil Ilchev - Initial Contribution
* @author Yordan Mihaylov - Initial Contribution
* @author Ana Dimova - Initial Contribution
* @author Vasil Ilchev - Initial Contribution
*/
public class RuleTemplate implements Template {
private String UID;
/**
* This field holds an unique identifier of the {@link RuleTemplate} instance.
*/
private String uid;
/**
* This field holds a list with the unique {@link Trigger}s participating in the {@link Rule} and starting its
* execution.
*/
private List<Trigger> triggers;
/**
* This field holds a list with the unique {@link Condition}s participating in the {@link Rule} and determine the
* completion of the execution.
*/
private List<Condition> conditions;
/**
* This field holds a list with the unique {@link Action}s participating in the {@link Rule} and are the real work
* that will be done by the rule.
*/
private List<Action> actions;
/**
* This field holds a set of non-hierarchical keywords or terms for describing the {@link RuleTemplate}.
*/
private Set<String> tags;
/**
* This field holds the short, user friendly name of the Template.
*/
private String label;
/**
* This field describes the usage of the {@link Rule} and its benefits.
*/
private String description;
/**
* This field determines {@link Visibility} of the template.
*/
private Visibility visibility;
private Set<ConfigDescriptionParameter> configDescriptions;
/**
* This field defines a set of configuration properties of the {@link Rule}.
*/
private List<ConfigDescriptionParameter> configDescriptions;
/**
* This constructor creates a {@link RuleTemplate} instance.
*
* @param UID unique identifier of the rule template
* @param UID is an unique identifier of the {@link RuleTemplate} instance.
* @param triggers - list of unique {@link Trigger}s participating in the {@link Rule}
* @param conditions - list of unique {@link Condition}s participating in the {@link Rule}
* @param actions - list of unique {@link Action}s participating in the {@link Rule}
* @param configDescriptions - set of configuration properties of the {@link Rule}
* @param visibility visibility of template. It can be public or private
* @param visibility defines if the template can be public or private.
*/
public RuleTemplate(String UID,
List<Trigger> triggers, //
List<Condition> conditions, List<Action> actions, Set<ConfigDescriptionParameter> configDescriptions,
public RuleTemplate(String UID, String label, String description, Set<String> tags, List<Trigger> triggers,
List<Condition> conditions, List<Action> actions, List<ConfigDescriptionParameter> configDescriptions,
Visibility visibility) {
this.UID = UID;
this.uid = UID;
this.label = label;
this.description = description;
this.triggers = triggers;
this.conditions = conditions;
this.actions = actions;
this.configDescriptions = configDescriptions;
this.visibility = visibility;
if (tags == null || tags.isEmpty())
return;
this.tags = new HashSet<String>(tags);
}
/**
* This method is used for getting the type of Template. It is unique in scope
* of RuleEngine.
* This method is used for getting the type of Template. It is unique in scope of RuleEngine.
*
* @return the unique id of Template.
*/
@Override
public String getUID() {
return UID;
return uid;
}
/**
* Templates can have <li><code>tags</code> - non-hierarchical keywords or terms for describing them. The tags are
* used to filter the templates. This method is used for getting the assign tags to this Template.
* This method is used for getting the assigned <code>tags</code> to this Template. The <code>tags</code> are
* non-hierarchical keywords or terms that are used for describing the template and to filter the templates.
*
* @return tags of the template
* @return tags that is a set of non-hierarchical keywords or terms, describing the template.
*/
@Override
public Set<String> getTags() {
return new HashSet<String>(tags);
return tags != null ? tags : Collections.<String> emptySet();
}
/**
* Templates can have <li><code>tags</code> - non-hierarchical keywords or terms for describing them. The tags are
* used to filter the templates. This method is used for assigning tags to this Template.
* This method is used for getting the label of the Template.
*
* @param tags set of tags assign to the template.
*/
@Override
public void setTags(Set<String> tags) {
tags = new HashSet<String>(tags);
}
/**
* This method is used for getting the label of the Template. The label is a
* short, user friendly name of the Template defined by this descriptor.
*
* @return the label of the Template.
* @return the short, user friendly name of the Template.
*/
@Override
public String getLabel() {
return label;
}
/**
* This method is used for setting the label of the Template. The label is a
* short, user friendly name of the Template defined by this descriptor.
*
* @param label of the Template.
*/
@Override
public void setLabel(String label) {
this.label = label;
}
/**
* This method is used for getting the description of the Template. The
* description is a long, user friendly description of the Template defined by
* this descriptor.
* description is a long, user friendly description of the Rule defined by
* this Template.
*
* @return the description of the Template.
*/
@ -137,18 +156,6 @@ public class RuleTemplate implements Template {
return description;
}
/**
* This method is used for setting the description of the Template. The
* description is a long, user friendly description of the Template defined by
* this descriptor.
*
* @param description of the Template.
*/
@Override
public void setDescription(String description) {
this.description = description;
}
/**
* This method is used to show visibility of the template
*
@ -156,18 +163,20 @@ public class RuleTemplate implements Template {
*/
@Override
public Visibility getVisibility() {
if (visibility == null) {
return Visibility.VISIBLE;
}
return visibility;
}
/**
* This method is used for getting the Set with {@link ConfigDescriptionParameter}s defining meta info for
* configuration
* properties of the Rule.<br/>
* configuration properties of the Rule.
*
* @return a {@link Set} of {@link ConfigDescriptionParameter}s.
*/
public Set<ConfigDescriptionParameter> getConfigurationDescription() {
return new HashSet<ConfigDescriptionParameter>(configDescriptions);
public List<ConfigDescriptionParameter> getConfigurationDescription() {
return configDescriptions != null ? configDescriptions : Collections.<ConfigDescriptionParameter> emptyList();
}
/**
@ -189,15 +198,34 @@ public class RuleTemplate implements Template {
* specified.
*/
@SuppressWarnings("unchecked")
public <T extends Module> List<T> getModules(Class<T> clazz) {
if (clazz == Trigger.class) {
return (List<T>) triggers;
} else if (clazz == Condition.class) {
return (List<T>) conditions;
} else if (clazz == Action.class) {
return (List<T>) actions;
@Deprecated
public <T extends Module> List<T> getModules(Class<T> moduleClazz) {
List<T> result = null;
if (moduleClazz == null) {
result = new ArrayList<T>();
result.addAll((Collection<? extends T>) triggers);
result.addAll((Collection<? extends T>) conditions);
result.addAll((Collection<? extends T>) actions);
} else if (Trigger.class == moduleClazz) {
result = (List<T>) triggers;
} else if (Condition.class == moduleClazz) {
result = (List<T>) conditions;
} else if (Action.class == moduleClazz) {
result = (List<T>) actions;
}
return null;
return result != null ? result : Collections.<T> emptyList();
}
public List<Trigger> getTriggers() {
return triggers != null ? triggers : Collections.<Trigger> emptyList();
}
public List<Condition> getConditions() {
return conditions != null ? conditions : Collections.<Condition> emptyList();
}
public List<Action> getActions() {
return actions != null ? actions : Collections.<Action> emptyList();
}
}

Просмотреть файл

@ -1,20 +1,16 @@
/*******************************************************************************
* Copyright (c) 1997, 2015 by ProSyst Software GmbH
* http://www.prosyst.com
/**
* 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
*
* Contributors:
* ProSyst Software GmbH - initial API and implementation
*******************************************************************************/
*/
package org.eclipse.smarthome.automation.template;
import java.util.Set;
import org.eclipse.smarthome.automation.Rule;
import org.eclipse.smarthome.automation.Visibility;
/**
* The templates define types of shared, ready to use rule definitions, which
@ -26,23 +22,12 @@ import org.eclipse.smarthome.automation.Rule;
* <p>
* Templates can have <code>tags</code> - non-hierarchical keywords or terms for describing them.
*
* @author Yordan Mihaylov, Ana Dimova, Vasil Ilchev - Initial Contribution
* @author Yordan Mihaylov - Initial Contribution
* @author Ana Dimova - Initial Contribution
* @author Vasil Ilchev - Initial Contribution
*/
public interface Template {
public enum Visibility {
/**
* The template is visible by everyone.
*/
PUBLIC,
/**
* The template is visible only by its creator.
*/
PRIVATE
}
/**
* This method is used for getting the type of Template. It is unique in scope
* of RuleEngine.
@ -52,21 +37,14 @@ public interface Template {
public String getUID();
/**
* Templates can have <li><code>tags</code> - non-hierarchical keywords or terms for describing them. The tags are
* Templates can have
* <li><code>tags</code> - non-hierarchical keywords or terms for describing them. The tags are
* used to filter the templates. This method is used for getting the assign tags to this Template.
*
* @return tags of the template
*/
public Set<String> getTags();
/**
* Templates can have <li><code>tags</code> - non-hierarchical keywords or terms for describing them. The tags are
* used to filter the templates. This method is used for assigning tags to this Template.
*
* @param tags set of tags assign to the template.
*/
public void setTags(Set<String> tags);
/**
* This method is used for getting the label of the Template. The label is a
* short, user friendly name of the Template defined by this descriptor.
@ -75,14 +53,6 @@ public interface Template {
*/
public String getLabel();
/**
* This method is used for setting the label of the Template. The label is a
* short, user friendly name of the Template defined by this descriptor.
*
* @param label of the Template.
*/
public void setLabel(String label);
/**
* This method is used for getting the description of the Template. The
* description is a long, user friendly description of the Template defined by
@ -92,15 +62,6 @@ public interface Template {
*/
public String getDescription();
/**
* This method is used for setting the description of the Template. The
* description is a long, user friendly description of the Template defined by
* this descriptor.
*
* @param description of the Template.
*/
public void setDescription(String description);
/**
* This method is used to show visibility of the template
*

Просмотреть файл

@ -1,15 +1,10 @@
/*******************************************************************************
* Copyright (c) 1997, 2015 by ProSyst Software GmbH
* http://www.prosyst.com
/**
* 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
*
* Contributors:
* ProSyst Software GmbH - initial API and implementation
*******************************************************************************/
*/
package org.eclipse.smarthome.automation.template;
import java.util.Collection;
@ -19,10 +14,18 @@ import java.util.Locale;
* This interface has to be implemented by all providers of {@link Template}s.
* The {@link TemplateRegistry} uses it to get access to available {@link Template} s.
*
* @author Yordan Mihaylov
* @author Yordan Mihaylov - Initial Contribution
* @author Kai Kreuzer - refactored (managed) provider and registry implementation
* @author Ana Dimova - add registration property - rule.templates
*/
public interface TemplateProvider {
/**
* This constant is used as registration property for Rule Templates Provider when the provider expects to modify
* the provided objects dynamically. Its value is a set of current provided rule template UIDs.
*/
public static final String REG_PROPERTY_RULE_TEMPLATES = "rule.templates";
/**
* This method is used to get localized Template. When the localization is not
* specified or it is not supported a Template with default locale is
@ -32,7 +35,7 @@ public interface TemplateProvider {
* @param locale defines localization of label and description of the {@link Template} or null.
* @return localized Template.
*/
Template getTemplate(String UID, Locale locale);
<T extends Template> T getTemplate(String UID, Locale locale);
/**
* This method is used to get localized Templates defined by this provider.
@ -42,6 +45,6 @@ public interface TemplateProvider {
* @param locale defines localization of label and description of the {@link Template}s or null.
* @return collection of localized {@link Template} provided by this provider
*/
Collection<Template> getTemplates(Locale locale);
<T extends Template> Collection<T> getTemplates(Locale locale);
}

Просмотреть файл

@ -1,19 +1,15 @@
/*******************************************************************************
* Copyright (c) 1997, 2015 by ProSyst Software GmbH
* http://www.prosyst.com
/**
* 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
*
* Contributors:
* ProSyst Software GmbH - initial API and implementation
*******************************************************************************/
*/
package org.eclipse.smarthome.automation.template;
import java.util.Collection;
import java.util.Locale;
import java.util.Set;
/**
* This interface provides functionality to get available {@link Template}s. The {@link Template} can be returned
@ -21,10 +17,21 @@ import java.util.Locale;
* When the parameter is not specified or there is no such localization
* resources the returned template is localized with default locale.
*
* @author Yordan Mihaylov, Ana Dimova, Vasil Ilchev - Initial Contribution
* @author Yordan Mihaylov - Initial Contribution
* @author Ana Dimova - Initial Contribution
* @author Vasil Ilchev - Initial Contribution
*/
public interface TemplateRegistry {
/**
* This method is used to get template of specified by type.
*
* @param uid the an unique id in scope of registered templates
* @param locale user locale
* @return template instance or null.
*/
public <T extends Template> T get(String uid);
/**
* This method is used to get template of specified by type.
*
@ -34,6 +41,14 @@ public interface TemplateRegistry {
*/
public <T extends Template> T get(String uid, Locale locale);
/**
* This method is used for getting the templates filtered by tag.
*
* @param tag specifies the filter for getting the templates, if it is <code>null</code> then returns all templates.
* @return the templates, which correspond to the specified filter.
*/
public <T extends Template> Collection<T> getByTag(String tag);
/**
* This method is used for getting the templates filtered by tag.
*
@ -43,12 +58,37 @@ public interface TemplateRegistry {
public <T extends Template> Collection<T> getByTag(String tag, Locale locale);
/**
* This method is used for getting the templates, specified by type module,
* i.e. {@link ActionTemplate}, {@link ConditionTemplate}, {@link TriggerTemplate} and etc.
* This method is used for getting the templates filtered by tags.
*
* @param tags set of tags which specifies the filter for getting the templates, if it is <code>null</code> then
* returns all templates.
* @return collection of templates, which correspond to the filter.
*/
public <T extends Template> Collection<T> getByTags(Set<String> tags);
/**
* This method is used for getting the templates filtered by tags.
*
* @param tags set of tags which specifies the filter for getting the templates, if it is <code>null</code> then
* returns all templates.
* @return the templates, which correspond to the the filter.
*/
public <T extends Template> Collection<T> getByTags(Set<String> tags, Locale locale);
/**
* This method is used for getting all templates, localized by specified locale,
*
* @param moduleType the class of module which is looking for.
* @return collection of templates, corresponding to specified type
*/
public <T extends Template> Collection<T> get(Class<T> moduleType, Locale locale);
public <T extends Template> Collection<T> getAll();
/**
* This method is used for getting all templates, localized by specified locale,
*
* @param moduleType the class of module which is looking for.
* @return collection of templates, corresponding to specified type
*/
public <T extends Template> Collection<T> getAll(Locale locale);
}

Просмотреть файл

@ -1,84 +1,116 @@
/*******************************************************************************
* Copyright (c) 1997, 2015 by ProSyst Software GmbH
* http://www.prosyst.com
/**
* 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
*
* Contributors:
* ProSyst Software GmbH - initial API and implementation
*******************************************************************************/
*/
package org.eclipse.smarthome.automation.type;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.eclipse.smarthome.automation.Action;
import org.eclipse.smarthome.automation.Rule;
import org.eclipse.smarthome.automation.Module;
import org.eclipse.smarthome.automation.Visibility;
import org.eclipse.smarthome.config.core.ConfigDescriptionParameter;
/**
* This interface provides common functionality for creating {@link Action} instances. The actions are part of "THEN"
* section of the {@link Rule}. Each
* action ModuleType is defined by unique id and defines meta info for {@link ConfigDescriptionParameter}s,
* {@link Input}s and {@link Output}s of
* created {@link Action} instances.
* This class provides common functionality for creating {@link Action} instances by supplying types with their
* meta-information. The {@link Action}s are part of "THEN" section of the Rule. Each {@link ActionType} is defined by
* unique id in scope of the RuleEngine and defines {@link ConfigDescriptionParameter}s that are meta-information for
* configuration and meta-information for {@link Input}s and {@link Output}s used for creation of {@link Action}
* instances.
*
* @author Yordan Mihaylov, Ana Dimova, Vasil Ilchev - Initial Contribution
* @author Yordan Mihaylov - Initial Contribution
* @author Ana Dimova - Initial Contribution
* @author Vasil Ilchev - Initial Contribution
*/
public class ActionType extends ModuleType {
private Set<Input> inputs;
private Set<Output> outputs;
/**
* This field contains meta-information describing the incoming connections of the {@link Action} module to the
* other {@link Module}s.
*/
private List<Input> inputs;
/**
* Constructor of ActionDescriptor.
*
* @param UID unique id of action type
*
* @param configDescriptions is a {@link Set} of configuration descriptions.
* @param inputs is a {@link Set} of {@link Input} definitions.
* This field contains meta-information describing the outgoing connections of the {@link Action} module to the
* other {@link Action}s.
*/
public ActionType(String UID, Set<ConfigDescriptionParameter> configDescriptions, Set<Input> inputs) {
private List<Output> outputs;
/**
* This constructor is responsible to create an instance of {@link ActionType} with base properties - UID, a
* {@link List} of configuration descriptions and a {@link List} of {@link Input} definitions.
*
* @param UID is an unique id of the {@link ActionType}, used as reference from the {@link Module}s, to find their
* meta-information.
* @param configDescriptions is a {@link List} of meta-information configuration descriptions.
* @param inputs is a {@link List} of {@link Input} meta-information descriptions.
*/
public ActionType(String UID, List<ConfigDescriptionParameter> configDescriptions, List<Input> inputs) {
this(UID, configDescriptions, inputs, null);
}
/**
* Default constructor of ActionDescriptor. Constructs an empty
* ActionDescriptor.
* This constructor is responsible to create an instance of the {@link ActionType} with UID, a {@link List} of
* configuration descriptions, a {@link List} of {@link Input} definitions and a {@link List} of {@link Output}
* descriptions.
*
* @param UID unique id of action type
*
* @param configDescriptions is a {@link Set} of configuration descriptions.
* @param inputs is a {@link Set} of {@link Input} definitions.
* @param outputs is a {@link Set} of {@link Output} definitions.
* @param UID is an unique id of the {@link ActionType}, used as reference from the {@link Module}s, to find their
* meta-information.
* @param configDescriptions is a {@link List} of meta-information configuration descriptions.
* @param inputs is a {@link List} of {@link Input} meta-information descriptions.
* @param outputs is a {@link List} of {@link Output} meta-information descriptions.
*/
public ActionType(String UID, Set<ConfigDescriptionParameter> configDescriptions, Set<Input> inputs,
Set<Output> outputs) {
public ActionType(String UID, List<ConfigDescriptionParameter> configDescriptions, List<Input> inputs,
List<Output> outputs) {
super(UID, configDescriptions);
this.inputs = inputs;
this.outputs = outputs;
}
/**
* This method is used for getting the meta info of inputs defined by this
* descriptor.<br/>
* This constructor is responsible to create an instance of {@link ActionType} with UID, label, description, a
* {@link Set} of tags, visibility, a {@link List} of configuration descriptions, a {@link List} of {@link Input}
* descriptions and a {@link List} of {@link Output} descriptions.
*
* @return a {@link Set} of {@link Input} definitions.
* @param UID unique id of the {@link ActionType}.
* @param configDescriptions is a {@link List} of meta-information configuration descriptions.
* @param label is a short and accurate name of the {@link ActionType}.
* @param description is a short and understandable description of which can be used the {@link ActionType}.
* @param tags defines categories that fit the {@link ActionType} and which can serve as criteria for searching
* or filtering it.
* @param visibility determines whether the {@link ActionType} can be used by anyone if it is
* {@link Visibility#VISIBLE} or only by its creator if it is {@link Visibility#HIDDEN}.
* @param inputs is a {@link List} of {@link Input} meta-information descriptions.
* @param outputs is a {@link List} of {@link Output} meta-information descriptions.
*/
public Set<Input> getInputs() {
return inputs;
public ActionType(String UID, List<ConfigDescriptionParameter> configDescriptions, String label, String description,
Set<String> tags, Visibility visibility, List<Input> inputs, List<Output> outputs) {
super(UID, configDescriptions, label, description, tags, visibility);
this.inputs = inputs;
this.outputs = outputs;
}
/**
* This method is used for getting the meta info of outputs defined by this
* descriptor.<br/>
* This method is used for getting the meta-information descriptions of {@link Input}s defined by this type.<br/>
*
* @return a {@link Set} of {@link Output} definitions.
* @return a {@link List} of {@link Input} definitions.
*/
public Set<Output> getOutputs() {
return outputs;
public List<Input> getInputs() {
return inputs != null ? inputs : Collections.<Input> emptyList();
}
/**
* This method is used for getting the meta-information descriptions of {@link Output}s defined by this type.<br/>
*
* @return a {@link List} of {@link Output} definitions.
*/
public List<Output> getOutputs() {
return outputs != null ? outputs : Collections.<Output> emptyList();
}
}

Просмотреть файл

@ -1,57 +1,85 @@
/*******************************************************************************
* Copyright (c) 1997, 2015 by ProSyst Software GmbH
* http://www.prosyst.com
/**
* 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
*
* Contributors:
* ProSyst Software GmbH - initial API and implementation
*******************************************************************************/
*/
package org.eclipse.smarthome.automation.type;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.smarthome.automation.Action;
import org.eclipse.smarthome.automation.Module;
import org.eclipse.smarthome.automation.Visibility;
import org.eclipse.smarthome.config.core.ConfigDescriptionParameter;
/**
* CompositeActionType is as {@link ActionType} which logically combines {@link Action} instances. The composite action
* hides internal logic and inner
* connections between participating actions and it can be used as a regular {@link Action} module.
* {@code CompositeActionType} is as {@link ActionType} which logically combines {@link Action} instances. The composite
* action hides internal logic and inner connections between participating {@link Action}s and it can be used as a
* regular
* {@link Action} module.
*
* @author Yordan Mihaylov - Initial Contribution
* @author Ana Dimova - Initial Contribution
* @author Vasil Ilchev - Initial Contribution
*/
public class CompositeActionType extends ActionType {
private List<Action> modules;
private List<Action> children;
/**
* Creates a CompositeActionType with ordered set of {@link Action}s
*
* @param UID unique id of this module type
* @param configDescriptions is a {@link Set} of configuration descriptions.
* @param modules LinkedHashSet of {@link Module}(s)
* @param inputs is a {@link Set} of {@link Input} definitions.
* @param outputs is a {@link Set} of {@link Output} definitions.
* This constructor is responsible for creation of a {@code CompositeActionType} with ordered set of {@link Action}
* s.
* It initialize only base properties of the {@code CompositeActionType}.
*
* @param UID is the unique id of this module type in scope of the RuleEngine.
* @param configDescriptions is a {@link List} of configuration descriptions.
* @param children is a {@link LinkedHashSet} of {@link Action}s.
* @param inputs is a {@link List} of {@link Input} descriptions.
* @param outputs is a {@link List} of {@link Output} descriptions.
*/
public CompositeActionType(String UID, Set<ConfigDescriptionParameter> configDescriptions, Set<Input> inputs,
Set<Output> outputs, List<Action> modules) {
public CompositeActionType(String UID, List<ConfigDescriptionParameter> configDescriptions, List<Input> inputs,
List<Output> outputs, List<Action> children) {
super(UID, configDescriptions, inputs, outputs);
this.modules = modules;
this.children = children;
}
/**
* This method is used for getting Actions of the CompositeActionDescriptor.
* This constructor is responsible for creation of a {@code CompositeActionType} with ordered set of {@link Action}
* s.
* It initialize all properties of the {@code CompositeActionType}.
*
* @return ordered set of modules of this CompositeActionDescriptor
* @param UID is the unique id of this module type in scope of the RuleEngine.
* @param configDescriptions is a {@link List} of configuration descriptions.
* @param label is a short and accurate name of the {@code CompositeActionType}.
* @param description is a short and understandable description of which can be used the {@code CompositeActionType}
* .
* @param tags defines categories that fit the {@code CompositeActionType} and which can serve as criteria for
* searching
* or filtering it.
* @param visibility determines whether the {@code CompositeActionType} can be used by anyone if it is
* {@link Visibility#VISIBLE} or only by its creator if it is {@link Visibility#HIDDEN}.
* @param inputs is a {@link List} of {@link Input} descriptions.
* @param outputs is a {@link List} of {@link Output} descriptions.
* @param children is a {@link LinkedHashSet} of {@link Action}s.
*/
public List<Action> getModules() {
return modules;
public CompositeActionType(String UID, List<ConfigDescriptionParameter> configDescriptions, String label,
String description, Set<String> tags, Visibility visibility, List<Input> inputs, List<Output> outputs,
List<Action> children) {
super(UID, configDescriptions, label, description, tags, visibility, inputs, outputs);
this.children = children;
}
/**
* This method is used for getting the {@link Action}s of the {@code CompositeActionType}.
*
* @return a {@link LinkedHashSet} of the {@link Action} modules of this {@code CompositeActionType}.
*/
public List<Action> getChildren() {
return children != null ? children : Collections.<Action> emptyList();
}
}

Просмотреть файл

@ -1,58 +1,81 @@
/*******************************************************************************
* Copyright (c) 1997, 2015 by ProSyst Software GmbH
* http://www.prosyst.com
/**
* 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
*
* Contributors:
* ProSyst Software GmbH - initial API and implementation
*******************************************************************************/
*/
package org.eclipse.smarthome.automation.type;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.smarthome.automation.Condition;
import org.eclipse.smarthome.automation.Trigger;
import org.eclipse.smarthome.automation.Visibility;
import org.eclipse.smarthome.config.core.ConfigDescriptionParameter;
/**
* CompositeConditionType is as {@link ConditionType} which logically combines {@link Condition} modules. The composite
* condition hides internal logic
* between participating conditions and it can be used as a regular {@link Condition} module.
* {@code CompositeConditionType} is as {@link ConditionType} which logically combines {@link Condition} modules. The
* composite condition hides internal logic between participating conditions and it can be used as a regular
* {@link Condition} module.
*
* @author Yordan Mihaylov - Initial Contribution
* @author Ana Dimova - Initial Contribution
* @author Vasil Ilchev - Initial Contribution
*/
public class CompositeConditionType extends ConditionType {
private List<Condition> modules;
private List<Condition> children;
/**
* Creates a CompositeTriggerDescriptor with ordered set of {@link Trigger}s
*
* @param UID unique id of composite condition module type
* This constructor is responsible for creation of a {@code CompositeConditionType} with ordered set of
* {@link Condition}s.
* It initialize only base properties of the {@code CompositeConditionType}.
*
* @param UID is the unique id of this module type in scope of the RuleEngine.
* @param configDescriptions is a {@link Set} of configuration descriptions.
* @param modules is an ordered list of {@link Trigger}(s)
* @param inputs is a {@link Set} of {@link Input} definitions.
*
* @param children is a LinkedHashSet of {@link Condition}s.
* @param inputs is a {@link Set} of {@link Input} descriptions.
*/
public CompositeConditionType(String UID, Set<ConfigDescriptionParameter> configDescriptions, Set<Input> inputs,
List<Condition> modules) {
public CompositeConditionType(String UID, List<ConfigDescriptionParameter> configDescriptions, List<Input> inputs,
List<Condition> children) {
super(UID, configDescriptions, inputs);
this.modules = modules;
this.children = children;
}
/**
* This method is used for getting Conditions of the CompositeCoditionType.
* This constructor is responsible for creation of a {@code CompositeConditionType} with ordered set of
* {@link Condition}s.
* It initialize all properties of the {@code CompositeConditionType}.
*
* @return ordered set of Condition of this CompositeCoditionType.
* @param UID is the unique id of this module type in scope of the RuleEngine.
* @param configDescriptions is a {@link List} of configuration descriptions.
* @param label is a short and accurate name of the {@code CompositeConditionType}.
* @param description is a short and understandable description of which can be used the
* {@code CompositeConditionType}.
* @param tags defines categories that fit the {@code CompositeConditionType} and which can serve as criteria for
* searching
* or filtering it.
* @param visibility determines whether the {@code CompositeConditionType} can be used by anyone if it is
* {@link Visibility#VISIBLE} or only by its creator if it is {@link Visibility#HIDDEN}.
* @param inputs is a {@link List} of {@link Input} descriptions.
* @param children is a {@link LinkedHashSet} of {@link Condition}s.
*/
public List<Condition> getModules() {
return modules;
public CompositeConditionType(String UID, List<ConfigDescriptionParameter> configDescriptions, String label,
String description, Set<String> tags, Visibility visibility, List<Input> inputs, List<Condition> children) {
super(UID, configDescriptions, label, description, tags, visibility, inputs);
this.children = children;
}
/**
* This method is used for getting Conditions of the {@code CompositeConditionType}.
*
* @return a {@link LinkedHashSet} of the {@link Condition} modules of this {@code CompositeConditionType}.
*/
public List<Condition> getChildren() {
return children != null ? children : Collections.<Condition> emptyList();
}
}

Просмотреть файл

@ -1,57 +1,82 @@
/*******************************************************************************
* Copyright (c) 1997, 2015 by ProSyst Software GmbH
* http://www.prosyst.com
/**
* 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
*
* Contributors:
* ProSyst Software GmbH - initial API and implementation
*******************************************************************************/
*/
package org.eclipse.smarthome.automation.type;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.smarthome.automation.Trigger;
import org.eclipse.smarthome.automation.Visibility;
import org.eclipse.smarthome.config.core.ConfigDescriptionParameter;
/**
* CompositeTriggerType is as {@link TriggerType} which logically combines {@link Trigger} modules. The composite
* trigger hides internal logic between
* participating actions and it can be used as a regular {@link Trigger} module.
* {@code CompositeTriggerType} is as {@link TriggerType} which logically combines {@link Trigger} modules. The
* composite trigger hides internal logic between participating {@link Trigger}s and it can be used as a regular
* {@link Trigger} module.
*
* @author Yordan Mihaylov - Initial Contribution
* @author Ana Dimova - Initial Contribution
* @author Vasil Ilchev - Initial Contribution
*/
public class CompositeTriggerType extends TriggerType {
private List<Trigger> modules;
private List<Trigger> children;
/**
* Creates a CompositeTriggerType with ordered set of {@link Trigger}s
*
* @param UID unique id of this composite trigger type.
* This constructor is responsible for creation of a {@code CompositeTriggerType} with ordered set of
* {@link Trigger}s.
* It initialize only base properties of the {@code CompositeTriggerType}.
*
* @param UID is the unique id of this module type in scope of the RuleEngine.
* @param configDescriptions is a {@link Set} of configuration descriptions.
* @param modules is an ordered list of {@link Trigger}(s)
* @param outputs is a {@link Set} of {@link Output} definitions.
* @param children is a {@link LinkedHashSet} of {@link Trigger}s.
* @param outputs is a {@link Set} of {@link Output} descriptions.
*
*/
public CompositeTriggerType(String UID, Set<ConfigDescriptionParameter> configDescriptions, Set<Output> outputs,
List<Trigger> modules) {
public CompositeTriggerType(String UID, List<ConfigDescriptionParameter> configDescriptions, List<Output> outputs,
List<Trigger> children) {
super(UID, configDescriptions, outputs);
this.modules = modules;
this.children = children;
}
/**
* This method is used for getting Triggers of the CompositeTriggerDescriptor.
* This constructor is responsible for creation of a {@code CompositeTriggerType} with ordered set of
* {@link Trigger}s.
* It initialize all properties of the {@code CompositeTriggerType}.
*
* @return ordered set of Triggers defined by CompositeTriggerType
* @param UID is the unique id of this module type in scope of the RuleEngine.
* @param configDescriptions is a {@link Set} of configuration descriptions.
* @param label is a short and accurate name of the {@code CompositeTriggerType}.
* @param description is a short and understandable description of which can be used the {@code CompositeActionType}
* .
* @param tags defines categories that fit the {@code CompositTriggerType} and which can serve as criteria for
* searching
* or filtering it.
* @param visibility determines whether the {@code CompositeTriggerType} can be used by anyone if it is
* {@link Visibility#VISIBLE} or only by its creator if it is {@link Visibility#HIDDEN}.
* @param outputs is a {@link Set} of {@link Output} descriptions.
* @param children is a {@link LinkedHashSet} of {@link Trigger}s.
*/
public List<Trigger> getModules() {
return modules;
public CompositeTriggerType(String UID, List<ConfigDescriptionParameter> configDescriptions, String label,
String description, Set<String> tags, Visibility visibility, List<Output> outputs, List<Trigger> children) {
super(UID, configDescriptions, label, description, tags, visibility, outputs);
this.children = children;
}
/**
* This method is used for getting the {@link Trigger}s of the {@code CompositeTriggerType}.
*
* @return a {@link LinkedHashSet} of the {@link Trigger} modules of this {@code CompositeTriggerType}.
*/
public List<Trigger> getChildren() {
return children != null ? children : new ArrayList<Trigger>(0);
}
}

Просмотреть файл

@ -1,56 +1,77 @@
/*******************************************************************************
* Copyright (c) 1997, 2015 by ProSyst Software GmbH
* http://www.prosyst.com
/**
* 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
*
* Contributors:
* ProSyst Software GmbH - initial API and implementation
*******************************************************************************/
*/
package org.eclipse.smarthome.automation.type;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.eclipse.smarthome.automation.Condition;
import org.eclipse.smarthome.automation.Module;
import org.eclipse.smarthome.automation.Visibility;
import org.eclipse.smarthome.config.core.ConfigDescriptionParameter;
/**
* This class is used to define condition types. The condition types contains
* meta info of the {@link Condition} instances. Each condition type has unique
* id in scope of the rule engine and defines {@link ConfigDescriptionParameter} s and {@link Input}s of the
* {@link Condition} instance.
* This class provides common functionality for creating {@link Condition} instances by supplying types with their
* meta-information. The {@link Condition}s are part of "IF" section of the Rule. Each {@link ConditionType} is defined
* by unique id in scope of the RuleEngine and defines {@link ConfigDescriptionParameter}s that are meta-information for
* configuration and meta-information for {@link Input}s used for creation of {@link Condition} instances.
*
* @author Yordan Mihaylov, Ana Dimova, Vasil Ilchev - Initial Contribution
* @author Yordan Mihaylov - Initial Contribution
* @author Ana Dimova - Initial Contribution
* @author Vasil Ilchev - Initial Contribution
*/
public class ConditionType extends ModuleType {
private Set<Input> inputs;
private List<Input> inputs;
/**
* Constructor of condition type.
*
* @param UID unique id of the condition type.
*
* @param configDescriptions is a {@link Set} of configuration descriptions.
* @param inputs is a {@link Set} of {@link Input} definitions.
* @param visibility defines if this type can be used by other users.
* This constructor is responsible to create an instance of {@link ConditionType} with base properties - UID, a
* {@link List} of configuration descriptions and a {@link List} of {@link Input} descriptions.
*
* @param UID is an unique id of the {@link ActionType}, used as reference from the {@link Module}s, to find their
* meta-information.
* @param configDescriptions is a {@link List} of meta-information configuration descriptions.
* @param inputs is a {@link List} of {@link Input} meta-information descriptions.
*/
public ConditionType(String UID, Set<ConfigDescriptionParameter> configDescriptions, Set<Input> inputs) {
public ConditionType(String UID, List<ConfigDescriptionParameter> configDescriptions, List<Input> inputs) {
super(UID, configDescriptions);
this.inputs = inputs;
}
/**
* This method is used for getting the meta info of inputs defined by this
* module type.
* This constructor is responsible to create an instance of {@link ConditionType} with UID, label, description, a
* {@link Set} of tags, visibility, a {@link List} of configuration descriptions and a {@link List} of {@link Input}
* descriptions.
*
* @return a {@link Set} of {@link Input} definitions.
* @param UID unique id of the {@link ConditionType}.
* @param configDescriptions is a {@link List} of meta-information configuration descriptions.
* @param label is a short and accurate name of the {@link ConditionType}.
* @param description is a short and understandable description of which can be used the {@link ConditionType}.
* @param tags defines categories that fit the {@link ConditionType} and which can serve as criteria for searching
* or filtering it.
* @param visibility determines whether the {@link ConditionType} can be used by anyone if it is
* {@link Visibility#VISIBLE} or only by its creator if it is {@link Visibility#HIDDEN}.
* @param inputs is a {@link List} of {@link Input} meta-information descriptions.
*/
public Set<Input> getInputs() {
return inputs;
public ConditionType(String UID, List<ConfigDescriptionParameter> configDescriptions, String label,
String description, Set<String> tags, Visibility visibility, List<Input> inputs) {
super(UID, configDescriptions, label, description, tags, visibility);
this.inputs = inputs;
}
/**
* This method is used for getting the meta-information descriptions of {@link Input}s defined by this
* {@link ConditionType}.
*
* @return a {@link List} of {@link Input} meta-information descriptions.
*/
public List<Input> getInputs() {
return inputs != null ? inputs : Collections.<Input> emptyList();
}
}

Просмотреть файл

@ -1,25 +1,21 @@
/*******************************************************************************
* Copyright (c) 1997, 2015 by ProSyst Software GmbH
* http://www.prosyst.com
/**
* 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
*
* Contributors:
* ProSyst Software GmbH - initial API and implementation
*******************************************************************************/
*/
package org.eclipse.smarthome.automation.type;
import java.util.Collections;
import java.util.Set;
import org.eclipse.smarthome.automation.Module;
import org.eclipse.smarthome.automation.Rule;
/**
* This class defines meta info which is used by the RuleEngine when creating
* connection between modules. The meta info contains:
* This class defines meta-information which is used by the RuleEngine when creating connection between modules. The
* meta-information contains:
* <ul>
* <li>name(mandatory) - unequal id in scope of containing Module</li>
* <li>type(mandatory) - accepted data type by this Parameter</li>
@ -36,48 +32,69 @@ import org.eclipse.smarthome.automation.Rule;
*/
public class Input {
/**
* is an unique name of the {@code Input} in scope of the {@link Module}.
*/
private String name;
/**
* This field specifies the type of the {@code Input}. The accepted types are all java types defined by fully
* qualified names.
*/
private String type;
/**
* This field keeps a single word description of the {@code Input}.
*/
private String label;
/**
* This field keeps the user friendly description of the {@code Input}.
*/
private String description;
/**
* This field determines if the {@code Input} is required or optional.
*/
private boolean required = false;
private Set<String> tags;
private String reference;
private Object defaultValue;
/**
* Constructor of Input object. Creates Input base on type of accepted data
* and input name
* Constructor of the {@code Input} object. Creates Input base on type of accepted data and {@code Input}'s name.
*
* @param type data type accepted by this Input. The accepted types are any
* java types defined by fully qualified names.
* @param type data type accepted by this Input. The accepted types are any java types defined by fully qualified
* names.
* @param name unique name of the Input.
*/
public Input(String name, String type) {
this(name, type, null, null, null, false, null);
this(name, type, null, null, null, false, null, null);
}
/**
* Constructor of Input object. Creates Input base on type of accepted data
* and input name
*
* @param type data type accepted by this Input.;
* @param name unique name of the Input.
* @param label a single word description of the Input.
* @param description user friendly description of the Input.
* @param tags tags associated with the Input. The tags adds additional
* restrictions to connections between {@link Input}s and {@link Output}s. The input tags must be subset
* of the output tags
* to succeed the connection.</br> For example: When we want to
* connect input to output and both have same java.lang.double data
* type. The the output has assign "temperature" and "celsius" tags
* then the input must have at least one of these output's tags (i.e.
* "temperature") to connect this input to the selected output.
* @param required determining if the Input is required or optional
* @param defaultValue default value takes place when there is no value for
* this Input. Type of the default value must be the type the Input.
* @param type data type accepted by this {@code Input}.
* @param name unique name of the {@code Input}.
* @param label a single word description of the {@code Input}.
* @param description user friendly description of the {@code Input}.
* @param tags are associated with the {@code Input}. The tags adds additional restrictions to connections between
* {@code Input}s and {@link Output}s. The input tags must be subset of the output tags to succeed the
* connection.</br>
* For example: When we want to connect input to output and both have same
* java.lang.double data type. The the output has assign "temperature" and "celsius" tags then the input
* must have at least one of these output's tags (i.e. "temperature") to connect this {@code Input} to
* the selected output.
* @param required determines if the {@code Input} is required or optional.
* @param reference refers to the input of parent module type or null. If this input is part of the system module
* the reference should be null.
* @param defaultValue default value takes place when there is no value for this Input. Type of the default value
* must be the type the Input.
*/
public Input(String name, String type, String label, String description, Set<String> tags, boolean required,
Object defaultValue) {
String reference, Object defaultValue) {
if (name == null)
throw new IllegalArgumentException("The name of the input must not be NULL!");
this.name = name;
@ -86,12 +103,12 @@ public class Input {
this.description = description;
this.tags = tags;
this.required = required;
this.reference = reference;
this.defaultValue = defaultValue;
}
/**
* This method is used for getting the name of Input. It must be unique in
* scope of {@link Rule}.
* This method is used for getting the name of Input. It must be unique in scope of the {@link Rule}.
*
* @return name is an unique identifier of the Input.
*/
@ -100,8 +117,8 @@ public class Input {
}
/**
* This method is used for getting the short description of the Input. Usually
* the label should be a single word description.
* This method is used for getting the short description of the Input. Usually the label should be a single word
* description.
*
* @return label of the Input.
*/
@ -128,8 +145,8 @@ public class Input {
}
/**
* This method is used for getting the type of the Input. The accepted types
* are all java types defined by fully qualified names.
* This method is used for getting the type of the Input. The accepted types are all java types defined by fully
* qualified names.
*
* @return type is a fully qualified name of java type.
*/
@ -138,25 +155,32 @@ public class Input {
}
/**
* This method is used for getting the tags of the Input. The tags adds
* additional restrictions to connections between {@link Input}s and {@link Output}s. The input tags must be subset
* of the output tags to
* succeed the connection.</br> For example: When we want to connect input to
* output and they both have same java.lang.double data type, and the output
* has assign "temperature" and "celsius" tags then the input must have at
* least one of these output's tags (i.e. "temperature") to connect this input
* to the selected output.
* This method is used for getting the tags of the Input. The tags adds additional restrictions to connections
* between {@link Input}s and {@link Output}s. The input tags must be subset of the output tags to succeed the
* connection.</br>
* For example: When we want to connect input to output and they both have same java.lang.double
* data type, and the output has assign "temperature" and "celsius" tags then the input must have at least one of
* these output's tags (i.e. "temperature") to connect this input to the selected output.
*
* @return tags associated with this Input.
*/
public Set<String> getTags() {
return tags;
return tags != null ? tags : Collections.<String> emptySet();
}
/**
* This method is used for getting the default value of the Input. Default
* value takes place when there is no value for this Input. Type of the
* default value must be the type the Input.
* This method is used for getting the reference to data source. It is used to link custom inputs (inputs of custom
* module type) to system input (defined by the system module type. The system module type uses only system inputs).
*
* @return reference to data source.
*/
public String getReference() {
return reference;
}
/**
* This method is used for getting the default value of the Input. Default value takes place when there is no value
* for this Input. Type of the default value must be the type the Input.
*
* @return default Input value
*/
@ -165,8 +189,8 @@ public class Input {
}
/**
* This method is used for setting the type of the Input. The accepted types
* are all java types defined by fully qualified names.
* This method is used for setting the type of the Input. The accepted types are all java types defined by fully
* qualified names.
*
* @param type is a fully qualified name of java type.
*/
@ -175,4 +199,8 @@ public class Input {
this.type = type;
}
@Override
public String toString() {
return "Input " + name;
}
}

Просмотреть файл

@ -1,171 +1,191 @@
/*******************************************************************************
* Copyright (c) 1997, 2015 by ProSyst Software GmbH
* http://www.prosyst.com
/**
* 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
*
* Contributors:
* ProSyst Software GmbH - initial API and implementation
*******************************************************************************/
*/
package org.eclipse.smarthome.automation.type;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.eclipse.smarthome.automation.Module;
import org.eclipse.smarthome.automation.Rule;
import org.eclipse.smarthome.automation.Visibility;
import org.eclipse.smarthome.automation.handler.ModuleHandler;
import org.eclipse.smarthome.config.core.ConfigDescriptionParameter;
/**
* ModuleType defines meta info of {@link Module} instance which are building
* blocks of the {@link Rule}. The meta info contains information about ( {@link ConfigDescriptionParameter}s,
* {@link Input}s and {@link Output}s) and
* defines an unique id which can be referred by the {@link Module} have {@link Input} elements.
* Each {@link ModuleType} instance defines the meta-information needed for creation of {@link Module} instance which is
* a building block for the {@link Rule}. The meta-information describes the {@link ConfigDescriptionParameter}s,
* {@link Input}s and {@link Output}s of the {@link Module}s. Each {@link ModuleType} instance defines an unique id
* which is used as reference from the {@link Module}s, to find their meta-information.
* <p>
* The {@link ModuleType}s can be used by any creator of Rules, but they can be modified only by its owner.
* Whether the {@link ModuleType}s can be used by anyone, depends from their visibility, but they can be modified only
* by their creator.
*
* @author Yordan Mihaylov - Initial Contribution
* @author Ana Dimova - Initial Contribution
*
*/
public abstract class ModuleType {
private String UID;
private Visibility visibility = Visibility.PUBLIC;
private Set<String> tags;
private String label;
private String description;
protected Set<ConfigDescriptionParameter> configDescriptions;
public enum Visibility {
/**
* The ModuleType is visible by everyone.
*/
PUBLIC,
/**
* The ModuleType is visible only by its creator.
*/
PRIVATE
}
/**
* This field is used as reference from the {@link Module}s, to find their meta-information.
*/
private String uid;
/**
* @param UID
* @param configDescriptions
* @param visability
* The value of this field determines whether the {@link ModuleType}s can be used by anyone if they are
* {@link Visibility#VISIBLE} or only by their creator if they are {@link Visibility#HIDDEN}.
*/
public ModuleType(String UID, Set<ConfigDescriptionParameter> configDescriptions) {
this.UID = UID;
private Visibility visibility = Visibility.VISIBLE;
/**
* Tags define categories that fit the particular {@link ModuleType} and which can serve as criteria for searching
* or filtering of {@link ModuleType}s.
*/
private Set<String> tags;
/**
* Short and accurate name of the {@link ModuleType}.
*/
private String label;
/**
* Short and understandable description of that for what can be used the {@link ModuleType}.
*/
private String description;
protected List<ConfigDescriptionParameter> configDescriptions;
/**
* This constructor is responsible to initialize common base properties of the {@link ModuleType}s.
*
* @param UID is an unique id of the {@link ModuleType}, used as reference from the {@link Module}s, to find their
* meta-information.
* @param configDescriptions is a {@link List} of meta-information configuration descriptions.
*/
public ModuleType(String UID, List<ConfigDescriptionParameter> configDescriptions) {
this.uid = UID;
this.configDescriptions = configDescriptions;
}
/**
* This method is used for getting the unique id (UID) of ModuleType. It is
* unique in scope of RuleEngine. The UID can consists of segments separated
* by column. The first segment contains system ModuleType, which corresponds
* to the {@link ModuleHandler} of the same type, and the rest are optional and
* contains UIDs of custom module type.
* This constructor is responsible to initialize all common properties of the {@link ModuleType}s.
*
* @return the type of descriptor
* @param UID unique id of the {@link ModuleType}.
* @param configDescriptions is a {@link List} of meta-information configuration descriptions.
* @param label is a short and accurate name of the {@link ModuleType}.
* @param description is a short and understandable description of which can be used the {@link ModuleType}.
* @param tags defines categories that fit the {@link ModuleType} and which can serve as criteria for searching
* or filtering it.
* @param visibility determines whether the {@link ModuleType} can be used by anyone if it is
* {@link Visibility#VISIBLE} or only by its creator if it is {@link Visibility#HIDDEN}.
*/
public ModuleType(String UID, List<ConfigDescriptionParameter> configDescriptions, String label, String description,
Set<String> tags, Visibility visibility) {
this(UID, configDescriptions);
this.label = label;
this.description = description;
this.tags = tags;
this.visibility = visibility;
}
/**
* This method is used for getting the unique id (UID) of the {@link ModuleType}. It is unique in scope of
* RuleEngine. The UID
* can consists of segments separated by column. The first segment contains system {@link ModuleType}, which
* corresponds to the {@link ModuleHandler} of the same type, and the rest are optional and contains UIDs of custom
* the {@link ModuleType}s. It uses as reference from the {@link Module}s, to find their meta-information.
*
* @return the unique id (UID) of the {@link ModuleType}, corresponding to the some type of {@link Module}s.
*/
public String getUID() {
return UID;
return uid;
}
/**
* This method is used for getting the Set of {@link ConfigDescriptionParameter}s define by this module type.<br/>
* This method is used for getting the Set of {@link ConfigDescriptionParameter}s defined by this {@link ModuleType}
* .<br/>
*
* @return a {@link Set} of configuration descriptions.
* @return a {@link Set} of meta-information configuration descriptions.
*/
public Set<ConfigDescriptionParameter> getConfigurationDescription() {
return configDescriptions;
public List<ConfigDescriptionParameter> getConfigurationDescription() {
return configDescriptions != null ? configDescriptions : Collections.<ConfigDescriptionParameter> emptyList();
}
/**
* ModuleTypes can have <li><code>tags</code> - non-hierarchical keywords or terms for describing them. The tags are
* used to filter the ModuleTypes. This method is used for getting the tags assign to this ModuleType.
* {@link ModuleType}s can have
* <li><code>tags</code> which are non-hierarchical keywords or terms for describing
* them. The tags are used to filter the ModuleTypes. This method is used for getting the tags assign to this
* {@link ModuleType}.
*
* @return tags assign to this ModuleType
* @return {@link #tags} assign to this {@link ModuleType}
*/
public Set<String> getTags() {
return tags;
return tags != null ? tags : Collections.<String> emptySet();
}
/**
* ModuleTypes can have <li><code>tags</code> - non-hierarchical keywords or terms for describing them. The tags are
* used to filter the ModuleTypes. This method is used for assigning tags to this ModuleType.
* This method is used for getting the label of the {@link ModuleType}. The label is a
* short, user friendly name of the {@link ModuleType}.
*
* @param tags set of tags assign to this Rule.
*/
public void setTags(Set<String> tags) {
this.tags = tags;
}
/**
* This method is used for getting the label of the ModuleType. The label is a
* short, user friendly name of the ModuleType defined by this descriptor.
*
* @return the label of the ModuleType.
* @return the {@link #label} of the {@link ModuleType}.
*/
public String getLabel() {
return label;
}
/**
* This method is used for setting the label of the ModuleType. The label is a
* short, user friendly name of the ModuleType defined by this descriptor.
* This method is used for getting the description of the {@link ModuleType}. The description is a short and
* understandable description of that for what can be used the {@link ModuleType}.
*
* @param label of the ModuleType.
*/
public void setLabel(String label) {
this.label = label;
}
/**
* This method is used for getting the description of the ModuleType. The
* description is a long, user friendly description of the ModuleType defined
* by this descriptor.
*
* @return the description of the ModuleType.
* @return the {@link #description} of the ModuleType.
*/
public String getDescription() {
return description;
}
/**
* This method is used for setting the description of the ModuleType. The
* description is a long, user friendly description of the ModuleType defined
* by this descriptor.
* This method is used for getting visibility of the {@link ModuleType}. The visibility determines whether the
* {@link ModuleType}s can be used by anyone if they are {@link Visibility#VISIBLE} or only by their creator if they
* are {@link Visibility#HIDDEN}. The default visibility is {@link Visibility#VISIBLE}.
*
* @param description of the ModuleType.
*/
public void setDescription(String description) {
this.description = description;
}
/**
* This method is used to show visibility of the ModuleType. Default
* visibility is {@link Visibility#PUBLIC}.
*
* @return visibility of ModuleType
* @return the {@link #visibility} of the {@link ModuleType}.
*/
public Visibility getVisibility() {
if (visibility == null) {
return Visibility.VISIBLE;
}
return visibility;
}
/**
* This method is used to change visibility of module type. Default visibility
* is {@link Visibility#PUBLIC}
*
* @param visibility new visibility value.
*/
public void setVisibility(Visibility visibility) {
this.visibility = visibility;
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((uid == null) ? 0 : uid.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ModuleType other = (ModuleType) obj;
if (uid == null) {
if (other.uid != null)
return false;
} else if (!uid.equals(other.uid))
return false;
return true;
}
}

Просмотреть файл

@ -1,15 +1,10 @@
/*******************************************************************************
* Copyright (c) 1997, 2015 by ProSyst Software GmbH
* http://www.prosyst.com
/**
* 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
*
* Contributors:
* ProSyst Software GmbH - initial API and implementation
*******************************************************************************/
*/
package org.eclipse.smarthome.automation.type;
import java.util.Collection;
@ -19,10 +14,18 @@ import java.util.Locale;
* This interface has to be implemented by all providers of {@link ModuleType}s.
* The {@link ModuleTypeRegistry} uses it to get access to available {@link ModuleType}s.
*
* @author Yordan Mihaylov
* @author Yordan Mihaylov - Initial Contribution
* @author Kai Kreuzer - refactored (managed) provider and registry implementation
* @author Ana Dimova - add registration property - module.types
*/
public interface ModuleTypeProvider {
/**
* This constant is used as registration property for Module Types Provider when the provider expects to modify
* the provided objects dynamically. Its value is a set of current provided module types UIDs.
*/
public static final String REG_PROPERTY_MODULE_TYPES = "module.types";
/**
* This method is used to get localized ModuleType. When the localization is
* not specified or it is not supported a ModuleType with default locale is
@ -32,7 +35,7 @@ public interface ModuleTypeProvider {
* @param locale defines localization of label and description of the {@link ModuleType} or null.
* @return localized module type.
*/
ModuleType getModuleType(String UID, Locale locale);
<T extends ModuleType> T getModuleType(String UID, Locale locale);
/**
* This method is used to get localized ModuleTypes defined by this provider.
@ -43,6 +46,6 @@ public interface ModuleTypeProvider {
* @return collection of localized {@link ModuleType} provided by this
* provider
*/
Collection<ModuleType> getModuleTypes(Locale locale);
<T extends ModuleType> Collection<T> getModuleTypes(Locale locale);
}

Просмотреть файл

@ -1,19 +1,15 @@
/*******************************************************************************
* Copyright (c) 1997, 2015 by ProSyst Software GmbH
* http://www.prosyst.com
/**
* 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
*
* Contributors:
* ProSyst Software GmbH - initial API and implementation
*******************************************************************************/
*/
package org.eclipse.smarthome.automation.type;
import java.util.Collection;
import java.util.Locale;
import java.util.Set;
/**
* This interface provides functionality to get available {@link ModuleType}s.
@ -21,10 +17,20 @@ import java.util.Locale;
* When it is not specified or there is no such localization resources the
* returned module type is localized with default locale.
*
* @author Yordan Mihaylov, Ana Dimova, Vasil Ilchev - Initial Contribution
* @author Yordan Mihaylov - Initial Contribution
* @author Ana Dimova - Initial Contribution
* @author Vasil Ilchev - Initial Contribution
*/
public interface ModuleTypeRegistry {
/**
* This method is used to get ModuleType of specified by type.
*
* @param moduleTypeUID the an unique id in scope of registered ModuleTypes
* @return ModuleType instance or null.
*/
public <T extends ModuleType> T get(String moduleTypeUID);
/**
* This method is used to get ModuleType of specified by type.
*
@ -33,6 +39,15 @@ public interface ModuleTypeRegistry {
*/
public <T extends ModuleType> T get(String moduleTypeUID, Locale locale);
/**
* This method is used for getting the ModuleTypes filtered by tag.
*
* @param moduleTypeTag specifies the filter for getting the ModuleTypes, if
* it is <code>null</code> then returns all ModuleTypes.
* @return the ModuleTypes, which correspond to the specified filter.
*/
public <T extends ModuleType> Collection<T> getByTag(String moduleTypeTag);
/**
* This method is used for getting the ModuleTypes filtered by tag.
*
@ -42,6 +57,24 @@ public interface ModuleTypeRegistry {
*/
public <T extends ModuleType> Collection<T> getByTag(String moduleTypeTag, Locale locale);
/**
* This method is used for getting the ModuleTypes filtered by tags.
*
* @param tags specifies the filter for getting the ModuleTypes, if
* it is <code>null</code> then returns all ModuleTypes.
* @return the ModuleTypes, which correspond to the filter.
*/
public <T extends ModuleType> Collection<T> getByTags(Set<String> tags);
/**
* This method is used for getting the ModuleTypes filtered by tags.
*
* @param moduleTypeTag specifies the filter for getting the ModuleTypes, if
* it is <code>null</code> then returns all ModuleTypes.
* @return the ModuleTypes, which correspond to the filter.
*/
public <T extends ModuleType> Collection<T> getByTags(Set<String> tags, Locale locale);
/**
* This method is used for getting the ModuleTypes, specified by type module,
* i.e. {@link ActionModuleType}, {@link ConditionModuleType}, {@link TriggerModuleType} and etc.
@ -49,6 +82,15 @@ public interface ModuleTypeRegistry {
* @param moduleType the class of module which is looking for.
* @return collection of ModuleTypes, corresponding to specified type
*/
public <T extends ModuleType> Collection<T> get(Class<T> moduleType, Locale locale);
public <T extends ModuleType> Collection<T> getAll(Class<T> moduleType);
/**
* This method is used for getting the ModuleTypes, specified by type module,
* i.e. {@link ActionModuleType}, {@link ConditionModuleType}, {@link TriggerModuleType} and etc.
*
* @param moduleType the class of module which is looking for.
* @return collection of ModuleTypes, corresponding to specified type
*/
public <T extends ModuleType> Collection<T> getAll(Class<T> moduleType, Locale locale);
}

Просмотреть файл

@ -1,25 +1,21 @@
/*******************************************************************************
* Copyright (c) 1997, 2015 by ProSyst Software GmbH
* http://www.prosyst.com
/**
* 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
*
* Contributors:
* ProSyst Software GmbH - initial API and implementation
*******************************************************************************/
*/
package org.eclipse.smarthome.automation.type;
import java.util.Collections;
import java.util.Set;
import org.eclipse.smarthome.automation.Module;
import org.eclipse.smarthome.automation.Rule;
/**
* This class defines meta info for {@link Output} which is used by the
* RuleEngine when creating connection between modules. The meta info contains:
* This class defines meta-information for {@link Output} which is used by the RuleEngine when creating connection
* between modules. The meta-information contains:
* <ul>
* <li>name(mandatory) - unique id in scope of containing Module</li>
* <li>type(mandatory) - accepted data type by this Output</li>
@ -30,27 +26,66 @@ import org.eclipse.smarthome.automation.Rule;
* has to be used as value of this output.
* </ul>
* Outputs are exit points of a {@link Module}. They are used as data source for {@link Input}s of other {@link Module}
* s. The {@link Output} can be connected
* s.
* The {@link Output} can be connected
* to more then one {@link Input} of the same data type.<br>
*
* @author Yordan Mihaylov, Ana Dimova, Vasil Ilchev - Initial Contribution
* @author Yordan Mihaylov - Initial Contribution
* @author Ana Dimova - Initial Contribution
* @author Vasil Ilchev - Initial Contribution
*/
public class Output {
/**
* is an unique name of the {@code Output} in scope of the {@link Module}.
*/
private String name;
/**
* This field specifies the type of the {@code Output}. The accepted types are all java types defined by fully
* qualified names.
*/
private String type;
/**
* This field is associated with the {@code Output}. The tags add additional restrictions to connections between
* {@link Input}s and {@link Output}s. The {@link Input}'s tags must be subset of the {@code Output}'s tags to
* succeed the connection.</br>
* For example: When we want to connect {@link Input} to {@code Output} and both have
* same java.lang.double data type. The the output has assign "temperature" and "celsius" tags then the input must
* have at least one of these output's tags (i.e. "temperature") to connect this input to the selected
* {@code Output}.
*/
private Set<String> tags;
/**
* This field keeps a single word description of the {@code Output}.
*/
private String label;
/**
* This field keeps the user friendly description of the {@code Output}.
*/
private String description;
/**
* The value of this field refers to the data source. It defines what part of complex data should be used as source
* of this {@code Output}.
*/
private String reference;
/**
* The value of this field takes place when there is no runtime value for this {@code Output}. Type of the default
* value must be the type of the {@code Output}.
*/
private Object defaultValue;
/**
* Constructor of Output objects. It is based on the type of data and Output's
* name
* Constructor of {@code Output} objects. It is based on the type of data and {@code Output}'s name.
*
* @param name is an unique name of the {@code Output}.
* @param type is the data type accepted by this {@code Output}.
*
* @param type data type accepted by this Output.
* @param name unique name of the Output.
* @see #getType()
*/
public Output(String name, String type) {
@ -59,26 +94,24 @@ public class Output {
}
/**
* Constructor of Output object. Creates Output base on type of accepted data
* and Output name
* Constructor of {@code Output} object. Creates an {@code Output} instance based on the type of accepted data
* and {@code Output}'s name.
*
* @param type data type accepted by this Output.;
* @param name unique name of the Output.
* @param label a single word description of the Output.
* @param description user friendly description of the Output.
* @param tags tags associated with the Output. The tags adds additional
* restrictions to connections between {@link Input}s and {@link Output}s. The input tags must be subset
* of the output tags
* to succeed the connection.</br> For example: When we want to
* connect input to output and both have same java.lang.double data
* type. The the output has assign "temperature" and "celsius" tags
* then the input must have at least one of these output's tags (i.e.
* "temperature") to connect this input to the selected output.
* @param reference a reference to data source. It defines what part of
* complex data should be used as source of this Output
* @param defaultValue default value takes place when there is no value for
* this Output. Type of the default value must be the type the
* output.
* @param type is the data type accepted by this {@code Output}.
* @param name is an unique name of the {@code Output}.
* @param label a single word description of the {@code Output}.
* @param description is an user friendly description of the {@code Output}.
* @param tags are associated with the {@code Output}. The tags add additional restrictions to connections between
* {@link Input}s and {@link Output}s. The {@link Input}'s tags must be subset of the {@code Output}'s
* tags to succeed the connection.</br>
* For example: When we want to connect {@link Input} to
* {@code Output} and both have same java.lang.double data type. The the output has assign "temperature"
* and "celsius" tags then the input must have at least one of these output's tags (i.e. "temperature")
* to connect this input to the selected {@code Output}.
* @param reference refers to the data source. It defines what part of complex data should be used as source of
* this {@code Output}.
* @param defaultValue takes place when there is no runtime value for this {@code Output}. Type of the default value
* must be the type of the {@code Output}.
*/
public Output(String name, String type, String label, String description, Set<String> tags, String reference,
Object defaultValue) {
@ -94,17 +127,17 @@ public class Output {
}
/**
* This method is used for getting the name of Output. It must be unique in
* This method is used for getting the name of {@code Output}. It must be unique in
* scope of {@link Rule}.
*
* @return name is an unique identifier of the Output.
* @return name is an unique identifier of the {@code Output}.
*/
public String getName() {
return name;
}
/**
* This method is used for getting the type of the Output. The accepted types
* This method is used for getting the type of the {@code Output}. The accepted types
* are all java types defined by fully qualified names.
*
* @return type is a fully qualified name of java type.
@ -114,7 +147,7 @@ public class Output {
}
/**
* This method is used for getting the short description of the Output.
* This method is used for getting the short description of the {@code Output}.
* Usually the label should be a single word description.
*
* @return label of the Output.
@ -124,63 +157,65 @@ public class Output {
}
/**
* This method is used for getting the long description of the Output.
* This method is used for getting the long description of the {@code Output}.
*
* @return user friendly description of the Output.
* @return user friendly description of the {@code Output}.
*/
public String getDescription() {
return description;
}
/**
* This method is used for getting the reference to data source. It defines
* what part of complex data (i.e. JavaBean, java.lang.Map etc.) has to be
* used as value of this output. For example in the Output data is
* java.lang.Map the reference points which property has to be used as output
* value.
* This method is used for getting the reference to data source. It defines what part of complex data (i.e.
* JavaBean, java.lang.Map etc.) has to be used as a value of this {@code Output}. For example, in the
* {@code Output} data - java.lang.Map, the reference points to the property that has to be used as an output value.
*
* @return reference to data source.
* @return a reference to data source.
*/
public String getReference() {
return reference;
}
/**
* This method is used for getting the tags of the Output. The tags adds
* additional restrictions to connections between {@link Input}s and {@link Output}s. The input tags must be subset
* of the output tags to
* succeed the connection.</br> For example: When we want to connect input to
* output and they both have same java.lang.double data type, and the output
* has assign "temperature" and "celsius" tags then the input must have at
* least one of these output's tags (i.e. "temperature") to connect this input
* to the selected output.
* This method is used for getting the tags of the {@code Output}. The tags add additional restrictions to
* connections between {@link Input}s and {@code Output}s. The input tags must be subset of the output tags to
* succeed the connection.</br>
* For example: When we want to connect {@link Input} to {@code Output} and they both
* have same data type - java.lang.double and the {@link Output} has assign "temperature" and "celsius" tags, then
* the {@link Input} must have at least one of these {@code Output}'s tags (i.e. "temperature") to connect this
* {@link Input} to the selected {@code Output}.
*
* @return tags associated with this Input.
* @return the tags, associated with this {@link Input}.
*/
public Set<String> getTags() {
return tags;
return tags != null ? tags : Collections.<String> emptySet();
}
/**
* This method is used for getting the default value of the Output. Default
* value takes place when there is no value for this Ouput. Type of the
* default value must be the type the Output.
* This method is used for getting the default value of the {@code Output}. Default value takes place when there is
* no runtime value for this {@code Output}. Type of the default value must be the type of the {@code Output}.
*
* @return default Output value
* @return the default value of this {@code Output}.
*/
public Object getDefaultValue() {
return defaultValue;
}
/**
* This method is used for setting the type of the Output. The accepted types
* are all java types defined by fully qualified names.
* This method is used for setting the type of the {@code Output}. The accepted types are all java types defined by
* fully qualified names.
*
* @param type is a fully qualified name of java type.
* @param type is a fully qualified name of the java type.
*/
private void setType(String type) {
// TODO verify type if it is a fully qualified class name
this.type = type;
}
/**
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "Output " + name;
}
}

Просмотреть файл

@ -1,20 +1,19 @@
/*******************************************************************************
* Copyright (c) 1997, 2015 by ProSyst Software GmbH
* http://www.prosyst.com
/**
* 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
*
* Contributors:
* ProSyst Software GmbH - initial API and implementation
*******************************************************************************/
*/
package org.eclipse.smarthome.automation.type;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.eclipse.smarthome.automation.Module;
import org.eclipse.smarthome.automation.Trigger;
import org.eclipse.smarthome.automation.Visibility;
import org.eclipse.smarthome.config.core.ConfigDescriptionParameter;
/**
@ -23,32 +22,60 @@ import org.eclipse.smarthome.config.core.ConfigDescriptionParameter;
* scope of the rule engine and defines {@link ConfigDescriptionParameter}s and {@link Output}s of the {@link Trigger}
* instance.
*
* This class provides common functionality for creating {@link Trigger} instances by supplying types with their
* meta-information. The {@link Trigger}s are part of "ON" section of the Rule. Each {@link TriggerType} is defined by
* unique id in scope of the RuleEngine and defines {@link ConfigDescriptionParameter}s that are meta-information for
* configuration and meta-information for {@link Output}s used for creation of {@link Trigger} instances.
*
* @author Yordan Mihaylov - Initial Contribution
*/
public class TriggerType extends ModuleType {
private Set<Output> outputs;
private List<Output> outputs;
/**
* Constructor of TriggerType.
* This constructor is responsible to create an instance of {@link TriggerType} with base properties - UID, a
* {@link List} of configuration descriptions and a {@link List} of {@link Output} descriptions.
*
* @param UID unique id of the trigger type
* @param configDescriptions is a {@link Set} of configuration descriptions.
* @param outputs is a {@link Set} of {@link Output} definitions.
* @param UID is an unique id of the {@link ActionType}, used as reference from the {@link Module}s, to find their
* meta-information.
* @param configDescriptions is a {@link List} of meta-information configuration descriptions.
* @param outputs is a {@link List} of {@link Output} meta-information descriptions.
*/
public TriggerType(String UID, Set<ConfigDescriptionParameter> configDescriptions, Set<Output> outputs) {
public TriggerType(String UID, List<ConfigDescriptionParameter> configDescriptions, List<Output> outputs) {
super(UID, configDescriptions);
this.outputs = outputs;
}
/**
* This method is used for getting the meta info of inputs defined by this
* module type.<br/>
* This constructor is responsible to create an instance of {@link TriggerType} with UID, label, description, a
* {@link Set} of tags, visibility, a {@link List} of configuration descriptions and a {@link List} of
* {@link Output}
* descriptions.
*
* @return a {@link Set} of {@link Input} definitions.
* @param UID unique id of the {@link TriggerType}.
* @param configDescriptions is a {@link List} of meta-information configuration descriptions.
* @param label is a short and accurate name of the {@link TriggerType}.
* @param description is a short and understandable description of which can be used the {@link TriggerType}.
* @param tags defines categories that fit the {@link TriggerType} and which can serve as criteria for searching
* or filtering it.
* @param visibility determines whether the {@link TriggerType} can be used by anyone if it is
* {@link Visibility#VISIBLE} or only by its creator if it is {@link Visibility#HIDDEN}.
* @param outputs is a {@link List} of {@link Output} meta-information descriptions.
*/
public Set<Output> getOutputs() {
return outputs;
public TriggerType(String UID, List<ConfigDescriptionParameter> configDescriptions, String label,
String description, Set<String> tags, Visibility visibility, List<Output> outputs) {
super(UID, configDescriptions, label, description, tags, visibility);
this.outputs = outputs;
}
/**
* This method is used for getting the meta-information descriptions of {@link Output}s defined by this type.<br/>
*
* @return a {@link List} of {@link Output} definitions.
*/
public List<Output> getOutputs() {
return outputs != null ? outputs : Collections.<Output> emptyList();
}
}

Просмотреть файл

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src/main/java"/> <classpathentry kind="output" path="target/classes"/>
</classpath>

Просмотреть файл

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>org.eclipse.smarthome.automation.commands</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ds.core.builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

Просмотреть файл

@ -0,0 +1,23 @@
Bundle-ManifestVersion: 2
Bundle-SymbolicName: org.eclipse.smarthome.automation.commands
Bundle-Vendor: Eclipse.org/SmartHome
Bundle-Version: 0.8.0.qualifier
Bundle-Name: Eclipse SmartHome Automation commands
Import-Package:
org.apache.commons.lang,
org.eclipse.smarthome.automation,
org.eclipse.smarthome.automation.core.util,
org.eclipse.smarthome.automation.handler,
org.eclipse.smarthome.automation.parser,
org.eclipse.smarthome.automation.template,
org.eclipse.smarthome.automation.type,
org.eclipse.smarthome.config.core,
org.eclipse.smarthome.core.common.registry,
org.eclipse.smarthome.io.console,
org.eclipse.smarthome.io.console.extensions,
org.osgi.framework,
org.osgi.service.event,
org.osgi.util.tracker,
org.slf4j
Bundle-Activator: org.eclipse.smarthome.automation.internal.commands.Activator
Bundle-RequiredExecutionEnvironment: JavaSE-1.7

Просмотреть файл

@ -0,0 +1,28 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
<title>About</title>
</head>
<body lang="EN-US">
<h2>About This Content</h2>
<p>June 5, 2006</p>
<h3>License</h3>
<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;). Unless otherwise
indicated below, the Content is provided to you under the terms and conditions of the
Eclipse Public License Version 1.0 (&quot;EPL&quot;). A copy of the EPL is available
at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
apply to your use of any object code in the Content. Check the Redistributor's license that was
provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
indicated below, the terms and conditions of the EPL still apply to any source code in the Content
and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
</body>
</html>

Просмотреть файл

@ -0,0 +1,5 @@
output.. = target/classes/
bin.includes = META-INF/,\
.,\
about.html
source.. = src/main/java/

Просмотреть файл

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<groupId>org.eclipse.smarthome.bundles</groupId>
<artifactId>automation</artifactId>
<version>0.8.0-SNAPSHOT</version>
</parent>
<properties>
<bundle.symbolicName>org.eclipse.smarthome.automation.commands</bundle.symbolicName>
<bundle.namespace>org.eclipse.smarthome.automation.commands</bundle.namespace>
</properties>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.smarthome.automation</groupId>
<artifactId>org.eclipse.smarthome.automation.commands</artifactId>
<name>Eclipse SmartHome Automation Commands</name>
<packaging>eclipse-plugin</packaging>
</project>

Просмотреть файл

@ -0,0 +1,182 @@
/**
* 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.internal.commands;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.smarthome.automation.parser.Parser;
import org.eclipse.smarthome.automation.parser.ParsingException;
import org.eclipse.smarthome.automation.template.TemplateProvider;
import org.eclipse.smarthome.automation.type.ModuleTypeProvider;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.util.tracker.ServiceTrackerCustomizer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This class is base for {@link ModuleTypeProvider}, {@link TemplateProvider} and RuleImporter which are responsible
* for execution of automation commands.
* <p>
* It provides functionality for tracking {@link Parser} services by implementing {@link ServiceTrackerCustomizer} and
* provides common functionality for exporting automation objects.
*
* @author Ana Dimova - Initial Contribution
* @author Kai Kreuzer - refactored (managed) provider and registry implementation
*
*/
@SuppressWarnings("rawtypes")
public abstract class AbstractCommandProvider<E> implements ServiceTrackerCustomizer {
protected Logger logger;
/**
* A bundle's execution context within the Framework.
*/
protected BundleContext bc;
/**
* This Map provides reference between provider of resources and the loaded objects from these resources.
* <p>
* The Map has for keys - {@link URL} resource provider and for values - Lists with UIDs of the objects.
*/
Map<URL, List<String>> providerPortfolio = new HashMap<URL, List<String>>();
/**
* This field is a {@link ServiceTracker} for {@link Parser} services.
*/
protected ServiceTracker<Parser, Parser> parserTracker;
/**
* This Map provides structure for fast access to the {@link Parser}s. This provides opportunity for high
* performance at runtime of the system.
*/
protected Map<String, Parser<E>> parsers = new HashMap<String, Parser<E>>();
/**
* This Map provides structure for fast access to the provided automation objects. This provides opportunity for
* high performance at runtime of the system, when the Rule Engine asks for any particular object, instead of
* waiting it for parsing every time.
* <p>
* The Map has for keys UIDs of the objects and for values {@link Localizer}s of the objects.
*/
protected Map<String, E> providedObjectsHolder = new HashMap<String, E>();
/**
* This constructor is responsible for creation and opening a tracker for {@link Parser} services.
*
* @param context is the {@link BundleContext}, used for creating a tracker for {@link Parser} services.
*/
@SuppressWarnings("unchecked")
public AbstractCommandProvider(BundleContext context) {
this.bc = context;
logger = LoggerFactory.getLogger(AbstractCommandProvider.this.getClass());
parserTracker = new ServiceTracker(context, Parser.class.getName(), this);
parserTracker.open();
}
/**
* This method is inherited from {@link AbstractPersistentProvider}.
* Extends parent's functionality with closing the {@link Parser} service tracker.
* Sets <code>null</code> to {@link #parsers}, {@link #providedObjectsHolder}, {@link #providerPortfolio}
*/
public void close() {
if (parserTracker != null) {
parserTracker.close();
parserTracker = null;
parsers = null;
synchronized (providedObjectsHolder) {
providedObjectsHolder = null;
}
synchronized (providerPortfolio) {
providerPortfolio = null;
}
}
}
/**
* This method tracks the {@link Parser} services and stores them into the Map "{@link #parsers}" in the
* memory, for fast access on demand.
*
* @see org.osgi.util.tracker.ServiceTrackerCustomizer#addingService(org.osgi.framework.ServiceReference)
*/
@Override
public Object addingService(ServiceReference reference) {
@SuppressWarnings("unchecked")
Parser<E> service = (Parser<E>) bc.getService(reference);
String key = (String) reference.getProperty(Parser.FORMAT);
key = key == null ? Parser.FORMAT_JSON : key;
parsers.put(key, service);
return service;
}
/**
* @see org.osgi.util.tracker.ServiceTrackerCustomizer#modifiedService(org.osgi.framework.ServiceReference,
* java.lang.Object)
*/
@Override
public void modifiedService(ServiceReference reference, Object service) {
// do nothing
}
/**
* This method removes the {@link Parser} service objects from the Map "{@link #parsers}".
*
* @see org.osgi.util.tracker.ServiceTrackerCustomizer#removedService(org.osgi.framework.ServiceReference,
* java.lang.Object)
*/
@Override
public void removedService(ServiceReference reference, Object service) {
String key = (String) reference.getProperty(Parser.FORMAT);
key = key == null ? Parser.FORMAT_JSON : key;
parsers.remove(key);
}
/**
* This method is responsible for execution of the {@link AutomationCommandExport} operation by choosing the
* {@link Parser} which to be used for exporting a set of automation objects, in a file. When the choice is made,
* the chosen {@link Parser} is used to do the export.
*
* @param parserType is a criteria for choosing the {@link Parser} which to be used.
* @param set a Set of automation objects for export.
* @param file is the file in which to export the automation objects.
* @throws Exception is thrown when I/O operation has failed or has been interrupted or generating of the text fails
* for some reasons.
*/
public void exportData(String parserType, Set<E> set, File file) throws Exception {
OutputStreamWriter oWriter = null;
oWriter = new OutputStreamWriter(new FileOutputStream(file));
Parser<E> parser = parsers.get(parserType);
if (parser != null)
parser.serialize(set, oWriter);
throw new Exception("Parser \"" + parserType + "\" not found!");
}
/**
* This method is responsible for execution of the {@link AutomationCommandImport} operation.
*
* @param parser the {@link Parser} which to be used for operation.
* @param inputStreamReader
* @return the set of automation objects created as result of the {@link AutomationCommandImport} operation.
* Operation can be successful or can fail because of {@link ParsingException}.
* @throws ParsingException is thrown when there are exceptions during the parsing process. It accumulates all of
* them.
*/
protected abstract Set<E> importData(URL url, Parser<E> parser, InputStreamReader inputStreamReader)
throws ParsingException;
}

Просмотреть файл

@ -0,0 +1,43 @@
/**
* 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.internal.commands;
import org.eclipse.smarthome.automation.template.TemplateProvider;
import org.eclipse.smarthome.automation.type.ModuleTypeProvider;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
/**
* This class is an activator of this bundle. Opens the all used service trackers and registers the services -
* AutomationCommands, {@link ModuleTypeProvider} and {@link TemplateProvider}.
*
* @author Ana Dimova - Initial Contribution
*
*/
public class Activator implements BundleActivator {
private AutomationCommandsPluggable autoCommands;
/**
* This method initialize pluggable commands for importing, exporting, listing and removing automation objects.
*/
@Override
public void start(BundleContext bc) throws Exception {
autoCommands = new AutomationCommandsPluggable(bc);
}
/**
* This method close all used service trackers, unregisters the services - AutomationCommands,
* {@link ModuleTypeProvider} and {@link TemplateProvider}.
*/
@Override
public void stop(BundleContext bc) throws Exception {
autoCommands.stop();
}
}

Просмотреть файл

@ -0,0 +1,103 @@
/**
* 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.internal.commands;
/**
* This class is base for all automation commands. It defines common functionality for an automation command. Each class
* of commands is responsible for a group of commands, that are equivalent but each of them is related to a different
* provider.
*
* @author Ana Dimova - Initial Contribution
*
*/
public abstract class AutomationCommand {
/**
* This constant is used as a part of the string representing understandable for the user message containing
* information for the success of the command.
*/
protected static final String SUCCESS = "SUCCESS";
/**
* This constant is used as a part of the string representing understandable for the user message containing
* information for the failure of the command.
*/
protected static final String FAIL = "FAIL";
/**
* This constant is used for detection of <tt>PrintStackTrace</tt> option. If some of the parameters of the command
* is equal to this constant, then the option is present.
*/
protected static final String OPTION_ST = "-st";
/**
* This field is an indicator of presence of <tt>PrintStackTrace</tt> option. Its value is <b>true</b> if the
* option is present and <b>false</b> in the opposite case.
*/
protected boolean st = false;
/**
* This field keeps the result of parsing the parameters and options of the command.
*/
protected String parsingResult;
/**
* This field keeps the identifier of the command because each class of commands is responsible for a group
* of commands.
*/
protected String command;
/**
* This field keeps information about which provider is responsible for execution of the command.
*/
protected int providerType;
/**
* This field keeps a reference to the particular implementation of the <tt>AutomationCommandsPluggable</tt>.
*/
protected AutomationCommandsPluggable autoCommands;
/**
* This constructor is responsible for initializing the common properties for each automation command.
*
* @param command is the identifier of the command.
* @param parameterValues is an array of strings which are basis for initializing the options and parameters of the
* command. The order for their description is a random.
* @param providerType is which provider is responsible for execution of the command.
* @param autoCommands a reference to the particular implementation of the <tt>AutomationCommandsPluggable</tt>.
*/
public AutomationCommand(String command, String[] parameterValues, int providerType,
AutomationCommandsPluggable autoCommands) {
this.command = command;
this.providerType = providerType;
this.autoCommands = autoCommands;
parsingResult = parseOptionsAndParameters(parameterValues);
}
/**
* This method is common for all automation commands and it is responsible for execution of every particular
* command.
*
* @return a string representing understandable for the user message containing information on the outcome of the
* command.
*/
public abstract String execute();
/**
* This method is used to determine the options and parameters for every particular command. If there are redundant
* options and parameters or the required are missing the execution of the command will be ended and the parsing
* result will be returned as a result of the command.
*
* @param parameterValues is an array of strings which are basis for initializing the options and parameters of the
* command. The order for their description is a random.
* @return a string representing understandable for the user message containing information on the outcome of the
* parsing the parameters and options.
*/
protected abstract String parseOptionsAndParameters(String[] parameterValues);
}

Просмотреть файл

@ -0,0 +1,100 @@
/**
* 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.internal.commands;
import org.eclipse.smarthome.automation.RuleStatus;
/**
* This class provides functionality of command {@link AutomationCommands#ENABLE_RULE}.
*
* @author Ana Dimova - Initial Contribution
*
*/
public class AutomationCommandEnableRule extends AutomationCommand {
/**
* This field keeps the value of "enable" parameter of the command.
*/
private boolean enable;
/**
* This field indicates the presence of the "enable" parameter of the command.
*/
private boolean hasEnable;
/**
* This field keeps the specified rule UID.
*/
private String uid;
public AutomationCommandEnableRule(String command, String[] parameterValues, int providerType,
AutomationCommandsPluggable autoCommands) {
super(command, parameterValues, providerType, autoCommands);
}
@Override
public String execute() {
if (parsingResult != SUCCESS) {
return parsingResult;
}
if (hasEnable) {
autoCommands.setEnabled(uid, enable);
return SUCCESS;
} else {
RuleStatus status = autoCommands.getRuleStatus(uid);
if (status != null)
return Printer.printRuleStatus(uid, status);
}
return FAIL;
}
@Override
protected String parseOptionsAndParameters(String[] parameterValues) {
for (int i = 0; i < parameterValues.length; i++) {
if (null == parameterValues[i]) {
continue;
}
if (parameterValues[i].charAt(0) == '-') {
if (parameterValues[i].equals(OPTION_ST)) {
st = true;
continue;
}
return String.format("Unsupported option: %s", parameterValues[i]);
}
if (uid == null) {
uid = parameterValues[i];
continue;
}
getEnable(parameterValues[i]);
if (hasEnable)
continue;
if (uid == null)
return "Missing required parameter: Rule UID";
return String.format("Unsupported parameter: %s", parameterValues[i]);
}
return SUCCESS;
}
/**
* Utility method for parsing the command parameter - "enable".
*
* @param parameterValue is the value entered from command line.
*/
private void getEnable(String parameterValue) {
if (parameterValue.equals("true")) {
enable = true;
hasEnable = true;
} else if (parameterValue.equals("false")) {
enable = false;
hasEnable = true;
} else {
hasEnable = false;
}
}
}

Просмотреть файл

@ -0,0 +1,212 @@
/**
* 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.internal.commands;
import java.io.File;
import java.util.Collection;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
import org.eclipse.smarthome.automation.parser.Parser;
import org.eclipse.smarthome.automation.type.ActionType;
import org.eclipse.smarthome.automation.type.CompositeActionType;
import org.eclipse.smarthome.automation.type.CompositeConditionType;
import org.eclipse.smarthome.automation.type.CompositeTriggerType;
import org.eclipse.smarthome.automation.type.ConditionType;
import org.eclipse.smarthome.automation.type.TriggerType;
/**
* This class provides common functionality of commands:
* <ul>
* <li>{@link AutomationCommands#EXPORT_MODULE_TYPES}
* <li>{@link AutomationCommands#EXPORT_TEMPLATES}
* <li>{@link AutomationCommands#EXPORT_RULES}
* </ul>
*
* @author Ana Dimova - Initial Contribution
*
*/
public class AutomationCommandExport extends AutomationCommand {
/**
* This constant is used for detection of <tt>ParserType</tt> parameter. If some of the parameters of the command
* is equal to this constant, then the <tt>ParserType</tt> parameter is present and its value is the next one.
*/
private static final String OPTION_P = "-p";
/**
* This field keeps the value of the <tt>ParserType</tt> parameter and it is initialized as
* {@link Parser#FORMAT_JSON} by default.
*/
private String parserType = Parser.FORMAT_JSON;
/**
* This field keeps the path of the output file where the automation objects to be exported.
*/
private File file;
/**
* This field stores the value of <b>locale</b> parameter of the command.
*/
private Locale locale = Locale.getDefault(); // For now is initialized with the default locale, but when the
// localization is implemented, it will be initialized with a parameter
// of the command.
/**
* @see AutomationCommand#AutomationCommand(String, String[], int, AutomationCommandsPluggable)
*/
public AutomationCommandExport(String command, String[] params, int providerType,
AutomationCommandsPluggable autoCommands) {
super(command, params, providerType, autoCommands);
}
/**
* This method is responsible for execution of commands:
* <ul>
* <li>{@link AutomationCommands#EXPORT_MODULE_TYPES}
* <li>{@link AutomationCommands#EXPORT_TEMPLATES}
* <li>{@link AutomationCommands#EXPORT_RULES}
* </ul>
*/
@SuppressWarnings("unchecked")
@Override
public String execute() {
if (parsingResult != SUCCESS) {
return parsingResult;
}
@SuppressWarnings("rawtypes")
Set set = new HashSet();
switch (providerType) {
case AutomationCommands.MODULE_TYPE_PROVIDER:
@SuppressWarnings("rawtypes")
Collection collection = autoCommands.getModuleTypes(TriggerType.class, locale);
if (collection != null)
set.addAll(collection);
collection = autoCommands.getModuleTypes(CompositeTriggerType.class, locale);
if (collection != null)
set.addAll(collection);
collection = autoCommands.getModuleTypes(ConditionType.class, locale);
if (collection != null)
set.addAll(collection);
collection = autoCommands.getModuleTypes(CompositeConditionType.class, locale);
if (collection != null)
set.addAll(collection);
collection = autoCommands.getModuleTypes(ActionType.class, locale);
if (collection != null)
set.addAll(collection);
collection = autoCommands.getModuleTypes(CompositeActionType.class, locale);
if (collection != null)
set.addAll(collection);
try {
autoCommands.exportModuleTypes(parserType, set, file);
} catch (Exception e) {
return e.getMessage();
}
if (set.isEmpty()) {
return "There are no ModuleTypes available!";
}
return SUCCESS;
case AutomationCommands.TEMPLATE_PROVIDER:
collection = autoCommands.getTemplates(locale);
if (collection != null)
set.addAll(collection);
try {
autoCommands.exportTemplates(parserType, set, file);
} catch (Exception e) {
return e.getMessage();
}
if (set.isEmpty()) {
return "There are no Templates available!";
}
return SUCCESS;
case AutomationCommands.RULE_PROVIDER:
collection = autoCommands.getRules();
if (collection != null)
set.addAll(collection);
try {
autoCommands.exportRules(parserType, set, file);
} catch (Exception e) {
return e.getMessage();
}
if (set.isEmpty()) {
return "There are no Rules available!";
}
return SUCCESS;
}
return String.format("%s : Unsupported provider type!", FAIL);
}
/**
* This method serves to create a {@link File} object from a string that is passed as a parameter of the command.
*
* @param parameterValue is a string that is passed as parameter of the command and it supposed to be a file
* representation.
* @return a {@link File} object created from the string that is passed as a parameter of the command or <b>null</b>
* if the parent directory could not be found or created or the string could not be parsed.
*/
private File initFile(String parameterValue) {
File f = new File(parameterValue);
File parent = f.getParentFile();
if (!parent.isDirectory() && !parent.mkdirs()) {
return null;
}
return f;
}
/**
* This method is invoked from the constructor to parse all parameters and options of the command <b>EXPORT</b>.
* If there are redundant parameters or options, or the required parameter is missing the result will be the failure
* of the command. This command has:
* <ul>
* <b>Options:</b>
* <ul>
* <li><b>PrintStackTrace</b> which is common for all commands
* </ul>
* </ul>
* <ul>
* <b>Parameters:</b>
* <ul>
* <li><b>parserType</b> is optional and by default its value is {@link Parser#FORMAT_JSON}.
* <li><b>file</b> is required and specifies the path to the file for export.
* </ul>
* </ul>
*/
@Override
protected String parseOptionsAndParameters(String[] parameterValues) {
boolean getFile = true;
for (int i = 0; i < parameterValues.length; i++) {
if (null == parameterValues[i]) {
continue;
}
if (parameterValues[i].equals(OPTION_ST)) {
st = true;
} else if (parameterValues[i].equalsIgnoreCase(OPTION_P)) {
i++;
if (i >= parameterValues.length) {
return String.format("The option [%s] should be followed by value for the parser type.", OPTION_P);
}
parserType = parameterValues[i];
} else if (parameterValues[i].charAt(0) == '-') {
return String.format("Unsupported option: {1}", parameterValues[i]);
} else if (getFile) {
file = initFile(parameterValues[i]);
if (file != null) {
getFile = false;
}
} else {
return String.format("Unsupported parameter: %s", parameterValues[i]);
}
}
if (getFile) {
return "Missing destination file parameter!";
}
return SUCCESS;
}
}

Просмотреть файл

@ -0,0 +1,176 @@
/**
* 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
*/
/**
* 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.internal.commands;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import org.eclipse.smarthome.automation.parser.Parser;
/**
* This class provides common functionality of commands:
* <ul>
* <li>{@link AutomationCommands#IMPORT_MODULE_TYPES}
* <li>{@link AutomationCommands#IMPORT_TEMPLATES}
* <li>{@link AutomationCommands#IMPORT_RULES}
* </ul>
*
* @author Ana Dimova - Initial Contribution
*
*/
public class AutomationCommandImport extends AutomationCommand {
/**
* This constant is used for detection of <tt>ParserType</tt> parameter. If some of the parameters of the command
* is equal to this constant, then the <tt>ParserType</tt> parameter is present and its value is the next one.
*/
private static final String OPTION_P = "-p";
/**
* This field keeps the value of the <tt>ParserType</tt> parameter and it is initialized as
* {@link Parser#FORMAT_JSON} by default.
*/
private String parserType = Parser.FORMAT_JSON;
/**
* This field keeps URL of the source of automation objects that has to be imported.
*/
private URL url;
/**
* @see AutomationCommand#AutomationCommand(String, String[], int, AutomationCommandsPluggable)
*/
public AutomationCommandImport(String command, String[] params, int adminType,
AutomationCommandsPluggable autoCommands) {
super(command, params, adminType, autoCommands);
}
/**
* This method is responsible for execution of commands:
* <ul>
* <li>{@link AutomationCommands#IMPORT_MODULE_TYPES}
* <li>{@link AutomationCommands#IMPORT_TEMPLATES}
* <li>{@link AutomationCommands#IMPORT_RULES}
* </ul>
*/
@Override
public String execute() {
if (parsingResult != SUCCESS) {
return parsingResult;
}
try {
switch (providerType) {
case AutomationCommands.MODULE_TYPE_PROVIDER:
autoCommands.importModuleTypes(parserType, url);
break;
case AutomationCommands.TEMPLATE_PROVIDER:
autoCommands.importTemplates(parserType, url);
break;
case AutomationCommands.RULE_PROVIDER:
autoCommands.importRules(parserType, url);
break;
}
} catch (Exception e) {
StringBuilder writer = new StringBuilder();
if (st) {
StackTraceElement[] ste = e.getStackTrace();
for (int i = 0; i < ste.length; i++) {
writer.append(String.format("FAIL : %s", ste[i].toString() + "\n"));
}
} else {
writer.append(String.format("FAIL : %s", e.getMessage() + "\n"));
}
return writer.toString();
}
return SUCCESS + "\n";
}
/**
* This method serves to create an {@link URL} object or {@link File} object from a string that is passed as
* a parameter of the command. From the {@link File} object the URL is constructed.
*
* @param parameterValue is a string that is passed as parameter of the command and it supposed to be an URL
* representation.
* @return an {@link URL} object created from the string that is passed as parameter of the command or <b>null</b>
* if either no legal protocol could be found in the specified string or the string could not be parsed.
*/
private URL initURL(String parameterValue) {
try {
return new URL(parameterValue);
} catch (MalformedURLException mue) {
File f = new File(parameterValue);
if (f.isFile()) {
try {
return f.toURI().toURL();
} catch (MalformedURLException e) {
}
}
}
return null;
}
/**
* This method is invoked from the constructor to parse all parameters and options of the command <b>EXPORT</b>.
* If there are redundant parameters or options or the required is missing the result will be the failure of the
* command. This command has:
* <ul>
* <b>Options:</b>
* <ul>
* <li><b>PrintStackTrace</b> is common for all commands and its presence triggers printing of stack trace in case
* of exception.
* </ul>
* </ul>
* <ul>
* <b>Parameters:</b>
* <ul>
* <li><b>parserType</b> is optional and by default its value is {@link Parser#FORMAT_JSON}.
* <li><b>url</b> is required and it points the resource of automation objects that has to be imported.
* </ul>
* </ul>
*/
@Override
protected String parseOptionsAndParameters(String[] parameterValues) {
boolean getUrl = true;
for (int i = 0; i < parameterValues.length; i++) {
if (null == parameterValues[i]) {
continue;
}
if (parameterValues[i].equals(OPTION_ST)) {
st = true;
} else if (parameterValues[i].equalsIgnoreCase(OPTION_P)) {
i++;
if (i >= parameterValues.length) {
return String.format("The option [%s] should be followed by value for the parser type.", OPTION_P);
}
parserType = parameterValues[i];
} else if (parameterValues[i].charAt(0) == '-') {
return String.format("Unsupported option: %s", parameterValues[i]);
} else if (getUrl) {
url = initURL(parameterValues[i]);
if (url != null) {
getUrl = false;
}
} else {
return String.format("Unsupported parameter: %s", parameterValues[i]);
}
}
if (getUrl) {
return "Missing source URL parameter or its value is incorrect!";
}
return SUCCESS;
}
}

Просмотреть файл

@ -0,0 +1,440 @@
/**
* 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.internal.commands;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Locale;
import org.eclipse.smarthome.automation.Rule;
import org.eclipse.smarthome.automation.RuleStatus;
import org.eclipse.smarthome.automation.template.RuleTemplate;
import org.eclipse.smarthome.automation.template.Template;
import org.eclipse.smarthome.automation.type.ActionType;
import org.eclipse.smarthome.automation.type.CompositeActionType;
import org.eclipse.smarthome.automation.type.CompositeConditionType;
import org.eclipse.smarthome.automation.type.CompositeTriggerType;
import org.eclipse.smarthome.automation.type.ConditionType;
import org.eclipse.smarthome.automation.type.ModuleType;
import org.eclipse.smarthome.automation.type.TriggerType;
/**
* This class provides common functionality of commands:
* <ul>
* <li>{@link AutomationCommands#LIST_MODULE_TYPES}
* <li>{@link AutomationCommands#LIST_TEMPLATES}
* <li>{@link AutomationCommands#LIST_RULES}
* </ul>
*
* @author Ana Dimova - Initial Contribution
*
*/
public class AutomationCommandList extends AutomationCommand {
/**
* This field serves to keep the UID of a {@link Rule}, {@link Template} or {@link ModuleType}, or part of it, or
* sequence number of a {@link Rule}, {@link Template}, or {@link ModuleType} in the list.
*/
private String id;
/**
* This field is used to search for templates or types of modules, which have been translated to the language from
* the locale. If the parameter <b>locale</b> is not passed to the command line then the default locale will be
* used.
*/
private Locale locale;
/**
* Distance of status column form previous column.
*/
private static final int STATUS_COLUMN_DISTANCE = 83;
/**
* @see AutomationCommand#AutomationCommand(String, String[], int, AutomationCommandsPluggable)
*/
public AutomationCommandList(String command, String[] params, int adminType,
AutomationCommandsPluggable autoCommands) {
super(command, params, adminType, autoCommands);
if (locale == null)
locale = Locale.getDefault();
}
/**
* This method is responsible for execution of commands:
* <ul>
* <li>{@link AutomationCommands#LIST_MODULE_TYPES}
* <li>{@link AutomationCommands#LIST_TEMPLATES}
* <li>{@link AutomationCommands#LIST_RULES}
* </ul>
*/
@Override
public String execute() {
if (parsingResult != SUCCESS) {
return parsingResult;
}
if (providerType == AutomationCommands.MODULE_TYPE_PROVIDER) {
return listModuleTypes();
}
if (providerType == AutomationCommands.TEMPLATE_PROVIDER) {
return listTemplates();
}
if (providerType == AutomationCommands.RULE_PROVIDER) {
return listRules();
}
return FAIL;
}
/**
* This method is invoked from the constructor to parse all parameters and options of the command <b>LIST</b>.
* If there are redundant parameters or options the result will be the failure of the command. This command has:
* <ul>
* <b>Options:</b>
* <ul>
* <li><b>PrintStackTrace</b> is common for all commands and its presence triggers printing of stack trace in case
* of exception.
* </ul>
* </ul>
* <ul>
* <b>Parameters:</b>
* <ul>
* <li><b>id</b> is optional and its presence triggers printing of details on specified automation object.
* <li><b>locale</b> is optional and it triggers printing of localized details on specified automation object. Its
* value is interpreted as <b>language</b> or <b>language tag</b>. If missing - the default locale will be used.
* </ul>
* </ul>
*/
@Override
protected String parseOptionsAndParameters(String[] parameterValues) {
boolean getId = true;
boolean getLocale = true;
for (int i = 0; i < parameterValues.length; i++) {
if (null == parameterValues[i]) {
continue;
}
if (parameterValues[i].charAt(0) == '-') {
if (parameterValues[i].equals(OPTION_ST)) {
st = true;
continue;
}
return String.format("Unsupported option: %s", parameterValues[i]);
}
if (getId) {
id = parameterValues[i];
getId = false;
continue;
}
if (getLocale) {
String l = parameterValues[i];
locale = new Locale(l);
getLocale = false;
}
if (getId && getLocale)
return String.format("Unsupported parameter: %s", parameterValues[i]);
}
return SUCCESS;
}
/**
* This method is responsible for execution of command {@link AutomationCommands#LIST_RULES}.
*
* @return a string representing understandable for the user message containing information on the outcome of the
* command {@link AutomationCommands#LIST_RULES}.
*/
private String listRules() {
Collection<Rule> collection = autoCommands.getRules();
Hashtable<String, Rule> rules = new Hashtable<String, Rule>();
Hashtable<String, String> listRules = null;
if (collection != null && !collection.isEmpty()) {
addCollection(collection, rules);
listRules = Utils.sortList(rules);
if (id != null) {
collection = getRuleByFilter(listRules);
if (collection.size() == 1) {
Rule r = (Rule) collection.toArray()[0];
if (r != null) {
RuleStatus status = autoCommands.getRuleStatus(r.getUID());
return Printer.printRule(r, status);
} else {
return String.format("Nonexistent ID: %s", id);
}
} else if (collection.isEmpty()) {
return String.format("Nonexistent ID: %s", id);
} else {
if (!rules.isEmpty())
rules.clear();
addCollection(collection, rules);
listRules = Utils.filterList(rules, listRules);
}
}
if (listRules != null && !listRules.isEmpty()) {
collectRuleStatuses(listRules);
return Printer.printRules(listRules);
}
}
return "There are no Rules available!";
}
/**
* Utility method for execution of command {@link AutomationCommands#LIST_RULES}.
* Concatenates the rule status plus separator to the rule UID.
*/
private void collectRuleStatuses(Hashtable<String, String> listRules) {
Hashtable<String, String> newList = new Hashtable<String, String>();
for (String uid : listRules.values()) {
StringBuilder res = new StringBuilder();
res.append(uid);
int count = STATUS_COLUMN_DISTANCE - uid.length();
RuleStatus status = autoCommands.getRuleStatus(uid);
if (status != null) {
Printer.printChars(res, ' ', count, false);
res.append(status.toString());
newList.put(uid, res.toString());
}
}
for (String id : listRules.keySet()) {
String uid = listRules.get(id);
String ruleDisp = newList.get(uid);
if (ruleDisp != null) {
listRules.put(id, ruleDisp);
}
}
}
/**
* This method is responsible for execution of command {@link AutomationCommands#LIST_TEMPLATES}.
*
* @return a string representing understandable for the user message containing information on the outcome of the
* command {@link AutomationCommands#LIST_TEMPLATES}.
*/
private String listTemplates() {
Collection<Template> collection = autoCommands.getTemplates(locale);
Hashtable<String, Template> templates = new Hashtable<String, Template>();
Hashtable<String, String> listTemplates = null;
if (collection != null && !collection.isEmpty()) {
addCollection(collection, templates);
listTemplates = Utils.sortList(templates);
if (id != null) {
collection = getTemplateByFilter(listTemplates);
if (collection.size() == 1) {
Template t = (Template) collection.toArray()[0];
if (t != null) {
return Printer.printTemplate(t);
} else {
return String.format("Nonexistent ID: %s", id);
}
} else if (collection.isEmpty()) {
return String.format("Nonexistent ID: %s", id);
} else {
if (!templates.isEmpty())
templates.clear();
addCollection(collection, templates);
listTemplates = Utils.filterList(templates, listTemplates);
}
}
if (listTemplates != null && !listTemplates.isEmpty()) {
return Printer.print(listTemplates);
}
}
return "There are no Templates available!";
}
/**
* This method is responsible for execution of command {@link AutomationCommands#LIST_MODULE_TYPES}.
*
* @return a string representing understandable for the user message containing information on the outcome of the
* command {@link AutomationCommands#LIST_MODULE_TYPES}.
*/
private String listModuleTypes() {
Collection<? extends ModuleType> collection = null;
Hashtable<String, ModuleType> moduleTypes = new Hashtable<String, ModuleType>();
Hashtable<String, String> listModuleTypes = null;
collection = autoCommands.getModuleTypes(TriggerType.class, locale);
addCollection(collection, moduleTypes);
collection = autoCommands.getModuleTypes(ConditionType.class, locale);
addCollection(collection, moduleTypes);
collection = autoCommands.getModuleTypes(ActionType.class, locale);
addCollection(collection, moduleTypes);
collection = autoCommands.getModuleTypes(CompositeTriggerType.class, locale);
addCollection(collection, moduleTypes);
collection = autoCommands.getModuleTypes(CompositeConditionType.class, locale);
addCollection(collection, moduleTypes);
collection = autoCommands.getModuleTypes(CompositeActionType.class, locale);
addCollection(collection, moduleTypes);
listModuleTypes = Utils.sortList(moduleTypes);
if (id != null) {
collection = getModuleTypeByFilter(listModuleTypes);
if (collection.size() == 1) {
ModuleType mt = (ModuleType) collection.toArray()[0];
if (mt != null) {
return Printer.printModuleType(mt);
} else {
return String.format("Nonexistent ID: %s", id);
}
} else if (collection.isEmpty()) {
return String.format("Nonexistent ID: %s", id);
} else {
if (!moduleTypes.isEmpty())
moduleTypes.clear();
addCollection(collection, moduleTypes);
listModuleTypes = Utils.filterList(moduleTypes, listModuleTypes);
}
}
if (listModuleTypes != null && !listModuleTypes.isEmpty()) {
return Printer.print(listModuleTypes);
}
return "There are no Module Types available!";
}
/**
* This method reduces the list of {@link Rule}s so that their unique identifier or part of it to match the
* {@link #id} or
* the index in the <tt>list</tt> to match the {@link #id}.
*
* @param list is the list of {@link Rule}s for reducing.
* @return a collection of {@link Rule}s that match the filter.
*/
private Collection<Rule> getRuleByFilter(Hashtable<String, String> list) {
Collection<Rule> rules = new ArrayList<Rule>();
if (!list.isEmpty()) {
Rule r = null;
String uid = list.get(id);
if (uid != null) {
r = autoCommands.getRule(uid);
if (r != null) {
rules.add(r);
return rules;
}
} else {
r = autoCommands.getRule(id);
if (r != null) {
rules.add(r);
return rules;
} else {
for (String ruleUID : list.values()) {
if (ruleUID.indexOf(id) > -1) {
rules.add(autoCommands.getRule(ruleUID));
}
}
}
}
}
return rules;
}
/**
* This method reduces the list of {@link Template}s so that their unique identifier or part of it to match the
* {@link #id} or
* the index in the <tt>list</tt> to match the {@link #id}.
*
* @param list is the list of {@link Template}s for reducing.
* @return a collection of {@link Template}s that match the filter.
*/
private Collection<Template> getTemplateByFilter(Hashtable<String, String> list) {
Collection<Template> templates = new ArrayList<Template>();
if (!list.isEmpty()) {
Template t = null;
String uid = list.get(id);
if (uid != null) {
t = autoCommands.getTemplate(uid, locale);
if (t != null) {
templates.add(t);
return templates;
}
} else {
t = autoCommands.getTemplate(id, locale);
if (t != null) {
templates.add(t);
return templates;
} else {
for (String templateUID : list.keySet()) {
if (templateUID.indexOf(id) != -1) {
templates.add(autoCommands.getTemplate(templateUID, locale));
}
}
}
}
}
return templates;
}
/**
* This method reduces the list of {@link ModuleType}s so that their unique identifier or part of it to match the
* {@link #id} or
* the index in the <tt>list</tt> to match the {@link #id}.
*
* @param list is the list of {@link ModuleType}s for reducing.
* @return a collection of {@link ModuleType}s that match the filter.
*/
private Collection<ModuleType> getModuleTypeByFilter(Hashtable<String, String> list) {
Collection<ModuleType> moduleTypes = new ArrayList<ModuleType>();
if (!list.isEmpty()) {
ModuleType mt = null;
String uid = list.get(id);
if (uid != null) {
mt = autoCommands.getModuleType(uid, locale);
if (mt != null) {
moduleTypes.add(mt);
return moduleTypes;
}
} else {
mt = autoCommands.getModuleType(id, locale);
if (mt != null) {
moduleTypes.add(mt);
return moduleTypes;
} else {
for (String typeUID : list.values()) {
if (typeUID.indexOf(id) != -1) {
moduleTypes.add(autoCommands.getModuleType(typeUID, locale));
}
}
}
}
}
return moduleTypes;
}
/**
* This method converts a {@link Collection} of {@link Rule}s, {@link Template}s or {@link ModuleType}s to a
* {@link Hashtable} with keys - the UID of the object and values - the object.
*
* @param collection is the {@link Collection} of {@link Rule}s, {@link Template}s or {@link ModuleType}s which
* must be converted.
* @param list is the {@link Hashtable} with keys - the UID of the object and values - the object, which must be
* filled with the objects from <tt>collection</tt>.
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
private void addCollection(Collection collection, Hashtable list) {
if (collection != null && !collection.isEmpty()) {
Iterator i = collection.iterator();
while (i.hasNext()) {
Object element = i.next();
if (element instanceof ModuleType) {
list.put(((ModuleType) element).getUID(), element);
}
if (element instanceof RuleTemplate) {
list.put(((RuleTemplate) element).getUID(), element);
}
if (element instanceof Rule) {
list.put(((Rule) element).getUID(), element);
}
}
}
}
public String getRuleStatus(RuleStatus status) {
if (status != null) {
StringBuffer writer = new StringBuffer();
writer.append(" [ ").append(status).append(" ] ");
return writer.toString();
}
return null;
}
}

Просмотреть файл

@ -0,0 +1,177 @@
/**
* 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.internal.commands;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import org.eclipse.smarthome.automation.Rule;
/**
* This class provides common functionality of commands:
* <ul>
* <li>{@link AutomationCommands#REMOVE_MODULE_TYPES}
* <li>{@link AutomationCommands#REMOVE_TEMPLATES}
* <li>{@link AutomationCommands#REMOVE_RULES}
* <li>{@link AutomationCommands#REMOVE_RULE}
* </ul>
*
* @author Ana Dimova - Initial Contribution
* @author Kai Kreuzer - fixed feedback when deleting non-existent rule
* @author Marin Mitev - removed prefixes in the output
*
*/
public class AutomationCommandRemove extends AutomationCommand {
/**
* This field keeps the UID of the {@link Rule} if command is {@link AutomationCommands#REMOVE_RULE}
*/
private String id;
/**
* This field keeps URL of the source of automation objects that has to be removed.
*/
private URL url;
/**
* @see AutomationCommand#AutomationCommand(String, String[], int, AutomationCommandsPluggable)
*/
public AutomationCommandRemove(String command, String[] params, int providerType,
AutomationCommandsPluggable autoCommands) {
super(command, params, providerType, autoCommands);
}
/**
* This method is responsible for execution of commands:
* <ul>
* <li>{@link AutomationCommands#REMOVE_MODULE_TYPES}
* <li>{@link AutomationCommands#REMOVE_TEMPLATES}
* <li>{@link AutomationCommands#REMOVE_RULES}
* <li>{@link AutomationCommands#REMOVE_RULE}
* </ul>
*/
@Override
public String execute() {
if (parsingResult != SUCCESS) {
return parsingResult;
}
switch (providerType) {
case AutomationCommands.MODULE_TYPE_PROVIDER:
if (autoCommands.remove(AutomationCommands.MODULE_TYPE_PROVIDER, url)) {
return SUCCESS;
}
return String.format("%s! ModuleTypeProvider not available!", FAIL);
case AutomationCommands.TEMPLATE_PROVIDER:
if (autoCommands.remove(AutomationCommands.TEMPLATE_PROVIDER, url)) {
return SUCCESS;
}
return String.format("%s! TemplateProvider not available!", FAIL);
case AutomationCommands.RULE_PROVIDER:
if (command == AutomationCommands.REMOVE_RULE) {
if (autoCommands.removeRule(id)) {
return SUCCESS;
}
} else {
if (autoCommands.removeRules(id)) {
return SUCCESS;
} else {
return String.format("Rule with id '%s' does not exist.", id);
}
}
return String.format("%s! RuleRegistry not available!", FAIL);
}
return FAIL;
}
/**
* This method serves to create an {@link URL} object or {@link File} object from a string that is passed as
* a parameter of the command. From the {@link File} object the URL is constructed.
*
* @param parameterValue is a string that is passed as parameter of the command and it supposed to be an URL
* representation.
* @return an {@link URL} object created from the string that is passed as parameter of the command or <b>null</b>
* if either no legal protocol could be found in the specified string or the string could not be parsed.
*/
private URL initURL(String parameterValue) {
try {
return new URL(parameterValue);
} catch (MalformedURLException mue) {
File f = new File(parameterValue);
if (f.isFile()) {
try {
return f.toURI().toURL();
} catch (MalformedURLException e) {
}
}
}
return null;
}
/**
* This method is invoked from the constructor to parse all parameters and options of the command <b>REMOVE</b>.
* If there are redundant parameters or options or the required are missing the result will be the failure of the
* command. This command has:
* <ul>
* <b>Options:</b>
* <ul>
* <li><b>PrintStackTrace</b> is common for all commands and its presence triggers printing of stack trace in case
* of exception.
* </ul>
* </ul>
* <ul>
* <b>Parameters:</b>
* <ul>
* <li><b>id</b> is required for {@link AutomationCommands#REMOVE_RULE} command. If it is present for all
* <b>REMOVE</b> commands, except {@link AutomationCommands#REMOVE_RULE}, it will be treated as redundant.
* <li><b>url</b> is required for all <b>REMOVE</b> commands, except {@link AutomationCommands#REMOVE_RULE}.
* If it is present for {@link AutomationCommands#REMOVE_RULE}, it will be treated as redundant.
* </ul>
* </ul>
*/
@Override
protected String parseOptionsAndParameters(String[] parameterValues) {
boolean getUrl = true;
boolean getId = true;
if (providerType == AutomationCommands.RULE_PROVIDER) {
getUrl = false;
} else {
getId = false;
}
for (int i = 0; i < parameterValues.length; i++) {
if (null == parameterValues[i]) {
continue;
}
if (parameterValues[i].equals(OPTION_ST)) {
st = true;
} else if (parameterValues[i].charAt(0) == '-') {
return String.format("Unsupported option: %s", parameterValues[i]);
} else if (getUrl) {
url = initURL(parameterValues[i]);
if (url != null) {
getUrl = false;
}
} else if (getId) {
id = parameterValues[i];
if (id != null) {
getId = false;
}
} else {
return String.format("Unsupported parameter: %s", parameterValues[i]);
}
}
if (getUrl) {
return "Missing source URL parameter!";
}
if (getId) {
return "Missing UID parameter!";
}
return SUCCESS;
}
}

Просмотреть файл

@ -0,0 +1,462 @@
/**
* 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.internal.commands;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Collection;
import java.util.Locale;
import java.util.Set;
import org.eclipse.smarthome.automation.Rule;
import org.eclipse.smarthome.automation.RuleStatus;
import org.eclipse.smarthome.automation.parser.ParsingException;
import org.eclipse.smarthome.automation.template.RuleTemplate;
import org.eclipse.smarthome.automation.template.Template;
import org.eclipse.smarthome.automation.template.TemplateProvider;
import org.eclipse.smarthome.automation.type.ActionType;
import org.eclipse.smarthome.automation.type.ConditionType;
import org.eclipse.smarthome.automation.type.ModuleType;
import org.eclipse.smarthome.automation.type.ModuleTypeProvider;
import org.eclipse.smarthome.automation.type.TriggerType;
import org.osgi.framework.BundleContext;
/**
* This class provides mechanism to separate the Automation Commands implementation from the Automation Core
* implementation.
*
* @author Ana Dimova - Initial Contribution
* @author Kai Kreuzer - refactored (managed) provider and registry implementation
*
*/
public abstract class AutomationCommands {
/**
* This static field is used to switch between providers in different commands.
*/
protected static final int RULE_PROVIDER = 1;
/**
* This static field is used to switch between providers in different commands.
*/
protected static final int TEMPLATE_PROVIDER = 2;
/**
* This static field is used to switch between providers in different commands.
*/
protected static final int MODULE_TYPE_PROVIDER = 3;
/**
* This static field is an identifier of the command {@link AutomationCommandImport} for {@link ModuleType}s.
*/
protected static final String IMPORT_MODULE_TYPES = "importModuleTypes";
/**
* This static field is a short identifier of the command {@link AutomationCommandImport} for {@link ModuleType}s.
*/
protected static final String IMPORT_MODULE_TYPES_SHORT = "imt";
/**
* This static field is an identifier of the command {@link AutomationCommandImport} for {@link RuleTemplate}s.
*/
protected static final String IMPORT_TEMPLATES = "importTemplates";
/**
* This static field is a short identifier of the command {@link AutomationCommandImport} for {@link RuleTemplate}s.
*/
protected static final String IMPORT_TEMPLATES_SHORT = "it";
/**
* This static field is an identifier of the command {@link AutomationCommandImport} for {@link Rule}s.
*/
protected static final String IMPORT_RULES = "importRules";
/**
* This static field is a short identifier of the command {@link AutomationCommandImport} for {@link Rule}s.
*/
protected static final String IMPORT_RULES_SHORT = "ir";
/**
* This static field is an identifier of the command {@link AutomationCommandExport} for {@link ModuleType}s.
*/
protected static final String EXPORT_MODULE_TYPES = "exportModuleTypes";
/**
* This static field is a short identifier of the command {@link AutomationCommandExport} for {@link ModuleType}s.
*/
protected static final String EXPORT_MODULE_TYPES_SHORT = "emt";
/**
* This static field is an identifier of the command {@link AutomationCommandExport} for {@link RuleTemplate}s.
*/
protected static final String EXPORT_TEMPLATES = "exportTemplates";
/**
* This static field is a short identifier of the command {@link AutomationCommandExport} for {@link RuleTemplate}s.
*/
protected static final String EXPORT_TEMPLATES_SHORT = "et";
/**
* This static field is an identifier of the command {@link AutomationCommandExport} for {@link Rule}s.
*/
protected static final String EXPORT_RULES = "exportRules";
/**
* This static field is a short identifier of the command {@link AutomationCommandExport} for {@link Rule}s.
*/
protected static final String EXPORT_RULES_SHORT = "er";
/**
* This static field is an identifier of the command {@link AutomationCommandRemove} for {@link Rule}.
*/
protected static final String REMOVE_RULE = "removeRule";
/**
* This static field is a short identifier of the command {@link AutomationCommandRemove} for {@link Rule}.
*/
protected static final String REMOVE_RULE_SHORT = "rmr";
/**
* This static field is an identifier of the command {@link AutomationCommandRemove} for {@link Rule}s.
*/
protected static final String REMOVE_RULES = "removeRules";
/**
* This static field is a short identifier of the command {@link AutomationCommandRemove} for {@link Rule}s.
*/
protected static final String REMOVE_RULES_SHORT = "rmrs";
/**
* This static field is an identifier of the command {@link AutomationCommandRemove} for {@link RuleTemplate}s.
*/
protected static final String REMOVE_TEMPLATES = "removeTemplates";
/**
* This static field is a short identifier of the command {@link AutomationCommandRemove} for {@link RuleTemplate}s.
*/
protected static final String REMOVE_TEMPLATES_SHORT = "rmts";
/**
* This static field is an identifier of the command {@link AutomationCommandRemove} for {@link ModuleType}s.
*/
protected static final String REMOVE_MODULE_TYPES = "removeModuleTypes";
/**
* This static field is a short identifier of the command {@link AutomationCommandRemove} for {@link ModuleType}s.
*/
protected static final String REMOVE_MODULE_TYPES_SHORT = "rmmts";
/**
* This static field is an identifier of the command {@link AutomationCommandList} for {@link ModuleType}s.
*/
protected static final String LIST_MODULE_TYPES = "listModuleTypes";
/**
* This static field is a short identifier of the command {@link AutomationCommandList} for {@link ModuleType}s.
*/
protected static final String LIST_MODULE_TYPES_SHORT = "lsmt";
/**
* This static field is an identifier of the command {@link AutomationCommandList} for {@link RuleTemplate}s.
*/
protected static final String LIST_TEMPLATES = "listTemplates";
/**
* This static field is a short identifier of the command {@link AutomationCommandList} for {@link RuleTemplate}s.
*/
protected static final String LIST_TEMPLATES_SHORT = "lst";
/**
* This static field is an identifier of the command {@link AutomationCommandList} for {@link Rule}s.
*/
protected static final String LIST_RULES = "listRules";
/**
* This static field is a short identifier of the command {@link AutomationCommandList} for {@link Rule}s.
*/
protected static final String LIST_RULES_SHORT = "lsr";
/**
* This static field is an identifier of the command {@link AutomationCommandEnableRule}.
*/
protected static final String ENABLE_RULE = "enableRule";
/**
* This static field is a short identifier of the command {@link AutomationCommandEnableRule}.
*/
protected static final String ENABLE_RULE_SHORT = "enr";
/**
* This field serves for the {@link ModuleTypeProvider} service and the {@link TemplateProvider} service
* registration.
*/
protected BundleContext bc;
/**
* This field holds a reference to the {@link CommandlineModuleTypeProvider} instance.
*/
protected CommandlineModuleTypeProvider moduleTypeProvider;
/**
* This field holds a reference to the {@link CommandlineTemplateProvider} instance.
*/
protected CommandlineTemplateProvider templateProvider;
/**
* This field holds a reference to the {@link CommandlineRuleImporter} instance.
*/
protected CommandlineRuleImporter ruleImporter;
/**
* This method is used for getting the rule corresponding to the specified UID from the RuleEngine.
*
* @param uid specifies the wanted {@link Rule} uniquely.
* @return a {@link Rule}, corresponding to the specified UID.
*/
public abstract Rule getRule(String uid);
/**
* This method is used to get the all existing rules from the RuleEngine.
*
* @return a collection of all existing rules in the RuleEngine.
*/
public abstract Collection<Rule> getRules();
public abstract RuleStatus getRuleStatus(String uid);
public abstract void setEnabled(String uid, boolean isEnabled);
/**
* This method is used for getting the {@link RuleTemplate} corresponding to the specified UID from the manager of
* the {@link Template}s.
*
* @param templateUID specifies the wanted {@link RuleTemplate} uniquely.
* @param locale a {@link Locale} that specifies the variant of the {@link RuleTemplate} that the user wants to see.
* Can be <code>null</code> and then the default locale will be used.
* @return a {@link RuleTemplate}, corresponding to the specified UID and locale.
*/
public abstract Template getTemplate(String templateUID, Locale locale);
/**
* This method is used for getting the collection of {@link RuleTemplate}s corresponding to the specified locale
* from the manager of the {@link Template}s.
*
* @param locale a {@link Locale} that specifies the variant of the {@link RuleTemplate}s that the user wants to
* see.
* Can be <code>null</code> and then the default locale will be used.
* @return a collection of {@link RuleTemplate}s, corresponding to the specified locale.
*/
public abstract Collection<Template> getTemplates(Locale locale);
/**
* This method is used for getting the {@link ModuleType} corresponding to the specified UID from the manager of the
* {@link ModuleType}s.
*
* @param typeUID specifies the wanted {@link ModuleType} uniquely.
* @param locale a {@link Locale} that specifies the variant of the {@link ModuleType} that the user wants to see.
* Can be <code>null</code> and then the default locale will be used.
* @return a {@link ModuleType}, corresponding to the specified UID and locale.
*/
public abstract ModuleType getModuleType(String typeUID, Locale locale);
/**
* This method is used for getting the collection of {@link ModuleType}s corresponding to the specified class and
* locale from the manager of the {@link ModuleType}s.
*
* @param clazz can be {@link TriggerType}, {@link ConditionType} or {@link ActionType} class.
* @param locale a {@link Locale} that specifies the variant of the {@link ModuleType}s that the user wants to see.
* Can be <code>null</code> and then the default locale will be used.
* @return a collection of {@link ModuleType}s from given class and locale.
*/
public abstract <T extends ModuleType> Collection<T> getModuleTypes(Class<T> clazz, Locale locale);
/**
* This method is used for removing a rule corresponding to the specified UID from the RuleEngine.
*
* @param uid specifies the wanted {@link Rule} uniquely.
* @return <b>true</b> if succeeds and <b>false</b> if fails.
*/
public abstract boolean removeRule(String uid);
/**
* This method is used for removing the rules from the RuleEngine, corresponding to the specified filter.
*
* @param ruleFilter specifies the wanted {@link Rule}s.
* @return <b>true</b> if succeeds and <b>false</b> if fails.
*/
public abstract boolean removeRules(String ruleFilter);
/**
* This method is responsible for choosing a particular class of commands and creates an instance of this class on
* the basis of the identifier of the command.
*
* @param command is the identifier of the command.
* @param parameterValues is an array of strings which are basis for initializing the options and parameters of the
* command. The order for their description is a random.
* @return an instance of the class corresponding to the identifier of the command.
*/
protected abstract AutomationCommand parseCommand(String command, String[] parameterValues);
/**
* This method is responsible for exporting a set of {@link ModuleType}s in a specified file.
*
* @param parserType is relevant to the format that you need for conversion of the {@link ModuleType}s in text.
* @param set a set of {@link ModuleType}s to export.
* @param file a specified file for export.
* @throws Exception when I/O operation has failed or has been interrupted or generating of the text fails
* for some reasons.
*/
public void exportModuleTypes(String parserType, Set<ModuleType> set, File file) throws Exception {
if (moduleTypeProvider != null) {
moduleTypeProvider.exportModuleTypes(parserType, set, file);
}
throw new Exception("Pluggable Commands Service not available.");
}
/**
* This method is responsible for exporting a set of {@link Template}s in a specified file.
*
* @param parserType is relevant to the format that you need for conversion of the {@link Template}s in text.
* @param set a set of {@link Template}s to export.
* @param file a specified file for export.
* @throws Exception when I/O operation has failed or has been interrupted or generating of the text fails
* for some reasons.
*/
public void exportTemplates(String parserType, Set<RuleTemplate> set, File file) throws Exception {
if (templateProvider != null) {
templateProvider.exportTemplates(parserType, set, file);
}
throw new Exception("Pluggable Commands Service not available.");
}
/**
* This method is responsible for exporting a set of {@link Rule}s in a specified file.
*
* @param parserType is relevant to the format that you need for conversion of the {@link Rule}s in text.
* @param set a set of {@link Rule}s to export.
* @param file a specified file for export.
* @throws Exception when I/O operation has failed or has been interrupted or generating of the text fails
* for some reasons.
*/
public void exportRules(String parserType, Set<Rule> set, File file) throws Exception {
if (ruleImporter != null) {
ruleImporter.exportRules(parserType, set, file);
}
throw new Exception("Pluggable Commands Service not available.");
}
/**
* This method is responsible for importing a set of {@link ModuleType}s from a specified file or URL resource.
*
* @param parserType is relevant to the format that you need for conversion of the {@link ModuleType}s from text.
* @param url is a specified file or URL resource.
* @return a set of {@link Status} objects, representing understandable for the user message containing information
* on the outcome of the import per each {@link ModuleType}.
* @throws ParsingException when parsing of the text fails for some reasons.
* @throws IOException when I/O operation has failed or has been interrupted.
* @throws Exception when Pluggable Commands Service not available.
*/
public Set<ModuleType> importModuleTypes(String parserType, URL url) throws Exception {
if (moduleTypeProvider != null) {
return moduleTypeProvider.importModuleTypes(parserType, url);
}
throw new Exception("Pluggable Commands Service not available.");
}
/**
* This method is responsible for importing a set of {@link Template}s from a specified file or URL resource.
*
* @param parserType is relevant to the format that you need for conversion of the {@link Template}s from text.
* @param url is a specified file or URL resource.
* @return a set of {@link Status} objects, representing understandable for the user message containing information
* on the outcome of the import per each {@link Template}.
* @throws ParsingException is thrown when parsing of the text fails for some reasons.
* @throws IOException is thrown when I/O operation has failed or has been interrupted.
* @throws Exception is thrown when Pluggable Commands Service not available.
*/
public Set<RuleTemplate> importTemplates(String parserType, URL url) throws Exception {
if (templateProvider != null) {
return templateProvider.importTemplates(parserType, url);
}
throw new Exception("Pluggable Commands Service not available.");
}
/**
* This method is responsible for importing a set of {@link Rule}s from a specified file or URL resource.
*
* @param parserType is relevant to the format that you need for conversion of the {@link Rule}s from text.
* @param url is a specified file or URL resource.
* @return a set of {@link Status} objects, representing understandable for the user message containing information
* on the outcome of the import per each {@link Rule}.
* @throws ParsingException is thrown when parsing of the text fails for some reasons.
* @throws IOException is thrown when I/O operation has failed or has been interrupted.
* @throws Exception is thrown when Pluggable Commands Service not available.
*/
public Set<Rule> importRules(String parserType, URL url) throws Exception {
if (ruleImporter != null) {
return ruleImporter.importRules(parserType, url);
}
throw new Exception("Pluggable Commands Service not available.");
}
/**
* This method is responsible for removing a set of objects loaded from a specified file or URL resource.
*
* @param providerType specifies the provider responsible for removing the objects loaded from a specified file or
* URL resource.
* @param url is a specified file or URL resource.
* @return <b>true</b> if succeeds and <b>false</b> if fails.
*/
public boolean remove(int providerType, URL url) {
switch (providerType) {
case AutomationCommands.MODULE_TYPE_PROVIDER:
if (moduleTypeProvider != null) {
return moduleTypeProvider.remove(url);
}
break;
case AutomationCommands.TEMPLATE_PROVIDER:
if (templateProvider != null) {
return templateProvider.remove(url);
}
break;
}
return false;
}
/**
* This method is responsible for execution of every particular command and to return the result of the execution.
*
* @param command is an identifier of the command.
* @param parameterValues is an array of strings which are basis for initializing the options and parameters of the
* command.
* The order for their description is a random.
* @return understandable for the user message containing information on the outcome of the command.
*/
public String executeCommand(String command, String[] parameterValues) {
AutomationCommand commandInst = parseCommand(command, parameterValues);
if (commandInst != null) {
return commandInst.execute();
}
return String.format("Command \"%s\" is not supported!", command);
}
/**
* This method closes the providers and the importer and unregisters the services {@link ModuleTypeProvider} and
* {@link TemplateProvider}.
*/
public void stop() {
moduleTypeProvider.close();
templateProvider.close();
ruleImporter.close();
moduleTypeProvider = null;
templateProvider = null;
ruleImporter = null;
}
}

Просмотреть файл

@ -0,0 +1,404 @@
/**
* 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.internal.commands;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import org.apache.commons.lang.StringUtils;
import org.eclipse.smarthome.automation.Rule;
import org.eclipse.smarthome.automation.RuleRegistry;
import org.eclipse.smarthome.automation.RuleStatus;
import org.eclipse.smarthome.automation.RuleStatusInfo;
import org.eclipse.smarthome.automation.template.Template;
import org.eclipse.smarthome.automation.template.TemplateRegistry;
import org.eclipse.smarthome.automation.type.ModuleType;
import org.eclipse.smarthome.automation.type.ModuleTypeRegistry;
import org.eclipse.smarthome.io.console.Console;
import org.eclipse.smarthome.io.console.extensions.ConsoleCommandExtension;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Filter;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.util.tracker.ServiceTrackerCustomizer;
/**
* This class provides functionality for defining and executing automation commands for importing, exporting, removing
* and listing the automation objects.
*
* @author Ana Dimova - Initial Contribution
* @author Kai Kreuzer - refactored (managed) provider and registry implementation
*
*/
@SuppressWarnings("rawtypes")
public class AutomationCommandsPluggable extends AutomationCommands
implements ServiceTrackerCustomizer, ConsoleCommandExtension {
/**
* This constant defines the command group name.
*/
public static final String NAME = "automation";
/**
* This constant describes the commands group.
*/
public static final String DESCRIPTION = "Commands for managing Automation Rules, Templates and ModuleTypes resources.";
/**
* This field holds the reference to the {@code RuleRegistry} providing the {@code Rule} automation objects.
*/
static RuleRegistry ruleRegistry;
/**
* This field holds the reference to the {@code TemplateRegistry} providing the {@code Template} automation objects.
*/
static TemplateRegistry templateRegistry;
/**
* This field holds the reference to the {@code ModuleTypeRegistry} providing the {@code ModuleType} automation
* objects.
*/
static ModuleTypeRegistry moduleTypeRegistry;
/**
* This constant is defined for compatibility and is used to switch to a particular provider of {@code ModuleType}
* automation objects.
*/
private static final int MODULE_TYPE_REGISTRY = 3;
/**
* This constant is defined for compatibility and is used to switch to a particular provider of {@code Template}
* automation objects.
*/
private static final int TEMPLATE_REGISTRY = 2;
/**
* This constant is defined for compatibility and is used to switch to a particular provider of {@code Rule}
* automation objects.
*/
private static final int RULE_REGISTRY = 1;
/**
* This field holds a reference to the tracker for {@code RuleRegistry}, {@code TemplateRegistry} and
* {@code ModuleTypeRegistry}.
*/
private ServiceTracker tracker;
/**
* This field holds a reference to the {@code ServiceRegistration} of the Automation Console Commands service.
*/
private ServiceRegistration commandsServiceReg;
/**
* This constructor is responsible for creating a tracker for {@code RuleRegistry}, {@code TemplateRegistry} and
* {@code ModuleTypeRegistry}. Also it registers the Automation Console Commands service.
*
* @param bc is the bundle's execution context within the Framework.
*/
@SuppressWarnings("unchecked")
public AutomationCommandsPluggable(BundleContext bc) {
this.bc = bc;
moduleTypeProvider = new CommandlineModuleTypeProvider(bc);
templateProvider = new CommandlineTemplateProvider(bc);
ruleImporter = new CommandlineRuleImporter(bc);
try {
Filter filter = bc.createFilter("(|(objectClass=" + RuleRegistry.class.getName() + ")(objectClass="
+ TemplateRegistry.class.getName() + ")(objectClass=" + ModuleTypeRegistry.class.getName() + "))");
tracker = new ServiceTracker(bc, filter, this);
tracker.open();
} catch (InvalidSyntaxException e) {
e.printStackTrace();
}
commandsServiceReg = bc.registerService(ConsoleCommandExtension.class.getName(), this, null);
}
/**
* This method extends the parent functionality with unregistering the Automation Console Commands service and
* stopping the tracker for {@code RuleRegistry}, {@code TemplateRegistry} and {@code ModuleTypeRegistry}.
*/
@Override
public void stop() {
commandsServiceReg.unregister();
if (tracker != null) {
tracker.close();
tracker = null;
}
super.stop();
}
@SuppressWarnings("unchecked")
@Override
public Object addingService(ServiceReference reference) {
Object service = bc.getService(reference);
if (service instanceof TemplateRegistry) {
AutomationCommandsPluggable.templateRegistry = (TemplateRegistry) service;
}
if (service instanceof RuleRegistry) {
AutomationCommandsPluggable.ruleRegistry = (RuleRegistry) service;
}
if (service instanceof ModuleTypeRegistry) {
AutomationCommandsPluggable.moduleTypeRegistry = (ModuleTypeRegistry) service;
}
return service;
}
@Override
public void modifiedService(ServiceReference reference, Object service) {
}
@Override
public void removedService(ServiceReference reference, Object service) {
if (service == templateRegistry) {
templateRegistry = null;
}
if (service == ruleRegistry) {
ruleRegistry = null;
}
if (service == moduleTypeRegistry) {
moduleTypeRegistry = null;
}
}
@Override
public void execute(String[] args, Console console) {
if (args.length == 0) {
console.println(StringUtils.join(getUsages(), "\n"));
return;
}
String command = args[0];// the first argument is the subcommand name
String[] params = new String[args.length - 1];// extract the remaining arguments except the first one
if (params.length > 0) {
System.arraycopy(args, 1, params, 0, params.length);
}
String res = super.executeCommand(command, params);
if (res == null) {
console.println(String.format("Unsupported command %s", command));
} else {
console.println(res);
}
}
@Override
public List<String> getUsages() {
return Arrays.asList(new String[] {
buildCommandUsage(LIST_MODULE_TYPES + " [-st] <filter> <language>",
"lists all Module Types. If filter is present, lists only matching Module Types."
+ " If language is missing, the default language will be used."),
buildCommandUsage(LIST_TEMPLATES + " [-st] <filter> <language>",
"lists all Templates. If filter is present, lists only matching Templates."
+ " If language is missing, the default language will be used."),
buildCommandUsage(LIST_RULES + " [-st] <filter>",
"lists all Rules. If filter is present, lists only matching Rules"),
buildCommandUsage(REMOVE_MODULE_TYPES + " [-st] <url>",
"Removes the Module Types, loaded from the given url"),
buildCommandUsage(REMOVE_TEMPLATES + " [-st] <url>",
"Removes the Templates, loaded from the given url"),
buildCommandUsage(REMOVE_RULE + " [-st] <uid>", "Removes the rule, specified by given UID"),
buildCommandUsage(REMOVE_RULES + " [-st] <filter>",
"Removes the rules. If filter is present, removes only matching Rules"),
buildCommandUsage(IMPORT_MODULE_TYPES + " [-p] <parserType> [-st] <url>",
"Imports Module Types from given url. If parser type missing, \"json\" parser will be set as default"),
buildCommandUsage(IMPORT_TEMPLATES + " [-p] <parserType> [-st] <url>",
"Imports Templates from given url. If parser type missing, \"json\" parser will be set as default"),
buildCommandUsage(IMPORT_RULES + " [-p] <parserType> [-st] <url>",
"Imports Rules from given url. If parser type missing, \"json\" parser will be set as default"),
buildCommandUsage(EXPORT_MODULE_TYPES + " [-p] <parserType> [-st] <file>",
"Exports Module Types in a file. If parser type missing, \"json\" parser will be set as default"),
buildCommandUsage(EXPORT_TEMPLATES + " [-p] <parserType> [-st] <file>",
"Exports Templates in a file. If parser type missing, \"json\" parser will be set as default"),
buildCommandUsage(EXPORT_RULES + " [-p] <parserType> [-st] <file>",
"Exports Rules in a file. If parser type missing, \"json\" parser will be set as default"),
buildCommandUsage(ENABLE_RULE + " [-st] <uid> <enable>",
"Enables the Rule, specified by given UID. If enable parameter is missing, "
+ "the result of the command will be visualization of enabled/disabled state of the rule, "
+ "if its value is \"true\" or \"false\", "
+ "the result of the command will be to set enable/disable on the Rule.") });
}
@Override
public String getCommand() {
return NAME;
}
@Override
public String getDescription() {
return DESCRIPTION;
}
@Override
public Rule getRule(String uid) {
if (ruleRegistry != null) {
return ruleRegistry.get(uid);
}
return null;
}
@Override
public Template getTemplate(String templateUID, Locale locale) {
if (templateRegistry != null) {
return templateRegistry.get(templateUID, locale);
}
return null;
}
@Override
public Collection<Template> getTemplates(Locale locale) {
if (templateRegistry != null) {
return templateRegistry.getAll(locale);
}
return null;
}
@Override
public ModuleType getModuleType(String typeUID, Locale locale) {
if (moduleTypeRegistry != null) {
return moduleTypeRegistry.get(typeUID, locale);
}
return null;
}
@Override
public <T extends ModuleType> Collection<T> getModuleTypes(Class<T> clazz, Locale locale) {
if (moduleTypeRegistry != null) {
return moduleTypeRegistry.getAll(clazz, locale);
}
return null;
}
@Override
public boolean removeRule(String uid) {
if (ruleRegistry != null) {
if (ruleRegistry.remove(uid) != null) {
return true;
}
return false;
}
return false;
}
@Override
public boolean removeRules(String ruleFilter) {
boolean res = false;
if (ruleRegistry != null) {
ruleRegistry.remove(ruleFilter);
}
return res;
}
@Override
protected AutomationCommand parseCommand(String command, String[] params) {
if (command.equalsIgnoreCase(IMPORT_MODULE_TYPES)) {
return new AutomationCommandImport(IMPORT_MODULE_TYPES, params, MODULE_TYPE_REGISTRY, this);
}
if (command.equalsIgnoreCase(EXPORT_MODULE_TYPES)) {
return new AutomationCommandExport(EXPORT_MODULE_TYPES, params, MODULE_TYPE_REGISTRY, this);
}
if (command.equalsIgnoreCase(LIST_MODULE_TYPES)) {
return new AutomationCommandList(LIST_MODULE_TYPES, params, MODULE_TYPE_REGISTRY, this);
}
if (command.equalsIgnoreCase(IMPORT_TEMPLATES)) {
return new AutomationCommandImport(IMPORT_TEMPLATES, params, TEMPLATE_REGISTRY, this);
}
if (command.equalsIgnoreCase(EXPORT_TEMPLATES)) {
return new AutomationCommandExport(EXPORT_TEMPLATES, params, TEMPLATE_REGISTRY, this);
}
if (command.equalsIgnoreCase(LIST_TEMPLATES)) {
return new AutomationCommandList(LIST_TEMPLATES, params, TEMPLATE_REGISTRY, this);
}
if (command.equalsIgnoreCase(IMPORT_RULES)) {
return new AutomationCommandImport(IMPORT_RULES, params, RULE_REGISTRY, this);
}
if (command.equalsIgnoreCase(EXPORT_RULES)) {
return new AutomationCommandExport(EXPORT_RULES, params, RULE_REGISTRY, this);
}
if (command.equalsIgnoreCase(LIST_RULES)) {
return new AutomationCommandList(LIST_RULES, params, RULE_REGISTRY, this);
}
if (command.equalsIgnoreCase(REMOVE_TEMPLATES)) {
return new AutomationCommandRemove(REMOVE_TEMPLATES, params, TEMPLATE_REGISTRY, this);
}
if (command.equalsIgnoreCase(REMOVE_MODULE_TYPES)) {
return new AutomationCommandRemove(REMOVE_MODULE_TYPES, params, MODULE_TYPE_REGISTRY, this);
}
if (command.equalsIgnoreCase(REMOVE_RULE)) {
return new AutomationCommandRemove(REMOVE_RULE, params, RULE_REGISTRY, this);
}
if (command.equalsIgnoreCase(REMOVE_RULES)) {
return new AutomationCommandRemove(REMOVE_RULES, params, RULE_REGISTRY, this);
}
if (command.equalsIgnoreCase(ENABLE_RULE)) {
return new AutomationCommandEnableRule(ENABLE_RULE, params, RULE_REGISTRY, this);
}
return null;
}
/**
* Build a command usage string.
*
* You should always use that function to use a usage string that complies
* to a standard format.
*
* @param description
* the description of the command
* @return a usage string that complies to a standard format
*/
protected String buildCommandUsage(final String description) {
return String.format("%s - %s", getCommand(), description);
}
/**
* Build a command usage string.
*
* You should always use that function to use a usage string that complies
* to a standard format.
*
* @param syntax
* the syntax format
* @param description
* the description of the command
* @return a usage string that complies to a standard format
*/
protected String buildCommandUsage(final String syntax, final String description) {
return String.format("%s %s - %s", getCommand(), syntax, description);
}
@Override
public Collection<Rule> getRules() {
if (ruleRegistry != null) {
return ruleRegistry.getAll();
} else {
return null;
}
}
@Override
public RuleStatus getRuleStatus(String ruleUID) {
if (ruleRegistry != null) {
RuleStatusInfo rsi = ruleRegistry.getStatus(ruleUID);
return rsi != null ? rsi.getStatus() : null;
} else {
return null;
}
}
@Override
public void setEnabled(String uid, boolean isEnabled) {
if (ruleRegistry != null) {
ruleRegistry.setEnabled(uid, isEnabled);
}
}
}

Просмотреть файл

@ -0,0 +1,232 @@
/**
* 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.internal.commands;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import org.eclipse.smarthome.automation.parser.Parser;
import org.eclipse.smarthome.automation.parser.ParsingException;
import org.eclipse.smarthome.automation.parser.ParsingNestedException;
import org.eclipse.smarthome.automation.template.TemplateProvider;
import org.eclipse.smarthome.automation.type.ModuleType;
import org.eclipse.smarthome.automation.type.ModuleTypeProvider;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
/**
* This class is implementation of {@link ModuleTypeProvider}. It extends functionality of
* {@link AbstractCommandProvider}.
* <p>
* It is responsible for execution of Automation {@link PluggableCommands}, corresponding to the {@link ModuleType}s:
* <ul>
* <li>imports the {@link ModuleType}s from local files or from URL resources
* <li>provides functionality for persistence of the {@link ModuleType}s
* <li>removes the {@link ModuleType}s and their persistence
* <li>lists the {@link ModuleType}s and their details
* </ul>
* <p>
* accordingly to the used command.
*
* @author Ana Dimova - Initial Contribution
* @author Kai Kreuzer - refactored (managed) provider and registry implementation
*
*/
public class CommandlineModuleTypeProvider extends AbstractCommandProvider<ModuleType>implements ModuleTypeProvider {
/**
* This field holds a reference to the {@link TemplateProvider} service registration.
*/
@SuppressWarnings("rawtypes")
protected ServiceRegistration mtpReg;
/**
* This constructor creates instances of this particular implementation of {@link ModuleTypeProvider}. It does not
* add any new functionality to the constructors of the providers. Only provides consistency by invoking the
* parent's constructor.
*
* @param context is the {@code BundleContext}, used for creating a tracker for {@link Parser} services.
*/
public CommandlineModuleTypeProvider(BundleContext context) {
super(context);
}
/**
* This method differentiates what type of {@link Parser}s is tracked by the tracker.
* For this concrete provider, this type is a {@link ModuleType} {@link Parser}.
*
* @see AbstractCommandProvider#addingService(org.osgi.framework.ServiceReference)
*/
@Override
public Object addingService(@SuppressWarnings("rawtypes") ServiceReference reference) {
if (reference.getProperty(Parser.PARSER_TYPE).equals(Parser.PARSER_MODULE_TYPE)) {
return super.addingService(reference);
}
return null;
}
/**
* This method is responsible for exporting a set of ModuleTypes in a specified file.
*
* @param parserType is relevant to the format that you need for conversion of the ModuleTypes in text.
* @param set a set of ModuleTypes to export.
* @param file a specified file for export.
* @throws Exception when I/O operation has failed or has been interrupted or generating of the text fails
* for some reasons.
* @see AutomationCommandsPluggable#exportModuleTypes(String, Set, File)
*/
public void exportModuleTypes(String parserType, Set<ModuleType> set, File file) throws Exception {
super.exportData(parserType, set, file);
}
/**
* This method is responsible for importing a set of ModuleTypes from a specified file or URL resource.
*
* @param parserType is relevant to the format that you need for conversion of the ModuleTypes in text.
* @param url a specified URL for import.
* @throws IOException when I/O operation has failed or has been interrupted.
* @throws ParsingException when parsing of the text fails for some reasons.
* @see AutomationCommandsPluggable#importModuleTypes(String, URL)
*/
public Set<ModuleType> importModuleTypes(String parserType, URL url) throws IOException, ParsingException {
InputStreamReader inputStreamReader = null;
Parser<ModuleType> parser = parsers.get(parserType);
if (parser != null) {
InputStream is = url.openStream();
BufferedInputStream bis = new BufferedInputStream(is);
inputStreamReader = new InputStreamReader(bis);
return importData(url, parser, inputStreamReader);
} else {
throw new ParsingException(new ParsingNestedException(ParsingNestedException.MODULE_TYPE, null,
new Exception("Parser " + parserType + " not available")));
}
}
@SuppressWarnings("unchecked")
@Override
public ModuleType getModuleType(String UID, Locale locale) {
synchronized (providedObjectsHolder) {
return providedObjectsHolder.get(UID);
}
}
@Override
public Collection<ModuleType> getModuleTypes(Locale locale) {
synchronized (providedObjectsHolder) {
return !providedObjectsHolder.isEmpty() ? providedObjectsHolder.values()
: Collections.<ModuleType> emptyList();
}
}
/**
* This method is responsible for removing a set of objects loaded from a specified file or URL resource.
*
* @param providerType specifies the provider responsible for removing the objects loaded from a specified file or
* URL resource.
* @param url is a specified file or URL resource.
* @return <b>true</b> if succeeds and <b>false</b> if fails.
*/
public boolean remove(URL url) {
List<String> portfolio = null;
synchronized (providerPortfolio) {
portfolio = providerPortfolio.remove(url);
}
if (portfolio != null && !portfolio.isEmpty()) {
synchronized (providedObjectsHolder) {
for (String uid : portfolio) {
providedObjectsHolder.remove(uid);
}
}
return true;
}
return false;
}
@Override
public void close() {
if (mtpReg != null) {
mtpReg.unregister();
mtpReg = null;
}
super.close();
}
@SuppressWarnings("unchecked")
@Override
protected Set<ModuleType> importData(URL url, Parser<ModuleType> parser, InputStreamReader inputStreamReader)
throws ParsingException {
Set<ModuleType> providedObjects = parser.parse(inputStreamReader);
if (providedObjects != null && !providedObjects.isEmpty()) {
String uid = null;
List<String> portfolio = new ArrayList<String>();
synchronized (providerPortfolio) {
providerPortfolio.put(url, portfolio);
}
List<ParsingNestedException> importDataExceptions = new ArrayList<ParsingNestedException>();
for (ModuleType providedObject : providedObjects) {
List<ParsingNestedException> exceptions = new ArrayList<ParsingNestedException>();
uid = providedObject.getUID();
checkExistence(uid, exceptions);
if (exceptions.isEmpty()) {
portfolio.add(uid);
synchronized (providedObjectsHolder) {
providedObjectsHolder.put(uid, providedObject);
}
} else
importDataExceptions.addAll(exceptions);
}
if (importDataExceptions.isEmpty()) {
Dictionary<String, Object> properties = new Hashtable<String, Object>();
properties.put(REG_PROPERTY_MODULE_TYPES, providedObjectsHolder.keySet());
if (mtpReg == null)
mtpReg = bc.registerService(ModuleTypeProvider.class.getName(), this, properties);
else {
mtpReg.setProperties(properties);
}
} else {
throw new ParsingException(importDataExceptions);
}
}
return providedObjects;
}
/**
* This method is responsible for checking the existence of {@link ModuleType}s with the same
* UIDs before these objects to be added in the system.
*
* @param uid UID of the newly created {@link ModuleType}, which to be checked.
* @param exceptions accumulates exceptions if {@link ModuleType} with the same UID exists.
*/
protected void checkExistence(String uid, List<ParsingNestedException> exceptions) {
if (AutomationCommandsPluggable.moduleTypeRegistry == null) {
exceptions.add(new ParsingNestedException(ParsingNestedException.MODULE_TYPE, uid,
new IllegalArgumentException("Failed to create Module Type with UID \"" + uid
+ "\"! Can't guarantee yet that other Module Type with the same UID does not exist.")));
}
if (AutomationCommandsPluggable.moduleTypeRegistry.get(uid) != null) {
exceptions.add(new ParsingNestedException(ParsingNestedException.MODULE_TYPE, uid,
new IllegalArgumentException("Module Type with UID \"" + uid
+ "\" already exists! Failed to create a second with the same UID!")));
}
}
}

Просмотреть файл

@ -0,0 +1,122 @@
/**
* 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.internal.commands;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Iterator;
import java.util.Set;
import org.eclipse.smarthome.automation.Rule;
import org.eclipse.smarthome.automation.parser.Parser;
import org.eclipse.smarthome.automation.parser.ParsingException;
import org.eclipse.smarthome.automation.parser.ParsingNestedException;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
/**
* This class is a {@link Rule}s importer. It extends functionality of {@link AbstractCommandProvider}.
* <p>
* It is responsible for execution of Automation Commands, corresponding to the {@link Rule}s:
* <ul>
* <li>imports the {@link Rule}s from local files or from URL resources
* <li>provides functionality for persistence of the {@link Rule}s
* <li>removes the {@link Rule}s and their persistence
* <li>lists the {@link Rule}s and their details
* </ul>
*
* @author Ana Dimova - Initial Contribution
* @author Kai Kreuzer - refactored (managed) provider and registry implementation
*
*/
public class CommandlineRuleImporter extends AbstractCommandProvider<Rule> {
/**
* This constructor creates instances of this particular implementation of Rule Importer. It does not add any new
* functionality to the constructors of the providers. Only provides consistency by invoking the parent's
* constructor.
*
* @param context is the {@link BundleContext}, used for creating a tracker for {@link Parser} services.
*/
public CommandlineRuleImporter(BundleContext context) {
super(context);
}
/**
* This method differentiates what type of {@link Parser}s is tracked by the tracker.
* For this concrete provider, this type is a {@link Rule} {@link Parser}.
*
* @see AbstractCommandProvider#addingService(org.osgi.framework.ServiceReference)
*/
@Override
public Object addingService(@SuppressWarnings("rawtypes") ServiceReference reference) {
if (reference.getProperty(Parser.PARSER_TYPE).equals(Parser.PARSER_RULE)) {
return super.addingService(reference);
}
return null;
}
/**
* This method is responsible for exporting a set of Rules in a specified file.
*
* @param parserType is relevant to the format that you need for conversion of the Rules in text.
* @param set a set of Rules to export.
* @param file a specified file for export.
* @throws Exception when I/O operation has failed or has been interrupted or generating of the text fails
* for some reasons.
* @see AutomationCommandsPluggable#exportRules(String, Set, File)
*/
public void exportRules(String parserType, Set<Rule> set, File file) throws Exception {
super.exportData(parserType, set, file);
}
/**
* This method is responsible for importing a set of Rules from a specified file or URL resource.
*
* @param parserType is relevant to the format that you need for conversion of the Rules in text.
* @param url a specified URL for import.
* @throws IOException when I/O operation has failed or has been interrupted.
* @throws ParsingException when parsing of the text fails for some reasons.
* @see AutomationCommandsPluggable#importRules(String, URL)
*/
public Set<Rule> importRules(String parserType, URL url) throws IOException, ParsingException {
InputStreamReader inputStreamReader = null;
Parser<Rule> parser = parsers.get(parserType);
if (parser != null) {
inputStreamReader = new InputStreamReader(new BufferedInputStream(url.openStream()));
return importData(url, parser, inputStreamReader);
} else {
throw new ParsingException(new ParsingNestedException(ParsingNestedException.RULE, null,
new Exception("Parser " + parserType + " not available")));
}
}
@Override
protected Set<Rule> importData(URL url, Parser<Rule> parser, InputStreamReader inputStreamReader)
throws ParsingException {
Set<Rule> providedRules = parser.parse(inputStreamReader);
if (providedRules != null && !providedRules.isEmpty()) {
Iterator<Rule> i = providedRules.iterator();
while (i.hasNext()) {
Rule rule = i.next();
if (rule != null) {
if (AutomationCommandsPluggable.ruleRegistry.get(rule.getUID()) != null) {
AutomationCommandsPluggable.ruleRegistry.update(rule);
} else {
AutomationCommandsPluggable.ruleRegistry.add(rule);
}
}
}
}
return providedRules;
}
}

Просмотреть файл

@ -0,0 +1,224 @@
/**
* 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.internal.commands;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import org.eclipse.smarthome.automation.parser.Parser;
import org.eclipse.smarthome.automation.parser.ParsingException;
import org.eclipse.smarthome.automation.parser.ParsingNestedException;
import org.eclipse.smarthome.automation.template.RuleTemplate;
import org.eclipse.smarthome.automation.template.Template;
import org.eclipse.smarthome.automation.template.TemplateProvider;
import org.eclipse.smarthome.automation.type.ModuleType;
import org.eclipse.smarthome.automation.type.ModuleTypeProvider;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
/**
* This class is implementation of {@link TemplateProvider}. It extends functionality of {@link AbstractCommandProvider}
* <p>
* It is responsible for execution of Automation {@link PluggableCommands}, corresponding to the {@link RuleTemplate}s:
* <ul>
* <li>imports the {@link RuleTemplate}s from local files or from URL resources
* <li>provides functionality for persistence of the {@link RuleTemplate}s
* <li>removes the {@link RuleTemplate}s and their persistence
* </ul>
*
* @author Ana Dimova - Initial Contribution
* @author Kai Kreuzer - refactored (managed) provider and registry implementation
*
*/
public class CommandlineTemplateProvider extends AbstractCommandProvider<RuleTemplate>implements TemplateProvider {
/**
* This field holds a reference to the {@link ModuleTypeProvider} service registration.
*/
@SuppressWarnings("rawtypes")
protected ServiceRegistration tpReg;
/**
* This constructor creates instances of this particular implementation of {@link TemplateProvider}. It does not add
* any new functionality to the constructors of the providers. Only provides consistency by invoking the parent's
* constructor.
*
* @param context is the {@link BundleContext}, used for creating a tracker for {@link Parser} services.
*/
public CommandlineTemplateProvider(BundleContext context) {
super(context);
}
/**
* This method differentiates what type of {@link Parser}s is tracked by the tracker.
* For this concrete provider, this type is a {@link RuleTemplate} {@link Parser}.
*
* @see AbstractCommandProvider#addingService(org.osgi.framework.ServiceReference)
*/
@Override
public Object addingService(@SuppressWarnings("rawtypes") ServiceReference reference) {
if (reference.getProperty(Parser.PARSER_TYPE).equals(Parser.PARSER_TEMPLATE)) {
return super.addingService(reference);
}
return null;
}
/**
* This method is responsible for exporting a set of RuleTemplates in a specified file.
*
* @param parserType is relevant to the format that you need for conversion of the RuleTemplates in text.
* @param set a set of RuleTemplates to export.
* @param file a specified file for export.
* @throws Exception when I/O operation has failed or has been interrupted or generating of the text fails
* for some reasons.
* @see AutomationCommandsPluggable#exportTemplates(String, Set, File)
*/
public void exportTemplates(String parserType, Set<RuleTemplate> set, File file) throws Exception {
super.exportData(parserType, set, file);
}
/**
* This method is responsible for importing a set of RuleTemplates from a specified file or URL resource.
*
* @param parserType is relevant to the format that you need for conversion of the RuleTemplates in text.
* @param url a specified URL for import.
* @throws IOException when I/O operation has failed or has been interrupted.
* @throws ParsingException when parsing of the text fails for some reasons.
* @see AutomationCommandsPluggable#importTemplates(String, URL)
*/
public Set<RuleTemplate> importTemplates(String parserType, URL url) throws IOException, ParsingException {
InputStreamReader inputStreamReader = null;
Parser<RuleTemplate> parser = parsers.get(parserType);
if (parser == null) {
inputStreamReader = new InputStreamReader(new BufferedInputStream(url.openStream()));
return importData(url, parser, inputStreamReader);
} else {
throw new ParsingException(new ParsingNestedException(ParsingNestedException.TEMPLATE, null,
new Exception("Parser " + parserType + " not available")));
}
}
@SuppressWarnings("unchecked")
@Override
public RuleTemplate getTemplate(String UID, Locale locale) {
synchronized (providerPortfolio) {
return providedObjectsHolder.get(UID);
}
}
@SuppressWarnings("unchecked")
@Override
public Collection<RuleTemplate> getTemplates(Locale locale) {
synchronized (providedObjectsHolder) {
return providedObjectsHolder.values();
}
}
/**
* This method is responsible for removing a set of objects loaded from a specified file or URL resource.
*
* @param providerType specifies the provider responsible for removing the objects loaded from a specified file or
* URL resource.
* @param url is a specified file or URL resource.
* @return <b>true</b> if succeeds and <b>false</b> if fails.
*/
public boolean remove(URL url) {
List<String> portfolio = null;
synchronized (providerPortfolio) {
portfolio = providerPortfolio.remove(url);
}
if (portfolio != null && !portfolio.isEmpty()) {
synchronized (providedObjectsHolder) {
for (String uid : portfolio) {
providedObjectsHolder.remove(uid);
}
}
return true;
}
return false;
}
@Override
public void close() {
if (tpReg != null) {
tpReg.unregister();
tpReg = null;
}
super.close();
}
@SuppressWarnings("unchecked")
@Override
protected Set<RuleTemplate> importData(URL url, Parser<RuleTemplate> parser, InputStreamReader inputStreamReader)
throws ParsingException {
Set<RuleTemplate> providedObjects = parser.parse(inputStreamReader);
if (providedObjects != null && !providedObjects.isEmpty()) {
List<String> portfolio = new ArrayList<String>();
synchronized (providerPortfolio) {
providerPortfolio.put(url, portfolio);
}
List<ParsingNestedException> importDataExceptions = new ArrayList<ParsingNestedException>();
for (RuleTemplate ruleT : providedObjects) {
List<ParsingNestedException> exceptions = new ArrayList<ParsingNestedException>();
String uid = ruleT.getUID();
checkExistence(uid, exceptions);
if (exceptions.isEmpty()) {
portfolio.add(uid);
synchronized (providedObjectsHolder) {
providedObjectsHolder.put(uid, ruleT);
}
} else
importDataExceptions.addAll(exceptions);
}
if (importDataExceptions.isEmpty()) {
Dictionary<String, Object> properties = new Hashtable<String, Object>();
properties.put(REG_PROPERTY_RULE_TEMPLATES, providedObjectsHolder.keySet());
if (tpReg == null)
tpReg = bc.registerService(TemplateProvider.class.getName(), this, properties);
else {
tpReg.setProperties(properties);
}
} else {
throw new ParsingException(importDataExceptions);
}
}
return providedObjects;
}
/**
* This method is responsible for checking the existence of {@link Template}s with the same
* UIDs before these objects to be added in the system.
*
* @param uid UID of the newly created {@link Template}, which to be checked.
* @param exceptions accumulates exceptions if {@link ModuleType} with the same UID exists.
*/
protected void checkExistence(String uid, List<ParsingNestedException> exceptions) {
if (AutomationCommandsPluggable.templateRegistry == null) {
exceptions.add(new ParsingNestedException(ParsingNestedException.TEMPLATE, uid,
new IllegalArgumentException("Failed to create Rule Template with UID \"" + uid
+ "\"! Can't guarantee yet that other Rule Template with the same UID does not exist.")));
}
if (AutomationCommandsPluggable.templateRegistry.get(uid) != null) {
exceptions.add(new ParsingNestedException(ParsingNestedException.TEMPLATE, uid,
new IllegalArgumentException("Rule Template with UID \"" + uid
+ "\" already exists! Failed to create a second with the same UID!")));
}
}
}

Просмотреть файл

@ -0,0 +1,710 @@
/**
* 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.internal.commands;
import java.math.BigDecimal;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.eclipse.smarthome.automation.Action;
import org.eclipse.smarthome.automation.Condition;
import org.eclipse.smarthome.automation.Module;
import org.eclipse.smarthome.automation.Rule;
import org.eclipse.smarthome.automation.RuleStatus;
import org.eclipse.smarthome.automation.Trigger;
import org.eclipse.smarthome.automation.template.RuleTemplate;
import org.eclipse.smarthome.automation.template.Template;
import org.eclipse.smarthome.automation.type.ActionType;
import org.eclipse.smarthome.automation.type.CompositeActionType;
import org.eclipse.smarthome.automation.type.CompositeConditionType;
import org.eclipse.smarthome.automation.type.CompositeTriggerType;
import org.eclipse.smarthome.automation.type.ConditionType;
import org.eclipse.smarthome.automation.type.Input;
import org.eclipse.smarthome.automation.type.ModuleType;
import org.eclipse.smarthome.automation.type.Output;
import org.eclipse.smarthome.automation.type.TriggerType;
import org.eclipse.smarthome.config.core.ConfigDescriptionParameter;
import org.eclipse.smarthome.config.core.FilterCriteria;
import org.eclipse.smarthome.config.core.ParameterOption;
/**
* This class provides the functionality responsible for printing the automation objects as a result of commands.
*
* @author Ana Dimova - Initial Contribution
* @author Yordan Mihaylov - updates related to api changes
*
*/
public class Printer {
/**
* This method is responsible for printing the list with indexes and UIDs of the {@link Template}s or
* {@link ModuleType}s.
*
* @param list with indexes and UIDs of the {@link Template}s or {@link ModuleType}s.
* @return a formated string, representing the list with indexes and UIDs of the {@link Template}s or
* {@link ModuleType}s.
*/
static String print(Hashtable<String, String> list) {
StringBuilder writer = new StringBuilder();
writer.append("\nID");
int size = Integer.toString(list.size()).length() + 4;
printChars(writer, ' ', size - 2, false);
writer.append("UID\n");
printChars(writer, '-', 100, true);
for (int i = 1; i <= list.size(); i++) {
String key = Integer.toString(i);
writer.append(key);
printChars(writer, ' ', size - key.length(), false);
writer.append(list.get(key) + "\n");
}
printChars(writer, '-', 100, true);
return writer.toString();
}
/**
* This method is responsible for printing the {@link Rule}.
*
* @param rule the {@link Rule} for printing.
* @return a formated string, representing the {@link Rule}.
*/
static String printRule(Rule rule, RuleStatus status) {
StringBuilder writer = new StringBuilder();
printChars(writer, '-', 100, true);
writer.append(rule.getUID());
if (status != null) {
writer.append(" [ ").append(status).append("]");
}
writer.append("\n");
printChars(writer, '-', 100, true);
writer.append("UID");
printChars(writer, ' ', 27, false);
writer.append(rule.getUID() + "\n");
writer.append("NAME");
printChars(writer, ' ', 26, false);
writer.append(rule.getName() + "\n");
String description = rule.getDescription();
if (description != null) {
writer.append("DESCRIPTION");
printChars(writer, ' ', 19, false);
writer.append(description + "\n");
}
Set<String> tags = rule.getTags();
if (tags != null && !tags.isEmpty()) {
writer.append("TAGS");
printChars(writer, ' ', 26, false);
writer.append(makeString(tags) + "\n");
}
Map<String, ?> config = rule.getConfiguration();
if (config != null && !config.isEmpty()) {
writer.append("CONFIGURATION");
printChars(writer, ' ', 17, false);
String str = " ";
writer.append(makeString(str, config) + "\n");
}
List<ConfigDescriptionParameter> cd = rule.getConfigurationDescriptions();
if (cd != null && !cd.isEmpty()) {
writer.append("CONFIGURATION_DESCRIPTIONS");
printChars(writer, ' ', 4, false);
writer.append(printConfigurationDescription(cd) + "\n");
}
List<Trigger> triggers = rule.getTriggers();
if (triggers != null && !triggers.isEmpty()) {
writer.append("TRIGGERS");
printChars(writer, ' ', 22, false);
int last = triggers.size();
for (Trigger trigger : triggers) {
writer.append(printModule(trigger));
last--;
if (last > 0)
printChars(writer, ' ', 30, false);
}
}
List<Condition> conditions = rule.getConditions();
if (conditions != null && !conditions.isEmpty()) {
writer.append("CONDITIONS");
printChars(writer, ' ', 20, false);
int last = conditions.size();
for (Condition condition : conditions) {
writer.append(printModule(condition));
last--;
if (last > 0)
printChars(writer, ' ', 30, false);
}
}
List<Action> actions = rule.getActions();
if (actions != null && !actions.isEmpty()) {
writer.append("ACTIONS");
printChars(writer, ' ', 23, false);
int last = actions.size();
for (Action action : actions) {
writer.append(printModule(action));
last--;
if (last > 0)
printChars(writer, ' ', 30, false);
}
}
printChars(writer, '-', 100, true);
return writer.toString();
}
/**
* This method is responsible for printing the {@link Template}.
*
* @param template the {@link Template} for printing.
* @return a formated string, representing the {@link Template}.
*/
static String printTemplate(Template template) {
StringBuilder writer = new StringBuilder();
printChars(writer, '-', 100, true);
writer.append(template.getUID() + "\n");
printChars(writer, '-', 100, true);
writer.append("UID");
printChars(writer, ' ', 27, false);
writer.append(template.getUID() + "\n");
String label = template.getLabel();
if (label != null) {
writer.append("LABEL");
printChars(writer, ' ', 25, false);
writer.append(label + "\n");
}
String description = template.getDescription();
if (description != null) {
writer.append("DESCRIPTION");
printChars(writer, ' ', 19, false);
writer.append(description + "\n");
}
writer.append("VISIBILITY");
printChars(writer, ' ', 20, false);
writer.append(template.getVisibility() + "\n");
Set<String> tags = template.getTags();
if (tags != null && !tags.isEmpty()) {
writer.append("TAGS");
printChars(writer, ' ', 26, false);
writer.append(makeString(tags) + "\n");
}
if (template instanceof RuleTemplate) {
List<ConfigDescriptionParameter> cd = ((RuleTemplate) template).getConfigurationDescription();
if (cd != null && !cd.isEmpty()) {
writer.append("CONFIGURATION_DESCRIPTIONS");
printChars(writer, ' ', 4, false);
writer.append(printConfigurationDescription(cd) + "\n");
}
List<Trigger> triggers = ((RuleTemplate) template).getTriggers();
if (!triggers.isEmpty()) {
writer.append("TRIGGERS");
printChars(writer, ' ', 22, false);
int last = triggers.size();
for (Trigger trigger : triggers) {
writer.append(printModule(trigger));
last--;
if (last > 0)
printChars(writer, ' ', 30, false);
}
}
List<Condition> conditions = ((RuleTemplate) template).getConditions();
if (!conditions.isEmpty()) {
writer.append("CONDITIONS");
printChars(writer, ' ', 20, false);
int last = conditions.size();
for (Condition condition : conditions) {
writer.append(printModule(condition));
last--;
if (last > 0)
printChars(writer, ' ', 30, false);
}
}
List<Action> actions = ((RuleTemplate) template).getActions();
if (!actions.isEmpty()) {
writer.append("ACTIONS");
printChars(writer, ' ', 23, false);
int last = actions.size();
for (Action action : actions) {
writer.append(printModule(action));
last--;
if (last > 0)
printChars(writer, ' ', 30, false);
}
}
}
printChars(writer, '-', 100, true);
return writer.toString();
}
/**
* This method is responsible for printing the {@link ModuleType}.
*
* @param moduleType the {@link ModuleType} for printing.
* @return a formated string, representing the {@link ModuleType}.
*/
static String printModuleType(ModuleType moduleType) {
StringBuilder writer = new StringBuilder();
printChars(writer, '-', 100, true);
writer.append(moduleType.getUID() + "\n");
printChars(writer, '-', 100, true);
writer.append("UID");
printChars(writer, ' ', 27, false);
writer.append(moduleType.getUID() + "\n");
String label = moduleType.getLabel();
if (label != null) {
writer.append("LABEL");
printChars(writer, ' ', 25, false);
writer.append(label + "\n");
}
String description = moduleType.getDescription();
if (description != null) {
writer.append("DESCRIPTION");
printChars(writer, ' ', 19, false);
writer.append(description + "\n");
}
writer.append("VISIBILITY");
printChars(writer, ' ', 20, false);
writer.append(moduleType.getVisibility() + "\n");
Set<String> tags = moduleType.getTags();
if (tags != null && !tags.isEmpty()) {
writer.append("TAGS");
printChars(writer, ' ', 26, false);
writer.append(makeString(tags) + "\n");
}
List<ConfigDescriptionParameter> cd = moduleType.getConfigurationDescription();
if (cd != null && !cd.isEmpty()) {
writer.append("CONFIGURATION_DESCRIPTIONS");
printChars(writer, ' ', 4, false);
writer.append(printConfigurationDescription(cd) + "\n");
}
if (moduleType instanceof TriggerType) {
List<Output> outputs = ((TriggerType) moduleType).getOutputs();
if (!outputs.isEmpty()) {
writer.append("OUTPUTS");
printChars(writer, ' ', 23, false);
writer.append(makeString(outputs) + "\n");
}
}
if (moduleType instanceof ConditionType) {
List<Input> inputs = ((ConditionType) moduleType).getInputs();
if (!inputs.isEmpty()) {
writer.append("INPUTS");
printChars(writer, ' ', 24, false);
writer.append(makeString(inputs) + "\n");
}
}
if (moduleType instanceof ActionType) {
List<Input> inputs = ((ActionType) moduleType).getInputs();
if (!inputs.isEmpty()) {
writer.append("INPUTS");
printChars(writer, ' ', 24, false);
writer.append(makeString(inputs) + "\n");
}
List<Output> outputs = ((ActionType) moduleType).getOutputs();
if (!outputs.isEmpty()) {
writer.append("OUTPUTS");
printChars(writer, ' ', 23, false);
writer.append(makeString(outputs) + "\n");
}
}
if (moduleType instanceof CompositeTriggerType) {
List<Trigger> triggers = ((CompositeTriggerType) moduleType).getChildren();
if (triggers != null && !triggers.isEmpty()) {
writer.append("CHILDREN");
printChars(writer, ' ', 22, false);
int last = triggers.size();
for (Trigger trigger : triggers) {
writer.append(printModule(trigger));
last--;
if (last > 0)
printChars(writer, ' ', 30, false);
}
}
}
if (moduleType instanceof CompositeConditionType) {
List<Condition> conditions = ((CompositeConditionType) moduleType).getChildren();
if (conditions != null && !conditions.isEmpty()) {
writer.append("CHILDREN");
printChars(writer, ' ', 20, false);
int last = conditions.size();
for (Condition condition : conditions) {
writer.append(printModule(condition));
last--;
if (last > 0)
printChars(writer, ' ', 30, false);
}
}
}
if (moduleType instanceof CompositeActionType) {
List<Action> actions = ((CompositeActionType) moduleType).getChildren();
if (actions != null && !actions.isEmpty()) {
writer.append("CHILDREN");
printChars(writer, ' ', 23, false);
int last = actions.size();
for (Action action : actions) {
writer.append(printModule(action));
last--;
if (last > 0)
printChars(writer, ' ', 30, false);
}
}
}
printChars(writer, '-', 100, true);
return writer.toString();
}
/**
* This method is responsible for printing the {@link Module}.
*
* @param module the {@link Module} for printing.
* @return a formated string, representing the {@link Module}.
*/
private static String printModule(Module module) {
StringBuilder writer = new StringBuilder();
printChars(writer, '-', 70, true);
printChars(writer, ' ', 30, false);
writer.append(module.getId() + "\n");
printChars(writer, ' ', 30, false);
printChars(writer, '-', 70, true);
printChars(writer, ' ', 30, false);
writer.append("ID");
printChars(writer, ' ', 28, false);
writer.append(module.getId() + "\n");
printChars(writer, ' ', 30, false);
writer.append("TYPE_UID");
printChars(writer, ' ', 22, false);
writer.append(module.getTypeUID() + "\n");
String label = module.getLabel();
if (label != null) {
printChars(writer, ' ', 30, false);
writer.append("LABEL");
printChars(writer, ' ', 22, false);
writer.append(label + "\n");
}
String description = module.getDescription();
if (description != null) {
printChars(writer, ' ', 30, false);
writer.append("DESCRIPTION");
printChars(writer, ' ', 19, false);
writer.append(description + "\n");
}
Map<String, Object> config = module.getConfiguration();
if (config != null && !config.isEmpty()) {
printChars(writer, ' ', 30, false);
writer.append("CONFIGURATION");
printChars(writer, ' ', 17, false);
String str = " ";
writer.append(makeString(str, config));
}
Map<String, String> connections = null;
if (module instanceof Condition) {
connections = ((Condition) module).getInputs();
}
if (module instanceof Action) {
connections = ((Action) module).getInputs();
}
if (connections != null && !connections.isEmpty()) {
printChars(writer, ' ', 30, false);
writer.append("CONNECTIONS");
printChars(writer, ' ', 19, false);
writer.append(makeString(connections) + "\n");
}
return writer.toString();
}
/**
* This method is responsible for printing the set of {@link ConfigDescriptionParameter}s.
*
* @param configDescriptions set of {@link ConfigDescriptionParameter}s for printing.
* @return a formated string, representing the set of {@link ConfigDescriptionParameter}s.
*/
private static String printConfigurationDescription(List<ConfigDescriptionParameter> configDescriptions) {
StringBuilder writer = new StringBuilder();
Iterator<ConfigDescriptionParameter> i = configDescriptions.iterator();
ConfigDescriptionParameter parameter = i.next();
writer.append(parameter.getName() + "\n");
writer.append(printParameter(parameter));
while (i.hasNext()) {
parameter = i.next();
printChars(writer, ' ', 30, false);
writer.append(parameter.getName() + "\n");
writer.append(printParameter(parameter));
}
return writer.toString();
}
/**
* This method is responsible for printing the {@link ConfigDescriptionParameter}.
*
* @param parameter the {@link ConfigDescriptionParameter} for printing.
* @return a formated string, representing the {@link ConfigDescriptionParameter}.
*/
private static String printParameter(ConfigDescriptionParameter parameter) {
StringBuilder writer = new StringBuilder();
printChars(writer, ' ', 34, false);
writer.append("TYPE = ");
writer.append(parameter.getType() + "\n");
String label = parameter.getLabel();
if (label != null) {
printChars(writer, ' ', 34, false);
writer.append("LABEL = ");
writer.append(label + "\n");
}
String description = parameter.getDescription();
if (description != null) {
printChars(writer, ' ', 34, false);
writer.append("DESCRIPTION = ");
writer.append(description + "\n");
}
String defaultVal = parameter.getDefault();
if (defaultVal != null) {
printChars(writer, ' ', 34, false);
writer.append("DEFAULT = ");
writer.append(defaultVal + "\n");
}
String context = parameter.getContext();
if (context != null) {
printChars(writer, ' ', 34, false);
writer.append("CONTEXT = ");
writer.append(context + "\n");
}
String pattern = parameter.getPattern();
if (pattern != null) {
printChars(writer, ' ', 34, false);
writer.append("PATTERN = ");
writer.append(pattern + "\n");
}
BigDecimal stepSize = parameter.getStepSize();
if (stepSize != null) {
printChars(writer, ' ', 34, false);
writer.append("STEP_SIZE = ");
writer.append(stepSize + "\n");
}
BigDecimal min = parameter.getMinimum();
if (min != null) {
printChars(writer, ' ', 34, false);
writer.append("MIN = ");
writer.append(min + "\n");
}
BigDecimal max = parameter.getMaximum();
if (max != null) {
printChars(writer, ' ', 34, false);
writer.append("MAX = ");
writer.append(max + "\n");
}
List<ParameterOption> options = parameter.getOptions();
if (options != null && !options.isEmpty()) {
printChars(writer, ' ', 34, false);
writer.append("OPTIONS = ");
writer.append(makeString(options) + "\n");
}
List<FilterCriteria> filter = parameter.getFilterCriteria();
if (filter != null && !filter.isEmpty()) {
printChars(writer, ' ', 34, false);
writer.append("FILTER_CRITERIA");
writer.append(makeString(filter) + "\n");
}
return writer.toString();
}
/**
* This method is responsible for printing the list of {@link FilterCriteria} or {@link ParameterOption}s.
*
* @param list is the list of {@link FilterCriteria} or {@link ParameterOption}s for printing.
* @return a formated string, representing the list of {@link FilterCriteria} or {@link ParameterOption}s.
*/
private static String makeString(List<?> list) {
int index = list.size();
String res = "[\n";
for (Object element : list) {
index--;
String string = " ";
if (element instanceof FilterCriteria) {
string = string + "name=\"" + ((FilterCriteria) element).getName() + "\", value=\""
+ ((FilterCriteria) element).getValue() + "\"";
} else if (element instanceof ParameterOption) {
string = string + "value=\"" + ((ParameterOption) element).getValue() + "\", label=\""
+ ((ParameterOption) element).getLabel() + "\"";
} else if (element instanceof Input) {
Input in = (Input) element;
string = string + "name=\"" + in.getName() + "\", type=\"" + in.getType() + "\", "
+ (in.isRequired() ? "REQUIRED" : "NOT REQUIRED")
+ (in.getDefaultValue() != null ? "\", default=\"" + in.getDefaultValue() : "");
} else if (element instanceof Output) {
Output out = (Output) element;
string = string + "name=\"" + out.getName() + "\", type=\"" + out.getType() + "\"";
}
if (index > 0) {
res = res + string + ",\n";
} else {
res = res + string + "\n";
}
}
return res = res + " ]";
}
/**
* This method is responsible for printing the set of {@link Input}s or {@link Output}s or {@link Inputs}s.
*
* @param set is the set of {@link Input}s or {@link Output}s or {@link Inputs}s for printing.
* @return a formated string, representing the set of {@link Input}s or {@link Output}s or {@link Input}s.
*/
private static String makeString(Set<?> set) {
if (set == null || set.size() == 0) {
return "[ ]";
}
String str = " ";
String res = "[";
Iterator<?> i = set.iterator();
while (i.hasNext()) {
Object element = i.next();
if (element instanceof String) {
if (i.hasNext()) {
res = res + element + ", ";
} else {
res = res + element + "]";
}
} else if (element instanceof Input) {
res = ((Input) element).getName();
res = res + "\n " + str + "TYPE = " + ((Input) element).getType();
res = res + "\n " + str + "LABEL = " + ((Input) element).getLabel();
res = res + "\n " + str + "DESCRIPTION = " + ((Input) element).getDescription();
res = res + "\n " + str + "DEFAULT = " + ((Input) element).getDefaultValue();
res = res + "\n " + str + "TAGS = " + makeString(((Input) element).getTags());
} else if (element instanceof Output) {
res = ((Output) element).getName();
res = res + "\n " + str + "TYPE = " + ((Output) element).getType();
res = res + "\n " + str + "LABEL = " + ((Output) element).getLabel();
res = res + "\n " + str + "DESCRIPTION = " + ((Output) element).getDescription();
res = res + "\n " + str + "DEFAULT = " + ((Output) element).getDefaultValue();
res = res + "\n " + str + "REFERENCE = " + ((Output) element).getReference();
res = res + "\n " + str + "TAGS = " + makeString(((Output) element).getTags());
}
}
return res;
}
private static String makeString(Map<String, ?> map) {
if (map == null || map.isEmpty()) {
return "[ ]";
}
String str = " ";
String res = "[";
Iterator<?> i = map.entrySet().iterator();
while (i.hasNext()) {
Entry<?, ?> element = (Entry<?, ?>) i.next();
if (i.hasNext()) {
res = "\n" + str + str + element.getKey() + " = " + element.getValue();
} else {
res = element.getKey() + " = " + element.getValue();
}
}
return res;
}
/**
* This method is responsible for printing the configuration map.
*
* @param str is a prefix per each member of the map.
* @param config is the configuration map for printing.
* @return a formated string, representing the configuration map.
*/
private static String makeString(String str, Map<String, ?> config) {
int index = config.size();
String res = "";
for (String key : config.keySet()) {
if (index == config.size()) {
res = key + " = " + config.get(key) + "\n";
} else {
res = res + str + key + " = " + config.get(key) + "\n";
}
index--;
}
return res;
}
/**
* This method is responsible for printing the {@link RuleStatus}.
*
* @param ruleUID specifies the rule, which status is requested.
* @param status corresponds to the status of specified rule.
* @return a string representing the response of the command {@link AutomationCommands#ENABLE_RULE}.
*/
static String printRuleStatus(String ruleUID, RuleStatus status) {
StringBuilder writer = new StringBuilder();
printChars(writer, '-', 100, true);
writer.append(ruleUID);
if (status != null) {
writer.append(" [ ").append(status.toString()).append("]");
}
writer.append("\n");
printChars(writer, '-', 100, true);
return writer.toString();
}
/**
* This method is responsible for the printing a symbol - <tt>ch</tt> as many times as specified by the parameter of
* the method
* - <tt>count</tt> and skip a line or not depending on other parameter of the method - a <tt>nl</tt>.
*
* @param sb is a {@link StringBuffer} for appending the specified symbol.
* @param ch the specified symbol.
* @param count specifies how many times to append the specified symbol.
* @param nl specifies to skip a line or not.
*/
static void printChars(StringBuilder sb, char ch, int count, boolean nl) {
if (count < 1) {
return;
}
for (int i = 0; i < count; i++) {
sb.append(ch);
}
if (nl) {
sb.append("\n");
}
}
/**
* This method is responsible for printing the list with indexes, UIDs and statuses of the {@link Rule}s.
*
* @param list with indexes, UIDs and statuses of the {@link Rule}s.
* @return a formated string, representing the list with indexes, UIDs and statuses of the {@link Rule}s.
*/
static String printRules(Hashtable<String, String> listRules) {
StringBuilder writer = new StringBuilder();
writer.append("\nID");
int size = Integer.toString(listRules.size()).length() + 4;
printChars(writer, ' ', size - 2, false);
writer.append("UID");
printChars(writer, ' ', 80, false);
writer.append("Status\n");
printChars(writer, '-', 100, true);
for (int i = 1; i <= listRules.size(); i++) {
String key = Integer.toString(i);
writer.append(key);
printChars(writer, ' ', size - key.length(), false);
writer.append(listRules.get(key) + "\n");
}
printChars(writer, '-', 100, true);
return writer.toString();
}
}

Просмотреть файл

@ -0,0 +1,294 @@
/**
* 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.internal.commands;
import java.util.Hashtable;
/**
* This class contains methods for facilitating sorting and filtering lists stored in {@link Hashtable}s.
*
* @author Ana Dimova - Initial Contribution
*
*/
public class Utils {
/**
* This method sorts lexicographically and sets an index of the UIDs of the automation objects.
*
* @param objects holds the list with automation objects for sorting and indexing.
* @return sorted and indexed list with UIDs of the automation objects.
*/
static Hashtable<String, String> sortList(Hashtable<String, ?> objects) {
if (objects == null || objects.isEmpty())
return null;
String[] uids = new String[objects.size()];
sort(objects.keySet().toArray(uids), false, false);
Hashtable<String, String> sorted = new Hashtable<String, String>();
for (int i = 0; i < uids.length; i++) {
sorted.put(new Integer(i + 1).toString(), uids[i]);
}
return sorted;
}
/**
* This method filters the list with UIDs of the automation objects to correspond to the list with the automation
* objects.
*
* @param listObjects holds the list with automation objects for filter criteria.
* @param listUIDs holds the list with UIDs of the automation objects for filtering.
* @return filtered list with UIDs of the automation objects.
*/
static Hashtable<String, String> filterList(Hashtable<String, ?> listObjects, Hashtable<String, String> listUIDs) {
Hashtable<String, String> filtered = new Hashtable<String, String>();
for (String id : listUIDs.keySet()) {
String uid = listUIDs.get(id);
Object obj = listObjects.get(uid);
if (obj != null)
filtered.put(id, uid);
}
return filtered;
}
private static void sort(String[] array, boolean ignoreCase, boolean backSort) {
if (backSort) {
backquickSort(array, 0, array.length, ignoreCase);
} else {
quickSort(array, 0, array.length, ignoreCase);
}
}
private static void quickSort(String[] a, int begin, int length, boolean ignoreCase) {
int i, j, leftLength, rightLength, t;
String x;
while (length >= 3) {
t = length - 1;
j = t + begin;
i = (t >> 1) + begin;
sort3(a, begin, i, j, ignoreCase);
if (length == 3) {
return;
}
x = a[i];
i = begin + 1;
j--;
do {
if (ignoreCase) {
while (a[i].toLowerCase().compareTo(x.toLowerCase()) < 0) {
i++;
}
while (a[j].toLowerCase().compareTo(x.toLowerCase()) > 0) {
j--;
}
} else {
while (a[i].compareTo(x) < 0) {
i++;
}
while (a[j].compareTo(x) > 0) {
j--;
}
}
if (i < j) {
swap(a, i, j);
} else {
if (i == j) {
i++;
j--;
}
break;
}
} while (++i <= --j);
leftLength = (j - begin) + 1;
rightLength = (begin - i) + length;
if (leftLength < rightLength) {
if (leftLength > 1) {
quickSort(a, begin, leftLength, ignoreCase);
}
begin = i;
length = rightLength;
} else {
if (rightLength > 1) {
quickSort(a, i, rightLength, ignoreCase);
}
length = leftLength;
}
}
if (ignoreCase) {
if (length == 2 && a[begin].toLowerCase().compareTo(a[begin + 1].toLowerCase()) > 0) {
swap(a, begin, begin + 1);
}
} else {
if (length == 2 && a[begin].compareTo(a[begin + 1]) > 0) {
swap(a, begin, begin + 1);
}
}
}
private static void backsort3(String[] a, int x, int y, int z, boolean ignoreCase) {
if (ignoreCase) {
if (a[x].toLowerCase().compareTo(a[y].toLowerCase()) < 0) {
if (a[x].toLowerCase().compareTo(a[z].toLowerCase()) < 0) {
if (a[y].toLowerCase().compareTo(a[z].toLowerCase()) < 0) {
backswap(a, x, z);
} else {
backswap3(a, x, y, z);
}
} else {
backswap(a, x, y);
}
} else if (a[x].toLowerCase().compareTo(a[z].toLowerCase()) < 0) {
backswap3(a, x, z, y);
} else if (a[y].toLowerCase().compareTo(a[z].toLowerCase()) < 0) {
backswap(a, y, z);
}
} else {
if (a[x].compareTo(a[y]) < 0) {
if (a[x].compareTo(a[z]) < 0) {
if (a[y].compareTo(a[z]) < 0) {
backswap(a, x, z);
} else {
backswap3(a, x, y, z);
}
} else {
backswap(a, x, y);
}
} else if (a[x].compareTo(a[z]) < 0) {
backswap3(a, x, z, y);
} else if (a[y].compareTo(a[z]) < 0) {
backswap(a, y, z);
}
}
}
private static void backswap(String[] a, int x, int y) {
String t = a[x];
a[x] = a[y];
a[y] = t;
}
private static void backswap3(String[] a, int x, int y, int z) {
String t = a[x];
a[x] = a[y];
a[y] = a[z];
a[z] = t;
}
private static void sort3(String[] a, int x, int y, int z, boolean ignoreCase) {
if (ignoreCase) {
if (a[x].toLowerCase().compareTo(a[y].toLowerCase()) > 0) {
if (a[x].toLowerCase().compareTo(a[z].toLowerCase()) > 0) {
if (a[y].toLowerCase().compareTo(a[z].toLowerCase()) > 0) {
swap(a, x, z);
} else {
swap3(a, x, y, z);
}
} else {
swap(a, x, y);
}
} else if (a[x].toLowerCase().compareTo(a[z].toLowerCase()) > 0) {
swap3(a, x, z, y);
} else if (a[y].toLowerCase().compareTo(a[z].toLowerCase()) > 0) {
swap(a, y, z);
}
} else {
if (a[x].compareTo(a[y]) > 0) {
if (a[x].compareTo(a[z]) > 0) {
if (a[y].compareTo(a[z]) > 0) {
swap(a, x, z);
} else {
swap3(a, x, y, z);
}
} else {
swap(a, x, y);
}
} else if (a[x].compareTo(a[z]) > 0) {
swap3(a, x, z, y);
} else if (a[y].compareTo(a[z]) > 0) {
swap(a, y, z);
}
}
}
private static void swap(String[] a, int x, int y) {
String t = a[x];
a[x] = a[y];
a[y] = t;
}
private static void swap3(String[] a, int x, int y, int z) {
String t = a[x];
a[x] = a[y];
a[y] = a[z];
a[z] = t;
}
private static void backquickSort(String[] a, int begin, int length, boolean ignoreCase) {
int i, j, leftLength, rightLength, t;
String x;
while (length >= 3) {
t = length - 1;
j = t + begin;
i = (t >> 1) + begin;
backsort3(a, begin, i, j, ignoreCase);
if (length == 3) {
return;
}
x = a[i];
i = begin + 1;
j--;
do {
if (ignoreCase) {
while (a[i].toLowerCase().compareTo(x.toLowerCase()) > 0) {
i++;
}
while (a[j].toLowerCase().compareTo(x.toLowerCase()) < 0) {
j--;
}
} else {
while (a[i].compareTo(x) > 0) {
i++;
}
while (a[j].compareTo(x) < 0) {
j--;
}
}
if (i < j) {
backswap(a, i, j);
} else {
if (i == j) {
i++;
j--;
}
break;
}
} while (++i <= --j);
leftLength = (j - begin) + 1;
rightLength = (begin - i) + length;
if (leftLength < rightLength) {
if (leftLength > 1) {
backquickSort(a, begin, leftLength, ignoreCase);
}
begin = i;
length = rightLength;
} else {
if (rightLength > 1) {
backquickSort(a, i, rightLength, ignoreCase);
}
length = leftLength;
}
}
if (ignoreCase) {
if (length == 2 && a[begin].toLowerCase().compareTo(a[begin + 1].toLowerCase()) < 0) {
backswap(a, begin, begin + 1);
}
} else {
if (length == 2 && a[begin].compareTo(a[begin + 1]) < 0) {
backswap(a, begin, begin + 1);
}
}
}
}

Просмотреть файл

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src/test/java"/>
<classpathentry kind="output" path="target/test-classes"/>
</classpath>

Просмотреть файл

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>org.eclipse.smarthome.automation.core.test</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

Просмотреть файл

@ -0,0 +1,8 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
org.eclipse.jdt.core.compiler.compliance=1.7
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.7

Просмотреть файл

@ -0,0 +1,9 @@
#Fri Feb 18 22:39:16 CET 2011
activeProfiles=
eclipse.preferences.version=1
fullBuildGoals=process-test-resources
includeModules=false
resolveWorkspaceProjects=true
resourceFilterGoals=process-resources resources\:testResources
skipCompilerPlugin=true
version=1

Просмотреть файл

@ -0,0 +1,9 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Tests for the Automation Core
Bundle-SymbolicName: org.eclipse.smarthome.automation.core.test
Bundle-Version: 0.8.0.qualifier
Bundle-Vendor: Eclipse.org/SmartHome
Fragment-Host: org.eclipse.smarthome.automation.core
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Require-Bundle: org.junit;bundle-version="4.8.1"

Просмотреть файл

@ -0,0 +1,28 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
<title>About</title>
</head>
<body lang="EN-US">
<h2>About This Content</h2>
<p>June 5, 2006</p>
<h3>License</h3>
<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;). Unless otherwise
indicated below, the Content is provided to you under the terms and conditions of the
Eclipse Public License Version 1.0 (&quot;EPL&quot;). A copy of the EPL is available
at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
apply to your use of any object code in the Content. Check the Redistributor's license that was
provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
indicated below, the terms and conditions of the EPL still apply to any source code in the Content
and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
</body>
</html>

Просмотреть файл

@ -0,0 +1,4 @@
source.. = src/test/java/
output.. = target/test-classes/
bin.includes = META-INF/,\
about.html

Просмотреть файл

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<groupId>org.eclipse.smarthome.bundles</groupId>
<artifactId>automation</artifactId>
<version>0.8.0-SNAPSHOT</version>
</parent>
<properties>
<bundle.symbolicName>org.eclipse.smarthome.automation.core.test</bundle.symbolicName>
<bundle.namespace>org.eclipse.smarthome.automation.core.test</bundle.namespace>
</properties>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.smarthome.io</groupId>
<artifactId>org.eclipse.smarthome.automation.core.test</artifactId>
<name>Eclipse SmartHome Automation Core Tests</name>
<packaging>eclipse-test-plugin</packaging>
<build>
<plugins>
<plugin>
<groupId>org.eclipse.tycho</groupId>
<artifactId>tycho-surefire-plugin</artifactId>
<version>${tycho-version}</version>
</plugin>
</plugins>
</build>
</project>

Просмотреть файл

@ -0,0 +1,163 @@
/**
* 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;
import java.io.File;
import java.io.InputStream;
import java.util.Collection;
import java.util.Dictionary;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.BundleListener;
import org.osgi.framework.Filter;
import org.osgi.framework.FrameworkListener;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceFactory;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceObjects;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
/**
* Mockup class for OSGi BundleContext used in junit tests
*
* @author Marin Mitev - initial version
*/
public class BundleContextMockup implements BundleContext {
@Override
public String getProperty(String key) {
return null;
}
@Override
public Bundle getBundle() {
return null;
}
@Override
public Bundle installBundle(String location, InputStream input) throws BundleException {
return null;
}
@Override
public Bundle installBundle(String location) throws BundleException {
return null;
}
@Override
public Bundle getBundle(long id) {
return null;
}
@Override
public Bundle[] getBundles() {
return null;
}
@Override
public void addServiceListener(ServiceListener listener, String filter) throws InvalidSyntaxException {}
@Override
public void addServiceListener(ServiceListener listener) {}
@Override
public void removeServiceListener(ServiceListener listener) {}
@Override
public void addBundleListener(BundleListener listener) {}
@Override
public void removeBundleListener(BundleListener listener) {}
@Override
public void addFrameworkListener(FrameworkListener listener) {}
@Override
public void removeFrameworkListener(FrameworkListener listener) {}
@Override
public ServiceRegistration<?> registerService(String[] clazzes, Object service, Dictionary<String, ?> properties) {
return null;
}
@Override
public ServiceRegistration<?> registerService(String clazz, Object service, Dictionary<String, ?> properties) {
return null;
}
@Override
public <S> ServiceRegistration<S> registerService(Class<S> clazz, S service, Dictionary<String, ?> properties) {
return null;
}
@Override
public <S> ServiceRegistration<S> registerService(Class<S> clazz, ServiceFactory<S> factory,
Dictionary<String, ?> properties) {
return null;
}
@Override
public ServiceReference<?>[] getServiceReferences(String clazz, String filter) throws InvalidSyntaxException {
return null;
}
@Override
public ServiceReference<?>[] getAllServiceReferences(String clazz, String filter) throws InvalidSyntaxException {
return null;
}
@Override
public ServiceReference<?> getServiceReference(String clazz) {
return null;
}
@Override
public <S> ServiceReference<S> getServiceReference(Class<S> clazz) {
return null;
}
@Override
public <S> Collection<ServiceReference<S>> getServiceReferences(Class<S> clazz, String filter)
throws InvalidSyntaxException {
return null;
}
@Override
public <S> S getService(ServiceReference<S> reference) {
return null;
}
@Override
public boolean ungetService(ServiceReference<?> reference) {
return false;
}
@Override
public <S> ServiceObjects<S> getServiceObjects(ServiceReference<S> reference) {
return null;
}
@Override
public File getDataFile(String filename) {
return null;
}
@Override
public Filter createFilter(String filter) throws InvalidSyntaxException {
return null;
}
@Override
public Bundle getBundle(String location) {
return null;
}
}

Просмотреть файл

@ -0,0 +1,315 @@
/**
* 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;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.smarthome.automation.Action;
import org.eclipse.smarthome.automation.Condition;
import org.eclipse.smarthome.automation.Rule;
import org.eclipse.smarthome.automation.Trigger;
import org.eclipse.smarthome.automation.core.internal.type.ModuleTypeManager;
import org.eclipse.smarthome.config.core.ConfigDescriptionParameter;
import org.eclipse.smarthome.config.core.ConfigDescriptionParameter.Type;
import org.eclipse.smarthome.config.core.FilterCriteria;
import org.eclipse.smarthome.config.core.ParameterOption;
import org.junit.Assert;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Test adding, retrieving and updating rules from the RuleEngine
*
* @author Marin Mitev - initial version
*/
public class RuleEngineTest {
Logger log = LoggerFactory.getLogger(RuleEngineTest.class);
private RuleEngine createRuleEngine() {
BundleContextMockup bc = new BundleContextMockup();
RuleEngine ruleEngine = new RuleEngine(bc);
ruleEngine.setModuleTypeManager(new ModuleTypeManager(bc, ruleEngine));
return ruleEngine;
}
/**
* test adding and retrieving rules
*/
@Test
public void testAddRetrieveRules() {
RuleEngine ruleEngine = createRuleEngine();
Rule rule0 = new Rule();
ruleEngine.addRule(rule0, true);
Collection<Rule> rules = ruleEngine.getRules();
Assert.assertNotNull("null returned instead of rules list", rules);
Assert.assertEquals("empty rules list is returned", 1, rules.size());
rules.add(new Rule());
Assert.assertNotEquals("new copy of rules list should be returned", rules.hashCode(),
ruleEngine.getRules().hashCode());
Rule rule1 = createRule();
ruleEngine.addRule(rule1, true);
Rule rule1Get = ruleEngine.getRule("rule1");
Assert.assertEquals("Returned rule with wrong UID", "rule1", rule1Get.getUID());
}
/**
* test editing rule tags
*/
@Test
public void testRuleTags() {
RuleEngine ruleEngine = createRuleEngine();
Rule rule2 = new Rule("rule2", null, null, null, null, null);
Set<String> ruleTags = new LinkedHashSet<String>();
ruleTags.add("tag1");
ruleTags.add("tag2");
rule2.setTags(ruleTags);
ruleEngine.addRule(rule2, true);
Rule rule2Get = ruleEngine.getRule("rule2");
Assert.assertNotNull("Cannot find rule by UID", rule2Get);
Assert.assertNotNull("rule.getTags is null", rule2Get.getTags());
Assert.assertEquals("rule.getTags is empty", 2, rule2Get.getTags().size());
Collection<Rule> rules = ruleEngine.getRulesByTag("tag1");
Assert.assertNotNull("getRulesByTag returned null", rules);
Assert.assertEquals("getRulesByTag returned empty list", 1, rules.size());
Rule[] array = new Rule[1];
array = rules.toArray(array);
Set<String> rule2GetTags = array[0].getTags();
Assert.assertNotNull("rule.getTags is null", rule2GetTags);
Assert.assertEquals("rule.getTags is empty", 2, rule2GetTags.size());
Assert.assertTrue("Missing tag in rule", rule2GetTags.contains("tag1"));
Assert.assertTrue("Missing tag in rule", rule2GetTags.contains("tag2"));
}
/**
* test rule configurations with null
*/
@Test
public void testRuleConfigNull() {
RuleEngine ruleEngine = createRuleEngine();
Rule rule3 = new Rule("rule3", createTriggers(), createConditions(), createActions(), null, null);
ruleEngine.addRule(rule3, true);
Rule rule3Get = ruleEngine.getRule("rule3");
Assert.assertNotNull("Rule configuration description is null", rule3Get.getConfigurationDescriptions());
Assert.assertNotNull("Rule configuration is null", rule3Get.getConfiguration());
}
/**
* test rule configurations with real values
*/
@Test
public void testRuleConfigValue() {
RuleEngine ruleEngine = createRuleEngine();
List<ConfigDescriptionParameter> configDescriptions = createConfigDescriptions();
Map<String, Object> configurations = new HashMap<String, Object>();
configurations.put("config1", 5);
Rule rule4 = new Rule("rule4", createTriggers(), createConditions(), createActions(), configDescriptions,
configurations);
ruleEngine.addRule(rule4, true);
Rule rule4Get = ruleEngine.getRule("rule4");
Map<String, ?> rule4cfg = rule4Get.getConfiguration();
List<ConfigDescriptionParameter> rule4cfgD = rule4Get.getConfigurationDescriptions();
Assert.assertNotNull("Rule configuration is null", rule4cfg);
Assert.assertTrue("Missing config property in rule copy", rule4cfg.containsKey("config1"));
Assert.assertEquals("Wrong config value", 5, rule4cfg.get("config1"));
Assert.assertNotNull("Rule configuration description is null", rule4cfgD);
Assert.assertEquals("Missing config description in rule copy", 1, rule4cfgD.size());
ConfigDescriptionParameter rule4cfgDP = rule4cfgD.iterator().next();
Assert.assertEquals("Wrong default value in config description", "3", rule4cfgDP.getDefault());
Assert.assertEquals("Wrong context value in config description", "context1", rule4cfgDP.getContext());
Assert.assertNotNull("Null options in config description", rule4cfgDP.getOptions());
Assert.assertEquals("Wrong option value in config description", "1", rule4cfgDP.getOptions().get(0).getValue());
Assert.assertEquals("Wrong option label in config description", "one",
rule4cfgDP.getOptions().get(0).getLabel());
}
/**
* test rule actions
*/
@Test
public void testRuleActions() {
RuleEngine ruleEngine = createRuleEngine();
Rule rule1 = createRule();
ruleEngine.addRule(rule1, true);
Rule rule1Get = ruleEngine.getRule("rule1");
List<Action> actionsGet = rule1Get.getActions();
Assert.assertNotNull("Null actions list", actionsGet);
Assert.assertEquals("Empty actions list", 1, actionsGet.size());
Assert.assertEquals("Returned actions list should not be a copy", actionsGet, rule1Get.getActions());
actionsGet.add(new Action("actionId2", "typeUID2", null, null));
List<Action> actionsGet2 = rule1Get.getActions();
Assert.assertNotNull("Null actions list", actionsGet2);
Assert.assertEquals("Action was not added to the rule's list of actions", 2, actionsGet2.size());
Assert.assertNotNull("Rule action with wrong id is returned", rule1Get.getModule("actionId2"));
actionsGet.add(new Action("actionId3", "typeUID3", null, null));
List<Action> actionsGet3 = rule1Get.getActions();
Assert.assertNotNull("Null actions list", actionsGet3);
Assert.assertEquals("Action was not added to the rule's list of actions", 3, actionsGet3.size());
// Assert.assertNull("Rule modules are not cached", rule1Get.getModule("actionId3"));
ruleEngine.updateRule(rule1Get);// ruleEngine.update will update the RuntimeRule.moduleMap with the new
// module
Assert.assertNotNull("Rule modules map was not updated", ruleEngine.getRule("rule1").getModule("actionId3"));
}
/**
* test rule triggers
*/
@Test
public void testRuleTriggers() {
RuleEngine ruleEngine = createRuleEngine();
Rule rule1 = createRule();
ruleEngine.addRule(rule1, true);
Rule rule1Get = ruleEngine.getRule("rule1");
List<Trigger> triggersGet = rule1Get.getTriggers();
Assert.assertNotNull("Null triggers list", triggersGet);
Assert.assertEquals("Empty triggers list", 1, triggersGet.size());
Assert.assertEquals("Returned triggers list should not be a copy", triggersGet, rule1Get.getTriggers());
triggersGet.add(new Trigger("triggerId2", "typeUID2", null));
ruleEngine.updateRule(rule1Get);// ruleEngine.update will update the RuntimeRule.moduleMap with the new
// module
Rule rule2Get = ruleEngine.getRule("rule1");
List<Trigger> triggersGet2 = rule2Get.getTriggers();
Assert.assertNotNull("Null triggers list", triggersGet2);
Assert.assertEquals("Trigger was not added to the rule's list of triggers", 2, triggersGet2.size());
Assert.assertEquals("Returned triggers list should not be a copy", triggersGet2, rule2Get.getTriggers());
Assert.assertNotNull("Rule trigger with wrong id is returned: " + triggersGet2,
rule2Get.getModule("triggerId2"));
}
/**
* test rule conditions
*/
@Test
public void testRuleConditions() {
RuleEngine ruleEngine = createRuleEngine();
Rule rule1 = createRule();
ruleEngine.addRule(rule1, true);
Rule rule1Get = ruleEngine.getRule("rule1");
List<Condition> conditionsGet = rule1Get.getConditions();
Assert.assertNotNull("Null conditions list", conditionsGet);
Assert.assertEquals("Empty conditions list", 1, conditionsGet.size());
Assert.assertEquals("Returned conditions list should not be a copy", conditionsGet, rule1Get.getConditions());
conditionsGet.add(new Condition("conditionId2", "typeUID2", null, null));
ruleEngine.updateRule(rule1Get);// ruleEngine.update will update the RuntimeRule.moduleMap with the new
// module
Rule rule2Get = ruleEngine.getRule("rule1");
List<Condition> conditionsGet2 = rule2Get.getConditions();
Assert.assertNotNull("Null conditions list", conditionsGet2);
Assert.assertEquals("Condition was not added to the rule's list of conditions", 2, conditionsGet2.size());
Assert.assertEquals("Returned conditions list should not be a copy", conditionsGet2, rule2Get.getConditions());
Assert.assertNotNull("Rule condition with wrong id is returned: " + conditionsGet2,
rule2Get.getModule("conditionId2"));
}
private Rule createRule() {
List<ConfigDescriptionParameter> configDescriptions = null;// new LinkedHashSet<ConfigDescriptionParameter>();
Map<String, Object> configurations = null;// new HashMap<String, Object>();
return new Rule("rule1", createTriggers(), createConditions(), createActions(), configDescriptions,
configurations);
}
private List<Trigger> createTriggers() {
List<Trigger> triggers = new ArrayList<Trigger>();
Map<String, Object> configurations = new HashMap<String, Object>();
configurations.put("a", "x");
configurations.put("b", "y");
configurations.put("c", "z");
triggers.add(new Trigger("triggerId", "typeUID", configurations));
return triggers;
}
private List<Condition> createConditions() {
List<Condition> conditions = new ArrayList<Condition>();
Map<String, Object> configurations = new HashMap<String, Object>();
configurations.put("a", "x");
configurations.put("b", "y");
configurations.put("c", "z");
Map<String, String> inputs = new HashMap<>(11);
String ouputModuleId = "triggerId";
String outputName = "triggerOutput";
String inputName = "conditionInput";
inputs.put(inputName, ouputModuleId + "." + outputName);
conditions.add(new Condition("conditionId", "typeUID", configurations, inputs));
return conditions;
}
private List<Action> createActions() {
List<Action> actions = new ArrayList<Action>();
Map<String, Object> configurations = new HashMap<String, Object>();
configurations.put("a", "x");
configurations.put("b", "y");
configurations.put("c", "z");
Map<String, String> inputs = new HashMap<>(11);
String ouputModuleId = "triggerId";
String outputName = "triggerOutput";
String inputName = "conditionInput";
inputs.put(inputName, ouputModuleId + "." + outputName);
actions.add(new Action("actionId", "typeUID", configurations, inputs));
return actions;
}
private List<ConfigDescriptionParameter> createConfigDescriptions() {
List<ConfigDescriptionParameter> configDescriptions = new ArrayList<ConfigDescriptionParameter>();
List<ParameterOption> options = new ArrayList<ParameterOption>();
options.add(new ParameterOption("1", "one"));
options.add(new ParameterOption("2", "two"));
String groupName = null;
Boolean advanced = false;
Boolean limitToOptions = true;
Integer multipleLimit = 0;
String label = "label1";
String pattern = null;
String context = "context1";
String description = "description1";
BigDecimal min = null;
BigDecimal max = null;
BigDecimal step = null;
Boolean required = true;
Boolean multiple = false;
Boolean readOnly = false;
String typeStr = ConfigDescriptionParameter.Type.INTEGER.name();
String defValue = "3";
List<FilterCriteria> filter = new ArrayList<FilterCriteria>();
String configPropertyName = "config1";
ConfigDescriptionParameter cfgDP = new ConfigDescriptionParameter(configPropertyName, Type.valueOf(typeStr),
max, min, step, pattern, required, readOnly, multiple, context, defValue, label, description, options,
filter, groupName, advanced, limitToOptions, multipleLimit);
configDescriptions.add(cfgDP);
return configDescriptions;
}
}

Просмотреть файл

@ -2,5 +2,6 @@
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src/main/java"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>

Просмотреть файл

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>org.eclipse.smarthome.automation.core</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

Просмотреть файл

@ -0,0 +1,26 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Eclipse SmartHome Automation Core
Bundle-SymbolicName: org.eclipse.smarthome.automation.core
Bundle-Version: 0.8.0.qualifier
Bundle-Vendor: Eclipse.org/SmartHome
Import-Package:
com.google.common.collect,
org.eclipse.smarthome.automation,
org.eclipse.smarthome.automation.core.util,
org.eclipse.smarthome.automation.events,
org.eclipse.smarthome.automation.handler,
org.eclipse.smarthome.automation.parser,
org.eclipse.smarthome.automation.template,
org.eclipse.smarthome.automation.type,
org.eclipse.smarthome.config.core,
org.eclipse.smarthome.core.common.registry,
org.eclipse.smarthome.core.events,
org.eclipse.smarthome.core.storage,
org.osgi.framework,
org.osgi.service.cm,
org.osgi.service.component,
org.osgi.util.tracker,
org.slf4j
Bundle-Activator: org.eclipse.smarthome.automation.core.internal.Activator
Export-Package: org.eclipse.smarthome.automation.core.util

Просмотреть файл

@ -0,0 +1,28 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
<title>About</title>
</head>
<body lang="EN-US">
<h2>About This Content</h2>
<p>June 5, 2006</p>
<h3>License</h3>
<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;). Unless otherwise
indicated below, the Content is provided to you under the terms and conditions of the
Eclipse Public License Version 1.0 (&quot;EPL&quot;). A copy of the EPL is available
at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
apply to your use of any object code in the Content. Check the Redistributor's license that was
provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
indicated below, the terms and conditions of the EPL still apply to any source code in the Content
and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
</body>
</html>

Просмотреть файл

@ -0,0 +1,5 @@
output.. = target/classes/
bin.includes = META-INF/,\
.,\
about.html
source.. = src/main/java/

Просмотреть файл

@ -10,15 +10,16 @@
</parent>
<properties>
<bundle.symbolicName>org.eclipse.smarthome.automation.json</bundle.symbolicName>
<bundle.namespace>org.eclipse.smarthome.automation.json</bundle.namespace>
<bundle.symbolicName>org.eclipse.smarthome.automation.core</bundle.symbolicName>
<bundle.namespace>org.eclipse.smarthome.automation.core</bundle.namespace>
</properties>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.smarthome.automation</groupId>
<artifactId>org.eclipse.smarthome.automation.json</artifactId>
<name>Eclipse SmartHome Automation JSON</name>
<artifactId>org.eclipse.smarthome.automation.core</artifactId>
<name>Eclipse SmartHome Automation Core</name>
<packaging>eclipse-plugin</packaging>
</project>

Просмотреть файл

@ -0,0 +1,196 @@
/**
* 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;
import java.util.Hashtable;
import org.eclipse.smarthome.automation.RuleProvider;
import org.eclipse.smarthome.automation.RuleRegistry;
import org.eclipse.smarthome.automation.core.internal.composite.CompositeModuleHandlerFactory;
import org.eclipse.smarthome.automation.core.internal.template.TemplateManager;
import org.eclipse.smarthome.automation.core.internal.template.TemplateRegistryImpl;
import org.eclipse.smarthome.automation.core.internal.type.ModuleTypeManager;
import org.eclipse.smarthome.automation.core.internal.type.ModuleTypeRegistryImpl;
import org.eclipse.smarthome.automation.core.util.ConnectionValidator;
import org.eclipse.smarthome.automation.events.RuleEventFactory;
import org.eclipse.smarthome.automation.template.TemplateRegistry;
import org.eclipse.smarthome.automation.type.ModuleTypeRegistry;
import org.eclipse.smarthome.core.events.EventFactory;
import org.eclipse.smarthome.core.events.EventPublisher;
import org.eclipse.smarthome.core.storage.Storage;
import org.eclipse.smarthome.core.storage.StorageService;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.Filter;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.cm.ManagedService;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.util.tracker.ServiceTrackerCustomizer;
/**
* This class is an activator of this bundle. Opens the all used service trackers and registers the services -
* {@link ModuleTypeRegistry}, {@link TemplateRegistry}, {@link RuleRegistry} and {@link AutomationFactory}.
*
* @author Kai Kreuzer - refactored (managed) provider and registry implementation
* @author Benedikt Niehues - added events for rules
*/
public class Activator implements BundleActivator {
private ModuleTypeRegistryImpl moduleTypeRegistry;
private TemplateRegistryImpl templateRegistry;
private RuleEventFactory ruleEventFactory;
private ModuleTypeManager mtManager;
private TemplateManager tManager;
@SuppressWarnings("rawtypes")
private ServiceRegistration/* <?> */ ruleRegistryReg;
private RuleRegistryImpl ruleRegistry;
@SuppressWarnings("rawtypes")
private ServiceRegistration/* <?> */ managedRuleProviderReg;
@SuppressWarnings("rawtypes")
private ServiceRegistration/* <?> */ templateRegistryReg;
@SuppressWarnings("rawtypes")
private ServiceRegistration/* <?> */ moduleTypeRegistryReg;
@SuppressWarnings("rawtypes")
private ServiceRegistration ruleEventFactoryReg;
@SuppressWarnings("rawtypes")
private ServiceTracker serviceTracker;
private ServiceRegistration<?> configReg;
private RuleEngine ruleEngine;
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public void start(final BundleContext bc) throws Exception {
ruleEngine = new RuleEngine(bc);
Hashtable props = new Hashtable(11);
props.put(Constants.SERVICE_PID, "smarthome.rule.configuration");
configReg = bc.registerService(ManagedService.class.getName(), ruleEngine, props);
this.tManager = new TemplateManager(bc, ruleEngine);
ruleEngine.setTemplateManager(tManager);
mtManager = new ModuleTypeManager(bc, ruleEngine);
ruleEngine.setModuleTypeManager(mtManager);
ruleEngine.setCompositeModuleFactory(new CompositeModuleHandlerFactory(bc, mtManager, ruleEngine));
ConnectionValidator.setManager(mtManager);
templateRegistry = new TemplateRegistryImpl(tManager);
templateRegistryReg = bc.registerService(TemplateRegistry.class.getName(), templateRegistry, null);
moduleTypeRegistry = new ModuleTypeRegistryImpl(mtManager);
moduleTypeRegistryReg = bc.registerService(ModuleTypeRegistry.class.getName(), moduleTypeRegistry, null);
ruleEventFactory = new RuleEventFactory();
ruleEventFactoryReg = bc.registerService(EventFactory.class.getName(), ruleEventFactory, null);
ruleRegistry = new RuleRegistryImpl(ruleEngine);
ruleRegistryReg = bc.registerService(RuleRegistry.class.getName(), ruleRegistry, null);
Filter filter = bc.createFilter("(|(" + Constants.OBJECTCLASS + "=" + StorageService.class.getName() + ")("
+ Constants.OBJECTCLASS + "=" + RuleProvider.class.getName() + ")(" + Constants.OBJECTCLASS + "="
+ EventPublisher.class.getName() + "))");
serviceTracker = new ServiceTracker(bc, filter, new ServiceTrackerCustomizer() {
@Override
public Object addingService(ServiceReference reference) {
Object service = bc.getService(reference);
if (service instanceof StorageService) {
StorageService storage = (StorageService) service;
if (storage != null) {
Storage storageDisabledRules = storage.getStorage("automation_rules_disabled",
this.getClass().getClassLoader());
ruleRegistry.setDisabledRuleStorage(storageDisabledRules);
final ManagedRuleProvider rp = new ManagedRuleProvider(storage);
managedRuleProviderReg = bc.registerService(RuleProvider.class.getName(), rp, null);
return storage;
}
} else if (service instanceof RuleProvider) {
RuleProvider rp = (RuleProvider) service;
ruleRegistry.addProvider(rp);
return rp;
} else if (service instanceof EventPublisher) {
EventPublisher ep = (EventPublisher) service;
ruleRegistry.setEventPublisher(ep);
return ep;
}
return null;
}
@Override
public void modifiedService(ServiceReference reference, Object service) {
}
@Override
public void removedService(ServiceReference reference, Object service) {
if (service instanceof StorageService) {
if (managedRuleProviderReg != null) {
managedRuleProviderReg.unregister();
managedRuleProviderReg = null;
}
} else if (service instanceof EventPublisher) {
if (ruleRegistry != null) {
ruleRegistry.unsetEventPublisher((EventPublisher) service);
}
} else if (service instanceof RuleProvider) {
if (ruleRegistry != null) {
RuleProvider rp = (RuleProvider) service;
ruleRegistry.removeProvider(rp);
}
}
}
});
serviceTracker.open();
}
@Override
public void stop(BundleContext bc) throws Exception {
serviceTracker.close();
serviceTracker = null;
if (configReg != null) {
configReg.unregister();
configReg = null;
}
if (ruleRegistryReg != null) {
ruleRegistryReg.unregister();
ruleRegistryReg = null;
ruleRegistry.dispose();
ruleRegistry = null;
}
if (templateRegistryReg != null) {
templateRegistryReg.unregister();
templateRegistryReg = null;
templateRegistry.dispose();
templateRegistry = null;
}
if (moduleTypeRegistryReg != null) {
moduleTypeRegistryReg.unregister();
moduleTypeRegistryReg = null;
moduleTypeRegistry.dispose();
moduleTypeRegistry = null;
}
if (ruleEventFactoryReg != null) {
ruleEventFactoryReg.unregister();
ruleEventFactory = null;
ruleEventFactoryReg = null;
}
ruleEngine.dispose();
}
}

Просмотреть файл

@ -0,0 +1,156 @@
/**
* 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;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.eclipse.smarthome.automation.Module;
import org.eclipse.smarthome.automation.Rule;
import org.eclipse.smarthome.automation.type.Input;
import org.eclipse.smarthome.automation.type.Output;
import org.slf4j.Logger;
/**
* This class defines connection between {@link Input} of the current {@link Module} and {@link Output} of the external
* one. The current module is the module containing {@link Connection} instance and the external one is the
* module where the current is connected to. <br>
* The input of the current module is defined by name of the {@link Input}. The {@link Output} of the external module is
* defined by id of the module and name of the output.
*
* @author Yordan Mihaylov - Initial Contribution
*/
public class Connection {
public static final String REF_IDENTIFIER = "$";
private String ouputModuleId;
private String outputName;
private String inputName;
/**
* This constructor is responsible for creation of connections between modules in the rule.
*
* @param inputName is an unique name of the {@code Input} in scope of the {@link Module}.
* @param ouputModuleId is an unique id of the {@code Module} in scope of the {@link Rule}.
* @param outputName is an unique name of the {@code Output} in scope of the {@link Module}.
*/
public Connection(String inputName, String ouputModuleId, String outputName) {
validate("inputName", inputName);
validate("outputName", outputName);
this.inputName = inputName;
this.ouputModuleId = ouputModuleId;
this.outputName = outputName;
}
/**
* This method is used to get id of external {@link Module} of this
* connection.
*
* @return id of external {@link Module}
*/
public String getOuputModuleId() {
return ouputModuleId;
}
/**
* This method is used to get output name of external {@link Module} of this
* connection.
*
* @return name of {@link Output} of external {@link Module}
*/
public String getOutputName() {
return outputName;
}
/**
* This method is used to get input name of current {@link Module} of this
* connection.
*
* @return name {@link Input} of the current {@link Module}
*/
public String getInputName() {
return inputName;
}
/**
* Compare two connection objects.
*/
@Override
public boolean equals(Object obj) {
return (inputName != null && obj instanceof Connection) && inputName.equals(((Connection) obj).getInputName());
};
@Override
public int hashCode() {
return inputName.hashCode();
};
/**
* This method is used to validate the connection.
*
* @param field serves to construct an understandable message that indicates what property of the connection is not
* correct.
* @param id is the value of the specified property. It can't be empty string.
*/
private void validate(String field, String id) {
if (id == null || id.length() == 0) {
throw new IllegalArgumentException("Invalid identifier for " + field);
}
}
@Override
public String toString() {
return "Connection " + ouputModuleId + "." + outputName + "->" + inputName;
}
/**
* This method is used for collecting of Connections of {@link Module}s.
*
* @param type specifies the type of the automation object - module type, rule or rule template.
* @param UID is the unique identifier of the automation object - module type, rule or rule template.
* @param jsonModule is a JSONObject representing the module.
* @param exceptions is a list used for collecting the exceptions occurred during {@link Module}s creation.
* @param log is used for logging of exceptions.
* @return collected Connections
*/
public static Set<Connection> getConnections(Map<String, String> inputs, Logger log) {
Set<Connection> connections = new HashSet<Connection>(11);
if (inputs != null) {
for (Entry<String, String> input : inputs.entrySet()) {
String inputName = input.getKey();
String outputName = null;
String output = input.getValue();
if (output.startsWith(REF_IDENTIFIER)) {
outputName = output;
Connection connection = new Connection(inputName, null, outputName);
connections.add(connection);
} else {
int index = output.indexOf('.');
if (index != -1) {
String outputId = output.substring(0, index);
outputName = output.substring(index + 1);
Connection connection = new Connection(inputName, outputId, outputName);
connections.add(connection);
} else {
log.error("Wrong format of Output : " + inputName + ": " + output);
continue;
}
}
}
}
return connections;
}
}

Просмотреть файл

@ -0,0 +1,43 @@
/**
* 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;
import org.eclipse.smarthome.automation.Rule;
import org.eclipse.smarthome.automation.RuleProvider;
import org.eclipse.smarthome.core.common.registry.DefaultAbstractManagedProvider;
import org.eclipse.smarthome.core.storage.StorageService;
/**
* Implementation of a rule provider that uses the storage service for persistence
*
* @author Yordan Mihaylov - Initial Contribution
* @author Ana Dimova - Persistence implementation
* @author Kai Kreuzer - refactored (managed) provider and registry implementation
*/
public class ManagedRuleProvider extends DefaultAbstractManagedProvider<Rule, String>implements RuleProvider {
public ManagedRuleProvider(StorageService storage) {
setStorageService(storage);
}
@Override
protected String getKey(Rule element) {
return element.getUID();
}
@Override
protected String getStorageName() {
return "automation_rules";
}
@Override
protected String keyToString(String key) {
return key;
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,86 @@
/**
* 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;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import org.eclipse.smarthome.automation.Rule;
import org.eclipse.smarthome.automation.Trigger;
import org.eclipse.smarthome.automation.handler.RuleEngineCallback;
/**
* This class is implementation of {@link RuleEngineCallback} used by the {@link Trigger}s to notify rule engine about
* appearing of new triggered data. There is one and only one {@link RuleEngineCallback} per Rule and it is used by all
* rule's {@link Trigger}s.
*
* @author Yordan Mihaylov - Initial Contribution
*/
public class RuleEngineCallbackImpl implements RuleEngineCallback {
private RuntimeRule r;
private ExecutorService executor;
private Future<?> feature;
private RuleEngine re;
protected RuleEngineCallbackImpl(RuleEngine re, RuntimeRule r) {
this.re = re;
this.r = r;
executor = Executors.newSingleThreadExecutor();
}
@Override
public void triggered(Trigger trigger, Map<String, ?> outputs) {
feature = executor.submit(new TriggerData(trigger, outputs));
}
public Rule getRule() {
return r;
}
public boolean isRunning() {
return feature == null || !feature.isDone();
}
class TriggerData implements Runnable {
private Trigger trigger;
public Trigger getTrigger() {
return trigger;
}
public Map<String, ?> getOutputs() {
return outputs;
}
private Map<String, ?> outputs;
public TriggerData(Trigger t, Map<String, ?> outputs) {
this.trigger = t;
this.outputs = outputs;
}
@Override
public void run() {
re.runRule(r, this);
}
}
public void dispose() {
executor.shutdownNow();
executor = null;
r = null;
}
}

Просмотреть файл

@ -0,0 +1,208 @@
/**
* 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;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
import org.eclipse.smarthome.automation.Rule;
import org.eclipse.smarthome.automation.RuleRegistry;
import org.eclipse.smarthome.automation.RuleStatus;
import org.eclipse.smarthome.automation.RuleStatusInfo;
import org.eclipse.smarthome.automation.StatusInfoCallback;
import org.eclipse.smarthome.automation.events.RuleEventFactory;
import org.eclipse.smarthome.core.common.registry.AbstractRegistry;
import org.eclipse.smarthome.core.common.registry.Provider;
import org.eclipse.smarthome.core.events.EventPublisher;
import org.eclipse.smarthome.core.storage.Storage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This is the main implementation of the {@link RuleRegistry}, which is registered as a service.
*
* @author Yordan Mihaylov - Initial Contribution
* @author Ana Dimova - Persistence implementation
* @author Kai Kreuzer - refactored (managed) provider and registry implementation and other fixes
* @author Benedikt Niehues - added events for rules
*/
public class RuleRegistryImpl extends AbstractRegistry<Rule, String>implements RuleRegistry, StatusInfoCallback {
private RuleEngine ruleEngine;
private Logger logger;
private Storage<Boolean> disabledRulesStorage;
private boolean hasManagedRuleProvider;
private static final String SOURCE = RuleRegistryImpl.class.getSimpleName();
public RuleRegistryImpl(RuleEngine ruleEngine) {
logger = LoggerFactory.getLogger(getClass());
this.ruleEngine = ruleEngine;
ruleEngine.setStatusInfoCallback(this);
}
@Override
protected synchronized void addProvider(Provider<Rule> provider) {
if (provider instanceof ManagedRuleProvider) {
hasManagedRuleProvider = true;
}
Collection<Rule> rules = provider.getAll();
for (Iterator<Rule> it = rules.iterator(); it.hasNext();) {
Rule rule = it.next();
try {
String rUID = rule.getUID();
if (rUID != null && disabledRulesStorage != null && disabledRulesStorage.get(rUID) != null) {
ruleEngine.addRule(rule, false);
} else {
ruleEngine.addRule(rule, true);
}
} catch (Exception e) {
logger.error("Can't add rule: " + rule.getUID() + " into rule engine from provider " + provider, e);
}
}
super.addProvider(provider);
}
@Override
protected synchronized void removeProvider(Provider<Rule> provider) {
Collection<Rule> rules = provider.getAll();
for (Iterator<Rule> it = rules.iterator(); it.hasNext();) {
Rule rule = it.next();
String uid = rule.getUID();
if (ruleEngine.removeRule(uid)) {
postEvent(RuleEventFactory.createRuleRemovedEvent(rule, SOURCE));
}
if (disabledRulesStorage != null) {
disabledRulesStorage.remove(uid);
}
}
if (provider instanceof ManagedRuleProvider) {
hasManagedRuleProvider = false;
}
super.removeProvider(provider);
}
@Override
public synchronized void add(Rule element) {
if (element == null) {
throw new IllegalArgumentException("The added rule must not be null!");
}
String rUID = element.getUID();
if (!hasManagedRuleProvider) {
throw new IllegalStateException("ManagedProvider is not available. The rule '"
+ (rUID != null ? rUID : element) + "' can't be added!");
}
Rule ruleToPersist;
if (rUID != null && disabledRulesStorage != null && disabledRulesStorage.get(rUID) != null) {
ruleToPersist = ruleEngine.addRule(element, false);
} else {
ruleToPersist = ruleEngine.addRule(element, true);
}
super.add(ruleToPersist);
postEvent(RuleEventFactory.createRuleAddedEvent(ruleToPersist, SOURCE));
}
@Override
public synchronized Rule remove(String key) {
Rule rule = super.remove(key);
if (ruleEngine.removeRule(key)) {
postEvent(RuleEventFactory.createRuleRemovedEvent(rule, SOURCE));
}
if (disabledRulesStorage != null) {
disabledRulesStorage.remove(key);
}
return rule;
}
@Override
public synchronized Rule update(Rule element) {
Rule old = null;
if (element != null) {
old = super.update(element); // update storage with new rule and return old rule
if (old != null) {
postEvent(RuleEventFactory.createRuleUpdatedEvent(element, old, SOURCE));
String rUID = element.getUID();
if (disabledRulesStorage != null && disabledRulesStorage.get(rUID) != null) {
ruleEngine.setRuleEnabled(rUID, false);
}
ruleEngine.updateRule(element); // update memory map
}
}
return old;
}
@Override
public Rule get(String key) {
return ruleEngine.getRule(key);
}
@Override
public Collection<Rule> getByTag(String tag) {
return ruleEngine.getRulesByTag(tag);
}
@Override
public Collection<Rule> getByTags(Set<String> tags) {
return ruleEngine.getRulesByTags(tags);
}
@Override
public synchronized void setEnabled(String uid, boolean isEnabled) {
ruleEngine.setRuleEnabled(uid, isEnabled);
if (disabledRulesStorage != null)
if (isEnabled) {
disabledRulesStorage.remove(uid);
} else {
disabledRulesStorage.put(uid, isEnabled);
}
}
@Override
public RuleStatusInfo getStatus(String ruleUID) {
return ruleEngine.getRuleStatusInfo(ruleUID);
}
protected void setDisabledRuleStorage(Storage<Boolean> disabledRulesStorage) {
this.disabledRulesStorage = disabledRulesStorage;
for (Rule rule : ruleEngine.getRules()) {
String uid = rule.getUID();
if (ruleEngine.getRuleStatus(uid).equals(RuleStatus.DISABLED)) {
disabledRulesStorage.put(uid, false);
} else {
disabledRulesStorage.remove(uid);
}
}
}
@Override
public void setEventPublisher(EventPublisher eventPublisher) {
super.setEventPublisher(eventPublisher);
}
@Override
public void unsetEventPublisher(EventPublisher eventPublisher) {
super.unsetEventPublisher(eventPublisher);
}
@Override
public void statusInfoChanged(String ruleUID, RuleStatusInfo statusInfo) {
postEvent(RuleEventFactory.createRuleStatusInfoEvent(statusInfo, ruleUID, SOURCE));
}
@Override
public Boolean isEnabled(String ruleUID) {
if (disabledRulesStorage != null && disabledRulesStorage.get(ruleUID) != null) {
return Boolean.FALSE;
}
return ruleEngine.hasRule(ruleUID) ? !ruleEngine.getRuleStatus(ruleUID).equals(RuleStatus.DISABLED) : null;
}
public void dispose() {}
}

Просмотреть файл

@ -0,0 +1,74 @@
/**
* 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;
import java.util.Set;
import org.eclipse.smarthome.automation.Action;
import org.eclipse.smarthome.automation.handler.ActionHandler;
import org.slf4j.LoggerFactory;
/**
* This class is implementation of {@link Action} modules used in the {@link RuleEngine}s.
*
* @author Yordan Mihaylov - Initial Contribution
* @author Ana Dimova - Initial Contribution
* @author Vasil Ilchev - Initial Contribution
*/
public class RuntimeAction extends Action {
/**
* The handler of this module.
*/
private ActionHandler actionHandler;
private Set<Connection> connections;
/**
* Utility constructor creating copy of passed action.
*
* @param action another action which is uses as base of created
*/
public RuntimeAction(Action action) {
super(action.getId(), action.getTypeUID(), action.getConfiguration(), action.getInputs());
setConnections(Connection.getConnections(action.getInputs(), LoggerFactory.getLogger(getClass())));
setLabel(action.getLabel());
setDescription(action.getDescription());
}
/**
* This method set deep copy of passed connections as connections of for this module.
*
* @see org.eclipse.smarthome.automation.Action#setConnections(java.util.Set)
*/
void setConnections(Set<Connection> connections) {
this.connections = connections;
}
public Set<Connection> getConnections() {
return connections;
}
/**
* This method gets handler which is responsible for handling of this module.
*
* @return handler of the module or null.
*/
ActionHandler getModuleHandler() {
return actionHandler;
}
/**
* This method sets handler of the module.
*
* @param actionHandler
*/
public void setModuleHandler(ActionHandler actionHandler) {
this.actionHandler = actionHandler;
}
}

Просмотреть файл

@ -0,0 +1,92 @@
/**
* 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;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.eclipse.smarthome.automation.Condition;
import org.eclipse.smarthome.automation.handler.ConditionHandler;
import org.slf4j.LoggerFactory;
/**
* This class is implementation of {@link Condition} modules used in the {@link RuleEngine}s.
*
* @author Yordan Mihaylov - Initial Contribution
*/
public class RuntimeCondition extends Condition {
private ConditionHandler conditionHandler;
private Set<Connection> connections;
public RuntimeCondition(Condition condition) {
super(condition.getId(), condition.getTypeUID(), condition.getConfiguration(), condition.getInputs());
setConnections(Connection.getConnections(condition.getInputs(), LoggerFactory.getLogger(getClass())));
setLabel(condition.getLabel());
setDescription(condition.getDescription());
}
@Override
public void setConfiguration(Map<String, ?> configuration) {
this.configuration = configuration != null ? new HashMap<String, Object>(configuration) : null;
}
/**
* Creates deep copy of passed connection. The copy is used to unlink connection used by this module with the
* connection object passed as source. In this way the connection can't be changed runtime except by this method.
*
* @see org.eclipse.smarthome.automation.Condition#setConnections(java.util.Set)
*/
void setConnections(Set<Connection> connections) {
this.connections = connections;
}
public Set<Connection> getConnections() {
return connections;
}
/**
* Utility method creating deep copy of passed connection set.
*
* @param connections connections used by this module.
* @return copy of passed connections.
*/
Set<Connection> copyConnections(Set<Connection> connections) {
if (connections == null) {
return null;
}
Set<Connection> result = new HashSet<Connection>(connections.size());
for (Iterator<Connection> it = connections.iterator(); it.hasNext();) {
Connection c = it.next();
result.add(new Connection(c.getInputName(), c.getOuputModuleId(), c.getOutputName()));
}
return result;
}
/**
* This method gets handler which is responsible for handling of this module.
*
* @return handler of the module or null.
*/
ConditionHandler getModuleHandler() {
return conditionHandler;
}
/**
* This method sets handler of the module.
*
* @param conditionHandler
*/
public void setModuleHandler(ConditionHandler conditionHandler) {
this.conditionHandler = conditionHandler;
}
}

Просмотреть файл

@ -0,0 +1,359 @@
/**
* 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;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.smarthome.automation.Action;
import org.eclipse.smarthome.automation.Condition;
import org.eclipse.smarthome.automation.Module;
import org.eclipse.smarthome.automation.Rule;
import org.eclipse.smarthome.automation.Trigger;
import org.eclipse.smarthome.automation.template.RuleTemplate;
import org.eclipse.smarthome.config.core.ConfigDescriptionParameter;
import org.eclipse.smarthome.config.core.ConfigDescriptionParameter.Type;
/**
* This is a class to be used within the {@link RuleEngine} for resolved rules.
*
* @author Yordan Mihaylov - Initial Contribution
* @author Kai Kreuzer - refactored (managed) provider and registry implementation
*
*/
public class RuntimeRule extends Rule {
/**
* Module configuration properties can have reference to Rule configuration properties.
* This symbol is put as prefix to the name of the Rule configuration property.
*/
private static final char REFERENCE_SYMBOL = '$';
private Map<String, Module> moduleMap;
/**
* @param ruleTemplateUID
* @param configurations
* @throws Exception
*/
public RuntimeRule(String ruleTemplateUID, Map<String, ?> configurations) {
super(ruleTemplateUID, configurations);
}
public RuntimeRule(String ruleUID, RuleTemplate template, Map<String, ?> configuration) {
super(ruleUID, getRuntimeTriggersCopy(template.getTriggers()),
getRuntimeConditionsCopy(template.getConditions()), getRuntimeActionsCopy(template.getActions()),
template.getConfigurationDescription(), configuration, template.getVisibility());
}
/**
* Utility constructor creating copy of the Rule or create a new empty instance.
*
* @param rule a rule which has to be copied or null when an empty instance of rule
* has to be created.
*/
protected RuntimeRule(Rule rule) {
super(rule.getUID(), getRuntimeTriggersCopy(rule.getTriggers()), getRuntimeConditionsCopy(rule.getConditions()),
getRuntimeActionsCopy(rule.getActions()), rule.getConfigurationDescriptions(), rule.getConfiguration(),
rule.getTemplateUID(), rule.getVisibility());
setName(rule.getName());
setTags(rule.getTags());
setDescription(rule.getDescription());
}
@Override
public void setConfiguration(Map<String, ?> ruleConfiguration) {
this.config = ruleConfiguration != null ? new HashMap<String, Object>(ruleConfiguration)
: new HashMap<String, Object>(11);
}
@Override
public Module getModule(String moduleId) {
if (moduleMap == null) {
moduleMap = initModuleMap();
}
return moduleMap.get(moduleId);
}
private Map<String, Module> initModuleMap() {
moduleMap = new HashMap<String, Module>(20);
for (Module m : getTriggers()) {
moduleMap.put(m.getId(), m);
}
for (Module m : getConditions()) {
moduleMap.put(m.getId(), m);
}
for (Module m : getActions()) {
moduleMap.put(m.getId(), m);
}
return moduleMap;
}
protected void setScopeIdentifier(String scopeId) {
this.scopeId = scopeId;
}
/**
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (obj instanceof RuntimeRule && getUID() != null) {
RuntimeRule r = (RuntimeRule) obj;
return getUID().equals(r.getUID());
}
return super.equals(obj);
}
/**
*
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
if (getUID() != null) {
return getUID().hashCode();
}
return super.hashCode();
}
/**
*
* @param configurations
*/
private void validateConfiguration(Map<String, Object> configurations) {
if (configurations == null || configurations.isEmpty()) {
if (isOptionalConfig(configDescriptions)) {
return;
} else
throw new IllegalArgumentException("Missing required configuration properties!");
} else {
for (ConfigDescriptionParameter configParameter : configDescriptions) {
String configParameterName = configParameter.getName();
Object configValue = configurations.remove(configParameterName);
if (configValue != null) {
processValue(configValue, configParameter);
}
}
if (!configurations.isEmpty()) {
String msg = "\"";
Iterator<ConfigDescriptionParameter> i = configDescriptions.iterator();
while (i.hasNext()) {
ConfigDescriptionParameter configParameter = i.next();
if (i.hasNext())
msg = msg + configParameter.getName() + "\", ";
else
msg = msg + configParameter.getName();
}
throw new IllegalArgumentException("Extra configuration properties : " + msg + "\"!");
}
}
}
private boolean isOptionalConfig(List<ConfigDescriptionParameter> configDescriptions) {
if (configDescriptions != null && !configDescriptions.isEmpty()) {
boolean required = false;
Iterator<ConfigDescriptionParameter> i = configDescriptions.iterator();
while (i.hasNext()) {
ConfigDescriptionParameter param = i.next();
required = required || param.isRequired();
}
return !required;
}
return true;
}
private void processValue(Object configValue, ConfigDescriptionParameter configParameter) {
if (configValue != null) {
checkType(configValue, configParameter);
return;
}
if (configParameter.getDefault() != null) {
return;
}
if (configParameter.isRequired()) {
throw new IllegalArgumentException(
"Required configuration property missing: \"" + configParameter.getName() + "\"!");
}
}
/**
* @param configValue
* @param configParameter
* @throws Exception
*/
@SuppressWarnings("rawtypes")
private void checkType(Object configValue, ConfigDescriptionParameter configParameter) {
Type type = configParameter.getType();
if (configParameter.isMultiple()) {
if (configValue instanceof List) {
int size = ((List) configValue).size();
for (int index = 0; index < size; index++) {
boolean error = false;
if (Type.TEXT.equals(type)) {
if (((List) configValue).get(index) instanceof String) {
error = true;
}
} else if (Type.BOOLEAN.equals(type)) {
if (((List) configValue).get(index) instanceof Boolean) {
error = true;
}
} else if (Type.INTEGER.equals(type)) {
if (((List) configValue).get(index) instanceof Integer) {
error = true;
}
} else if (Type.DECIMAL.equals(type)) {
if (((List) configValue).get(index) instanceof Double) {
error = true;
}
}
if (error) {
throw new IllegalArgumentException("Unexpected value for configuration property \""
+ configParameter.getName() + "\". Expected type: " + type);
}
}
}
throw new IllegalArgumentException(
"Unexpected value for configuration property \"" + configParameter.getName()
+ "\". Expected is Array with type for elements : " + type.toString() + "!");
} else {
if (Type.TEXT.equals(type) && configValue instanceof String)
return;
else if (Type.BOOLEAN.equals(type) && configValue instanceof Boolean)
return;
else if (Type.INTEGER.equals(type) && (configValue instanceof Short || configValue instanceof Byte
|| configValue instanceof Integer || configValue instanceof Long))
return;
else if (Type.DECIMAL.equals(type) && (configValue instanceof Float || configValue instanceof Double))
return;
else {
throw new IllegalArgumentException("Unexpected value for configuration property \""
+ configParameter.getName() + "\". Expected is " + type.toString() + "!");
}
}
}
void handleModuleConfigReferences() {
Map<String, ?> ruleConfiguration = getConfiguration();
if (ruleConfiguration != null) {
validateConfiguration(new HashMap<String, Object>(ruleConfiguration));
handleModuleConfigReferences0(getTriggers(), ruleConfiguration);
handleModuleConfigReferences0(getConditions(), ruleConfiguration);
handleModuleConfigReferences0(getActions(), ruleConfiguration);
}
}
private void handleModuleConfigReferences0(List<? extends Module> modules, Map<String, ?> ruleConfiguration) {
if (modules != null) {
for (Module module : modules) {
Map<String, Object> moduleConfiguration = module.getConfiguration();
if (moduleConfiguration != null) {
for (Map.Entry<String, ?> entry : moduleConfiguration.entrySet()) {
String configName = entry.getKey();
Object configValue = entry.getValue();
if (configValue instanceof String) {
String configValueStr = (String) configValue;
if (configValueStr.charAt(0) == REFERENCE_SYMBOL) {
String referredRuleConfigName = configValueStr.substring(1);
Object referredRuleConfigValue = ruleConfiguration.get(referredRuleConfigName);
moduleConfiguration.put(configName, referredRuleConfigValue);
}
}
}
}
}
}
}
protected void setUID(String rUID) {
uid = rUID;
}
private static List<Action> getActionsCopy(List<Action> actions) {
List<Action> res = new ArrayList<Action>();
if (actions != null) {
for (Action a : actions) {
Action action = new Action(a.getId(), a.getTypeUID(), a.getConfiguration(), a.getInputs());
action.setLabel(a.getLabel());
action.setDescription(a.getDescription());
res.add(action);
}
}
return res;
}
private static List<Action> getRuntimeActionsCopy(List<Action> actions) {
List<Action> res = new ArrayList<Action>();
if (actions != null) {
for (Action action : actions) {
res.add(new RuntimeAction(action));
}
}
return res;
}
private static List<Condition> getConditionsCopy(List<Condition> conditions) {
List<Condition> res = new ArrayList<Condition>(11);
if (conditions != null) {
for (Condition c : conditions) {
Condition condition = new Condition(c.getId(), c.getTypeUID(), c.getConfiguration(), c.getInputs());
condition.setLabel(condition.getLabel());
condition.setDescription(condition.getDescription());
res.add(condition);
}
}
return res;
}
private static List<Condition> getRuntimeConditionsCopy(List<Condition> conditions) {
List<Condition> res = new ArrayList<Condition>(11);
if (conditions != null) {
for (Condition condition : conditions) {
res.add(new RuntimeCondition(condition));
}
}
return res;
}
private static List<Trigger> getTriggersCopy(List<Trigger> triggers) {
List<Trigger> res = new ArrayList<Trigger>(11);
if (triggers != null) {
for (Trigger t : triggers) {
Trigger trigger = new Trigger(t.getId(), t.getTypeUID(), t.getConfiguration());
trigger.setLabel(trigger.getLabel());
trigger.setDescription(trigger.getDescription());
res.add(trigger);
}
}
return res;
}
private static List<Trigger> getRuntimeTriggersCopy(List<Trigger> triggers) {
List<Trigger> res = new ArrayList<Trigger>(11);
if (triggers != null) {
for (Trigger trigger : triggers) {
res.add(new RuntimeTrigger(trigger));
}
}
return res;
}
protected Rule getRuleCopy() {
Rule rule = new Rule(getUID(), getTriggersCopy(getTriggers()), getConditionsCopy(getConditions()),
getActionsCopy(getActions()), getConfigurationDescriptions(), getConfiguration(), getTemplateUID(),
getVisibility());
rule.setName(getName());
rule.setTags(getTags());
rule.setDescription(getDescription());
return rule;
}
}

Просмотреть файл

@ -0,0 +1,58 @@
/**
* 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;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.smarthome.automation.Trigger;
import org.eclipse.smarthome.automation.handler.TriggerHandler;
/**
* This class is implementation of {@link Trigger} modules used in the {@link RuleEngine}s.
*
* @author Yordan Mihaylov - Initial Contribution
*/
public class RuntimeTrigger extends Trigger {
private TriggerHandler triggerHandler;
public RuntimeTrigger(String id, String typeUID, Map<String, ?> configuration) {
super(id, typeUID, configuration);
}
public RuntimeTrigger(Trigger trigger) {
super(trigger.getId(), trigger.getTypeUID(), trigger.getConfiguration());
setLabel(trigger.getLabel());
setDescription(trigger.getDescription());
}
@Override
public void setConfiguration(Map<String, ?> configuration) {
this.configuration = configuration != null ? new HashMap<String, Object>(configuration) : null;
}
/**
* This method gets handler which is responsible for handling of this module.
*
* @return handler of the module or null.
*/
TriggerHandler getModuleHandler() {
return triggerHandler;
}
/**
* This method sets handler of the module.
*
* @param triggerHandler
*/
public void setModuleHandler(TriggerHandler triggerHandler) {
this.triggerHandler = triggerHandler;
}
}

Просмотреть файл

@ -0,0 +1,139 @@
/**
* 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.Map;
import java.util.Map.Entry;
import org.eclipse.smarthome.automation.Action;
import org.eclipse.smarthome.automation.Condition;
import org.eclipse.smarthome.automation.Module;
import org.eclipse.smarthome.automation.Trigger;
import org.eclipse.smarthome.automation.handler.ActionHandler;
import org.eclipse.smarthome.automation.handler.ConditionHandler;
import org.eclipse.smarthome.automation.handler.ModuleHandler;
import org.eclipse.smarthome.automation.handler.TriggerHandler;
import org.eclipse.smarthome.automation.type.ActionType;
import org.eclipse.smarthome.automation.type.ConditionType;
import org.eclipse.smarthome.automation.type.ModuleType;
import org.eclipse.smarthome.automation.type.TriggerType;
/**
* This class is base implementation of all system composite module handlers: {@link CompositeTriggerHandler},
* {@link CompositeConditionHandler} and {@link CompositeActionHandler}. The instances of these handlers are created by
* {@link CompositeModuleHandlerFactory}.
* The composite module handlers have to serve modules of composite module types. These handlers are responsible to
* propagate configuration properties and input values of composite module to the child modules defined by the composite
* module type and to call the handlers which are responsible for the child modules.
*
*
* @author Yordan Mihaylov - Initial Contribution
*
* @param <M> type of module. It can be {@link Trigger}, {@link Condition} or {@link Action}
* @param <MT> type of module type. It can be {@link TriggerType}, {@link ConditionType} or {@link ActionType}
* @param <H> type of module handler. It can be {@link TriggerHandler}, {@link ConditionHandler} or
* {@link ActionHandler}
*/
public class AbstractCompositeModuleHandler<M extends Module, MT extends ModuleType, H extends ModuleHandler>
implements ModuleHandler {
protected LinkedHashMap<M, H> moduleHandlerMap;
protected M module;
protected MT moduleType;
/**
* This constructor creates composite module handler base on composite module, module type of the module and map of
* pairs of child module instances and corresponding handlers.
*
* @param module module of composite type.
* @param moduleType composite module type. This is the type of module.
* @param mapModuleToHandler map containing pairs of child modules instances (defined by module type) and their
* handlers
*/
public AbstractCompositeModuleHandler(M module, MT moduleType, LinkedHashMap<M, H> mapModuleToHandler) {
this.module = module;
this.moduleType = moduleType;
this.moduleHandlerMap = mapModuleToHandler;
}
/**
* This method creates internal composite context which will be used as context passed to the child
* handlers. The composite context is base on the rule context, but it also has configuration properties and input
* values of parent module (the module which type is composite one). The keys in composite context of parent input
* values and config values are same with '$' prefix.
*
* @param context rule context pass to the parent module
* @return context which combines rule context and input and configuration properties of the parent module.
*/
protected Map<String, ?> getCompositeContext(Map<String, ?> context) {
Map<String, Object> result = new HashMap<String, Object>(context);
for (Entry<String, Object> config : module.getConfiguration().entrySet()) {
result.put("$" + config.getKey(), config.getValue());
}
Map<String, String> inputs = null;
if (module instanceof Condition) {
inputs = ((Condition) module).getInputs();
} else if (module instanceof Action) {
inputs = ((Action) module).getInputs();
}
if (inputs != null) {
for (Entry<String, String> input : inputs.entrySet()) {
Object o = context.get(input.getValue());
result.put("$" + input.getKey(), o);
}
}
return result;
}
/**
* This method updates (changes) configuration properties of the child module base on the composite context values.
* It resolve references of child module configuration properties to inputs and configuration properties of
* parent module.
* For example: if a child configuration property has a value '$name' the method looks for such key in composite
* context and replace the child's configuration value.
*
* @param child child module defined by composite module type
* @param compositeContext context containing rule context and inputs and configuration values of parent module.
*/
protected void updateChildConfig(Module child, Map<String, ?> compositeContext) {
for (Entry<String, Object> config : child.getConfiguration().entrySet()) {
Object o = config.getValue();
if (o instanceof String) {
String key = (String) o;
if (isReference(key)) {
Object contextValue = compositeContext.get(key);
config.setValue(contextValue);
}
}
}
}
/**
* Check if the string argument is a reference to the composite context or it is a real value.
*
* @param ref a string value.
* @return true when the string value is a reference to the context value
*/
protected boolean isReference(String ref) {
return ref.startsWith("$") && ref.length() > 1;
}
@Override
public void dispose() {
if (moduleHandlerMap != null) {
moduleHandlerMap.clear();
moduleHandlerMap = null;
}
}
}

Просмотреть файл

@ -0,0 +1,114 @@
/**
* 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.Map.Entry;
import java.util.StringTokenizer;
import org.eclipse.smarthome.automation.Action;
import org.eclipse.smarthome.automation.handler.ActionHandler;
import org.eclipse.smarthome.automation.type.CompositeActionType;
import org.eclipse.smarthome.automation.type.Output;
/**
* This class is a handler implementation for {@link CompositeActionType}. The action of type
* {@link CompositeActionType} has to execute handlers of all child actions. The handler has to return outputs of the
* action, base on the outputs of the child actions, into rule context. The outputs of the child actions are not
* visible out of the context of the action.
*
* @author Yordan Mihaylov - Initial Contribution
*
*/
public class CompositeActionHandler extends AbstractCompositeModuleHandler<Action, CompositeActionType, ActionHandler>
implements ActionHandler {
public final static String REFERENCE = "reference";
private Map<String, String> compositeOutputs;
/**
* Create a system handler for modules of {@link CompositeActionType} type.
*
* @param action parent action module instance. The action which has {@link CompositeActionType} type.
* @param mt {@link CompositeActionType} instance of the parent module
* @param mapModuleToHandler map of pairs child action module to its action handler
* @param ruleUID UID of rule where the parent action is part of.
*/
public CompositeActionHandler(Action action, CompositeActionType mt,
LinkedHashMap<Action, ActionHandler> mapModuleToHandler, String ruleUID) {
super(action, mt, mapModuleToHandler);
compositeOutputs = getCompositeOutputMap(moduleType.getOutputs());
}
/**
* The method calls handlers of child action, collect their outputs and sets the output of the parent action.
*
* @see org.eclipse.smarthome.automation.handler.ActionHandler#execute(java.util.Map)
*/
@Override
public Map<String, Object> execute(Map<String, ?> context) {
Map<String, Object> internalContext = new HashMap<String, Object>(context);
Map<String, Object> result = new HashMap<String, Object>();
List<Action> children = moduleType.getChildren();
for (Action child : children) {
Map<String, ?> compositeContext = getCompositeContext(internalContext);
Map<String, Object> originalConfig = new HashMap<String, Object>(child.getConfiguration());
updateChildConfig(child, compositeContext);
ActionHandler childHandler = moduleHandlerMap.get(child);
Map<String, Object> childResults = childHandler.execute(compositeContext);
child.setConfiguration(originalConfig); // restore original config (restore links in config)
if (childResults != null) {
for (Entry<String, Object> childResult : childResults.entrySet()) {
String childOuputName = childResult.getKey();
String childOuputRef = child.getId() + "." + childOuputName;
String compositeOutputName = compositeOutputs.get(childOuputRef);
if (compositeOutputName != null) {
result.put(compositeOutputName, childResult.getValue());
}
}
}
}
return result.size() > 0 ? result : null;
}
/**
* Create a map of links between child outputs and parent outputs. These links are base on the refecences defined in
* the outputs of parent action.
*
* @param outputs outputs of the parent action. The action of {@link CompositeActionType}
* @return map of links between child action outputs and parent output
*/
protected Map<String, String> getCompositeOutputMap(List<Output> outputs) {
Map<String, String> result = new LinkedHashMap<String, String>(11);
if (outputs != null) {
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();
result.put(ref, output.getName());
}
}
}
}
return result;
}
@Override
public void dispose() {
super.dispose();
}
}

Просмотреть файл

@ -0,0 +1,63 @@
/**
* 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 org.eclipse.smarthome.automation.Condition;
import org.eclipse.smarthome.automation.handler.ConditionHandler;
import org.eclipse.smarthome.automation.type.CompositeConditionType;
/**
* This class is a handler implementation for {@link CompositeConditionType}. The condition which has
* {@link CompositeConditionType} module type will be satisfied only when all child conditions (defined
* by its {@link CompositeConditionType}) are satisfied.
*
* @author Yordan Mihaylov - Initial Contribution
*
*/
public class CompositeConditionHandler extends
AbstractCompositeModuleHandler<Condition, CompositeConditionType, ConditionHandler>implements ConditionHandler {
public CompositeConditionHandler(Condition condition, CompositeConditionType mt,
LinkedHashMap<Condition, ConditionHandler> mapModuleToHandler, String ruleUID) {
super(condition, mt, mapModuleToHandler);
}
/**
* The method calls handlers of child modules and return true only when they all are satisfied.
*
* @see org.eclipse.smarthome.automation.handler.ConditionHandler#isSatisfied(java.util.Map)
*/
@Override
public boolean isSatisfied(Map<String, ?> context) {
Map<String, Object> internalContext = new HashMap<String, Object>(context);
List<Condition> children = moduleType.getChildren();
for (Condition child : children) {
Map<String, ?> compositeContext = getCompositeContext(internalContext);
Map<String, Object> originalConfig = new HashMap<String, Object>(child.getConfiguration());
updateChildConfig(child, compositeContext);
ConditionHandler childHandler = moduleHandlerMap.get(child);
boolean isSatisfied = childHandler.isSatisfied(compositeContext);
child.setConfiguration(originalConfig); // restore original configs with links
if (!isSatisfied) {
return false;
}
}
return true;
}
@Override
public void dispose() {
super.dispose();
}
}

Просмотреть файл

@ -0,0 +1,202 @@
/**
* 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.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.smarthome.automation.Action;
import org.eclipse.smarthome.automation.Condition;
import org.eclipse.smarthome.automation.Module;
import org.eclipse.smarthome.automation.Trigger;
import org.eclipse.smarthome.automation.core.internal.RuleEngine;
import org.eclipse.smarthome.automation.core.internal.type.ModuleTypeManager;
import org.eclipse.smarthome.automation.handler.ActionHandler;
import org.eclipse.smarthome.automation.handler.BaseModuleHandlerFactory;
import org.eclipse.smarthome.automation.handler.ConditionHandler;
import org.eclipse.smarthome.automation.handler.ModuleHandler;
import org.eclipse.smarthome.automation.handler.ModuleHandlerFactory;
import org.eclipse.smarthome.automation.handler.TriggerHandler;
import org.eclipse.smarthome.automation.type.CompositeActionType;
import org.eclipse.smarthome.automation.type.CompositeConditionType;
import org.eclipse.smarthome.automation.type.CompositeTriggerType;
import org.eclipse.smarthome.automation.type.ModuleType;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This class is a factory for system module handler for modules of composite module types: {@link CompositeTriggerType}
* , {@link CompositeConditionType} and {@link CompositeActionType}. The composite module type is a type which contains
* one or more internal (child) modules and these modules have access to configuration properties and inputs of
* composite module. The outputs of module of composite type (if they exists) are set these handlers and they are base
* on the values of child module outputs.
* The {@link CompositeModuleHandlerFactory} is a system handler factory and it is not registered as service in OSGi
* framework, but it will be used by the rule engine to serve composite module types without any action of the user.
*
*
* @author Yordan Mihaylov - Initial Contribution
*/
public class CompositeModuleHandlerFactory extends BaseModuleHandlerFactory implements ModuleHandlerFactory {
private ModuleTypeManager mtManager;
private RuleEngine ruleEngine;
private Logger logger = LoggerFactory.getLogger(getClass());
/**
* The constructor of system handler factory for composite module types
*
* @param bc is a bundle context
* @param mtManager is a module type manager
* @param re is a rule engine
*/
public CompositeModuleHandlerFactory(BundleContext bc, ModuleTypeManager mtManager, RuleEngine re) {
super(bc);
this.mtManager = mtManager;
this.ruleEngine = re;
}
/**
* It is system factory and must not be registered as service. This method is not used.
*
* @see org.eclipse.smarthome.automation.handler.ModuleHandlerFactory#getTypes()
*/
@Override
public Collection<String> getTypes() {
return null;
}
@SuppressWarnings({ "unchecked" })
@Override
public void ungetHandler(Module module, String ruleUID, ModuleHandler handler) {
ModuleHandler handlerOfModule = handlers.get(ruleUID + module.getId());
if (handlerOfModule instanceof AbstractCompositeModuleHandler) {
AbstractCompositeModuleHandler<Module, ?, ?> h = (AbstractCompositeModuleHandler<Module, ?, ?>) handlerOfModule;
Set<Module> modules = h.moduleHandlerMap.keySet();
if (modules != null) {
for (Module child : modules) {
ModuleHandler childHandler = h.moduleHandlerMap.get(child);
ModuleHandlerFactory mhf = ruleEngine.getModuleHandlerFactory(child.getTypeUID(), ruleUID);
mhf.ungetHandler(child, ruleUID, childHandler);
}
}
}
super.ungetHandler(module, ruleUID, handler);
}
@Override
public ModuleHandler internalCreate(Module module, String ruleUID) {
ModuleHandler handler = null;
if (module != null) {
logger.debug("create composite module:" + module + ", of rule: " + ruleUID);
String moduleType = module.getTypeUID();
ModuleType mt = mtManager.get(moduleType);
if (mt instanceof CompositeTriggerType) {
List<Trigger> childModules = ((CompositeTriggerType) mt).getChildren();
LinkedHashMap<Trigger, TriggerHandler> mapModuleToHandler = getChildHandlers(module.getConfiguration(),
childModules, ruleUID);
if (mapModuleToHandler != null) {
handler = new CompositeTriggerHandler((Trigger) module, (CompositeTriggerType) mt,
mapModuleToHandler, ruleUID);
}
} else if (mt instanceof CompositeConditionType) {
List<Condition> childModules = ((CompositeConditionType) mt).getChildren();
LinkedHashMap<Condition, ConditionHandler> mapModuleToHandler = getChildHandlers(
module.getConfiguration(), childModules, ruleUID);
if (mapModuleToHandler != null) {
handler = new CompositeConditionHandler((Condition) module, (CompositeConditionType) mt,
mapModuleToHandler, ruleUID);
}
} else if (mt instanceof CompositeActionType) {
List<Action> childModules = ((CompositeActionType) mt).getChildren();
LinkedHashMap<Action, ActionHandler> mapModuleToHandler = getChildHandlers(module.getConfiguration(),
childModules, ruleUID);
if (mapModuleToHandler != null) {
handler = new CompositeActionHandler((Action) module, (CompositeActionType) mt, mapModuleToHandler,
ruleUID);
}
}
}
logger.debug("Set handler to composite module:" + module + " -> " + handler);
return handler;
}
/**
* This method associates module handlers to the child modules of composite module types. It links module types of
* child modules to the rule which contains this composite module. It also resolve links between child configuration
* properties and configuration of composite module see: {@link #resolveConfigurationProperties(Map, Module)}.
*
* @param compositeConfig configuration values of composite module.
* @param childModules list of child modules
* @param ruleUID UID of rule where the composite module is participating
* @return map of pairs of module and its handler. Return null when some of the child modules can not find its
* handler.
*/
@SuppressWarnings("unchecked")
private <T extends Module, MT extends ModuleHandler> LinkedHashMap<T, MT> getChildHandlers(
Map<String, Object> compositeConfig, List<T> childModules, String ruleUID) {
LinkedHashMap<T, MT> mapModuleToHandler = new LinkedHashMap<T, MT>();
for (T child : childModules) {
ruleEngine.updateMapModuleTypeToRule(ruleUID, child.getTypeUID());
ModuleHandlerFactory childMhf = ruleEngine.getModuleHandlerFactory(child.getTypeUID(), ruleUID);
if (childMhf == null) {
mapModuleToHandler.clear();
mapModuleToHandler = null;
return null;
}
resolveConfigurationProperties(compositeConfig, child);
MT childHandler = (MT) childMhf.getHandler(child, ruleUID);
if (childHandler == null) {
mapModuleToHandler.clear();
mapModuleToHandler = null;
return null;
}
mapModuleToHandler.put(child, childHandler);
}
return mapModuleToHandler;
}
/**
* Resolves links between child configuration property values and composite config property ones.
* When the child configuration value is a string and start "$" sign, the rest of value is a
* name of configuration property of composite type. This method gets this composite configuration value and sets
* it as child configuration values.
*
* @param compositeConfig configuration of composite module type.
* @param child child module of composite module type.
*/
private void resolveConfigurationProperties(Map<String, Object> compositeConfig, Module child) {
Map<String, Object> childConfig = child.getConfiguration();
for (Map.Entry<String, Object> e : childConfig.entrySet()) {
Object value = e.getValue();
if (value != null && value instanceof String) {
String ref = (String) value;
if (ref.startsWith("$") && ref.length() > 1) {
ref = ref.substring(1);
Object o = compositeConfig.get(ref);
if (o != null) {
e.setValue(o);
}
}
}
}
}
@Override
public void dispose() {
super.dispose();
mtManager = null;
ruleEngine = null;
}
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше