From eacc77fa43e8897c8c0f623026255e73893abc0d Mon Sep 17 00:00:00 2001 From: Claudio Maggioni Date: Mon, 27 Apr 2020 18:51:55 +0200 Subject: [PATCH 1/3] fix --- .../smarthut/config/GsonConfig.java | 12 +++ .../smarthut/config/SpringFoxConfig.java | 1 + .../controller/AutomationController.java | 52 ++++++++-- .../dto/AutomationFastUpdateRequest.java | 97 +++++++++++++++++++ .../smarthut/models/Automation.java | 6 +- .../smarthut/models/AutomationRepository.java | 7 +- .../smarthut/models/BooleanTrigger.java | 4 + .../smarthut/models/RangeTrigger.java | 4 + .../smarthut/models/ScenePriority.java | 3 +- .../models/ScenePriorityRepository.java | 5 + .../sanmarinoes/smarthut/models/Trigger.java | 24 ++--- .../smarthut/models/TriggerRepository.java | 4 + 12 files changed, 197 insertions(+), 22 deletions(-) create mode 100644 src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/dto/AutomationFastUpdateRequest.java diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/GsonConfig.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/GsonConfig.java index 08c3e60..1204a60 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/GsonConfig.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/GsonConfig.java @@ -1,5 +1,6 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.config; +import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.AutomationFastUpdateRequest; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.DimmableState; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.State; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.SwitchableState; @@ -30,7 +31,18 @@ public class GsonConfig { RuntimeTypeAdapterFactory.of(State.class, "kind") .registerSubtype(SwitchableState.class, "switchableState") .registerSubtype(DimmableState.class, "dimmableState"); + RuntimeTypeAdapterFactory + runtimeTypeAdapterFactoryII = + RuntimeTypeAdapterFactory.of( + AutomationFastUpdateRequest.TriggerDTO.class, "kind") + .registerSubtype( + AutomationFastUpdateRequest.BooleanTriggerDTO.class, + "booleanTrigger") + .registerSubtype( + AutomationFastUpdateRequest.RangeTriggerDTO.class, + "rangeTrigger"); builder.registerTypeAdapterFactory(runtimeTypeAdapterFactory); + builder.registerTypeAdapterFactory(runtimeTypeAdapterFactoryII); return builder; } diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/SpringFoxConfig.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/SpringFoxConfig.java index d09adfb..3f6e6f9 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/SpringFoxConfig.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/SpringFoxConfig.java @@ -82,6 +82,7 @@ public class SpringFoxConfig { .or(PathSelectors.regex("/motionSensor.*")::apply) .or(PathSelectors.regex("/curtains.*")::apply) .or(PathSelectors.regex("/user.*")::apply) + .or(PathSelectors.regex("/automation.*")::apply) .or(PathSelectors.regex("/auth/profile.*")::apply); } diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/AutomationController.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/AutomationController.java index 7abd499..cfad787 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/AutomationController.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/AutomationController.java @@ -1,14 +1,12 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.controller; +import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.AutomationFastUpdateRequest; import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.AutomationSaveRequest; import ch.usi.inf.sa4.sanmarinoes.smarthut.error.NotFoundException; -import ch.usi.inf.sa4.sanmarinoes.smarthut.models.Automation; -import ch.usi.inf.sa4.sanmarinoes.smarthut.models.AutomationRepository; -import ch.usi.inf.sa4.sanmarinoes.smarthut.models.ScenePriorityRepository; -import ch.usi.inf.sa4.sanmarinoes.smarthut.models.SceneRepository; -import ch.usi.inf.sa4.sanmarinoes.smarthut.models.UserRepository; +import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*; import java.security.Principal; import java.util.List; +import java.util.stream.Collectors; import javax.validation.Valid; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; @@ -28,8 +26,8 @@ import org.springframework.web.bind.annotation.RestController; public class AutomationController { @Autowired private AutomationRepository automationRepository; - @Autowired private SceneRepository sceneRepository; - @Autowired private ScenePriorityRepository scenePriorityRepository; + @Autowired private ScenePriorityRepository sceneRepository; + @Autowired private TriggerRepository> triggerRepository; @Autowired private UserRepository userService; @GetMapping @@ -73,6 +71,46 @@ public class AutomationController { principal); } + @PutMapping("/fast") + public Automation fastUpdate( + @Valid @RequestBody AutomationFastUpdateRequest req, Principal principal) + throws NotFoundException { + final Automation a = + automationRepository + .findByIdAndUserId( + req.getId(), + userService.findByUsername(principal.getName()).getId()) + .orElseThrow(NotFoundException::new); + + a.setName(req.getName()); + automationRepository.save(a); + + triggerRepository.deleteAllByAutomationId(a.getId()); + sceneRepository.deleteAllByAutomationId(a.getId()); + + Iterable> tt = + triggerRepository.saveAll( + req.getTriggers() + .stream() + .map(AutomationFastUpdateRequest.TriggerDTO::toModel) + .map(t -> t.setAutomationId(a.getId())) + .collect(Collectors.toList())); + Iterable ss = + sceneRepository.saveAll( + req.getScenes() + .stream() + .map(AutomationFastUpdateRequest.ScenePriorityDTO::toModel) + .map(t -> t.setAutomationId(a.getId())) + .collect(Collectors.toList())); + + a.getScenes().clear(); + a.getTriggers().clear(); + ss.forEach(t -> a.getScenes().add(t)); + tt.forEach(t -> a.getTriggers().add(t)); + + return a; + } + @DeleteMapping("/{id}") public void delete(@PathVariable long id) { automationRepository.deleteById(id); diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/dto/AutomationFastUpdateRequest.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/dto/AutomationFastUpdateRequest.java new file mode 100644 index 0000000..58ce46c --- /dev/null +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/dto/AutomationFastUpdateRequest.java @@ -0,0 +1,97 @@ +package ch.usi.inf.sa4.sanmarinoes.smarthut.dto; + +import ch.usi.inf.sa4.sanmarinoes.smarthut.models.BooleanTrigger; +import ch.usi.inf.sa4.sanmarinoes.smarthut.models.RangeTrigger; +import ch.usi.inf.sa4.sanmarinoes.smarthut.models.ScenePriority; +import ch.usi.inf.sa4.sanmarinoes.smarthut.models.Trigger; +import java.util.List; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +public class AutomationFastUpdateRequest { + public abstract static class TriggerDTO { + @NotNull public long deviceId; + + public abstract Trigger toModel(); + } + + public static class BooleanTriggerDTO extends TriggerDTO { + @NotNull public boolean on; + + @Override + public Trigger toModel() { + BooleanTrigger t = new BooleanTrigger<>(); + t.setDeviceId(this.deviceId); + t.setOn(this.on); + return t; + } + } + + public static class RangeTriggerDTO extends TriggerDTO { + @NotNull RangeTrigger.Operator operator; + @NotNull double range; + + @Override + public Trigger toModel() { + RangeTrigger t = new RangeTrigger<>(); + t.setDeviceId(this.deviceId); + t.setOperator(this.operator); + t.setRange(this.range); + return t; + } + } + + public static class ScenePriorityDTO { + @NotNull public long sceneId; + + @NotNull + @Min(0) + public Integer priority; + + public ScenePriority toModel() { + ScenePriority s = new ScenePriority(); + s.setSceneId(sceneId); + s.setPriority(priority); + return s; + } + } + + @NotNull private List scenes; + @NotNull private List triggers; + @NotNull private long id; + + @NotNull @NotEmpty private String name; + + public long getId() { + return id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getScenes() { + return scenes; + } + + public void setScenes(List scenes) { + this.scenes = scenes; + } + + public List getTriggers() { + return triggers; + } + + public void setTriggers(List triggers) { + this.triggers = triggers; + } + + public void setId(long id) { + this.id = id; + } +} diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Automation.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Automation.java index 17d5bfc..e6b4d0b 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Automation.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Automation.java @@ -28,11 +28,9 @@ public class Automation { private Long userId; @OneToMany(mappedBy = "automation", orphanRemoval = true) - @GsonExclude private Set> triggers = new HashSet<>(); @OneToMany(mappedBy = "automation", cascade = CascadeType.REMOVE) - @GsonExclude private Set scenes = new HashSet<>(); @NotNull @NotEmpty private String name; @@ -53,6 +51,10 @@ public class Automation { return scenes; } + public Set> getTriggers() { + return triggers; + } + public String getName() { return name; } diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/AutomationRepository.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/AutomationRepository.java index a54a9ee..b874146 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/AutomationRepository.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/AutomationRepository.java @@ -1,10 +1,15 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.models; import java.util.List; +import java.util.Optional; +import org.springframework.data.jpa.repository.EntityGraph; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.query.Param; public interface AutomationRepository extends CrudRepository { - + @EntityGraph(attributePaths = {"scenes", "triggers"}) List findAllByUserId(@Param("userId") long userId); + + @EntityGraph(attributePaths = {"scenes", "triggers"}) + Optional findByIdAndUserId(@Param("id") long id, @Param("userId") long userId); } diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/BooleanTrigger.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/BooleanTrigger.java index fde9b3b..f6e493e 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/BooleanTrigger.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/BooleanTrigger.java @@ -9,6 +9,10 @@ public class BooleanTrigger extends Trigg @Column(name = "switchable_on") private boolean on; + public BooleanTrigger() { + super("booleanTrigger"); + } + public boolean isOn() { return on; } diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/RangeTrigger.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/RangeTrigger.java index db94966..19e179c 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/RangeTrigger.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/RangeTrigger.java @@ -8,6 +8,10 @@ import javax.validation.constraints.NotNull; @Entity public class RangeTrigger extends Trigger { + public RangeTrigger() { + super("rangeTrigger"); + } + @Override public boolean triggered() { double value = getDevice().readTriggerState(); diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ScenePriority.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ScenePriority.java index 04586d9..64e755b 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ScenePriority.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ScenePriority.java @@ -65,8 +65,9 @@ public class ScenePriority { return automationId; } - public void setAutomationId(Long automationId) { + public ScenePriority setAutomationId(Long automationId) { this.automationId = automationId; + return this; } public Scene getScene() { diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ScenePriorityRepository.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ScenePriorityRepository.java index 1d9b3c6..67e14e6 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ScenePriorityRepository.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ScenePriorityRepository.java @@ -1,6 +1,7 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.models; import java.util.List; +import javax.transaction.Transactional; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.query.Param; @@ -8,7 +9,11 @@ public interface ScenePriorityRepository extends CrudRepository findAllBySceneId(@Param("sceneId") long sceneId); + @Transactional void deleteBySceneId(@Param("sceneId") long sceneId); List findAllByAutomationId(@Param("automationId") long automationId); + + @Transactional + void deleteAllByAutomationId(Long automationId); } diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Trigger.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Trigger.java index 4e74b11..77010c6 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Trigger.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Trigger.java @@ -2,22 +2,23 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.models; import ch.usi.inf.sa4.sanmarinoes.smarthut.config.GsonExclude; import io.swagger.annotations.ApiModelProperty; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.Inheritance; -import javax.persistence.InheritanceType; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.PreRemove; +import javax.persistence.*; import javax.validation.constraints.NotNull; @Entity @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) public abstract class Trigger { + @Transient private String kind; + + protected Trigger(String kind) { + this.kind = kind; + } + + public String getKind() { + return kind; + } + public abstract boolean triggered(); @Id @@ -84,8 +85,9 @@ public abstract class Trigger { return automationId; } - public void setAutomationId(Long automationId) { + public Trigger setAutomationId(Long automationId) { this.automationId = automationId; + return this; } @PreRemove diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/TriggerRepository.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/TriggerRepository.java index a506ce6..8fea53a 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/TriggerRepository.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/TriggerRepository.java @@ -1,10 +1,14 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.models; import java.util.List; +import javax.transaction.Transactional; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.query.Param; public interface TriggerRepository> extends CrudRepository { List findAllByDeviceId(@Param("deviceId") long deviceId); + + @Transactional + void deleteAllByAutomationId(Long automationId); } From cf06950b622e0199946d9f71b89d81546bdbc52f Mon Sep 17 00:00:00 2001 From: omenem Date: Mon, 27 Apr 2020 18:59:01 +0200 Subject: [PATCH 2/3] fix --- .../sa4/sanmarinoes/smarthut/models/Thermostat.java | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Thermostat.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Thermostat.java index 689c7ee..e8f0e86 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Thermostat.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Thermostat.java @@ -1,14 +1,9 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.models; -import ch.usi.inf.sa4.sanmarinoes.smarthut.config.GsonExclude; -import ch.usi.inf.sa4.sanmarinoes.smarthut.config.SocketGsonExclude; import com.google.gson.annotations.SerializedName; import java.math.BigDecimal; -import java.util.HashSet; -import java.util.Set; import javax.persistence.Column; import javax.persistence.Entity; -import javax.persistence.OneToMany; import javax.persistence.Transient; import javax.validation.constraints.NotNull; @@ -86,11 +81,6 @@ public class Thermostat extends Switchable implements BooleanTriggerable { @Column private boolean useExternalSensors = false; - @OneToMany(mappedBy = "scene", orphanRemoval = true) - @GsonExclude - @SocketGsonExclude - private Set> triggers = new HashSet<>(); - /** Creates a thermostat with a temperature sensor and its initial OFF state */ public Thermostat() { super("thermostat"); From 5fc63edf4ff92b13ea462a98b128c698ae516762 Mon Sep 17 00:00:00 2001 From: omenem Date: Mon, 27 Apr 2020 19:04:52 +0200 Subject: [PATCH 3/3] fix --- .../smarthut/controller/ThermostatController.java | 1 + .../smarthut/dto/ThermostatSaveRequest.java | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/ThermostatController.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/ThermostatController.java index 670df76..6761ee5 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/ThermostatController.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/ThermostatController.java @@ -28,6 +28,7 @@ public class ThermostatController { newT.setId(t.getId()); newT.setName(t.getName()); newT.setRoomId(t.getRoomId()); + newT.setMeasuredTemperature(t.getMeasuredTemperature()); newT.setUseExternalSensors(t.isUseExternalSensors()); newT.setOn(t.isTurnOn()); diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/dto/ThermostatSaveRequest.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/dto/ThermostatSaveRequest.java index 5ac3402..3986996 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/dto/ThermostatSaveRequest.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/dto/ThermostatSaveRequest.java @@ -22,6 +22,8 @@ public class ThermostatSaveRequest { @NotNull private boolean useExternalSensors; + @NotNull private BigDecimal measuredTemperature; + /** State of this thermostat */ @NotNull private boolean turnOn; @@ -72,4 +74,12 @@ public class ThermostatSaveRequest { public void setId(long id) { this.id = id; } + + public BigDecimal getMeasuredTemperature() { + return measuredTemperature; + } + + public void setMeasuredTemperature(BigDecimal measuredTemperature) { + this.measuredTemperature = measuredTemperature; + } }