diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/ButtonDimmerController.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/ButtonDimmerController.java index c7984ea..92d14db 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/ButtonDimmerController.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/ButtonDimmerController.java @@ -24,7 +24,7 @@ public class ButtonDimmerController @Autowired protected ButtonDimmerController( ButtonDimmerRepository inputRepository, DimmableLightRepository outputRepository) { - super(inputRepository, outputRepository); + super(inputRepository, outputRepository, ButtonDimmer.CONNECTOR); this.buttonDimmerRepository = inputRepository; this.dimmableLightRepository = outputRepository; } @@ -63,20 +63,20 @@ public class ButtonDimmerController break; } - dimmableLightRepository.saveAll(buttonDimmer.getLights()); + dimmableLightRepository.saveAll(buttonDimmer.getOutputs()); return buttonDimmer.getOutputs(); } @PostMapping("/{id}/lights") - public Set addLight( + public Set addLight( @PathVariable("id") long inputId, @RequestParam("lightId") Long lightId) throws NotFoundException { return addOutput(inputId, lightId); } @DeleteMapping("/{id}/lights") - public Set removeLight( + public Set removeLight( @PathVariable("id") long inputId, @RequestParam("lightId") Long lightId) throws NotFoundException { return removeOutput(inputId, lightId); diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/InputDeviceConnectionController.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/InputDeviceConnectionController.java index cbcdc98..52f3483 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/InputDeviceConnectionController.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/InputDeviceConnectionController.java @@ -12,8 +12,7 @@ import java.util.Set; * @param the output device attached to I */ public abstract class InputDeviceConnectionController< - I extends InputDevice & OutputConnectable, - O extends OutputDevice & InputConnectable> { + I extends InputDevice, O extends OutputDevice> { private class IOPair { private final I input; @@ -29,10 +28,22 @@ public abstract class InputDeviceConnectionController< private DeviceRepository outputReposiory; + private Connector connector; + + /** + * Contstructs the controller by requiring essential object for the controller implementation + * + * @param inputRepository the input device repository + * @param outputRepository the output device repository + * @param connector a appropriate Connector instance for the I and O tyoes. + */ protected InputDeviceConnectionController( - DeviceRepository inputRepository, DeviceRepository outputRepository) { + DeviceRepository inputRepository, + DeviceRepository outputRepository, + Connector connector) { this.inputRepository = inputRepository; this.outputReposiory = outputRepository; + this.connector = connector; } private IOPair checkConnectionIDs(Long inputId, Long outputId) throws NotFoundException { @@ -55,10 +66,10 @@ public abstract class InputDeviceConnectionController< * @return the list of output devices attached to the input device of id inputId * @throws NotFoundException if inputId or outputId are not valid */ - protected Set addOutput(Long inputId, Long outputId) throws NotFoundException { + protected Set addOutput(Long inputId, Long outputId) + throws NotFoundException { final IOPair pair = checkConnectionIDs(inputId, outputId); - pair.input.getOutputs().add(pair.output); - pair.output.connect(pair.input.getId()); + connector.connect(pair.input, pair.output, true); outputReposiory.save(pair.output); return pair.input.getOutputs(); } @@ -71,10 +82,10 @@ public abstract class InputDeviceConnectionController< * @return the list of output devices attached to the input device of id inputId * @throws NotFoundException if inputId or outputId are not valid */ - protected Set removeOutput(Long inputId, Long outputId) throws NotFoundException { + protected Set removeOutput(Long inputId, Long outputId) + throws NotFoundException { final IOPair pair = checkConnectionIDs(inputId, outputId); - pair.input.getOutputs().remove(pair.output); - pair.output.connect(null); + connector.connect(pair.input, pair.output, false); outputReposiory.save(pair.output); return pair.input.getOutputs(); } diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/KnobDimmerController.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/KnobDimmerController.java index 82d9507..4d51733 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/KnobDimmerController.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/KnobDimmerController.java @@ -25,7 +25,7 @@ public class KnobDimmerController @Autowired protected KnobDimmerController( KnobDimmerRepository inputRepository, DimmableLightRepository outputRepository) { - super(inputRepository, outputRepository); + super(inputRepository, outputRepository, KnobDimmer.CONNECTOR); this.knobDimmerRepository = inputRepository; this.dimmableLightRepository = outputRepository; } @@ -56,20 +56,20 @@ public class KnobDimmerController knobDimmerRepository.findById(bd.getId()).orElseThrow(NotFoundException::new); dimmer.setLightIntensity(bd.getIntensity()); - dimmableLightRepository.saveAll(dimmer.getLights()); + dimmableLightRepository.saveAll(dimmer.getOutputs()); return dimmer.getOutputs(); } @PostMapping("/{id}/lights") - public Set addLight( + public Set addLight( @PathVariable("id") long inputId, @RequestParam("lightId") Long lightId) throws NotFoundException { return addOutput(inputId, lightId); } @DeleteMapping("/{id}/lights") - public Set removeLight( + public Set removeLight( @PathVariable("id") long inputId, @RequestParam("lightId") Long lightId) throws NotFoundException { return removeOutput(inputId, lightId); diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ButtonDimmer.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ButtonDimmer.java index 17c09f5..85d4fe0 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ButtonDimmer.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ButtonDimmer.java @@ -1,77 +1,35 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.models; -import java.util.Set; import javax.persistence.Entity; -import javax.persistence.OneToMany; /** * Represents a dimmer that can only instruct an increase or decrease of intensity (i.e. like a * dimmer with a '+' and a '-' button) */ @Entity -public class ButtonDimmer extends Dimmer implements OutputConnectable { +public class ButtonDimmer extends Dimmer { + + public static final Connector CONNECTOR = + Connector.basic(ButtonDimmer::getOutputs, DimmableLight::setDimmerId); + /** The delta amount to apply to a increase or decrease intensity */ - public static final int DIM_INCREMENT = 10; + private static final int DIM_INCREMENT = 10; public ButtonDimmer() { super("button-dimmer"); } - @OneToMany(mappedBy = "dimmer") - private Set lights; - /** Increases the current intensity level of the dimmable light by DIM_INCREMENT */ public void increaseIntensity() { - for (DimmableLight dl : lights) { + for (DimmableLight dl : getOutputs()) { dl.setIntensity(dl.getIntensity() + DIM_INCREMENT); } } /** Decreases the current intensity level of the dimmable light by DIM_INCREMENT */ public void decreaseIntensity() { - for (DimmableLight dl : lights) { + for (DimmableLight dl : getOutputs()) { dl.setIntensity(dl.getIntensity() - DIM_INCREMENT); } } - - /** - * Adds a DimmableLight to this set of DimmableLights - * - * @param dl The DimmableLight to be added - */ - public void addLight(DimmableLight dl) { - lights.add(dl); - } - - /** - * Removes the given DimmableLight - * - * @param dl The DimmableLight to be removed - */ - public void removeLight(DimmableLight dl) { - lights.remove(dl); - } - - /** Clears this set */ - public void clearSet() { - lights.clear(); - } - - /** - * Get the lights - * - * @return duh - */ - public Set getLights() { - return this.lights; - } - - @Override - public Set getOutputs() { - return this.lights; - } - - public void setLights(Set newLights) { - this.lights = newLights; - } } diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Connector.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Connector.java new file mode 100644 index 0000000..dd68b10 --- /dev/null +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Connector.java @@ -0,0 +1,47 @@ +package ch.usi.inf.sa4.sanmarinoes.smarthut.models; + +import java.util.Set; +import java.util.function.BiConsumer; +import java.util.function.Function; + +/** + * A rule on how to connect an input device type to an output device type + * + * @param the input device type + * @param the output device type + */ +@FunctionalInterface +public interface Connector { + + /** + * Connects or disconnects input to output + * + * @param input the input device + * @param output the output device + * @param connect true if connection, false if disconnection + */ + void connect(I input, O output, boolean connect); + + /** + * Produces a basic implementation of a connector, assuming there is a OneToMany relationship + * between J and K + * + * @param outputsGetter the getter method of the set of outputs on the input class + * @param inputSetter the setter method for the input id on the output class + * @param the input device type + * @param the output device type + * @return a Connector implementation for the pair of types J and K + */ + static Connector basic( + Function> outputsGetter, BiConsumer inputSetter) { + return (i, o, connect) -> { + if (connect) { + outputsGetter.apply(i).add(o); + } else { + outputsGetter.apply(i).remove(o); + } + + inputSetter.accept(o, connect ? i.getId() : null); + }; + } +} diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/DimmableLight.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/DimmableLight.java index 486203b..277a7e9 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/DimmableLight.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/DimmableLight.java @@ -11,7 +11,7 @@ import javax.validation.constraints.NotNull; /** Represent a dimmable light */ @Entity -public class DimmableLight extends Light implements InputConnectable { +public class DimmableLight extends OutputDevice implements Switchable { public DimmableLight() { super("light"); @@ -46,29 +46,24 @@ public class DimmableLight extends Light implements InputConnectable { public void setIntensity(Integer intensity) { if (intensity <= 0) { this.intensity = 0; - setOn(false); + } else if (intensity > 100) { + this.intensity = 100; } else { - setOn(true); - if (intensity > 100) { - this.intensity = 100; - } else { - this.intensity = intensity; - } + this.intensity = intensity; } } + @Override + public boolean isOn() { + return intensity != 0; + } + @Override public void setOn(boolean on) { - super.setOn(on); - if (on) { - intensity = 100; - } else { - intensity = 0; - } + intensity = on ? 100 : 0; } - @Override - public void connect(Long inputId) { - this.dimmerId = inputId; - } + public void setDimmerId(Long dimmerId) { + this.dimmerId = dimmerId; + }; } diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Dimmer.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Dimmer.java index 2658b35..af00025 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Dimmer.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Dimmer.java @@ -1,8 +1,10 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.models; +import java.util.Set; import javax.persistence.Entity; import javax.persistence.Inheritance; import javax.persistence.InheritanceType; +import javax.persistence.OneToMany; /** Represents a generic dimmer input device */ @Entity @@ -11,4 +13,17 @@ public abstract class Dimmer extends InputDevice { public Dimmer(String kind) { super(kind); } + + @OneToMany(mappedBy = "dimmer") + private Set lights; + + /** + * Get the lights connected to this dimmer + * + * @return duh + */ + @Override + public Set getOutputs() { + return this.lights; + } } diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/InputConnectable.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/InputConnectable.java deleted file mode 100644 index 74b6487..0000000 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/InputConnectable.java +++ /dev/null @@ -1,18 +0,0 @@ -package ch.usi.inf.sa4.sanmarinoes.smarthut.models; - - -/** - * An output device to which an input can be connected - * - * @param the type of input device that can be connected to this device - */ -public interface InputConnectable { - - /** - * Connect an input device to this output device. This method should set the corresponding FK in - * the entity. - * - * @param inputId the input device id, null for deleting the connection - */ - void connect(Long inputId); -} diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/InputDevice.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/InputDevice.java index e632178..ad96347 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/InputDevice.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/InputDevice.java @@ -1,5 +1,6 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.models; +import java.util.Set; import javax.persistence.Entity; /** @@ -11,4 +12,8 @@ public abstract class InputDevice extends Device { public InputDevice(String kind) { super(kind, FlowType.INPUT); } + + public Set getOutputs() { + return Set.of(); + } } diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/KnobDimmer.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/KnobDimmer.java index 35d243c..d4eea0e 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/KnobDimmer.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/KnobDimmer.java @@ -1,44 +1,29 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.models; -import java.util.Set; import javax.persistence.Entity; -import javax.persistence.OneToMany; /** * Represents a dimmer able to set absolute intensity values (i.e. knowing the absolute intensity * value, like a knob) */ @Entity -public class KnobDimmer extends Dimmer implements OutputConnectable { +public class KnobDimmer extends Dimmer { + + public static final Connector CONNECTOR = + Connector.basic(KnobDimmer::getOutputs, DimmableLight::setDimmerId); + public KnobDimmer() { super("knob-dimmer"); } - @OneToMany(mappedBy = "dimmer") - private Set lights; - /** * Sets absolutely the intensity level of all lights connected * * @param intensity the intensity (must be from 0 to 100) */ public void setLightIntensity(int intensity) { - - for (DimmableLight dl : lights) { + for (DimmableLight dl : getOutputs()) { dl.setIntensity(intensity); } } - - public void setLights(Set lights) { - this.lights = lights; - } - - public Set getLights() { - return lights; - } - - @Override - public Set getOutputs() { - return lights; - } } diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Light.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Light.java deleted file mode 100644 index 68a819b..0000000 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Light.java +++ /dev/null @@ -1,31 +0,0 @@ -package ch.usi.inf.sa4.sanmarinoes.smarthut.models; - -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Inheritance; -import javax.persistence.InheritanceType; -import javax.validation.constraints.NotNull; - -/** Represents a generic light */ -@Entity -@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) -public abstract class Light extends OutputDevice { - - /** Whether the light is on or not */ - @Column(name = "light_on", nullable = false) - @NotNull - boolean on; - - protected Light(String kind) { - super(kind); - this.on = false; - } - - public boolean isOn() { - return on; - } - - public void setOn(boolean on) { - this.on = on; - } -} diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/OutputConnectable.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/OutputConnectable.java deleted file mode 100644 index c6360e9..0000000 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/OutputConnectable.java +++ /dev/null @@ -1,18 +0,0 @@ -package ch.usi.inf.sa4.sanmarinoes.smarthut.models; - -import java.util.Set; - -/** - * An input device to which outputs can be connected - * - * @param the type of output device that can be connected to this device - */ -public interface OutputConnectable { - - /** - * Get the set of all output devices connected to this device - * - * @return The set of outputs connected to this device - */ - Set getOutputs(); -} diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/OutputDevice.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/OutputDevice.java index 39e5dd0..c5b401f 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/OutputDevice.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/OutputDevice.java @@ -1,8 +1,6 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.models; -import javax.persistence.Entity; -import javax.persistence.Inheritance; -import javax.persistence.InheritanceType; +import javax.persistence.*; /** * Represents a generic output device, i.e. something that causes some behaviour (light, smartPlugs, diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/RegularLight.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/RegularLight.java index 8f07377..02b5f35 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/RegularLight.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/RegularLight.java @@ -1,11 +1,30 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.models; +import javax.persistence.Column; import javax.persistence.Entity; +import javax.validation.constraints.NotNull; /** Represents a standard non-dimmable light */ @Entity -public class RegularLight extends Light { +public class RegularLight extends OutputDevice implements Switchable { + + /** Whether the light is on or not */ + @Column(name = "light_on", nullable = false) + @NotNull + boolean on; + public RegularLight() { super("regular-light"); + this.on = false; + } + + @Override + public boolean isOn() { + return on; + } + + @Override + public void setOn(boolean on) { + this.on = on; } } diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/SmartPlug.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/SmartPlug.java index e0d7981..6a77a13 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/SmartPlug.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/SmartPlug.java @@ -6,17 +6,19 @@ import javax.validation.constraints.NotNull; /** A smart plug that can be turned either on or off */ @Entity -public class SmartPlug extends OutputDevice { +public class SmartPlug extends OutputDevice implements Switchable { /** Whether the smart plug is on */ @Column(name = "smart_plug_on", nullable = false) @NotNull private boolean on; + @Override public boolean isOn() { return on; } + @Override public void setOn(boolean on) { this.on = on; } diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Switchable.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Switchable.java new file mode 100644 index 0000000..e13eea1 --- /dev/null +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Switchable.java @@ -0,0 +1,24 @@ +package ch.usi.inf.sa4.sanmarinoes.smarthut.models; + +/** A device that can be turned either on or off */ +public interface Switchable { + + /** + * Returns whether the device is on (true) or not (false) + * + * @return whether the device is on (true) or not (false) + */ + boolean isOn(); + + /** + * Sets the on status of the device + * + * @param on the new on status: true for on, false for off + */ + void setOn(boolean on); + + /** Toggle between on are off state */ + default void toggle() { + setOn(!isOn()); + } +}