@Override
  protected ViewQuery create(Part part, Iterator<Object> objectIterator) {
    ConvertingIterator iterator = new ConvertingIterator(objectIterator, converter);

    switch (part.getType()) {
      case GREATER_THAN_EQUAL:
        startKey(iterator);
        break;
      case LESS_THAN_EQUAL:
        query.inclusiveEnd(true);
      case BEFORE:
      case LESS_THAN: // fall-through on purpose here
        endKey(iterator);
        break;
      case BETWEEN:
        startKey(iterator);
        endKey(iterator);
        break;
      case STARTING_WITH: // starting_with only supports String keys
        String nameStart = nextString(iterator);
        query.startKey(nameStart).endKey(nameStart + "\uefff");
        query.inclusiveEnd(false);
        break;
      case SIMPLE_PROPERTY:
        key(iterator);
        break;
      case IN:
        query.keys(in(iterator));
        break;
      default:
        throw new IllegalArgumentException(
            "Unsupported keyword in View query derivation: " + part.toString());
    }
    return query;
  }
  private void startKey(Iterator<Object> iterator) {
    if (!iterator.hasNext()) {
      throw new IllegalArgumentException("Not enough parameters for startKey");
    }

    Object next = iterator.next();
    if (next instanceof String) {
      query.startKey((String) next);
    } else if (next instanceof Boolean) {
      query.startKey((Boolean) next);
    } else if (next instanceof Double) {
      query.startKey((Double) next);
    } else if (next instanceof Integer) {
      query.startKey((Integer) next);
    } else if (next instanceof Long) {
      query.startKey((Long) next);
    } else if (next instanceof Collection) {
      // when creating a JsonArray, the from(List) method is preferred because it will convert
      // internal
      // Lists and Maps to JsonObject and JsonArray respectively
      List<Object> arrayContent = new ArrayList<Object>((Collection) next);
      query.startKey(JsonArray.from(arrayContent));
    } else if (next.getClass().isArray()) {
      List<Object> arrayContent = Arrays.asList((Object[]) next);
      query.startKey(JsonArray.from(arrayContent));
    } else if (next
        instanceof
        JsonArray) { // discouraged, since it's leaking store-specifics in the method signature
      query.startKey((JsonArray) next);
    } else if (next
        instanceof
        JsonObject) { // discouraged, since it's leaking store-specifics in the method signature
      query.startKey((JsonObject) next);
    } else {
      throw new IllegalArgumentException(
          "Unsupported parameter type for startKey: " + next.getClass());
    }
  }
  /**
   * Queries all documents of a view with an optional range parameter
   *
   * @param designDocName
   * @param viewName
   * @param startKey
   * @param endKey
   * @return
   */
  public static ViewResult query(
      String designDocName, String viewName, String startKey, String endKey) {
    ViewResult result;

    // Perform the query
    ViewQuery query = ViewQuery.from(designDocName, viewName).inclusiveEnd(true).stale(Stale.FALSE);

    if (startKey != null) {
      query = query.startKey(startKey);
    }

    if (endKey != null) {
      query = query.endKey(endKey);
    }

    result = client.query(query);

    return result;
  }