@Override
  public Map.Entry<RdfCloudTripleStoreConstants.TABLE_LAYOUT, ByteRange> defineRange(
      RyaURI subject,
      RyaURI predicate,
      RyaType object,
      RyaURI context,
      RdfCloudTripleStoreConfiguration conf)
      throws IOException {
    try {
      // po(ng)
      // po_r(s)(ng)
      // p(ng)
      // p_r(o)(ng)
      // r(p)(ng)
      if (!handles(subject, predicate, object, context)) return null;

      RyaContext ryaContext = RyaContext.getInstance();
      MessageDigest md = MessageDigest.getInstance("MD5");

      RdfCloudTripleStoreConstants.TABLE_LAYOUT table_layout =
          RdfCloudTripleStoreConstants.TABLE_LAYOUT.PO;
      byte[] start, stop;
      if (object != null) {
        if (object instanceof RyaRange) {
          // p_r(o)
          RyaRange rv = (RyaRange) object;
          rv = ryaContext.transformRange(rv);
          byte[] objStartBytes = ryaContext.serializeType(rv.getStart())[0];
          byte[] objEndBytes = ryaContext.serializeType(rv.getStop())[0];
          byte[] predBytes = predicate.getData().getBytes();
          byte[] predHash = md.digest(predBytes);
          start = Bytes.concat(predHash, DELIM_BYTES, predBytes, DELIM_BYTES, objStartBytes);
          stop =
              Bytes.concat(
                  predHash,
                  DELIM_BYTES,
                  predBytes,
                  DELIM_BYTES,
                  objEndBytes,
                  DELIM_BYTES,
                  LAST_BYTES);
        } else {
          if (subject != null && subject instanceof RyaRange) {
            // po_r(s)
            RyaRange ru = (RyaRange) subject;
            ru = ryaContext.transformRange(ru);
            byte[] subjStartBytes = ru.getStart().getData().getBytes();
            byte[] subjStopBytes = ru.getStop().getData().getBytes();
            byte[] predBytes = predicate.getData().getBytes();
            byte[] predHash = md.digest(predBytes);
            byte[] objBytes = ryaContext.serializeType(object)[0];
            start =
                Bytes.concat(
                    predHash,
                    DELIM_BYTES,
                    predBytes,
                    DELIM_BYTES,
                    objBytes,
                    DELIM_BYTES,
                    subjStartBytes);
            stop =
                Bytes.concat(
                    predHash,
                    DELIM_BYTES,
                    predBytes,
                    DELIM_BYTES,
                    objBytes,
                    DELIM_BYTES,
                    subjStopBytes,
                    TYPE_DELIM_BYTES,
                    LAST_BYTES);
          } else {
            // po
            // TODO: There must be a better way than creating multiple byte[]
            byte[] predBytes = predicate.getData().getBytes();
            byte[] predHash = md.digest(predBytes);
            byte[] objBytes = ryaContext.serializeType(object)[0];
            start =
                Bytes.concat(predHash, DELIM_BYTES, predBytes, DELIM_BYTES, objBytes, DELIM_BYTES);
            stop = Bytes.concat(start, LAST_BYTES);
          }
        }
      } else {
        // p
        byte[] predBytes = predicate.getData().getBytes();
        byte[] predHash = md.digest(predBytes);
        start = Bytes.concat(predHash, DELIM_BYTES, predBytes, DELIM_BYTES);
        stop = Bytes.concat(start, LAST_BYTES);
      }
      return new RdfCloudTripleStoreUtils.CustomEntry<
          RdfCloudTripleStoreConstants.TABLE_LAYOUT, ByteRange>(
          table_layout, new ByteRange(start, stop));
    } catch (RyaTypeResolverException e) {
      throw new IOException(e);
    } catch (NoSuchAlgorithmException e) {
      throw new IOException(e);
    }
  }