Skip to content

Commit 041a213

Browse files
dfcoffinclaude
andauthored
refactor: Phase 8 - PnodeRef ESPI 4.0 schema compliance (#74)
Per ESPI 4.0 specification, PnodeRef extends Object (not IdentifiedObject), so it has NO Atom metadata fields. This phase aligns the mapper, repository, and tests with the XSD definition. Entity and DTO were already compliant. Changes: - PnodeRefMapper: Remove updateEntity method (read-only operations) - PnodeRefMapper: Remove MappingTarget import - PnodeRefRepository: Keep only indexed queries (findAllIds, findAllByUsagePointId) - PnodeRefRepository: Remove 9 non-indexed custom queries - PnodeRefRepository: Remove unused UsagePointEntity import - PnodeRefRepositoryTest: Add test for findAllIds() - PnodeRefRepositoryTest: Update test for renamed findAllByUsagePointId - PnodeRefRepositoryTest: Remove 9 tests for deleted queries All 529 tests pass. Entity and DTO already match XSD structure correctly. Co-authored-by: Claude Sonnet 4.5 <[email protected]>
1 parent 406b3c0 commit 041a213

File tree

3 files changed

+17
-290
lines changed

3 files changed

+17
-290
lines changed

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

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
import org.greenbuttonalliance.espi.common.dto.usage.PnodeRefDto;
2424
import org.mapstruct.Mapper;
2525
import org.mapstruct.Mapping;
26-
import org.mapstruct.MappingTarget;
2726

2827
/**
2928
* MapStruct mapper for converting between PnodeRefEntity and PnodeRefDto.
@@ -60,13 +59,4 @@ public interface PnodeRefMapper {
6059
@Mapping(target = "endEffectiveDate", source = "endEffectiveDate")
6160
PnodeRefEntity toEntity(PnodeRefDto dto);
6261

63-
/**
64-
* Updates an existing PnodeRefEntity with data from a PnodeRefDto.
65-
*
66-
* @param dto the source DTO
67-
* @param entity the target entity to update
68-
*/
69-
@Mapping(target = "id", ignore = true)
70-
@Mapping(target = "usagePoint", ignore = true)
71-
void updateEntity(PnodeRefDto dto, @MappingTarget PnodeRefEntity entity);
7262
}

openespi-common/src/main/java/org/greenbuttonalliance/espi/common/repositories/usage/PnodeRefRepository.java

Lines changed: 4 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
package org.greenbuttonalliance.espi.common.repositories.usage;
2121

