@Override
 public void mergeWith(Record record, Map<Record, Object> recordsToRefresh) {
   super.mergeWith(record, recordsToRefresh);
   HierarchicalRecord hierarchicalRecord = (HierarchicalRecord) record;
   // parent ids
   for (HierarchicalRecord parentRecord : hierarchicalRecord.getParentRecords()) {
     if (!isParentOf(parentRecord) && !parentRecord.isRoot())
       getHierarchicalIndex().addRelationship(parentRecord, this);
   }
   // child ids
   for (HierarchicalRecord childRecord : hierarchicalRecord.getChildRecords()) {
     if (!isChildOf(childRecord)) getHierarchicalIndex().addRelationship(this, childRecord);
   }
 }
 public boolean isParentOf(HierarchicalRecord record) {
   if (record != null) {
     for (HierarchicalRecord parent : record.getParentRecords()) {
       if (this == parent) return true;
       if (isParentOf(parent)) return true;
     }
   }
   return false;
 }
 public boolean isChildOf(HierarchicalRecord record) {
   if (record != null) {
     for (HierarchicalRecord child : record.getChildRecords()) {
       if (this == child) return true;
       if (isChildOf(child)) return true;
     }
   }
   return false;
 }
 private boolean updateChildren(HierarchicalRecord record, boolean add) {
   boolean result = false;
   if (record == null) return result;
   try {
     childSem.acquire(uniqueId << 4 + getDataType());
     getWriteLockSem().startRead("updateChildren");
     if (add) {
       boolean found = false;
       int i = 0;
       if (childIds != null) {
         while ((i < childIds.length) && !found) {
           if (childIds[i] == record.getUniqueId()) found = true;
           ++i;
         }
       }
       if (!found) {
         int[] newChilds = new int[(childIds != null) ? childIds.length + 1 : 1];
         i = 0;
         if (childIds != null) {
           while (i < childIds.length) {
             newChilds[i] = childIds[i];
             ++i;
           }
         }
         newChilds[i] = record.getUniqueId();
         childIds = newChilds;
         result = true;
       }
     } else {
       // remove
       removeChildId(record.getUniqueId());
       if (record.getDuplicateIds() != null) {
         for (int duplicateId : record.getDuplicateIds()) removeChildId(duplicateId);
       }
     }
   } catch (Exception e) {
     log.error("updateChildren(): error", e);
   } finally {
     getWriteLockSem().endRead();
     childSem.release(uniqueId << 4 + getDataType());
   }
   childRecords = null;
   return result;
 }
 public boolean isRootChild() {
   for (HierarchicalRecord record : getParentRecords()) {
     if ((record != null) && record.isRoot()) return true;
   }
   return false;
 }
 private boolean updateParents(HierarchicalRecord record, boolean add) {
   boolean result = false;
   if (record == null) return result;
   try {
     parentSem.acquire(uniqueId << 4 + getDataType());
     getWriteLockSem().startRead("updateParents");
     if (add) {
       boolean found = false;
       int i = 0;
       if (parentIds != null) {
         while ((i < parentIds.length) && !found) {
           if (parentIds[i] == record.getUniqueId()) found = true;
           ++i;
         }
       }
       if (!found) {
         int[] newParents = new int[(parentIds != null) ? parentIds.length + 1 : 1];
         i = 0;
         if (parentIds != null) {
           while (i < parentIds.length) {
             newParents[i] = parentIds[i];
             ++i;
           }
         }
         newParents[i] = record.getUniqueId();
         parentIds = newParents;
         result = true;
       }
     } else {
       // remove
       boolean found = false;
       int removedIndex = 0;
       if (parentIds != null) {
         while ((removedIndex < parentIds.length) && !found) {
           if (parentIds[removedIndex] == record.getUniqueId()) found = true;
           else ++removedIndex;
         }
       }
       if (found) {
         int[] newParents = new int[parentIds.length - 1];
         int i = 0;
         while (i < parentIds.length) {
           if (i < removedIndex) newParents[i] = parentIds[i];
           else if (i > removedIndex) newParents[i - 1] = parentIds[i];
           ++i;
         }
         parentIds = newParents;
         result = true;
       } else {
         if (log.isDebugEnabled()) log.debug("updateParents(): parent not found=" + record);
       }
     }
   } catch (Exception e) {
     log.error("updateParents(): error", e);
   } finally {
     getWriteLockSem().endRead();
     parentSem.release(uniqueId << 4 + getDataType());
   }
   parentRecords = null;
   return result;
 }
 public boolean containsParentDirectly(HierarchicalRecord record) {
   if (parentIds != null) {
     for (int parentId : parentIds) if (parentId == record.getUniqueId()) return true;
   }
   return false;
 }
 public boolean containsChildDirectly(HierarchicalRecord record) {
   if (childIds != null) {
     for (int childId : childIds) if (childId == record.getUniqueId()) return true;
   }
   return false;
 }