private static Map<Object, IRecord> getRecordsById(
     List<IRecord> updatedOrAdded, int idFieldIndex) {
   Map<Object, IRecord> res = new HashMap<Object, IRecord>(updatedOrAdded.size());
   for (IRecord iRecord : updatedOrAdded) {
     IField fieldId = iRecord.getFieldAt(idFieldIndex);
     Assert.assertNotNull(fieldId, "fieldId");
     Object value = fieldId.getValue();
     Assert.assertNotNull(value, "value");
     res.put(value, iRecord);
   }
   return res;
 }
 private static List<IRecord> getAdded(
     IDataStore prev, RecordRetriever currRetr, int prevFieldIndex) {
   List<IRecord> added = new ArrayList<IRecord>();
   for (int i = 0; i < currRetr.countRecords(); i++) {
     IRecord currRec = currRetr.getRecord(i);
     IField currIdField = currRec.getFieldAt(prevFieldIndex);
     Assert.assertNotNull(currIdField, "currId");
     Object id = currIdField.getValue();
     Assert.assertNotNull(id, "id");
     if (prev.getRecordByID(id) == null) {
       added.add(currRec);
     }
   }
   return added;
 }
 private static List<IRecord> getDeleted(IDataStore prev, IDataStore curr, int prevFieldIndex) {
   List<IRecord> deleted = new ArrayList<IRecord>();
   for (int i = 0; i < prev.getRecordsCount(); i++) {
     IRecord prevRec = prev.getRecordAt(i);
     IField prevIdField = prevRec.getFieldAt(prevFieldIndex);
     Assert.assertNotNull(prevIdField, "prevIdField");
     Object prevId = prevIdField.getValue();
     Assert.assertNotNull(prevId, "prevId");
     IRecord currRec = curr.getRecordByID(prevId);
     if (currRec == null) {
       deleted.add(prevRec);
       continue;
     }
   }
   return deleted;
 }
  private static List<IRecord> getUpdated(
      IDataStore prev, RecordIdRetriever currRetr, int prevFieldIndex) {
    List<IRecord> updated = new ArrayList<IRecord>();
    for (int i = 0; i < prev.getRecordsCount(); i++) {
      IRecord prevRec = prev.getRecordAt(i);
      IField prevIdField = prevRec.getFieldAt(prevFieldIndex);
      Assert.assertNotNull(prevIdField, "prevIdField");
      Object prevId = prevIdField.getValue();
      Assert.assertNotNull(prevId, "prevId");
      IRecord currRec = currRetr.getRecordById(prevId);
      if (currRec == null) {
        // deleted
        continue;
      }

      // check updated by position of field
      // a impossible improvement: check the changes by field meta's name
      List<IField> prevFields = prevRec.getFields();
      List<IField> currFields = currRec.getFields();
      if (prevFields.size() != currFields.size()) {
        updated.add(currRec);
        continue;
      }

      // check updated by checking fields values
      for (int j = 0; j < prevFields.size(); j++) {
        IField prevField = prevFields.get(j);
        IField currField = currFields.get(j);

        Assert.assertNotNull(prevField, "prevField");
        Assert.assertNotNull(currField, "currField");

        Object prevValue = prevField.getValue();
        Object currValue = currField.getValue();

        boolean equals = areEquals(prevValue, currValue);
        if (!equals) {
          updated.add(currRec);
          break;
        }
      }
    }
    return updated;
  }