/** * Copyright (c) 1997, 2015 by ProSyst Software GmbH and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package org.eclipse.smarthome.automation.internal.commands; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.eclipse.smarthome.automation.Action; import org.eclipse.smarthome.automation.Condition; import org.eclipse.smarthome.automation.Module; import org.eclipse.smarthome.automation.Rule; import org.eclipse.smarthome.automation.RuleStatus; import org.eclipse.smarthome.automation.template.RuleTemplate; import org.eclipse.smarthome.automation.template.Template; import org.eclipse.smarthome.automation.type.ActionType; import org.eclipse.smarthome.automation.type.CompositeActionType; import org.eclipse.smarthome.automation.type.CompositeConditionType; import org.eclipse.smarthome.automation.type.CompositeTriggerType; import org.eclipse.smarthome.automation.type.ConditionType; import org.eclipse.smarthome.automation.type.Input; import org.eclipse.smarthome.automation.type.ModuleType; import org.eclipse.smarthome.automation.type.Output; import org.eclipse.smarthome.automation.type.TriggerType; import org.eclipse.smarthome.config.core.ConfigDescriptionParameter; import org.eclipse.smarthome.config.core.FilterCriteria; import org.eclipse.smarthome.config.core.ParameterOption; /** * This class provides the functionality responsible for printing the automation objects as a result of commands. * * @author Ana Dimova - Initial Contribution * @author Yordan Mihaylov - updates related to api changes * */ public class Printer { private static final int TABLE_WIDTH = 100; private static final int COLUMN_ID = 7; private static final int COLUMN_UID = 93; private static final int COLUMN_RULE_UID = 36; private static final int COLUMN_RULE_NAME = 36; private static final int COLUMN_RULE_STATUS = 15; private static final int COLUMN_PROPERTY = 28; private static final int COLUMN_PROPERTY_VALUE = 72; private static final int COLUMN_CONFIG_PARAMETER = 20; private static final int COLUMN_CONFIG_PARAMETER_VALUE = 52; private static final int COLUMN_CONFIG_PARAMETER_PROP = 16; private static final int COLUMN_CONFIG_PARAMETER_PROP_VALUE = 36; private static final String ID = "ID"; private static final String UID = "UID"; private static final String NAME = "NAME"; private static final String STATUS = "STATUS"; private static final String TAGS = "TAGS"; private static final String LABEL = "LABEL"; private static final String VISIBILITY = "VISIBILITY"; private static final String DESCRIPTION = "DESCRIPTION"; private static final String CONFIGURATION_DESCRIPTIONS = "CONFIGURATION DESCRIPTIONS "; private static final String ACTIONS = "ACTIONS"; private static final String TRIGGERS = "TRIGGERS"; private static final String CONDITIONS = "CONDITIONS"; private static final String INPUTS = "INPUTS"; private static final String OUTPUTS = "OUTPUTS"; private static final String CHILDREN = "CHILDREN"; private static final String TYPE = "TYPE"; private static final String CONFIGURATION = "CONFIGURATION"; private static final String MIN = "MIN"; private static final String MAX = "MAX"; private static final String DEFAULT = "DEFAULT"; private static final String CONTEXT = "CONTEXT"; private static final String PATTERN = "PATTERN"; private static final String OPTIONS = "OPTIONS"; private static final String STEP_SIZE = "STEP_SIZE"; private static final String FILTER_CRITERIA = "FILTER CRITERIA "; private static final String REQUIRED = "REQUIRED"; private static final String NOT_REQUIRED = "NOT REQUIRED"; /** * This method is responsible for printing the list with indexes, UIDs, names and statuses of the {@link Rule}s. * * @param autoCommands * @param ruleUIDs * @return */ static String printRules(AutomationCommandsPluggable autoCommands, Map<String, String> ruleUIDs) { int[] columnWidths = new int[] { COLUMN_ID, COLUMN_RULE_UID, COLUMN_RULE_NAME, COLUMN_RULE_STATUS }; List<String> columnValues = new ArrayList<String>(); columnValues.add(ID); columnValues.add(UID); columnValues.add(NAME); columnValues.add(STATUS); String titleRow = Utils.getRow(columnWidths, columnValues); List<String> rulesRows = new ArrayList<String>(); for (int i = 1; i <= ruleUIDs.size(); i++) { String id = new Integer(i).toString(); String uid = ruleUIDs.get(id); columnValues.set(0, id); columnValues.set(1, uid); Rule rule = autoCommands.getRule(uid); columnValues.set(2, rule.getName()); columnValues.set(3, autoCommands.getRuleStatus(uid).toString()); rulesRows.add(Utils.getRow(columnWidths, columnValues)); } return Utils.getTableContent(TABLE_WIDTH, columnWidths, rulesRows, titleRow); } /** * This method is responsible for printing the list with indexes and UIDs of the {@link Template}s. * * @param templateUIDs is a map with keys UIDs of the {@link Template}s and values the {@link Template}s. * @return a formated string, representing the sorted list with indexed UIDs of the available {@link Template}s. */ static String printTemplates(Map<String, String> templateUIDs) { int[] columnWidths = new int[] { COLUMN_ID, COLUMN_UID }; List<String> columnTitles = new ArrayList<String>(); columnTitles.add(ID); columnTitles.add(UID); String titleRow = Utils.getRow(columnWidths, columnTitles); List<String> templates = new ArrayList<String>(); collectListRecords(templateUIDs, templates, columnWidths); return Utils.getTableContent(TABLE_WIDTH, columnWidths, templates, titleRow); } /** * This method is responsible for printing the list with indexes and UIDs of the {@link ModuleType}s. * * @param moduleTypeUIDs is a map with keys UIDs of the {@link ModuleType}s and values the {@link ModuleType}s. * @return a formated string, representing the sorted list with indexed UIDs of the available {@link ModuleType}s. */ static String printModuleTypes(Map<String, String> moduleTypeUIDs) { int[] columnWidths = new int[] { COLUMN_ID, COLUMN_UID }; List<String> columnTitles = new ArrayList<String>(); columnTitles.add(ID); columnTitles.add(UID); String titleRow = Utils.getRow(columnWidths, columnTitles); List<String> moduleTypes = new ArrayList<String>(); collectListRecords(moduleTypeUIDs, moduleTypes, columnWidths); return Utils.getTableContent(TABLE_WIDTH, columnWidths, moduleTypes, titleRow); } /** * This method is responsible for printing the {@link Rule}. * * @param rule the {@link Rule} for printing. * @return a formated string, representing the {@link Rule} info. */ static String printRule(Rule rule, RuleStatus status) { int[] columnWidths = new int[] { TABLE_WIDTH }; List<String> ruleProperty = new ArrayList<String>(); ruleProperty.add(rule.getUID() + " [ " + status + " ]"); String titleRow = Utils.getRow(columnWidths, ruleProperty); List<String> ruleContent = new ArrayList<String>(); columnWidths = new int[] { COLUMN_PROPERTY, COLUMN_PROPERTY_VALUE }; ruleProperty.set(0, UID); ruleProperty.add(rule.getUID()); ruleContent.add(Utils.getRow(columnWidths, ruleProperty)); if (rule.getName() != null) { ruleProperty.set(0, NAME); ruleProperty.set(1, rule.getName()); ruleContent.add(Utils.getRow(columnWidths, ruleProperty)); } if (rule.getDescription() != null) { ruleProperty.set(0, DESCRIPTION); ruleProperty.set(1, rule.getDescription()); ruleContent.add(Utils.getRow(columnWidths, ruleProperty)); } ruleProperty.set(0, TAGS); ruleProperty.set(1, getTagsRecord(rule.getTags())); ruleContent.add(Utils.getRow(columnWidths, ruleProperty)); ruleContent.addAll( collectRecords(columnWidths, CONFIGURATION, rule.getConfiguration().getProperties().entrySet())); ruleContent.addAll(collectRecords(columnWidths, CONFIGURATION_DESCRIPTIONS, getConfigurationDescriptionRecords(rule.getConfigurationDescriptions()))); ruleContent.addAll(collectRecords(columnWidths, TRIGGERS, rule.getTriggers())); ruleContent.addAll(collectRecords(columnWidths, CONDITIONS, rule.getConditions())); ruleContent.addAll(collectRecords(columnWidths, ACTIONS, rule.getActions())); return Utils.getTableContent(TABLE_WIDTH, columnWidths, ruleContent, titleRow); } /** * This method is responsible for printing the {@link Template}. * * @param template the {@link Template} for printing. * @return a formated string, representing the {@link Template} info. */ static String printTemplate(Template template) { int[] columnWidths = new int[] { TABLE_WIDTH }; List<String> templateProperty = new ArrayList<String>(); templateProperty.add(template.getUID()); String titleRow = Utils.getRow(columnWidths, templateProperty); List<String> templateContent = new ArrayList<String>(); columnWidths = new int[] { COLUMN_PROPERTY, COLUMN_PROPERTY_VALUE }; templateProperty.set(0, UID); templateProperty.add(template.getUID()); templateContent.add(Utils.getRow(columnWidths, templateProperty)); if (template.getLabel() != null) { templateProperty.set(0, LABEL); templateProperty.set(1, template.getLabel()); templateContent.add(Utils.getRow(columnWidths, templateProperty)); } if (template.getDescription() != null) { templateProperty.set(0, DESCRIPTION); templateProperty.set(1, template.getDescription()); templateContent.add(Utils.getRow(columnWidths, templateProperty)); } templateProperty.set(0, VISIBILITY); templateProperty.set(1, template.getVisibility().toString()); templateContent.add(Utils.getRow(columnWidths, templateProperty)); templateProperty.set(0, TAGS); templateProperty.set(1, getTagsRecord(template.getTags())); templateContent.add(Utils.getRow(columnWidths, templateProperty)); if (template instanceof RuleTemplate) { templateContent.addAll(collectRecords(columnWidths, CONFIGURATION_DESCRIPTIONS, getConfigurationDescriptionRecords(((RuleTemplate) template).getConfigurationDescriptions()))); templateContent.addAll(collectRecords(columnWidths, TRIGGERS, ((RuleTemplate) template).getTriggers())); templateContent.addAll(collectRecords(columnWidths, CONDITIONS, ((RuleTemplate) template).getConditions())); templateContent.addAll(collectRecords(columnWidths, ACTIONS, ((RuleTemplate) template).getActions())); } return Utils.getTableContent(TABLE_WIDTH, columnWidths, templateContent, titleRow); } /** * This method is responsible for printing the {@link ModuleType}. * * @param moduleType the {@link ModuleType} for printing. * @return a formated string, representing the {@link ModuleType} info. */ static String printModuleType(ModuleType moduleType) { int[] columnWidths = new int[] { TABLE_WIDTH }; List<String> moduleTypeProperty = new ArrayList<String>(); moduleTypeProperty.add(moduleType.getUID()); String titleRow = Utils.getRow(columnWidths, moduleTypeProperty); List<String> moduleTypeContent = new ArrayList<String>(); columnWidths = new int[] { COLUMN_PROPERTY, COLUMN_PROPERTY_VALUE }; moduleTypeProperty.set(0, UID); moduleTypeProperty.add(moduleType.getUID()); moduleTypeContent.add(Utils.getRow(columnWidths, moduleTypeProperty)); if (moduleType.getLabel() != null) { moduleTypeProperty.set(0, LABEL); moduleTypeProperty.set(1, moduleType.getLabel()); moduleTypeContent.add(Utils.getRow(columnWidths, moduleTypeProperty)); } if (moduleType.getDescription() != null) { moduleTypeProperty.set(0, DESCRIPTION); moduleTypeProperty.set(1, moduleType.getDescription()); moduleTypeContent.add(Utils.getRow(columnWidths, moduleTypeProperty)); } moduleTypeProperty.set(0, VISIBILITY); moduleTypeProperty.set(1, moduleType.getVisibility().toString()); moduleTypeContent.add(Utils.getRow(columnWidths, moduleTypeProperty)); moduleTypeProperty.set(0, TAGS); moduleTypeProperty.set(1, getTagsRecord(moduleType.getTags())); moduleTypeContent.add(Utils.getRow(columnWidths, moduleTypeProperty)); moduleTypeContent.addAll(collectRecords(columnWidths, CONFIGURATION_DESCRIPTIONS, getConfigurationDescriptionRecords(moduleType.getConfigurationDescriptions()))); if (moduleType instanceof TriggerType) { moduleTypeContent.addAll(collectRecords(columnWidths, OUTPUTS, ((TriggerType) moduleType).getOutputs())); } if (moduleType instanceof ConditionType) { moduleTypeContent.addAll(collectRecords(columnWidths, INPUTS, ((ConditionType) moduleType).getInputs())); } if (moduleType instanceof ActionType) { moduleTypeContent.addAll(collectRecords(columnWidths, INPUTS, ((ActionType) moduleType).getInputs())); moduleTypeContent.addAll(collectRecords(columnWidths, OUTPUTS, ((ActionType) moduleType).getOutputs())); } if (moduleType instanceof CompositeTriggerType) { moduleTypeContent .addAll(collectRecords(columnWidths, CHILDREN, ((CompositeTriggerType) moduleType).getChildren())); } if (moduleType instanceof CompositeConditionType) { moduleTypeContent.addAll( collectRecords(columnWidths, CHILDREN, ((CompositeConditionType) moduleType).getChildren())); } if (moduleType instanceof CompositeActionType) { moduleTypeContent .addAll(collectRecords(columnWidths, CHILDREN, ((CompositeActionType) moduleType).getChildren())); } return Utils.getTableContent(TABLE_WIDTH, columnWidths, moduleTypeContent, titleRow); } /** * This method is responsible for printing the {@link RuleStatus}. * * @param ruleUID specifies the rule, which status is requested. * @param status corresponds to the status of specified rule. * @return a string representing the response of the command {@link AutomationCommands#ENABLE_RULE}. */ static String printRuleStatus(String ruleUID, RuleStatus status) { List<String> title = new ArrayList<String>(); title.add(ruleUID + " [ " + status + " ]"); String titleRow = Utils.getRow(new int[] { TABLE_WIDTH }, title); List<String> res = Utils.getTableTitle(titleRow, TABLE_WIDTH); StringBuilder sb = new StringBuilder(); for (String line : res) { sb.append(line + Utils.ROW_END); } return sb.toString(); } /** * This method is responsible for printing the strings, representing the auxiliary automation objects. * * @param columnWidths represents the column widths of the table. * @param width represents the table width. * @param prop is a property name of the property with value the collection of the auxiliary automation objects for * printing. * @param list with the auxiliary automation objects for printing. * @return list of strings, representing the auxiliary automation objects. */ @SuppressWarnings("unchecked") private static List<String> collectRecords(int[] columnWidths, String prop, Collection<?> list) { List<String> res = new ArrayList<String>(); boolean isFirst = true; boolean isList = false; List<String> values = new ArrayList<String>(); values.add(prop); values.add(""); if (list != null && !list.isEmpty()) { for (Object element : list) { if (element instanceof String) { res.add(Utils.getColumn(columnWidths[0], values.get(0)) + (String) element); if (isFirst) { isFirst = false; values.set(0, ""); } } else if (element instanceof Module) { List<String> moduleRecords = getModuleRecords((Module) element); for (String elementRecord : moduleRecords) { res.add(Utils.getColumn(columnWidths[0], values.get(0)) + elementRecord); if (isFirst) { isFirst = false; values.set(0, ""); } } } else { isList = true; if (isFirst) { values.set(1, "["); res.add(Utils.getRow(columnWidths, values)); isFirst = false; } values.set(0, ""); if (element instanceof FilterCriteria) { values.set(1, getFilterCriteriaRecord((FilterCriteria) element)); } else if (element instanceof ParameterOption) { values.set(1, getParameterOptionRecord((ParameterOption) element)); } else if (element instanceof Input) { values.set(1, getInputRecord((Input) element)); } else if (element instanceof Output) { values.set(1, getOutputRecord((Output) element)); } else if (element instanceof Entry) { values.set(1, " " + ((Entry<String, ?>) element).getKey() + " = \"" + ((Entry<String, ?>) element).getValue().toString() + "\""); } res.add(Utils.getRow(columnWidths, values)); } } if (isList) { values.set(0, ""); values.set(1, "]"); res.add(Utils.getRow(columnWidths, values)); } } return res; } /** * This method is responsible for printing the {@link Module}. * * @param module the {@link Module} for printing. * @return a formated string, representing the {@link Module}. */ private static List<String> getModuleRecords(Module module) { int[] columnWidths = new int[] { COLUMN_PROPERTY_VALUE }; List<String> columnValues = new ArrayList<String>(); columnValues.add(module.getId()); List<String> moduleContent = new ArrayList<String>(); moduleContent.addAll(Utils.getTableTitle(Utils.getRow(columnWidths, columnValues), COLUMN_PROPERTY_VALUE)); columnWidths = new int[] { COLUMN_CONFIG_PARAMETER, COLUMN_CONFIG_PARAMETER_VALUE }; columnValues.set(0, ID); columnValues.add(module.getId()); moduleContent.add(Utils.getRow(columnWidths, columnValues)); if (module.getLabel() != null) { columnValues.set(0, LABEL); columnValues.set(1, module.getLabel()); moduleContent.add(Utils.getRow(columnWidths, columnValues)); } if (module.getDescription() != null) { columnValues.set(0, DESCRIPTION); columnValues.set(1, module.getDescription()); moduleContent.add(Utils.getRow(columnWidths, columnValues)); } columnValues.set(0, TYPE); columnValues.set(1, module.getTypeUID()); moduleContent.add(Utils.getRow(columnWidths, columnValues)); moduleContent.addAll( collectRecords(columnWidths, CONFIGURATION, module.getConfiguration().getProperties().entrySet())); Map<String, String> inputs = null; if (module instanceof Condition) { inputs = ((Condition) module).getInputs(); } if (module instanceof Action) { inputs = ((Action) module).getInputs(); } if (inputs != null && !inputs.isEmpty()) { moduleContent.addAll( collectRecords(columnWidths, INPUTS, new ArrayList<Entry<String, String>>(inputs.entrySet()))); } return moduleContent; } private static String getParameterOptionRecord(ParameterOption option) { return " value=\"" + option.getValue() + "\", label=\"" + option.getLabel() + "\""; } private static String getFilterCriteriaRecord(FilterCriteria criteria) { return " name=\"" + criteria.getName() + "\", value=\"" + criteria.getValue() + "\""; } private static String getInputRecord(Input input) { return " name=\"" + input.getName() + "\", label=\"" + input.getLabel() + "\", decription=\"" + input.getDescription() + "\", type=\"" + input.getType() + "\", " + (input.isRequired() ? REQUIRED : NOT_REQUIRED) + (input.getDefaultValue() != null ? "\", default=\"" + input.getDefaultValue() : ""); } private static String getOutputRecord(Output output) { return " name=\"" + output.getName() + "\", label=\"" + output.getLabel() + "\", decription=\"" + output.getDescription() + "\", type=\"" + output.getType() + "\""; } /** * This method is responsible for printing the set of {@link ConfigDescriptionParameter}s. * * @param configDescriptions set of {@link ConfigDescriptionParameter}s for printing. * @return a formated string, representing the set of {@link ConfigDescriptionParameter}s. */ private static List<String> getConfigurationDescriptionRecords( List<ConfigDescriptionParameter> configDescriptions) { List<String> configParamContent = new ArrayList<String>(); if (configDescriptions != null && !configDescriptions.isEmpty()) { for (ConfigDescriptionParameter parameter : configDescriptions) { int[] columnWidths = new int[] { COLUMN_CONFIG_PARAMETER, COLUMN_CONFIG_PARAMETER_PROP, COLUMN_CONFIG_PARAMETER_PROP_VALUE }; configParamContent.add(Utils.getColumn(COLUMN_PROPERTY_VALUE, parameter.getName() + " : ")); List<String> configParamProperty = new ArrayList<String>(); configParamProperty.add(""); configParamProperty.add(TYPE); configParamProperty.add(parameter.getType().toString()); configParamContent.add(Utils.getRow(columnWidths, configParamProperty)); if (parameter.getLabel() != null) { configParamProperty.set(1, LABEL); configParamProperty.set(2, parameter.getLabel()); configParamContent.add(Utils.getRow(columnWidths, configParamProperty)); } if (parameter.getDescription() != null) { configParamProperty.set(1, DESCRIPTION); configParamProperty.set(2, parameter.getDescription()); configParamContent.add(Utils.getRow(columnWidths, configParamProperty)); } if (parameter.getDefault() != null) { configParamProperty.set(1, DEFAULT); configParamProperty.set(2, parameter.getDefault()); configParamContent.add(Utils.getRow(columnWidths, configParamProperty)); } if (parameter.getContext() != null) { configParamProperty.set(1, CONTEXT); configParamProperty.set(2, parameter.getContext()); configParamContent.add(Utils.getRow(columnWidths, configParamProperty)); } if (parameter.getPattern() != null) { configParamProperty.set(1, PATTERN); configParamProperty.set(2, parameter.getPattern()); configParamContent.add(Utils.getRow(columnWidths, configParamProperty)); } if (parameter.getStepSize() != null) { configParamProperty.set(1, STEP_SIZE); configParamProperty.set(2, parameter.getStepSize().toString()); configParamContent.add(Utils.getRow(columnWidths, configParamProperty)); } if (parameter.getMinimum() != null) { configParamProperty.set(1, MIN); configParamProperty.set(2, parameter.getMinimum().toString()); configParamContent.add(Utils.getRow(columnWidths, configParamProperty)); } if (parameter.getMaximum() != null) { configParamProperty.set(1, MAX); configParamProperty.set(2, parameter.getMaximum().toString()); configParamContent.add(Utils.getRow(columnWidths, configParamProperty)); } columnWidths = new int[] { COLUMN_CONFIG_PARAMETER_PROP, COLUMN_CONFIG_PARAMETER_PROP_VALUE }; List<String> options = collectRecords(columnWidths, OPTIONS, parameter.getOptions()); for (String option : options) { configParamContent.add(Utils.getColumn(COLUMN_CONFIG_PARAMETER, "") + option); } List<String> filters = collectRecords(columnWidths, FILTER_CRITERIA, parameter.getFilterCriteria()); for (String filter : filters) { configParamContent.add(Utils.getColumn(COLUMN_CONFIG_PARAMETER, "") + filter); } configParamContent .add(Utils.getColumn(COLUMN_PROPERTY_VALUE, Utils.printChars('-', COLUMN_PROPERTY_VALUE))); } } return configParamContent; } /** * This method is responsible for printing the set of {@link Input}s or {@link Output}s or {@link Inputs}s. * * @param set is the set of {@link Input}s or {@link Output}s or {@link Inputs}s for printing. * @return a formated string, representing the set of {@link Input}s or {@link Output}s or {@link Input}s. */ private static String getTagsRecord(Set<String> tags) { if (tags == null || tags.size() == 0) { return "[ ]"; } StringBuilder res = new StringBuilder().append("[ "); int i = 1; for (String tag : tags) { if (i < tags.size()) { res.append(tag + ", "); } else { res.append(tag); } i++; } return res.append(" ]").toString(); } /** * This method is responsible for constructing the rows of a table with 2 columns - first column is for the * numbering, second column is for the numbered records. * * @param list is the list with row values for printing. * @param rows is used for accumulation of result * @param columnWidths represents the column widths of the table. */ private static void collectListRecords(Map<String, String> list, List<String> rows, int[] columnWidths) { for (int i = 1; i <= list.size(); i++) { String id = new Integer(i).toString(); String uid = list.get(id); List<String> columnValues = new ArrayList<String>(); columnValues.add(id); columnValues.add(uid); rows.add(Utils.getRow(columnWidths, columnValues)); } } }