Compare commits
1 Commits
master
...
expression
| Author | SHA1 | Date | |
|---|---|---|---|
| ded17239b6 |
24
src/main/angular/src/app/api/Automation/Automation.ts
Normal file
24
src/main/angular/src/app/api/Automation/Automation.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import {Expression, expressionFromJson} from '../Expression/Expression';
|
||||
import {validateBoolean, validateString} from '../common/validators';
|
||||
|
||||
export class Automation {
|
||||
|
||||
constructor(
|
||||
readonly uuid: string,
|
||||
readonly name: string,
|
||||
readonly enabled: boolean,
|
||||
readonly condition: Expression,
|
||||
) {
|
||||
//
|
||||
}
|
||||
|
||||
static fromJson(json: any): Automation {
|
||||
return new Automation(
|
||||
validateString(json.uuid),
|
||||
validateString(json.name),
|
||||
validateBoolean(json.enabled),
|
||||
expressionFromJson(json.condition),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
35
src/main/angular/src/app/api/Expression/Expression.ts
Normal file
35
src/main/angular/src/app/api/Expression/Expression.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import {validateString} from '../common/validators';
|
||||
import {ExpressionLiteralBoolean} from './ExpressionLiteralBoolean';
|
||||
import {ExpressionLiteralNumber} from './ExpressionLiteralNumber';
|
||||
import {ExpressionProperty} from './ExpressionProperty';
|
||||
import {ExpressionUnary} from './ExpressionUnary';
|
||||
import {ExpressionNary} from './ExpressionNary';
|
||||
|
||||
export abstract class Expression {
|
||||
|
||||
protected constructor(
|
||||
readonly _type_: string,
|
||||
readonly uuid: string,
|
||||
readonly name: string,
|
||||
) {
|
||||
//
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export function expressionFromJson(json: any): Expression {
|
||||
const _type_ = validateString(json._type_);
|
||||
switch (_type_) {
|
||||
case 'ExpressionLiteralBoolean':
|
||||
return ExpressionLiteralBoolean.fromJson(json);
|
||||
case 'ExpressionLiteralNumber':
|
||||
return ExpressionLiteralNumber.fromJson(json);
|
||||
case 'ExpressionProperty':
|
||||
return ExpressionProperty.fromJson(json);
|
||||
case 'ExpressionUnary':
|
||||
return ExpressionUnary.fromJson(json);
|
||||
case 'ExpressionNary':
|
||||
return ExpressionNary.fromJson(json);
|
||||
}
|
||||
throw Error("expression type not implemented: " + _type_);
|
||||
}
|
||||
14
src/main/angular/src/app/api/Expression/ExpressionLiteral.ts
Normal file
14
src/main/angular/src/app/api/Expression/ExpressionLiteral.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import {Expression} from "./Expression";
|
||||
|
||||
export abstract class ExpressionLiteral<T> extends Expression {
|
||||
|
||||
protected constructor(
|
||||
_type_: string,
|
||||
uuid: string,
|
||||
name: string,
|
||||
readonly literal: T | null,
|
||||
) {
|
||||
super(_type_, uuid, name);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
import {validateBooleanOrNull, validateString} from "../common/validators";
|
||||
|
||||
import {ExpressionLiteral} from './ExpressionLiteral';
|
||||
|
||||
export class ExpressionLiteralBoolean extends ExpressionLiteral<boolean> {
|
||||
|
||||
constructor(
|
||||
_type_: string,
|
||||
uuid: string,
|
||||
name: string,
|
||||
readonly value: boolean | null,
|
||||
) {
|
||||
super(_type_, uuid, name, value);
|
||||
}
|
||||
|
||||
static fromJson(json: any): ExpressionLiteralBoolean {
|
||||
return new ExpressionLiteralBoolean(
|
||||
validateString(json._type_),
|
||||
validateString(json.uuid),
|
||||
validateString(json.name),
|
||||
validateBooleanOrNull(json.value),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
import {validateNumberOrNull, validateString} from "../common/validators";
|
||||
|
||||
import {ExpressionLiteral} from './ExpressionLiteral';
|
||||
|
||||
export class ExpressionLiteralNumber extends ExpressionLiteral<number> {
|
||||
|
||||
constructor(
|
||||
_type_: string,
|
||||
uuid: string,
|
||||
name: string,
|
||||
readonly value: number | null,
|
||||
) {
|
||||
super(_type_, uuid, name, value);
|
||||
}
|
||||
|
||||
static fromJson(json: any): ExpressionLiteralNumber {
|
||||
return new ExpressionLiteralNumber(
|
||||
validateString(json._type_),
|
||||
validateString(json.uuid),
|
||||
validateString(json.name),
|
||||
validateNumberOrNull(json.value),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
29
src/main/angular/src/app/api/Expression/ExpressionNary.ts
Normal file
29
src/main/angular/src/app/api/Expression/ExpressionNary.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import {orNull, validateString} from "../common/validators";
|
||||
import {Expression, expressionFromJson} from './Expression';
|
||||
import {ExpressionNaryOperator} from './ExpressionNaryOperator';
|
||||
|
||||
export class ExpressionNary extends Expression {
|
||||
|
||||
constructor(
|
||||
_type_: string,
|
||||
uuid: string,
|
||||
name: string,
|
||||
readonly operator: ExpressionNaryOperator,
|
||||
readonly expression0: Expression | null,
|
||||
readonly expression1: Expression | null,
|
||||
) {
|
||||
super(_type_, uuid, name);
|
||||
}
|
||||
|
||||
static fromJson(json: any): ExpressionNary {
|
||||
return new ExpressionNary(
|
||||
validateString(json._type_),
|
||||
validateString(json.uuid),
|
||||
validateString(json.name),
|
||||
validateString(json.operator) as ExpressionNaryOperator,
|
||||
orNull(json.expression0, j => expressionFromJson(j)),
|
||||
orNull(json.expression1, j => expressionFromJson(j)),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
export enum ExpressionNaryOperator {
|
||||
OR = 'OR',
|
||||
AND = 'AND',
|
||||
XOR = 'XOR',
|
||||
ADD = 'ADD',
|
||||
SUB = 'SUB',
|
||||
MUL = 'MUL',
|
||||
DIV = 'DIV',
|
||||
MOD = 'MOD',
|
||||
POW = 'POW',
|
||||
HYPOT = 'HYPOT',
|
||||
ATAN2 = 'ATAN2',
|
||||
MIN = 'MIN',
|
||||
MAX = 'MAX',
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
import {validateString} from "../common/validators";
|
||||
import {Expression} from './Expression';
|
||||
|
||||
export class ExpressionProperty extends Expression {
|
||||
|
||||
constructor(
|
||||
_type_: string,
|
||||
uuid: string,
|
||||
name: string,
|
||||
readonly propertyId: string,
|
||||
) {
|
||||
super(_type_, uuid, name);
|
||||
}
|
||||
|
||||
static fromJson(json: any): ExpressionProperty {
|
||||
return new ExpressionProperty(
|
||||
validateString(json._type_),
|
||||
validateString(json.uuid),
|
||||
validateString(json.name),
|
||||
validateString(json.propertyId),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
27
src/main/angular/src/app/api/Expression/ExpressionUnary.ts
Normal file
27
src/main/angular/src/app/api/Expression/ExpressionUnary.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import {orNull, validateString} from "../common/validators";
|
||||
import {Expression, expressionFromJson} from './Expression';
|
||||
import {ExpressionUnaryOperator} from './ExpressionUnaryOperator';
|
||||
|
||||
export class ExpressionUnary extends Expression {
|
||||
|
||||
constructor(
|
||||
_type_: string,
|
||||
uuid: string,
|
||||
name: string,
|
||||
readonly operator: ExpressionUnaryOperator,
|
||||
readonly expression: Expression | null,
|
||||
) {
|
||||
super(_type_, uuid, name);
|
||||
}
|
||||
|
||||
static fromJson(json: any): ExpressionUnary {
|
||||
return new ExpressionUnary(
|
||||
validateString(json._type_),
|
||||
validateString(json.uuid),
|
||||
validateString(json.name),
|
||||
validateString(json.operator) as ExpressionUnaryOperator,
|
||||
orNull(json.expression, j => expressionFromJson(j)),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
export enum ExpressionUnaryOperator {
|
||||
NOT = 'NOT',
|
||||
NEG = 'NEG',
|
||||
POS = 'POS',
|
||||
FLOOR = 'FLOOR',
|
||||
CEIL = 'CEIL',
|
||||
ROUND = 'ROUND',
|
||||
SQRT = 'SQRT',
|
||||
ABS = 'ABS',
|
||||
COS = 'COS',
|
||||
SIN = 'SIN',
|
||||
TAN = 'TAN',
|
||||
ACOS = 'ACOS',
|
||||
ASIN = 'ASIN',
|
||||
ATAN = 'ATAN',
|
||||
COSH = 'COSH',
|
||||
SINH = 'SINH',
|
||||
TANH = 'TANH',
|
||||
EXP = 'EXP',
|
||||
EXPM1 = 'EXPM1',
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
import {Injectable} from '@angular/core';
|
||||
import {ExpressionLiteralBoolean} from './ExpressionLiteralBoolean';
|
||||
import {ApiService} from '../common/api.service';
|
||||
import {CrudService} from '../common/CrudService';
|
||||
import {Next} from '../common/types';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class ExpressionLiteralBooleanService extends CrudService<ExpressionLiteralBoolean> {
|
||||
|
||||
constructor(
|
||||
apiService: ApiService,
|
||||
) {
|
||||
super(apiService, ['ExpressionLiteralBoolean'], ExpressionLiteralBoolean.fromJson);
|
||||
}
|
||||
|
||||
setValue(expression: ExpressionLiteralBoolean, value: boolean, next?: Next<ExpressionLiteralBoolean>) {
|
||||
this.postSingle([expression.uuid, 'setValue'], value, next);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
import {Injectable} from '@angular/core';
|
||||
import {ExpressionLiteralNumber} from './ExpressionLiteralNumber';
|
||||
import {ApiService} from '../common/api.service';
|
||||
import {CrudService} from '../common/CrudService';
|
||||
import {Next} from '../common/types';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class ExpressionLiteralNumberService extends CrudService<ExpressionLiteralNumber> {
|
||||
|
||||
constructor(
|
||||
apiService: ApiService,
|
||||
) {
|
||||
super(apiService, ['ExpressionLiteralNumber'], ExpressionLiteralNumber.fromJson);
|
||||
}
|
||||
|
||||
setValue(expression: ExpressionLiteralNumber, value: number, next?: Next<ExpressionLiteralNumber>) {
|
||||
this.postSingle([expression.uuid, 'setValue'], value, next);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
<input type="checkbox" [ngModel]="expression.value" (ngModelChange)="expressionService.setValue(expression, $event)">
|
||||
@ -0,0 +1,26 @@
|
||||
import {Component, Input} from '@angular/core';
|
||||
import {FormsModule} from '@angular/forms';
|
||||
import {ExpressionLiteralBoolean} from '../../../api/Expression/ExpressionLiteralBoolean';
|
||||
import {ExpressionLiteralBooleanService} from '../../../api/Expression/expression-literal-boolean.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-expression-literal-boolean',
|
||||
standalone: true,
|
||||
imports: [
|
||||
FormsModule
|
||||
],
|
||||
templateUrl: './expression-literal-boolean.component.html',
|
||||
styleUrl: './expression-literal-boolean.component.less'
|
||||
})
|
||||
export class ExpressionLiteralBooleanComponent {
|
||||
|
||||
@Input()
|
||||
expression!: ExpressionLiteralBoolean;
|
||||
|
||||
constructor(
|
||||
readonly expressionService: ExpressionLiteralBooleanService,
|
||||
) {
|
||||
//
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
<input type="number" [ngModel]="expression.value" (ngModelChange)="expressionService.setValue(expression, $event)">
|
||||
@ -0,0 +1,26 @@
|
||||
import {Component, Input} from '@angular/core';
|
||||
import {FormsModule} from '@angular/forms';
|
||||
import {ExpressionLiteralNumber} from '../../../api/Expression/ExpressionLiteralNumber';
|
||||
import {ExpressionLiteralNumberService} from '../../../api/Expression/expression-literal-number.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-expression-literal-number',
|
||||
standalone: true,
|
||||
imports: [
|
||||
FormsModule
|
||||
],
|
||||
templateUrl: './expression-literal-number.component.html',
|
||||
styleUrl: './expression-literal-number.component.less'
|
||||
})
|
||||
export class ExpressionLiteralNumberComponent {
|
||||
|
||||
@Input()
|
||||
expression!: ExpressionLiteralNumber;
|
||||
|
||||
constructor(
|
||||
readonly expressionService: ExpressionLiteralNumberService,
|
||||
) {
|
||||
//
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
<ng-container [ngSwitch]="expression._type_">
|
||||
<ng-container *ngSwitchCase="'ExpressionLiteralDouble'">
|
||||
<app-expression-literal-boolean [expression]="asExpressionLiteralBoolean()"></app-expression-literal-boolean>
|
||||
</ng-container>
|
||||
<ng-container *ngSwitchCase="'ExpressionLiteralDouble'">
|
||||
<app-expression-literal-number [expression]="asExpressionLiteralNumber()"></app-expression-literal-number>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
@ -0,0 +1,49 @@
|
||||
import {Component, Input} from '@angular/core';
|
||||
import {Expression} from '../../api/Expression/Expression';
|
||||
import {ExpressionLiteralBoolean} from '../../api/Expression/ExpressionLiteralBoolean';
|
||||
import {NgSwitch, NgSwitchCase} from '@angular/common';
|
||||
import {ExpressionLiteralNumber} from '../../api/Expression/ExpressionLiteralNumber';
|
||||
import {ExpressionProperty} from '../../api/Expression/ExpressionProperty';
|
||||
import {ExpressionUnary} from '../../api/Expression/ExpressionUnary';
|
||||
import {ExpressionNary} from '../../api/Expression/ExpressionNary';
|
||||
import {ExpressionLiteralBooleanComponent} from './expression-literal-boolean/expression-literal-boolean.component';
|
||||
import {ExpressionLiteralNumberComponent} from './expression-literal-number/expression-literal-number.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-expression',
|
||||
standalone: true,
|
||||
imports: [
|
||||
NgSwitch,
|
||||
NgSwitchCase,
|
||||
ExpressionLiteralBooleanComponent,
|
||||
ExpressionLiteralNumberComponent
|
||||
],
|
||||
templateUrl: './expression.component.html',
|
||||
styleUrl: './expression.component.less'
|
||||
})
|
||||
export class ExpressionComponent {
|
||||
|
||||
@Input()
|
||||
expression!: Expression;
|
||||
|
||||
asExpressionLiteralBoolean(): ExpressionLiteralBoolean {
|
||||
return this.expression as ExpressionLiteralBoolean;
|
||||
}
|
||||
|
||||
asExpressionLiteralNumber(): ExpressionLiteralNumber {
|
||||
return this.expression as ExpressionLiteralNumber;
|
||||
}
|
||||
|
||||
asExpressionProperty(): ExpressionProperty {
|
||||
return this.expression as ExpressionProperty;
|
||||
}
|
||||
|
||||
asExpressionUnary(): ExpressionUnary {
|
||||
return this.expression as ExpressionUnary;
|
||||
}
|
||||
|
||||
asExpressionNary(): ExpressionNary {
|
||||
return this.expression as ExpressionNary;
|
||||
}
|
||||
|
||||
}
|
||||
48
src/main/java/de/ph87/home/automation/Automation.java
Normal file
48
src/main/java/de/ph87/home/automation/Automation.java
Normal file
@ -0,0 +1,48 @@
|
||||
package de.ph87.home.automation;
|
||||
|
||||
import de.ph87.home.expression.AbstractExpression;
|
||||
import de.ph87.home.expression.Runtime;
|
||||
import jakarta.annotation.Nullable;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@Entity
|
||||
@Getter
|
||||
@ToString
|
||||
@NoArgsConstructor
|
||||
public class Automation {
|
||||
|
||||
@Id
|
||||
@NonNull
|
||||
private String uuid = UUID.randomUUID().toString();
|
||||
|
||||
@NonNull
|
||||
@Column(nullable = false)
|
||||
private String name;
|
||||
|
||||
@Column(nullable = false)
|
||||
private boolean enabled = false;
|
||||
|
||||
@Nullable
|
||||
@ManyToOne
|
||||
private AbstractExpression condition;
|
||||
|
||||
public Automation(@NonNull final String name, final boolean enabled, @NonNull final AbstractExpression condition) {
|
||||
this.name = name;
|
||||
this.enabled = enabled;
|
||||
this.condition = condition;
|
||||
}
|
||||
|
||||
public boolean evaluateCondition(@NonNull final Runtime runtime) {
|
||||
return AbstractExpression.mapOrElseNotNull(condition, c -> c.evaluate(runtime), AbstractExpression::convertToBoolean, false);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
package de.ph87.home.automation;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("Automation")
|
||||
public class AutomationController {
|
||||
|
||||
private final AutomationService automationService;
|
||||
|
||||
@GetMapping("list")
|
||||
public List<AutomationDto> list() {
|
||||
return automationService.listDto();
|
||||
}
|
||||
|
||||
}
|
||||
31
src/main/java/de/ph87/home/automation/AutomationDto.java
Normal file
31
src/main/java/de/ph87/home/automation/AutomationDto.java
Normal file
@ -0,0 +1,31 @@
|
||||
package de.ph87.home.automation;
|
||||
|
||||
import de.ph87.home.expression.AbstractExpressionDto;
|
||||
import jakarta.annotation.Nullable;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.ToString;
|
||||
|
||||
@Getter
|
||||
@ToString
|
||||
public class AutomationDto {
|
||||
|
||||
@NonNull
|
||||
private final String uuid;
|
||||
|
||||
@NonNull
|
||||
private final String name;
|
||||
|
||||
private final boolean enabled;
|
||||
|
||||
@Nullable
|
||||
private final AbstractExpressionDto condition;
|
||||
|
||||
public AutomationDto(@NonNull final Automation automation, @Nullable final AbstractExpressionDto condition) {
|
||||
this.uuid = automation.getUuid();
|
||||
this.name = automation.getName();
|
||||
this.enabled = automation.isEnabled();
|
||||
this.condition = condition;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package de.ph87.home.automation;
|
||||
|
||||
import org.springframework.data.repository.ListCrudRepository;
|
||||
|
||||
public interface AutomationRepository extends ListCrudRepository<Automation, String> {
|
||||
|
||||
}
|
||||
36
src/main/java/de/ph87/home/automation/AutomationService.java
Normal file
36
src/main/java/de/ph87/home/automation/AutomationService.java
Normal file
@ -0,0 +1,36 @@
|
||||
package de.ph87.home.automation;
|
||||
|
||||
import de.ph87.home.expression.AbstractExpressionDto;
|
||||
import de.ph87.home.expression.expression.ExpressionService;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static de.ph87.home.expression.AbstractExpression.mapOrElse;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@Transactional
|
||||
@RequiredArgsConstructor
|
||||
public class AutomationService {
|
||||
|
||||
private final AutomationRepository automationRepository;
|
||||
|
||||
private final ExpressionService expressionService;
|
||||
|
||||
@NonNull
|
||||
public List<AutomationDto> listDto() {
|
||||
return automationRepository.findAll().stream().map(this::toDto).toList();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private AutomationDto toDto(@NonNull final Automation automation) {
|
||||
final AbstractExpressionDto condition = mapOrElse(automation.getCondition(), expressionService::toDto, null);
|
||||
return new AutomationDto(automation, condition);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,6 +1,10 @@
|
||||
package de.ph87.home.demo;
|
||||
|
||||
import de.ph87.home.automation.Automation;
|
||||
import de.ph87.home.automation.AutomationRepository;
|
||||
import de.ph87.home.device.DeviceService;
|
||||
import de.ph87.home.expression.expression.ExpressionRepository;
|
||||
import de.ph87.home.expression.expression.literal.bool.ExpressionLiteralBoolean;
|
||||
import de.ph87.home.knx.property.KnxPropertyService;
|
||||
import de.ph87.home.knx.property.KnxPropertyType;
|
||||
import de.ph87.home.shutter.ShutterService;
|
||||
@ -24,6 +28,10 @@ public class DemoService {
|
||||
|
||||
private final ShutterService shutterService;
|
||||
|
||||
private final ExpressionRepository expressionRepository;
|
||||
|
||||
private final AutomationRepository automationRepository;
|
||||
|
||||
@EventListener(ApplicationStartedEvent.class)
|
||||
public void startup() {
|
||||
knxPropertyService.create("eg_ambiente", KnxPropertyType.BOOLEAN, adr(849), adr(848));
|
||||
@ -58,6 +66,9 @@ public class DemoService {
|
||||
|
||||
knxPropertyService.create("kueche_tuer", KnxPropertyType.DOUBLE, adr(2324), adr(2324));
|
||||
shutterService.create("Küche Tür", "kueche_tuer", "kueche_tuer");
|
||||
|
||||
final ExpressionLiteralBoolean exp = expressionRepository.save(new ExpressionLiteralBoolean(true));
|
||||
automationRepository.save(new Automation("test", true, exp));
|
||||
}
|
||||
|
||||
private static GroupAddress adr(final int rawGroupAddress) {
|
||||
|
||||
168
src/main/java/de/ph87/home/expression/AbstractExpression.java
Normal file
168
src/main/java/de/ph87/home/expression/AbstractExpression.java
Normal file
@ -0,0 +1,168 @@
|
||||
package de.ph87.home.expression;
|
||||
|
||||
import jakarta.annotation.Nullable;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
@Getter
|
||||
@ToString
|
||||
@NoArgsConstructor
|
||||
@Entity(name = "expression")
|
||||
@DiscriminatorColumn(name = "_type_")
|
||||
@Inheritance(strategy = InheritanceType.JOINED)
|
||||
public abstract class AbstractExpression {
|
||||
|
||||
@Id
|
||||
@NonNull
|
||||
private String uuid = UUID.randomUUID().toString();
|
||||
|
||||
@NonNull
|
||||
@Column(nullable = false)
|
||||
private String name = "";
|
||||
|
||||
public abstract Object evaluate(@NonNull final Runtime runtime);
|
||||
|
||||
@NonNull
|
||||
public static <T, R> Object applyFallback(final Object v0, final Object v1, @NonNull final Function<Object, T> convert, @NonNull final T fallback, @NonNull final BiFunction<T, T, R> function) {
|
||||
final T c0 = orElseNotNull(convert.apply(v0), fallback);
|
||||
final T c1 = orElseNotNull(convert.apply(v1), fallback);
|
||||
return function.apply(c0, c1);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static <T, R> Object applyNullToNull(final Object value, @NonNull final Function<Object, T> convert, @NonNull final Function<T, R> function) {
|
||||
final T converted = convert.apply(value);
|
||||
if (converted == null) {
|
||||
return null;
|
||||
}
|
||||
return function.apply(converted);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static <T, R> Object applyNullToNull(final Object v0, final Object v1, @NonNull final Function<Object, T> convert, @NonNull final BiFunction<T, T, R> function) {
|
||||
final T c0 = convert.apply(v0);
|
||||
final T c1 = convert.apply(v1);
|
||||
if (c0 == null || c1 == null) {
|
||||
return null;
|
||||
}
|
||||
return function.apply(c0, c1);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Object evalOrNull(@NonNull final Runtime runtime, @Nullable final AbstractExpression expression) {
|
||||
if (expression == null) {
|
||||
return null;
|
||||
}
|
||||
return expression.evaluate(runtime);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Boolean convertToBoolean(@Nullable final Object value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
if (value instanceof Boolean) {
|
||||
return (boolean) value;
|
||||
}
|
||||
final Double number = convertToNumber(value);
|
||||
if (number == null) {
|
||||
return null;
|
||||
}
|
||||
return number > 0;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Double convertToNumber(@Nullable final Object value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
if (value instanceof Number) {
|
||||
return (double) value;
|
||||
}
|
||||
try {
|
||||
return Double.parseDouble((String) value);
|
||||
} catch (NumberFormatException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static <T> T orElseNotNull(@Nullable final T t, @NonNull final T orElse) {
|
||||
if (t == null) {
|
||||
return orElse;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static <T, R> R mapOrElseNotNull(@Nullable final T t, @NonNull final Function<T, R> tr, @NonNull final R orElse) {
|
||||
if (t == null) {
|
||||
return orElse;
|
||||
}
|
||||
final R r = tr.apply(t);
|
||||
if (r == null) {
|
||||
return orElse;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static <T, U, R> R mapOrElseNotNull(@Nullable final T t, @NonNull final Function<T, U> tu, @NonNull final Function<U, R> ur, @NonNull final R orElse) {
|
||||
if (t == null) {
|
||||
return orElse;
|
||||
}
|
||||
final U u = tu.apply(t);
|
||||
if (u == null) {
|
||||
return orElse;
|
||||
}
|
||||
final R r = ur.apply(u);
|
||||
if (r == null) {
|
||||
return orElse;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static <T> T orElse(@Nullable final T t, @Nullable final T orElse) {
|
||||
if (t == null) {
|
||||
return orElse;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static <T, R> R mapOrElse(@Nullable final T t, @NonNull final Function<T, R> tr, @Nullable final R orElse) {
|
||||
if (t == null) {
|
||||
return orElse;
|
||||
}
|
||||
final R r = tr.apply(t);
|
||||
if (r == null) {
|
||||
return orElse;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static <T, U, R> R mapOrElse(@Nullable final T t, @NonNull final Function<T, U> tu, @NonNull final Function<U, R> ur, @Nullable final R orElse) {
|
||||
if (t == null) {
|
||||
return orElse;
|
||||
}
|
||||
final U u = tu.apply(t);
|
||||
if (u == null) {
|
||||
return orElse;
|
||||
}
|
||||
final R r = ur.apply(u);
|
||||
if (r == null) {
|
||||
return orElse;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
package de.ph87.home.expression;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public abstract class AbstractExpressionController<E extends AbstractExpression, D extends AbstractExpressionDto> {
|
||||
|
||||
protected final AbstractExpressionService<E, D> expressionService;
|
||||
|
||||
@GetMapping("{uuid}")
|
||||
public D byUuid(@PathVariable("uuid") String uuid) {
|
||||
return expressionService.getDtoByUuid(uuid);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
package de.ph87.home.expression;
|
||||
|
||||
import jakarta.annotation.Nullable;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.ToString;
|
||||
|
||||
@Getter
|
||||
@ToString
|
||||
public abstract class AbstractExpressionDto {
|
||||
|
||||
@NonNull
|
||||
private final String uuid;
|
||||
|
||||
@NonNull
|
||||
private final String name;
|
||||
|
||||
@Nullable
|
||||
private final Object value;
|
||||
|
||||
protected AbstractExpressionDto(@NonNull final AbstractExpression expression, @Nullable final Object value) {
|
||||
this.uuid = expression.getUuid();
|
||||
this.name = expression.getName();
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
package de.ph87.home.expression;
|
||||
|
||||
import org.springframework.data.repository.ListCrudRepository;
|
||||
import org.springframework.data.repository.NoRepositoryBean;
|
||||
|
||||
@NoRepositoryBean
|
||||
public interface AbstractExpressionRepository<E extends AbstractExpression> extends ListCrudRepository<E, String> {
|
||||
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
package de.ph87.home.expression;
|
||||
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@Transactional
|
||||
@RequiredArgsConstructor
|
||||
public abstract class AbstractExpressionService<E extends AbstractExpression, D extends AbstractExpressionDto> {
|
||||
|
||||
protected final AbstractExpressionRepository<E> repository;
|
||||
|
||||
protected final ApplicationEventPublisher applicationEventPublisher;
|
||||
|
||||
@NonNull
|
||||
public D set(@NonNull final String uuid, @NonNull final Consumer<E> setter) {
|
||||
final E expression = getByUuid(uuid);
|
||||
setter.accept(expression);
|
||||
return publish(expression);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private E getByUuid(@NonNull final String uuid) {
|
||||
return repository.findById(uuid).orElseThrow();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public D getDtoByUuid(@NonNull final String uuid) {
|
||||
return toDto(getByUuid(uuid));
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private D publish(@NonNull final E expression) {
|
||||
final D dto = toDto(expression);
|
||||
applicationEventPublisher.publishEvent(dto);
|
||||
return dto;
|
||||
}
|
||||
|
||||
public abstract D toDto(final E expression);
|
||||
|
||||
}
|
||||
26
src/main/java/de/ph87/home/expression/Runtime.java
Normal file
26
src/main/java/de/ph87/home/expression/Runtime.java
Normal file
@ -0,0 +1,26 @@
|
||||
package de.ph87.home.expression;
|
||||
|
||||
import de.ph87.home.property.PropertyService;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@ToString
|
||||
public class Runtime {
|
||||
|
||||
public final ZonedDateTime now = ZonedDateTime.now();
|
||||
|
||||
public final Map<String, Object> write = new HashMap<>();
|
||||
|
||||
public final PropertyService propertyService;
|
||||
|
||||
public Runtime(@NonNull final PropertyService propertyService) {
|
||||
this.propertyService = propertyService;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package de.ph87.home.expression.expression;
|
||||
|
||||
import de.ph87.home.expression.AbstractExpression;
|
||||
import de.ph87.home.expression.AbstractExpressionController;
|
||||
import de.ph87.home.expression.AbstractExpressionDto;
|
||||
import de.ph87.home.expression.AbstractExpressionService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("Expression")
|
||||
public class ExpressionController extends AbstractExpressionController<AbstractExpression, AbstractExpressionDto> {
|
||||
|
||||
public ExpressionController(final AbstractExpressionService<AbstractExpression, AbstractExpressionDto> expressionService) {
|
||||
super(expressionService);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,60 @@
|
||||
package de.ph87.home.expression.expression;
|
||||
|
||||
import de.ph87.home.expression.AbstractExpression;
|
||||
import de.ph87.home.expression.AbstractExpressionDto;
|
||||
import de.ph87.home.expression.AbstractExpressionRepository;
|
||||
import de.ph87.home.expression.AbstractExpressionService;
|
||||
import de.ph87.home.expression.expression.literal.bool.ExpressionLiteralBoolean;
|
||||
import de.ph87.home.expression.expression.literal.bool.ExpressionLiteralBooleanService;
|
||||
import de.ph87.home.expression.expression.literal.number.ExpressionLiteralDouble;
|
||||
import de.ph87.home.expression.expression.literal.number.ExpressionLiteralDoubleService;
|
||||
import de.ph87.home.expression.expression.list.ExpressionList;
|
||||
import de.ph87.home.expression.expression.list.ExpressionListService;
|
||||
import de.ph87.home.expression.expression.property.ExpressionProperty;
|
||||
import de.ph87.home.expression.expression.property.ExpressionPropertyService;
|
||||
import de.ph87.home.expression.expression.unary.ExpressionUnary;
|
||||
import de.ph87.home.expression.expression.unary.ExpressionUnaryService;
|
||||
import lombok.NonNull;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@Transactional
|
||||
public class ExpressionMapper extends AbstractExpressionService<AbstractExpression, AbstractExpressionDto> {
|
||||
|
||||
private final ExpressionLiteralBooleanService expressionLiteralBooleanService;
|
||||
|
||||
private final ExpressionLiteralDoubleService expressionLiteralDoubleService;
|
||||
|
||||
private final ExpressionUnaryService expressionUnaryService;
|
||||
|
||||
private final ExpressionListService expressionNaryService;
|
||||
|
||||
private final ExpressionPropertyService expressionPropertyService;
|
||||
|
||||
public ExpressionMapper(final AbstractExpressionRepository<AbstractExpression> repository, final ApplicationEventPublisher applicationEventPublisher, final ExpressionLiteralBooleanService expressionLiteralBooleanService, final ExpressionLiteralDoubleService expressionLiteralDoubleService, final ExpressionUnaryService expressionUnaryService, final ExpressionListService expressionNaryService, final ExpressionPropertyService expressionPropertyService) {
|
||||
super(repository, applicationEventPublisher);
|
||||
this.expressionLiteralBooleanService = expressionLiteralBooleanService;
|
||||
this.expressionLiteralDoubleService = expressionLiteralDoubleService;
|
||||
this.expressionUnaryService = expressionUnaryService;
|
||||
this.expressionNaryService = expressionNaryService;
|
||||
this.expressionPropertyService = expressionPropertyService;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public AbstractExpressionDto toDto(@NonNull final AbstractExpression expression) {
|
||||
return switch (expression) {
|
||||
case final ExpressionLiteralBoolean expressionLiteralBoolean -> expressionLiteralBooleanService.toDto(expressionLiteralBoolean);
|
||||
case final ExpressionLiteralDouble expressionLiteralDouble -> expressionLiteralDoubleService.toDto(expressionLiteralDouble);
|
||||
case final ExpressionProperty expressionProperty -> expressionPropertyService.toDto(expressionProperty);
|
||||
case final ExpressionUnary expressionUnary -> expressionUnaryService.toDto(expressionUnary);
|
||||
case final ExpressionList expressionNary -> expressionNaryService.toDto(expressionNary);
|
||||
default -> throw new RuntimeException("Expression type not implemented: " + expression.getClass().getSimpleName());
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
package de.ph87.home.expression.expression;
|
||||
|
||||
import de.ph87.home.expression.AbstractExpression;
|
||||
import de.ph87.home.expression.AbstractExpressionRepository;
|
||||
|
||||
public interface ExpressionRepository extends AbstractExpressionRepository<AbstractExpression> {
|
||||
|
||||
}
|
||||
@ -0,0 +1,60 @@
|
||||
package de.ph87.home.expression.expression;
|
||||
|
||||
import de.ph87.home.expression.AbstractExpression;
|
||||
import de.ph87.home.expression.AbstractExpressionDto;
|
||||
import de.ph87.home.expression.AbstractExpressionRepository;
|
||||
import de.ph87.home.expression.AbstractExpressionService;
|
||||
import de.ph87.home.expression.expression.literal.bool.ExpressionLiteralBoolean;
|
||||
import de.ph87.home.expression.expression.literal.bool.ExpressionLiteralBooleanService;
|
||||
import de.ph87.home.expression.expression.literal.number.ExpressionLiteralDouble;
|
||||
import de.ph87.home.expression.expression.literal.number.ExpressionLiteralDoubleService;
|
||||
import de.ph87.home.expression.expression.list.ExpressionList;
|
||||
import de.ph87.home.expression.expression.list.ExpressionListService;
|
||||
import de.ph87.home.expression.expression.property.ExpressionProperty;
|
||||
import de.ph87.home.expression.expression.property.ExpressionPropertyService;
|
||||
import de.ph87.home.expression.expression.unary.ExpressionUnary;
|
||||
import de.ph87.home.expression.expression.unary.ExpressionUnaryService;
|
||||
import lombok.NonNull;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@Transactional
|
||||
public class ExpressionService extends AbstractExpressionService<AbstractExpression, AbstractExpressionDto> {
|
||||
|
||||
private final ExpressionLiteralBooleanService expressionLiteralBooleanService;
|
||||
|
||||
private final ExpressionLiteralDoubleService expressionLiteralDoubleService;
|
||||
|
||||
private final ExpressionUnaryService expressionUnaryService;
|
||||
|
||||
private final ExpressionListService expressionNaryService;
|
||||
|
||||
private final ExpressionPropertyService expressionPropertyService;
|
||||
|
||||
public ExpressionService(final AbstractExpressionRepository<AbstractExpression> repository, final ApplicationEventPublisher applicationEventPublisher, final ExpressionLiteralBooleanService expressionLiteralBooleanService, final ExpressionLiteralDoubleService expressionLiteralDoubleService, final ExpressionUnaryService expressionUnaryService, final ExpressionListService expressionNaryService, final ExpressionPropertyService expressionPropertyService) {
|
||||
super(repository, applicationEventPublisher);
|
||||
this.expressionLiteralBooleanService = expressionLiteralBooleanService;
|
||||
this.expressionLiteralDoubleService = expressionLiteralDoubleService;
|
||||
this.expressionUnaryService = expressionUnaryService;
|
||||
this.expressionNaryService = expressionNaryService;
|
||||
this.expressionPropertyService = expressionPropertyService;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public AbstractExpressionDto toDto(@NonNull final AbstractExpression expression) {
|
||||
return switch (expression) {
|
||||
case final ExpressionLiteralBoolean expressionLiteralBoolean -> expressionLiteralBooleanService.toDto(expressionLiteralBoolean);
|
||||
case final ExpressionLiteralDouble expressionLiteralDouble -> expressionLiteralDoubleService.toDto(expressionLiteralDouble);
|
||||
case final ExpressionProperty expressionProperty -> expressionPropertyService.toDto(expressionProperty);
|
||||
case final ExpressionUnary expressionUnary -> expressionUnaryService.toDto(expressionUnary);
|
||||
case final ExpressionList expressionNary -> expressionNaryService.toDto(expressionNary);
|
||||
default -> throw new RuntimeException("Expression type not implemented: " + expression.getClass().getSimpleName());
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
package de.ph87.home.expression.expression.list;
|
||||
|
||||
import de.ph87.home.expression.AbstractExpression;
|
||||
import de.ph87.home.expression.Runtime;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
@Entity
|
||||
@NoArgsConstructor
|
||||
@ToString(callSuper = true)
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class ExpressionList extends AbstractExpression {
|
||||
|
||||
@NonNull
|
||||
@Enumerated(EnumType.STRING)
|
||||
private ExpressionListOperator operator = ExpressionListOperator.OR;
|
||||
|
||||
@NonNull
|
||||
@ManyToMany
|
||||
@OrderColumn
|
||||
private List<AbstractExpression> list = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public Object evaluate(@NonNull final Runtime runtime) {
|
||||
if (list.size() < 2) {
|
||||
return null;
|
||||
}
|
||||
final List<Object> valueList = list.stream().map(e -> evalOrNull(runtime, e)).toList();
|
||||
Object vLast = valueList.removeFirst();
|
||||
while (!valueList.isEmpty()) {
|
||||
final Object vNext = evalOrNull(runtime, list.removeFirst());
|
||||
vLast = operator.apply(vLast, vNext);
|
||||
}
|
||||
return vLast;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
package de.ph87.home.expression.expression.list;
|
||||
|
||||
import de.ph87.home.expression.AbstractExpression;
|
||||
import de.ph87.home.expression.AbstractExpressionDto;
|
||||
import jakarta.annotation.Nullable;
|
||||
import lombok.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
@ToString(callSuper = true)
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class ExpressionListDto extends AbstractExpressionDto {
|
||||
|
||||
@NonNull
|
||||
private final ExpressionListOperator operator;
|
||||
|
||||
@NonNull
|
||||
private final List<String> expressionUuidList;
|
||||
|
||||
public ExpressionListDto(@NonNull final ExpressionList expression, @Nullable final Object value) {
|
||||
super(expression, value);
|
||||
this.operator = expression.getOperator();
|
||||
this.expressionUuidList = expression.getList().stream().map(AbstractExpression::getUuid).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
package de.ph87.home.expression.expression.list;
|
||||
|
||||
import de.ph87.home.expression.AbstractExpression;
|
||||
import jakarta.annotation.Nullable;
|
||||
import lombok.NonNull;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import static de.ph87.home.expression.AbstractExpression.applyFallback;
|
||||
import static de.ph87.home.expression.AbstractExpression.applyNullToNull;
|
||||
|
||||
public enum ExpressionListOperator {
|
||||
OR((v0, v1) -> applyFallback(v0, v1, AbstractExpression::convertToBoolean, false, (c0, c1) -> c0 || c1)),
|
||||
AND((v0, v1) -> applyNullToNull(v0, v1, AbstractExpression::convertToBoolean, (c0, c1) -> c0 && c1)),
|
||||
XOR((v0, v1) -> applyNullToNull(v0, v1, AbstractExpression::convertToBoolean, (c0, c1) -> c0 ^ c1)),
|
||||
ADD((v0, v1) -> applyNullToNull(v0, v1, AbstractExpression::convertToNumber, Double::sum)),
|
||||
SUB((v0, v1) -> applyNullToNull(v0, v1, AbstractExpression::convertToNumber, (c0, c1) -> c0 - c1)),
|
||||
MUL((v0, v1) -> applyNullToNull(v0, v1, AbstractExpression::convertToNumber, (c0, c1) -> c0 * c1)),
|
||||
DIV((v0, v1) -> applyNullToNull(v0, v1, AbstractExpression::convertToNumber, (c0, c1) -> c0 / c1)),
|
||||
MOD((v0, v1) -> applyNullToNull(v0, v1, AbstractExpression::convertToNumber, (c0, c1) -> c0 % c1)),
|
||||
POW((v0, v1) -> applyNullToNull(v0, v1, AbstractExpression::convertToNumber, Math::pow)),
|
||||
HYPOT((v0, v1) -> applyNullToNull(v0, v1, AbstractExpression::convertToNumber, Math::hypot)),
|
||||
ATAN2((v0, v1) -> applyNullToNull(v0, v1, AbstractExpression::convertToNumber, Math::atan2)),
|
||||
MIN((v0, v1) -> applyNullToNull(v0, v1, AbstractExpression::convertToNumber, Math::min)),
|
||||
MAX((v0, v1) -> applyNullToNull(v0, v1, AbstractExpression::convertToNumber, Math::max)),
|
||||
;
|
||||
|
||||
private final BiFunction<Object, Object, Object> function;
|
||||
|
||||
ExpressionListOperator(@NonNull final BiFunction<Object, Object, Object> function) {
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Object apply(@Nullable final Object v0, @Nullable final Object v1) {
|
||||
return function.apply(v0, v1);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package de.ph87.home.expression.expression.list;
|
||||
|
||||
import de.ph87.home.expression.AbstractExpressionRepository;
|
||||
|
||||
public interface ExpressionListRepository extends AbstractExpressionRepository<ExpressionList> {
|
||||
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package de.ph87.home.expression.expression.list;
|
||||
|
||||
import de.ph87.home.expression.AbstractExpressionService;
|
||||
import de.ph87.home.expression.Runtime;
|
||||
import de.ph87.home.property.PropertyService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@Transactional
|
||||
public class ExpressionListService extends AbstractExpressionService<ExpressionList, ExpressionListDto> {
|
||||
|
||||
private final PropertyService propertyService;
|
||||
|
||||
public ExpressionListService(final ExpressionListRepository repository, final ApplicationEventPublisher applicationEventPublisher, final PropertyService propertyService) {
|
||||
super(repository, applicationEventPublisher);
|
||||
this.propertyService = propertyService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionListDto toDto(final ExpressionList expression) {
|
||||
return new ExpressionListDto(expression, expression.evaluate(new Runtime(propertyService)));
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
package de.ph87.home.expression.expression.literal;
|
||||
|
||||
import de.ph87.home.expression.AbstractExpression;
|
||||
import de.ph87.home.expression.Runtime;
|
||||
import jakarta.annotation.Nullable;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.MappedSuperclass;
|
||||
import lombok.*;
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
@MappedSuperclass
|
||||
@NoArgsConstructor
|
||||
@ToString(callSuper = true)
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public abstract class ExpressionLiteral<T> extends AbstractExpression {
|
||||
|
||||
@Nullable
|
||||
@Column(name = "`value`")
|
||||
private T value = null;
|
||||
|
||||
public ExpressionLiteral(final T value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Object evaluate(@NonNull final Runtime runtime) {
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
package de.ph87.home.expression.expression.literal;
|
||||
|
||||
import de.ph87.home.expression.AbstractExpressionController;
|
||||
import de.ph87.home.expression.AbstractExpressionDto;
|
||||
import jakarta.annotation.Nullable;
|
||||
import lombok.NonNull;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
|
||||
public abstract class ExpressionLiteralController<T, E extends ExpressionLiteral<T>, D extends AbstractExpressionDto> extends AbstractExpressionController<E, D> {
|
||||
|
||||
public ExpressionLiteralController(final ExpressionLiteralService<T, E, D> expressionService) {
|
||||
super(expressionService);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@PostMapping("{uuid}/setValue")
|
||||
public D setValue(@PathVariable final String uuid, @RequestBody(required = false) @Nullable final T value) {
|
||||
return expressionService.set(uuid, e -> e.setValue(value));
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package de.ph87.home.expression.expression.literal;
|
||||
|
||||
import de.ph87.home.expression.AbstractExpressionDto;
|
||||
import de.ph87.home.expression.AbstractExpressionRepository;
|
||||
import de.ph87.home.expression.AbstractExpressionService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@Transactional
|
||||
public abstract class ExpressionLiteralService<T, E extends ExpressionLiteral<T>, D extends AbstractExpressionDto> extends AbstractExpressionService<E, D> {
|
||||
|
||||
public ExpressionLiteralService(final AbstractExpressionRepository<E> repository, final ApplicationEventPublisher applicationEventPublisher) {
|
||||
super(repository, applicationEventPublisher);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package de.ph87.home.expression.expression.literal.bool;
|
||||
|
||||
import de.ph87.home.expression.expression.literal.ExpressionLiteral;
|
||||
import jakarta.annotation.Nullable;
|
||||
import jakarta.persistence.Entity;
|
||||
import lombok.*;
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
@Entity
|
||||
@NoArgsConstructor
|
||||
@ToString(callSuper = true)
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class ExpressionLiteralBoolean extends ExpressionLiteral<Boolean> {
|
||||
|
||||
public ExpressionLiteralBoolean(@Nullable final Boolean value) {
|
||||
super(value);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package de.ph87.home.expression.expression.literal.bool;
|
||||
|
||||
import de.ph87.home.expression.expression.literal.ExpressionLiteralController;
|
||||
import de.ph87.home.expression.expression.literal.ExpressionLiteralService;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("ExpressionLiteralBoolean")
|
||||
public class ExpressionLiteralBooleanController extends ExpressionLiteralController<Boolean, ExpressionLiteralBoolean, ExpressionLiteralBooleanDto> {
|
||||
|
||||
public ExpressionLiteralBooleanController(final ExpressionLiteralService<Boolean, ExpressionLiteralBoolean, ExpressionLiteralBooleanDto> expressionLiteralService) {
|
||||
super(expressionLiteralService);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
package de.ph87.home.expression.expression.literal.bool;
|
||||
|
||||
import de.ph87.home.expression.AbstractExpressionDto;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.ToString;
|
||||
|
||||
@Getter
|
||||
@ToString(callSuper = true)
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class ExpressionLiteralBooleanDto extends AbstractExpressionDto {
|
||||
|
||||
protected ExpressionLiteralBooleanDto(@NonNull final ExpressionLiteralBoolean expression) {
|
||||
super(expression, expression.getValue());
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
package de.ph87.home.expression.expression.literal.bool;
|
||||
|
||||
import de.ph87.home.expression.AbstractExpressionRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface ExpressionLiteralBooleanRepository extends AbstractExpressionRepository<ExpressionLiteralBoolean> {
|
||||
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
package de.ph87.home.expression.expression.literal.bool;
|
||||
|
||||
import de.ph87.home.expression.expression.literal.ExpressionLiteralService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@Transactional
|
||||
public class ExpressionLiteralBooleanService extends ExpressionLiteralService<Boolean, ExpressionLiteralBoolean, ExpressionLiteralBooleanDto> {
|
||||
|
||||
public ExpressionLiteralBooleanService(final ExpressionLiteralBooleanRepository repository, final ApplicationEventPublisher applicationEventPublisher) {
|
||||
super(repository, applicationEventPublisher);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionLiteralBooleanDto toDto(final ExpressionLiteralBoolean expression) {
|
||||
return new ExpressionLiteralBooleanDto(expression);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package de.ph87.home.expression.expression.literal.number;
|
||||
|
||||
import de.ph87.home.expression.expression.literal.ExpressionLiteral;
|
||||
import jakarta.annotation.Nullable;
|
||||
import jakarta.persistence.Entity;
|
||||
import lombok.*;
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
@Entity
|
||||
@NoArgsConstructor
|
||||
@ToString(callSuper = true)
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class ExpressionLiteralDouble extends ExpressionLiteral<Double> {
|
||||
|
||||
public ExpressionLiteralDouble(@Nullable final Double value) {
|
||||
super(value);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package de.ph87.home.expression.expression.literal.number;
|
||||
|
||||
import de.ph87.home.expression.expression.literal.ExpressionLiteralController;
|
||||
import de.ph87.home.expression.expression.literal.ExpressionLiteralService;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("ExpressionLiteralDouble")
|
||||
public class ExpressionLiteralDoubleController extends ExpressionLiteralController<Double, ExpressionLiteralDouble, ExpressionLiteralDoubleDto> {
|
||||
|
||||
public ExpressionLiteralDoubleController(final ExpressionLiteralService<Double, ExpressionLiteralDouble, ExpressionLiteralDoubleDto> expressionLiteralService) {
|
||||
super(expressionLiteralService);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
package de.ph87.home.expression.expression.literal.number;
|
||||
|
||||
import de.ph87.home.expression.AbstractExpressionDto;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.ToString;
|
||||
|
||||
@Getter
|
||||
@ToString(callSuper = true)
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class ExpressionLiteralDoubleDto extends AbstractExpressionDto {
|
||||
|
||||
protected ExpressionLiteralDoubleDto(@NonNull final ExpressionLiteralDouble expression) {
|
||||
super(expression, expression.getValue());
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package de.ph87.home.expression.expression.literal.number;
|
||||
|
||||
import de.ph87.home.expression.AbstractExpressionRepository;
|
||||
|
||||
public interface ExpressionLiteralDoubleRepository extends AbstractExpressionRepository<ExpressionLiteralDouble> {
|
||||
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
package de.ph87.home.expression.expression.literal.number;
|
||||
|
||||
import de.ph87.home.expression.expression.literal.ExpressionLiteralService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@Transactional
|
||||
public class ExpressionLiteralDoubleService extends ExpressionLiteralService<Double, ExpressionLiteralDouble, ExpressionLiteralDoubleDto> {
|
||||
|
||||
public ExpressionLiteralDoubleService(final ExpressionLiteralDoubleRepository repository, final ApplicationEventPublisher applicationEventPublisher) {
|
||||
super(repository, applicationEventPublisher);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionLiteralDoubleDto toDto(final ExpressionLiteralDouble expression) {
|
||||
return new ExpressionLiteralDoubleDto(expression);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package de.ph87.home.expression.expression.property;
|
||||
|
||||
import de.ph87.home.expression.AbstractExpression;
|
||||
import de.ph87.home.expression.Runtime;
|
||||
import de.ph87.home.property.Property;
|
||||
import de.ph87.home.property.State;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import lombok.*;
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
@Entity
|
||||
@NoArgsConstructor
|
||||
@ToString(callSuper = true)
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class ExpressionProperty extends AbstractExpression {
|
||||
|
||||
@NonNull
|
||||
@Column(nullable = false)
|
||||
private String propertyId;
|
||||
|
||||
@Override
|
||||
public Object evaluate(@NonNull final Runtime runtime) {
|
||||
return runtime.propertyService.findById(propertyId).map(Property::getState).map(State::getValue).orElse(null);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
package de.ph87.home.expression.expression.property;
|
||||
|
||||
import de.ph87.home.expression.AbstractExpressionDto;
|
||||
import de.ph87.home.property.IProperty;
|
||||
import de.ph87.home.property.PropertyDto;
|
||||
import jakarta.annotation.Nullable;
|
||||
import lombok.*;
|
||||
|
||||
import static de.ph87.home.expression.AbstractExpression.mapOrElse;
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
@ToString(callSuper = true)
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class ExpressionPropertyDto extends AbstractExpressionDto {
|
||||
|
||||
@NonNull
|
||||
private final String propertyId;
|
||||
|
||||
@Nullable
|
||||
private final PropertyDto<?> property;
|
||||
|
||||
public ExpressionPropertyDto(@NonNull final ExpressionProperty expressionProperty, @Nullable final PropertyDto<?> property) {
|
||||
super(expressionProperty, mapOrElse(property, IProperty::getStateValue, null));
|
||||
this.propertyId = expressionProperty.getPropertyId();
|
||||
this.property = property;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package de.ph87.home.expression.expression.property;
|
||||
|
||||
import de.ph87.home.expression.AbstractExpressionRepository;
|
||||
|
||||
public interface ExpressionPropertyRepository extends AbstractExpressionRepository<ExpressionProperty> {
|
||||
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
package de.ph87.home.expression.expression.property;
|
||||
|
||||
import de.ph87.home.expression.AbstractExpressionService;
|
||||
import de.ph87.home.property.PropertyDto;
|
||||
import de.ph87.home.property.PropertyService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@Transactional
|
||||
public class ExpressionPropertyService extends AbstractExpressionService<ExpressionProperty, ExpressionPropertyDto> {
|
||||
|
||||
private final PropertyService propertyService;
|
||||
|
||||
public ExpressionPropertyService(final ExpressionPropertyRepository repository, final ApplicationEventPublisher applicationEventPublisher, final PropertyService propertyService) {
|
||||
super(repository, applicationEventPublisher);
|
||||
this.propertyService = propertyService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionPropertyDto toDto(final ExpressionProperty expressionProperty) {
|
||||
final PropertyDto<?> property = propertyService.dtoByIdOrNull(expressionProperty.getPropertyId());
|
||||
return new ExpressionPropertyDto(expressionProperty, property);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
package de.ph87.home.expression.expression.unary;
|
||||
|
||||
import de.ph87.home.expression.AbstractExpression;
|
||||
import de.ph87.home.expression.Runtime;
|
||||
import jakarta.annotation.Nullable;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
@Entity
|
||||
@NoArgsConstructor
|
||||
@ToString(callSuper = true)
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class ExpressionUnary extends AbstractExpression {
|
||||
|
||||
@NonNull
|
||||
@Enumerated(EnumType.STRING)
|
||||
private ExpressionUnaryOperator operator = ExpressionUnaryOperator.NOT;
|
||||
|
||||
@Nullable
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
private AbstractExpression expression;
|
||||
|
||||
@Override
|
||||
public Object evaluate(@NonNull final Runtime runtime) {
|
||||
final Object value = evalOrNull(runtime, expression);
|
||||
return operator.apply(value);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package de.ph87.home.expression.expression.unary;
|
||||
|
||||
import de.ph87.home.expression.AbstractExpression;
|
||||
import de.ph87.home.expression.AbstractExpressionDto;
|
||||
import jakarta.annotation.Nullable;
|
||||
import lombok.*;
|
||||
|
||||
import static de.ph87.home.expression.AbstractExpression.mapOrElse;
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
@ToString(callSuper = true)
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class ExpressionUnaryDto extends AbstractExpressionDto {
|
||||
|
||||
@NonNull
|
||||
private final ExpressionUnaryOperator operator;
|
||||
|
||||
@Nullable
|
||||
private final String expressionUuid;
|
||||
|
||||
public ExpressionUnaryDto(@NonNull final ExpressionUnary expressionUnary, @Nullable final Object value) {
|
||||
super(expressionUnary, value);
|
||||
this.operator = expressionUnary.getOperator();
|
||||
this.expressionUuid = mapOrElse(expressionUnary.getExpression(), AbstractExpression::getUuid, null);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
package de.ph87.home.expression.expression.unary;
|
||||
|
||||
import de.ph87.home.expression.AbstractExpression;
|
||||
import jakarta.annotation.Nullable;
|
||||
import lombok.NonNull;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public enum ExpressionUnaryOperator {
|
||||
NOT(v -> AbstractExpression.applyNullToNull(v, AbstractExpression::convertToBoolean, c -> !c)),
|
||||
NEG(v -> AbstractExpression.applyNullToNull(v, AbstractExpression::convertToNumber, c -> -c)),
|
||||
POS(v -> AbstractExpression.applyNullToNull(v, AbstractExpression::convertToNumber, c -> +c)),
|
||||
FLOOR(v -> AbstractExpression.applyNullToNull(v, AbstractExpression::convertToNumber, Math::floor)),
|
||||
CEIL(v -> AbstractExpression.applyNullToNull(v, AbstractExpression::convertToNumber, Math::ceil)),
|
||||
ROUND(v -> AbstractExpression.applyNullToNull(v, AbstractExpression::convertToNumber, Math::round)),
|
||||
SQRT(v -> AbstractExpression.applyNullToNull(v, AbstractExpression::convertToNumber, Math::sqrt)),
|
||||
ABS(v -> AbstractExpression.applyNullToNull(v, AbstractExpression::convertToNumber, Math::abs)),
|
||||
COS(v -> AbstractExpression.applyNullToNull(v, AbstractExpression::convertToNumber, Math::cos)),
|
||||
SIN(v -> AbstractExpression.applyNullToNull(v, AbstractExpression::convertToNumber, Math::sin)),
|
||||
TAN(v -> AbstractExpression.applyNullToNull(v, AbstractExpression::convertToNumber, Math::tan)),
|
||||
ACOS(v -> AbstractExpression.applyNullToNull(v, AbstractExpression::convertToNumber, Math::acos)),
|
||||
ASIN(v -> AbstractExpression.applyNullToNull(v, AbstractExpression::convertToNumber, Math::asin)),
|
||||
ATAN(v -> AbstractExpression.applyNullToNull(v, AbstractExpression::convertToNumber, Math::atan)),
|
||||
COSH(v -> AbstractExpression.applyNullToNull(v, AbstractExpression::convertToNumber, Math::cosh)),
|
||||
SINH(v -> AbstractExpression.applyNullToNull(v, AbstractExpression::convertToNumber, Math::sinh)),
|
||||
TANH(v -> AbstractExpression.applyNullToNull(v, AbstractExpression::convertToNumber, Math::tanh)),
|
||||
EXP(v -> AbstractExpression.applyNullToNull(v, AbstractExpression::convertToNumber, Math::exp)),
|
||||
EXPM1(v -> AbstractExpression.applyNullToNull(v, AbstractExpression::convertToNumber, Math::expm1)),
|
||||
;
|
||||
|
||||
private final Function<Object, Object> function;
|
||||
|
||||
ExpressionUnaryOperator(@NonNull final Function<Object, Object> function) {
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Object apply(@Nullable final Object value) {
|
||||
return function.apply(value);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package de.ph87.home.expression.expression.unary;
|
||||
|
||||
import de.ph87.home.expression.AbstractExpressionRepository;
|
||||
|
||||
public interface ExpressionUnaryRepository extends AbstractExpressionRepository<ExpressionUnary> {
|
||||
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package de.ph87.home.expression.expression.unary;
|
||||
|
||||
import de.ph87.home.expression.AbstractExpressionService;
|
||||
import de.ph87.home.expression.Runtime;
|
||||
import de.ph87.home.property.PropertyService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@Transactional
|
||||
public class ExpressionUnaryService extends AbstractExpressionService<ExpressionUnary, ExpressionUnaryDto> {
|
||||
|
||||
private final PropertyService propertyService;
|
||||
|
||||
public ExpressionUnaryService(final ExpressionUnaryRepository repository, final ApplicationEventPublisher applicationEventPublisher, final PropertyService propertyService) {
|
||||
super(repository, applicationEventPublisher);
|
||||
this.propertyService = propertyService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionUnaryDto toDto(final ExpressionUnary expression) {
|
||||
return new ExpressionUnaryDto(expression, expression.evaluate(new Runtime(propertyService)));
|
||||
}
|
||||
|
||||
}
|
||||
@ -89,7 +89,7 @@ public class PropertyService {
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private Optional<Property<?>> findById(final String id) {
|
||||
public Optional<Property<?>> findById(final String id) {
|
||||
return propertyList.stream().filter(p -> p.getId().equals(id)).findFirst();
|
||||
}
|
||||
|
||||
@ -120,4 +120,9 @@ public class PropertyService {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PropertyDto<?> dtoByIdOrNull(@NonNull final String propertyId) {
|
||||
return findById(propertyId).map(this::toDto).orElse(null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user