2222
import org.greenbuttonalliance.espi.common.domain.usage.PnodeRefEntity;
23-
import org.greenbuttonalliance.espi.common.domain.usage.UsagePointEntity;
2423
import org.springframework.data.jpa.repository.JpaRepository;
2524
import org.springframework.data.jpa.repository.Query;
2625
import org.springframework.data.repository.query.Param;
@@ -34,92 +33,13 @@
3433
* <p>
3534
* PnodeRef extends Object (not IdentifiedObject) in ESPI 4.0 XSD,
3635
* so it uses Long ID (not UUID).
37-
* <p>
38-
* Provides CRUD operations and custom queries for pricing node references.
3936
*/
4037
@Repository
4138
public interface PnodeRefRepository extends JpaRepository<PnodeRefEntity, Long> {
4239

43-
/**
44-
* Find all pricing node references for a specific usage point.
45-
*
46-
* @param usagePoint the usage point
47-
* @return list of pricing node references
48-
*/
49-
List<PnodeRefEntity> findByUsagePoint(UsagePointEntity usagePoint);
50-
51-
/**
52-
* Find pricing node references by usage point ID.
53-
*
54-
* @param usagePointId the usage point ID (UUID for UsagePoint which extends IdentifiedObject)
55-
* @return list of pricing node references
56-
*/
57-
List<PnodeRefEntity> findByUsagePointId(UUID usagePointId);
58-
59-
/**
60-
* Find pricing node references by type.
61-
*
62-
* @param apnodeType the pricing node type
63-
* @return list of pricing node references
64-
*/
65-
List<PnodeRefEntity> findByApnodeType(String apnodeType);
66-
67-
/**
68-
* Find pricing node references by usage point and type.
69-
*
70-
* @param usagePoint the usage point
71-
* @param apnodeType the pricing node type
72-
* @return list of pricing node references
73-
*/
74-
List<PnodeRefEntity> findByUsagePointAndApnodeType(UsagePointEntity usagePoint, String apnodeType);
75-
76-
/**
77-
* Find pricing node references by reference identifier.
78-
*
79-
* @param ref the reference identifier
80-
* @return list of pricing node references
81-
*/
82-
List<PnodeRefEntity> findByRef(String ref);
83-
84-
/**
85-
* Find currently valid pricing node references for a usage point.
86-
*
87-
* @param usagePointId the usage point ID
88-
* @param currentTime current time in epoch seconds
89-
* @return list of valid pricing node references
90-
*/
91-
@Query("SELECT p FROM PnodeRefEntity p WHERE p.usagePoint.id = :usagePointId " +
92-
"AND (p.startEffectiveDate IS NULL OR p.startEffectiveDate <= :currentTime) " +
93-
"AND (p.endEffectiveDate IS NULL OR p.endEffectiveDate >= :currentTime)")
94-
List<PnodeRefEntity> findValidByUsagePointId(@Param("usagePointId") UUID usagePointId,
95-
@Param("currentTime") Long currentTime);
96-
97-
/**
98-
* Find currently valid pricing node references by type.
99-
*
100-
* @param apnodeType the pricing node type
101-
* @param currentTime current time in epoch seconds
102-
* @return list of valid pricing node references
103-
*/
104-
@Query("SELECT p FROM PnodeRefEntity p WHERE p.apnodeType = :apnodeType " +
105-
"AND (p.startEffectiveDate IS NULL OR p.startEffectiveDate <= :currentTime) " +
106-
"AND (p.endEffectiveDate IS NULL OR p.endEffectiveDate >= :currentTime)")
107-
List<PnodeRefEntity> findValidByApnodeType(@Param("apnodeType") String apnodeType,
108-
@Param("currentTime") Long currentTime);
109-
110-
/**
111-
* Delete all pricing node references for a usage point.
112-
*
113-
* @param usagePoint the usage point
114-
* @return number of deleted records
115-
*/
116-
Long deleteByUsagePoint(UsagePointEntity usagePoint);
40+
@Query("SELECT p.id FROM PnodeRefEntity p")
41+
List<Long> findAllIds();
11742

118-
/**
119-
* Delete pricing node references by usage point ID.
120-
*
121-
* @param usagePointId the usage point ID
122-
* @return number of deleted records
123-
*/
124-
Long deleteByUsagePointId(UUID usagePointId);
43+
@Query("SELECT p FROM PnodeRefEntity p WHERE p.usagePoint.id = :usagePointId")
44+
List<PnodeRefEntity> findAllByUsagePointId(@Param("usagePointId") UUID usagePointId);
12545
}

openespi-common/src/test/java/org/greenbuttonalliance/espi/common/repositories/usage/PnodeRefRepositoryTest.java

