diff --git a/.github/workflows/daily.yml b/.github/workflows/daily.yml
index e494a50e0..71d1f6208 100644
--- a/.github/workflows/daily.yml
+++ b/.github/workflows/daily.yml
@@ -15,7 +15,7 @@ jobs:
uses: actions/setup-java@v3
with:
distribution: 'temurin'
- java-version: 11
+ java-version: 17
- name: Build with Maven
run: mvn -U -B clean install
@@ -28,7 +28,7 @@ jobs:
uses: actions/setup-java@v3
with:
distribution: 'temurin'
- java-version: 11
+ java-version: 17
server-id: sonatype-nexus-snapshots
server-username: MAVEN_USERNAME
server-password: MAVEN_PASSWORD
diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml
index 0e3cd938d..739307b58 100644
--- a/.github/workflows/push.yml
+++ b/.github/workflows/push.yml
@@ -33,7 +33,7 @@ jobs:
uses: actions/setup-java@v3
with:
distribution: 'temurin'
- java-version: 11
+ java-version: 17
server-id: sonatype-nexus-snapshots
server-username: MAVEN_USERNAME
server-password: MAVEN_PASSWORD
diff --git a/.github/workflows/push_java_8.yml b/.github/workflows/push_java_8.yml
index e6254bdd3..aba627181 100644
--- a/.github/workflows/push_java_8.yml
+++ b/.github/workflows/push_java_8.yml
@@ -33,7 +33,7 @@ jobs:
uses: actions/setup-java@v3
with:
distribution: 'temurin'
- java-version: 8
+ java-version: 17
server-id: sonatype-nexus-snapshots
server-username: MAVEN_USERNAME
server-password: MAVEN_PASSWORD
diff --git a/.gitignore b/.gitignore
index 4a587ab0d..1876c424e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,3 +10,7 @@ codegen/console.log
.idea/*
*.iml
*.checkstyle
+.clawdea/REPO_STATE.md
+
+## local, credential-bearing config
+db.properties
diff --git a/CLAUDE.md b/CLAUDE.md
new file mode 100644
index 000000000..3cef15a4f
--- /dev/null
+++ b/CLAUDE.md
@@ -0,0 +1,17 @@
+1. Ask, don't assume. If something is unclear, ask before writing a single line. Never make silent assumptions about intent, architecture, or requirements. When running unattended, pick the most reasonable interpretation, proceed, and record the assumption rather than blocking.
+
+2. Implement the simplest solution for simple problems, better solutions for harder problems. Do not over-engineer or add flexibility that isn't needed yet.
+
+3. Don't touch unrelated code but please do surface bad code or design smells you discover with me so we can address them as a separate issue.
+
+4. Flag uncertainty explicitly. If you're unsure about something, see point 1 above. If it makes sense to do so, conduct a small, localised and low-risk experiment and bring the hypothesis and results to me to discuss. Confidence without certainty causes more damage than admitting a gap.
+
+# Inline Comments
+
+- Use short comments to clarify non-obvious logic or business rules.
+- Prefer comments above the line they explain.
+- Mark decision points with `// decision:` and assumptions with `// assumption:`
+
+# Verification
+
+- Always ask the user for input from the user if uncertainties arise during implementation
\ No newline at end of file
diff --git a/dialects/pom.xml b/dialects/pom.xml
deleted file mode 100644
index af0c3e09e..000000000
--- a/dialects/pom.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
- 4.0.0
-
- org.n52.sensorweb-server.db-model
- db-model-parent
- 4.0.5-SNAPSHOT
-
- db-model-dialects
- jar
- Sensor Web Server Database Model - Hibernate Spatial Dialects
-
-
-
- org.hibernate
- hibernate-core
- provided
-
-
- org.hibernate
- hibernate-spatial
-
-
- org.geolatte
- geolatte-geom
- provided
-
-
-
-
-
diff --git a/dialects/src/main/java/org/n52/hibernate/spatial/dialect/h2geodb/TimestampWithTimeZoneGeoDBDialect.java b/dialects/src/main/java/org/n52/hibernate/spatial/dialect/h2geodb/TimestampWithTimeZoneGeoDBDialect.java
deleted file mode 100644
index 23f9ae41c..000000000
--- a/dialects/src/main/java/org/n52/hibernate/spatial/dialect/h2geodb/TimestampWithTimeZoneGeoDBDialect.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2015-2023 52°North Spatial Information Research GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.n52.hibernate.spatial.dialect.h2geodb;
-
-import java.sql.Types;
-
-import org.hibernate.spatial.dialect.h2geodb.GeoDBDialect;
-
-public class TimestampWithTimeZoneGeoDBDialect extends GeoDBDialect {
-
- private static final long serialVersionUID = 3719262383564175336L;
-
- public TimestampWithTimeZoneGeoDBDialect() {
- super();
- registerColumnType(Types.TIMESTAMP, "timestamp with time zone");
- }
-}
diff --git a/dialects/src/main/java/org/n52/hibernate/spatial/dialect/mysql/TimestampMySQL57SpatialDialect.java b/dialects/src/main/java/org/n52/hibernate/spatial/dialect/mysql/TimestampMySQL57SpatialDialect.java
deleted file mode 100644
index 2d46bc871..000000000
--- a/dialects/src/main/java/org/n52/hibernate/spatial/dialect/mysql/TimestampMySQL57SpatialDialect.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2015-2023 52°North Spatial Information Research GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.n52.hibernate.spatial.dialect.mysql;
-
-import java.sql.Types;
-
-import org.hibernate.HibernateException;
-import org.hibernate.spatial.dialect.mysql.MySQL56SpatialDialect;
-
-public class TimestampMySQL57SpatialDialect extends MySQL56SpatialDialect {
-
- private static final long serialVersionUID = -8145146230035810465L;
- private static final String TIMESTAMP = "timestamp";
-
- public TimestampMySQL57SpatialDialect() {
- super();
- registerColumnType(Types.TIMESTAMP, TIMESTAMP);
- }
-
- @Override
- public String getTypeName(int code, long length, int precision, int scale) throws HibernateException {
- if (Types.TIMESTAMP == code) {
- return TIMESTAMP;
- }
- return super.getTypeName(code, length, precision, scale);
- }
-
- @Override
- public String getTypeName(int code) throws HibernateException {
- if (Types.TIMESTAMP == code) {
- return TIMESTAMP;
- }
- return super.getTypeName(code);
- }
-
- @Override
- public String getNullColumnString() {
- return " NULL";
- }
-}
diff --git a/dialects/src/main/java/org/n52/hibernate/spatial/dialect/mysql/TimestampMySQL8SpatialDialect.java b/dialects/src/main/java/org/n52/hibernate/spatial/dialect/mysql/TimestampMySQL8SpatialDialect.java
deleted file mode 100644
index 18c44fc9b..000000000
--- a/dialects/src/main/java/org/n52/hibernate/spatial/dialect/mysql/TimestampMySQL8SpatialDialect.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2015-2023 52°North Spatial Information Research GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.n52.hibernate.spatial.dialect.mysql;
-
-import java.sql.Types;
-
-import org.hibernate.HibernateException;
-import org.hibernate.spatial.dialect.mysql.MySQL8SpatialDialect;
-
-public class TimestampMySQL8SpatialDialect extends MySQL8SpatialDialect {
-
- private static final long serialVersionUID = -8145146230035810465L;
- private static final String TIMESTAMP = "timestamp";
-
- public TimestampMySQL8SpatialDialect() {
- super();
- registerColumnType(Types.TIMESTAMP, TIMESTAMP);
- }
-
- @Override
- public String getTypeName(int code, long length, int precision, int scale) throws HibernateException {
- if (Types.TIMESTAMP == code) {
- return TIMESTAMP;
- }
- return super.getTypeName(code, length, precision, scale);
- }
-
- @Override
- public String getTypeName(int code) throws HibernateException {
- if (Types.TIMESTAMP == code) {
- return TIMESTAMP;
- }
- return super.getTypeName(code);
- }
-
- @Override
- public String getNullColumnString() {
- return " NULL";
- }
-}
diff --git a/dialects/src/main/java/org/n52/hibernate/spatial/dialect/oracle/TimestampWithTimeZoneOracleSpatial10gDialect.java b/dialects/src/main/java/org/n52/hibernate/spatial/dialect/oracle/TimestampWithTimeZoneOracleSpatial10gDialect.java
deleted file mode 100644
index 44e94c3b3..000000000
--- a/dialects/src/main/java/org/n52/hibernate/spatial/dialect/oracle/TimestampWithTimeZoneOracleSpatial10gDialect.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2015-2023 52°North Spatial Information Research GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.n52.hibernate.spatial.dialect.oracle;
-
-import java.sql.Types;
-
-import org.hibernate.spatial.dialect.oracle.OracleSpatial10gDialect;
-
-public class TimestampWithTimeZoneOracleSpatial10gDialect extends OracleSpatial10gDialect {
-
- private static final long serialVersionUID = 2459190033248440220L;
-
- public TimestampWithTimeZoneOracleSpatial10gDialect() {
- super();
- registerColumnType(Types.DOUBLE, "float");
- registerColumnType(Types.TIMESTAMP, "timestamp with time zone");
- }
-
-}
diff --git a/dialects/src/main/java/org/n52/hibernate/spatial/dialect/postgis/TimestampWithTimeZonePostgisPG95Dialect.java b/dialects/src/main/java/org/n52/hibernate/spatial/dialect/postgis/TimestampWithTimeZonePostgisPG95Dialect.java
deleted file mode 100644
index f028045e0..000000000
--- a/dialects/src/main/java/org/n52/hibernate/spatial/dialect/postgis/TimestampWithTimeZonePostgisPG95Dialect.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2015-2023 52°North Spatial Information Research GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.n52.hibernate.spatial.dialect.postgis;
-
-import java.sql.Types;
-
-import org.hibernate.spatial.dialect.postgis.PostgisPG95Dialect;
-
-public class TimestampWithTimeZonePostgisPG95Dialect extends PostgisPG95Dialect {
-
- private static final long serialVersionUID = -3409681181015765469L;
-
- public TimestampWithTimeZonePostgisPG95Dialect() {
- super();
- registerColumnType(Types.TIMESTAMP, "timestamp with time zone");
- }
-
-}
diff --git a/dialects/src/main/java/org/n52/hibernate/spatial/dialect/sqlserver/TimestampWithTimeZoneSqlServer2008SpatialDialect.java b/dialects/src/main/java/org/n52/hibernate/spatial/dialect/sqlserver/TimestampWithTimeZoneSqlServer2008SpatialDialect.java
deleted file mode 100644
index c208e70cd..000000000
--- a/dialects/src/main/java/org/n52/hibernate/spatial/dialect/sqlserver/TimestampWithTimeZoneSqlServer2008SpatialDialect.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2015-2023 52°North Spatial Information Research GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.n52.hibernate.spatial.dialect.sqlserver;
-
-import java.sql.Types;
-
-import org.hibernate.spatial.dialect.sqlserver.SqlServer2008SpatialDialect;
-
-public class TimestampWithTimeZoneSqlServer2008SpatialDialect extends SqlServer2008SpatialDialect {
-
- private static final long serialVersionUID = -5075490566512423995L;
-
- public TimestampWithTimeZoneSqlServer2008SpatialDialect() {
- super();
- registerColumnType(Types.TIMESTAMP, "datetimeoffset");
- }
-
-}
diff --git a/dialects/src/main/java/org/n52/hibernate/spatial/dialect/sqlserver/TimestampWithTimeZoneSqlServer2012SpatialDialect.java b/dialects/src/main/java/org/n52/hibernate/spatial/dialect/sqlserver/TimestampWithTimeZoneSqlServer2012SpatialDialect.java
deleted file mode 100644
index b3a0feed6..000000000
--- a/dialects/src/main/java/org/n52/hibernate/spatial/dialect/sqlserver/TimestampWithTimeZoneSqlServer2012SpatialDialect.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2015-2023 52°North Spatial Information Research GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.n52.hibernate.spatial.dialect.sqlserver;
-
-import java.sql.Types;
-
-import org.hibernate.spatial.dialect.sqlserver.SqlServer2012SpatialDialect;
-
-public class TimestampWithTimeZoneSqlServer2012SpatialDialect extends SqlServer2012SpatialDialect {
-
- private static final long serialVersionUID = -5075490566512423995L;
-
- public TimestampWithTimeZoneSqlServer2012SpatialDialect() {
- super();
- registerColumnType(Types.TIMESTAMP, "datetimeoffset");
- }
-
-}
diff --git a/entities/pom.xml b/entities/pom.xml
index 1b0afcf4a..8d65ec690 100644
--- a/entities/pom.xml
+++ b/entities/pom.xml
@@ -1,5 +1,6 @@
-
+
4.0.0
org.n52.sensorweb-server.db-model
@@ -11,19 +12,17 @@
Sensor Web Server Database Model - Entities
-
-
- javax
- javaee-api
-
-
com.neovisionaries
nv-i18n
- com.google.code.findbugs
- jsr305
+ jakarta.persistence
+ jakarta.persistence-api
+
+
+ org.hibernate.orm
+ hibernate-core
@@ -39,6 +38,11 @@
spotbugs-annotations
provided
+
+ jakarta.annotation
+ jakarta.annotation-api
+ provided
+
org.slf4j
@@ -60,6 +64,18 @@
hamcrest
test
+
+
+
+ org.postgresql
+ postgresql
+ test
+
+
+ org.hibernate.orm
+ hibernate-spatial
+ test
+
diff --git a/entities/src/main/java/org/n52/series/db/beans/AbstractCodespaceEntity.java b/entities/src/main/java/org/n52/series/db/beans/AbstractCodespaceEntity.java
new file mode 100644
index 000000000..9ef2a9c81
--- /dev/null
+++ b/entities/src/main/java/org/n52/series/db/beans/AbstractCodespaceEntity.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2015-2023 52°North Spatial Information Research GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.n52.series.db.beans;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.MappedSuperclass;
+
+import java.io.Serial;
+
+/**
+ * Marks entities that have an identifier/name codespace in their schema, as opposed to entities extending
+ * {@link DescribableEntity} directly (e.g. CategoryEntity, UnitEntity, TagEntity)
+ */
+@SuppressFBWarnings({ "EI_EXPOSE_REP", "EI_EXPOSE_REP2" })
+@MappedSuperclass
+public abstract class AbstractCodespaceEntity extends DescribableEntity {
+
+ @Serial
+ private static final long serialVersionUID = -3196986792845310821L;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "fk_identifier_codespace_id")
+ private CodespaceEntity identifierCodespace;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "fk_name_codespace_id")
+ private CodespaceEntity nameCodespace;
+
+ @Override
+ public CodespaceEntity getIdentifierCodespace() {
+ return identifierCodespace;
+ }
+
+ @Override
+ public void setIdentifierCodespace(CodespaceEntity identifierCodespace) {
+ this.identifierCodespace = identifierCodespace;
+ }
+
+ @Override
+ public CodespaceEntity getNameCodespace() {
+ return nameCodespace;
+ }
+
+ @Override
+ public void setNameCodespace(CodespaceEntity nameCodespace) {
+ this.nameCodespace = nameCodespace;
+ }
+}
diff --git a/entities/src/main/java/org/n52/series/db/beans/AbstractDatasetEntity.java b/entities/src/main/java/org/n52/series/db/beans/AbstractDatasetEntity.java
index 11a01037d..c762776ab 100644
--- a/entities/src/main/java/org/n52/series/db/beans/AbstractDatasetEntity.java
+++ b/entities/src/main/java/org/n52/series/db/beans/AbstractDatasetEntity.java
@@ -13,17 +13,38 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.n52.series.db.beans;
-import java.io.Serializable;
-import java.math.BigDecimal;
-import java.sql.Timestamp;
-import java.util.Collections;
-import java.util.Date;
-import java.util.Set;
-import java.util.stream.Collectors;
+package org.n52.series.db.beans;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import jakarta.persistence.Access;
+import jakarta.persistence.AccessType;
+import jakarta.persistence.AttributeOverride;
+import jakarta.persistence.CascadeType;
+import jakarta.persistence.Column;
+import jakarta.persistence.DiscriminatorColumn;
+import jakarta.persistence.Embedded;
+import jakarta.persistence.Entity;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.ForeignKey;
+import jakarta.persistence.Index;
+import jakarta.persistence.Inheritance;
+import jakarta.persistence.InheritanceType;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.OneToMany;
+import jakarta.persistence.Table;
+import jakarta.persistence.Temporal;
+import jakarta.persistence.TemporalType;
+import jakarta.persistence.Transient;
+import jakarta.persistence.UniqueConstraint;
+import org.hibernate.annotations.SQLRestriction;
import org.locationtech.jts.geom.Geometry;
+import org.n52.series.db.beans.i18n.I18nDatasetEntity;
+import org.n52.series.db.beans.i18n.I18nEntity;
+import org.n52.series.db.beans.i18n.I18nPhenomenonEntity;
+import org.n52.series.db.beans.parameter.ParameterEntity;
+import org.n52.series.db.beans.parameter.dataset.DatasetParameterEntity;
import org.n52.series.db.beans.sta.AbstractDatastreamEntity;
import org.n52.series.db.beans.sta.LicenseEntity;
import org.n52.series.db.beans.sta.PartyEntity;
@@ -31,13 +52,55 @@
import org.n52.series.db.beans.sta.StaRelations;
import org.n52.series.db.common.Utils;
-import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import java.io.Serial;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.sql.Timestamp;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Set;
+import java.util.stream.Collectors;
/**
* @author Jan Speckamp
*/
@SuppressFBWarnings({ "EI_EXPOSE_REP", "EI_EXPOSE_REP2" })
-public class AbstractDatasetEntity extends DescribableEntity
+@Entity(name = "org.n52.series.db.beans.AbstractDatasetEntity")
+@Table(name = "dataset",
+ indexes = { @Index(name = "idx_dataset_identifier", columnList = "identifier"),
+ @Index(name = "idx_dataset_staIdentifier", columnList = "sta_identifier"),
+ @Index(name = "idx_dataset_procedure", columnList = "fk_procedure_id"),
+ @Index(name = "idx_dataset_phenomenon", columnList = "fk_phenomenon_id"),
+ @Index(name = "idx_dataset_offering", columnList = "fk_offering_id"),
+ @Index(name = "idx_dataset_category", columnList = "fk_category_id"),
+ @Index(name = "idx_dataset_feature", columnList = "fk_feature_id"),
+ @Index(name = "idx_dataset_platform", columnList = "fk_platform_id"),
+ @Index(name = "idx_dataset_unit", columnList = "fk_unit_id"),
+ @Index(name = "idx_dataset_observation_type", columnList = "fk_format_id, observation_type"),
+ @Index(name = "idx_dataset_aggregation", columnList = "fk_aggregation_id"),
+ @Index(name = "idx_dataset_first_observation", columnList = "fk_first_observation_id"),
+ @Index(name = "idx_dataset_last_observation", columnList = "fk_last_observation_id"),
+ @Index(name = "idx_dataset_dataset_type", columnList = "dataset_type"),
+ @Index(name = "idx_dataset_value_type", columnList = "value_type"),
+ @Index(name = "idx_dataset_is_deleted", columnList = "is_deleted"),
+ @Index(name = "idx_dataset_is_disabled", columnList = "is_disabled"),
+ @Index(name = "idx_dataset_is_published", columnList = "is_published"),
+ @Index(name = "idx_dataset_is_mobile", columnList = "is_mobile"),
+ @Index(name = "idx_dataset_is_insitu", columnList = "is_insitu"),
+ @Index(name = "idx_dataset_is_hidden", columnList = "is_hidden"),
+ @Index(name = "idx_dataset_identifier_codespace", columnList = "fk_identifier_codespace_id"),
+ @Index(name = "idx_dataset_name_codespace", columnList = "fk_name_codespace_id"),
+ @Index(name = "idx_dataset_value_profile", columnList = "fk_value_profile_id") },
+ uniqueConstraints = { @UniqueConstraint(name = "un_dataset_identifier", columnNames = { "identifier" }),
+ @UniqueConstraint(name = "un_dataset_staIdentifier", columnNames = { "sta_identifier" }),
+ @UniqueConstraint(name = "un_dataset_identity",
+ columnNames = { "fk_procedure_id", "fk_phenomenon_id", "fk_offering_id", "fk_category_id",
+ "fk_feature_id", "fk_platform_id", "fk_unit_id" }) })
+// table comment: Storage of the dataset, the core table of the whole database model.
+@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
+@DiscriminatorColumn(name = "discriminator")
+@AttributeOverride(name = "id", column = @Column(name = "dataset_id"))
+public class AbstractDatasetEntity extends AbstractCodespaceEntity
implements Serializable, HibernateRelations.IsStaEntity, AbstractDatastreamEntity,
StaRelations.HasLicense, StaRelations.HasParty {
@@ -57,35 +120,120 @@ public class AbstractDatasetEntity extends DescribableEntity
public static final String PROPERTY_UNIT = "unit";
public static final String PROPERTY_AGGREGATION = "aggregation";
public static final String PROPERTY_PROJECT = "project";
+ @Serial
private static final long serialVersionUID = 4178505006632345142L;
- private AbstractFeatureEntity> feature;
- private PhenomenonEntity phenomenon;
+ @Temporal(TemporalType.TIMESTAMP) // DELETE THIS LINE if the field is a java.time type
+ @Column(name = "first_time")
+ // @Comment("The timestamp of the temporally first observation that belongs to this dataset.")
+ private Date firstValueAt;
+
+ @Temporal(TemporalType.TIMESTAMP) // DELETE THIS LINE if the field is a java.time type
+ @Column(name = "last_time")
+ // @Comment("The timestamp of the temporally last observation that belongs to this dataset.")
+ private Date lastValueAt;
+
+ @Temporal(TemporalType.TIMESTAMP) // DELETE THIS LINE if the field is a java.time type
+ @Column(name = "result_time_start")
+ // @Comment("The timestamp of the earliest result time of the observations that belong to this dataset.")
+ private Date resultTimeStart;
+
+ @Temporal(TemporalType.TIMESTAMP) // DELETE THIS LINE if the field is a java.time type
+ @Column(name = "result_time_end")
+ // @Comment("The timestamp of the latest result time of the observations that belong to this dataset.")
+ private Date resultTimeEnd;
+
+ @Embedded
+ @AttributeOverride(name = "geometry", column = @Column(name = "observed_area"))
+ private GeometryEntity observedArea;
+
+ @ManyToOne(fetch = FetchType.LAZY, optional = false)
+ @JoinColumn(name = "fk_procedure_id", nullable = false, foreignKey = @ForeignKey(name = "fk_dataset_procedure"))
private ProcedureEntity procedure;
- private CategoryEntity category;
- private UnitEntity unit;
+
+ @ManyToOne(fetch = FetchType.LAZY, optional = false)
+ @JoinColumn(name = "fk_phenomenon_id", nullable = false, foreignKey = @ForeignKey(name = "fk_dataset_phenomenon"))
+ private PhenomenonEntity phenomenon;
+
+ @ManyToOne(fetch = FetchType.LAZY, optional = false)
+ @JoinColumn(name = "fk_offering_id", nullable = false, foreignKey = @ForeignKey(name = "fk_dataset_offering"))
private OfferingEntity offering;
+
+ @ManyToOne(fetch = FetchType.LAZY, optional = false)
+ @JoinColumn(name = "fk_category_id", nullable = false, foreignKey = @ForeignKey(name = "fk_dataset_category"))
+ private CategoryEntity category;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "fk_feature_id", foreignKey = @ForeignKey(name = "fk_dataset_feature"))
+ private AbstractFeatureEntity> feature;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "fk_platform_id", foreignKey = @ForeignKey(name = "fk_dataset_platform"))
private PlatformEntity platform;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "fk_unit_id", foreignKey = @ForeignKey(name = "fk_dataset_unit"))
+ private UnitEntity unit;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "fk_format_id", foreignKey = @ForeignKey(name = "fk_dataset_om_obs_type"))
+ private FormatEntity omObservationType;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "fk_aggregation_id", foreignKey = @ForeignKey(name = "fk_aggregation_id"))
+ private AbstractDatasetEntity aggregation;
+
+ @Column(name = "first_value")
+ // @Comment("The value of the temporally first observation that belongs to this dataset.")
+ private BigDecimal firstQuantityValue;
+
+ @Column(name = "last_value")
+ // @Comment("The value of the temporally last quantity observation that belongs to this dataset.")
+ private BigDecimal lastQuantityValue;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "fk_first_observation_id", foreignKey = @ForeignKey(name = "fk_dataset_first_obs"))
+ private DataEntity> firstObservation;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "fk_last_observation_id", foreignKey = @ForeignKey(name = "fk_dataset_last_obs"))
+ private DataEntity> lastObservation;
+
+ @Transient
private PartyEntity party;
+
+ @Transient
private ProjectEntity project;
+
+ @Transient
private LicenseEntity license;
- private GeometryEntity observedArea;
- private Set resultTimes;
- private Date firstValueAt;
- private Date lastValueAt;
- private DataEntity> firstObservation;
- private DataEntity> lastObservation;
- private BigDecimal firstQuantityValue;
- private BigDecimal lastQuantityValue;
- private Date resultTimeStart;
- private Date resultTimeEnd;
- private FormatEntity omObservationType;
+ @Transient
+ private Set resultTimes;
+ @Transient
private Set> observations;
- private AbstractDatasetEntity aggregation;
+
+ @Transient
private boolean processed;
+ @Override
+ @Access(AccessType.PROPERTY)
+ @OneToMany(targetEntity = DatasetParameterEntity.class, fetch = FetchType.LAZY, cascade = CascadeType.ALL)
+ @JoinColumn(name = "fk_dataset_id", nullable = false, foreignKey = @ForeignKey(name = "fk_param_dataset_id"))
+ @SQLRestriction("fk_parent_parameter_id is null")
+ public Set> getParameters() {
+ return super.getParameters();
+ }
+
+ @Override
+ @Access(AccessType.PROPERTY)
+ @OneToMany(targetEntity = I18nDatasetEntity.class, fetch = FetchType.LAZY, cascade = CascadeType.ALL)
+ @JoinColumn(name = "fk_dataset_id", nullable = false, foreignKey = @ForeignKey(name = "fk_dataset_i18n"))
+ public Set> getTranslations() {
+ return super.getTranslations();
+ }
+
public PhenomenonEntity getPhenomenon() {
return phenomenon;
}
diff --git a/entities/src/main/java/org/n52/series/db/beans/AbstractFeatureEntity.java b/entities/src/main/java/org/n52/series/db/beans/AbstractFeatureEntity.java
index 734c48b2b..714b1e6a3 100644
--- a/entities/src/main/java/org/n52/series/db/beans/AbstractFeatureEntity.java
+++ b/entities/src/main/java/org/n52/series/db/beans/AbstractFeatureEntity.java
@@ -13,21 +13,59 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.n52.series.db.beans;
-import java.util.Objects;
-import java.util.Set;
-import java.util.stream.Collectors;
+package org.n52.series.db.beans;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import jakarta.persistence.Access;
+import jakarta.persistence.AccessType;
+import jakarta.persistence.AttributeOverride;
+import jakarta.persistence.CascadeType;
+import jakarta.persistence.Column;
+import jakarta.persistence.DiscriminatorColumn;
+import jakarta.persistence.Embedded;
+import jakarta.persistence.Entity;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.ForeignKey;
+import jakarta.persistence.Index;
+import jakarta.persistence.Inheritance;
+import jakarta.persistence.InheritanceType;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.OneToMany;
+import jakarta.persistence.Table;
+import jakarta.persistence.Transient;
+import jakarta.persistence.UniqueConstraint;
+import org.hibernate.annotations.SQLRestriction;
import org.locationtech.jts.geom.Geometry;
import org.n52.series.db.beans.HibernateRelations.HasDatasets;
import org.n52.series.db.beans.HibernateRelations.HasGeometry;
import org.n52.series.db.beans.HibernateRelations.HasXml;
import org.n52.series.db.beans.HibernateRelations.IsStaEntity;
+import org.n52.series.db.beans.i18n.I18nEntity;
+import org.n52.series.db.beans.i18n.I18nFeatureEntity;
+import org.n52.series.db.beans.parameter.ParameterEntity;
+import org.n52.series.db.beans.parameter.feature.FeatureParameterEntity;
-import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import java.io.Serial;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
@SuppressFBWarnings({ "EI_EXPOSE_REP", "EI_EXPOSE_REP2" })
+@Entity(name = "org.n52.series.db.beans.AbstractFeatureEntity")
+@Table(name = "feature",
+ indexes = { @Index(name = "idx_feature_format", columnList = "fk_format_id"),
+ @Index(name = "idx_feature_identifier", columnList = "identifier"),
+ @Index(name = "idx_feature_staIdentifier", columnList = "sta_identifier"),
+ @Index(name = "idx_feature_identifier_codespace", columnList = "fk_identifier_codespace_id"),
+ @Index(name = "idx_feature_name_codespace", columnList = "fk_name_codespace_id") },
+ uniqueConstraints = { @UniqueConstraint(name = "un_feature_identifier", columnNames = { "identifier" }),
+ @UniqueConstraint(name = "un_feature_staIdentifier", columnNames = { "sta_identifier" }),
+ @UniqueConstraint(name = "un_feature_url", columnNames = { "url" }) })
+@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
+@DiscriminatorColumn(name = "discriminator")
+@AttributeOverride(name = "id", column = @Column(name = "feature_id"))
public abstract class AbstractFeatureEntity extends HierarchicalEntity
implements HasXml, HasGeometry, HasDatasets, IsStaEntity {
@@ -38,14 +76,49 @@ public abstract class AbstractFeatureEntity extends HierarchicalEntity
public static final String PROPERTY_GEOMETRY_ENTITY_LON = PROPERTY_GEOMETRY_ENTITY + ".lon";
public static final String PROPERTY_FEATURE_TYPE = "featureType";
+ @Serial
private static final long serialVersionUID = 6712642995944229067L;
- private GeometryEntity geometryEntity;
+
+ @ManyToOne(fetch = FetchType.LAZY, optional = false)
+ @JoinColumn(name = "fk_format_id", nullable = false, foreignKey = @ForeignKey(name = "fk_feature_format"))
private FormatEntity featureType;
- private String url;
+
+ @Column(name = "xml", columnDefinition = "text")
+ // @Comment("The XML encoded representation of the feature.")
private String xml;
+
+ @Column(name = "url")
+ // @Comment("Optional URL to an external resource that describes the feature, e.g. a WFS")
+ private String url;
+
+ @Embedded
+ @AttributeOverride(name = "geometry", column = @Column(name = "geom"))
+ private GeometryEntity geometryEntity;
+
+ @OneToMany(mappedBy = DatasetEntity.PROPERTY_FEATURE, fetch = FetchType.LAZY, cascade = CascadeType.ALL,
+ orphanRemoval = true)
private Set datasets;
+
+ @Transient
private Set> observations;
+ @Override
+ @Access(AccessType.PROPERTY)
+ @OneToMany(targetEntity = FeatureParameterEntity.class, fetch = FetchType.LAZY, cascade = CascadeType.ALL)
+ @JoinColumn(name = "fk_feature_id", nullable = false, foreignKey = @ForeignKey(name = "fk_param_feature_id"))
+ @SQLRestriction("fk_parent_parameter_id is null")
+ public Set> getParameters() {
+ return super.getParameters();
+ }
+
+ @Override
+ @Access(AccessType.PROPERTY)
+ @OneToMany(targetEntity = I18nFeatureEntity.class, fetch = FetchType.LAZY, cascade = CascadeType.ALL)
+ @JoinColumn(name = "fk_feature_id", nullable = false, foreignKey = @ForeignKey(name = "fk_feature"))
+ public Set> getTranslations() {
+ return super.getTranslations();
+ }
+
@Override
public GeometryEntity getGeometryEntity() {
return geometryEntity;
@@ -126,7 +199,7 @@ public int hashCode() {
@Override
public boolean equals(Object obj) {
- return obj instanceof AbstractFeatureEntity && super.equals(obj)
- && Objects.hash(observations) == Objects.hash(((AbstractFeatureEntity) obj).getObservations());
+ return obj instanceof AbstractFeatureEntity afe && super.equals(obj)
+ && Objects.hash(observations) == Objects.hash(afe.getObservations());
}
}
diff --git a/entities/src/main/java/org/n52/series/db/beans/AbstractRelationEntity.java b/entities/src/main/java/org/n52/series/db/beans/AbstractRelationEntity.java
index 66b0d0a11..3c85677de 100644
--- a/entities/src/main/java/org/n52/series/db/beans/AbstractRelationEntity.java
+++ b/entities/src/main/java/org/n52/series/db/beans/AbstractRelationEntity.java
@@ -15,50 +15,46 @@
*/
package org.n52.series.db.beans;
-public abstract class AbstractRelationEntity extends IdEntity {
+import jakarta.persistence.Column;
+import jakarta.persistence.MappedSuperclass;
- public static final String PROPERTY_ITEM = "item";
- public static final String PROPERTY_RELATED_ITEM = "relatedItem";
-
- private static final long serialVersionUID = -2573767006446257428L;
+import java.io.Serial;
- private T item;
+@MappedSuperclass
+public abstract class AbstractRelationEntity {
- private T relatedItem;
+ public static final String PROPERTY_ITEM = "item";
+ public static final String PROPERTY_RELATED_ITEM = "relatedItem";
+ @Column(name = "role")
+ // @Comment("Definition of the role of the relation")
private String role;
+ @Column(name = "url")
+ // @Comment("URL that point to external information")
private String relatedUrl;
/**
* @return the item
*/
- public T getItem() {
- return item;
- }
+ public abstract T getItem();
/**
* @param item
* the item to set
*/
- public void setItem(T item) {
- this.item = item;
- }
+ public abstract void setItem(T item);
/**
* @return the relatedItem
*/
- public T getRelatedItem() {
- return relatedItem;
- }
+ public abstract T getRelatedItem();
/**
* @param relatedItem
* the relatedItem to set
*/
- public void setRelatedItem(T relatedItem) {
- this.relatedItem = relatedItem;
- }
+ public abstract void setRelatedItem(T relatedItem);
/**
* @return the role
diff --git a/entities/src/main/java/org/n52/series/db/beans/AssessmentTypeEntity.java b/entities/src/main/java/org/n52/series/db/beans/AssessmentTypeEntity.java
index 9e439c033..6ba5d5cdb 100644
--- a/entities/src/main/java/org/n52/series/db/beans/AssessmentTypeEntity.java
+++ b/entities/src/main/java/org/n52/series/db/beans/AssessmentTypeEntity.java
@@ -15,6 +15,7 @@
*/
package org.n52.series.db.beans;
+import java.io.Serial;
import java.io.Serializable;
public class AssessmentTypeEntity implements Serializable {
@@ -23,6 +24,7 @@ public class AssessmentTypeEntity implements Serializable {
public static final String PROPERTY_ASSESSMENT_TYPE = PROPERTY_ID;
+ @Serial
private static final long serialVersionUID = 1721670905098408954L;
private String assessmentType;
diff --git a/entities/src/main/java/org/n52/series/db/beans/BlobDataEntity.java b/entities/src/main/java/org/n52/series/db/beans/BlobDataEntity.java
index 2f4f5c4fd..8be7fbf9d 100644
--- a/entities/src/main/java/org/n52/series/db/beans/BlobDataEntity.java
+++ b/entities/src/main/java/org/n52/series/db/beans/BlobDataEntity.java
@@ -15,14 +15,46 @@
*/
package org.n52.series.db.beans;
+import jakarta.persistence.Column;
+import jakarta.persistence.DiscriminatorValue;
+import jakarta.persistence.Entity;
+import jakarta.persistence.ForeignKey;
+import jakarta.persistence.Lob;
+import jakarta.persistence.PrimaryKeyJoinColumn;
+import jakarta.persistence.SecondaryTable;
+import jakarta.persistence.Transient;
+
+import java.io.Serial;
import java.util.Collection;
+@Entity(name = "org.n52.series.db.beans.BlobDataEntity")
+// @SecondaryTable(name = "value_blob",
+// pkJoinColumns = @PrimaryKeyJoinColumn(name = "fk_observation_id",
+// foreignKey = @ForeignKey(name = "fk_blob_value")))
+@DiscriminatorValue("blob")
public class BlobDataEntity extends DataEntity