Fixed circular dependency on switch connector

This commit is contained in:
Claudio Maggioni (maggicl) 2020-05-09 14:23:39 +02:00
parent 191870d3c6
commit 15faf0a6b4
10 changed files with 38 additions and 74 deletions

View file

@ -26,7 +26,7 @@ public class ButtonDimmerController
ButtonDimmerRepository inputRepository, ButtonDimmerRepository inputRepository,
DimmableRepository<Dimmable> outputRepository, DimmableRepository<Dimmable> outputRepository,
DeviceService deviceService) { DeviceService deviceService) {
super(inputRepository, outputRepository, DimmableLight.BUTTON_DIMMER_DIMMABLE_CONNECTOR); super(inputRepository, outputRepository);
this.deviceService = deviceService; this.deviceService = deviceService;
this.buttonDimmerRepository = inputRepository; this.buttonDimmerRepository = inputRepository;
} }

View file

@ -23,7 +23,7 @@ import org.springframework.web.bind.annotation.RequestBody;
* @param <O> the output device attached to I * @param <O> the output device attached to I
*/ */
public abstract class InputDeviceConnectionController< public abstract class InputDeviceConnectionController<
I extends InputDevice, O extends OutputDevice> { I extends InputDevice & Connectable<O>, O extends OutputDevice> {
private class Connection { private class Connection {
private final I input; private final I input;
@ -53,26 +53,20 @@ public abstract class InputDeviceConnectionController<
@Autowired private DeviceService deviceService; @Autowired private DeviceService deviceService;
private DeviceRepository<I> inputRepository; private final DeviceRepository<I> inputRepository;
private DeviceRepository<O> outputReposiory; private final DeviceRepository<O> outputReposiory;
private Connector<I, O> connector;
/** /**
* Contstructs the controller by requiring essential object for the controller implementation * Contstructs the controller by requiring essential object for the controller implementation
* *
* @param inputRepository the input device repository * @param inputRepository the input device repository
* @param outputRepository the output device repository * @param outputRepository the output device repository
* @param connector a appropriate Connector instance for the I and O tyoes.
*/ */
protected InputDeviceConnectionController( protected InputDeviceConnectionController(
DeviceRepository<I> inputRepository, DeviceRepository<I> inputRepository, DeviceRepository<O> outputRepository) {
DeviceRepository<O> outputRepository,
Connector<I, O> connector) {
this.inputRepository = inputRepository; this.inputRepository = inputRepository;
this.outputReposiory = outputRepository; this.outputReposiory = outputRepository;
this.connector = connector;
} }
private Connection checkConnectionIDs(Long inputId, List<Long> outputs, String username) private Connection checkConnectionIDs(Long inputId, List<Long> outputs, String username)
@ -104,7 +98,7 @@ public abstract class InputDeviceConnectionController<
final Connection pair = checkConnectionIDs(inputId, outputs, username); final Connection pair = checkConnectionIDs(inputId, outputs, username);
for (final O o : pair.getOutputs()) { for (final O o : pair.getOutputs()) {
connector.connect(pair.getInput(), o, true); pair.getInput().connect(o, true);
} }
deviceService.saveAllAsOwner(pair.getOutputs(), username); deviceService.saveAllAsOwner(pair.getOutputs(), username);
@ -124,7 +118,7 @@ public abstract class InputDeviceConnectionController<
final Connection pair = checkConnectionIDs(inputId, outputs, username); final Connection pair = checkConnectionIDs(inputId, outputs, username);
for (final O o : pair.getOutputs()) { for (final O o : pair.getOutputs()) {
connector.connect(pair.getInput(), o, false); pair.getInput().connect(o, false);
} }
deviceService.saveAllAsOwner(pair.getOutputs(), username); deviceService.saveAllAsOwner(pair.getOutputs(), username);

View file

@ -25,7 +25,7 @@ public class KnobDimmerController extends InputDeviceConnectionController<KnobDi
KnobDimmerRepository inputRepository, KnobDimmerRepository inputRepository,
DimmableRepository<Dimmable> outputRepository, DimmableRepository<Dimmable> outputRepository,
DeviceService deviceService) { DeviceService deviceService) {
super(inputRepository, outputRepository, Dimmable.KNOB_DIMMER_DIMMABLE_CONNECTOR); super(inputRepository, outputRepository);
this.knobDimmerRepository = inputRepository; this.knobDimmerRepository = inputRepository;
this.deviceService = deviceService; this.deviceService = deviceService;
} }

View file

@ -17,8 +17,8 @@ import org.springframework.web.bind.annotation.*;
@RequestMapping("/switch") @RequestMapping("/switch")
public class SwitchController extends InputDeviceConnectionController<Switch, Switchable> { public class SwitchController extends InputDeviceConnectionController<Switch, Switchable> {
private SwitchRepository switchRepository; private final SwitchRepository switchRepository;
private DeviceService deviceService; private final DeviceService deviceService;
/** /**
* Contstructs the controller by requiring essential object for the controller implementation * Contstructs the controller by requiring essential object for the controller implementation
@ -31,7 +31,7 @@ public class SwitchController extends InputDeviceConnectionController<Switch, Sw
SwitchRepository inputRepository, SwitchRepository inputRepository,
SwitchableRepository<Switchable> outputRepository, SwitchableRepository<Switchable> outputRepository,
DeviceService deviceService) { DeviceService deviceService) {
super(inputRepository, outputRepository, Switchable.SWITCH_SWITCHABLE_CONNECTOR); super(inputRepository, outputRepository);
this.deviceService = deviceService; this.deviceService = deviceService;
this.switchRepository = inputRepository; this.switchRepository = inputRepository;
} }

View file

@ -0,0 +1,5 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
public interface Connectable<O extends OutputDevice> {
void connect(O output, boolean connect);
}

View file

@ -1,46 +0,0 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
import java.util.Set;
import java.util.function.Function;
/**
* A rule on how to connect an input device type to an output device type
*
* @param <I> the input device type
* @param <O> the output device type
*/
@FunctionalInterface
public interface Connector<I extends InputDevice, O extends OutputDevice> {
/**
* 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 ManyToMany relationship
* between J and K
*
* @param outputsGetter the getter method of the set of outputs on the input class
* @param inputsGetter the getter method of the set of outputs on the input class
* @param <J> the input device type
* @param <K> the output device type
* @return a Connector implementation for the pair of types J and K
*/
static <J extends InputDevice, K extends OutputDevice> Connector<J, K> basic(
Function<J, Set<? super K>> outputsGetter, Function<K, Set<? super J>> inputsGetter) {
return (i, o, connect) -> {
if (connect) {
outputsGetter.apply(i).add(o);
inputsGetter.apply(o).add(i);
} else {
outputsGetter.apply(i).remove(o);
inputsGetter.apply(o).remove(i);
}
};
}
}

View file

@ -12,12 +12,6 @@ import javax.validation.constraints.NotNull;
@Inheritance(strategy = InheritanceType.SINGLE_TABLE) @Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class Dimmable extends Switchable implements RangeTriggerable { public class Dimmable extends Switchable implements RangeTriggerable {
public static final Connector<KnobDimmer, Dimmable> KNOB_DIMMER_DIMMABLE_CONNECTOR =
Connector.basic(KnobDimmer::getOutputs, Dimmable::getDimmers);
public static final Connector<ButtonDimmer, Dimmable> BUTTON_DIMMER_DIMMABLE_CONNECTOR =
Connector.basic(ButtonDimmer::getOutputs, Dimmable::getDimmers);
protected Dimmable(String kind) { protected Dimmable(String kind) {
super(kind); super(kind);
} }

View file

@ -9,7 +9,7 @@ import javax.persistence.*;
/** Represents a generic dimmer input device */ /** Represents a generic dimmer input device */
@Entity @Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Dimmer extends InputDevice { public abstract class Dimmer extends InputDevice implements Connectable<Dimmable> {
public Dimmer(String kind) { public Dimmer(String kind) {
super(kind); super(kind);
} }
@ -37,4 +37,14 @@ public abstract class Dimmer extends InputDevice {
public void addDimmable(Dimmable dimmable) { public void addDimmable(Dimmable dimmable) {
dimmables.add(dimmable); dimmables.add(dimmable);
} }
public void connect(Dimmable output, boolean connect) {
if (connect) {
output.getDimmers().add(this);
getOutputs().add(output);
} else {
output.getDimmers().remove(this);
getOutputs().remove(output);
}
}
} }

View file

@ -8,7 +8,7 @@ import javax.persistence.*;
/** A switch input device */ /** A switch input device */
@Entity @Entity
public class Switch extends InputDevice implements BooleanTriggerable { public class Switch extends InputDevice implements BooleanTriggerable, Connectable<Switchable> {
@ManyToMany( @ManyToMany(
cascade = { cascade = {
@ -64,6 +64,16 @@ public class Switch extends InputDevice implements BooleanTriggerable {
return switchables; return switchables;
} }
public void connect(Switchable output, boolean connect) {
if (connect) {
output.getSwitches().add(this);
getOutputs().add(output);
} else {
output.getSwitches().remove(this);
getOutputs().remove(output);
}
}
@Override @Override
public boolean readTriggerState() { public boolean readTriggerState() {
return on; return on;

View file

@ -11,9 +11,6 @@ import javax.persistence.*;
@Inheritance(strategy = InheritanceType.JOINED) @Inheritance(strategy = InheritanceType.JOINED)
public abstract class Switchable extends OutputDevice { public abstract class Switchable extends OutputDevice {
public static final Connector<Switch, Switchable> SWITCH_SWITCHABLE_CONNECTOR =
Connector.basic(Switch::getOutputs, Switchable::getSwitches);
@ManyToMany( @ManyToMany(
mappedBy = "switchables", mappedBy = "switchables",
cascade = { cascade = {