public static Set<RecordDefinition> edgeRecordDefinitions(final Node<?> node) {
   final Set<RecordDefinition> recordDefinitions = new HashSet<>();
   for (final Edge<?> edge : node.getEdges()) {
     final Object object = edge.getObject();
     if (object instanceof Record) {
       final Record record = (Record) object;
       final RecordDefinition recordDefinition = record.getRecordDefinition();
       recordDefinitions.add(recordDefinition);
     }
   }
   return recordDefinitions;
 }
 @Override
 protected synchronized Record getNext() throws NoSuchElementException {
   final FileGdbRecordStore recordStore = this.recordStore;
   final FileGdbEnumRowsIterator rows = this.rows;
   if (rows == null || this.closed) {
     throw new NoSuchElementException();
   } else {
     Row row = null;
     while (this.offset > 0 && this.count < this.offset) {
       row = rows.next();
       this.count++;
       if (this.closed) {
         throw new NoSuchElementException();
       }
     }
     if (this.count - this.offset >= this.limit) {
       throw new NoSuchElementException();
     }
     row = rows.next();
     this.count++;
     try {
       final Record record = this.recordFactory.newRecord(this.recordDefinition);
       if (this.labelCountMap == null) {
         recordStore.addStatistic("query", record);
       } else {
         this.labelCountMap.addCount(record);
       }
       record.setState(RecordState.INITIALIZING);
       for (final FieldDefinition field : this.recordDefinition.getFields()) {
         final String name = field.getName();
         final AbstractFileGdbFieldDefinition esriFieldDefinition =
             (AbstractFileGdbFieldDefinition) field;
         final Object value = esriFieldDefinition.getValue(row);
         record.setValue(name, value);
         if (this.closed) {
           throw new NoSuchElementException();
         }
       }
       record.setState(RecordState.PERSISTED);
       if (this.closed) {
         throw new NoSuchElementException();
       }
       return record;
     } finally {
       row.delete();
     }
   }
 }
 @Override
 public void write(final Record record) {
   if (record != null) {
     try {
       final RecordState state = record.getState();
       switch (state) {
         case MODIFIED:
           this.recordStore.updateRecord(record);
           break;
         case PERSISTED:
           this.recordStore.updateRecord(record);
           break;
         case DELETED:
           this.recordStore.deleteRecord(record);
           break;
         default:
           this.recordStore.insertRecord(record);
           break;
       }
     } catch (final RuntimeException e) {
       throw e;
     } catch (final Error e) {
       throw e;
     } catch (final Exception e) {
       throw new RuntimeException("Unable to write", e);
     }
   }
 }
 @Override
 public synchronized void write(final Record record) {
   try {
     final RecordDefinition recordDefinition = record.getRecordDefinition();
     final RecordStore recordStore = recordDefinition.getRecordStore();
     final RecordState state = record.getState();
     if (recordStore != this.recordStore) {
       if (state != RecordState.DELETED) {
         insert(record);
       }
     } else {
       switch (state) {
         case NEW:
           insert(record);
           break;
         case MODIFIED:
           update(record);
           break;
         case PERSISTED:
           // No action required
           break;
         case DELETED:
           delete(record);
           break;
         default:
           throw new IllegalStateException("State not known");
       }
     }
   } catch (final RuntimeException e) {
     throw e;
   } catch (final Error e) {
     throw e;
   } catch (final BatchUpdateException e) {
     for (SQLException e1 = e.getNextException(); e1 != null; e1 = e1.getNextException()) {
       LOG.error("Unable to write", e1);
     }
     throw new RuntimeException("Unable to write", e);
   } catch (final Exception e) {
     throw new RuntimeException("Unable to write", e);
   }
 }
  private void insert(final Record record) throws SQLException {
    final PathName typePath = record.getPathName();
    final RecordDefinition recordDefinition = getRecordDefinition(typePath);
    flushIfRequired(recordDefinition);
    final String idFieldName = recordDefinition.getIdFieldName();
    final boolean hasId = idFieldName != null;

    final GlobalIdProperty globalIdProperty = GlobalIdProperty.getProperty(record);
    if (globalIdProperty != null) {
      if (record.getValue(globalIdProperty.getFieldName()) == null) {
        record.setValue(globalIdProperty.getFieldName(), UUID.randomUUID().toString());
      }
    }

    final boolean hasIdValue = hasId && record.getValue(idFieldName) != null;

    if (!hasId || hasIdValue) {
      insert(record, typePath, recordDefinition);
    } else {
      insertSequence(record, typePath, recordDefinition);
    }
    record.setState(RecordState.PERSISTED);
    this.recordStore.addStatistic("Insert", record);
  }
 private void update(final Record object) throws SQLException {
   final RecordDefinition objectType = object.getRecordDefinition();
   final PathName typePath = objectType.getPathName();
   final RecordDefinition recordDefinition = getRecordDefinition(typePath);
   flushIfRequired(recordDefinition);
   PreparedStatement statement = this.typeUpdateStatementMap.get(typePath);
   if (statement == null) {
     final String sql = getUpdateSql(recordDefinition);
     try {
       statement = this.connection.prepareStatement(sql);
       this.typeUpdateStatementMap.put(typePath, statement);
     } catch (final SQLException e) {
       LOG.error(sql, e);
     }
   }
   int parameterIndex = 1;
   final List<FieldDefinition> idFields = recordDefinition.getIdFields();
   for (final FieldDefinition fieldDefinition : recordDefinition.getFields()) {
     if (!idFields.contains(fieldDefinition)) {
       final JdbcFieldDefinition jdbcFieldDefinition = (JdbcFieldDefinition) fieldDefinition;
       parameterIndex =
           jdbcFieldDefinition.setInsertPreparedStatementValue(statement, parameterIndex, object);
     }
   }
   for (final FieldDefinition idField : idFields) {
     final JdbcFieldDefinition jdbcFieldDefinition = (JdbcFieldDefinition) idField;
     parameterIndex =
         jdbcFieldDefinition.setInsertPreparedStatementValue(statement, parameterIndex, object);
   }
   statement.addBatch();
   Integer batchCount = this.typeUpdateBatchCountMap.get(typePath);
   if (batchCount == null) {
     batchCount = 1;
     this.typeUpdateBatchCountMap.put(typePath, 1);
   } else {
     batchCount += 1;
     this.typeUpdateBatchCountMap.put(typePath, batchCount);
   }
   if (batchCount >= this.batchSize) {
     final String sql = getUpdateSql(recordDefinition);
     processCurrentBatch(typePath, sql, statement, this.typeUpdateBatchCountMap);
   }
   this.recordStore.addStatistic("Update", object);
 }
  private void delete(final Record object) throws SQLException {
    final RecordDefinition objectType = object.getRecordDefinition();
    final PathName typePath = objectType.getPathName();
    final RecordDefinition recordDefinition = getRecordDefinition(typePath);
    flushIfRequired(recordDefinition);
    PreparedStatement statement = this.typeDeleteStatementMap.get(typePath);
    if (statement == null) {
      final String sql = getDeleteSql(recordDefinition);
      try {
        statement = this.connection.prepareStatement(sql);
        this.typeDeleteStatementMap.put(typePath, statement);
      } catch (final SQLException e) {
        LOG.error(sql, e);
      }
    }
    int parameterIndex = 1;
    final JdbcFieldDefinition idField = (JdbcFieldDefinition) recordDefinition.getIdField();
    parameterIndex = idField.setInsertPreparedStatementValue(statement, parameterIndex, object);
    statement.addBatch();
    Integer batchCount = this.typeDeleteBatchCountMap.get(typePath);
    if (batchCount == null) {
      batchCount = 1;
      this.typeDeleteBatchCountMap.put(typePath, 1);
    } else {
      batchCount += 1;
      this.typeDeleteBatchCountMap.put(typePath, batchCount);
    }
    this.recordStore.addStatistic("Delete", object);

    // TODO this locks code tables which prevents insert
    // if (batchCount >= batchSize) {
    // final String sql = getDeleteSql(recordDefinition);
    // processCurrentBatch(typePath, sql, statement, typeDeleteBatchCountMap,
    // getDeleteStatistics());
    // }
  }