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); }