/** * Copyright (c) 1997, 2015 by ProSyst Software GmbH and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package org.eclipse.smarthome.automation.internal.commands; import java.util.ArrayList; import java.util.Collection; import java.util.Hashtable; import java.util.Iterator; import java.util.Locale; import java.util.Map; 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.ModuleType; /** * This class provides common functionality of commands: * <ul> * <li>{@link AutomationCommands#LIST_MODULE_TYPES} * <li>{@link AutomationCommands#LIST_TEMPLATES} * <li>{@link AutomationCommands#LIST_RULES} * </ul> * * @author Ana Dimova - Initial Contribution * */ public class AutomationCommandList extends AutomationCommand { /** * This field serves to keep the UID of a {@link Rule}, {@link Template} or {@link ModuleType}, or part of it, or * sequence number of a {@link Rule}, {@link Template}, or {@link ModuleType} in the list. */ private String id; /** * This field is used to search for templates or types of modules, which have been translated to the language from * the locale. If the parameter <b>locale</b> is not passed to the command line then the default locale will be * used. */ private Locale locale; /** * @see AutomationCommand#AutomationCommand(String, String[], int, AutomationCommandsPluggable) */ public AutomationCommandList(String command, String[] params, int adminType, AutomationCommandsPluggable autoCommands) { super(command, params, adminType, autoCommands); if (locale == null) { locale = Locale.getDefault(); } } /** * This method is responsible for execution of commands: * <ul> * <li>{@link AutomationCommands#LIST_MODULE_TYPES} * <li>{@link AutomationCommands#LIST_TEMPLATES} * <li>{@link AutomationCommands#LIST_RULES} * </ul> */ @Override public String execute() { if (parsingResult != SUCCESS) { return parsingResult; } if (providerType == AutomationCommands.MODULE_TYPE_PROVIDER) { return listModuleTypes(); } if (providerType == AutomationCommands.TEMPLATE_PROVIDER) { return listTemplates(); } if (providerType == AutomationCommands.RULE_PROVIDER) { return listRules(); } return FAIL; } /** * This method is invoked from the constructor to parse all parameters and options of the command <b>LIST</b>. * If there are redundant parameters or options the result will be the failure of the command. This command has: * <ul> * <b>Options:</b> * <ul> * <li><b>PrintStackTrace</b> is common for all commands and its presence triggers printing of stack trace in case * of exception. * </ul> * </ul> * <ul> * <b>Parameters:</b> * <ul> * <li><b>id</b> is optional and its presence triggers printing of details on specified automation object. * <li><b>locale</b> is optional and it triggers printing of localized details on specified automation object. Its * value is interpreted as <b>language</b> or <b>language tag</b>. If missing - the default locale will be used. * </ul> * </ul> */ @Override protected String parseOptionsAndParameters(String[] parameterValues) { boolean getId = true; boolean getLocale = true; for (int i = 0; i < parameterValues.length; i++) { if (null == parameterValues[i]) { continue; } if (parameterValues[i].charAt(0) == '-') { if (parameterValues[i].equals(OPTION_ST)) { st = true; continue; } return String.format("Unsupported option: %s", parameterValues[i]); } if (getId) { id = parameterValues[i]; getId = false; continue; } if (getLocale) { String l = parameterValues[i]; locale = new Locale(l); getLocale = false; } if (getId && getLocale) { return String.format("Unsupported parameter: %s", parameterValues[i]); } } return SUCCESS; } /** * This method is responsible for execution of command {@link AutomationCommands#LIST_RULES}. * * @return a string representing understandable for the user message containing information on the outcome of the * command {@link AutomationCommands#LIST_RULES}. */ private String listRules() { Collection<Rule> collection = autoCommands.getRules(); Map<String, Rule> rules = new Hashtable<String, Rule>(); Map<String, String> listRules = null; if (collection != null && !collection.isEmpty()) { addCollection(collection, rules); String[] uids = new String[rules.size()]; Utils.quickSort(rules.keySet().toArray(uids), 0, rules.size()); listRules = Utils.putInHastable(uids); } if (listRules != null && !listRules.isEmpty()) { if (id != null) { collection = getRuleByFilter(listRules); if (collection.size() == 1) { Rule r = (Rule) collection.toArray()[0]; if (r != null) { RuleStatus status = autoCommands.getRuleStatus(r.getUID()); return Printer.printRule(r, status); } else { return String.format("Nonexistent ID: %s", id); } } else if (collection.isEmpty()) { return String.format("Nonexistent ID: %s", id); } else { if (!rules.isEmpty()) { rules.clear(); } addCollection(collection, rules); listRules = Utils.filterList(rules, listRules); } } return Printer.printRules(autoCommands, listRules); } return "There are no Rules available!"; } /** * This method is responsible for execution of command {@link AutomationCommands#LIST_TEMPLATES}. * * @return a string representing understandable for the user message containing information on the outcome of the * command {@link AutomationCommands#LIST_TEMPLATES}. */ private String listTemplates() { Collection<RuleTemplate> collection = autoCommands.getTemplates(locale); Map<String, Template> templates = new Hashtable<String, Template>(); Map<String, String> listTemplates = null; if (collection != null && !collection.isEmpty()) { addCollection(collection, templates); String[] uids = new String[templates.size()]; Utils.quickSort(templates.keySet().toArray(uids), 0, templates.size()); listTemplates = Utils.putInHastable(uids); } if (listTemplates != null && !listTemplates.isEmpty()) { if (id != null) { collection = getTemplateByFilter(listTemplates); if (collection.size() == 1) { Template t = (Template) collection.toArray()[0]; if (t != null) { return Printer.printTemplate(t); } else { return String.format("Nonexistent ID: %s", id); } } else if (collection.isEmpty()) { return String.format("Nonexistent ID: %s", id); } else { if (!templates.isEmpty()) { templates.clear(); } addCollection(collection, templates); listTemplates = Utils.filterList(templates, listTemplates); } } if (listTemplates != null && !listTemplates.isEmpty()) { return Printer.printTemplates(listTemplates); } } return "There are no Templates available!"; } /** * This method is responsible for execution of command {@link AutomationCommands#LIST_MODULE_TYPES}. * * @return a string representing understandable for the user message containing information on the outcome of the * command {@link AutomationCommands#LIST_MODULE_TYPES}. */ private String listModuleTypes() { Map<String, ModuleType> moduleTypes = new Hashtable<String, ModuleType>(); Collection<? extends ModuleType> collection = autoCommands.getTriggers(locale); addCollection(collection, moduleTypes); collection = autoCommands.getConditions(locale); addCollection(collection, moduleTypes); collection = autoCommands.getActions(locale); addCollection(collection, moduleTypes); Map<String, String> listModuleTypes = null; if (!moduleTypes.isEmpty()) { String[] uids = new String[moduleTypes.size()]; Utils.quickSort(moduleTypes.keySet().toArray(uids), 0, moduleTypes.size()); listModuleTypes = Utils.putInHastable(uids); } if (listModuleTypes != null && !listModuleTypes.isEmpty()) { if (id != null) { collection = getModuleTypeByFilter(listModuleTypes); if (collection.size() == 1) { ModuleType mt = (ModuleType) collection.toArray()[0]; if (mt != null) { return Printer.printModuleType(mt); } else { return String.format("Nonexistent ID: %s", id); } } else if (collection.isEmpty()) { return String.format("Nonexistent ID: %s", id); } else { if (!moduleTypes.isEmpty()) { moduleTypes.clear(); } addCollection(collection, moduleTypes); listModuleTypes = Utils.filterList(moduleTypes, listModuleTypes); } } return Printer.printModuleTypes(listModuleTypes); } return "There are no Module Types available!"; } /** * This method reduces the list of {@link Rule}s so that their unique identifier or part of it to match the * {@link #id} or * the index in the <tt>list</tt> to match the {@link #id}. * * @param list is the list of {@link Rule}s for reducing. * @return a collection of {@link Rule}s that match the filter. */ private Collection<Rule> getRuleByFilter(Map<String, String> list) { Collection<Rule> rules = new ArrayList<Rule>(); if (!list.isEmpty()) { Rule r = null; String uid = list.get(id); if (uid != null) { r = autoCommands.getRule(uid); if (r != null) { rules.add(r); return rules; } } else { r = autoCommands.getRule(id); if (r != null) { rules.add(r); return rules; } else { for (String ruleUID : list.values()) { if (ruleUID.indexOf(id) > -1) { rules.add(autoCommands.getRule(ruleUID)); } } } } } return rules; } /** * This method reduces the list of {@link Template}s so that their unique identifier or part of it to match the * {@link #id} or * the index in the <tt>list</tt> to match the {@link #id}. * * @param list is the list of {@link Template}s for reducing. * @return a collection of {@link Template}s that match the filter. */ private Collection<RuleTemplate> getTemplateByFilter(Map<String, String> list) { Collection<RuleTemplate> templates = new ArrayList<RuleTemplate>(); RuleTemplate t = null; String uid = list.get(id); if (uid != null) { t = autoCommands.getTemplate(uid, locale); if (t != null) { templates.add(t); return templates; } } else { t = autoCommands.getTemplate(id, locale); if (t != null) { templates.add(t); return templates; } else { for (String templateUID : list.keySet()) { if (templateUID.indexOf(id) != -1) { templates.add(autoCommands.getTemplate(templateUID, locale)); } } } } return templates; } /** * This method reduces the list of {@link ModuleType}s so that their unique identifier or part of it to match the * {@link #id} or * the index in the <tt>list</tt> to match the {@link #id}. * * @param list is the list of {@link ModuleType}s for reducing. * @return a collection of {@link ModuleType}s that match the filter. */ private Collection<ModuleType> getModuleTypeByFilter(Map<String, String> list) { Collection<ModuleType> moduleTypes = new ArrayList<ModuleType>(); if (!list.isEmpty()) { ModuleType mt = null; String uid = list.get(id); if (uid != null) { mt = autoCommands.getModuleType(uid, locale); if (mt != null) { moduleTypes.add(mt); return moduleTypes; } } else { mt = autoCommands.getModuleType(id, locale); if (mt != null) { moduleTypes.add(mt); return moduleTypes; } else { for (String typeUID : list.values()) { if (typeUID.indexOf(id) != -1) { moduleTypes.add(autoCommands.getModuleType(typeUID, locale)); } } } } } return moduleTypes; } /** * This method converts a {@link Collection} of {@link Rule}s, {@link Template}s or {@link ModuleType}s to a * {@link Hashtable} with keys - the UID of the object and values - the object. * * @param collection is the {@link Collection} of {@link Rule}s, {@link Template}s or {@link ModuleType}s which * must be converted. * @param list is the map with keys - the UID of the object and values - the object, which must be * filled with the objects from <tt>collection</tt>. */ @SuppressWarnings({ "rawtypes", "unchecked" }) private void addCollection(Collection collection, Map list) { if (collection != null && !collection.isEmpty()) { Iterator i = collection.iterator(); while (i.hasNext()) { Object element = i.next(); if (element instanceof ModuleType) { list.put(((ModuleType) element).getUID(), element); } if (element instanceof RuleTemplate) { list.put(((RuleTemplate) element).getUID(), element); } if (element instanceof Rule) { list.put(((Rule) element).getUID(), element); } } } } }