/**
   * Returns the command class that provides the best suitable converter to convert between the
   * Z-Wave API and the binding.
   *
   * @param item the {@link item} to resolve a converter for.
   * @param node the {@link ZWaveNode} node to resolve a Command class on.
   * @param the enpoint ID to use to resolve a converter.
   * @return the {@link ZWaveCommandClass} that can be used to get a converter suitable to do the
   *     conversion.
   */
  private ZWaveCommandClass resolveConverter(Item item, ZWaveNode node, int endpointId) {
    if (item == null) return null;

    ZWaveMultiInstanceCommandClass multiInstanceCommandClass = null;
    ZWaveCommandClass result = null;

    if (endpointId != 1)
      multiInstanceCommandClass =
          (ZWaveMultiInstanceCommandClass) node.getCommandClass(CommandClass.MULTI_INSTANCE);

    if (!preferredCommandClasses.containsKey(item.getClass())) {
      logger.warn(
          "No preferred command classes found for item class = {}", item.getClass().toString());
      return null;
    }

    for (CommandClass commandClass : preferredCommandClasses.get(item.getClass())) {
      if (multiInstanceCommandClass != null && multiInstanceCommandClass.getVersion() == 2) {
        ZWaveEndpoint endpoint = multiInstanceCommandClass.getEndpoint(endpointId);

        if (endpoint != null) {
          result = endpoint.getCommandClass(commandClass);
        }
      }

      if (result == null) result = node.getCommandClass(commandClass);

      if (result == null) continue;

      if (multiInstanceCommandClass != null
          && multiInstanceCommandClass.getVersion() == 1
          && result.getInstances() < endpointId) continue;

      if (converters.containsKey(commandClass)) return result;
    }

    logger.warn(
        "No matching command classes found for item class = {}, node id = {}, endpoint id = {}",
        item.getClass().toString(),
        node.getNodeId(),
        endpointId);
    return null;
  }