@SuppressWarnings("rawtypes")
  protected String buildRowSpec(final byte[] row, final Map familyMap, final long startTime,
    final long endTime, final int maxVersions) {
    StringBuilder sb = new StringBuilder();
    sb.append(pathPrefix);
    sb.append(Bytes.toString(name));
    sb.append('/');
    sb.append(toURLEncodedBytes(row));
    Set families = familyMap.entrySet();
    if (families != null) {
      Iterator i = familyMap.entrySet().iterator();
      sb.append('/');
      while (i.hasNext()) {
        Map.Entry e = (Map.Entry) i.next();
        Collection quals = (Collection) e.getValue();
        if (quals == null || quals.isEmpty()) {
          // this is an unqualified family. append the family name and NO ':'
          sb.append(toURLEncodedBytes((byte[]) e.getKey()));
        } else {
          Iterator ii = quals.iterator();
          while (ii.hasNext()) {
            sb.append(toURLEncodedBytes((byte[]) e.getKey()));
            Object o = ii.next();
            // Puts use byte[] but Deletes use KeyValue
            if (o instanceof byte[]) {
              sb.append(':');
              sb.append(toURLEncodedBytes((byte[]) o));
            } else if (o instanceof KeyValue) {
              if (((KeyValue) o).getQualifierLength() != 0) {
                sb.append(':');
                sb.append(toURLEncodedBytes(CellUtil.cloneQualifier((KeyValue) o)));
              }
            } else {
              throw new RuntimeException("object type not handled");
            }
            if (ii.hasNext()) {
              sb.append(',');
            }
          }
        }
        if (i.hasNext()) {
          sb.append(',');
        }
      }
    }
    if (startTime >= 0 && endTime != Long.MAX_VALUE) {
      sb.append('/');
      sb.append(startTime);
      if (startTime != endTime) {
        sb.append(',');
        sb.append(endTime);
      }
    } else if (endTime != Long.MAX_VALUE) {
      sb.append('/');
      sb.append(endTime);
    }
    if (maxVersions > 1) {
      sb.append("?v=");
      sb.append(maxVersions);
    }
    return sb.toString();
  }
HTable interface to remote tables accessed via REST gateway
hbase-rest/src/test/java/org/apache/hadoop/hbase/rest/client/RemoteHTable.java