From 162e1fd2f3ced86d251f2d465d55f5822bf82783 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20Ha=C3=9Fel?= Date: Mon, 24 Oct 2022 12:53:34 +0200 Subject: [PATCH] Bulk add, delete + BulkEntry add, delete --- src/main/angular/src/app/api/SearchResult.ts | 2 + src/main/angular/src/app/api/api.service.ts | 5 + .../angular/src/app/api/bulk/BulkEntry.ts | 4 +- .../src/app/api/bulk/BulkEntryCreate.ts | 19 ++++ .../angular/src/app/api/bulk/BulkService.ts | 24 +++- .../angular/src/app/api/property/Property.ts | 12 +- .../src/app/api/property/property.service.ts | 5 + .../app/pages/bulk/bulk/bulk.component.html | 104 ++++++++++-------- .../src/app/pages/bulk/bulk/bulk.component.ts | 13 +++ .../property-list.component.html | 13 +++ .../property-list/property-list.component.ts | 9 ++ src/main/angular/src/styles.less | 1 + .../ph87/homeautomation/DemoDataService.java | 5 +- .../homeautomation/bulk/BulkController.java | 2 +- .../homeautomation/bulk/BulkExecutor.java | 2 +- .../ph87/homeautomation/bulk/BulkMapper.java | 2 +- .../ph87/homeautomation/bulk/BulkReader.java | 5 + .../homeautomation/bulk/BulkRepository.java | 3 + .../homeautomation/bulk/entry/BulkEntry.java | 2 +- .../bulk/entry/BulkEntryController.java | 4 +- .../bulk/entry/BulkEntryWriter.java | 4 +- .../channel/ChannelController.java | 2 +- .../property/PropertyController.java | 2 +- .../homeautomation/property/PropertyDto.java | 7 +- .../property/PropertyMapper.java | 32 +++++- .../homeautomation/schedule/Schedule.java | 2 +- .../schedule/ScheduleCalculationService.java | 4 +- .../schedule/ScheduleController.java | 6 +- .../schedule/ScheduleExecutionService.java | 4 +- ...leReadService.java => ScheduleReader.java} | 7 +- .../schedule/ScheduleRepository.java | 3 + .../schedule/ScheduleThreadService.java | 6 +- .../schedule/ScheduleWriteService.java | 6 +- .../schedule/entry/ScheduleEntry.java | 42 +++---- ...dService.java => ScheduleEntryReader.java} | 2 +- .../entry/ScheduleEntryWriteService.java | 24 ++-- .../homeautomation/shared/SearchResult.java | 9 +- 37 files changed, 281 insertions(+), 117 deletions(-) create mode 100644 src/main/angular/src/app/api/bulk/BulkEntryCreate.ts rename src/main/java/de/ph87/homeautomation/schedule/{ScheduleReadService.java => ScheduleReader.java} (83%) rename src/main/java/de/ph87/homeautomation/schedule/entry/{ScheduleEntryReadService.java => ScheduleEntryReader.java} (95%) diff --git a/src/main/angular/src/app/api/SearchResult.ts b/src/main/angular/src/app/api/SearchResult.ts index 816ba67..8efeede 100644 --- a/src/main/angular/src/app/api/SearchResult.ts +++ b/src/main/angular/src/app/api/SearchResult.ts @@ -3,6 +3,7 @@ import {validateNumberNotNull, validateStringNotEmptyNotNull} from "./validators export class SearchResult { constructor( + readonly type: string, readonly id: number, readonly title: string, ) { @@ -10,6 +11,7 @@ export class SearchResult { static fromJson(json: any): SearchResult { return new SearchResult( + validateStringNotEmptyNotNull(json['type']), validateNumberNotNull(json['id']), validateStringNotEmptyNotNull(json['title']), ); diff --git a/src/main/angular/src/app/api/api.service.ts b/src/main/angular/src/app/api/api.service.ts index 984906d..92dafda 100644 --- a/src/main/angular/src/app/api/api.service.ts +++ b/src/main/angular/src/app/api/api.service.ts @@ -7,6 +7,7 @@ import {CompatClient, Stomp} from "@stomp/stompjs"; import {Update} from "./Update"; import {LocationStrategy} from "@angular/common"; import {Page} from "./Page"; +import {Next} from "./types"; export function NO_OP() { } @@ -81,6 +82,10 @@ export class ApiService { this.http.post(this.restUrl(path), data).pipe(map(list => list.map(fromJson))).subscribe(next, errorInterceptor(error)); } + delete(path: string, next: Next): void { + this.http.delete(this.restUrl(path)).subscribe(next); + } + private restUrl(path: string): string { return environment.restBase + this.locationStrategy.getBaseHref() + path; } diff --git a/src/main/angular/src/app/api/bulk/BulkEntry.ts b/src/main/angular/src/app/api/bulk/BulkEntry.ts index 6e5e6d5..0ae472a 100644 --- a/src/main/angular/src/app/api/bulk/BulkEntry.ts +++ b/src/main/angular/src/app/api/bulk/BulkEntry.ts @@ -8,7 +8,7 @@ export class BulkEntry { readonly version: number, readonly position: number, readonly enabled: boolean, - readonly property: Property, + readonly property: Property | null, readonly value: number, ) { // nothing @@ -20,7 +20,7 @@ export class BulkEntry { validateNumberNotNull(json['version']), validateNumberNotNull(json['position']), validateBooleanNotNull(json['enabled']), - Property.fromJson(json['property']), + Property.fromJsonOrNull(json['property']), validateNumberNotNull(json['value']), ); } diff --git a/src/main/angular/src/app/api/bulk/BulkEntryCreate.ts b/src/main/angular/src/app/api/bulk/BulkEntryCreate.ts new file mode 100644 index 0000000..38c28b4 --- /dev/null +++ b/src/main/angular/src/app/api/bulk/BulkEntryCreate.ts @@ -0,0 +1,19 @@ +import {Property} from "../property/Property"; +import {Bulk} from "./Bulk"; + +export class BulkEntryCreate { + readonly bulkId: number; + + readonly position: number; + + public constructor( + bulk: Bulk, + readonly enabled: boolean, + readonly property: Property | null, + readonly value: number, + ) { + this.bulkId = bulk.id; + this.position = bulk.entries.length; + } + +} diff --git a/src/main/angular/src/app/api/bulk/BulkService.ts b/src/main/angular/src/app/api/bulk/BulkService.ts index d0861ef..3589a81 100644 --- a/src/main/angular/src/app/api/bulk/BulkService.ts +++ b/src/main/angular/src/app/api/bulk/BulkService.ts @@ -5,6 +5,19 @@ import {SearchResult} from "../SearchResult"; import {Update} from "../Update"; import {Bulk} from "./Bulk"; import {BulkEntry} from "./BulkEntry"; +import {Next} from "../types"; +import {BulkEntryCreate} from "./BulkEntryCreate"; + +class BulkCreate { + + constructor( + readonly name: string, + readonly enabled: boolean, + ) { + // nothing + } + +} @Injectable({ providedIn: 'root' @@ -42,7 +55,7 @@ export class BulkService implements ISearchService { } create(next: (item: Bulk) => void, error: (error: any) => void = NO_OP): void { - this.api.getReturnItem("bulk/create/", Bulk.fromJson, next, error); + this.api.postReturnItem("bulk/create/", new BulkCreate("Neu", true), Bulk.fromJson, next, error); } delete(bulk: Bulk, next: () => void, error: (error: any) => void = NO_OP): void { @@ -53,4 +66,13 @@ export class BulkService implements ISearchService { this.api.putReturnItem("BulkEntry/" + entry.id + "/set/" + key, value, next, error); } + deleteEntry(entry: BulkEntry, next: Next): void { + this.api.delete("BulkEntry/" + entry.id, next); + } + + createEntry(bulk: Bulk, next: Next): void { + const dto: BulkEntryCreate = new BulkEntryCreate(bulk, false, null, 0); + this.api.postReturnItem("BulkEntry/create", dto, BulkEntry.fromJson, next); + } + } diff --git a/src/main/angular/src/app/api/property/Property.ts b/src/main/angular/src/app/api/property/Property.ts index 52c0ad9..18d55b7 100644 --- a/src/main/angular/src/app/api/property/Property.ts +++ b/src/main/angular/src/app/api/property/Property.ts @@ -1,5 +1,6 @@ -import {validateDateAllowNull, validateNumberAllowNull, validateNumberNotNull, validateStringNotEmptyNotNull} from "../validators"; +import {validateDateAllowNull, validateListOrEmpty, validateNumberAllowNull, validateNumberNotNull, validateStringNotEmptyNotNull} from "../validators"; import {Channel} from "../channel/Channel"; +import {SearchResult} from "../SearchResult"; export class Property { @@ -11,6 +12,7 @@ export class Property { public timestamp: Date | null, public readChannel: Channel | null, public writeChannel: Channel | null, + public usages: SearchResult[], ) { // nothing } @@ -31,9 +33,17 @@ export class Property { validateDateAllowNull(json['timestamp']), Channel.fromJsonAllowNull(json['readChannel']), Channel.fromJsonAllowNull(json['writeChannel']), + validateListOrEmpty(json['usages'], SearchResult.fromJson), ); } + static fromJsonOrNull(json: any): Property | null { + if (json === null) { + return null; + } + return this.fromJson(json); + } + public static trackBy(index: number, item: Property): number { return item.id; } diff --git a/src/main/angular/src/app/api/property/property.service.ts b/src/main/angular/src/app/api/property/property.service.ts index 1aeba15..966e22f 100644 --- a/src/main/angular/src/app/api/property/property.service.ts +++ b/src/main/angular/src/app/api/property/property.service.ts @@ -4,6 +4,7 @@ import {ISearchService} from "../ISearchService"; import {SearchResult} from "../SearchResult"; import {Update} from "../Update"; import {Property} from "./Property"; +import {Next} from "../types"; @Injectable({ providedIn: 'root' @@ -40,4 +41,8 @@ export class PropertyService implements ISearchService { this.api.getReturnItem("property/create/", Property.fromJson, next, error); } + delete(property: Property, next: Next): void { + this.api.delete("property/" + property.id, next); + } + } diff --git a/src/main/angular/src/app/pages/bulk/bulk/bulk.component.html b/src/main/angular/src/app/pages/bulk/bulk/bulk.component.html index 3f3a3d5..3b64cf4 100644 --- a/src/main/angular/src/app/pages/bulk/bulk/bulk.component.html +++ b/src/main/angular/src/app/pages/bulk/bulk/bulk.component.html @@ -1,46 +1,60 @@ - - - - - - - - - - - - - - - - + +

