private String getDeleteSql(final RecordDefinition type) {
    final PathName typePath = type.getPathName();
    final String tableName = this.recordStore.getDatabaseQualifiedTableName(typePath);
    String sql = this.typeDeleteSqlMap.get(typePath);
    if (sql == null) {
      final StringBuilder sqlBuffer = new StringBuilder();
      if (this.sqlPrefix != null) {
        sqlBuffer.append(this.sqlPrefix);
      }
      sqlBuffer.append("delete ");
      if (this.hints != null) {
        sqlBuffer.append(this.hints);
      }
      sqlBuffer.append(" from ");
      sqlBuffer.append(tableName);
      sqlBuffer.append(" where ");
      final JdbcFieldDefinition idField = (JdbcFieldDefinition) type.getIdField();
      if (idField == null) {
        throw new RuntimeException("No primary key found for " + type);
      }
      addSqlColumEqualsPlaceholder(sqlBuffer, idField);

      sqlBuffer.append(" ");
      if (this.sqlSuffix != null) {
        sqlBuffer.append(this.sqlSuffix);
      }
      sql = sqlBuffer.toString();

      this.typeDeleteSqlMap.put(typePath, sql);
    }
    return sql;
  }
 private void initValues(final RecordDefinition recordDefinition) {
   if (recordDefinition == null) {
     this.values = new Object[0];
   } else {
     final int fieldCount = recordDefinition.getFieldCount();
     this.values = new Object[fieldCount];
     final Map<String, Object> defaultValues = recordDefinition.getDefaultValues();
     setValuesByPath(defaultValues);
   }
 }
  public GeometryStylePanel(final GeometryStyleRenderer geometryStyleRenderer) {
    super(geometryStyleRenderer, true);

    this.geometryStyleRenderer = geometryStyleRenderer;
    this.geometryStyle = geometryStyleRenderer.getStyle();
    final AbstractRecordLayer layer = geometryStyleRenderer.getLayer();
    final RecordDefinition recordDefinition = layer.getRecordDefinition();
    final FieldDefinition geometryField = recordDefinition.getGeometryField();

    if (geometryField != null) {
      this.geometryDataType = geometryField.getDataType();
      if (DataTypes.GEOMETRY_COLLECTION.equals(this.geometryDataType)) {
        this.geometryDataType = DataTypes.GEOMETRY;
      } else if (DataTypes.MULTI_POINT.equals(this.geometryDataType)) {
        this.geometryDataType = DataTypes.POINT;
      } else if (DataTypes.MULTI_LINE_STRING.equals(this.geometryDataType)) {
        this.geometryDataType = DataTypes.LINE_STRING;
      } else if (DataTypes.MULTI_POLYGON.equals(this.geometryDataType)) {
        this.geometryDataType = DataTypes.POLYGON;
      }

      final JPanel panel = new JPanel(new BorderLayout());
      add(panel, 1);
      final JPanel stylePanels = new JPanel(new VerticalLayout(5));
      panel.add(stylePanels, BorderLayout.CENTER);

      this.previews = Panels.titledTransparentVerticalLayout("Preview", 5);

      final JPanel previewContainer = new JPanel(new VerticalLayout());
      previewContainer.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0));
      previewContainer.add(this.previews);
      panel.add(previewContainer, BorderLayout.EAST);

      if (DataTypes.GEOMETRY.equals(this.geometryDataType)) {
        addMarkerStylePanel(stylePanels, this.geometryStyle);
        addLineStylePanel(stylePanels, this.geometryStyle);
        addPolygonStylePanel(stylePanels, this.geometryStyle);
        this.previews.add(new MarkerStylePreview(this.geometryStyle));
        addGeometryPreview(DataTypes.LINE_STRING);
        addGeometryPreview(DataTypes.POLYGON);
      } else if (DataTypes.POINT.equals(this.geometryDataType)) {
        addMarkerStylePanel(stylePanels, this.geometryStyle);
        this.previews.add(new MarkerStylePreview(this.geometryStyle));
      } else if (DataTypes.LINE_STRING.equals(this.geometryDataType)) {
        addLineStylePanel(stylePanels, this.geometryStyle);
        addGeometryPreview(DataTypes.LINE_STRING);
      } else if (DataTypes.POLYGON.equals(this.geometryDataType)) {
        addLineStylePanel(stylePanels, this.geometryStyle);
        addPolygonStylePanel(stylePanels, this.geometryStyle);
        addGeometryPreview(DataTypes.POLYGON);
      }
    }
  }
  private String getUpdateSql(final RecordDefinition type) {
    final PathName typePath = type.getPathName();
    final String tableName = this.recordStore.getDatabaseQualifiedTableName(typePath);
    String sql = this.typeUpdateSqlMap.get(typePath);
    if (sql == null) {
      final StringBuilder sqlBuffer = new StringBuilder();
      if (this.sqlPrefix != null) {
        sqlBuffer.append(this.sqlPrefix);
      }
      sqlBuffer.append("update ");
      if (this.hints != null) {
        sqlBuffer.append(this.hints);
      }
      sqlBuffer.append(tableName);
      sqlBuffer.append(" set ");
      final List<FieldDefinition> idFields = type.getIdFields();
      boolean first = true;
      for (final FieldDefinition attribute : type.getFields()) {
        if (!idFields.contains(attribute)) {
          final JdbcFieldDefinition jdbcAttribute = (JdbcFieldDefinition) attribute;
          if (first) {
            first = false;
          } else {
            sqlBuffer.append(", ");
          }
          addSqlColumEqualsPlaceholder(sqlBuffer, jdbcAttribute);
        }
      }
      sqlBuffer.append(" where ");
      first = true;
      for (final FieldDefinition idField : idFields) {
        if (first) {
          first = false;
        } else {
          sqlBuffer.append(" AND ");
        }
        final JdbcFieldDefinition idJdbcAttribute = (JdbcFieldDefinition) idField;
        addSqlColumEqualsPlaceholder(sqlBuffer, idJdbcAttribute);
      }

      sqlBuffer.append(" ");
      if (this.sqlSuffix != null) {
        sqlBuffer.append(this.sqlSuffix);
      }
      sql = sqlBuffer.toString();

      this.typeUpdateSqlMap.put(typePath, sql);
    }
    return sql;
  }
 private void insert(
     final Record object, final PathName typePath, final RecordDefinition recordDefinition)
     throws SQLException {
   PreparedStatement statement = this.typeInsertStatementMap.get(typePath);
   if (statement == null) {
     final String sql = getInsertSql(recordDefinition, false);
     try {
       statement = this.connection.prepareStatement(sql);
       this.typeInsertStatementMap.put(typePath, statement);
     } catch (final SQLException e) {
       LOG.error(sql, e);
     }
   }
   int parameterIndex = 1;
   for (final FieldDefinition fieldDefinition : recordDefinition.getFields()) {
     final JdbcFieldDefinition jdbcFieldDefinition = (JdbcFieldDefinition) fieldDefinition;
     parameterIndex =
         jdbcFieldDefinition.setInsertPreparedStatementValue(statement, parameterIndex, object);
   }
   statement.addBatch();
   Integer batchCount = this.typeInsertBatchCountMap.get(typePath);
   if (batchCount == null) {
     batchCount = 1;
     this.typeInsertBatchCountMap.put(typePath, 1);
   } else {
     batchCount += 1;
     this.typeInsertBatchCountMap.put(typePath, batchCount);
   }
   if (batchCount >= this.batchSize) {
     final String sql = getInsertSql(recordDefinition, false);
     processCurrentBatch(typePath, sql, statement, this.typeInsertBatchCountMap);
   }
 }
 public void setBoundingBox(final BoundingBox boundingBox) {
   final RecordDefinition recordDefinition = this.recordDefinition;
   if (recordDefinition != null) {
     this.boundingBox = boundingBox;
     if (boundingBox != null) {
       final FieldDefinition geometryField = recordDefinition.getGeometryField();
       if (geometryField != null) {
         final GeometryFactory geometryFactory =
             geometryField.getProperty(FieldProperties.GEOMETRY_FACTORY);
         if (geometryFactory != null) {
           this.boundingBox = boundingBox.convert(geometryFactory);
         }
       }
     }
   }
 }
 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);
 }
 @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 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());
    // }
  }
  public static void write(
      final File file, final RecordDefinition recordDefinition, final String dataSource)
      throws IOException {
    try (XmlWriter writer = new XmlWriter(new FileWriter(file))) {
      writer.setIndent(true);
      writer.startDocument("UTF-8", "1.0");
      writer.startTag("OGRVRTDataSource");
      writer.startTag("OGRVRTLayer");
      final String typeName = recordDefinition.getName();
      writer.attribute("name", typeName);
      writer.startTag("SrcDataSource");
      writer.attribute("relativeToVRT", "1");
      writer.text(dataSource);
      writer.endTag("SrcDataSource");

      writer.element(new QName("SrcLayer"), typeName);

      for (final FieldDefinition attribute : recordDefinition.getFields()) {
        final String fieldName = attribute.getName();
        final DataType fieldType = attribute.getDataType();
        final Class<?> typeClass = attribute.getTypeClass();
        if (Geometry.class.isAssignableFrom(typeClass)) {
          final GeometryFactory geometryFactory = recordDefinition.getGeometryFactory();
          writer.element("GeometryType", "wkb" + fieldType);
          if (geometryFactory != null) {
            writer.element("LayerSRS", "EPSG:" + geometryFactory.getCoordinateSystemId());
          }
          writer.startTag("GeometryField");
          writer.attribute("encoding", "WKT");
          writer.attribute("field", fieldName);
          writer.attribute("name", fieldName);
          writer.attribute("reportSrcColumn", "FALSE");
          writer.element("GeometryType", "wkb" + fieldType);
          if (geometryFactory != null) {
            writer.element("SRS", "EPSG:" + geometryFactory.getCoordinateSystemId());
          }
          writer.endTag("GeometryField");
        } else {
          writer.startTag("Field");
          writer.attribute("name", fieldName);
          String type = "String";
          if (Arrays.asList(
                  DataTypes.BYTE, DataTypes.SHORT, DataTypes.INT, DataTypes.LONG, DataTypes.INTEGER)
              .contains(fieldType)) {
            type = "Integer";
          } else if (Arrays.asList(DataTypes.FLOAT, DataTypes.DOUBLE, DataTypes.DECIMAL)
              .contains(fieldType)) {
            type = "Real";
          } else if (DataTypes.DATE.equals(type)) {
            type = "Date";
          } else if (DataTypes.DATE_TIME.equals(type)) {
            type = "DateTime";
          } else {
            type = "String";
          }
          writer.attribute("type", type);
          final int length = attribute.getLength();
          if (length > 0) {
            writer.attribute("width", length);
          }
          final int scale = attribute.getScale();
          if (scale > 0) {
            writer.attribute("scale", scale);
          }
          writer.attribute("src", fieldName);
          writer.endTag("Field");
        }
      }
      writer.endTag("OGRVRTLayer");
      writer.endTag("OGRVRTDataSource");
      writer.endDocument();
    }
  }
 private String getInsertSql(final RecordDefinition type, final boolean generatePrimaryKey) {
   final PathName typePath = type.getPathName();
   final String tableName = this.recordStore.getDatabaseQualifiedTableName(typePath);
   String sql;
   if (generatePrimaryKey) {
     sql = this.typeInsertSequenceSqlMap.get(typePath);
   } else {
     sql = this.typeInsertSqlMap.get(typePath);
   }
   if (sql == null) {
     final StringBuilder sqlBuffer = new StringBuilder();
     if (this.sqlPrefix != null) {
       sqlBuffer.append(this.sqlPrefix);
     }
     sqlBuffer.append("insert ");
     if (this.hints != null) {
       sqlBuffer.append(this.hints);
     }
     sqlBuffer.append(" into ");
     sqlBuffer.append(tableName);
     sqlBuffer.append(" (");
     if (generatePrimaryKey) {
       final String idFieldName = type.getIdFieldName();
       if (this.quoteColumnNames) {
         sqlBuffer.append('"').append(idFieldName).append('"');
       } else {
         sqlBuffer.append(idFieldName);
       }
       sqlBuffer.append(",");
     }
     for (int i = 0; i < type.getFieldCount(); i++) {
       if (!generatePrimaryKey || i != type.getIdFieldIndex()) {
         final String fieldName = type.getFieldName(i);
         if (this.quoteColumnNames) {
           sqlBuffer.append('"').append(fieldName).append('"');
         } else {
           sqlBuffer.append(fieldName);
         }
         if (i < type.getFieldCount() - 1) {
           sqlBuffer.append(", ");
         }
       }
     }
     sqlBuffer.append(") VALUES (");
     if (generatePrimaryKey) {
       sqlBuffer.append(getGeneratePrimaryKeySql(type));
       sqlBuffer.append(",");
     }
     for (int i = 0; i < type.getFieldCount(); i++) {
       if (!generatePrimaryKey || i != type.getIdFieldIndex()) {
         final JdbcFieldDefinition attribute = (JdbcFieldDefinition) type.getField(i);
         attribute.addInsertStatementPlaceHolder(sqlBuffer, generatePrimaryKey);
         if (i < type.getFieldCount() - 1) {
           sqlBuffer.append(", ");
         }
       }
     }
     sqlBuffer.append(")");
     if (this.sqlSuffix != null) {
       sqlBuffer.append(this.sqlSuffix);
     }
     sql = sqlBuffer.toString();
     if (generatePrimaryKey) {
       this.typeInsertSequenceSqlMap.put(typePath, sql);
     } else {
       this.typeInsertSqlMap.put(typePath, sql);
     }
   }
   return sql;
 }