Package org.openhab.io.transport.cul

Source Code of org.openhab.io.transport.cul.CULManager

/**
* Copyright (c) 2010-2014, 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.io.transport.cul;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.openhab.io.transport.cul.internal.CULHandlerInternal;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
* This class handles all CULHandler. You can only obtain CULHandlers via this
* manager.
*
* @author Till Klocke
* @since 1.4.0
*/
public class CULManager {

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

  private static Map<String, CULHandler> openDevices = new HashMap<String, CULHandler>();

  private static Map<String, Class<? extends CULHandler>> deviceTypeClasses = new HashMap<String, Class<? extends CULHandler>>();
 

  /**
   * Get CULHandler for the given device in the given mode. The same
   * CULHandler can be returned multiple times if you ask multiple times for
   * the same device in the same mode. It is not possible to obtain a
   * CULHandler of an already openend device for another RF mode.
   *
   * @param deviceName
   *            String representing the device. Currently only serial ports
   *            are supported.
   * @param mode
   *            The RF mode for which the device will be configured.
   * @return A CULHandler to communicate with the culfw based device.
   * @throws CULDeviceException
   */
  public static CULHandler getOpenCULHandler(String deviceName, CULMode mode) throws CULDeviceException {
    return getOpenCULHandler(deviceName, mode, null);
  }
 
  /**
   * Get CULHandler for the given device in the given mode. The same
   * CULHandler can be returned multiple times if you ask multiple times for
   * the same device in the same mode. It is not possible to obtain a
   * CULHandler of an already openend device for another RF mode.
   *
   * @param deviceName
   *            String representing the device. Currently only serial ports
   *            are supported.
   * @param mode
   *            The RF mode for which the device will be configured.
   * @param properties
   *            Map of properties, do configure a specific CUL Handler Implementation.
   *            For details please reference the Handler it self.
   * @return A CULHandler to communicate with the culfw based device.
   * @throws CULDeviceException
   */
  public static CULHandler getOpenCULHandler(String deviceName, CULMode mode, Map<String, ?> properties) throws CULDeviceException {
    logger.debug("Trying to open device " + deviceName + " in mode " + mode.toString());
    synchronized (openDevices) {

      if (openDevices.containsKey(deviceName)) {
        CULHandler handler = openDevices.get(deviceName);
        if (handler.getCULMode() == mode) {
          logger.debug("Device " + deviceName + " is already open in mode " + mode.toString()
              + ", returning already openend handler");
          return handler;
        } else {
          throw new CULDeviceException("The device " + deviceName + " is already open in mode "
              + mode.toString());
        }
      }
      CULHandler handler = createNewHandler(deviceName, mode, properties);
      openDevices.put(deviceName, handler);
      return handler;
    }
  }

  private static String getPrefix(String deviceName) {
    int index = deviceName.indexOf(':');
    return deviceName.substring(0, index);
  }

  private static String getRawDeviceName(String deviceName) {
    int index = deviceName.indexOf(':');
    return deviceName.substring(index + 1);
  }

  /**
   * Return a CULHandler to the manager. The CULHandler will only be closed if
   * there aren't any listeners registered with it. So it is save to call this
   * methods as soon as you don't need the CULHandler any more.
   *
   * @param handler
   */
  public static void close(CULHandler handler) {
    synchronized (openDevices) {

      if (handler instanceof CULHandlerInternal) {
        CULHandlerInternal internalHandler = (CULHandlerInternal) handler;
        if (!internalHandler.hasListeners()) {
          openDevices.remove(handler);
          try {
            handler.send("X00");
          } catch (CULCommunicationException e) {
            logger.warn("Couldn't reset rf mode to X00");
          }
          internalHandler.close();
        } else {
          logger.warn("Can't close device because it still has listeners");
        }
      }
    }
  }

  public static void registerHandlerClass(String deviceType, Class<? extends CULHandler> clazz) {
    logger.debug("Registering class " + clazz.getCanonicalName() + " for device type " + deviceType);
    deviceTypeClasses.put(deviceType, clazz);
  }

  private static CULHandler createNewHandler(String deviceName, CULMode mode, Map<String, ?> properties) throws CULDeviceException {
    String deviceType = getPrefix(deviceName);
    String deviceAddress = getRawDeviceName(deviceName);
    logger.debug("Searching class for device type " + deviceType);
    Class<? extends CULHandler> culHandlerclass = deviceTypeClasses.get(deviceType);
    if (culHandlerclass == null) {
      throw new CULDeviceException("No class for the device type " + deviceType + " is registred");
    }
   
    Class<?>[] constructorParametersTypes = { String.class, CULMode.class };
    Object[] parameters = { deviceAddress, mode };
   
    if(properties != null){
      constructorParametersTypes = Arrays.copyOf(constructorParametersTypes, constructorParametersTypes.length + 1);
      constructorParametersTypes[constructorParametersTypes.length -1] = Map.class;
     
      parameters = Arrays.copyOf(parameters, parameters.length + 1);
      parameters[parameters.length -1] = properties;
    }
   
    try {
      Constructor<? extends CULHandler> culHanlderConstructor = culHandlerclass
          .getConstructor(constructorParametersTypes);
     
      CULHandler culHandler = culHanlderConstructor.newInstance(parameters);
      List<String> initCommands = mode.getCommands();
      if (!(culHandler instanceof CULHandlerInternal)) {
        logger.error("Class " + culHandlerclass.getCanonicalName()
            + " does not implement the internal interface");
        throw new CULDeviceException("This CULHandler class does not implement the internal interface: "
            + culHandlerclass.getCanonicalName());
      }
      CULHandlerInternal internalHandler = (CULHandlerInternal) culHandler;
      internalHandler.open();
      for (String command : initCommands) {
        internalHandler.sendWithoutCheck(command);
      }
      return culHandler;
    } catch (SecurityException e1) {
      throw new CULDeviceException("Not allowed to access the constructor ", e1);
    } catch (NoSuchMethodException e1) {
      throw new CULDeviceException("Can't find the constructor to build the CULHandler", e1);
    } catch (IllegalArgumentException e) {
      throw new CULDeviceException("Invalid arguments for constructor. Device name: " + deviceAddress
          + " CULMode " + mode, e);
    } catch (InstantiationException e) {
      throw new CULDeviceException("Can't instantiate CULHandler object", e);
    } catch (IllegalAccessException e) {
      throw new CULDeviceException("Can't instantiate CULHandler object", e);
    } catch (InvocationTargetException e) {
      throw new CULDeviceException("Can't instantiate CULHandler object", e);
    } catch (CULCommunicationException e) {
      throw new CULDeviceException("Can't initialise RF mode", e);
    }
  }
}
TOP

Related Classes of org.openhab.io.transport.cul.CULManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.