// Retrieves the row from the table and check if it exists and has not been flagged as deleted
  protected Map<RecordId, Result> getRows(List<RecordId> recordIds, List<FieldType> fields)
      throws RecordException {
    Map<RecordId, Result> results = new HashMap<RecordId, Result>();

    try {
      List<Get> gets = new ArrayList<Get>();
      for (RecordId recordId : recordIds) {
        Get get = new Get(recordId.toBytes());
        // Add the columns for the fields to get
        addFieldsToGet(get, fields);
        get.setMaxVersions(1); // Only retrieve the most recent version of each field
        gets.add(get);
      }

      // Retrieve the data from the repository
      int i = 0;
      for (Result result : recordTable.get(gets)) {
        if (result == null || result.isEmpty()) {
          i++; // Skip this recordId (instead of throwing a RecordNotFoundException)
          continue;
        }
        // Check if the record was deleted
        byte[] deleted = recdec.getLatest(result, RecordCf.DATA.bytes, RecordColumn.DELETED.bytes);
        if ((deleted == null) || (Bytes.toBoolean(deleted))) {
          i++; // Skip this recordId (instead of throwing a RecordNotFoundException)
          continue;
        }
        results.put(recordIds.get(i++), result);
      }
    } catch (IOException e) {
      throw new RecordException(
          "Exception occurred while retrieving records '" + recordIds + "' from HBase table", e);
    }
    return results;
  }
  // Retrieves the row from the table and check if it exists and has not been flagged as deleted
  protected Result getRow(
      RecordId recordId, Long version, int numberOfVersions, List<FieldType> fields)
      throws RecordException {
    Result result;
    Get get = new Get(recordId.toBytes());
    get.setFilter(REAL_RECORDS_FILTER);

    try {
      // Add the columns for the fields to get
      addFieldsToGet(get, fields);

      if (version != null)
        get.setTimeRange(0, version + 1); // Only retrieve data within this timerange
      get.setMaxVersions(numberOfVersions);

      // Retrieve the data from the repository
      result = recordTable.get(get);

      if (result == null || result.isEmpty()) throw new RecordNotFoundException(recordId);

    } catch (IOException e) {
      throw new RecordException(
          "Exception occurred while retrieving record '" + recordId + "' from HBase table", e);
    }
    return result;
  }
 public SolrInputDocument build() throws InterruptedException, RepositoryException {
   solrDoc.setField("lily.id", recordId.toString());
   solrDoc.setField("lily.table", table);
   solrDoc.setField("lily.key", key);
   solrDoc.setField("lily.vtagId", vtag.toString());
   solrDoc.setField("lily.vtag", typeManager.getFieldTypeById(vtag).getName().getName());
   solrDoc.setField("lily.version", version);
   return solrDoc;
 }
  @Override
  public boolean softEquals(Object obj) {
    if (this == obj) {
      return true;
    }
    if (obj == null) {
      return false;
    }
    if (obj instanceof RecordRvtImpl) {
      return softEquals(((RecordRvtImpl) obj).getRecord());
    }
    if (obj instanceof IdRecordImpl) {
      return softEquals(((IdRecordImpl) obj).getRecord());
    }
    if (getClass() != obj.getClass()) {
      return false;
    }
    RecordImpl other = (RecordImpl) obj;

    if (fields == null) {
      if (other.fields != null) {
        return false;
      }
    } else if (!fields.equals(other.fields)) {
      return false;
    }

    if (fieldsToDelete == null) {
      if (other.fieldsToDelete != null) {
        return false;
      }
    } else if (!fieldsToDelete.equals(other.fieldsToDelete)) {
      return false;
    }

    if (id == null) {
      if (other.id != null) {
        return false;
      }
    } else if (!id.equals(other.id)) {
      return false;
    }

    QName nonVersionedRT1 = getRecordTypeName(Scope.NON_VERSIONED);
    QName nonVersionedRT2 = other.getRecordTypeName(Scope.NON_VERSIONED);

    if (nonVersionedRT1 != null
        && nonVersionedRT2 != null
        && !nonVersionedRT1.equals(nonVersionedRT2)) {
      return false;
    }

    return true;
  }
 @Override
 public int hashCode() {
   final int prime = 31;
   int result = 1;
   result = prime * result + ((fields == null) ? 0 : fields.hashCode());
   result = prime * result + ((fieldsToDelete == null) ? 0 : fieldsToDelete.hashCode());
   result = prime * result + ((id == null) ? 0 : id.hashCode());
   result = prime * result + ((recordTypes == null) ? 0 : recordTypes.hashCode());
   result = prime * result + ((version == null) ? 0 : version.hashCode());
   return result;
 }
  @Test
  public void testScanRecordVariantFilter() throws Exception {
    IdGenerator idGenerator = new IdGeneratorImpl();

    final Map<String, String> variantProperties = new HashMap<String, String>();
    variantProperties.put("lang", "en");
    variantProperties.put("branch", null);

    RecordId recordId = idGenerator.newRecordId("foo");

    RecordScan scan = new RecordScan();
    scan.setRecordFilter(new RecordVariantFilter(recordId, variantProperties));

    byte[] data = scanToBytes(scan);
    RecordScan parsedScan = scanFromBytes(data);

    assertNotNull(parsedScan.getRecordFilter());
    assertTrue(parsedScan.getRecordFilter() instanceof RecordVariantFilter);
    assertEquals(
        recordId.getMaster(),
        ((RecordVariantFilter) parsedScan.getRecordFilter()).getMasterRecordId());
    assertEquals(
        variantProperties,
        ((RecordVariantFilter) parsedScan.getRecordFilter()).getVariantProperties());

    // Check json
    JsonNode node = new ObjectMapper().readTree(data);
    assertEquals(
        "org.lilyproject.repository.api.filter.RecordVariantFilter",
        node.get("recordFilter").get("@class").getTextValue());
    assertEquals("USER.foo", node.get("recordFilter").get("recordId").getTextValue());
    assertEquals(
        "en", node.get("recordFilter").get("variantProperties").get("lang").getTextValue());
    assertEquals(
        null, node.get("recordFilter").get("variantProperties").get("branch").getTextValue());
  }