Lines changed: 13 additions & 196 deletions
Original file line numberDiff line numberDiff line change
@@ -112,235 +112,52 @@ void shouldSavePricingNodeRefWithEffectiveDates() {
112112
class CustomQueryMethodsTest {
113113

114114
@Test
115-
@DisplayName("Should find pricing node refs by usage point")
116-
void shouldFindPricingNodeRefsByUsagePoint() {
115+
@DisplayName("Should find all IDs")
116+
void shouldFindAllIds() {
117117
// Arrange
118118
UsagePointEntity usagePoint = TestDataBuilders.createValidUsagePoint();
119119
UsagePointEntity savedUsagePoint = usagePointRepository.save(usagePoint);
120-
120+
121121
PnodeRefEntity pnodeRef1 = new PnodeRefEntity("HUB", "HUB_1", savedUsagePoint);
122122
PnodeRefEntity pnodeRef2 = new PnodeRefEntity("LOAD_ZONE", "ZONE_1", savedUsagePoint);
123-
124-
pnodeRefRepository.save(pnodeRef1);
125-
pnodeRefRepository.save(pnodeRef2);
123+
124+
PnodeRefEntity saved1 = pnodeRefRepository.save(pnodeRef1);
125+
PnodeRefEntity saved2 = pnodeRefRepository.save(pnodeRef2);
126126
flushAndClear();
127127

128128
// Act
129-
List<PnodeRefEntity> pnodeRefs = pnodeRefRepository.findByUsagePoint(savedUsagePoint);
129+
List<Long> allIds = pnodeRefRepository.findAllIds();
130130

131131
// Assert
132-
assertThat(pnodeRefs).hasSize(2);
133-
assertThat(pnodeRefs).extracting(PnodeRefEntity::getRef)
134-
.containsExactlyInAnyOrder("HUB_1", "ZONE_1");
132+
assertThat(allIds).contains(saved1.getId(), saved2.getId());
135133
}
136134

137135
@Test
138-
@DisplayName("Should find pricing node refs by usage point ID")
139-
void shouldFindPricingNodeRefsByUsagePointId() {
136+
@DisplayName("Should find all pricing node refs by usage point ID")
137+
void shouldFindAllPricingNodeRefsByUsagePointId() {
140138
// Arrange
141139
UsagePointEntity usagePoint1 = TestDataBuilders.createValidUsagePoint();
142140
UsagePointEntity usagePoint2 = TestDataBuilders.createValidUsagePoint();
143141
UsagePointEntity savedUsagePoint1 = usagePointRepository.save(usagePoint1);
144142
UsagePointEntity savedUsagePoint2 = usagePointRepository.save(usagePoint2);
145-
143+
146144
PnodeRefEntity pnodeRef1 = new PnodeRefEntity("HUB", "HUB_1", savedUsagePoint1);
147145
PnodeRefEntity pnodeRef2 = new PnodeRefEntity("HUB", "HUB_2", savedUsagePoint1);
148146
PnodeRefEntity pnodeRef3 = new PnodeRefEntity("HUB", "HUB_3", savedUsagePoint2);
149-
147+
150148
pnodeRefRepository.save(pnodeRef1);
151149
pnodeRefRepository.save(pnodeRef2);
152150
pnodeRefRepository.save(pnodeRef3);
153151
flushAndClear();
154152

155153
// Act
156-
List<PnodeRefEntity> pnodeRefs = pnodeRefRepository.findByUsagePointId(savedUsagePoint1.getId());
154+
List<PnodeRefEntity> pnodeRefs = pnodeRefRepository.findAllByUsagePointId(savedUsagePoint1.getId());
157155

158156
// Assert
159157
assertThat(pnodeRefs).hasSize(2);
160158
assertThat(pnodeRefs).extracting(PnodeRefEntity::getRef)
161159
.containsExactlyInAnyOrder("HUB_1", "HUB_2");
162160
}
163-
164-
@Test
165-
@DisplayName("Should find pricing node refs by apnode type")
166-
void shouldFindPricingNodeRefsByApnodeType() {
167-
// Arrange
168-
UsagePointEntity usagePoint = TestDataBuilders.createValidUsagePoint();
169-
UsagePointEntity savedUsagePoint = usagePointRepository.save(usagePoint);
170-
171-
PnodeRefEntity pnodeRef1 = new PnodeRefEntity("HUB", "HUB_1", savedUsagePoint);
172-
PnodeRefEntity pnodeRef2 = new PnodeRefEntity("HUB", "HUB_2", savedUsagePoint);
173-
PnodeRefEntity pnodeRef3 = new PnodeRefEntity("LOAD_ZONE", "ZONE_1", savedUsagePoint);
174-
175-
pnodeRefRepository.save(pnodeRef1);
176-
pnodeRefRepository.save(pnodeRef2);
177-
pnodeRefRepository.save(pnodeRef3);
178-
flushAndClear();
179-
180-
// Act
181-
List<PnodeRefEntity> hubRefs = pnodeRefRepository.findByApnodeType("HUB");
182-
183-
// Assert
184-
assertThat(hubRefs).hasSize(2);
185-
assertThat(hubRefs).extracting(PnodeRefEntity::getRef)
186-
.containsExactlyInAnyOrder("HUB_1", "HUB_2");
187-
}
188-
189-
@Test
190-
@DisplayName("Should find pricing node refs by usage point and apnode type")
191-
void shouldFindPricingNodeRefsByUsagePointAndApnodeType() {
192-
// Arrange
193-
UsagePointEntity usagePoint = TestDataBuilders.createValidUsagePoint();
194-
UsagePointEntity savedUsagePoint = usagePointRepository.save(usagePoint);
195-
196-
PnodeRefEntity pnodeRef1 = new PnodeRefEntity("HUB", "HUB_1", savedUsagePoint);
197-
PnodeRefEntity pnodeRef2 = new PnodeRefEntity("LOAD_ZONE", "ZONE_1", savedUsagePoint);
198-
199-
pnodeRefRepository.save(pnodeRef1);
200-
pnodeRefRepository.save(pnodeRef2);
201-
flushAndClear();
202-
203-
// Act
204-
List<PnodeRefEntity> hubRefs = pnodeRefRepository.findByUsagePointAndApnodeType(savedUsagePoint, "HUB");
205-
206-
// Assert
207-
assertThat(hubRefs).hasSize(1);
208-
assertThat(hubRefs.get(0).getRef()).isEqualTo("HUB_1");
209-
}
210-
211-
@Test
212-
@DisplayName("Should find pricing node refs by ref")
213-
void shouldFindPricingNodeRefsByRef() {
214-
// Arrange
215-
UsagePointEntity usagePoint = TestDataBuilders.createValidUsagePoint();
216-
UsagePointEntity savedUsagePoint = usagePointRepository.save(usagePoint);
217-
218-
PnodeRefEntity pnodeRef1 = new PnodeRefEntity("HUB", "UNIQUE_HUB", savedUsagePoint);
219-
PnodeRefEntity pnodeRef2 = new PnodeRefEntity("LOAD_ZONE", "COMMON_REF", savedUsagePoint);
220-
221-
pnodeRefRepository.save(pnodeRef1);
222-
pnodeRefRepository.save(pnodeRef2);
223-
flushAndClear();
224-
225-
// Act
226-
List<PnodeRefEntity> refs = pnodeRefRepository.findByRef("UNIQUE_HUB");
227-
228-
// Assert
229-
assertThat(refs).hasSize(1);
230-
assertThat(refs.get(0).getApnodeType()).isEqualTo("HUB");
231-
}
232-
233-
@Test
234-
@DisplayName("Should find valid pricing node refs by usage point ID")
235-
void shouldFindValidPricingNodeRefsByUsagePointId() {
236-
// Arrange
237-
UsagePointEntity usagePoint = TestDataBuilders.createValidUsagePoint();
238-
UsagePointEntity savedUsagePoint = usagePointRepository.save(usagePoint);
239-
240-
long currentTime = System.currentTimeMillis() / 1000;
241-
long pastTime = currentTime - 3600; // 1 hour ago
242-
long futureTime = currentTime + 3600; // 1 hour from now
243-
244-
// Valid: no dates set (always valid)
245-
PnodeRefEntity validRef1 = new PnodeRefEntity("HUB", "ALWAYS_VALID", savedUsagePoint);
246-
247-
// Valid: started in past, no end date
248-
PnodeRefEntity validRef2 = new PnodeRefEntity("HUB", "STARTED_VALID", pastTime, null, savedUsagePoint);
249-
250-
// Invalid: starts in future
251-
PnodeRefEntity invalidRef = new PnodeRefEntity("HUB", "FUTURE_START", futureTime, null, savedUsagePoint);
252-
253-
pnodeRefRepository.save(validRef1);
254-
pnodeRefRepository.save(validRef2);
255-
pnodeRefRepository.save(invalidRef);
256-
flushAndClear();
257-
258-
// Act
259-
List<PnodeRefEntity> validRefs = pnodeRefRepository.findValidByUsagePointId(savedUsagePoint.getId(), currentTime);
260-
261-
// Assert
262-
assertThat(validRefs).hasSize(2);
263-
assertThat(validRefs).extracting(PnodeRefEntity::getRef)
264-
.containsExactlyInAnyOrder("ALWAYS_VALID", "STARTED_VALID");
265-
}
266-
267-
@Test
268-
@DisplayName("Should find valid pricing node refs by apnode type")
269-
void shouldFindValidPricingNodeRefsByApnodeType() {
270-
// Arrange
271-
UsagePointEntity usagePoint = TestDataBuilders.createValidUsagePoint();
272-
UsagePointEntity savedUsagePoint = usagePointRepository.save(usagePoint);
273-
274-
long currentTime = System.currentTimeMillis() / 1000;
275-
long pastTime = currentTime - 3600; // 1 hour ago
276-
long futureTime = currentTime + 3600; // 1 hour from now
277-
278-
// Valid HUB
279-
PnodeRefEntity validHub = new PnodeRefEntity("HUB", "VALID_HUB", pastTime, futureTime, savedUsagePoint);
280-
281-
// Invalid HUB (expired)
282-
PnodeRefEntity expiredHub = new PnodeRefEntity("HUB", "EXPIRED_HUB", pastTime, pastTime + 1800, savedUsagePoint);
283-
284-
// Valid LOAD_ZONE
285-
PnodeRefEntity validZone = new PnodeRefEntity("LOAD_ZONE", "VALID_ZONE", savedUsagePoint);
286-
287-
pnodeRefRepository.save(validHub);
288-
pnodeRefRepository.save(expiredHub);
289-
pnodeRefRepository.save(validZone);
290-
flushAndClear();
291-
292-
// Act
293-
List<PnodeRefEntity> validHubs = pnodeRefRepository.findValidByApnodeType("HUB", currentTime);
294-
295-
// Assert
296-
assertThat(validHubs).hasSize(1);
297-
assertThat(validHubs.get(0).getRef()).isEqualTo("VALID_HUB");
298-
}
299-
300-
@Test
301-
@DisplayName("Should delete pricing node refs by usage point")
302-
void shouldDeletePricingNodeRefsByUsagePoint() {
303-
// Arrange
304-
UsagePointEntity usagePoint = TestDataBuilders.createValidUsagePoint();
305-
UsagePointEntity savedUsagePoint = usagePointRepository.save(usagePoint);
306-
307-
PnodeRefEntity pnodeRef1 = new PnodeRefEntity("HUB", "HUB_1", savedUsagePoint);
308-
PnodeRefEntity pnodeRef2 = new PnodeRefEntity("HUB", "HUB_2", savedUsagePoint);
309-
310-
pnodeRefRepository.save(pnodeRef1);
311-
pnodeRefRepository.save(pnodeRef2);
312-
flushAndClear();
313-
314-
// Act
315-
Long deletedCount = pnodeRefRepository.deleteByUsagePoint(savedUsagePoint);
316-
flushAndClear();
317-
318-
// Assert
319-
assertThat(deletedCount).isEqualTo(2L);
320-
List<PnodeRefEntity> remainingRefs = pnodeRefRepository.findByUsagePoint(savedUsagePoint);
321-
assertThat(remainingRefs).isEmpty();
322-
}
323-
324-
@Test
325-
@DisplayName("Should delete pricing node refs by usage point ID")
326-
void shouldDeletePricingNodeRefsByUsagePointId() {
327-
// Arrange
328-
UsagePointEntity usagePoint = TestDataBuilders.createValidUsagePoint();
329-
UsagePointEntity savedUsagePoint = usagePointRepository.save(usagePoint);
330-
331-
PnodeRefEntity pnodeRef = new PnodeRefEntity("HUB", "DELETE_TEST", savedUsagePoint);
332-
pnodeRefRepository.save(pnodeRef);
333-
flushAndClear();
334-
335-
// Act
336-
Long deletedCount = pnodeRefRepository.deleteByUsagePointId(savedUsagePoint.getId());
337-
flushAndClear();
338-
339-
// Assert
340-
assertThat(deletedCount).isEqualTo(1L);
341-
List<PnodeRefEntity> remainingRefs = pnodeRefRepository.findByUsagePointId(savedUsagePoint.getId());
342-
assertThat(remainingRefs).isEmpty();
343-
}
344161
}
345162

346163
@Nested

0 commit comments

Comments
 (0)