Bulk editor
This commit is contained in:
parent
56660b2d31
commit
8f92c986aa
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,4 +2,5 @@
|
|||||||
/target/
|
/target/
|
||||||
/.idea/
|
/.idea/
|
||||||
/.jpb/
|
/.jpb/
|
||||||
|
/application.properties
|
||||||
/*.db
|
/*.db
|
||||||
@ -2,7 +2,7 @@ import {SearchResult} from "./SearchResult";
|
|||||||
|
|
||||||
export interface ISearchService {
|
export interface ISearchService {
|
||||||
|
|
||||||
get(id: number, next: (results: SearchResult) => void, error: (error: any) => void): void;
|
searchById(id: number, next: (results: SearchResult) => void, error: (error: any) => void): void;
|
||||||
|
|
||||||
search(term: string, next: (results: SearchResult[]) => void, error: (error: any) => void): void;
|
search(term: string, next: (results: SearchResult[]) => void, error: (error: any) => void): void;
|
||||||
|
|
||||||
|
|||||||
26
src/main/angular/src/app/api/Page.ts
Normal file
26
src/main/angular/src/app/api/Page.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import {FromJson} from "./types";
|
||||||
|
import {validateListOrEmpty, validateNumberNotNull} from "./validators";
|
||||||
|
|
||||||
|
export class Page<T> {
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
readonly page: number,
|
||||||
|
readonly size: number,
|
||||||
|
readonly content: T[],
|
||||||
|
) {
|
||||||
|
// nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
static fromJsonGenerator<T>(fromJson: FromJson<T>): FromJson<Page<T>> {
|
||||||
|
return (json: any) => this.fromJson2(json, fromJson);
|
||||||
|
}
|
||||||
|
|
||||||
|
static fromJson2<T>(json: any, fromJson: FromJson<T>): Page<T> {
|
||||||
|
return new Page<T>(
|
||||||
|
validateNumberNotNull(json['page']),
|
||||||
|
validateNumberNotNull(json['size']),
|
||||||
|
validateListOrEmpty(json['content'], fromJson),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
62
src/main/angular/src/app/api/abstract-repository.service.ts
Normal file
62
src/main/angular/src/app/api/abstract-repository.service.ts
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
import {Injectable} from '@angular/core';
|
||||||
|
import {NO_OP} from "./api.service";
|
||||||
|
import {Page} from "./Page";
|
||||||
|
import {Error, FromJson, IEntity, Next} from "./types";
|
||||||
|
import {environment} from "../../environments/environment";
|
||||||
|
import {HttpClient} from "@angular/common/http";
|
||||||
|
import {map} from "rxjs/operators";
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class AbstractRepositoryService<Entity extends IEntity, Creator, Filter> {
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
readonly http: HttpClient,
|
||||||
|
readonly prefix: string,
|
||||||
|
readonly fromJson: FromJson<Entity>,
|
||||||
|
) {
|
||||||
|
// nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
create(dto: Creator, next: Next<Entity> = NO_OP, error: Error = NO_OP) {
|
||||||
|
this._post(['create'], dto, this.fromJson, next, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
set(entity: Entity, key: string, value: any, next: Next<Entity> = NO_OP, error: Error = NO_OP) {
|
||||||
|
this._put(['put', entity.id, key], value, this.fromJson, next, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
get(id: number, next: Next<Entity> = NO_OP, error: Error = NO_OP) {
|
||||||
|
this._get(['get', id], this.fromJson, next, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
filter(filter: Filter, next: Next<Page<Entity>> = NO_OP, error: Error = NO_OP) {
|
||||||
|
this._post(['filter'], filter, Page.fromJsonGenerator(this.fromJson), next, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(id: number, next: Next<Entity> = NO_OP, error: Error = NO_OP) {
|
||||||
|
this._delete(['delete', id], this.fromJson, next, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _get<T>(path: any[], fromJson: FromJson<T>, next: Next<T>, error: Error): void {
|
||||||
|
this.http.get<any>(this._url(path)).pipe(map(fromJson)).subscribe(next, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _put<T>(path: any[], data: any, fromJson: FromJson<T>, next: Next<T>, error: Error): void {
|
||||||
|
this.http.put<any>(this._url(path), data).pipe(map(fromJson)).subscribe(next, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _post<T>(path: any[], data: any, fromJson: FromJson<T>, next: Next<T>, error: Error): void {
|
||||||
|
this.http.post<any>(this._url(path), data).pipe(map(fromJson)).subscribe(next, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _delete<T>(path: any[], fromJson: FromJson<T>, next: Next<T>, error: Error): void {
|
||||||
|
this.http.delete<any>(this._url(path)).pipe(map(fromJson)).subscribe(next, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _url(path: any[]): string {
|
||||||
|
return environment.restBase + '/' + this.prefix + '/' + path.join('/');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,16 +0,0 @@
|
|||||||
import {TestBed} from '@angular/core/testing';
|
|
||||||
|
|
||||||
import {ApiService} from './api.service';
|
|
||||||
|
|
||||||
describe('ApiService', () => {
|
|
||||||
let service: ApiService;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
TestBed.configureTestingModule({});
|
|
||||||
service = TestBed.inject(ApiService);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should be created', () => {
|
|
||||||
expect(service).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@ -6,6 +6,7 @@ import {Subject} from "rxjs";
|
|||||||
import {CompatClient, Stomp} from "@stomp/stompjs";
|
import {CompatClient, Stomp} from "@stomp/stompjs";
|
||||||
import {Update} from "./Update";
|
import {Update} from "./Update";
|
||||||
import {LocationStrategy} from "@angular/common";
|
import {LocationStrategy} from "@angular/common";
|
||||||
|
import {Page} from "./Page";
|
||||||
|
|
||||||
export function NO_OP() {
|
export function NO_OP() {
|
||||||
}
|
}
|
||||||
@ -48,7 +49,7 @@ export class ApiService {
|
|||||||
this.updateSubject.pipe(filter(update => update.type === type), map(update => Update.convert(update, fromJson))).subscribe(next);
|
this.updateSubject.pipe(filter(update => update.type === type), map(update => Update.convert(update, fromJson))).subscribe(next);
|
||||||
}
|
}
|
||||||
|
|
||||||
getItem<T>(path: string, fromJson: (json: any) => T, next: (item: T) => void = NO_OP, error: (error: any) => void = NO_OP) {
|
getReturnItem<T>(path: string, fromJson: (json: any) => T, next: (item: T) => void = NO_OP, error: (error: any) => void = NO_OP) {
|
||||||
this.http.get<any>(this.restUrl(path)).pipe(map(fromJson)).subscribe(next, errorInterceptor(error));
|
this.http.get<any>(this.restUrl(path)).pipe(map(fromJson)).subscribe(next, errorInterceptor(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,6 +65,18 @@ export class ApiService {
|
|||||||
this.http.post<any>(this.restUrl(path), data).pipe(map(fromJson)).subscribe(next, errorInterceptor(error));
|
this.http.post<any>(this.restUrl(path), data).pipe(map(fromJson)).subscribe(next, errorInterceptor(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
putReturnItem<T>(path: string, data: any, fromJson: (json: any) => T, next: (item: T) => void = NO_OP, error: (error: any) => void = NO_OP) {
|
||||||
|
this.http.put<any>(this.restUrl(path), data).pipe(map(fromJson)).subscribe(next, errorInterceptor(error));
|
||||||
|
}
|
||||||
|
|
||||||
|
postReturnPage<T>(path: string, data: any, fromJson: (json: any) => T, next: (page: Page<T>) => void = NO_OP, error: (error: any) => void = NO_OP) {
|
||||||
|
this.http.post<any>(this.restUrl(path), data).pipe(map(Page.fromJsonGenerator(fromJson))).subscribe(next, errorInterceptor(error));
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteReturnItem<T>(path: string, fromJson: (json: any) => T, next: (item: T) => void = NO_OP, error: (error: any) => void = NO_OP) {
|
||||||
|
this.http.delete<any>(this.restUrl(path)).pipe(map(fromJson)).subscribe(next, errorInterceptor(error));
|
||||||
|
}
|
||||||
|
|
||||||
postReturnList<T>(path: string, data: any, fromJson: (json: any) => T, next: (list: T[]) => void = NO_OP, error: (error: any) => void = NO_OP) {
|
postReturnList<T>(path: string, data: any, fromJson: (json: any) => T, next: (list: T[]) => void = NO_OP, error: (error: any) => void = NO_OP) {
|
||||||
this.http.post<any>(this.restUrl(path), data).pipe(map(list => list.map(fromJson))).subscribe(next, errorInterceptor(error));
|
this.http.post<any>(this.restUrl(path), data).pipe(map(list => list.map(fromJson))).subscribe(next, errorInterceptor(error));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,8 +24,8 @@ export class AreaService implements ISearchService {
|
|||||||
this.api.subscribe("AreaDto", Area.fromJson, next);
|
this.api.subscribe("AreaDto", Area.fromJson, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
get(id: number, next: (results: SearchResult) => void, error: (error: any) => void): void {
|
searchById(id: number, next: (results: SearchResult) => void, error: (error: any) => void): void {
|
||||||
this.api.getItem("area/getById/" + id, SearchResult.fromJson, next, error);
|
this.api.getReturnItem("area/searchById/" + id, SearchResult.fromJson, next, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
search(term: string, next: (results: SearchResult[]) => void = NO_OP, error: (error: any) => void = NO_OP): void {
|
search(term: string, next: (results: SearchResult[]) => void = NO_OP, error: (error: any) => void = NO_OP): void {
|
||||||
|
|||||||
@ -4,11 +4,11 @@ import {BulkEntry} from "./BulkEntry";
|
|||||||
export class Bulk {
|
export class Bulk {
|
||||||
|
|
||||||
private constructor(
|
private constructor(
|
||||||
public id: number,
|
readonly id: number,
|
||||||
public version: number,
|
readonly version: number,
|
||||||
public name: string,
|
readonly name: string,
|
||||||
public enabled: boolean,
|
readonly enabled: boolean,
|
||||||
public entries: BulkEntry[],
|
readonly entries: BulkEntry[],
|
||||||
) {
|
) {
|
||||||
// nothing
|
// nothing
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,13 @@
|
|||||||
import {Property} from "../property/Property";
|
import {Property} from "../property/Property";
|
||||||
import {validateNumberNotNull} from "../validators";
|
import {validateBooleanNotNull, validateNumberNotNull} from "../validators";
|
||||||
|
|
||||||
export class BulkEntry {
|
export class BulkEntry {
|
||||||
|
|
||||||
private constructor(
|
private constructor(
|
||||||
|
readonly id: number,
|
||||||
|
readonly version: number,
|
||||||
|
readonly position: number,
|
||||||
|
readonly enabled: boolean,
|
||||||
readonly property: Property,
|
readonly property: Property,
|
||||||
readonly value: number,
|
readonly value: number,
|
||||||
) {
|
) {
|
||||||
@ -12,6 +16,10 @@ export class BulkEntry {
|
|||||||
|
|
||||||
static fromJson(json: any): BulkEntry {
|
static fromJson(json: any): BulkEntry {
|
||||||
return new BulkEntry(
|
return new BulkEntry(
|
||||||
|
validateNumberNotNull(json['id']),
|
||||||
|
validateNumberNotNull(json['version']),
|
||||||
|
validateNumberNotNull(json['position']),
|
||||||
|
validateBooleanNotNull(json['enabled']),
|
||||||
Property.fromJson(json['property']),
|
Property.fromJson(json['property']),
|
||||||
validateNumberNotNull(json['value']),
|
validateNumberNotNull(json['value']),
|
||||||
);
|
);
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import {ISearchService} from "../ISearchService";
|
|||||||
import {SearchResult} from "../SearchResult";
|
import {SearchResult} from "../SearchResult";
|
||||||
import {Update} from "../Update";
|
import {Update} from "../Update";
|
||||||
import {Bulk} from "./Bulk";
|
import {Bulk} from "./Bulk";
|
||||||
|
import {BulkEntry} from "./BulkEntry";
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
@ -24,8 +25,12 @@ export class BulkService implements ISearchService {
|
|||||||
this.api.subscribe("BulkDto", Bulk.fromJson, next);
|
this.api.subscribe("BulkDto", Bulk.fromJson, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
get(id: number, next: (results: SearchResult) => void, error: (error: any) => void): void {
|
getById(id: number, next: (results: Bulk) => void, error?: (error: any) => void): void {
|
||||||
this.api.getItem("bulk/getById/" + id, SearchResult.fromJson, next, error);
|
this.api.getReturnItem("bulk/getById/" + id, Bulk.fromJson, next, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
searchById(id: number, next: (results: SearchResult) => void, error: (error: any) => void): void {
|
||||||
|
this.api.getReturnItem("bulk/searchById/" + id, SearchResult.fromJson, next, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
search(term: string, next: (results: SearchResult[]) => void = NO_OP, error: (error: any) => void = NO_OP): void {
|
search(term: string, next: (results: SearchResult[]) => void = NO_OP, error: (error: any) => void = NO_OP): void {
|
||||||
@ -37,11 +42,15 @@ export class BulkService implements ISearchService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
create(next: (item: Bulk) => void, error: (error: any) => void = NO_OP): void {
|
create(next: (item: Bulk) => void, error: (error: any) => void = NO_OP): void {
|
||||||
this.api.getItem("bulk/create/", Bulk.fromJson, next, error);
|
this.api.getReturnItem("bulk/create/", Bulk.fromJson, next, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete(bulk: Bulk, next: () => void, error: (error: any) => void = NO_OP): void {
|
delete(bulk: Bulk, next: () => void, error: (error: any) => void = NO_OP): void {
|
||||||
this.api.getItem("bulk/delete/" + bulk.id, _ => _, next, error);
|
this.api.getReturnItem("bulk/delete/" + bulk.id, _ => _, next, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
setEntry(entry: BulkEntry, key: string, value: any, next: (result: BulkEntry) => void = NO_OP, error: (error: any) => void = NO_OP): void {
|
||||||
|
this.api.putReturnItem("BulkEntry/" + entry.id + "/set/" + key, value, next, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -24,8 +24,8 @@ export class ChannelService implements ISearchService {
|
|||||||
this.api.subscribe("ChannelDto", Channel.fromJson, next);
|
this.api.subscribe("ChannelDto", Channel.fromJson, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
get(id: number, next: (results: SearchResult) => void, error: (error: any) => void): void {
|
searchById(id: number, next: (results: SearchResult) => void, error: (error: any) => void): void {
|
||||||
this.api.getItem("channel/getById/" + id, SearchResult.fromJson, next, error);
|
this.api.getReturnItem("channel/searchById/" + id, SearchResult.fromJson, next, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
search(term: string, next: (results: SearchResult[]) => void = NO_OP, error: (error: any) => void = NO_OP): void {
|
search(term: string, next: (results: SearchResult[]) => void = NO_OP, error: (error: any) => void = NO_OP): void {
|
||||||
|
|||||||
@ -65,7 +65,7 @@ export class DeviceService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getById(id: number, next: (item: Device) => void, error: (error: any) => void = NO_OP): void {
|
getById(id: number, next: (item: Device) => void, error: (error: any) => void = NO_OP): void {
|
||||||
this.api.getItem("device/getById/" + id, Device.fromJson, next, error);
|
this.api.getReturnItem("device/searchById/" + id, Device.fromJson, next, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
create(type: string, next: (item: Device) => void, error: (error: any) => void = NO_OP): void {
|
create(type: string, next: (item: Device) => void, error: (error: any) => void = NO_OP): void {
|
||||||
@ -73,7 +73,7 @@ export class DeviceService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
delete(device: Device, next: () => void, error: (error: any) => void = NO_OP): void {
|
delete(device: Device, next: () => void, error: (error: any) => void = NO_OP): void {
|
||||||
this.api.getItem("device/delete/" + device.id, _ => _, next, error);
|
this.api.getReturnItem("device/delete/" + device.id, _ => _, next, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,8 +24,8 @@ export class PropertyService implements ISearchService {
|
|||||||
this.api.subscribe("PropertyDto", Property.fromJson, next);
|
this.api.subscribe("PropertyDto", Property.fromJson, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
get(id: number, next: (results: SearchResult) => void, error: (error: any) => void): void {
|
searchById(id: number, next: (results: SearchResult) => void, error: (error: any) => void): void {
|
||||||
this.api.getItem("property/getById/" + id, SearchResult.fromJson, next, error);
|
this.api.getReturnItem("property/searchById/" + id, SearchResult.fromJson, next, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
search(term: string, next: (results: SearchResult[]) => void = NO_OP, error: (error: any) => void = NO_OP): void {
|
search(term: string, next: (results: SearchResult[]) => void = NO_OP, error: (error: any) => void = NO_OP): void {
|
||||||
@ -37,7 +37,7 @@ export class PropertyService implements ISearchService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
create(next: (item: Property) => void, error: (error: any) => void = NO_OP): void {
|
create(next: (item: Property) => void, error: (error: any) => void = NO_OP): void {
|
||||||
this.api.getItem("property/create/", Property.fromJson, next, error);
|
this.api.getReturnItem("property/create/", Property.fromJson, next, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,8 +24,8 @@ export class RoomService implements ISearchService {
|
|||||||
this.api.subscribe("RoomDto", Room.fromJson, next);
|
this.api.subscribe("RoomDto", Room.fromJson, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
get(id: number, next: (results: SearchResult) => void, error: (error: any) => void): void {
|
searchById(id: number, next: (results: SearchResult) => void, error: (error: any) => void): void {
|
||||||
this.api.getItem("room/getById/" + id, SearchResult.fromJson, next, error);
|
this.api.getReturnItem("room/searchById/" + id, SearchResult.fromJson, next, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
search(term: string, next: (results: SearchResult[]) => void = NO_OP, error: (error: any) => void = NO_OP): void {
|
search(term: string, next: (results: SearchResult[]) => void = NO_OP, error: (error: any) => void = NO_OP): void {
|
||||||
|
|||||||
@ -24,8 +24,8 @@ export class SceneService implements ISearchService {
|
|||||||
this.api.subscribe("SceneDto", Scene.fromJson, next);
|
this.api.subscribe("SceneDto", Scene.fromJson, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
get(id: number, next: (results: SearchResult) => void, error: (error: any) => void): void {
|
searchById(id: number, next: (results: SearchResult) => void, error: (error: any) => void): void {
|
||||||
this.api.getItem("scene/getById/" + id, SearchResult.fromJson, next, error);
|
this.api.getReturnItem("scene/searchById/" + id, SearchResult.fromJson, next, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
search(term: string, next: (results: SearchResult[]) => void = NO_OP, error: (error: any) => void = NO_OP): void {
|
search(term: string, next: (results: SearchResult[]) => void = NO_OP, error: (error: any) => void = NO_OP): void {
|
||||||
|
|||||||
@ -23,11 +23,11 @@ export class ScheduleEntryService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
create(schedule: Schedule, next: (item: ScheduleEntry) => void, error: (error: any) => void = NO_OP): void {
|
create(schedule: Schedule, next: (item: ScheduleEntry) => void, error: (error: any) => void = NO_OP): void {
|
||||||
this.api.getItem("schedule/entry/create/" + schedule.id, ScheduleEntry.fromJson, next, error);
|
this.api.getReturnItem("schedule/entry/create/" + schedule.id, ScheduleEntry.fromJson, next, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete(entry: ScheduleEntry, next: () => void, error: (error: any) => void = NO_OP): void {
|
delete(entry: ScheduleEntry, next: () => void, error: (error: any) => void = NO_OP): void {
|
||||||
this.api.getItem("schedule/entry/delete/" + entry.id, _ => _, next, error);
|
this.api.getReturnItem("schedule/entry/delete/" + entry.id, _ => _, next, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,15 +22,15 @@ export class ScheduleService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getById(id: number, next: (item: Schedule) => void, error: (error: any) => void = NO_OP): void {
|
getById(id: number, next: (item: Schedule) => void, error: (error: any) => void = NO_OP): void {
|
||||||
this.api.getItem("schedule/getById/" + id, Schedule.fromJson, next, error);
|
this.api.getReturnItem("schedule/searchById/" + id, Schedule.fromJson, next, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
create(next: (item: Schedule) => void, error: (error: any) => void = NO_OP): void {
|
create(next: (item: Schedule) => void, error: (error: any) => void = NO_OP): void {
|
||||||
this.api.getItem("schedule/create/", Schedule.fromJson, next, error);
|
this.api.getReturnItem("schedule/create/", Schedule.fromJson, next, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete(schedule: Schedule, next: () => void, error: (error: any) => void = NO_OP): void {
|
delete(schedule: Schedule, next: () => void, error: (error: any) => void = NO_OP): void {
|
||||||
this.api.getItem("schedule/delete/" + schedule.id, _ => _, next, error);
|
this.api.getReturnItem("schedule/delete/" + schedule.id, _ => _, next, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
7
src/main/angular/src/app/api/types.ts
Normal file
7
src/main/angular/src/app/api/types.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
export type FromJson<T> = (json: any) => T;
|
||||||
|
export type Next<T> = (entity: T) => void;
|
||||||
|
export type Error = () => void
|
||||||
|
|
||||||
|
export interface IEntity {
|
||||||
|
get id(): number;
|
||||||
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
import {Component, OnInit} from '@angular/core';
|
import {Component, OnInit} from '@angular/core';
|
||||||
import {BulkService} from "../../../api/bulk/bulkService";
|
import {BulkService} from "../../../api/bulk/BulkService";
|
||||||
import {Bulk} from "../../../api/bulk/Bulk";
|
import {Bulk} from "../../../api/bulk/Bulk";
|
||||||
import {faCheckCircle, faCircle, faTimesCircle} from "@fortawesome/free-regular-svg-icons";
|
import {faCheckCircle, faCircle, faTimesCircle} from "@fortawesome/free-regular-svg-icons";
|
||||||
|
|
||||||
|
|||||||
@ -1 +1,46 @@
|
|||||||
<p>bulk works!</p>
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>Eigenschaft</th>
|
||||||
|
<th>Wert</th>
|
||||||
|
</tr>
|
||||||
|
<ng-container *ngIf="bulk">
|
||||||
|
<tr *ngFor="let entry of bulk.entries">
|
||||||
|
<td>
|
||||||
|
<app-search [searchService]="propertyService" [allowEmpty]="false" [initial]="entry.property?.id" (valueChange)="setEntry(entry, 'property', $event)"></app-search>
|
||||||
|
</td>
|
||||||
|
<ng-container [ngSwitch]="entry.property?.type">
|
||||||
|
<td *ngSwitchCase="'BOOLEAN'" [class.true]="entry.value" [class.false]="!entry.value" (click)="setEntry(entry, 'value', entry.value > 0 ? 0 : 1)">
|
||||||
|
{{entry.value ? "An" : "Aus"}}
|
||||||
|
</td>
|
||||||
|
<td *ngSwitchCase="'SHUTTER'" [class.true]="entry.value === 0" [class.false]="entry.value === 100" [class.tristate]="0 < entry.value && entry.value < 100">
|
||||||
|
<select [ngModel]="entry.value" (ngModelChange)="setEntry(entry, 'value', entry.value)">
|
||||||
|
<option [ngValue]="0">100% Offen</option>
|
||||||
|
<option [ngValue]="35"> 50%</option>
|
||||||
|
<option [ngValue]="55"> 75%</option>
|
||||||
|
<option [ngValue]="75"> 90% Sonnenschutz</option>
|
||||||
|
<option [ngValue]="85">100% Schlitze</option>
|
||||||
|
<option [ngValue]="100">100% Geschlossen</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
<td *ngSwitchCase="'BRIGHTNESS_PERCENT'" [class.true]="entry.value" [class.false]="!entry.value" [class.tristate]="0 < entry.value && entry.value < 100">
|
||||||
|
<select [ngModel]="entry.value" (ngModelChange)="setEntry(entry, 'value', entry.value)">
|
||||||
|
<option *ngFor="let _ of [].constructor(21); let value = index" [ngValue]="value * 5">{{value * 5}}%</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
<td *ngSwitchCase="'COLOR_TEMPERATURE'" [class.true]="entry.value" [class.false]="!entry.value" [class.tristate]="0 < entry.value && entry.value < 100">
|
||||||
|
<select [ngModel]="entry.value" (ngModelChange)="setEntry(entry, 'value', entry.value)">
|
||||||
|
<option *ngFor="let _ of [].constructor(21); let value = index" [ngValue]="value * 5">{{value * 5}}%</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
<td *ngSwitchCase="'LUX'" [class.true]="entry.value" [class.false]="!entry.value" [class.tristate]="0 < entry.value && entry.value < 100">
|
||||||
|
<select [ngModel]="entry.value" (ngModelChange)="setEntry(entry, 'value', entry.value)">
|
||||||
|
<option *ngFor="let _ of [].constructor(21); let value = index" [ngValue]="value * 5">{{value * 5}}%</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
<td *ngSwitchDefault class="empty">
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
</tr>
|
||||||
|
</ng-container>
|
||||||
|
</table>
|
||||||
|
|||||||
@ -1,4 +1,9 @@
|
|||||||
import {Component, OnInit} from '@angular/core';
|
import {Component, OnInit} from '@angular/core';
|
||||||
|
import {BulkService} from "../../../api/bulk/BulkService";
|
||||||
|
import {Bulk} from "../../../api/bulk/Bulk";
|
||||||
|
import {ActivatedRoute} from "@angular/router";
|
||||||
|
import {PropertyService} from "../../../api/property/property.service";
|
||||||
|
import {BulkEntry} from "../../../api/bulk/BulkEntry";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-bulk',
|
selector: 'app-bulk',
|
||||||
@ -7,10 +12,36 @@ import {Component, OnInit} from '@angular/core';
|
|||||||
})
|
})
|
||||||
export class BulkComponent implements OnInit {
|
export class BulkComponent implements OnInit {
|
||||||
|
|
||||||
constructor() {
|
bulk!: Bulk;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
readonly activatedRoute: ActivatedRoute,
|
||||||
|
readonly bulkService: BulkService,
|
||||||
|
readonly propertyService: PropertyService,
|
||||||
|
) {
|
||||||
|
// nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
this.activatedRoute.paramMap.subscribe(params => {
|
||||||
|
const idString: string | null = params.get('id');
|
||||||
|
if (idString) {
|
||||||
|
this.bulkService.getById(parseInt(idString), bulk => this.bulk = bulk);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setEntry(entry: BulkEntry, property: string, value: any): void {
|
||||||
|
this.bulkService.setEntry(entry, property, value, result => this.update(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
private update(fresh: BulkEntry): void {
|
||||||
|
const index: number = this.bulk.entries.findIndex(existing => existing.id === fresh.id);
|
||||||
|
if (index >= 0) {
|
||||||
|
this.bulk.entries[index] = fresh;
|
||||||
|
} else {
|
||||||
|
this.bulk.entries.splice(fresh.position, 0, fresh);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import {DataService} from "../../data.service";
|
|||||||
import {PropertyService} from "../../api/property/property.service";
|
import {PropertyService} from "../../api/property/property.service";
|
||||||
import {Scene} from "../../api/scene/Scene";
|
import {Scene} from "../../api/scene/Scene";
|
||||||
import {SceneService} from "../../api/scene/scene.service";
|
import {SceneService} from "../../api/scene/scene.service";
|
||||||
import {BulkService} from "../../api/bulk/bulkService";
|
import {BulkService} from "../../api/bulk/BulkService";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-schedule',
|
selector: 'app-schedule',
|
||||||
|
|||||||
@ -47,7 +47,7 @@ export class SearchComponent<T> implements OnInit {
|
|||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
if (this.initial) {
|
if (this.initial) {
|
||||||
this.searchService.get(this.initial, result => this.selected = result, _ => _);
|
this.searchService.searchById(this.initial, result => this.selected = result, _ => _);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,13 +2,12 @@ package de.ph87.homeautomation;
|
|||||||
|
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
|
|
||||||
|
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
public class BackendApplication extends SpringBootServletInitializer {
|
public class BackendApplication {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
SpringApplication.run(BackendApplication.class);
|
SpringApplication.run(BackendApplication.class, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1,35 +1,23 @@
|
|||||||
package de.ph87.homeautomation;
|
package de.ph87.homeautomation;
|
||||||
|
|
||||||
import com.luckycatlabs.sunrisesunset.Zenith;
|
import com.luckycatlabs.sunrisesunset.Zenith;
|
||||||
import de.ph87.homeautomation.bulk.Bulk;
|
import de.ph87.homeautomation.bulk.BulkController;
|
||||||
import de.ph87.homeautomation.bulk.BulkCreateDto;
|
import de.ph87.homeautomation.bulk.BulkCreateDto;
|
||||||
import de.ph87.homeautomation.bulk.BulkEntryCreateDto;
|
import de.ph87.homeautomation.bulk.BulkDto;
|
||||||
import de.ph87.homeautomation.bulk.BulkWriter;
|
import de.ph87.homeautomation.bulk.entry.BulkEntryController;
|
||||||
|
import de.ph87.homeautomation.bulk.entry.BulkEntryCreateDto;
|
||||||
import de.ph87.homeautomation.channel.Channel;
|
import de.ph87.homeautomation.channel.Channel;
|
||||||
import de.ph87.homeautomation.knx.group.KnxGroup;
|
|
||||||
import de.ph87.homeautomation.knx.group.KnxGroupReadService;
|
|
||||||
import de.ph87.homeautomation.logic.Logic;
|
|
||||||
import de.ph87.homeautomation.logic.LogicOperator;
|
|
||||||
import de.ph87.homeautomation.logic.LogicRepository;
|
|
||||||
import de.ph87.homeautomation.property.Property;
|
import de.ph87.homeautomation.property.Property;
|
||||||
import de.ph87.homeautomation.property.PropertyRepository;
|
import de.ph87.homeautomation.property.PropertyRepository;
|
||||||
import de.ph87.homeautomation.property.PropertyType;
|
import de.ph87.homeautomation.property.PropertyType;
|
||||||
import de.ph87.homeautomation.scene.SceneWriteService;
|
import de.ph87.homeautomation.schedule.ScheduleController;
|
||||||
import de.ph87.homeautomation.schedule.Schedule;
|
import de.ph87.homeautomation.schedule.entry.ScheduleEntryController;
|
||||||
import de.ph87.homeautomation.schedule.ScheduleRepository;
|
|
||||||
import de.ph87.homeautomation.schedule.entry.ScheduleEntry;
|
|
||||||
import de.ph87.homeautomation.schedule.entry.ScheduleEntryType;
|
import de.ph87.homeautomation.schedule.entry.ScheduleEntryType;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.time.ZonedDateTime;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@SuppressWarnings({"unchecked", "UnusedReturnValue", "SameParameterValue", "UnusedAssignment", "RedundantSuppression"})
|
@SuppressWarnings({"unchecked", "UnusedReturnValue", "SameParameterValue", "UnusedAssignment", "RedundantSuppression"})
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
@ -37,19 +25,17 @@ import java.util.stream.Collectors;
|
|||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class DemoDataService {
|
public class DemoDataService {
|
||||||
|
|
||||||
private final PropertyRepository propertyRepository;
|
|
||||||
|
|
||||||
private final KnxGroupReadService knxGroupReadService;
|
|
||||||
|
|
||||||
private final SceneWriteService sceneWriteService;
|
|
||||||
|
|
||||||
private final LogicRepository logicRepository;
|
|
||||||
|
|
||||||
private final BulkWriter bulkWriter;
|
|
||||||
|
|
||||||
private final Config config;
|
private final Config config;
|
||||||
|
|
||||||
private final ScheduleRepository scheduleRepository;
|
private final PropertyRepository propertyRepository;
|
||||||
|
|
||||||
|
private final BulkController bulkController;
|
||||||
|
|
||||||
|
private final BulkEntryController bulkEntryController;
|
||||||
|
|
||||||
|
private final ScheduleController scheduleController;
|
||||||
|
|
||||||
|
private final ScheduleEntryController scheduleEntryController;
|
||||||
|
|
||||||
public void insertDemoData() {
|
public void insertDemoData() {
|
||||||
if (!config.isInsertDemoData()) {
|
if (!config.isInsertDemoData()) {
|
||||||
@ -60,30 +46,13 @@ public class DemoDataService {
|
|||||||
final Property propertyBulkShutter = createProperty("propertyBulkShutter", PropertyType.SHUTTER, null, null);
|
final Property propertyBulkShutter = createProperty("propertyBulkShutter", PropertyType.SHUTTER, null, null);
|
||||||
final Property propertyBulkBrightness = createProperty("propertyBulkBrightness", PropertyType.BRIGHTNESS_PERCENT, null, null);
|
final Property propertyBulkBrightness = createProperty("propertyBulkBrightness", PropertyType.BRIGHTNESS_PERCENT, null, null);
|
||||||
final Property propertyBulkColorTemperature = createProperty("propertyBulkColorTemperature", PropertyType.COLOR_TEMPERATURE, null, null);
|
final Property propertyBulkColorTemperature = createProperty("propertyBulkColorTemperature", PropertyType.COLOR_TEMPERATURE, null, null);
|
||||||
final List<BulkEntryCreateDto> entries = Arrays.asList(
|
final BulkDto bulk = bulkController.create(new BulkCreateDto("bulk", true));
|
||||||
new BulkEntryCreateDto(propertyBulkBoolean.getId(), 1, 0),
|
bulkEntryController.create(new BulkEntryCreateDto(bulk.getId(), propertyBulkBoolean.getId(), 1, 0));
|
||||||
new BulkEntryCreateDto(propertyBulkShutter.getId(), 35, 0),
|
bulkEntryController.create(new BulkEntryCreateDto(bulk.getId(), propertyBulkShutter.getId(), 35, 0));
|
||||||
new BulkEntryCreateDto(propertyBulkBrightness.getId(), 40, 0),
|
bulkEntryController.create(new BulkEntryCreateDto(bulk.getId(), propertyBulkBrightness.getId(), 40, 0));
|
||||||
new BulkEntryCreateDto(propertyBulkColorTemperature.getId(), 55, 0)
|
bulkEntryController.create(new BulkEntryCreateDto(bulk.getId(), propertyBulkColorTemperature.getId(), 55, 0));
|
||||||
);
|
final long scheduleId = createSchedule(true, "schedule");
|
||||||
final Bulk bulk = createBulk("bulk", true, entries.toArray(new BulkEntryCreateDto[0]));
|
createTime(scheduleId, true, 12, 0, 0, 0, propertyDirect, 1, bulk);
|
||||||
final Schedule schedule = createSchedule(true, "schedule");
|
|
||||||
createTime(schedule, true, 12, 0, 0, 0, propertyDirect, 1, bulk);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Bulk createBulk(final String name, final boolean enabled, final BulkEntryCreateDto... entries) {
|
|
||||||
return bulkWriter.create(new BulkCreateDto(name, enabled, Arrays.stream(entries).collect(Collectors.toList())));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Logic getOrCreateLogic(final String name, final LogicOperator operator, final Property... properties) {
|
|
||||||
return logicRepository.findByName(name).orElseGet(() -> {
|
|
||||||
final Logic logic = new Logic(name, operator, new HashSet<>(Arrays.asList(properties)));
|
|
||||||
return logicRepository.save(logic);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private KnxGroup knx(final int main, final int mid, final int sub) {
|
|
||||||
return knxGroupReadService.getByAddress(main, mid, sub).orElse(null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Property createProperty(final String title, final PropertyType type, final Channel readChannel, final Channel writeChannel) {
|
private Property createProperty(final String title, final PropertyType type, final Channel readChannel, final Channel writeChannel) {
|
||||||
@ -93,54 +62,31 @@ public class DemoDataService {
|
|||||||
return property;
|
return property;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Schedule createSchedule(final boolean enabled, final String title) {
|
private long createSchedule(final boolean enabled, final String title) {
|
||||||
final Schedule schedule = new Schedule();
|
final long id = scheduleController.create().getId();
|
||||||
schedule.setEnabled(enabled);
|
scheduleController.setEnabled(id, enabled);
|
||||||
schedule.setTitle(title);
|
scheduleController.setTitle(id, title);
|
||||||
return scheduleRepository.save(schedule);
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ScheduleEntry createRelative(final Schedule schedule, final boolean enabled, final int inSeconds, final int fuzzySeconds, final Property property, final Object value, final Bulk bulk) {
|
private void createTime(final long scheduleId, final boolean enabled, final int hour, final int minute, final int second, final int fuzzySeconds, final Property property, final double value, final BulkDto bulk) {
|
||||||
final ZonedDateTime now = ZonedDateTime.now().plusSeconds(inSeconds).withNano(0);
|
newScheduleEntry(scheduleId, enabled, ScheduleEntryType.TIME, null, hour, minute, second, fuzzySeconds, property, value, bulk);
|
||||||
return createTime(schedule, enabled, now.getHour(), now.getMinute(), now.getSecond(), fuzzySeconds, property, value, bulk);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ScheduleEntry createTime(final Schedule schedule, final boolean enabled, final int hour, final int minute, final int second, final int fuzzySeconds, final Property property, final Object value, final Bulk bulk) {
|
private void newScheduleEntry(final long scheduleId, final boolean enabled, final ScheduleEntryType type, final Zenith zenith, final int hour, final int minute, final int second, final int fuzzySeconds, final Property property, final double value, final BulkDto bulk) {
|
||||||
return newScheduleEntry(schedule, enabled, ScheduleEntryType.TIME, null, hour, minute, second, fuzzySeconds, property, value, bulk);
|
final long id = scheduleEntryController.create(scheduleId).getId();
|
||||||
}
|
scheduleEntryController.setEnabled(id, enabled);
|
||||||
|
scheduleEntryController.setType(id, type.name());
|
||||||
private ScheduleEntry createSunrise(final Schedule schedule, final boolean enabled, final Zenith zenith, final int fuzzySeconds, final Property property, final Object value, final Bulk bulk) {
|
|
||||||
return newScheduleEntry(schedule, enabled, ScheduleEntryType.SUNRISE, zenith, 0, 0, 0, fuzzySeconds, property, value, bulk);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ScheduleEntry createSunset(final Schedule schedule, final boolean enabled, final Zenith zenith, final int fuzzySeconds, final Property property, final Object value, final Bulk bulk) {
|
|
||||||
return newScheduleEntry(schedule, enabled, ScheduleEntryType.SUNSET, zenith, 0, 0, 0, fuzzySeconds, property, value, bulk);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ScheduleEntry newScheduleEntry(final Schedule schedule, final boolean enabled, final ScheduleEntryType type, final Zenith zenith, final int hour, final int minute, final int second, final int fuzzySeconds, final Property property, final Object value, final Bulk bulk) {
|
|
||||||
final ScheduleEntry entry = new ScheduleEntry();
|
|
||||||
entry.setEnabled(enabled);
|
|
||||||
entry.setType(type);
|
|
||||||
if (zenith != null) {
|
if (zenith != null) {
|
||||||
entry.setZenith(zenith.degrees().doubleValue());
|
scheduleEntryController.setZenith(id, zenith.degrees().doubleValue());
|
||||||
}
|
}
|
||||||
entry.setHour(hour);
|
scheduleEntryController.setHour(id, hour);
|
||||||
entry.setMinute(minute);
|
scheduleEntryController.setMinute(id, minute);
|
||||||
entry.setSecond(second);
|
scheduleEntryController.setSecond(id, second);
|
||||||
entry.setFuzzySeconds(fuzzySeconds);
|
scheduleEntryController.setFuzzySeconds(id, fuzzySeconds);
|
||||||
entry.setProperty(property);
|
scheduleEntryController.setProperty(id, property == null ? null : property.getId());
|
||||||
if (value instanceof Boolean) {
|
scheduleEntryController.setValue(id, value);
|
||||||
entry.setValue((boolean) value ? 1.0 : 0.0);
|
scheduleEntryController.setBulk(id, bulk == null ? null : bulk.getId());
|
||||||
} else if (value instanceof Double) {
|
|
||||||
entry.setValue((Double) value);
|
|
||||||
} else if (value instanceof Integer) {
|
|
||||||
entry.setValue((Integer) value);
|
|
||||||
} else {
|
|
||||||
throw new RuntimeException();
|
|
||||||
}
|
|
||||||
entry.setBulk(bulk);
|
|
||||||
schedule.getEntries().add(entry);
|
|
||||||
return entry;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package de.ph87.homeautomation.bulk;
|
package de.ph87.homeautomation.bulk;
|
||||||
|
|
||||||
|
import de.ph87.homeautomation.bulk.entry.BulkEntry;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
@ -13,6 +14,7 @@ import java.util.List;
|
|||||||
@Getter
|
@Getter
|
||||||
@ToString
|
@ToString
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
|
@SuppressWarnings("FieldMayBeFinal")
|
||||||
public class Bulk {
|
public class Bulk {
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
@ -23,20 +25,24 @@ public class Bulk {
|
|||||||
private long version;
|
private long version;
|
||||||
|
|
||||||
@Setter
|
@Setter
|
||||||
private boolean enabled = false;
|
private boolean enabled;
|
||||||
|
|
||||||
@Setter
|
@Setter
|
||||||
@Column(nullable = false, unique = true)
|
@Column(nullable = false, unique = true)
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@ElementCollection
|
|
||||||
@ToString.Exclude
|
@ToString.Exclude
|
||||||
|
@OneToMany(cascade = CascadeType.ALL)
|
||||||
private List<BulkEntry> entries = new ArrayList<>();
|
private List<BulkEntry> entries = new ArrayList<>();
|
||||||
|
|
||||||
public Bulk(final BulkCreateDto dto, final List<BulkEntry> entries) {
|
@ToString.Include
|
||||||
|
public int entryCount() {
|
||||||
|
return entries.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Bulk(final BulkCreateDto dto) {
|
||||||
this.enabled = dto.isEnabled();
|
this.enabled = dto.isEnabled();
|
||||||
this.name = dto.getName();
|
this.name = dto.getName();
|
||||||
this.entries = new ArrayList<>(entries);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
package de.ph87.homeautomation.bulk;
|
package de.ph87.homeautomation.bulk;
|
||||||
|
|
||||||
import de.ph87.homeautomation.property.Property;
|
import de.ph87.homeautomation.property.PropertyReader;
|
||||||
import de.ph87.homeautomation.property.PropertyReadService;
|
|
||||||
import de.ph87.homeautomation.shared.ISearchController;
|
import de.ph87.homeautomation.shared.ISearchController;
|
||||||
import de.ph87.homeautomation.shared.SearchResult;
|
import de.ph87.homeautomation.shared.SearchResult;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@ -20,7 +19,7 @@ public class BulkController implements ISearchController {
|
|||||||
|
|
||||||
private final BulkReader bulkReader;
|
private final BulkReader bulkReader;
|
||||||
|
|
||||||
private final PropertyReadService propertyReadService;
|
private final PropertyReader propertyReader;
|
||||||
|
|
||||||
@PostMapping("create")
|
@PostMapping("create")
|
||||||
public BulkDto create(@RequestBody final BulkCreateDto dto) {
|
public BulkDto create(@RequestBody final BulkCreateDto dto) {
|
||||||
@ -47,28 +46,15 @@ public class BulkController implements ISearchController {
|
|||||||
return bulkWriter.set(id, bulk -> bulk.setEnabled(enabled));
|
return bulkWriter.set(id, bulk -> bulk.setEnabled(enabled));
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("entryAdd/{id}")
|
@GetMapping("getById/{id}")
|
||||||
public BulkDto entryAdd(@PathVariable final long id, @RequestBody final BulkEntryCreateDto dto) {
|
public BulkDto getById(@PathVariable final long id) {
|
||||||
return bulkWriter.set(id, bulk -> {
|
return bulkReader.getDtoById(id);
|
||||||
final Property property = propertyReadService.getById(dto.getPropertyId());
|
|
||||||
bulk.getEntries().add(dto.getIndex(), new BulkEntry(dto, property));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping("entryMove/{id}/{indexFrom}/{indexTo}")
|
|
||||||
public BulkDto entryMove(@PathVariable final long id, @PathVariable final int indexFrom, @PathVariable final int indexTo) {
|
|
||||||
return bulkWriter.set(id, bulk -> bulk.getEntries().add(indexTo, bulk.getEntries().remove(indexFrom)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping("entryRemove/{id}/{index}")
|
|
||||||
public BulkDto entryRemove(@PathVariable final long id, @PathVariable final int index) {
|
|
||||||
return bulkWriter.set(id, bulk -> bulk.getEntries().remove(index));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@GetMapping("getById/{id}")
|
@GetMapping("searchById/{id}")
|
||||||
@Deprecated(since = "Use 'filter' instead", forRemoval = true)
|
@Deprecated(since = "Use 'filter' instead", forRemoval = true)
|
||||||
public SearchResult getById(@PathVariable final long id) {
|
public SearchResult searchById(@PathVariable final long id) {
|
||||||
return toSearchResult(bulkReader.getDtoById(id));
|
return toSearchResult(bulkReader.getDtoById(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,8 +2,6 @@ package de.ph87.homeautomation.bulk;
|
|||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class BulkCreateDto {
|
public class BulkCreateDto {
|
||||||
|
|
||||||
@ -11,6 +9,4 @@ public class BulkCreateDto {
|
|||||||
|
|
||||||
private final boolean enabled;
|
private final boolean enabled;
|
||||||
|
|
||||||
private final List<BulkEntryCreateDto> entries;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package de.ph87.homeautomation.bulk;
|
package de.ph87.homeautomation.bulk;
|
||||||
|
|
||||||
|
import de.ph87.homeautomation.bulk.entry.BulkEntryDto;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|||||||
@ -1,14 +0,0 @@
|
|||||||
package de.ph87.homeautomation.bulk;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class BulkEntryCreateDto {
|
|
||||||
|
|
||||||
private final long propertyId;
|
|
||||||
|
|
||||||
private final double value;
|
|
||||||
|
|
||||||
private final int index;
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
package de.ph87.homeautomation.bulk;
|
|
||||||
|
|
||||||
import de.ph87.homeautomation.property.PropertyDto;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class BulkEntryDto {
|
|
||||||
|
|
||||||
private final PropertyDto property;
|
|
||||||
|
|
||||||
private final double value;
|
|
||||||
|
|
||||||
public BulkEntryDto(final BulkEntry bulkEntry, final PropertyDto property) {
|
|
||||||
this.property = property;
|
|
||||||
this.value = bulkEntry.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -5,23 +5,22 @@ import org.springframework.data.jpa.domain.Specification;
|
|||||||
|
|
||||||
import javax.persistence.criteria.Predicate;
|
import javax.persistence.criteria.Predicate;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class BulkFilter extends Filter<Bulk> {
|
public class BulkFilter extends Filter<Bulk> {
|
||||||
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Specification<Bulk> getSpecification() {
|
public Specification<Bulk> getSpecification() {
|
||||||
return (root, query, criteriaBuilder) -> {
|
return (root, query, criteriaBuilder) -> {
|
||||||
final List<Predicate> predicates = new ArrayList<>();
|
final List<Predicate> predicates = new ArrayList<>();
|
||||||
if (id != null) {
|
|
||||||
predicates.add(criteriaBuilder.equal(root.get("id"), id));
|
|
||||||
}
|
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
predicates.add(criteriaBuilder.like(root.get("name"), "%" + name + "%"));
|
Arrays.stream(name.split("\\W+"))
|
||||||
|
.filter(p -> !p.isEmpty())
|
||||||
|
.map(name -> criteriaBuilder.like(root.get("name"), "%" + name + "%"))
|
||||||
|
.forEach(predicates::add);
|
||||||
}
|
}
|
||||||
return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
|
return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,13 +1,15 @@
|
|||||||
package de.ph87.homeautomation.bulk;
|
package de.ph87.homeautomation.bulk;
|
||||||
|
|
||||||
|
import de.ph87.homeautomation.bulk.entry.BulkEntry;
|
||||||
|
import de.ph87.homeautomation.bulk.entry.BulkEntryDto;
|
||||||
import de.ph87.homeautomation.property.PropertyDto;
|
import de.ph87.homeautomation.property.PropertyDto;
|
||||||
import de.ph87.homeautomation.property.PropertyMapper;
|
import de.ph87.homeautomation.property.PropertyMapper;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@Transactional
|
@Transactional
|
||||||
@ -17,15 +19,13 @@ public class BulkMapper {
|
|||||||
private final PropertyMapper propertyMapper;
|
private final PropertyMapper propertyMapper;
|
||||||
|
|
||||||
public BulkDto toDto(final Bulk bulk) {
|
public BulkDto toDto(final Bulk bulk) {
|
||||||
final List<BulkEntryDto> entries = bulk.getEntries().stream().map(this::toDto).collect(Collectors.toList());
|
final List<BulkEntryDto> entries = new ArrayList<>();
|
||||||
|
for (int position = 0; position < bulk.getEntries().size(); position++) {
|
||||||
|
entries.add(toDto(bulk.getEntries().get(position)));
|
||||||
|
}
|
||||||
return new BulkDto(bulk, entries);
|
return new BulkDto(bulk, entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BulkEntryDto toDto(final BulkEntry bulkEntry) {
|
|
||||||
final PropertyDto property = propertyMapper.toDto(bulkEntry.getProperty());
|
|
||||||
return new BulkEntryDto(bulkEntry, property);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BulkDto toDtoOrNull(final Bulk bulk) {
|
public BulkDto toDtoOrNull(final Bulk bulk) {
|
||||||
if (bulk == null) {
|
if (bulk == null) {
|
||||||
return null;
|
return null;
|
||||||
@ -33,4 +33,9 @@ public class BulkMapper {
|
|||||||
return toDto(bulk);
|
return toDto(bulk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BulkEntryDto toDto(final BulkEntry entry) {
|
||||||
|
final PropertyDto property = propertyMapper.toDto(entry.getProperty());
|
||||||
|
return new BulkEntryDto(entry, property);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package de.ph87.homeautomation.bulk;
|
package de.ph87.homeautomation.bulk;
|
||||||
|
|
||||||
|
import de.ph87.homeautomation.web.NotFoundException;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
@ -27,14 +28,13 @@ public class BulkReader {
|
|||||||
return bulkRepository.findAll(filter.getSpecification(), filter.getPageable()).map(bulkMapper::toDto);
|
return bulkRepository.findAll(filter.getSpecification(), filter.getPageable()).map(bulkMapper::toDto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated(since = "Use 'filter' instead", forRemoval = true)
|
|
||||||
public BulkDto getDtoById(final long id) {
|
public BulkDto getDtoById(final long id) {
|
||||||
return bulkMapper.toDto(getById(id));
|
return bulkMapper.toDto(getById(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated(since = "Use 'filter' instead", forRemoval = true)
|
@Deprecated(since = "Use 'filter' instead", forRemoval = true)
|
||||||
public List<BulkDto> findAllDtoLike(final String term) {
|
public List<BulkDto> findAllDtoLike(final String term) {
|
||||||
return bulkRepository.findAllByNameLike(term).stream().map(bulkMapper::toDto).collect(Collectors.toList());
|
return bulkRepository.findAllByNameLikeIgnoreCase(term).stream().map(bulkMapper::toDto).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated(since = "Use 'filter' instead", forRemoval = true)
|
@Deprecated(since = "Use 'filter' instead", forRemoval = true)
|
||||||
@ -42,4 +42,8 @@ public class BulkReader {
|
|||||||
return bulkRepository.findAll().stream().map(bulkMapper::toDto).collect(Collectors.toList());
|
return bulkRepository.findAll().stream().map(bulkMapper::toDto).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Bulk getBulkByEntryId(final long id) {
|
||||||
|
return bulkRepository.findByEntries_Id(id).orElseThrow(NotFoundException.supply(Bulk.class, "entries_id", id));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,10 +4,13 @@ import org.springframework.data.jpa.repository.JpaRepository;
|
|||||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
public interface BulkRepository extends JpaRepository<Bulk, Long>, JpaSpecificationExecutor<Bulk> {
|
public interface BulkRepository extends JpaRepository<Bulk, Long>, JpaSpecificationExecutor<Bulk> {
|
||||||
|
|
||||||
@Deprecated(since = "Use 'filter' instead", forRemoval = true)
|
@Deprecated(since = "Use 'filter' instead", forRemoval = true)
|
||||||
List<Bulk> findAllByNameLike(String term);
|
List<Bulk> findAllByNameLikeIgnoreCase(String term);
|
||||||
|
|
||||||
|
Optional<Bulk> findByEntries_Id(long id);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,14 +1,11 @@
|
|||||||
package de.ph87.homeautomation.bulk;
|
package de.ph87.homeautomation.bulk;
|
||||||
|
|
||||||
import de.ph87.homeautomation.property.PropertyReadService;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
@ -22,11 +19,8 @@ public class BulkWriter {
|
|||||||
|
|
||||||
private final BulkMapper bulkMapper;
|
private final BulkMapper bulkMapper;
|
||||||
|
|
||||||
private final PropertyReadService propertyReadService;
|
|
||||||
|
|
||||||
public Bulk create(final BulkCreateDto dto) {
|
public Bulk create(final BulkCreateDto dto) {
|
||||||
final List<BulkEntry> entries = dto.getEntries().stream().map(e -> new BulkEntry(e, propertyReadService.getById(e.getPropertyId()))).collect(Collectors.toList());
|
final Bulk bulk = bulkRepository.save(new Bulk(dto));
|
||||||
final Bulk bulk = bulkRepository.save(new Bulk(dto, entries));
|
|
||||||
log.info("Bulk created: {}", bulk);
|
log.info("Bulk created: {}", bulk);
|
||||||
return bulk;
|
return bulk;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,27 +1,42 @@
|
|||||||
package de.ph87.homeautomation.bulk;
|
package de.ph87.homeautomation.bulk.entry;
|
||||||
|
|
||||||
import de.ph87.homeautomation.property.Property;
|
import de.ph87.homeautomation.property.Property;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
|
|
||||||
import javax.persistence.Column;
|
import javax.persistence.*;
|
||||||
import javax.persistence.Embeddable;
|
|
||||||
import javax.persistence.ManyToOne;
|
|
||||||
|
|
||||||
@Embeddable
|
@Entity
|
||||||
@Getter
|
@Getter
|
||||||
@ToString
|
@ToString
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
public class BulkEntry {
|
public class BulkEntry {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private long id;
|
||||||
|
|
||||||
|
@Version
|
||||||
|
private long version;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
private boolean enabled;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
private int position;
|
||||||
|
|
||||||
|
@Setter
|
||||||
@ManyToOne(optional = false)
|
@ManyToOne(optional = false)
|
||||||
private Property property;
|
private Property property;
|
||||||
|
|
||||||
|
@Setter
|
||||||
@Column(name = "value_")
|
@Column(name = "value_")
|
||||||
private double value;
|
private double value;
|
||||||
|
|
||||||
public BulkEntry(final BulkEntryCreateDto dto, final Property property) {
|
public BulkEntry(final BulkEntryCreateDto dto, final Property property) {
|
||||||
|
this.position = dto.getPosition();
|
||||||
this.property = property;
|
this.property = property;
|
||||||
this.value = dto.getValue();
|
this.value = dto.getValue();
|
||||||
}
|
}
|
||||||
@ -0,0 +1,44 @@
|
|||||||
|
package de.ph87.homeautomation.bulk.entry;
|
||||||
|
|
||||||
|
import de.ph87.homeautomation.bulk.BulkMapper;
|
||||||
|
import de.ph87.homeautomation.property.PropertyReader;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("BulkEntry")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class BulkEntryController {
|
||||||
|
|
||||||
|
private final BulkEntryWriter bulkEntryWriter;
|
||||||
|
|
||||||
|
private final BulkMapper bulkMapper;
|
||||||
|
|
||||||
|
private final PropertyReader propertyReader;
|
||||||
|
|
||||||
|
@PostMapping("create")
|
||||||
|
public BulkEntryDto create(@RequestBody final BulkEntryCreateDto dto) {
|
||||||
|
return bulkMapper.toDto(bulkEntryWriter.create(dto));
|
||||||
|
}
|
||||||
|
|
||||||
|
@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))));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("{id}/set/value")
|
||||||
|
public BulkEntryDto setValue(@PathVariable final long id, @RequestBody final double value) {
|
||||||
|
return bulkMapper.toDto(bulkEntryWriter.set(id, entry -> entry.setValue(value)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("move/{id}/{indexFrom}/{indexTo}")
|
||||||
|
public BulkEntryDto move(@PathVariable final long id, @PathVariable final int indexTo) {
|
||||||
|
return bulkEntryWriter.move(id, indexTo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("{id}")
|
||||||
|
public void remove(@PathVariable final long id) {
|
||||||
|
bulkEntryWriter.remove(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
package de.ph87.homeautomation.bulk.entry;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class BulkEntryCreateDto {
|
||||||
|
|
||||||
|
private final long bulkId;
|
||||||
|
|
||||||
|
private final Long propertyId;
|
||||||
|
|
||||||
|
private final double value;
|
||||||
|
|
||||||
|
private final int position;
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
package de.ph87.homeautomation.bulk.entry;
|
||||||
|
|
||||||
|
import de.ph87.homeautomation.property.PropertyDto;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class BulkEntryDto {
|
||||||
|
|
||||||
|
private final long id;
|
||||||
|
|
||||||
|
private final long version;
|
||||||
|
|
||||||
|
private final int position;
|
||||||
|
|
||||||
|
private final boolean enabled;
|
||||||
|
|
||||||
|
private final PropertyDto property;
|
||||||
|
|
||||||
|
private final double value;
|
||||||
|
|
||||||
|
public BulkEntryDto(final BulkEntry entry, final PropertyDto propertyDto) {
|
||||||
|
this.id = entry.getId();
|
||||||
|
this.version = entry.getVersion();
|
||||||
|
this.enabled = entry.isEnabled();
|
||||||
|
this.position = entry.getPosition();
|
||||||
|
this.property = propertyDto;
|
||||||
|
this.value = entry.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
package de.ph87.homeautomation.bulk.entry;
|
||||||
|
|
||||||
|
import de.ph87.homeautomation.property.PropertyDto;
|
||||||
|
import de.ph87.homeautomation.property.PropertyMapper;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@Transactional
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class BulkEntryMapper {
|
||||||
|
|
||||||
|
private final PropertyMapper propertyMapper;
|
||||||
|
|
||||||
|
public BulkEntryDto toDto(final BulkEntry entry) {
|
||||||
|
final PropertyDto property = propertyMapper.toDto(entry.getProperty());
|
||||||
|
return new BulkEntryDto(entry, property);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,77 @@
|
|||||||
|
package de.ph87.homeautomation.bulk.entry;
|
||||||
|
|
||||||
|
import de.ph87.homeautomation.bulk.Bulk;
|
||||||
|
import de.ph87.homeautomation.bulk.BulkReader;
|
||||||
|
import de.ph87.homeautomation.bulk.BulkWriter;
|
||||||
|
import de.ph87.homeautomation.property.Property;
|
||||||
|
import de.ph87.homeautomation.property.PropertyReader;
|
||||||
|
import de.ph87.homeautomation.web.NotFoundException;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@Transactional
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class BulkEntryWriter {
|
||||||
|
|
||||||
|
private final PropertyReader propertyReader;
|
||||||
|
|
||||||
|
private final BulkWriter bulkWriter;
|
||||||
|
|
||||||
|
private final BulkReader bulkReader;
|
||||||
|
|
||||||
|
private final BulkEntryMapper bulkEntryMapper;
|
||||||
|
|
||||||
|
public BulkEntry create(final BulkEntryCreateDto dto) {
|
||||||
|
final Property property = dto.getPropertyId() == null ? null : propertyReader.getById(dto.getPropertyId());
|
||||||
|
final BulkEntry entry = new BulkEntry(dto, property);
|
||||||
|
bulkWriter.set(dto.getBulkId(), bulk -> {
|
||||||
|
bulk.getEntries().add(dto.getPosition(), entry);
|
||||||
|
updatePositions(bulk);
|
||||||
|
});
|
||||||
|
log.info("BulkEntry created: {}", entry);
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BulkEntryDto move(final long id, final int position) {
|
||||||
|
final Bulk bulk = bulkReader.getBulkByEntryId(id);
|
||||||
|
final BulkEntry entry = getEntryById(bulk, id);
|
||||||
|
final int oldIndex = bulk.getEntries().indexOf(entry);
|
||||||
|
bulk.getEntries().remove(entry);
|
||||||
|
bulk.getEntries().add(position, entry);
|
||||||
|
updatePositions(bulk);
|
||||||
|
log.info("BulkEntry moved from {} to {}: {}", oldIndex, position, entry);
|
||||||
|
return bulkEntryMapper.toDto(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void updatePositions(final Bulk bulk) {
|
||||||
|
for (int p = 0; p < bulk.getEntries().size(); p++) {
|
||||||
|
bulk.getEntries().get(p).setPosition(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(final long id) {
|
||||||
|
getEntryById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
private BulkEntry getEntryById(final long id) {
|
||||||
|
final Bulk bulk = bulkReader.getBulkByEntryId(id);
|
||||||
|
return getEntryById(bulk, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BulkEntry getEntryById(final Bulk bulk, final long id) {
|
||||||
|
return bulk.getEntries().stream().filter(e -> e.getId() == id).findFirst().orElseThrow(NotFoundException.supply(BulkEntry.class, "Bulk#" + bulk.getId() + ".entries.id", id));
|
||||||
|
}
|
||||||
|
|
||||||
|
public BulkEntry set(final long id, final Consumer<BulkEntry> consumer) {
|
||||||
|
final BulkEntry entry = getEntryById(id);
|
||||||
|
consumer.accept(entry);
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -22,8 +22,8 @@ public class ChannelController implements ISearchController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@GetMapping("getById/{id}")
|
@GetMapping("searchById/{id}")
|
||||||
public SearchResult getById(@PathVariable final long id) {
|
public SearchResult searchById(@PathVariable final long id) {
|
||||||
return channelService.findDtoById(id).map(this::toSearchResult).orElseThrow(() -> new NotFoundException("Channel.id=" + id));
|
return channelService.findDtoById(id).map(this::toSearchResult).orElseThrow(() -> new NotFoundException("Channel.id=" + id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -53,7 +53,7 @@ public class ChannelService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public List<? extends ChannelDto> findAllDtoLike(final String term) {
|
public List<? extends ChannelDto> findAllDtoLike(final String term) {
|
||||||
return channelOwners.stream().map(owner -> owner.findAllDtoLike(term)).reduce(new ArrayList<>(), Helpers::merge);
|
return channelOwners.stream().map(owner -> owner.findAllDtoLikeIgnoreCase(term)).reduce(new ArrayList<>(), Helpers::merge);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<? extends ChannelDto> findDtoById(final long id) {
|
public Optional<? extends ChannelDto> findDtoById(final long id) {
|
||||||
|
|||||||
@ -12,6 +12,6 @@ public interface IChannelOwner {
|
|||||||
|
|
||||||
List<? extends ChannelDto> findAllDto();
|
List<? extends ChannelDto> findAllDto();
|
||||||
|
|
||||||
List<? extends ChannelDto> findAllDtoLike(final String like);
|
List<? extends ChannelDto> findAllDtoLikeIgnoreCase(final String like);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@ package de.ph87.homeautomation.device;
|
|||||||
|
|
||||||
import de.ph87.homeautomation.device.devices.Device;
|
import de.ph87.homeautomation.device.devices.Device;
|
||||||
import de.ph87.homeautomation.device.devices.DeviceDto;
|
import de.ph87.homeautomation.device.devices.DeviceDto;
|
||||||
import de.ph87.homeautomation.property.PropertyReadService;
|
import de.ph87.homeautomation.property.PropertyReader;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
@ -19,14 +19,14 @@ public class DeviceController {
|
|||||||
|
|
||||||
private final DeviceWriteService deviceWriteService;
|
private final DeviceWriteService deviceWriteService;
|
||||||
|
|
||||||
private final PropertyReadService propertyReadService;
|
private final PropertyReader propertyReader;
|
||||||
|
|
||||||
@GetMapping("findAll")
|
@GetMapping("findAll")
|
||||||
public List<DeviceDto> findAll() {
|
public List<DeviceDto> findAll() {
|
||||||
return deviceReadService.findAll();
|
return deviceReadService.findAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("getById/{id}")
|
@GetMapping("searchById/{id}")
|
||||||
public DeviceDto getById(@PathVariable final long id) {
|
public DeviceDto getById(@PathVariable final long id) {
|
||||||
return deviceReadService.getDtoById(id);
|
return deviceReadService.getDtoById(id);
|
||||||
}
|
}
|
||||||
@ -53,22 +53,22 @@ public class DeviceController {
|
|||||||
|
|
||||||
@PostMapping("set/{id}/DeviceSwitch/stateProperty")
|
@PostMapping("set/{id}/DeviceSwitch/stateProperty")
|
||||||
public DeviceDto setDeviceSwitchStateProperty(@PathVariable final long id, @RequestBody(required = false) final Long propertyId) {
|
public DeviceDto setDeviceSwitchStateProperty(@PathVariable final long id, @RequestBody(required = false) final Long propertyId) {
|
||||||
return deviceWriteService.setDeviceSwitch(id, (device, v) -> device.setStateProperty(mapOrNull(v, propertyReadService::getById)), propertyId);
|
return deviceWriteService.setDeviceSwitch(id, (device, v) -> device.setStateProperty(mapOrNull(v, propertyReader::getById)), propertyId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("set/{id}/DeviceStateScene/stateProperty")
|
@PostMapping("set/{id}/DeviceStateScene/stateProperty")
|
||||||
public DeviceDto setDeviceStateSceneStateProperty(@PathVariable final long id, @RequestBody(required = false) final Long propertyId) {
|
public DeviceDto setDeviceStateSceneStateProperty(@PathVariable final long id, @RequestBody(required = false) final Long propertyId) {
|
||||||
return deviceWriteService.setDeviceStateScene(id, (device, v) -> device.setStateProperty(mapOrNull(v, propertyReadService::getById)), propertyId);
|
return deviceWriteService.setDeviceStateScene(id, (device, v) -> device.setStateProperty(mapOrNull(v, propertyReader::getById)), propertyId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("set/{id}/DeviceStateScene/sceneProperty")
|
@PostMapping("set/{id}/DeviceStateScene/sceneProperty")
|
||||||
public DeviceDto setDeviceStateSceneSceneProperty(@PathVariable final long id, @RequestBody(required = false) final Long propertyId) {
|
public DeviceDto setDeviceStateSceneSceneProperty(@PathVariable final long id, @RequestBody(required = false) final Long propertyId) {
|
||||||
return deviceWriteService.setDeviceStateScene(id, (device, v) -> device.setSceneProperty(mapOrNull(v, propertyReadService::getById)), propertyId);
|
return deviceWriteService.setDeviceStateScene(id, (device, v) -> device.setSceneProperty(mapOrNull(v, propertyReader::getById)), propertyId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("set/{id}/DeviceShutter/positionProperty")
|
@PostMapping("set/{id}/DeviceShutter/positionProperty")
|
||||||
public DeviceDto setDeviceShutterPositionProperty(@PathVariable final long id, @RequestBody(required = false) final Long propertyId) {
|
public DeviceDto setDeviceShutterPositionProperty(@PathVariable final long id, @RequestBody(required = false) final Long propertyId) {
|
||||||
return deviceWriteService.setDeviceShutter(id, (device, v) -> device.setPositionProperty(mapOrNull(v, propertyReadService::getById)), propertyId);
|
return deviceWriteService.setDeviceShutter(id, (device, v) -> device.setPositionProperty(mapOrNull(v, propertyReader::getById)), propertyId);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,7 +41,7 @@ public class KnxGroupChannelOwnerService implements IChannelOwner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<KnxGroupDto> findAllDtoLike(final String like) {
|
public List<KnxGroupDto> findAllDtoLikeIgnoreCase(final String like) {
|
||||||
return knxGroupReadService.findAllLike(like).stream().map(this::toDto).collect(Collectors.toList());
|
return knxGroupReadService.findAllLike(like).stream().map(this::toDto).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -19,17 +19,41 @@ import java.util.regex.Pattern;
|
|||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class KnxGroupImportService {
|
public class KnxGroupImportService {
|
||||||
|
|
||||||
|
private static final File ETS_HOME = new File("./data/Zuhause-ETS5");
|
||||||
|
|
||||||
private final KnxGroupRepository knxGroupRepository;
|
private final KnxGroupRepository knxGroupRepository;
|
||||||
|
|
||||||
public void importGroups() {
|
public void importGroups() {
|
||||||
|
try {
|
||||||
|
execute("/usr/bin/git", "fetch", "--all");
|
||||||
|
execute("/usr/bin/git", "checkout", "master", "--force");
|
||||||
|
execute("/usr/bin/git", "reset", "--hard", "origin/master");
|
||||||
|
} catch (IOException | InterruptedException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
knxGroupRepository.findAll().forEach(knxGroup -> knxGroup.setEts(false));
|
knxGroupRepository.findAll().forEach(knxGroup -> knxGroup.setEts(false));
|
||||||
try {
|
try {
|
||||||
Jsoup.parse(new File("./data/Zuhause-ETS5/G"), "UTF-8").select("GA").forEach(this::importGroup);
|
Jsoup.parse(new File(ETS_HOME, "G"), "UTF-8").select("GA").forEach(this::importGroup);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.error("Failed to import KnxGroups: {}", e.toString());
|
log.error("Failed to import KnxGroups: {}", e.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void execute(final String... command) throws IOException, InterruptedException {
|
||||||
|
log.info("{}", (Object) command);
|
||||||
|
final ProcessBuilder fetchBuilder = new ProcessBuilder(command);
|
||||||
|
fetchBuilder.directory(ETS_HOME);
|
||||||
|
fetchBuilder.redirectErrorStream(true);
|
||||||
|
final Process fetch = fetchBuilder.start();
|
||||||
|
fetch.waitFor();
|
||||||
|
final String output = new String(fetch.getInputStream().readAllBytes());
|
||||||
|
if (!output.matches("^\\s*$")) {
|
||||||
|
for (final String line : output.split("[\n\r]+")) {
|
||||||
|
log.info("GIT: {}", line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void importGroup(final Element ga) {
|
private void importGroup(final Element ga) {
|
||||||
final GroupAddress address = new GroupAddress(Integer.parseInt(ga.attr("Address")));
|
final GroupAddress address = new GroupAddress(Integer.parseInt(ga.attr("Address")));
|
||||||
final String name = ga.attr("Name");
|
final String name = ga.attr("Name");
|
||||||
@ -47,12 +71,18 @@ public class KnxGroupImportService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setDpt(final KnxGroup knxGroup, final String dptString) {
|
private void setDpt(final KnxGroup knxGroup, final String dptString) {
|
||||||
final Matcher matcher = Pattern.compile("^DPST-(?<main>\\d+)-(?<sub>\\d+)$").matcher(dptString);
|
final Matcher mainSub = Pattern.compile("^DPST-(?<main>\\d+)-(?<sub>\\d+)$").matcher(dptString);
|
||||||
if (!matcher.matches()) {
|
if (mainSub.matches()) {
|
||||||
throw new RuntimeException();
|
knxGroup.setDptMain(Integer.parseInt(mainSub.group("main")));
|
||||||
|
knxGroup.setDptSub(Integer.parseInt(mainSub.group("sub")));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Matcher main = Pattern.compile("^DPT-(?<main>\\d+)$").matcher(dptString);
|
||||||
|
if (main.matches()) {
|
||||||
|
knxGroup.setDptMain(Integer.parseInt(main.group("main")));
|
||||||
|
knxGroup.setDptSub(0);
|
||||||
}
|
}
|
||||||
knxGroup.setDptMain(Integer.parseInt(matcher.group("main")));
|
|
||||||
knxGroup.setDptSub(Integer.parseInt(matcher.group("sub")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,7 +40,7 @@ public class LogicChannelOwner implements IChannelOwner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<LogicDto> findAllDtoLike(final String like) {
|
public List<LogicDto> findAllDtoLikeIgnoreCase(final String like) {
|
||||||
return logicReader.findAllDtoLike(like);
|
return logicReader.findAllDtoLike(like);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -30,7 +30,6 @@ public class LogicWriter {
|
|||||||
private final WebSocketService webSocketService;
|
private final WebSocketService webSocketService;
|
||||||
|
|
||||||
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMPLETION)
|
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMPLETION)
|
||||||
// @Transactional(propagation = Propagation.REQUIRES_NEW)
|
|
||||||
public void onPropertyChanged(final PropertyDto dto) {
|
public void onPropertyChanged(final PropertyDto dto) {
|
||||||
log.debug("Listen [{}]: {}", getCurrentTransactionName(), dto.getTitle());
|
log.debug("Listen [{}]: {}", getCurrentTransactionName(), dto.getTitle());
|
||||||
logicReader.findAllByPropertyId(dto.getId()).forEach(this::update);
|
logicReader.findAllByPropertyId(dto.getId()).forEach(this::update);
|
||||||
|
|||||||
@ -16,7 +16,7 @@ public class PropertyController implements ISearchController {
|
|||||||
|
|
||||||
private final PropertyWriteService propertyWriteService;
|
private final PropertyWriteService propertyWriteService;
|
||||||
|
|
||||||
private final PropertyReadService propertyReadService;
|
private final PropertyReader propertyReader;
|
||||||
|
|
||||||
private final ChannelService channelService;
|
private final ChannelService channelService;
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ public class PropertyController implements ISearchController {
|
|||||||
|
|
||||||
@GetMapping("findAll")
|
@GetMapping("findAll")
|
||||||
public List<PropertyDto> findAll() {
|
public List<PropertyDto> findAll() {
|
||||||
return propertyReadService.findAllDto();
|
return propertyReader.findAllDto();
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("set/{id}/type")
|
@PostMapping("set/{id}/type")
|
||||||
@ -47,12 +47,17 @@ public class PropertyController implements ISearchController {
|
|||||||
|
|
||||||
@PostMapping("set/{id}/readChannel")
|
@PostMapping("set/{id}/readChannel")
|
||||||
public PropertyDto setReadChannel(@PathVariable final long id, @RequestBody(required = false) final Long channelId) {
|
public PropertyDto setReadChannel(@PathVariable final long id, @RequestBody(required = false) final Long channelId) {
|
||||||
return propertyWriteService.set(id, (p, v) -> p.setReadChannel(channelService.getById(v)), channelId);
|
return propertyWriteService.set(id, (p, v) -> p.setReadChannel(channelId == null ? null : channelService.getById(v)), channelId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("set/{id}/writeChannel")
|
@PostMapping("set/{id}/writeChannel")
|
||||||
public PropertyDto setWriteChannel(@PathVariable final long id, @RequestBody(required = false) final Long channelId) {
|
public PropertyDto setWriteChannel(@PathVariable final long id, @RequestBody(required = false) final Long channelId) {
|
||||||
return propertyWriteService.set(id, (p, v) -> p.setWriteChannel(channelService.getById(v)), channelId);
|
return propertyWriteService.set(id, (p, v) -> p.setWriteChannel(channelId == null ? null : channelService.getById(v)), channelId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("{id}")
|
||||||
|
public void delete(@PathVariable final long id) {
|
||||||
|
propertyWriteService.delete(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("toggle/{id}")
|
@PostMapping("toggle/{id}")
|
||||||
@ -62,7 +67,7 @@ public class PropertyController implements ISearchController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean getOldStateBoolean(final long id, final boolean orElse) {
|
private boolean getOldStateBoolean(final long id, final boolean orElse) {
|
||||||
final Double oldValue = propertyReadService.getDtoById(id).getValue();
|
final Double oldValue = propertyReader.getDtoById(id).getValue();
|
||||||
if (oldValue == null || oldValue.isNaN()) {
|
if (oldValue == null || oldValue.isNaN()) {
|
||||||
return orElse;
|
return orElse;
|
||||||
}
|
}
|
||||||
@ -70,15 +75,15 @@ public class PropertyController implements ISearchController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@GetMapping("getById/{id}")
|
@GetMapping("searchById/{id}")
|
||||||
public SearchResult getById(@PathVariable final long id) {
|
public SearchResult searchById(@PathVariable final long id) {
|
||||||
return toSearchResult(propertyReadService.getDtoById(id));
|
return toSearchResult(propertyReader.getDtoById(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@PostMapping("searchLike")
|
@PostMapping("searchLike")
|
||||||
public List<SearchResult> searchLike(@RequestBody final String term) {
|
public List<SearchResult> searchLike(@RequestBody final String term) {
|
||||||
return propertyReadService.findAllDtoLike("%" + term + "%").stream().map(this::toSearchResult).collect(Collectors.toList());
|
return propertyReader.findAllDtoLike("%" + term + "%").stream().map(this::toSearchResult).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
private SearchResult toSearchResult(final PropertyDto propertyDto) {
|
private SearchResult toSearchResult(final PropertyDto propertyDto) {
|
||||||
|
|||||||
@ -12,7 +12,7 @@ import java.util.stream.Collectors;
|
|||||||
@Service
|
@Service
|
||||||
@Transactional
|
@Transactional
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class PropertyReadService {
|
public class PropertyReader {
|
||||||
|
|
||||||
private final PropertyRepository propertyRepository;
|
private final PropertyRepository propertyRepository;
|
||||||
|
|
||||||
@ -23,7 +23,7 @@ public class PropertyReadService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public List<PropertyDto> findAllDtoLike(final String like) {
|
public List<PropertyDto> findAllDtoLike(final String like) {
|
||||||
return propertyRepository.findAllByTitleLike(like).stream().map(propertyMapper::toDto).collect(Collectors.toList());
|
return propertyRepository.findAllByTitleLikeIgnoreCase(like).stream().map(propertyMapper::toDto).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public PropertyDto getDtoById(final long id) {
|
public PropertyDto getDtoById(final long id) {
|
||||||
@ -1,19 +1,17 @@
|
|||||||
package de.ph87.homeautomation.property;
|
package de.ph87.homeautomation.property;
|
||||||
|
|
||||||
import org.springframework.data.repository.CrudRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
public interface PropertyRepository extends CrudRepository<Property, Long> {
|
public interface PropertyRepository extends JpaRepository<Property, Long> {
|
||||||
|
|
||||||
Optional<Property> findByTitle(String title);
|
Optional<Property> findByTitle(String title);
|
||||||
|
|
||||||
List<Property> findAllByReadChannel_Id(long readChannelId);
|
List<Property> findAllByReadChannel_Id(long readChannelId);
|
||||||
|
|
||||||
List<Property> findAll();
|
List<Property> findAllByTitleLikeIgnoreCase(final String like);
|
||||||
|
|
||||||
List<Property> findAllByTitleLike(final String like);
|
|
||||||
|
|
||||||
boolean existsByTitle(String title);
|
boolean existsByTitle(String title);
|
||||||
|
|
||||||
|
|||||||
@ -26,7 +26,7 @@ public class PropertyWriteService {
|
|||||||
|
|
||||||
private static final String TITLE_PREFIX = "NEU ";
|
private static final String TITLE_PREFIX = "NEU ";
|
||||||
|
|
||||||
private final PropertyReadService propertyReadService;
|
private final PropertyReader propertyReader;
|
||||||
|
|
||||||
private final ChannelService channelService;
|
private final ChannelService channelService;
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ public class PropertyWriteService {
|
|||||||
private final ApplicationEventPublisher applicationEventPublisher;
|
private final ApplicationEventPublisher applicationEventPublisher;
|
||||||
|
|
||||||
public void updateAllProperties() {
|
public void updateAllProperties() {
|
||||||
propertyReadService.findAllByReadChannelNotNull().forEach(property -> {
|
propertyReader.findAllByReadChannelNotNull().forEach(property -> {
|
||||||
final Optional<IChannelOwner> ownerOptional = channelService.findByChannel(property.getReadChannel());
|
final Optional<IChannelOwner> ownerOptional = channelService.findByChannel(property.getReadChannel());
|
||||||
if (ownerOptional.isPresent()) {
|
if (ownerOptional.isPresent()) {
|
||||||
ownerOptional.get().requestUpdate(property.getReadChannel());
|
ownerOptional.get().requestUpdate(property.getReadChannel());
|
||||||
@ -50,10 +50,9 @@ public class PropertyWriteService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMPLETION)
|
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMPLETION)
|
||||||
// @Transactional(propagation = Propagation.REQUIRES_NEW)
|
|
||||||
public void onChannelChanged(final ChannelDto dto) {
|
public void onChannelChanged(final ChannelDto dto) {
|
||||||
log.debug("onChannelChanged [{}]: {}", getCurrentTransactionName(), dto.getTitle());
|
log.debug("onChannelChanged [{}]: {}", getCurrentTransactionName(), dto.getTitle());
|
||||||
final List<Property> properties = propertyReadService.findAllByReadChannel_Id(dto.getId());
|
final List<Property> properties = propertyReader.findAllByReadChannel_Id(dto.getId());
|
||||||
if (!properties.isEmpty()) {
|
if (!properties.isEmpty()) {
|
||||||
properties.forEach(property -> {
|
properties.forEach(property -> {
|
||||||
property.setValue(property.getReadChannel().getValue());
|
property.setValue(property.getReadChannel().getValue());
|
||||||
@ -86,13 +85,13 @@ public class PropertyWriteService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public <T> PropertyDto set(final long id, final BiConsumer<Property, T> setter, final T value) {
|
public <T> PropertyDto set(final long id, final BiConsumer<Property, T> setter, final T value) {
|
||||||
final Property property = propertyReadService.getById(id);
|
final Property property = propertyReader.getById(id);
|
||||||
setter.accept(property, value);
|
setter.accept(property, value);
|
||||||
return publish(property, true);
|
return publish(property, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void delete(final long id) {
|
public void delete(final long id) {
|
||||||
final Property property = propertyReadService.getById(id);
|
final Property property = propertyReader.getById(id);
|
||||||
propertyRepository.delete(property);
|
propertyRepository.delete(property);
|
||||||
publish(property, false);
|
publish(property, false);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,7 +19,7 @@ public class SceneController {
|
|||||||
return sceneReadService.findAll();
|
return sceneReadService.findAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("getById/{id}")
|
@GetMapping("searchById/{id}")
|
||||||
public SceneDto getById(@PathVariable final long id) {
|
public SceneDto getById(@PathVariable final long id) {
|
||||||
return sceneReadService.getDtoById(id);
|
return sceneReadService.getDtoById(id);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
package de.ph87.homeautomation.schedule;
|
package de.ph87.homeautomation.schedule;
|
||||||
|
|
||||||
import de.ph87.homeautomation.property.PropertyReadService;
|
import de.ph87.homeautomation.property.PropertyReader;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
@ -15,14 +15,14 @@ public class ScheduleController {
|
|||||||
|
|
||||||
private final ScheduleWriteService scheduleWriteService;
|
private final ScheduleWriteService scheduleWriteService;
|
||||||
|
|
||||||
private final PropertyReadService propertyReadService;
|
private final PropertyReader propertyReader;
|
||||||
|
|
||||||
@GetMapping("findAll")
|
@GetMapping("findAll")
|
||||||
public List<ScheduleDto> findAll() {
|
public List<ScheduleDto> findAll() {
|
||||||
return scheduleReadService.findAllDtos();
|
return scheduleReadService.findAllDtos();
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("getById/{id}")
|
@GetMapping("searchById/{id}")
|
||||||
public ScheduleDto getById(@PathVariable final long id) {
|
public ScheduleDto getById(@PathVariable final long id) {
|
||||||
return scheduleReadService.getDtoById(id);
|
return scheduleReadService.getDtoById(id);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
package de.ph87.homeautomation.schedule.entry;
|
package de.ph87.homeautomation.schedule.entry;
|
||||||
|
|
||||||
import de.ph87.homeautomation.bulk.BulkReader;
|
import de.ph87.homeautomation.bulk.BulkReader;
|
||||||
import de.ph87.homeautomation.property.PropertyReadService;
|
import de.ph87.homeautomation.property.PropertyReader;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
@ -14,7 +14,7 @@ public class ScheduleEntryController {
|
|||||||
|
|
||||||
private final BulkReader bulkReader;
|
private final BulkReader bulkReader;
|
||||||
|
|
||||||
private final PropertyReadService propertyReadService;
|
private final PropertyReader propertyReader;
|
||||||
|
|
||||||
@GetMapping("create/{scheduleId}")
|
@GetMapping("create/{scheduleId}")
|
||||||
public ScheduleEntryDto create(@PathVariable final long scheduleId) {
|
public ScheduleEntryDto create(@PathVariable final long scheduleId) {
|
||||||
@ -72,8 +72,8 @@ public class ScheduleEntryController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("set/{id}/zenith")
|
@PostMapping("set/{id}/zenith")
|
||||||
public ScheduleEntryDto setZenith(@PathVariable final long id, @RequestBody final String value) {
|
public ScheduleEntryDto setZenith(@PathVariable final long id, @RequestBody final double value) {
|
||||||
return scheduleEntryWriteService.set(id, ScheduleEntry::setZenith, Double.parseDouble(value));
|
return scheduleEntryWriteService.set(id, ScheduleEntry::setZenith, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("set/{id}/hour")
|
@PostMapping("set/{id}/hour")
|
||||||
@ -97,8 +97,8 @@ public class ScheduleEntryController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("set/{id}/property")
|
@PostMapping("set/{id}/property")
|
||||||
public ScheduleEntryDto property(@PathVariable final long id, @RequestBody(required = false) final Long propertyId) {
|
public ScheduleEntryDto setProperty(@PathVariable final long id, @RequestBody(required = false) final Long propertyId) {
|
||||||
return scheduleEntryWriteService.set(id, entry -> entry.setProperty(propertyId == null ? null : propertyReadService.getById(propertyId)));
|
return scheduleEntryWriteService.set(id, entry -> entry.setProperty(propertyId == null ? null : propertyReader.getById(propertyId)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("set/{id}/value")
|
@PostMapping("set/{id}/value")
|
||||||
@ -107,7 +107,7 @@ public class ScheduleEntryController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("set/{id}/bulk")
|
@PostMapping("set/{id}/bulk")
|
||||||
public ScheduleEntryDto bulk(@PathVariable final long id, @RequestBody(required = false) final Long bulkId) {
|
public ScheduleEntryDto setBulk(@PathVariable final long id, @RequestBody(required = false) final Long bulkId) {
|
||||||
return scheduleEntryWriteService.set(id, entry -> entry.setBulk(bulkId == null ? null : bulkReader.getById(bulkId)));
|
return scheduleEntryWriteService.set(id, entry -> entry.setBulk(bulkId == null ? null : bulkReader.getById(bulkId)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import java.util.List;
|
|||||||
|
|
||||||
public interface ISearchController {
|
public interface ISearchController {
|
||||||
|
|
||||||
SearchResult getById(final long id);
|
SearchResult searchById(final long id);
|
||||||
|
|
||||||
List<SearchResult> searchLike(final String term);
|
List<SearchResult> searchLike(final String term);
|
||||||
|
|
||||||
|
|||||||
@ -3,14 +3,20 @@ package de.ph87.homeautomation.web;
|
|||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.web.server.ResponseStatusException;
|
import org.springframework.web.server.ResponseStatusException;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class NotFoundException extends ResponseStatusException {
|
public class NotFoundException extends ResponseStatusException {
|
||||||
|
|
||||||
public NotFoundException(final String message) {
|
public NotFoundException(final String format, final Object... args) {
|
||||||
super(HttpStatus.NOT_FOUND, message);
|
super(HttpStatus.NOT_FOUND, String.format(format, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
public NotFoundException(final String format, final Object... args) {
|
public NotFoundException(final Class<?> clazz, final String key, final Object value) {
|
||||||
this(String.format(format, args));
|
this("Entity not found: %s.%s = %s", clazz.getSimpleName(), key, value == null ? null : "\"" + value + "\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Supplier<NotFoundException> supply(final Class<?> clazz, final String key, final Object value) {
|
||||||
|
return () -> new NotFoundException(clazz, key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user