org.openhab.binding.plugwise.internal.PlugwiseGenericBindingProvider.java Source code

Java tutorial

Introduction

Here is the source code for org.openhab.binding.plugwise.internal.PlugwiseGenericBindingProvider.java

Source

/**
 * Copyright (c) 2010-2015, openHAB.org 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.openhab.binding.plugwise.internal;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;
import org.openhab.binding.plugwise.PlugwiseBindingProvider;
import org.openhab.binding.plugwise.PlugwiseCommandType;
import org.openhab.core.binding.BindingConfig;
import org.openhab.core.items.Item;
import org.openhab.core.library.items.DateTimeItem;
import org.openhab.core.library.items.NumberItem;
import org.openhab.core.library.items.StringItem;
import org.openhab.core.library.items.SwitchItem;
import org.openhab.core.types.Command;
import org.openhab.core.types.TypeParser;
import org.openhab.model.item.binding.AbstractGenericBindingProvider;
import org.openhab.model.item.binding.BindingConfigParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Implementation class of the Plugwise Binding Provider
 *
 * @author Karel Goderis
 * @since 1.1.0
 */
public class PlugwiseGenericBindingProvider extends AbstractGenericBindingProvider
        implements PlugwiseBindingProvider {

    static final Logger logger = LoggerFactory.getLogger(PlugwiseGenericBindingProvider.class);

    static int counter = 0;

    /** {@link Pattern} which matches a binding configuration part */
    private static final Pattern ACTION_CONFIG_PATTERN = Pattern.compile("\\[(.*):(.*):(.*):(.*)\\]");
    private static final Pattern STATUS_CONFIG_PATTERN = Pattern.compile("\\[(.*):(.*):(.*)\\]");

    @Override
    public String getBindingType() {
        return "plugwise";
    }

    @Override
    public void validateItemType(Item item, String bindingConfig) throws BindingConfigParseException {
        if (!(item instanceof SwitchItem || item instanceof NumberItem || item instanceof StringItem
                || item instanceof DateTimeItem)) {
            throw new BindingConfigParseException("item '" + item.getName() + "' is of type '"
                    + item.getClass().getSimpleName()
                    + "', only Switch-, String and NumberItems are allowed - please check your *.items configuration");
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void processBindingConfiguration(String context, Item item, String bindingConfig)
            throws BindingConfigParseException {
        super.processBindingConfiguration(context, item, bindingConfig);

        if (bindingConfig != null) {
            parseAndAddBindingConfig(item, bindingConfig);
        } else {
            logger.warn(getBindingType() + " bindingConfig is NULL (item=" + item
                    + ") -> processing bindingConfig aborted!");
        }
    }

    private void parseAndAddBindingConfig(Item item, String bindingConfigs) throws BindingConfigParseException {

        String bindingConfig = StringUtils.substringBefore(bindingConfigs, ",");
        String bindingConfigTail = StringUtils.substringAfter(bindingConfigs, ",");

        PlugwiseBindingConfig newConfig = new PlugwiseBindingConfig();
        parseBindingConfig(newConfig, item, bindingConfig);
        addBindingConfig(item, newConfig);

        while (StringUtils.isNotBlank(bindingConfigTail)) {
            bindingConfig = StringUtils.substringBefore(bindingConfigTail, ",");
            bindingConfig = StringUtils.strip(bindingConfig);
            bindingConfigTail = StringUtils.substringAfter(bindingConfig, ",");
            parseBindingConfig(newConfig, item, bindingConfig);
            addBindingConfig(item, newConfig);
        }

    }

    /**
     * Parses the configuration string and update the provided config
     * 
     * @param config
     * @param item
     * @param bindingConfig
     * @throws BindingConfigParseException
     */
    private void parseBindingConfig(PlugwiseBindingConfig config, Item item, String bindingConfig)
            throws BindingConfigParseException {

        String commandAsString = null;
        String plugwiseID = null;
        String plugwiseCommand = null;
        int interval = 60;

        if (bindingConfig != null) {

            Matcher actionMatcher = ACTION_CONFIG_PATTERN.matcher(bindingConfig);
            Matcher statusMatcher = STATUS_CONFIG_PATTERN.matcher(bindingConfig);

            if (!actionMatcher.matches() && !statusMatcher.matches()) {
                throw new BindingConfigParseException(
                        "Plugwise binding configuration must consist of either three [config=" + statusMatcher
                                + "] or four parts [config=" + actionMatcher + "]");
            } else {
                if (actionMatcher.matches()) {
                    commandAsString = actionMatcher.group(1);
                    plugwiseID = actionMatcher.group(2);
                    plugwiseCommand = actionMatcher.group(3);
                    interval = Integer.valueOf(actionMatcher.group(4));
                } else if (statusMatcher.matches()) {
                    commandAsString = null;
                    plugwiseID = statusMatcher.group(1);
                    plugwiseCommand = statusMatcher.group(2);
                    interval = Integer.valueOf(statusMatcher.group(3));
                }

                PlugwiseCommandType type = PlugwiseCommandType.getCommandType(plugwiseCommand);

                if (PlugwiseCommandType.validateBinding(type, item)) {

                    PlugwiseBindingConfigElement newElement = new PlugwiseBindingConfigElement(plugwiseID, type,
                            interval);

                    Command command = null;
                    if (commandAsString == null) {
                        // for those configuration strings that are not really linked to a openHAB command we
                        // create a dummy Command to be able to store the configuration information
                        // I have choosen to do that with NumberItems
                        NumberItem dummy = new NumberItem(Integer.toString(counter));
                        command = createCommandFromString(dummy, Integer.toString(counter));
                        counter++;
                        config.put(command, newElement);
                    } else {
                        command = createCommandFromString(item, commandAsString);
                        config.put(command, newElement);
                    }
                } else {
                    String validItemType = PlugwiseCommandType.getValidItemTypes(plugwiseCommand);
                    if (StringUtils.isEmpty(validItemType)) {
                        throw new BindingConfigParseException("'" + bindingConfig + "' is no valid binding type");
                    } else {
                        throw new BindingConfigParseException("'" + bindingConfig
                                + "' is not bound to a valid item type. Valid item type(s): " + validItemType);
                    }
                }
            }
        } else {
            return;
        }
    }

    /**
     * Creates a {@link Command} out of the given <code>commandAsString</code>
     * incorporating the {@link TypeParser}.
     *  
     * @param item
     * @param commandAsString
     * 
     * @return an appropriate Command (see {@link TypeParser} for more 
     * information
     * 
     * @throws BindingConfigParseException if the {@link TypeParser} couldn't
     * create a command appropriately
     * 
     * @see {@link TypeParser}
     */
    private Command createCommandFromString(Item item, String commandAsString) throws BindingConfigParseException {

        Command command = TypeParser.parseCommand(item.getAcceptedCommandTypes(), commandAsString);

        if (command == null) {
            throw new BindingConfigParseException("couldn't create Command from '" + commandAsString + "' ");
        }

        return command;
    }

    /**
     * This is an internal data structure to map commands to 
     * {@link ProtocolBindingConfigElement }. There will be map like 
     * <code>ON->ProtocolBindingConfigElement</code>
     */
    static class PlugwiseBindingConfig extends HashMap<Command, PlugwiseBindingConfigElement>
            implements BindingConfig {

        private static final long serialVersionUID = -7252828812548386063L;
    }

    public static class PlugwiseBindingConfigElement implements BindingConfig {

        final private String id;
        final private int interval;
        final private PlugwiseCommandType type;

        public String getId() {
            return id;
        }

        public int getInterval() {
            return interval;
        }

        public PlugwiseCommandType getCommandType() {
            return type;
        }

        public PlugwiseBindingConfigElement(String id, PlugwiseCommandType type, int interval) {
            this.id = id;
            this.type = type;
            this.interval = interval;
        }

        @Override
        public String toString() {
            return "PlugwiseBindingConfigElement [id=" + id + ", type=" + type.toString() + ", interval=" + interval
                    + "]";
        }

    }

    @Override
    public Boolean autoUpdate(String itemName) {
        return false;
    }

    @Override
    public String getPlugwiseID(String itemName, Command someCommand) {
        if (itemName != null && someCommand != null) {
            PlugwiseBindingConfig aConfig = (PlugwiseBindingConfig) bindingConfigs.get(itemName);
            if (aConfig != null) {
                PlugwiseBindingConfigElement element = aConfig.get(someCommand);
                if (element != null) {
                    return element.getId();
                }
            }
        }
        return null;
    }

    @Override
    public PlugwiseCommandType getPlugwiseCommandType(String itemName, Command someCommand) {
        if (itemName != null && someCommand != null) {
            PlugwiseBindingConfig aConfig = (PlugwiseBindingConfig) bindingConfigs.get(itemName);
            if (aConfig != null) {
                PlugwiseBindingConfigElement element = aConfig.get(someCommand);
                if (element != null) {
                    return element.getCommandType();
                }
            }
        }
        return null;
    }

    @Override
    public List<String> getPlugwiseID(String itemName) {
        List<String> ids = new ArrayList<String>();
        for (String anItem : bindingConfigs.keySet()) {
            PlugwiseBindingConfig aConfig = (PlugwiseBindingConfig) bindingConfigs.get(anItem);
            for (Command aCommand : aConfig.keySet()) {
                PlugwiseBindingConfigElement element = aConfig.get(aCommand);
                if (element != null) {
                    ids.add(element.getId());
                }
            }
        }
        return ids;
    }

    @Override
    public Set<String> getItemNames(String PlugwiseID, PlugwiseCommandType type) {

        Set<String> result = new HashSet<String>();

        Collection<String> items = getItemNames();

        Iterator<String> itemIterator = items.iterator();
        while (itemIterator.hasNext()) {
            String anItem = itemIterator.next();

            PlugwiseBindingConfig pbConfig = (PlugwiseBindingConfig) bindingConfigs.get(anItem);
            for (Command command : pbConfig.keySet()) {
                PlugwiseBindingConfigElement element = pbConfig.get(command);

                if (element.getCommandType() == type && element.getId().equals(PlugwiseID)) {
                    if (!result.contains(anItem)) {
                        result.add(anItem);
                    }
                }

            }

        }
        return result;
    }

    @Override
    public List<PlugwiseBindingConfigElement> getIntervalList() {

        List<PlugwiseBindingConfigElement> result = new ArrayList<PlugwiseBindingConfigElement>();

        Collection<String> items = getItemNames();

        Iterator<String> itemIterator = items.iterator();
        while (itemIterator.hasNext()) {
            String anItem = itemIterator.next();

            PlugwiseBindingConfig pbConfig = (PlugwiseBindingConfig) bindingConfigs.get(anItem);
            for (Command command : pbConfig.keySet()) {
                boolean found = false;
                PlugwiseBindingConfigElement element = pbConfig.get(command);

                // check if we already have a reference to this {ID,command}
                Iterator<PlugwiseBindingConfigElement> elementIterator = result.iterator();
                while (elementIterator.hasNext()) {
                    PlugwiseBindingConfigElement resultElement = elementIterator.next();
                    if (resultElement.getId().equals(element.getId()) && resultElement.getCommandType()
                            .getJobClass().equals(element.getCommandType().getJobClass())) {
                        // bingo - now check if the interval is smaller
                        found = true;
                        if (resultElement.getInterval() > element.getInterval()) {
                            result.remove(resultElement);
                            result.add(element);
                            break;
                        }
                    }
                }

                if (!found) {
                    result.add(element);
                }
            }
        }
        return result;
    }

    @Override
    public List<Command> getCommandsByType(String itemName, Class<? extends Command> class1) {
        List<Command> commands = new ArrayList<Command>();
        PlugwiseBindingConfig aConfig = (PlugwiseBindingConfig) bindingConfigs.get(itemName);
        for (Command aCommand : aConfig.keySet()) {
            PlugwiseBindingConfigElement element = aConfig.get(aCommand);
            if (element.getCommandType().getTypeClass().equals(class1)) {
                commands.add(aCommand);
            }
        }
        return commands;
    }

    @Override
    public List<Command> getAllCommands(String itemName) {
        List<Command> commands = new ArrayList<Command>();
        PlugwiseBindingConfig aConfig = (PlugwiseBindingConfig) bindingConfigs.get(itemName);
        for (Command aCommand : aConfig.keySet()) {
            commands.add(aCommand);
        }
        return commands;
    }

}