Skip to content

Commit 2df782c

Browse files
dfcoffinclaude
andauthored
feat: ESPI 4.0 Schema Compliance - Phase 4: ReadingQuality (#69)
This commit implements Phase 4 of ESPI 4.0 schema compliance, updating ReadingQuality to match the ESPI 4.0 XSD specification (espi.xsd:1062). Key Changes: ReadingQualityEntity: - Changed ID from UUID to Long (48+ bits) per Object pattern - ReadingQuality extends Object, not IdentifiedObject - Updated @GeneratedValue to use IDENTITY strategy - Removed UUID-related imports (JdbcTypeCode, SqlTypes) - Field order already correct (only has quality field per XSD) ReadingQualityDto: - Already compliant - no changes needed - Single quality field matches XSD specification ReadingQualityMapper: - Simplified mappings (MapStruct handles by name) - Removed explicit quality field mapping - Kept only necessary ignore mappings (id, intervalReading) Flyway Migrations: - Moved reading_qualities table from V3 to V2 vendor-specific files - Rationale: ReadingQuality requires vendor-specific auto-increment syntax (BIGINT AUTO_INCREMENT for MySQL/H2, BIGSERIAL for PostgreSQL) - Removed all IdentifiedObject fields (description, created, updated, published, links) from table structure - Updated V3 header to document reading_qualities relocation - Added to dependency chain: meter_readings → interval_blocks → interval_readings → reading_qualities Test Results: - All 550 tests passing including integration tests - PostgreSQL TestContainer integration tests: ✅ - MySQL TestContainer integration tests: ✅ - H2 in-memory integration tests: ✅ Migration Strategy: - V1: Base vendor-neutral tables - V2: Vendor-specific tables (now includes meter_readings, interval_blocks, interval_readings, reading_qualities with correct auto-increment syntax) - V3: Additional tables that depend on V1 and V2 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Sonnet 4.5 <[email protected]>
1 parent b9127e2 commit 2df782c

File tree

6 files changed

+76
-46
lines changed

6 files changed

+76
-46
lines changed

openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/usage/ReadingQualityEntity.java

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,9 @@
2525
import lombok.Getter;
2626
import lombok.NoArgsConstructor;
2727
import lombok.Setter;
28-
import org.hibernate.annotations.JdbcTypeCode;
2928
import org.hibernate.proxy.HibernateProxy;
30-
import org.hibernate.type.SqlTypes;
3129

3230
import java.util.Objects;
33-
import java.util.UUID;
3431

3532
/**
3633
* Pure JPA/Hibernate entity for ReadingQuality without JAXB concerns.
@@ -55,13 +52,13 @@
5552
public class ReadingQualityEntity {
5653

5754
/**
58-
* Primary key identifier.
55+
* Primary key identifier (48+ bits as per ESPI requirement).
56+
* ReadingQuality extends Object (not IdentifiedObject) per ESPI 4.0 XSD.
5957
*/
6058
@Id
61-
@GeneratedValue(strategy = GenerationType.UUID)
62-
@JdbcTypeCode(SqlTypes.CHAR)
63-
@Column(length = 36, columnDefinition = "char(36)", updatable = false, nullable = false)
64-
private UUID id;
59+
@GeneratedValue(strategy = GenerationType.IDENTITY)
60+
@Column(name = "id")
61+
private Long id;
6562

6663
// Quality constants based on common industry standards
6764
public static final String QUALITY_GOOD = "GOOD";

openespi-common/src/main/java/org/greenbuttonalliance/espi/common/mapper/usage/ReadingQualityMapper.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,18 +41,16 @@ public interface ReadingQualityMapper {
4141
* @param entity the reading quality entity
4242
* @return the reading quality DTO
4343
*/
44-
@Mapping(target = "quality", source = "quality")
4544
ReadingQualityDto toDto(ReadingQualityEntity entity);
4645

4746
/**
4847
* Converts a ReadingQualityDto to a ReadingQualityEntity.
49-
* Maps quality indicators and validation information.
48+
* The ID is generated by the database, and intervalReading is set by the parent.
5049
*
5150
* @param dto the reading quality DTO
5251
* @return the reading quality entity
5352
*/
5453
@Mapping(target = "id", ignore = true)
55-
@Mapping(target = "quality", source = "quality")
5654
@Mapping(target = "intervalReading", ignore = true)
5755
ReadingQualityEntity toEntity(ReadingQualityDto dto);
5856

openespi-common/src/main/resources/db/migration/V3__Create_additiional_Base_Tables.sql

Lines changed: 12 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@
1717
* - interval_blocks (depends on meter_readings)
1818
* - interval_block_related_links (FK dependency)
1919
* - interval_readings (extends Object, requires vendor-specific auto-increment, depends on interval_blocks)
20+
* - reading_qualities (extends Object, requires vendor-specific auto-increment, depends on interval_readings)
2021
*
21-
* Reason: IntervalReading extends Object (not IdentifiedObject) per ESPI 4.0 XSD (espi.xsd:1016),
22-
* requiring Long ID with vendor-specific auto-increment syntax (BIGINT AUTO_INCREMENT for MySQL/H2,
23-
* BIGSERIAL for PostgreSQL). To keep the dependency chain together (meter_readings → interval_blocks
24-
* interval_readings), all three were moved to V2 vendor files.
22+
* Reason: IntervalReading and ReadingQuality both extend Object (not IdentifiedObject) per ESPI 4.0 XSD
23+
* (espi.xsd:1016 and espi.xsd:1062), requiring Long ID with vendor-specific auto-increment syntax
24+
* (BIGINT AUTO_INCREMENT for MySQL/H2, BIGSERIAL for PostgreSQL). To keep the dependency chain together
25+
* (meter_readings → interval_blocks → interval_readings → reading_qualities), all were moved to V2 vendor files.
2526
*
2627
* Tables in this migration:
27-
* - reading_qualities (depends on interval_readings from V2)
2828
* - usage_summaries (depends on usage_points from V2)
2929
* - usage_summary_related_links (FK dependency)
3030
* - subscription_usage_points (join table)
@@ -49,40 +49,17 @@
4949
-- 1. meter_readings + meter_reading_related_links
5050
-- 2. interval_blocks + interval_block_related_links
5151
-- 3. interval_readings (no related_links - extends Object, not IdentifiedObject)
52+
-- 4. reading_qualities (no related_links - extends Object, not IdentifiedObject)
5253
--
5354
-- See file header for detailed explanation.
5455
-- ==================================================================================
5556

56-
-- Reading Quality Table
57-
CREATE TABLE reading_qualities
58-
(
59-
id CHAR(36) PRIMARY KEY ,
60-
description VARCHAR(255),
61-
created TIMESTAMP NOT NULL,
62-
updated TIMESTAMP NOT NULL,
63-
published TIMESTAMP,
64-
up_link_rel VARCHAR(255),
65-
up_link_href VARCHAR(1024),
66-
up_link_type VARCHAR(255),
67-
self_link_rel VARCHAR(255),
68-
self_link_href VARCHAR(1024),
69-
self_link_type VARCHAR(255),
70-
71-
-- Reading quality specific fields
72-
quality VARCHAR(50),
73-
74-
-- Foreign key relationships
75-
-- IntervalReading uses Long ID (BIGINT/BIGSERIAL) as it extends Object, not IdentifiedObject
76-
interval_reading_id BIGINT,
77-
78-
FOREIGN KEY (interval_reading_id) REFERENCES interval_readings (id) ON DELETE CASCADE
79-
);
80-
81-
-- Indexes for reading_qualities table
82-
CREATE INDEX idx_reading_quality_interval_reading_id ON reading_qualities (interval_reading_id);
83-
CREATE INDEX idx_reading_quality_quality ON reading_qualities (quality);
84-
CREATE INDEX idx_reading_quality_created ON reading_qualities (created);
85-
CREATE INDEX idx_reading_quality_updated ON reading_qualities (updated);
57+
-- Reading Quality Table - Moved to vendor-specific V2 migration files
58+
-- ReadingQuality extends Object (not IdentifiedObject) per ESPI 4.0 XSD (espi.xsd:1062)
59+
-- Table creation moved to V2 vendor files due to auto-increment syntax differences
60+
-- See: db/vendor/mysql/V2__MySQL_Specific_Tables.sql
61+
-- db/vendor/postgres/V2__PostgreSQL_Specific_Tables.sql
62+
-- db/vendor/h2/V2__H2_Specific_Tables.sql
8663

8764
-- Usage Summary Table
8865
CREATE TABLE usage_summaries

openespi-common/src/main/resources/db/vendor/h2/V2__H2_Specific_Tables.sql

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,3 +291,23 @@ CREATE TABLE interval_readings
291291
CREATE INDEX idx_interval_reading_block_id ON interval_readings (interval_block_id);
292292
CREATE INDEX idx_interval_reading_time_start ON interval_readings (time_period_start);
293293
CREATE INDEX idx_interval_reading_value ON interval_readings (reading_value);
294+
295+
-- Reading Quality Table (Object-based entity, no IdentifiedObject)
296+
-- ReadingQuality extends Object per ESPI 4.0 XSD (espi.xsd:1062)
297+
-- XSD sequence: quality
298+
CREATE TABLE reading_qualities
299+
(
300+
id BIGINT AUTO_INCREMENT PRIMARY KEY,
301+
302+
-- ESPI 4.0 field
303+
quality VARCHAR(50) NOT NULL,
304+
305+
-- Foreign key relationship (parent: IntervalReading)
306+
interval_reading_id BIGINT,
307+
308+
FOREIGN KEY (interval_reading_id) REFERENCES interval_readings (id) ON DELETE CASCADE
309+
);
310+
311+
-- Create indexes for reading_qualities table
312+
CREATE INDEX idx_reading_quality_interval_reading_id ON reading_qualities (interval_reading_id);
313+
CREATE INDEX idx_reading_quality_quality ON reading_qualities (quality);

openespi-common/src/main/resources/db/vendor/mysql/V2__MySQL_Specific_Tables.sql

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,3 +295,22 @@ CREATE TABLE interval_readings
295295
INDEX idx_interval_reading_time_start (time_period_start),
296296
INDEX idx_interval_reading_value (reading_value)
297297
);
298+
299+
-- Reading Quality Table (Object-based entity, no IdentifiedObject)
300+
-- ReadingQuality extends Object per ESPI 4.0 XSD (espi.xsd:1062)
301+
-- XSD sequence: quality
302+
CREATE TABLE reading_qualities
303+
(
304+
id BIGINT AUTO_INCREMENT PRIMARY KEY,
305+
306+
-- ESPI 4.0 field
307+
quality VARCHAR(50) NOT NULL,
308+
309+
-- Foreign key relationship (parent: IntervalReading)
310+
interval_reading_id BIGINT,
311+
312+
FOREIGN KEY (interval_reading_id) REFERENCES interval_readings (id) ON DELETE CASCADE,
313+
314+
INDEX idx_reading_quality_interval_reading_id (interval_reading_id),
315+
INDEX idx_reading_quality_quality (quality)
316+
);

openespi-common/src/main/resources/db/vendor/postgres/V2__PostgreSQL_Specific_Tables.sql

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,3 +283,22 @@ CREATE TABLE interval_readings
283283
CREATE INDEX idx_interval_reading_block_id ON interval_readings (interval_block_id);
284284
CREATE INDEX idx_interval_reading_time_start ON interval_readings (time_period_start);
285285
CREATE INDEX idx_interval_reading_value ON interval_readings (reading_value);
286+
287+
-- Reading Quality Table (Object-based entity, no IdentifiedObject)
288+
-- ReadingQuality extends Object per ESPI 4.0 XSD (espi.xsd:1062)
289+
-- XSD sequence: quality
290+
CREATE TABLE reading_qualities
291+
(
292+
id BIGSERIAL PRIMARY KEY,
293+
294+
-- ESPI 4.0 field
295+
quality VARCHAR(50) NOT NULL,
296+
297+
-- Foreign key relationship (parent: IntervalReading)
298+
interval_reading_id BIGINT,
299+
300+
FOREIGN KEY (interval_reading_id) REFERENCES interval_readings (id) ON DELETE CASCADE
301+
);
302+
303+
CREATE INDEX idx_reading_quality_interval_reading_id ON reading_qualities (interval_reading_id);
304+
CREATE INDEX idx_reading_quality_quality ON reading_qualities (quality);

0 commit comments

Comments
 (0)