diff --git a/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/Rule.java b/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/Rule.java index 5fcd43e4b38..31f3fc70a5e 100644 --- a/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/Rule.java +++ b/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/Rule.java @@ -8,32 +8,41 @@ package org.eclipse.smarthome.automation; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.UUID; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.automation.template.RuleTemplate; import org.eclipse.smarthome.config.core.ConfigDescriptionParameter; import org.eclipse.smarthome.config.core.Configuration; import org.eclipse.smarthome.core.common.registry.Identifiable; /** - * Rule is built from {@link Module}s and consists of three sections: - * ON/IF/THEN. + * An automation Rule is built from {@link Module}s and consists of three parts: * - * Rules can have tags - non-hierarchical keywords or terms for - * describing them. They help for classifying the items and allow them to be - * found. + * Additionally, Rules can have tags - non-hierarchical keywords or terms for describing them. + * They can help the user to classify or label the Rules, and to filter and search them. * * @author Yordan Mihaylov - Initial Contribution * @author Ana Dimova - Initial Contribution * @author Vasil Ilchev - Initial Contribution */ +@NonNullByDefault public class Rule implements Identifiable { protected List triggers; @@ -41,61 +50,65 @@ public class Rule implements Identifiable { protected List actions; protected Configuration configuration; protected List configDescriptions; + @Nullable protected String templateUID; protected String uid; + @Nullable protected String name; protected Set tags; protected Visibility visibility; + @Nullable protected String description; /** - * Constructor creates an empty rule. The rule has ruleUID set by the rule engine. - */ - public Rule() { - } - - /** - * Constructor creates an empty rule with specified rule uid + * Constructor for creating an empty {@link Rule} with a specified rule identifier. + * When {@code null} is passed for the {@code uid} parameter, the {@link Rule}'s identifier will + * be randomly generated. * - * @param uid is the unique identifier of created rule. + * @param uid the rule's identifier, or {@code null} if a random identifier should be generated. */ - public Rule(String uid) { - this.uid = uid; + public Rule(@Nullable String uid) { + this(uid, null, null, null, null, null, null, null); } /** - * Utility constructor which creates a rule from modules or template. + * Utility constructor for creating a {@link Rule} from a set of modules, or from a template. + * When {@code null} is passed for the {@code uid} parameter, the {@link Rule}'s identifier will be randomly + * generated. * - * @param uid is the unique identifier of the rule. - * @param triggers trigger modules - * @param conditions condition modules - * @param actions action modules - * @param configurations are values of rule template. It is available when the rule is created from template and the - * template is not resolved. - * @param templateUID the unique identifier of RuleTemplate. It is available when the rule is created from template - * and the template is not resolved. - * @param visibility visibility of rule + * @param uid the {@link Rule}'s identifier, or {@code null} if a random identifier should be generated. + * @param triggers the {@link Rule}'s triggers list, or {@code null} if the {@link Rule} should have no triggers or + * will be created from a template. + * @param conditions the {@link Rule}'s conditions list, or {@code null} if the {@link Rule} should have no + * conditions, or will be created from a template. + * @param actions the {@link Rule}'s actions list, or {@code null} if the {@link Rule} should have no + * actions, or will be created from a template. + * @param configDescriptions metadata describing the configuration of the {@link Rule}. + * @param configuration the values that will configure the modules of the {@link Rule}. + * @param templateUID the {@link RuleTemplate} identifier of the template that will be used by the + * {@link RuleRegistry} to validate the {@link Rule}'s configuration, as well as to create and configure + * the {@link Rule}'s modules, or null if the {@link Rule} should not be created from a template. + * @param visibility the {@link Rule}'s visibility */ - public Rule(String uid, List triggers, // - List conditions, // - List actions, // - List configDescriptions, // - Configuration configurations, String templateUID, Visibility visibility) { - this.uid = uid; - setTriggers(triggers); - setConditions(conditions); - setActions(actions); - setConfigurationDescriptions(configDescriptions); - setConfiguration(configurations); + public Rule(@Nullable String uid, @Nullable List triggers, @Nullable List conditions, + @Nullable List actions, @Nullable List configDescriptions, + @Nullable Configuration configuration, @Nullable String templateUID, @Nullable Visibility visibility) { + this.uid = uid == null ? UUID.randomUUID().toString() : uid; + this.triggers = triggers == null ? new ArrayList<>() : triggers; + this.conditions = conditions == null ? new ArrayList<>() : conditions; + this.actions = actions == null ? new ArrayList<>() : actions; + this.configDescriptions = configDescriptions == null ? new ArrayList<>() : configDescriptions; + this.configuration = configuration == null ? new Configuration() : configuration; setTemplateUID(templateUID); - setVisibility(visibility); + this.visibility = visibility == null ? Visibility.VISIBLE : visibility; + tags = new HashSet<>(); } /** - * 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. + * This method is used to obtain the identifier of the Rule. It can be specified by the {@link Rule}'s creator, or + * randomly generated. * - * @return unique id of this {@link Rule} + * @return an identifier of this {@link Rule}. Can't be {@code null}. */ @Override public String getUID() { @@ -103,252 +116,253 @@ public String getUID() { } /** - * 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. + * This method is used to obtain the {@link RuleTemplate} identifier of the template the {@link Rule} was created + * from. It will be used by the {@link RuleRegistry} to resolve the {@link Rule}: to validate the {@link Rule}'s + * configuration, as well as to create and configure the {@link Rule}'s modules. If a {@link Rule} has not been + * created from a template, or has been successfully resolved by the {@link RuleRegistry}, this method will return + * {@code null}. * - * @return unique id of this {@link Rule} + * @return the identifier of the {@link Rule}'s {@link RuleTemplate}, or {@code null} if the {@link Rule} has not + * been created from a template, or has been successfully resolved by the {@link RuleRegistry}. */ - public String getTemplateUID() { + public @Nullable String getTemplateUID() { return templateUID; } - public void setTemplateUID(String templateUID) { + /** + * This method is used to specify the {@link RuleTemplate} identifier of the template that will be used to + * by the {@link RuleRegistry} to resolve the {@link Rule}: to validate the {@link Rule}'s configuration, as well as + * to create and configure the {@link Rule}'s modules. + */ + public void setTemplateUID(@Nullable String templateUID) { this.templateUID = templateUID; } /** - * This method is used for getting the user friendly name of the {@link Rule}. It's optional property. + * This method is used to obtain the {@link Rule}'s human-readable name. * - * @return the name of rule or null. + * @return the {@link Rule}'s human-readable name, or {@code null}. */ - public String getName() { + public @Nullable String getName() { return name; } /** - * This method is used for setting a friendly name of the Rule. This property - * can be changed only when the Rule is not in active state. + * This method is used to specify the {@link Rule}'s human-readable name. * - * @param ruleName a new name. - * @throws IllegalStateException when the rule is in active state + * @param ruleName the {@link Rule}'s human-readable name, or {@code null}. */ - public void setName(String ruleName) throws IllegalStateException { + public void setName(@Nullable String ruleName) { name = ruleName; } /** - * Rules can have - *
    - *
  • tags - 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.
  • - *
+ * This method is used to obtain the {@link Rule}'s assigned tags. * - * @return a {@link Set} of tags + * @return the {@link Rule}'s assigned tags. */ public Set getTags() { - return tags = tags != null ? tags : Collections. emptySet(); + return tags; } /** - * Rules can have - *
    - *
  • tags - 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.
  • - *
+ * This method is used to specify the {@link Rule}'s assigned tags. * - * @param ruleTags list of tags assign to this Rule. - * @throws IllegalStateException when the rule is in active state. + * @param ruleTags the {@link Rule}'s assigned tags. */ - public void setTags(Set ruleTags) throws IllegalStateException { - tags = ruleTags != null ? ruleTags : Collections. emptySet(); + @SuppressWarnings("null") + public void setTags(Set ruleTags) { + tags = ruleTags != null ? ruleTags : new HashSet<>(); } /** - * This method is used for getting the description of the Rule. The - * description is a long, user friendly description of the Rule defined by - * this descriptor. + * This method is used to obtain the human-readable description of the purpose and consequences of the + * {@link Rule}'s execution. * - * @return the description of the Rule. + * @return the {@link Rule}'s human-readable description, or {@code null}. */ - public String getDescription() { + public @Nullable String getDescription() { return description; } /** - * This method is used for setting the description of the Rule. The - * description is a long, user friendly description of the Rule defined by - * this descriptor. + * This method is used to specify human-readable description of the purpose and consequences of the + * {@link Rule}'s execution. * - * @param ruleDescription of the Rule. + * @param ruleDescription the {@link Rule}'s human-readable description, or {@code null}. */ - public void setDescription(String ruleDescription) { + public void setDescription(@Nullable String ruleDescription) { description = ruleDescription; } /** - * This method is used to show visibility of the Rule + * This method is used to obtain the {@link Rule}'s {@link Visibility}. * - * @return visibility of rule + * @return the {@link Rule}'s {@link Visibility} value. */ public Visibility getVisibility() { - if (visibility == null) { - return Visibility.VISIBLE; - } return visibility; } + /** + * This method is used to specify the {@link Rule}'s {@link Visibility}. + * + * @param visibility the {@link Rule}'s {@link Visibility} value. + */ + @SuppressWarnings("null") public void setVisibility(Visibility visibility) { - this.visibility = visibility; + this.visibility = visibility == null ? Visibility.VISIBLE : visibility; } /** - * This method is used for getting Map with configuration values of the {@link Rule} Key -id of the - * {@link ConfigDescriptionParameter} Value - the - * value of the corresponding property + * This method is used to obtain the {@link Rule}'s {@link Configuration}. * - * @return current configuration values + * @return current configuration values, or an empty {@link Configuration}. */ public Configuration getConfiguration() { - if (configuration == null) { - configuration = new Configuration(); - } return configuration; } /** - * This method is used for setting the Map with configuration values of the {@link Rule}. Key - id of the - * {@link ConfigDescriptionParameter} Value - - * the value of the corresponding property + * This method is used to specify the {@link Rule}'s {@link Configuration}. * - * @param ruleConfiguration new configuration values. + * @param ruleConfiguration the new configuration values. */ + @SuppressWarnings("null") public void setConfiguration(Configuration ruleConfiguration) { - this.configuration = ruleConfiguration; + this.configuration = ruleConfiguration == null ? new Configuration() : ruleConfiguration; } /** - * This method is used for getting the {@link List} with {@link ConfigDescriptionParameter}s - * defining meta info for configuration properties of the Rule. + * This method is used to obtain the {@link List} with {@link ConfigDescriptionParameter}s + * defining meta info for configuration properties of the {@link Rule}. * - * @return a {@link Set} of {@link ConfigDescriptionParameter}s. + * @return a {@link List} of {@link ConfigDescriptionParameter}s. */ public List getConfigurationDescriptions() { - if (configDescriptions == null) { - configDescriptions = new ArrayList(3); - } return configDescriptions; } + /** + * This method is used to describe with {@link ConfigDescriptionParameter}s + * the meta info for configuration properties of the {@link Rule}. + */ + @SuppressWarnings("null") public void setConfigurationDescriptions(List configDescriptions) { - this.configDescriptions = (configDescriptions == null) ? new ArrayList(3) - : configDescriptions; + this.configDescriptions = configDescriptions == null ? new ArrayList<>() : configDescriptions; } + /** + * This method is used to get the conditions participating in {@link Rule}. + * + * @return a list with the conditions that belong to this {@link Rule}. + */ public List getConditions() { - if (conditions == null) { - conditions = new ArrayList(3); - } return conditions; } + /** + * This method is used to specify the conditions participating in {@link Rule}. + * + * @param conditions a list with the conditions that should belong to this {@link Rule}. + */ + @SuppressWarnings("null") public void setConditions(List conditions) { - this.conditions = (conditions == null) ? new ArrayList(3) : conditions; + this.conditions = conditions == null ? new ArrayList<>() : conditions; } + /** + * This method is used to get the actions participating in {@link Rule}. + * + * @return a list with the actions that belong to this {@link Rule}. + */ public List getActions() { - if (actions == null) { - actions = new ArrayList(3); - } return actions; } + /** + * This method is used to specify the actions participating in {@link Rule} + * + * @param actions a list with the actions that should belong to this {@link Rule}. + */ + @SuppressWarnings("null") public void setActions(List actions) { - this.actions = (actions == null) ? new ArrayList(3) : actions; + this.actions = actions == null ? new ArrayList<>() : actions; } + /** + * This method is used to get the triggers participating in {@link Rule} + * + * @return a list with the triggers that belong to this {@link Rule}. + */ public List getTriggers() { - if (triggers == null) { - triggers = new ArrayList(3); - } return triggers; } + /** + * This method is used to specify the triggers participating in {@link Rule} + * + * @param triggers a list with the triggers that should belong to this {@link Rule}. + */ + @SuppressWarnings("null") public void setTriggers(List triggers) { - this.triggers = (triggers == null) ? new ArrayList(3) : triggers; + this.triggers = triggers == null ? new ArrayList<>() : triggers; } /** - * This method is used to get a module participating in Rule + * This method is used to get a {@link Module} participating in {@link Rule} * - * @param moduleId unique id of the module in this rule. - * @return module with specified id or null when it does not exist. + * @param moduleId specifies the id of a module belonging to this {@link Rule}. + * @return module with specified id or {@code null} if it does not belong to this {@link Rule}. */ - 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 getModule(String moduleUID, List modules) { - if (modules != null) { - for (T module : modules) { - if (module.getId().equals(moduleUID)) { - return module; - } + public @Nullable Module getModule(String moduleId) { + for (Module module : getModules(Module.class)) { + if (module.getId().equals(moduleId)) { + return module; } } return null; } /** - * This method is used to return the module of this rule. + * This method is used to obtain the modules of the {@link Rule}, corresponding to the specified class. * - * @param moduleClazz optional parameter defining type looking modules. The - * types are {@link Trigger}, {@link Condition} or {@link Action} - * @return list of modules of defined type or all modules when the type is not - * specified. + * @param moduleClazz defines the class of the looking modules. It can be {@link Module}, {@link Trigger}, + * {@link Condition} or {@link Action}. + * @return the modules of defined type or empty list if the {@link Rule} has no modules that belong to the specified + * type. */ @SuppressWarnings("unchecked") public List getModules(Class moduleClazz) { - List result = null; - if (moduleClazz == null) { - result = new ArrayList(); - result.addAll((Collection) getTriggers()); - result.addAll((Collection) getConditions()); - result.addAll((Collection) getActions()); + final List result; + if (Module.class == moduleClazz) { + List modules = new ArrayList(); + modules.addAll(triggers); + modules.addAll(conditions); + modules.addAll(actions); + result = (List) Collections.unmodifiableList(modules); } else if (Trigger.class == moduleClazz) { - result = (List) getTriggers(); + result = (List) triggers; } else if (Condition.class == moduleClazz) { - result = (List) getConditions(); + result = (List) conditions; } else if (Action.class == moduleClazz) { - result = (List) getActions(); + result = (List) actions; + } else { + result = Collections.emptyList(); } - return result != null ? result : Collections. emptyList(); + return result; } @Override public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + ((uid == null) ? 0 : uid.hashCode()); + result = prime * result + uid.hashCode(); return result; } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (this == obj) { return true; } @@ -359,11 +373,7 @@ public boolean equals(Object obj) { return false; } Rule other = (Rule) obj; - if (uid == null) { - if (other.uid != null) { - return false; - } - } else if (!uid.equals(other.uid)) { + if (!uid.equals(other.uid)) { return false; } return true; diff --git a/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/RulePredicates.java b/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/RulePredicates.java index a84157a6fc5..741c3f8f4d5 100644 --- a/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/RulePredicates.java +++ b/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/RulePredicates.java @@ -47,16 +47,12 @@ public class RulePredicates { public static String getPrefix(Rule rule) { if (null != rule) { final String uid = rule.getUID(); - if (null != uid) { - final int index = uid.indexOf(PREFIX_SEPARATOR); - - // only when a delimiter was found and the prefix is not empty - if (0 < index) { - return uid.substring(0, index); - } + final int index = uid.indexOf(PREFIX_SEPARATOR); + // only when a delimiter was found and the prefix is not empty + if (0 < index) { + return uid.substring(0, index); } } - return null; } diff --git a/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/Visibility.java b/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/Visibility.java index 1faeb71a89a..9f0851ebea6 100644 --- a/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/Visibility.java +++ b/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/Visibility.java @@ -11,24 +11,24 @@ import org.eclipse.smarthome.automation.type.ModuleType; /** - * Defines visibility values of {@link ModuleType}s and {@link Template}s + * Defines visibility values of {@link Rule}s, {@link ModuleType}s and {@link Template}s * * @author Yordan Mihaylov - Initial Contribution * */ public enum Visibility { /** - * The UI has to show this object. + * The UI has always to show an object with such visibility. */ VISIBLE, /** - * The UI has to hide this object. + * The UI has always to hide an object with such visibility. */ HIDDEN, /** - * The UI has to show this object only to experts. + * The UI has to show an object with such visibility only to experts. */ EXPERT diff --git a/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/template/RuleTemplate.java b/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/template/RuleTemplate.java index d3d253d1c10..d8f0b1f5c5b 100644 --- a/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/template/RuleTemplate.java +++ b/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/template/RuleTemplate.java @@ -8,12 +8,13 @@ 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; +import java.util.UUID; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.automation.Action; import org.eclipse.smarthome.automation.Condition; import org.eclipse.smarthome.automation.Module; @@ -23,12 +24,11 @@ import org.eclipse.smarthome.config.core.ConfigDescriptionParameter; /** - * The templates define types of shared, ready to use rule definitions, which - * can be instantiated and configured to produce {@link Rule} instances . Each - * Template has a unique id. + * The {@link RuleTemplate} defines a shared, ready to use - rule definition, which can be configured to produce + * {@link Rule} instances. *

- * The {@link RuleTemplate}s can be used by any creator of Rules, but they can be modified only by its creator. The - * template modification is done by updating the {@link RuleTemplate} through {@link TemplateRegistry} + * The {@link RuleTemplate}s can be used by any creator of Rules, but they can be modified only by its creator. + * The template modification is done by updating the {@link RuleTemplate}. *

* Templates can have tags - non-hierarchical keywords or terms for describing them. * @@ -37,97 +37,95 @@ * @author Vasil Ilchev - Initial Contribution * @author Markus Rathgeb - Add default constructor for deserialization */ +@NonNullByDefault public class RuleTemplate implements Template { /** - * This field holds an unique identifier of the {@link RuleTemplate} instance. + * This field holds the {@link RuleTemplate}'s identifier, specified by its creator or randomly generated. */ - private String uid; + private final String uid; /** - * This field holds a list with the unique {@link Trigger}s participating in the {@link Rule} and starting its - * execution. + * This field holds a list with the {@link Trigger}s participating in the {@link RuleTemplate}. */ - private List triggers; + private final List triggers; /** - * This field holds a list with the unique {@link Condition}s participating in the {@link Rule} and determine the - * completion of the execution. + * This field holds a list with the {@link Condition}s participating in the {@link RuleTemplate}. */ - private List conditions; + private final List 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. + * This field holds a list with the {@link Action}s participating in the {@link RuleTemplate}. */ - private List actions; + private final List actions; /** * This field holds a set of non-hierarchical keywords or terms for describing the {@link RuleTemplate}. */ - private Set tags; + private final Set tags; /** - * This field holds the short, user friendly name of the Template. + * This field holds the short, human-readable label of the {@link RuleTemplate}. */ - private String label; + @Nullable + private final String label; /** - * This field describes the usage of the {@link Rule} and its benefits. + * This field describes the usage of the {@link RuleTemplate} and its benefits. */ - private String description; + @Nullable + private final String description; /** - * This field determines {@link Visibility} of the template. + * This field determines {@link Visibility} of the {@link RuleTemplate}. */ - private Visibility visibility; + private final Visibility visibility; /** - * This field defines a set of configuration properties of the {@link Rule}. + * This field defines a set of configuration properties of the future {@link Rule} instances. */ - private List configDescriptions; + private final List configDescriptions; /** - * Default constructor for deserialization e.g. by Gson. - */ - protected RuleTemplate() { - } - - /** - * This constructor creates a {@link RuleTemplate} instance. + * This constructor creates a {@link RuleTemplate} instance that will be used for creating {@link Rule}s from a set + * of modules, belong to the template. When {@code null} is passed for the {@code uid} parameter, the + * {@link RuleTemplate}'s identifier will be randomly generated. * - * @param UID is an unique identifier of the {@link RuleTemplate} instance - * @param label short human readable description - * @param description a detailed human readable description - * @param tags a set of tags - * @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 defines if the template can be public or private + * @param uid the {@link RuleTemplate}'s identifier, or {@code null} if a random identifier should be generated. + * @param label the short human-readable {@link RuleTemplate}'s label. + * @param description a detailed human-readable {@link RuleTemplate}'s description. + * @param tags the {@link RuleTemplate}'s assigned tags. + * @param triggers the {@link RuleTemplate}'s triggers list, or {@code null} if the {@link RuleTemplate} should have + * no triggers. + * @param conditions the {@link RuleTemplate}'s conditions list, or {@code null} if the {@link RuleTemplate} should + * have no conditions. + * @param actions the {@link RuleTemplate}'s actions list, or {@code null} if the {@link RuleTemplate} should have + * no actions. + * @param configDescriptions describing metadata for the configuration of the future {@link Rule} instances. + * @param visibility the {@link RuleTemplate}'s visibility. */ - public RuleTemplate(String UID, String label, String description, Set tags, List triggers, - List conditions, List actions, List configDescriptions, - Visibility visibility) { - - this.uid = UID; + public RuleTemplate(@Nullable String UID, @Nullable String label, @Nullable String description, + @Nullable Set tags, @Nullable List triggers, @Nullable List conditions, + @Nullable List actions, @Nullable List configDescriptions, + @Nullable Visibility visibility) { + this.uid = UID == null ? UUID.randomUUID().toString() : 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(tags); + this.triggers = triggers == null ? Collections.emptyList() : Collections.unmodifiableList(triggers); + this.conditions = conditions == null ? Collections.emptyList() : Collections.unmodifiableList(conditions); + this.actions = actions == null ? Collections.emptyList() : Collections.unmodifiableList(actions); + this.configDescriptions = configDescriptions == null ? Collections.emptyList() + : Collections.unmodifiableList(configDescriptions); + this.visibility = visibility == null ? Visibility.VISIBLE : visibility; + this.tags = tags == null ? Collections.emptySet() : Collections.unmodifiableSet(tags); } /** - * This method is used for getting the type of Template. It is unique in scope of RuleEngine. + * This method is used to obtain the identifier of the {@link RuleTemplate}. It can be specified by the + * {@link RuleTemplate}'s creator, or randomly generated. * - * @return the unique id of Template. + * @return an identifier of this {@link RuleTemplate}. Can't be {@code null}. */ @Override public String getUID() { @@ -135,122 +133,136 @@ public String getUID() { } /** - * This method is used for getting the assigned tags to this Template. The tags are - * non-hierarchical keywords or terms that are used for describing the template and to filter the templates. + * This method is used to obtain the {@link RuleTemplate}'s assigned tags. * - * @return tags that is a set of non-hierarchical keywords or terms, describing the template. + * @return the {@link RuleTemplate}'s assigned tags. */ @Override public Set getTags() { - return tags != null ? tags : Collections. emptySet(); + return tags; } /** - * This method is used for getting the label of the Template. + * This method is used to obtain the {@link RuleTemplate}'s human-readable label. * - * @return the short, user friendly name of the Template. + * @return the {@link RuleTemplate}'s human-readable label, or {@code null}. */ @Override - public String getLabel() { + public @Nullable String getLabel() { return label; } /** - * This method is used for getting the description of the Template. The - * description is a long, user friendly description of the Rule defined by - * this Template. + * This method is used to obtain the human-readable description of the purpose of the {@link RuleTemplate}. * - * @return the description of the Template. + * @return the {@link RuleTemplate}'s human-readable description, or {@code null}. */ @Override - public String getDescription() { + public @Nullable String getDescription() { return description; } /** - * This method is used to show visibility of the template + * This method is used to obtain the {@link RuleTemplate}'s {@link Visibility}. * - * @return visibility of template + * @return the {@link RuleTemplate}'s {@link Visibility} value. */ @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. + * This method is used to obtain the {@link List} with {@link ConfigDescriptionParameter}s + * defining meta info for configuration properties of the future {@link Rule} instances. * - * @return a {@link Set} of {@link ConfigDescriptionParameter}s. + * @return a {@link List} of {@link ConfigDescriptionParameter}s. */ public List getConfigurationDescriptions() { - return configDescriptions != null ? configDescriptions : Collections. emptyList(); + return configDescriptions; } /** - * This method is used to get a {@link Module} participating in Rule + * This method is used to get a {@link Module} participating in {@link RuleTemplate} * - * @param id unique id of the module in this rule. - * @param the type of the module + * @param moduleId unique id of the module in this {@link RuleTemplate}. * @return module with specified id or null when it does not exist. */ - public T getModule(String id) { + public @Nullable Module getModule(String moduleId) { + for (Module module : getModules(Module.class)) { + if (module.getId().equals(moduleId)) { + return module; + } + } return null; } /** - * This method is used to return a group of {@link Module}s of this rule + * This method is used to obtain the modules of the {@link RuleTemplate}, corresponding to the specified class. * - * @param moduleClazz optional parameter defining type looking modules. The types - * are {@link Trigger}, {@link Condition} or {@link Action} - * @param the type of the module that is required - * @return list of modules of defined type or all modules when the type is not - * specified. + * @param moduleClazz defines the class of the looking modules. It can be {@link Module}, {@link Trigger}, + * {@link Condition} or {@link Action}. + * @return the modules of defined type or empty list if the {@link RuleTemplate} has no modules that belong to the + * specified type. */ @SuppressWarnings("unchecked") - @Deprecated public List getModules(Class moduleClazz) { - List result = null; - if (moduleClazz == null) { - result = new ArrayList(); - result.addAll((Collection) triggers); - result.addAll((Collection) conditions); - result.addAll((Collection) actions); + final List result; + if (Module.class == moduleClazz) { + List modules = new ArrayList(); + modules.addAll(triggers); + modules.addAll(conditions); + modules.addAll(actions); + result = (List) Collections.unmodifiableList(modules); } else if (Trigger.class == moduleClazz) { result = (List) triggers; } else if (Condition.class == moduleClazz) { result = (List) conditions; } else if (Action.class == moduleClazz) { result = (List) actions; + } else { + result = Collections.emptyList(); } - return result != null ? result : Collections. emptyList(); + return result; } + /** + * This method is used to get the triggers participating in {@link RuleTemplate}. + * + * @return a list with the triggers that belong to this {@link RuleTemplate}. + */ public List getTriggers() { - return triggers != null ? triggers : Collections. emptyList(); + return triggers; } + /** + * This method is used to get the conditions participating in {@link RuleTemplate}. + * + * @return a list with the conditions that belong to this {@link RuleTemplate}. + */ public List getConditions() { - return conditions != null ? conditions : Collections. emptyList(); + return conditions; } + /** + * This method is used to get the actions participating in {@link RuleTemplate}. + * + * @return a list with the actions that belong to this {@link RuleTemplate}. + */ public List getActions() { - return actions != null ? actions : Collections. emptyList(); + return actions; } @Override public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + ((uid == null) ? 0 : uid.hashCode()); + result = prime * result + uid.hashCode(); return result; } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (this == obj) { return true; } @@ -261,11 +273,7 @@ public boolean equals(Object obj) { return false; } RuleTemplate other = (RuleTemplate) obj; - if (uid == null) { - if (other.uid != null) { - return false; - } - } else if (!uid.equals(other.uid)) { + if (!uid.equals(other.uid)) { return false; } return true; diff --git a/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/template/Template.java b/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/template/Template.java index e2b38f7b0e5..52edd9c95c6 100644 --- a/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/template/Template.java +++ b/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/template/Template.java @@ -9,6 +9,8 @@ import java.util.Set; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.automation.Rule; import org.eclipse.smarthome.automation.Visibility; import org.eclipse.smarthome.core.common.registry.Identifiable; @@ -27,6 +29,7 @@ * @author Ana Dimova - Initial Contribution * @author Vasil Ilchev - Initial Contribution */ +@NonNullByDefault public interface Template extends Identifiable { /** @@ -55,7 +58,7 @@ public interface Template extends Identifiable { * * @return the label of the Template. */ - public String getLabel(); + public @Nullable String getLabel(); /** * This method is used for getting the description of the Template. The @@ -64,7 +67,7 @@ public interface Template extends Identifiable { * * @return the description of the Template. */ - public String getDescription(); + public @Nullable String getDescription(); /** * This method is used to show visibility of the template diff --git a/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/type/ActionType.java b/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/type/ActionType.java index 87f39b436c1..263f4b10f76 100644 --- a/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/type/ActionType.java +++ b/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/type/ActionType.java @@ -11,17 +11,17 @@ import java.util.List; import java.util.Set; +import org.eclipse.jdt.annotation.Nullable; 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; /** - * 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. + * This class provides common functionality for creating {@link Action} instances by supplying their meta-information. + * Each {@link ActionType} is uniquely identifiable in scope of the {@link ModuleTypeRegistry} and defines + * {@link ConfigDescriptionParameter}s that are meta-information for configuration of the future {@link Action} + * instances and meta-information for {@link Input}s and {@link Output}s used from these {@link Action} instances. * * @author Yordan Mihaylov - Initial Contribution * @author Ana Dimova - Initial Contribution @@ -33,30 +33,25 @@ public class ActionType extends ModuleType { * This field contains meta-information describing the incoming connections of the {@link Action} module to the * other {@link Module}s. */ - private List inputs; + private final List inputs; /** * This field contains meta-information describing the outgoing connections of the {@link Action} module to the * other {@link Action}s. */ - private List outputs; - - /** - * Default constructor for deserialization e.g. by Gson. - */ - protected ActionType() { - } + private final List 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. + * @param UID the {@link ActionType}'s identifier, or {@code null} if a random identifier should be generated. + * @param configDescriptions describing metadata for the configuration of the future {@link Action} instances. + * @param inputs a {@link List} with {@link Input} meta-information descriptions of the future {@link Action} + * instances. */ - public ActionType(String UID, List configDescriptions, List inputs) { + public ActionType(@Nullable String UID, @Nullable List configDescriptions, + List inputs) { this(UID, configDescriptions, inputs, null); } @@ -65,17 +60,16 @@ public ActionType(String UID, List configDescription * configuration descriptions, a {@link List} of {@link Input} definitions and a {@link List} of {@link Output} * 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. - * @param outputs is a {@link List} of {@link Output} meta-information descriptions. + * @param UID the {@link ActionType}'s identifier, or {@code null} if a random identifier should be generated. + * @param configDescriptions describing metadata for the configuration of the future {@link Action} instances. + * @param inputs a {@link List} with {@link Input} meta-information descriptions of the future {@link Action} + * instances. + * @param outputs a {@link List} with {@link Output} meta-information descriptions of the future {@link Action} + * instances. */ - public ActionType(String UID, List configDescriptions, List inputs, - List outputs) { - super(UID, configDescriptions); - this.inputs = inputs; - this.outputs = outputs; + public ActionType(@Nullable String UID, @Nullable List configDescriptions, + @Nullable List inputs, @Nullable List outputs) { + this(UID, configDescriptions, null, null, null, null, inputs, outputs); } /** @@ -83,40 +77,43 @@ public ActionType(String UID, List configDescription * {@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. * - * @param UID unique id of the {@link ActionType}. - * @param configDescriptions is a {@link List} of meta-information configuration descriptions. + * @param UID the {@link ActionType}'s identifier, or {@code null} if a random identifier should be generated. + * @param configDescriptions describing metadata for the configuration of the future {@link Action} instances. * @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. + * @param inputs a {@link List} with {@link Input} meta-information descriptions of the future {@link Action} + * instances. + * @param outputs a {@link List} with {@link Output} meta-information descriptions of the future {@link Action} + * instances. */ - public ActionType(String UID, List configDescriptions, String label, String description, - Set tags, Visibility visibility, List inputs, List outputs) { + public ActionType(@Nullable String UID, @Nullable List configDescriptions, + @Nullable String label, @Nullable String description, @Nullable Set tags, + @Nullable Visibility visibility, @Nullable List inputs, @Nullable List outputs) { super(UID, configDescriptions, label, description, tags, visibility); - this.inputs = inputs; - this.outputs = outputs; + this.inputs = inputs != null ? Collections.unmodifiableList(inputs) : Collections.emptyList(); + this.outputs = outputs != null ? Collections.unmodifiableList(outputs) : Collections.emptyList(); } /** - * This method is used for getting the meta-information descriptions of {@link Input}s defined by this type. + * This method is used to obtain the meta-information descriptions of {@link Input}s defined by this type. * - * @return a {@link List} of {@link Input} definitions. + * @return a {@link List} with {@link Input} definitions. */ public List getInputs() { - return inputs != null ? inputs : Collections. emptyList(); + return inputs; } /** - * This method is used for getting the meta-information descriptions of {@link Output}s defined by this type. + * This method is used to obtain the meta-information descriptions of {@link Output}s defined by this type. * - * @return a {@link List} of {@link Output} definitions. + * @return a {@link List} with {@link Output} definitions. */ public List getOutputs() { - return outputs != null ? outputs : Collections. emptyList(); + return outputs; } } diff --git a/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/type/CompositeActionType.java b/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/type/CompositeActionType.java index eeb797ce882..380ec3a007d 100644 --- a/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/type/CompositeActionType.java +++ b/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/type/CompositeActionType.java @@ -12,6 +12,8 @@ import java.util.List; import java.util.Set; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.automation.Action; import org.eclipse.smarthome.automation.Visibility; import org.eclipse.smarthome.config.core.ConfigDescriptionParameter; @@ -19,73 +21,69 @@ /** * {@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. + * regular {@link Action} module. * * @author Yordan Mihaylov - Initial Contribution * @author Ana Dimova - Initial Contribution * @author Vasil Ilchev - Initial Contribution */ +@NonNullByDefault public class CompositeActionType extends ActionType { - private List children; + private final List children; /** - * Default constructor for deserialization e.g. by Gson. - */ - protected CompositeActionType() { - } - - /** - * 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}. + * This constructor creates a {@code CompositeActionType} with list of {@link Action}s. It initializes 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 UID the {@link ActionType}'s identifier, or {@code null} if a random identifier should be generated. + * @param configDescriptions describing metadata for the configuration of the future {@link Action} instances. + * @param children is a {@link LinkedHashSet} of {@link Action}s. + * @param inputs a {@link List} with {@link Input} meta-information descriptions of the future {@link Action} + * instances. + * @param outputs a {@link List} with {@link Output} meta-information descriptions of the future {@link Action} + * instances. * @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, List configDescriptions, List inputs, - List outputs, List children) { + public CompositeActionType(@Nullable String UID, @Nullable List configDescriptions, + @Nullable List inputs, @Nullable List outputs, @Nullable List children) { super(UID, configDescriptions, inputs, outputs); - this.children = children; + this.children = children != null ? Collections.unmodifiableList(children) : Collections.emptyList(); } /** - * 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}. + * This constructor creates a {@code CompositeActionType} with list of {@link Action}s. It initializes all + * 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 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 + * @param UID the {@link ActionType}'s identifier, or {@code null} if a random identifier should be generated. + * @param configDescriptions describing metadata for the configuration of the future {@link Action} instances. + * @param label a short and accurate, human-readable label of the {@link ActionType}. + * @param description a detailed, human-readable description of usage of {@link ActionType} and its benefits. + * @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 {@code CompositeActionType} can be used by anyone if it is + * @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} descriptions. - * @param outputs is a {@link List} of {@link Output} descriptions. + * @param inputs a {@link List} with {@link Input} meta-information descriptions of the future {@link Action} + * instances. + * @param outputs a {@link List} with {@link Output} meta-information descriptions of the future {@link Action} + * instances. * @param children is a {@link LinkedHashSet} of {@link Action}s. */ - public CompositeActionType(String UID, List configDescriptions, String label, - String description, Set tags, Visibility visibility, List inputs, List outputs, - List children) { + public CompositeActionType(@Nullable String UID, @Nullable List configDescriptions, + @Nullable String label, @Nullable String description, @Nullable Set tags, + @Nullable Visibility visibility, @Nullable List inputs, @Nullable List outputs, + @Nullable List children) { super(UID, configDescriptions, label, description, tags, visibility, inputs, outputs); - this.children = children; + this.children = children != null ? Collections.unmodifiableList(children) : Collections.emptyList(); } /** - * This method is used for getting the {@link Action}s of the {@code CompositeActionType}. + * This method is used to obtain the {@link Action}s of the {@code CompositeActionType}. * * @return a {@link LinkedHashSet} of the {@link Action} modules of this {@code CompositeActionType}. */ public List getChildren() { - return children != null ? children : Collections. emptyList(); + return children; } } diff --git a/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/type/CompositeConditionType.java b/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/type/CompositeConditionType.java index 8b567d86f79..6fc1631f4eb 100644 --- a/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/type/CompositeConditionType.java +++ b/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/type/CompositeConditionType.java @@ -12,6 +12,8 @@ import java.util.List; import java.util.Set; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.automation.Condition; import org.eclipse.smarthome.automation.Visibility; import org.eclipse.smarthome.config.core.ConfigDescriptionParameter; @@ -25,15 +27,10 @@ * @author Ana Dimova - Initial Contribution * @author Vasil Ilchev - Initial Contribution */ +@NonNullByDefault public class CompositeConditionType extends ConditionType { - private List children; - - /** - * Default constructor for deserialization e.g. by Gson. - */ - protected CompositeConditionType() { - } + private final List children; /** * This constructor is responsible for creation of a {@code CompositeConditionType} with ordered set of @@ -45,10 +42,10 @@ protected CompositeConditionType() { * @param children is a LinkedHashSet of {@link Condition}s. * @param inputs is a {@link Set} of {@link Input} descriptions. */ - public CompositeConditionType(String UID, List configDescriptions, List inputs, - List children) { + public CompositeConditionType(@Nullable String UID, @Nullable List configDescriptions, + @Nullable List inputs, @Nullable List children) { super(UID, configDescriptions, inputs); - this.children = children; + this.children = children != null ? Collections.unmodifiableList(children) : Collections.emptyList(); } /** @@ -69,10 +66,11 @@ public CompositeConditionType(String UID, List confi * @param inputs is a {@link List} of {@link Input} descriptions. * @param children is a {@link LinkedHashSet} of {@link Condition}s. */ - public CompositeConditionType(String UID, List configDescriptions, String label, - String description, Set tags, Visibility visibility, List inputs, List children) { + public CompositeConditionType(@Nullable String UID, @Nullable List configDescriptions, + @Nullable String label, @Nullable String description, @Nullable Set tags, + @Nullable Visibility visibility, @Nullable List inputs, @Nullable List children) { super(UID, configDescriptions, label, description, tags, visibility, inputs); - this.children = children; + this.children = children != null ? Collections.unmodifiableList(children) : Collections.emptyList(); } /** @@ -81,7 +79,7 @@ public CompositeConditionType(String UID, List confi * @return a {@link LinkedHashSet} of the {@link Condition} modules of this {@code CompositeConditionType}. */ public List getChildren() { - return children != null ? children : Collections. emptyList(); + return children; } } diff --git a/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/type/CompositeTriggerType.java b/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/type/CompositeTriggerType.java index f28371186ed..b3ec5851e10 100644 --- a/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/type/CompositeTriggerType.java +++ b/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/type/CompositeTriggerType.java @@ -7,11 +7,13 @@ */ package org.eclipse.smarthome.automation.type; -import java.util.ArrayList; +import java.util.Collections; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.automation.Trigger; import org.eclipse.smarthome.automation.Visibility; import org.eclipse.smarthome.config.core.ConfigDescriptionParameter; @@ -25,64 +27,58 @@ * @author Ana Dimova - Initial Contribution * @author Vasil Ilchev - Initial Contribution */ +@NonNullByDefault public class CompositeTriggerType extends TriggerType { - private List children; - - /** - * Default constructor for deserialization e.g. by Gson. - */ - protected CompositeTriggerType() { - } + private final List children; /** * 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}. + * {@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 UID the {@link TriggerType}'s identifier, or {@code null} if a random identifier should be generated. + * @param configDescriptions describing metadata for the configuration of the future {@link Trigger} instances. + * @param outputs a {@link List} with {@link Output} meta-information descriptions of the future {@link Trigger} + * instances. * @param children is a {@link LinkedHashSet} of {@link Trigger}s. - * @param outputs is a {@link Set} of {@link Output} descriptions. * */ - public CompositeTriggerType(String UID, List configDescriptions, List outputs, - List children) { + public CompositeTriggerType(@Nullable String UID, @Nullable List configDescriptions, + @Nullable List outputs, @Nullable List children) { super(UID, configDescriptions, outputs); - this.children = children; + this.children = children != null ? Collections.unmodifiableList(children) : Collections.emptyList(); } /** * 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}. + * {@link Trigger}s. It initialize all 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 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 + * @param UID the {@link TriggerType}'s identifier, or {@code null} if a random identifier should be generated. + * @param configDescriptions describing metadata for the configuration of the future {@link Trigger} instances. + * @param label a short and accurate, human-readable label of the {@link TriggerType}. + * @param description a detailed, human-readable description of usage of {@link TriggerType} and its benefits. + * @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 {@code CompositeTriggerType} can be used by anyone if it is + * @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 Set} of {@link Output} descriptions. + * @param outputs a {@link List} with {@link Output} meta-information descriptions of the future {@link Trigger} + * instances. * @param children is a {@link LinkedHashSet} of {@link Trigger}s. */ - public CompositeTriggerType(String UID, List configDescriptions, String label, - String description, Set tags, Visibility visibility, List outputs, List children) { + public CompositeTriggerType(@Nullable String UID, @Nullable List configDescriptions, + @Nullable String label, @Nullable String description, @Nullable Set tags, + @Nullable Visibility visibility, @Nullable List outputs, @Nullable List children) { super(UID, configDescriptions, label, description, tags, visibility, outputs); - this.children = children; + this.children = children != null ? Collections.unmodifiableList(children) : Collections.emptyList(); } /** - * This method is used for getting the {@link Trigger}s of the {@code CompositeTriggerType}. + * This method is used to obtain the {@link Trigger}s of the {@code CompositeTriggerType}. * * @return a {@link LinkedHashSet} of the {@link Trigger} modules of this {@code CompositeTriggerType}. */ public List getChildren() { - return children != null ? children : new ArrayList(0); + return children; } } diff --git a/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/type/ConditionType.java b/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/type/ConditionType.java index 6a59e218e71..26883c61396 100644 --- a/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/type/ConditionType.java +++ b/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/type/ConditionType.java @@ -11,16 +11,16 @@ import java.util.List; import java.util.Set; +import org.eclipse.jdt.annotation.Nullable; 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 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. + * This class provides common functionality for creating {@link Condition} instances by supplying their + * meta-information. Each {@link ConditionType} is uniquely identifiable in scope of the {@link ModuleTypeRegistry} and + * defines {@link ConfigDescriptionParameter}s that are meta-information for configuration of the future + * {@link Condition} instances and meta-information for {@link Input}s used from these {@link Condition} instances. * * @author Yordan Mihaylov - Initial Contribution * @author Ana Dimova - Initial Contribution @@ -28,26 +28,21 @@ */ public class ConditionType extends ModuleType { - private List inputs; - - /** - * Default constructor for deserialization e.g. by Gson. - */ - protected ConditionType() { - } + private final List inputs; /** * 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. + * @param UID the {@link ConditionType}'s identifier, or {@code null} if a random identifier should be generated. + * @param configDescriptions describing metadata for the configuration of the future {@link Condition} instances. + * @param inputs a {@link List} with {@link Input} meta-information descriptions of the future {@link Condition} + * instances. */ - public ConditionType(String UID, List configDescriptions, List inputs) { + public ConditionType(@Nullable String UID, @Nullable List configDescriptions, + @Nullable List inputs) { super(UID, configDescriptions); - this.inputs = inputs; + this.inputs = inputs != null ? Collections.unmodifiableList(inputs) : Collections.emptyList(); } /** @@ -55,29 +50,31 @@ public ConditionType(String UID, List configDescript * {@link Set} of tags, visibility, a {@link List} of configuration descriptions and a {@link List} of {@link Input} * descriptions. * - * @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 UID the {@link ConditionType}'s identifier, or {@code null} if a random identifier should be generated. + * @param configDescriptions describing metadata for the configuration of the future {@link Condition} instances. + * @param label a short and accurate, human-readable label of the {@link ConditionType}. + * @param description a detailed, human-readable description of usage of {@link ConditionType} and its benefits. * @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. + * @param inputs a {@link List} with {@link Input} meta-information descriptions of the future {@link Condition} + * instances. */ - public ConditionType(String UID, List configDescriptions, String label, - String description, Set tags, Visibility visibility, List inputs) { + public ConditionType(@Nullable String UID, @Nullable List configDescriptions, + @Nullable String label, @Nullable String description, @Nullable Set tags, + @Nullable Visibility visibility, @Nullable List inputs) { super(UID, configDescriptions, label, description, tags, visibility); - this.inputs = inputs; + this.inputs = inputs != null ? Collections.unmodifiableList(inputs) : Collections.emptyList(); } /** - * This method is used for getting the meta-information descriptions of {@link Input}s defined by this + * This method is used to obtain 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 getInputs() { - return inputs != null ? inputs : Collections. emptyList(); + return inputs; } } diff --git a/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/type/ModuleType.java b/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/type/ModuleType.java index e4a40665304..e6280703f66 100644 --- a/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/type/ModuleType.java +++ b/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/type/ModuleType.java @@ -10,64 +10,65 @@ import java.util.Collections; import java.util.List; import java.util.Set; +import java.util.UUID; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; 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; import org.eclipse.smarthome.core.common.registry.Identifiable; /** - * 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. + * Each {@link ModuleType} instance defines the meta-information needed for creation of a {@link Module} instance which + * is a building block for a {@link Rule}. The meta-information describes the {@link Configuration} of a {@link Module} + * providing list with {@link ConfigDescriptionParameter}s, {@link Input}s and {@link Output}s of a {@link Module}. + * Each {@link ModuleType} instance owns an unique id which is used as reference in the {@link Module}s, to find their + * meta-information. *

- * Whether the {@link ModuleType}s can be used by anyone, depends from their visibility, but they can be modified only - * by their creator. + * Whether the {@link ModuleType}s can be used by anyone, depends from their {@link Visibility} value, but they can be + * modified only by their creator. * * @author Yordan Mihaylov - Initial Contribution * @author Ana Dimova - Initial Contribution * */ +@NonNullByDefault public abstract class ModuleType implements Identifiable { /** - * This field is used as reference from the {@link Module}s, to find their meta-information. + * This field holds the {@link ModuleType}'s identifier, specified by its creator or randomly generated, and is + * used as reference in the {@link Module}s, to find their meta-information. */ - private String uid; + private final String uid; /** * 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}. */ - private Visibility visibility = Visibility.VISIBLE; + private final Visibility visibility; /** * 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 tags; + private final Set tags; /** - * Short and accurate name of the {@link ModuleType}. + * Short and accurate, human-readable label of the {@link ModuleType}. */ - private String label; + @Nullable + private final String label; /** - * Short and understandable description of that for what can be used the {@link ModuleType}. + * Detailed, human-readable description of usage of {@link ModuleType} and its benefits. */ - private String description; + @Nullable + private final String description; protected List configDescriptions; - /** - * Default constructor for deserialization e.g. by Gson. - */ - protected ModuleType() { - } - /** * This constructor is responsible to initialize common base properties of the {@link ModuleType}s. * @@ -75,40 +76,39 @@ protected ModuleType() { * meta-information. * @param configDescriptions is a {@link List} of meta-information configuration descriptions. */ - public ModuleType(String UID, List configDescriptions) { - this.uid = UID; - this.configDescriptions = configDescriptions; + public ModuleType(@Nullable String UID, @Nullable List configDescriptions) { + this(UID, configDescriptions, null, null, null, null); } /** * This constructor is responsible to initialize all common properties of the {@link ModuleType}s. * - * @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 UID the {@link ModuleType}'s identifier, or {@code null} if a random identifier should be generated. + * @param configDescriptions describing metadata for the configuration of the future {@link Module} instances. + * @param label a short and accurate, human-readable label of the {@link ModuleType}. + * @param description a detailed, human-readable description of usage of {@link ModuleType} and its benefits. * @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 configDescriptions, String label, String description, - Set tags, Visibility visibility) { - this(UID, configDescriptions); + public ModuleType(@Nullable String UID, @Nullable List configDescriptions, + @Nullable String label, @Nullable String description, @Nullable Set tags, + @Nullable Visibility visibility) { + this.uid = UID == null ? UUID.randomUUID().toString() : UID; this.label = label; this.description = description; - this.tags = tags; - this.visibility = visibility; + this.configDescriptions = configDescriptions == null ? Collections.emptyList() + : Collections.unmodifiableList(configDescriptions); + this.tags = tags == null ? Collections. emptySet() : Collections.unmodifiableSet(tags); + this.visibility = visibility == null ? Visibility.VISIBLE : 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. + * This method is used to obtain the identifier of the {@link ModuleType}. It can be specified by the + * {@link ModuleType}'s creator, or randomly generated. * - * @return the unique id (UID) of the {@link ModuleType}, corresponding to the some type of {@link Module}s. + * @return an identifier of this {@link ModuleType}. Can't be {@code null}. */ @Override public String getUID() { @@ -116,36 +116,30 @@ public String getUID() { } /** - * This method is used for getting the Set of {@link ConfigDescriptionParameter}s defined by this - * {@link ModuleType}. + * This method is used to obtain the metadata for the configuration of the future {@link Module} instances. * * @return a {@link Set} of meta-information configuration descriptions. */ public List getConfigurationDescriptions() { - return configDescriptions != null ? configDescriptions : Collections. emptyList(); + return configDescriptions; } /** - * {@link ModuleType}s can have - *

    - *
  • tags 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}.
  • - *
+ * This method is used to obtain the assigned to the {@link ModuleType} - {@link #tags}. * - * @return {@link #tags} assign to this {@link ModuleType} + * @return a set of tags, assigned to this {@link ModuleType}. */ public Set getTags() { - return tags != null ? tags : Collections. emptySet(); + return tags; } /** - * This method is used for getting the label of the {@link ModuleType}. The label is a - * short, user friendly name of the {@link ModuleType}. + * This method is used to obtain the label of the {@link ModuleType}. The label is a short and accurate, + * human-readable label of the {@link ModuleType}. * - * @return the {@link #label} of the {@link ModuleType}. + * @return the {@link ModuleType}'s {@link #label}. Can be {@code null}. */ - public String getLabel() { + public @Nullable String getLabel() { return label; } @@ -153,23 +147,20 @@ public String getLabel() { * 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}. * - * @return the {@link #description} of the ModuleType. + * @return the {@link ModuleType}'s {@link #description}. Can be {@code null}. */ - public String getDescription() { + public @Nullable String getDescription() { return description; } /** - * This method is used for getting visibility of the {@link ModuleType}. The visibility determines whether the + * This method is used to obtain 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}. * * @return the {@link #visibility} of the {@link ModuleType}. */ public Visibility getVisibility() { - if (visibility == null) { - return Visibility.VISIBLE; - } return visibility; } @@ -177,12 +168,12 @@ public Visibility getVisibility() { public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + ((uid == null) ? 0 : uid.hashCode()); + result = prime * result + uid.hashCode(); return result; } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (this == obj) { return true; } @@ -193,11 +184,7 @@ public boolean equals(Object obj) { return false; } ModuleType other = (ModuleType) obj; - if (uid == null) { - if (other.uid != null) { - return false; - } - } else if (!uid.equals(other.uid)) { + if (!uid.equals(other.uid)) { return false; } return true; diff --git a/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/type/TriggerType.java b/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/type/TriggerType.java index 63c4d104ee5..3f12313c20c 100644 --- a/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/type/TriggerType.java +++ b/bundles/automation/org.eclipse.smarthome.automation.api/src/main/java/org/eclipse/smarthome/automation/type/TriggerType.java @@ -11,77 +11,70 @@ import java.util.List; import java.util.Set; -import org.eclipse.smarthome.automation.Module; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.automation.Trigger; import org.eclipse.smarthome.automation.Visibility; import org.eclipse.smarthome.config.core.ConfigDescriptionParameter; /** - * This class is used to define trigger types. The triggers types contains meta - * info of the {@link Trigger} instances. Each trigger type has unique id in - * 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. + * This class provides common functionality for creating {@link Trigger} instances by supplying their meta-information. + * Each {@link TriggerType} is uniquely identifiable in scope of the {@link ModuleTypeRegistry} and defines + * {@link ConfigDescriptionParameter}s that are meta-information for configuration of the future {@link Trigger} + * instances and meta-information for {@link Output}s used from these {@link Trigger} instances. * * @author Yordan Mihaylov - Initial Contribution */ +@NonNullByDefault public class TriggerType extends ModuleType { - private List outputs; - - /** - * Default constructor for deserialization e.g. by Gson. - */ - protected TriggerType() { - } + private final List outputs; /** * 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 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. + * @param UID the {@link TriggerType}'s identifier, or {@code null} if a random identifier should be generated. + * @param configDescriptions describing metadata for the configuration of the future {@link Trigger} instances. + * @param outputs a {@link List} with {@link Output} meta-information descriptions of the future {@link Trigger} + * instances. */ - public TriggerType(String UID, List configDescriptions, List outputs) { + public TriggerType(@Nullable String UID, @Nullable List configDescriptions, + @Nullable List outputs) { super(UID, configDescriptions); - this.outputs = outputs; + this.outputs = outputs != null ? Collections.unmodifiableList(outputs) : Collections.emptyList(); } /** * 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. + * {@link Output} descriptions. * - * @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 UID the {@link TriggerType}'s identifier, or {@code null} if a random identifier should be generated. + * @param configDescriptions describing metadata for the configuration of the future {@link Trigger} instances. + * @param label a short and accurate, human-readable label of the {@link TriggerType}. + * @param description a detailed, human-readable description of usage of {@link TriggerType} and its benefits. * @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. + * @param outputs a {@link List} with {@link Output} meta-information descriptions of the future {@link Trigger} + * instances. */ - public TriggerType(String UID, List configDescriptions, String label, - String description, Set tags, Visibility visibility, List outputs) { + public TriggerType(@Nullable String UID, @Nullable List configDescriptions, + @Nullable String label, @Nullable String description, @Nullable Set tags, + @Nullable Visibility visibility, @Nullable List outputs) { super(UID, configDescriptions, label, description, tags, visibility); - this.outputs = outputs; + this.outputs = outputs != null ? Collections.unmodifiableList(outputs) : Collections.emptyList(); } /** - * This method is used for getting the meta-information descriptions of {@link Output}s defined by this type.
+ * This method is used to obtain the meta-information descriptions of {@link Output}s defined by this type.
* * @return a {@link List} of {@link Output} definitions. */ public List getOutputs() { - return outputs != null ? outputs : Collections. emptyList(); + return outputs; } } diff --git a/bundles/automation/org.eclipse.smarthome.automation.core.test/src/test/java/org/eclipse/smarthome/automation/core/internal/RuleEngineTest.java b/bundles/automation/org.eclipse.smarthome.automation.core.test/src/test/java/org/eclipse/smarthome/automation/core/internal/RuleEngineTest.java index cee32e9ae4f..5f553a35eed 100644 --- a/bundles/automation/org.eclipse.smarthome.automation.core.test/src/test/java/org/eclipse/smarthome/automation/core/internal/RuleEngineTest.java +++ b/bundles/automation/org.eclipse.smarthome.automation.core.test/src/test/java/org/eclipse/smarthome/automation/core/internal/RuleEngineTest.java @@ -50,12 +50,12 @@ private RuleEngine createRuleEngine() { @Test public void testAddRetrieveRules() { RuleEngine ruleEngine = createRuleEngine(); - Rule rule0 = new Rule(ruleEngine.getUniqueId()); + Rule rule0 = new Rule(null); ruleEngine.addRule(rule0, true); Collection rules = ruleEngine.getRuntimeRules(); Assert.assertNotNull("null returned instead of rules list", rules); Assert.assertEquals("empty rules list is returned", 1, rules.size()); - Assert.assertEquals("Returned rule with wrong UID", "rule_1", rules.iterator().next().getUID()); + Assert.assertNotNull("Returned rule with wrong UID", rules.iterator().next().getUID()); Rule rule1 = createRule(); ruleEngine.addRule(rule1, true); rules = ruleEngine.getRuntimeRules(); diff --git a/bundles/automation/org.eclipse.smarthome.automation.core.test/src/test/java/org/eclipse/smarthome/automation/core/internal/RulePrefixTest.java b/bundles/automation/org.eclipse.smarthome.automation.core.test/src/test/java/org/eclipse/smarthome/automation/core/internal/RulePrefixTest.java index 8f21f240d51..486a5176700 100644 --- a/bundles/automation/org.eclipse.smarthome.automation.core.test/src/test/java/org/eclipse/smarthome/automation/core/internal/RulePrefixTest.java +++ b/bundles/automation/org.eclipse.smarthome.automation.core.test/src/test/java/org/eclipse/smarthome/automation/core/internal/RulePrefixTest.java @@ -29,8 +29,8 @@ public class RulePrefixTest { */ @Test public void testEmptyPrefix() { - final Rule rule0 = new Rule(); - Assert.assertNull("Returned an UID instead of null", rule0.getUID()); + final Rule rule0 = new Rule(null); + Assert.assertNotNull("Returned UID is null instead of generated one", rule0.getUID()); Assert.assertNull("Returned a prefix instead of null", RulePredicates.getPrefix(rule0)); final String somethingWithoutSeparator = "something_without_separator"; diff --git a/bundles/automation/org.eclipse.smarthome.automation.core/src/main/java/org/eclipse/smarthome/automation/core/internal/RuleEngine.java b/bundles/automation/org.eclipse.smarthome.automation.core/src/main/java/org/eclipse/smarthome/automation/core/internal/RuleEngine.java index f8218a5d5bd..5da9f5b1fe3 100644 --- a/bundles/automation/org.eclipse.smarthome.automation.core/src/main/java/org/eclipse/smarthome/automation/core/internal/RuleEngine.java +++ b/bundles/automation/org.eclipse.smarthome.automation.core/src/main/java/org/eclipse/smarthome/automation/core/internal/RuleEngine.java @@ -93,11 +93,6 @@ public class RuleEngine implements RegistryChangeListener { */ public static final char OUTPUT_SEPARATOR = '.'; - /** - * Prefix of {@link Rule}'s UID created by the rule engine. - */ - public static final String ID_PREFIX = "rule_"; //$NON-NLS-1$ - /** * Default value of delay between rule's re-initialization tries. */ @@ -117,24 +112,24 @@ public class RuleEngine implements RegistryChangeListener { * {@link Map} of rule's id to corresponding {@link RuleEngineCallback}s. For each {@link Rule} there is one and * only one rule callback. */ - private Map reCallbacks = new HashMap(); + private final Map reCallbacks = new HashMap(); /** * {@link Map} of module type UIDs to rules where these module types participated. */ - private Map> mapModuleTypeToRules = new HashMap>(); + private final Map> mapModuleTypeToRules = new HashMap>(); /** * {@link Map} of created rules. It contains all rules added to rule engine independent if they are initialized or * not. The relation is rule's id to {@link Rule} object. */ - private Map rules; + private final Map rules; /** * {@link Map} system module type to corresponding module handler factories. */ - private Map moduleHandlerFactories; - private Set allModuleHandlerFactories = new CopyOnWriteArraySet<>(); + private final Map moduleHandlerFactories; + private final Set allModuleHandlerFactories = new CopyOnWriteArraySet<>(); /** * Locker which does not permit rule initialization when the rule engine is stopping. @@ -144,7 +139,7 @@ public class RuleEngine implements RegistryChangeListener { /** * {@link Map} of {@link Rule}'s id to current {@link RuleStatus} object. */ - private Map statusMap = new HashMap(); + private final Map statusMap = new HashMap(); protected Logger logger = LoggerFactory.getLogger(RuleEngine.class.getName()); @@ -156,8 +151,6 @@ public class RuleEngine implements RegistryChangeListener { private CompositeModuleHandlerFactory compositeFactory; - private int ruleMaxID = 0; - private Map scheduleTasks = new HashMap(31); private ScheduledExecutorService executor; @@ -366,11 +359,9 @@ private void setRule(RuntimeRule runtimeRule) { // property). The rule must stay NOT_INITIALISED. } - List modules = runtimeRule.getModules(null); - if (modules != null) { - for (Module m : modules) { - updateMapModuleTypeToRule(rUID, m.getTypeUID()); - } + List modules = runtimeRule.getModules(Module.class); + for (Module m : modules) { + updateMapModuleTypeToRule(rUID, m.getTypeUID()); } String errMsgs; @@ -994,29 +985,27 @@ private boolean calculateConditions(Rule rule) { */ private void executeActions(Rule rule, boolean stopOnFirstFail) { List actions = ((RuntimeRule) rule).getActions(); - if (actions == null || actions.size() == 0) { + if (actions.size() == 0) { return; } RuleStatus ruleStatus = null; - RuntimeAction action = null; for (Iterator it = actions.iterator(); it.hasNext();) { ruleStatus = getRuleStatus(rule.getUID()); if (ruleStatus != RuleStatus.RUNNING) { return; } - action = (RuntimeAction) it.next(); + RuntimeAction action = (RuntimeAction) it.next(); ActionHandler aHandler = action.getModuleHandler(); String rUID = rule.getUID(); Map context = getContext(rUID, action.getConnections()); try { - Map outputs = aHandler.execute(Collections.unmodifiableMap(context)); if (outputs != null) { context = getContext(rUID); updateContext(rUID, action.getId(), outputs); } } catch (Throwable t) { - String errMessage = "Fail to execute action: " + action != null ? action.getId() : ""; + String errMessage = "Fail to execute action: " + action.getId(); if (stopOnFirstFail) { RuntimeException re = new RuntimeException(errMessage, t); throw re; @@ -1088,34 +1077,6 @@ protected synchronized RuleStatusInfo getRuleStatusInfo(String rUID) { return statusMap.get(rUID); } - protected synchronized @NonNull String getUniqueId() { - int result = 0; - if (rules != null) { - Set col = rules.keySet(); - if (col != null) { - for (Iterator it = col.iterator(); it.hasNext();) { - String rUID = it.next(); - if (rUID != null && rUID.startsWith(ID_PREFIX)) { - String sNum = rUID.substring(ID_PREFIX.length()); - int i; - try { - i = Integer.parseInt(sNum); - result = i > result ? i : result; // find bigger key - } catch (NumberFormatException e) { - // skip this key - } - } - } - } - } - if (result > ruleMaxID) { - ruleMaxID = result + 1; - } else { - ++ruleMaxID; - } - return ID_PREFIX + ruleMaxID; - } - protected void setStatusInfoCallback(StatusInfoCallback statusInfoCallback) { this.statusInfoCallback = statusInfoCallback; } @@ -1303,8 +1264,8 @@ private Map getConnectionMap(Set connections) { class OutputRef { - private String moduleId; - private String outputName; + private final String moduleId; + private final String outputName; public OutputRef(String moduleId, String outputName) { this.moduleId = moduleId; @@ -1433,10 +1394,8 @@ private void handleModuleConfigReferences(List modules, Map configDescriptions = rule.getConfigurationDescriptions(); Map mapConfigDescriptions; - if (configDescriptions != null) { - mapConfigDescriptions = getConfigDescriptionMap(configDescriptions); - normalizeConfiguration(rule.getConfiguration(), mapConfigDescriptions); - } + mapConfigDescriptions = getConfigDescriptionMap(configDescriptions); + normalizeConfiguration(rule.getConfiguration(), mapConfigDescriptions); normalizeModuleConfigurations(rule.getTriggers()); normalizeModuleConfigurations(rule.getConditions()); normalizeModuleConfigurations(rule.getActions()); @@ -1451,11 +1410,9 @@ private void normalizeModuleConfigurations(List<@NonNull T> m ModuleType mt = mtRegistry.get(type); if (mt != null) { List configDescriptions = mt.getConfigurationDescriptions(); - if (configDescriptions != null) { - Map mapConfigDescriptions = getConfigDescriptionMap( - configDescriptions); - normalizeConfiguration(config, mapConfigDescriptions); - } + Map mapConfigDescriptions = getConfigDescriptionMap( + configDescriptions); + normalizeConfiguration(config, mapConfigDescriptions); } } } diff --git a/bundles/automation/org.eclipse.smarthome.automation.core/src/main/java/org/eclipse/smarthome/automation/core/internal/RuleRegistryImpl.java b/bundles/automation/org.eclipse.smarthome.automation.core/src/main/java/org/eclipse/smarthome/automation/core/internal/RuleRegistryImpl.java index 9b04478a999..fa427a34639 100644 --- a/bundles/automation/org.eclipse.smarthome.automation.core/src/main/java/org/eclipse/smarthome/automation/core/internal/RuleRegistryImpl.java +++ b/bundles/automation/org.eclipse.smarthome.automation.core/src/main/java/org/eclipse/smarthome/automation/core/internal/RuleRegistryImpl.java @@ -17,7 +17,6 @@ import java.util.Set; import java.util.stream.Stream; -import org.eclipse.jdt.annotation.NonNull; import org.eclipse.smarthome.automation.Rule; import org.eclipse.smarthome.automation.RuleProvider; import org.eclipse.smarthome.automation.RuleRegistry; @@ -91,7 +90,7 @@ public class RuleRegistryImpl extends AbstractRegistry disabledRulesStorage; private ModuleTypeRegistry moduleTypeRegistry; private RuleTemplateRegistry templateRegistry; @@ -99,7 +98,7 @@ public class RuleRegistryImpl extends AbstractRegistry> mapTemplateToRules = new HashMap>(); + private final Map> mapTemplateToRules = new HashMap>(); public RuleRegistryImpl() { super(RuleProvider.class); @@ -231,14 +230,8 @@ protected void removeModuleHandlerFactory(ModuleHandlerFactory moduleHandlerFact */ @Override public Rule add(Rule rule) { - String rUID = rule.getUID(); - if (rUID == null) { - rUID = ruleEngine.getUniqueId(); - super.add(initRuleId(rUID, rule)); - } else { - super.add(rule); - } - Rule ruleCopy = get(rUID); + super.add(rule); + Rule ruleCopy = get(rule.getUID()); if (ruleCopy != null) { return ruleCopy; } else { @@ -246,24 +239,6 @@ public Rule add(Rule rule) { } } - /** - * Sets a unique ID on the rule that should be added in the registry. If the rule already has an ID the method will - * not be invoked. - * - * @param rUID the unique Rule ID that should be set to the rule - * @param rule candidate for unique ID - * @return a rule with UID - */ - protected @NonNull Rule initRuleId(String rUID, Rule rule) { - Rule ruleWithUID = new Rule(rUID, rule.getTriggers(), rule.getConditions(), rule.getActions(), - rule.getConfigurationDescriptions(), rule.getConfiguration(), rule.getTemplateUID(), - rule.getVisibility()); - ruleWithUID.setName(rule.getName()); - ruleWithUID.setTags(rule.getTags()); - ruleWithUID.setDescription(rule.getDescription()); - return ruleWithUID; - } - /** * This method is used to add {@link Rule} into the RuleEngine. * When the rule is resolved it becomes into {@link RuleStatus#IDLE} state. @@ -280,20 +255,24 @@ public Rule add(Rule rule) { */ @Override protected void notifyListenersAboutAddedElement(Rule rule) { - super.notifyListenersAboutAddedElement(rule); - postRuleAddedEvent(rule); - String uid = rule.getUID(); - ruleEngine.addRule(rule, (disabledRulesStorage != null && disabledRulesStorage.get(uid) == null)); - String templateUID = rule.getTemplateUID(); - if (templateUID != null) { - synchronized (this) { - Set ruleUIDs = mapTemplateToRules.get(templateUID); - if (ruleUIDs == null) { - ruleUIDs = new HashSet(11); - mapTemplateToRules.put(templateUID, ruleUIDs); + try { + super.notifyListenersAboutAddedElement(rule); + postRuleAddedEvent(rule); + String uid = rule.getUID(); + ruleEngine.addRule(rule, (disabledRulesStorage != null && disabledRulesStorage.get(uid) == null)); + String templateUID = rule.getTemplateUID(); + if (templateUID != null) { + synchronized (this) { + Set ruleUIDs = mapTemplateToRules.get(templateUID); + if (ruleUIDs == null) { + ruleUIDs = new HashSet(11); + mapTemplateToRules.put(templateUID, ruleUIDs); + } + ruleUIDs.add(uid); } - ruleUIDs.add(uid); } + } catch (RuntimeException re) { + throw re; } } @@ -391,8 +370,7 @@ public Collection getByTag(String tag) { if (tag != null) { for (Collection rules : elementMap.values()) { for (Rule rule : rules) { - Set tags = rule.getTags(); - if (tags != null && tags.contains(tag)) { + if (rule.getTags().contains(tag)) { result.add(RuleUtils.getRuleCopy(rule)); } } @@ -420,8 +398,7 @@ public Collection getByTags(String... tags) { } else { for (Collection rules : elementMap.values()) { for (Rule rule : rules) { - Set rTags = rule.getTags(); - if (rTags != null && rTags.containsAll(tagSet)) { + if (rule.getTags().containsAll(tagSet)) { result.add(RuleUtils.getRuleCopy(rule)); } } @@ -494,11 +471,16 @@ private Rule resolveRuleByTemplate(Rule rule) { RuleUtils.getConditionsCopy(template.getConditions()), RuleUtils.getActionsCopy(template.getActions()), template.getConfigurationDescriptions(), rule.getConfiguration(), null, rule.getVisibility()); - resolvedRule.setName(rule.getName()); + String name = rule.getName(); + if (name != null) { + resolvedRule.setName(name); + } resolvedRule.setTags(rule.getTags()); - resolvedRule.setDescription(rule.getDescription()); + String description = rule.getDescription(); + if (description != null) { + resolvedRule.setDescription(description); + } - // TODO this provide config resolution twice - It must be done only in RuleEngine. Remove it. ruleEngine.resolveConfiguration(resolvedRule); return resolvedRule; @@ -518,13 +500,8 @@ protected void addProvider(Provider provider) { @Override public void added(Provider provider, Rule element) { - Rule ruleWithUID = element; - if (element.getUID() == null) { - String rUID = ruleEngine.getUniqueId(); - ruleWithUID = initRuleId(rUID, element); - } - super.added(provider, ruleWithUID); - updateRuleByTemplate(provider, ruleWithUID); + super.added(provider, element); + updateRuleByTemplate(provider, element); } private void updateRuleByTemplate(Provider provider, Rule rule) { @@ -538,12 +515,7 @@ private void updateRuleByTemplate(Provider provider, Rule rule) { @Override public void updated(Provider provider, Rule oldElement, Rule element) { - Rule ruleWithUID = element; - String rUID = oldElement.getUID(); - if (element.getUID() == null) { - ruleWithUID = initRuleId(rUID, element); - } - Rule resolvedRule = resolveRuleByTemplate(ruleWithUID); + Rule resolvedRule = resolveRuleByTemplate(element); super.updated(provider, oldElement, resolvedRule); } @@ -557,11 +529,9 @@ public void added(RuleTemplate element) { rules.addAll(rulesForResolving); } } - if (rules != null) { - for (String rUID : rules) { - Rule rule = get(rUID); - updateRuleByTemplate(getProvider(rule), rule); - } + for (String rUID : rules) { + Rule rule = get(rUID); + updateRuleByTemplate(getProvider(rule), rule); } } diff --git a/bundles/automation/org.eclipse.smarthome.automation.core/src/main/java/org/eclipse/smarthome/automation/core/internal/RuleUtils.java b/bundles/automation/org.eclipse.smarthome.automation.core/src/main/java/org/eclipse/smarthome/automation/core/internal/RuleUtils.java index 333ab8e0fe3..6b23e9ec3c3 100644 --- a/bundles/automation/org.eclipse.smarthome.automation.core/src/main/java/org/eclipse/smarthome/automation/core/internal/RuleUtils.java +++ b/bundles/automation/org.eclipse.smarthome.automation.core/src/main/java/org/eclipse/smarthome/automation/core/internal/RuleUtils.java @@ -8,12 +8,15 @@ package org.eclipse.smarthome.automation.core.internal; import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; 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.config.core.Configuration; /** * An utility class creating copy of the rule @@ -29,10 +32,12 @@ public class RuleUtils { * @return deep copy of list of conditions or empty list when the parameter is null. */ public static List getConditionsCopy(List conditions) { - List res = new ArrayList(11); + List res = new ArrayList(); if (conditions != null) { for (Condition c : conditions) { - Condition condition = new Condition(c.getId(), c.getTypeUID(), c.getConfiguration(), c.getInputs()); + Condition condition = new Condition(c.getId(), c.getTypeUID(), + new Configuration(c.getConfiguration().getProperties()), + new HashMap(c.getInputs())); condition.setLabel(c.getLabel()); condition.setDescription(c.getDescription()); res.add(condition); @@ -51,7 +56,9 @@ public static List getActionsCopy(List actions) { List res = new ArrayList(); if (actions != null) { for (Action a : actions) { - Action action = new Action(a.getId(), a.getTypeUID(), a.getConfiguration(), a.getInputs()); + Action action = new Action(a.getId(), a.getTypeUID(), + new Configuration(a.getConfiguration().getProperties()), + new HashMap(a.getInputs())); action.setLabel(a.getLabel()); action.setDescription(a.getDescription()); res.add(action); @@ -67,10 +74,11 @@ public static List getActionsCopy(List actions) { * @return deep copy of list of triggers or empty list when parameter is null. */ public static List getTriggersCopy(List triggers) { - List res = new ArrayList(11); + List res = new ArrayList(); if (triggers != null) { for (Trigger t : triggers) { - Trigger trigger = new Trigger(t.getId(), t.getTypeUID(), t.getConfiguration()); + Trigger trigger = new Trigger(t.getId(), t.getTypeUID(), + new Configuration(t.getConfiguration().getProperties())); trigger.setLabel(t.getLabel()); trigger.setDescription(t.getDescription()); res.add(trigger); @@ -81,17 +89,23 @@ public static List getTriggersCopy(List triggers) { /** * This method creates copy of the rule - * + * * @param rule the rule which has to be copied * @return copy of the rule. */ public static Rule getRuleCopy(Rule r) { Rule rule = new Rule(r.getUID(), getTriggersCopy(r.getTriggers()), getConditionsCopy(r.getConditions()), - getActionsCopy(r.getActions()), r.getConfigurationDescriptions(), r.getConfiguration(), - r.getTemplateUID(), r.getVisibility()); - rule.setName(r.getName()); - rule.setTags(r.getTags()); - rule.setDescription(r.getDescription()); + getActionsCopy(r.getActions()), new ArrayList<>(r.getConfigurationDescriptions()), + new Configuration(r.getConfiguration().getProperties()), r.getTemplateUID(), r.getVisibility()); + String name = r.getName(); + if (name != null) { + rule.setName(name); + } + rule.setTags(new HashSet(r.getTags())); + String description = r.getDescription(); + if (description != null) { + rule.setDescription(description); + } return rule; } diff --git a/bundles/automation/org.eclipse.smarthome.automation.core/src/main/java/org/eclipse/smarthome/automation/core/internal/RuntimeRule.java b/bundles/automation/org.eclipse.smarthome.automation.core/src/main/java/org/eclipse/smarthome/automation/core/internal/RuntimeRule.java index 06966e37df4..83e398a2282 100644 --- a/bundles/automation/org.eclipse.smarthome.automation.core/src/main/java/org/eclipse/smarthome/automation/core/internal/RuntimeRule.java +++ b/bundles/automation/org.eclipse.smarthome.automation.core/src/main/java/org/eclipse/smarthome/automation/core/internal/RuntimeRule.java @@ -35,6 +35,7 @@ public class RuntimeRule extends Rule { * @param rule a rule which has to be copied or null when an empty instance of rule * has to be created. */ + @SuppressWarnings("null") protected RuntimeRule(Rule rule) { super(rule.getUID(), getRuntimeTriggersCopy(rule.getTriggers()), getRuntimeConditionsCopy(rule.getConditions()), getRuntimeActionsCopy(rule.getActions()), rule.getConfigurationDescriptions(), rule.getConfiguration(), @@ -67,10 +68,6 @@ private Map initModuleMap() { return moduleMap; } - protected void setUID(String rUID) { - uid = rUID; - } - private static List getRuntimeActionsCopy(List actions) { List res = new ArrayList(); if (actions != null) { @@ -82,7 +79,7 @@ private static List getRuntimeActionsCopy(List actions) { } private static List getRuntimeConditionsCopy(List conditions) { - List res = new ArrayList(11); + List res = new ArrayList(); if (conditions != null) { for (Condition condition : conditions) { res.add(new RuntimeCondition(condition)); @@ -92,7 +89,7 @@ private static List getRuntimeConditionsCopy(List conditio } private static List getRuntimeTriggersCopy(List triggers) { - List res = new ArrayList(11); + List res = new ArrayList(); if (triggers != null) { for (Trigger trigger : triggers) { res.add(new RuntimeTrigger(trigger)); diff --git a/bundles/automation/org.eclipse.smarthome.automation.module.script.rulesupport/src/main/java/org/eclipse/smarthome/automation/module/script/rulesupport/shared/simple/SimpleRule.java b/bundles/automation/org.eclipse.smarthome.automation.module.script.rulesupport/src/main/java/org/eclipse/smarthome/automation/module/script/rulesupport/shared/simple/SimpleRule.java index a76f607ee46..2cb4e28d5e7 100644 --- a/bundles/automation/org.eclipse.smarthome.automation.module.script.rulesupport/src/main/java/org/eclipse/smarthome/automation/module/script/rulesupport/shared/simple/SimpleRule.java +++ b/bundles/automation/org.eclipse.smarthome.automation.module.script.rulesupport/src/main/java/org/eclipse/smarthome/automation/module/script/rulesupport/shared/simple/SimpleRule.java @@ -17,4 +17,8 @@ */ public abstract class SimpleRule extends Rule implements SimpleRuleActionHandler { + public SimpleRule(String uid) { + super(uid); + } + } diff --git a/bundles/automation/org.eclipse.smarthome.automation.parser.gson/META-INF/MANIFEST.MF b/bundles/automation/org.eclipse.smarthome.automation.parser.gson/META-INF/MANIFEST.MF index 38557830d7a..f078a5b4288 100644 --- a/bundles/automation/org.eclipse.smarthome.automation.parser.gson/META-INF/MANIFEST.MF +++ b/bundles/automation/org.eclipse.smarthome.automation.parser.gson/META-INF/MANIFEST.MF @@ -7,6 +7,7 @@ Bundle-Vendor: Eclipse.org/SmartHome Bundle-Version: 0.9.0.qualifier Import-Package: com.google.gson, + com.google.gson.reflect, com.google.gson.stream, org.eclipse.jdt.annotation;resolution:=optional, org.eclipse.smarthome.automation, @@ -14,5 +15,6 @@ Import-Package: org.eclipse.smarthome.automation.template, org.eclipse.smarthome.automation.type, org.eclipse.smarthome.config.core, + org.eclipse.smarthome.core.common, org.osgi.framework Service-Component: OSGI-INF/*.xml diff --git a/bundles/automation/org.eclipse.smarthome.automation.parser.gson/src/main/java/org/eclipse/smarthome/automation/parser/gson/internal/AbstractGSONParser.java b/bundles/automation/org.eclipse.smarthome.automation.parser.gson/src/main/java/org/eclipse/smarthome/automation/parser/gson/internal/AbstractGSONParser.java index 11fa2ab6887..89a29ac319d 100644 --- a/bundles/automation/org.eclipse.smarthome.automation.parser.gson/src/main/java/org/eclipse/smarthome/automation/parser/gson/internal/AbstractGSONParser.java +++ b/bundles/automation/org.eclipse.smarthome.automation.parser.gson/src/main/java/org/eclipse/smarthome/automation/parser/gson/internal/AbstractGSONParser.java @@ -10,7 +10,12 @@ import java.io.OutputStreamWriter; import java.util.Set; +import org.eclipse.smarthome.automation.Rule; import org.eclipse.smarthome.automation.parser.Parser; +import org.eclipse.smarthome.automation.template.RuleTemplate; +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.config.core.Configuration; import com.google.gson.Gson; @@ -20,13 +25,19 @@ * Abstract class that can be used by the parsers for the different entity types. * * @author Kai Kreuzer - Initial contribution + * @author Ana Dimova - add Instance Creators * * @param the type of the entities to parse */ public abstract class AbstractGSONParser implements Parser { // A Gson instance to use by the parsers - static protected Gson gson = new GsonBuilder() + static protected Gson gson = new GsonBuilder() // + .registerTypeAdapter(Rule.class, new RuleInstanceCreator()) // + .registerTypeAdapter(RuleTemplate.class, new TemplateInstanceCreator()) // + .registerTypeAdapter(CompositeActionType.class, new ActionInstanceCreator()) // + .registerTypeAdapter(CompositeConditionType.class, new ConditionInstanceCreator()) // + .registerTypeAdapter(CompositeTriggerType.class, new TriggerInstanceCreator()) // .registerTypeAdapter(Configuration.class, new ConfigurationDeserializer()) // .registerTypeAdapter(Configuration.class, new ConfigurationSerializer()) // .create(); diff --git a/bundles/automation/org.eclipse.smarthome.automation.parser.gson/src/main/java/org/eclipse/smarthome/automation/parser/gson/internal/ActionInstanceCreator.java b/bundles/automation/org.eclipse.smarthome.automation.parser.gson/src/main/java/org/eclipse/smarthome/automation/parser/gson/internal/ActionInstanceCreator.java new file mode 100644 index 00000000000..a49b415755a --- /dev/null +++ b/bundles/automation/org.eclipse.smarthome.automation.parser.gson/src/main/java/org/eclipse/smarthome/automation/parser/gson/internal/ActionInstanceCreator.java @@ -0,0 +1,29 @@ +/** +* Copyright (c) 2015, 2017 by Bosch Software Innovations 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.gson.internal; + +import java.lang.reflect.Type; + +import org.eclipse.smarthome.automation.type.ActionType; +import org.eclipse.smarthome.automation.type.CompositeActionType; + +import com.google.gson.InstanceCreator; + +/** + * This class creates {@link ActionType} instances. + * + * @author Ana Dimova - Initial Contribution + * + */ +public class ActionInstanceCreator implements InstanceCreator { + + @Override + public CompositeActionType createInstance(Type type) { + return new CompositeActionType(null, null, null, null, null); + } +} diff --git a/bundles/automation/org.eclipse.smarthome.automation.parser.gson/src/main/java/org/eclipse/smarthome/automation/parser/gson/internal/ConditionInstanceCreator.java b/bundles/automation/org.eclipse.smarthome.automation.parser.gson/src/main/java/org/eclipse/smarthome/automation/parser/gson/internal/ConditionInstanceCreator.java new file mode 100644 index 00000000000..3d467c21b5d --- /dev/null +++ b/bundles/automation/org.eclipse.smarthome.automation.parser.gson/src/main/java/org/eclipse/smarthome/automation/parser/gson/internal/ConditionInstanceCreator.java @@ -0,0 +1,29 @@ +/** +* Copyright (c) 2015, 2017 by Bosch Software Innovations 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.gson.internal; + +import java.lang.reflect.Type; + +import org.eclipse.smarthome.automation.type.CompositeConditionType; +import org.eclipse.smarthome.automation.type.ConditionType; + +import com.google.gson.InstanceCreator; + +/** + * This class creates {@link ConditionType} instances. + * + * @author Ana Dimova - Initial Contribution + * + */ +public class ConditionInstanceCreator implements InstanceCreator { + + @Override + public CompositeConditionType createInstance(Type type) { + return new CompositeConditionType(null, null, null, null); + } +} diff --git a/bundles/automation/org.eclipse.smarthome.automation.parser.gson/src/main/java/org/eclipse/smarthome/automation/parser/gson/internal/RuleGSONParser.java b/bundles/automation/org.eclipse.smarthome.automation.parser.gson/src/main/java/org/eclipse/smarthome/automation/parser/gson/internal/RuleGSONParser.java index a2ccfdd1bf6..99b9768c4a0 100644 --- a/bundles/automation/org.eclipse.smarthome.automation.parser.gson/src/main/java/org/eclipse/smarthome/automation/parser/gson/internal/RuleGSONParser.java +++ b/bundles/automation/org.eclipse.smarthome.automation.parser.gson/src/main/java/org/eclipse/smarthome/automation/parser/gson/internal/RuleGSONParser.java @@ -9,15 +9,16 @@ import java.io.IOException; import java.io.InputStreamReader; -import java.util.Arrays; import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Set; import org.eclipse.smarthome.automation.Rule; import org.eclipse.smarthome.automation.parser.ParsingException; import org.eclipse.smarthome.automation.parser.ParsingNestedException; +import com.google.gson.reflect.TypeToken; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonToken; @@ -33,17 +34,17 @@ public class RuleGSONParser extends AbstractGSONParser { public Set parse(InputStreamReader reader) throws ParsingException { JsonReader jr = new JsonReader(reader); try { + Set rules = new HashSet<>(); if (jr.hasNext()) { JsonToken token = jr.peek(); if (JsonToken.BEGIN_ARRAY.equals(token)) { - Rule[] rules = gson.fromJson(jr, Rule[].class); - return new HashSet(Arrays.asList(rules)); + rules.addAll(gson.fromJson(jr, new TypeToken>() { + }.getType())); } else { Rule rule = gson.fromJson(jr, Rule.class); - Set rules = new HashSet(); rules.add(rule); - return rules; } + return rules; } } catch (Exception e) { throw new ParsingException(new ParsingNestedException(ParsingNestedException.RULE, null, e)); diff --git a/bundles/automation/org.eclipse.smarthome.automation.parser.gson/src/main/java/org/eclipse/smarthome/automation/parser/gson/internal/RuleInstanceCreator.java b/bundles/automation/org.eclipse.smarthome.automation.parser.gson/src/main/java/org/eclipse/smarthome/automation/parser/gson/internal/RuleInstanceCreator.java new file mode 100644 index 00000000000..c4e8efe529a --- /dev/null +++ b/bundles/automation/org.eclipse.smarthome.automation.parser.gson/src/main/java/org/eclipse/smarthome/automation/parser/gson/internal/RuleInstanceCreator.java @@ -0,0 +1,28 @@ +/** +* Copyright (c) 2015, 2017 by Bosch Software Innovations 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.gson.internal; + +import java.lang.reflect.Type; + +import org.eclipse.smarthome.automation.Rule; + +import com.google.gson.InstanceCreator; + +/** + * This class creates {@link Rule} instances. + * + * @author Ana Dimova - Initial contribution + * + */ +public class RuleInstanceCreator implements InstanceCreator { + + @Override + public Rule createInstance(Type type) { + return new Rule(null); + } +} diff --git a/bundles/automation/org.eclipse.smarthome.automation.parser.gson/src/main/java/org/eclipse/smarthome/automation/parser/gson/internal/TemplateGSONParser.java b/bundles/automation/org.eclipse.smarthome.automation.parser.gson/src/main/java/org/eclipse/smarthome/automation/parser/gson/internal/TemplateGSONParser.java index 4707b5c6e68..7856c456ff6 100644 --- a/bundles/automation/org.eclipse.smarthome.automation.parser.gson/src/main/java/org/eclipse/smarthome/automation/parser/gson/internal/TemplateGSONParser.java +++ b/bundles/automation/org.eclipse.smarthome.automation.parser.gson/src/main/java/org/eclipse/smarthome/automation/parser/gson/internal/TemplateGSONParser.java @@ -9,9 +9,9 @@ import java.io.IOException; import java.io.InputStreamReader; -import java.util.Arrays; import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Set; import org.eclipse.smarthome.automation.parser.ParsingException; @@ -19,6 +19,7 @@ import org.eclipse.smarthome.automation.template.RuleTemplate; import org.eclipse.smarthome.automation.template.Template; +import com.google.gson.reflect.TypeToken; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonToken; @@ -36,18 +37,18 @@ public Set