{{bulk.name}}

+
EigenschaftWert
- - - {{entry.value ? "An" : "Aus"}} - - - - - - - - - -   -
+ + + + - -
EigenschaftWert 
+ + + + + + + + + {{entry.value ? "An" : "Aus"}} + + + + + + + + + + + + + + +   + + + + + + + + + + + +

+ +

+ diff --git a/src/main/angular/src/app/pages/bulk/bulk/bulk.component.ts b/src/main/angular/src/app/pages/bulk/bulk/bulk.component.ts index 645fe52..07d18bd 100644 --- a/src/main/angular/src/app/pages/bulk/bulk/bulk.component.ts +++ b/src/main/angular/src/app/pages/bulk/bulk/bulk.component.ts @@ -4,6 +4,7 @@ import {Bulk} from "../../../api/bulk/Bulk"; import {ActivatedRoute} from "@angular/router"; import {PropertyService} from "../../../api/property/property.service"; import {BulkEntry} from "../../../api/bulk/BulkEntry"; +import {faTimesCircle} from "@fortawesome/free-regular-svg-icons"; @Component({ selector: 'app-bulk', @@ -12,6 +13,8 @@ import {BulkEntry} from "../../../api/bulk/BulkEntry"; }) export class BulkComponent implements OnInit { + readonly faTimes = faTimesCircle; + bulk!: Bulk; constructor( @@ -44,4 +47,14 @@ export class BulkComponent implements OnInit { } } + delete(entry: BulkEntry): void { + if (confirm(`Eintrag #"${entry.position}" wirklich löschen?`)) { + this.bulkService.deleteEntry(entry, () => this.bulk.entries.splice(this.bulk.entries.findIndex(e => e.id === entry.id), 1)); + } + } + + create(): void { + this.bulkService.createEntry(this.bulk, entry => this.update(entry)); + } + } diff --git a/src/main/angular/src/app/pages/property-list/property-list.component.html b/src/main/angular/src/app/pages/property-list/property-list.component.html index 39682ec..c99c331 100644 --- a/src/main/angular/src/app/pages/property-list/property-list.component.html +++ b/src/main/angular/src/app/pages/property-list/property-list.component.html @@ -14,12 +14,17 @@ Zeitstempel Lesekanal Schreibkanal + + + + + + {{property.value ? "An" : "Aus"}} @@ -50,15 +56,22 @@ {{findScene(property)?.title || "Unbekannt: " + property.value}} + {{property.timestamp | date:'yyyy-MM-dd HH:mm:ss'}} + + + + + + diff --git a/src/main/angular/src/app/pages/property-list/property-list.component.ts b/src/main/angular/src/app/pages/property-list/property-list.component.ts index 487a652..3c5cd25 100644 --- a/src/main/angular/src/app/pages/property-list/property-list.component.ts +++ b/src/main/angular/src/app/pages/property-list/property-list.component.ts @@ -4,6 +4,7 @@ import {PropertyService} from "../../api/property/property.service"; import {Scene} from "../../api/scene/Scene"; import {SceneService} from "../../api/scene/scene.service"; import {ChannelService} from "../../api/channel/channel.service"; +import {faTimesCircle} from "@fortawesome/free-regular-svg-icons"; @Component({ selector: 'app-property-list', @@ -12,6 +13,8 @@ import {ChannelService} from "../../api/channel/channel.service"; }) export class PropertyListComponent implements OnInit { + readonly faTimes = faTimesCircle; + Property = Property; properties: Property[] = []; @@ -80,4 +83,10 @@ export class PropertyListComponent implements OnInit { this.propertyService.create(property => this.updateProperty(property, true)); } + delete(property: Property): void { + if (confirm(`Eigenschaft "${property.title}" wirklich löschen?`)) { + this.propertyService.delete(property, () => this.properties.splice(this.properties.findIndex(p => p.id === property.id), 1)); + } + } + } diff --git a/src/main/angular/src/styles.less b/src/main/angular/src/styles.less index 6f9a838..67a72cc 100644 --- a/src/main/angular/src/styles.less +++ b/src/main/angular/src/styles.less @@ -98,6 +98,7 @@ table.vertical { .delete { color: darkred; + text-align: center; } .disabled { diff --git a/src/main/java/de/ph87/homeautomation/DemoDataService.java b/src/main/java/de/ph87/homeautomation/DemoDataService.java index ded9a3a..53c6036 100644 --- a/src/main/java/de/ph87/homeautomation/DemoDataService.java +++ b/src/main/java/de/ph87/homeautomation/DemoDataService.java @@ -18,6 +18,8 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.time.ZonedDateTime; + @SuppressWarnings({"unchecked", "UnusedReturnValue", "SameParameterValue", "UnusedAssignment", "RedundantSuppression"}) @Slf4j @Service @@ -52,7 +54,8 @@ public class DemoDataService { bulkEntryController.create(new BulkEntryCreateDto(bulk.getId(), propertyBulkBrightness.getId(), 40, 0)); bulkEntryController.create(new BulkEntryCreateDto(bulk.getId(), propertyBulkColorTemperature.getId(), 55, 0)); final long scheduleId = createSchedule(true, "schedule"); - createTime(scheduleId, true, 12, 0, 0, 0, propertyDirect, 1, bulk); + final ZonedDateTime now = ZonedDateTime.now().plusSeconds(3); + createTime(scheduleId, true, now.getHour(), now.getMinute(), now.getSecond(), 0, propertyDirect, 1, bulk); } private Property createProperty(final String title, final PropertyType type, final Channel readChannel, final Channel writeChannel) { diff --git a/src/main/java/de/ph87/homeautomation/bulk/BulkController.java b/src/main/java/de/ph87/homeautomation/bulk/BulkController.java index 8a08709..902b36d 100644 --- a/src/main/java/de/ph87/homeautomation/bulk/BulkController.java +++ b/src/main/java/de/ph87/homeautomation/bulk/BulkController.java @@ -72,7 +72,7 @@ public class BulkController implements ISearchController { } private SearchResult toSearchResult(final BulkDto bulkDto) { - return new SearchResult(bulkDto.getId(), bulkDto.getName()); + return new SearchResult(Bulk.class, bulkDto.getId(), bulkDto.getName()); } } diff --git a/src/main/java/de/ph87/homeautomation/bulk/BulkExecutor.java b/src/main/java/de/ph87/homeautomation/bulk/BulkExecutor.java index 793e9d1..f5ef4ce 100644 --- a/src/main/java/de/ph87/homeautomation/bulk/BulkExecutor.java +++ b/src/main/java/de/ph87/homeautomation/bulk/BulkExecutor.java @@ -15,7 +15,7 @@ public class BulkExecutor { private final PropertyWriteService propertyWriteService; public void execute(final Bulk bulk) { - log.debug("Executing Bulk: {}", bulk); + log.info("Executing Bulk: {}", bulk); bulk.getEntries().forEach(entry -> propertyWriteService.writeToChannel(entry.getProperty(), entry.getValue())); log.debug("Finished executing Bulk: {}", bulk); } diff --git a/src/main/java/de/ph87/homeautomation/bulk/BulkMapper.java b/src/main/java/de/ph87/homeautomation/bulk/BulkMapper.java index 3283876..3b7c6e9 100644 --- a/src/main/java/de/ph87/homeautomation/bulk/BulkMapper.java +++ b/src/main/java/de/ph87/homeautomation/bulk/BulkMapper.java @@ -34,7 +34,7 @@ public class BulkMapper { } public BulkEntryDto toDto(final BulkEntry entry) { - final PropertyDto property = propertyMapper.toDto(entry.getProperty()); + final PropertyDto property = propertyMapper.toDtoOrNull(entry.getProperty()); return new BulkEntryDto(entry, property); } diff --git a/src/main/java/de/ph87/homeautomation/bulk/BulkReader.java b/src/main/java/de/ph87/homeautomation/bulk/BulkReader.java index 1b827cd..daabb83 100644 --- a/src/main/java/de/ph87/homeautomation/bulk/BulkReader.java +++ b/src/main/java/de/ph87/homeautomation/bulk/BulkReader.java @@ -1,5 +1,6 @@ package de.ph87.homeautomation.bulk; +import de.ph87.homeautomation.property.Property; import de.ph87.homeautomation.web.NotFoundException; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -46,4 +47,8 @@ public class BulkReader { return bulkRepository.findByEntries_Id(id).orElseThrow(NotFoundException.supply(Bulk.class, "entries_id", id)); } + public List findAllByProperty(final Property property) { + return bulkRepository.findDistinctByEntries_Property(property); + } + } diff --git a/src/main/java/de/ph87/homeautomation/bulk/BulkRepository.java b/src/main/java/de/ph87/homeautomation/bulk/BulkRepository.java index 8a84ab4..522ca4c 100644 --- a/src/main/java/de/ph87/homeautomation/bulk/BulkRepository.java +++ b/src/main/java/de/ph87/homeautomation/bulk/BulkRepository.java @@ -1,5 +1,6 @@ package de.ph87.homeautomation.bulk; +import de.ph87.homeautomation.property.Property; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; @@ -13,4 +14,6 @@ public interface BulkRepository extends JpaRepository, JpaSpecificat Optional findByEntries_Id(long id); + List findDistinctByEntries_Property(Property property); + } diff --git a/src/main/java/de/ph87/homeautomation/bulk/entry/BulkEntry.java b/src/main/java/de/ph87/homeautomation/bulk/entry/BulkEntry.java index 1ddb9c4..898c43f 100644 --- a/src/main/java/de/ph87/homeautomation/bulk/entry/BulkEntry.java +++ b/src/main/java/de/ph87/homeautomation/bulk/entry/BulkEntry.java @@ -28,7 +28,7 @@ public class BulkEntry { private int position; @Setter - @ManyToOne(optional = false) + @ManyToOne private Property property; @Setter diff --git a/src/main/java/de/ph87/homeautomation/bulk/entry/BulkEntryController.java b/src/main/java/de/ph87/homeautomation/bulk/entry/BulkEntryController.java index 17fbc67..690a580 100644 --- a/src/main/java/de/ph87/homeautomation/bulk/entry/BulkEntryController.java +++ b/src/main/java/de/ph87/homeautomation/bulk/entry/BulkEntryController.java @@ -22,8 +22,8 @@ public class BulkEntryController { } @PutMapping("{id}/set/property") - public BulkEntryDto setValue(@PathVariable final long id, @RequestBody final long propertyId) { - return bulkMapper.toDto(bulkEntryWriter.set(id, entry -> entry.setProperty(propertyReader.getById(propertyId)))); + public BulkEntryDto setValue(@PathVariable final long id, @RequestBody(required = false) final Long propertyId) { + return bulkMapper.toDto(bulkEntryWriter.set(id, entry -> entry.setProperty(propertyId == null ? null : propertyReader.getById(propertyId)))); } @PutMapping("{id}/set/value") diff --git a/src/main/java/de/ph87/homeautomation/bulk/entry/BulkEntryWriter.java b/src/main/java/de/ph87/homeautomation/bulk/entry/BulkEntryWriter.java index c80cfe0..6b7fa95 100644 --- a/src/main/java/de/ph87/homeautomation/bulk/entry/BulkEntryWriter.java +++ b/src/main/java/de/ph87/homeautomation/bulk/entry/BulkEntryWriter.java @@ -56,7 +56,9 @@ public class BulkEntryWriter { } public void remove(final long id) { - getEntryById(id); + final Bulk bulk = bulkReader.getBulkByEntryId(id); + final BulkEntry entry = getEntryById(bulk, id); + bulk.getEntries().remove(entry); } private BulkEntry getEntryById(final long id) { diff --git a/src/main/java/de/ph87/homeautomation/channel/ChannelController.java b/src/main/java/de/ph87/homeautomation/channel/ChannelController.java index e92aa68..092afde 100644 --- a/src/main/java/de/ph87/homeautomation/channel/ChannelController.java +++ b/src/main/java/de/ph87/homeautomation/channel/ChannelController.java @@ -34,7 +34,7 @@ public class ChannelController implements ISearchController { } private SearchResult toSearchResult(final ChannelDto dto) { - return new SearchResult(dto.getId(), dto.getTitle()); + return new SearchResult(Channel.class, dto.getId(), dto.getTitle()); } } diff --git a/src/main/java/de/ph87/homeautomation/property/PropertyController.java b/src/main/java/de/ph87/homeautomation/property/PropertyController.java index 33c44af..2c971fb 100644 --- a/src/main/java/de/ph87/homeautomation/property/PropertyController.java +++ b/src/main/java/de/ph87/homeautomation/property/PropertyController.java @@ -87,7 +87,7 @@ public class PropertyController implements ISearchController { } private SearchResult toSearchResult(final PropertyDto propertyDto) { - return new SearchResult(propertyDto.getId(), propertyDto.getTitle()); + return new SearchResult(Property.class, propertyDto.getId(), propertyDto.getTitle()); } } diff --git a/src/main/java/de/ph87/homeautomation/property/PropertyDto.java b/src/main/java/de/ph87/homeautomation/property/PropertyDto.java index 3185401..8577b47 100644 --- a/src/main/java/de/ph87/homeautomation/property/PropertyDto.java +++ b/src/main/java/de/ph87/homeautomation/property/PropertyDto.java @@ -1,10 +1,12 @@ package de.ph87.homeautomation.property; import de.ph87.homeautomation.channel.ChannelDto; +import de.ph87.homeautomation.shared.SearchResult; import lombok.Data; import java.io.Serializable; import java.time.ZonedDateTime; +import java.util.List; @Data public final class PropertyDto implements Serializable { @@ -23,7 +25,9 @@ public final class PropertyDto implements Serializable { private final ChannelDto writeChannel; - public PropertyDto(final Property property, final ChannelDto readChannel, final ChannelDto writeChannel) { + private final List usages; + + public PropertyDto(final Property property, final ChannelDto readChannel, final ChannelDto writeChannel, final List usages) { this.id = property.getId(); this.type = property.getType(); this.title = property.getTitle(); @@ -31,6 +35,7 @@ public final class PropertyDto implements Serializable { this.timestamp = property.getTimestamp(); this.readChannel = readChannel; this.writeChannel = writeChannel; + this.usages = usages; } } diff --git a/src/main/java/de/ph87/homeautomation/property/PropertyMapper.java b/src/main/java/de/ph87/homeautomation/property/PropertyMapper.java index 576d3ca..1089a09 100644 --- a/src/main/java/de/ph87/homeautomation/property/PropertyMapper.java +++ b/src/main/java/de/ph87/homeautomation/property/PropertyMapper.java @@ -1,11 +1,20 @@ package de.ph87.homeautomation.property; +import de.ph87.homeautomation.bulk.Bulk; +import de.ph87.homeautomation.bulk.BulkRepository; import de.ph87.homeautomation.channel.ChannelService; +import de.ph87.homeautomation.schedule.Schedule; +import de.ph87.homeautomation.schedule.ScheduleRepository; +import de.ph87.homeautomation.shared.SearchResult; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + @Slf4j @Service @Transactional @@ -14,14 +23,27 @@ public class PropertyMapper { private final ChannelService channelService; + private final ScheduleRepository scheduleRepository; + + private final BulkRepository bulkRepository; + public PropertyDto toDto(final Property property) { + final List usages = findUsages(property); return new PropertyDto( property, channelService.toDtoAllowNull(property.getReadChannel()), - channelService.toDtoAllowNull(property.getWriteChannel()) + channelService.toDtoAllowNull(property.getWriteChannel()), + usages ); } + private List findUsages(final Property property) { + final List searchResults = new ArrayList<>(); + searchResults.addAll(scheduleRepository.findDistinctByEntries_Property(property).stream().map(this::toSearchResult).collect(Collectors.toList())); + searchResults.addAll(bulkRepository.findDistinctByEntries_Property(property).stream().map(this::toSearchResult).collect(Collectors.toList())); + return searchResults; + } + public PropertyDto toDtoOrNull(final Property property) { if (property == null) { return null; @@ -29,4 +51,12 @@ public class PropertyMapper { return toDto(property); } + private SearchResult toSearchResult(final Schedule schedule) { + return new SearchResult(Schedule.class, schedule.getId(), schedule.getTitle()); + } + + private SearchResult toSearchResult(final Bulk bulk) { + return new SearchResult(Bulk.class, bulk.getId(), bulk.getName()); + } + } diff --git a/src/main/java/de/ph87/homeautomation/schedule/Schedule.java b/src/main/java/de/ph87/homeautomation/schedule/Schedule.java index 8cc94cd..0ca72e6 100644 --- a/src/main/java/de/ph87/homeautomation/schedule/Schedule.java +++ b/src/main/java/de/ph87/homeautomation/schedule/Schedule.java @@ -27,7 +27,7 @@ public class Schedule { private String title; @ToString.Exclude - @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "schedule") private Set entries = new HashSet<>(); } diff --git a/src/main/java/de/ph87/homeautomation/schedule/ScheduleCalculationService.java b/src/main/java/de/ph87/homeautomation/schedule/ScheduleCalculationService.java index 26603ae..d94f8d8 100644 --- a/src/main/java/de/ph87/homeautomation/schedule/ScheduleCalculationService.java +++ b/src/main/java/de/ph87/homeautomation/schedule/ScheduleCalculationService.java @@ -29,14 +29,14 @@ public class ScheduleCalculationService { private final Config config; - private final ScheduleReadService scheduleReadService; + private final ScheduleReader scheduleReader; private final ApplicationEventPublisher applicationEventPublisher; @EventListener(ApplicationStartedEvent.class) public void calculateAllNext() { final ZonedDateTime now = ZonedDateTime.now(); - scheduleReadService.findAll().forEach(schedule -> calculateSchedule(schedule, now)); + scheduleReader.findAll().forEach(schedule -> calculateSchedule(schedule, now)); } public void calculateSchedule(final Schedule schedule, final ZonedDateTime now) { diff --git a/src/main/java/de/ph87/homeautomation/schedule/ScheduleController.java b/src/main/java/de/ph87/homeautomation/schedule/ScheduleController.java index 669d83b..c9f2369 100644 --- a/src/main/java/de/ph87/homeautomation/schedule/ScheduleController.java +++ b/src/main/java/de/ph87/homeautomation/schedule/ScheduleController.java @@ -11,7 +11,7 @@ import java.util.List; @RequiredArgsConstructor public class ScheduleController { - private final ScheduleReadService scheduleReadService; + private final ScheduleReader scheduleReader; private final ScheduleWriteService scheduleWriteService; @@ -19,12 +19,12 @@ public class ScheduleController { @GetMapping("findAll") public List findAll() { - return scheduleReadService.findAllDtos(); + return scheduleReader.findAllDtos(); } @GetMapping("searchById/{id}") public ScheduleDto getById(@PathVariable final long id) { - return scheduleReadService.getDtoById(id); + return scheduleReader.getDtoById(id); } @GetMapping("create") diff --git a/src/main/java/de/ph87/homeautomation/schedule/ScheduleExecutionService.java b/src/main/java/de/ph87/homeautomation/schedule/ScheduleExecutionService.java index c2c7c81..7204d2e 100644 --- a/src/main/java/de/ph87/homeautomation/schedule/ScheduleExecutionService.java +++ b/src/main/java/de/ph87/homeautomation/schedule/ScheduleExecutionService.java @@ -17,7 +17,7 @@ import java.util.Comparator; @RequiredArgsConstructor public class ScheduleExecutionService { - private final ScheduleReadService scheduleReadService; + private final ScheduleReader scheduleReader; private final ScheduleCalculationService scheduleCalculationService; @@ -27,7 +27,7 @@ public class ScheduleExecutionService { public void executeAllLastDue() { final ZonedDateTime now = ZonedDateTime.now(); - scheduleReadService.findAll().forEach(schedule -> executeLastDue(schedule, now)); + scheduleReader.findAll().forEach(schedule -> executeLastDue(schedule, now)); } private void executeLastDue(final Schedule schedule, final ZonedDateTime now) { diff --git a/src/main/java/de/ph87/homeautomation/schedule/ScheduleReadService.java b/src/main/java/de/ph87/homeautomation/schedule/ScheduleReader.java similarity index 83% rename from src/main/java/de/ph87/homeautomation/schedule/ScheduleReadService.java rename to src/main/java/de/ph87/homeautomation/schedule/ScheduleReader.java index 582d7c7..0a9bdfd 100644 --- a/src/main/java/de/ph87/homeautomation/schedule/ScheduleReadService.java +++ b/src/main/java/de/ph87/homeautomation/schedule/ScheduleReader.java @@ -1,5 +1,6 @@ package de.ph87.homeautomation.schedule; +import de.ph87.homeautomation.property.Property; import de.ph87.homeautomation.schedule.entry.ScheduleEntry; import de.ph87.homeautomation.web.NotFoundException; import lombok.RequiredArgsConstructor; @@ -14,7 +15,7 @@ import java.util.stream.Collectors; @Service @Transactional @RequiredArgsConstructor -public class ScheduleReadService { +public class ScheduleReader { private final ScheduleRepository scheduleRepository; @@ -40,4 +41,8 @@ public class ScheduleReadService { return scheduleMapper.toDto(getById(id)); } + public List findAllByProperty(final Property property) { + return scheduleRepository.findDistinctByEntries_Property(property); + } + } diff --git a/src/main/java/de/ph87/homeautomation/schedule/ScheduleRepository.java b/src/main/java/de/ph87/homeautomation/schedule/ScheduleRepository.java index 9fe37eb..5934352 100644 --- a/src/main/java/de/ph87/homeautomation/schedule/ScheduleRepository.java +++ b/src/main/java/de/ph87/homeautomation/schedule/ScheduleRepository.java @@ -1,5 +1,6 @@ package de.ph87.homeautomation.schedule; +import de.ph87.homeautomation.property.Property; import de.ph87.homeautomation.schedule.entry.ScheduleEntry; import org.springframework.data.repository.CrudRepository; @@ -13,4 +14,6 @@ public interface ScheduleRepository extends CrudRepository { boolean existsByTitle(String title); + List findDistinctByEntries_Property(Property property); + } diff --git a/src/main/java/de/ph87/homeautomation/schedule/ScheduleThreadService.java b/src/main/java/de/ph87/homeautomation/schedule/ScheduleThreadService.java index 909afdf..5f7bea0 100644 --- a/src/main/java/de/ph87/homeautomation/schedule/ScheduleThreadService.java +++ b/src/main/java/de/ph87/homeautomation/schedule/ScheduleThreadService.java @@ -1,6 +1,6 @@ package de.ph87.homeautomation.schedule; -import de.ph87.homeautomation.schedule.entry.ScheduleEntryReadService; +import de.ph87.homeautomation.schedule.entry.ScheduleEntryReader; import de.ph87.homeautomation.shared.AbstractThreadService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -17,7 +17,7 @@ public class ScheduleThreadService extends AbstractThreadService { private final ScheduleExecutionService scheduleExecutionService; - private final ScheduleEntryReadService scheduleEntryReadService; + private final ScheduleEntryReader scheduleEntryReader; @Override protected String getThreadName() { @@ -32,7 +32,7 @@ public class ScheduleThreadService extends AbstractThreadService { @Override protected long doStep() throws InterruptedException { scheduleExecutionService.executeAllLastDue(); - return scheduleEntryReadService.getNextTimestamp().map(nextTimestamp -> Duration.between(ZonedDateTime.now(), nextTimestamp).toMillis()).orElse(0L); + return scheduleEntryReader.getNextTimestamp().map(nextTimestamp -> Duration.between(ZonedDateTime.now(), nextTimestamp).toMillis()).orElse(0L); } @Override diff --git a/src/main/java/de/ph87/homeautomation/schedule/ScheduleWriteService.java b/src/main/java/de/ph87/homeautomation/schedule/ScheduleWriteService.java index 9fdaccf..a0fcf1c 100644 --- a/src/main/java/de/ph87/homeautomation/schedule/ScheduleWriteService.java +++ b/src/main/java/de/ph87/homeautomation/schedule/ScheduleWriteService.java @@ -17,7 +17,7 @@ public class ScheduleWriteService { public static final String NAME_PREFIX = "Neu "; - private final ScheduleReadService scheduleReadService; + private final ScheduleReader scheduleReader; private final ScheduleCalculationService scheduleCalculationService; @@ -43,14 +43,14 @@ public class ScheduleWriteService { } public ScheduleDto set(final long id, final BiConsumer setter, final T value) { - final Schedule schedule = scheduleReadService.getById(id); + final Schedule schedule = scheduleReader.getById(id); setter.accept(schedule, value); scheduleCalculationService.calculateSchedule(schedule, ZonedDateTime.now()); return publish(schedule, true); } public void delete(final long id) { - final Schedule schedule = scheduleReadService.getById(id); + final Schedule schedule = scheduleReader.getById(id); scheduleRepository.delete(schedule); publish(schedule, false); } diff --git a/src/main/java/de/ph87/homeautomation/schedule/entry/ScheduleEntry.java b/src/main/java/de/ph87/homeautomation/schedule/entry/ScheduleEntry.java index 109f66b..ecd3b7b 100644 --- a/src/main/java/de/ph87/homeautomation/schedule/entry/ScheduleEntry.java +++ b/src/main/java/de/ph87/homeautomation/schedule/entry/ScheduleEntry.java @@ -3,8 +3,10 @@ package de.ph87.homeautomation.schedule.entry; import com.luckycatlabs.sunrisesunset.Zenith; import de.ph87.homeautomation.bulk.Bulk; import de.ph87.homeautomation.property.Property; +import de.ph87.homeautomation.schedule.Schedule; import lombok.AccessLevel; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; import javax.persistence.*; @@ -14,6 +16,7 @@ import java.util.Random; @Getter @Setter @Entity +@NoArgsConstructor public class ScheduleEntry { private static final Random RANDOM = new Random(System.currentTimeMillis()); @@ -23,6 +26,9 @@ public class ScheduleEntry { @Setter(AccessLevel.NONE) private Long id; + @ManyToOne + private Schedule schedule; + private boolean enabled = false; private boolean monday = true; @@ -71,6 +77,10 @@ public class ScheduleEntry { @Setter(AccessLevel.NONE) private ZonedDateTime nextFuzzyTimestamp; + public ScheduleEntry(final Schedule schedule) { + this.schedule = schedule; + } + public void setNextClearTimestamp(final ZonedDateTime next) { nextClearTimestamp = next; if (nextClearTimestamp == null) { @@ -82,24 +92,6 @@ public class ScheduleEntry { } } - public void setWorkday(final boolean enabled) { - monday = enabled; - tuesday = enabled; - wednesday = enabled; - thursday = enabled; - friday = enabled; - } - - public void setWeekend(final boolean enabled) { - saturday = enabled; - sunday = enabled; - } - - public void setEveryday(final boolean enabled) { - setWorkday(enabled); - setWeekend(enabled); - } - @Override public String toString() { final StringBuilder builder = new StringBuilder(); @@ -111,13 +103,13 @@ public class ScheduleEntry { builder.append(", type="); builder.append(type); builder.append(", weekdays="); - builder.append(monday ? 1 : 0); - builder.append(tuesday ? 1 : 0); - builder.append(wednesday ? 1 : 0); - builder.append(thursday ? 1 : 0); - builder.append(friday ? 1 : 0); - builder.append(saturday ? 1 : 0); - builder.append(sunday ? 1 : 0); + builder.append(monday ? "Mon" : "___"); + builder.append(tuesday ? "Tue" : "___"); + builder.append(wednesday ? "Wed" : "___"); + builder.append(thursday ? "Thu" : "___"); + builder.append(friday ? "Fri" : "___"); + builder.append(saturday ? "Sat" : "___"); + builder.append(sunday ? "Sun" : "___"); if (type != null) { switch (type) { case TIME: diff --git a/src/main/java/de/ph87/homeautomation/schedule/entry/ScheduleEntryReadService.java b/src/main/java/de/ph87/homeautomation/schedule/entry/ScheduleEntryReader.java similarity index 95% rename from src/main/java/de/ph87/homeautomation/schedule/entry/ScheduleEntryReadService.java rename to src/main/java/de/ph87/homeautomation/schedule/entry/ScheduleEntryReader.java index 4fe444f..6f755d8 100644 --- a/src/main/java/de/ph87/homeautomation/schedule/entry/ScheduleEntryReadService.java +++ b/src/main/java/de/ph87/homeautomation/schedule/entry/ScheduleEntryReader.java @@ -13,7 +13,7 @@ import java.util.Optional; @Service @Transactional @RequiredArgsConstructor -public class ScheduleEntryReadService { +public class ScheduleEntryReader { private final ScheduleEntryRepository scheduleEntryRepository; diff --git a/src/main/java/de/ph87/homeautomation/schedule/entry/ScheduleEntryWriteService.java b/src/main/java/de/ph87/homeautomation/schedule/entry/ScheduleEntryWriteService.java index d3b6a4f..5a6337c 100644 --- a/src/main/java/de/ph87/homeautomation/schedule/entry/ScheduleEntryWriteService.java +++ b/src/main/java/de/ph87/homeautomation/schedule/entry/ScheduleEntryWriteService.java @@ -2,7 +2,7 @@ package de.ph87.homeautomation.schedule.entry; import de.ph87.homeautomation.schedule.Schedule; import de.ph87.homeautomation.schedule.ScheduleCalculationService; -import de.ph87.homeautomation.schedule.ScheduleReadService; +import de.ph87.homeautomation.schedule.ScheduleReader; import de.ph87.homeautomation.web.WebSocketService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -19,9 +19,9 @@ import java.util.function.Consumer; @RequiredArgsConstructor public class ScheduleEntryWriteService { - private final ScheduleEntryReadService scheduleEntryReadService; + private final ScheduleEntryReader scheduleEntryReader; - private final ScheduleReadService scheduleReadService; + private final ScheduleReader scheduleReader; private final ScheduleCalculationService scheduleCalculationService; @@ -33,31 +33,31 @@ public class ScheduleEntryWriteService { @Deprecated(since = "Use alternative 'set' instead.", forRemoval = true) public ScheduleEntryDto set(final long id, final BiConsumer setter, final T value) { - final ScheduleEntry entry = scheduleEntryReadService.getById(id); + final ScheduleEntry entry = scheduleEntryReader.getById(id); setter.accept(entry, value); - final Schedule schedule = scheduleReadService.getByEntry(entry); + final Schedule schedule = scheduleReader.getByEntry(entry); scheduleCalculationService.calculateSchedule(schedule, ZonedDateTime.now()); return publish(entry, true); } public ScheduleEntryDto set(final long id, final Consumer setter) { - final ScheduleEntry entry = scheduleEntryReadService.getById(id); + final ScheduleEntry entry = scheduleEntryReader.getById(id); setter.accept(entry); - final Schedule schedule = scheduleReadService.getByEntry(entry); + final Schedule schedule = scheduleReader.getByEntry(entry); scheduleCalculationService.calculateSchedule(schedule, ZonedDateTime.now()); return publish(entry, true); } public ScheduleEntryDto create(final long scheduleId) { - final Schedule schedule = scheduleReadService.getById(scheduleId); - final ScheduleEntry entry = new ScheduleEntry(); - schedule.getEntries().add(scheduleEntryRepository.save(entry)); + final Schedule schedule = scheduleReader.getById(scheduleId); + final ScheduleEntry entry = scheduleEntryRepository.save(new ScheduleEntry(schedule)); + schedule.getEntries().add(entry); return publish(entry, true); } public void delete(final long id) { - final ScheduleEntry entry = scheduleEntryReadService.getById(id); - scheduleReadService.getByEntry(entry).getEntries().remove(entry); + final ScheduleEntry entry = scheduleEntryReader.getById(id); + scheduleReader.getByEntry(entry).getEntries().remove(entry); scheduleEntryRepository.delete(entry); publish(entry, false); } diff --git a/src/main/java/de/ph87/homeautomation/shared/SearchResult.java b/src/main/java/de/ph87/homeautomation/shared/SearchResult.java index c1ada88..bc53005 100644 --- a/src/main/java/de/ph87/homeautomation/shared/SearchResult.java +++ b/src/main/java/de/ph87/homeautomation/shared/SearchResult.java @@ -5,11 +5,14 @@ import lombok.Getter; @Getter public class SearchResult { - public final long id; + private final String type; - public final String title; + private final long id; - public SearchResult(final long id, final String title) { + private final String title; + + public SearchResult(final Class clazz, final long id, final String title) { + this.type = clazz.getSimpleName(); this.id = id; this.title = title; }