From bdae07859c0e467a764cc0836a0a51d7380ee530 Mon Sep 17 00:00:00 2001 From: martinpentrak Date: Mon, 26 Jun 2023 17:53:05 +0200 Subject: [PATCH] added RGBLight and Thermometer devices --- checkstyle.xml | 10 +- pom.xml | 179 ++++++------- .../APIErrors/APIError.java | 13 +- .../APIErrors/NotValidSubError.java | 9 +- .../APIExceptionHandler.java | 63 ++++- .../virtualsmarthomeplus/APIRoutes.java | 12 +- .../virtualsmarthomeplus/AppConfig.java | 2 +- .../DTOs/ActuatorDTO.java | 32 +++ .../virtualsmarthomeplus/DTOs/DeviceDTO.java | 44 +++- .../virtualsmarthomeplus/DTOs/DoorDTO.java | 31 ++- .../DTOs/FireplaceDTO.java | 31 ++- .../virtualsmarthomeplus/DTOs/HouseDTO.java | 7 +- .../DTOs/RGBLightDTO.java | 56 ++++ .../virtualsmarthomeplus/DTOs/SensorDTO.java | 6 + .../DTOs/ThermometerDTO.java | 41 +++ .../Mapper/DTOMapper.java | 96 ++++--- .../VirtualSmartHomePlusApplication.java | 15 +- .../controllers/DeviceController.java | 38 ++- .../controllers/DoorController.java | 86 +++++-- .../controllers/FinalDeviceHandling.java | 151 +++++------ .../controllers/FireplaceController.java | 79 ++++-- .../controllers/HouseController.java | 5 +- .../controllers/RGBLightController.java | 110 ++++++++ .../controllers/ThermometerController.java | 118 +++++++++ .../factory/DeviceFactory.java | 33 +++ .../virtualsmarthomeplus/house/House.java | 90 +++---- .../house/devices/Actuator.java | 85 ++++++ .../house/devices/Device.java | 49 +++- .../house/devices/Sensor.java | 12 + .../house/devices/finalDevices/Door.java | 33 ++- .../house/devices/finalDevices/Fireplace.java | 36 ++- .../house/devices/finalDevices/RGBLight.java | 243 ++++++++++++++++++ .../devices/finalDevices/Thermometer.java | 145 +++++++++++ .../VirtualSmartHomePlusApplicationTests.java | 6 +- .../controllers/DoorApiTest.java | 200 ++++++++++++++ .../controllers/FireplaceApiTest.java | 207 +++++++++++++++ .../controllers/HouseApiTest.java | 70 +++++ .../controllers/RGBLightApiTest.java | 234 +++++++++++++++++ .../controllers/ThermometerApiTest.java | 211 +++++++++++++++ .../virtualsmarthomeplus/house/HouseTest.java | 75 ++++++ .../house/devices/DeviceMock.java | 23 ++ .../house/devices/DoorTest.java | 68 +++++ .../house/devices/FireplaceTest.java | 67 +++++ .../house/devices/RGBLightTest.java | 149 +++++++++++ .../house/devices/ThermometerTest.java | 67 +++++ 45 files changed, 2948 insertions(+), 389 deletions(-) create mode 100644 src/main/java/io/patriotframework/virtualsmarthomeplus/DTOs/ActuatorDTO.java create mode 100644 src/main/java/io/patriotframework/virtualsmarthomeplus/DTOs/RGBLightDTO.java create mode 100644 src/main/java/io/patriotframework/virtualsmarthomeplus/DTOs/SensorDTO.java create mode 100644 src/main/java/io/patriotframework/virtualsmarthomeplus/DTOs/ThermometerDTO.java create mode 100644 src/main/java/io/patriotframework/virtualsmarthomeplus/controllers/RGBLightController.java create mode 100644 src/main/java/io/patriotframework/virtualsmarthomeplus/controllers/ThermometerController.java create mode 100644 src/main/java/io/patriotframework/virtualsmarthomeplus/factory/DeviceFactory.java create mode 100644 src/main/java/io/patriotframework/virtualsmarthomeplus/house/devices/Actuator.java create mode 100644 src/main/java/io/patriotframework/virtualsmarthomeplus/house/devices/Sensor.java create mode 100644 src/main/java/io/patriotframework/virtualsmarthomeplus/house/devices/finalDevices/RGBLight.java create mode 100644 src/main/java/io/patriotframework/virtualsmarthomeplus/house/devices/finalDevices/Thermometer.java create mode 100644 src/test/java/io/patriotframework/virtualsmarthomeplus/controllers/DoorApiTest.java create mode 100644 src/test/java/io/patriotframework/virtualsmarthomeplus/controllers/FireplaceApiTest.java create mode 100644 src/test/java/io/patriotframework/virtualsmarthomeplus/controllers/HouseApiTest.java create mode 100644 src/test/java/io/patriotframework/virtualsmarthomeplus/controllers/RGBLightApiTest.java create mode 100644 src/test/java/io/patriotframework/virtualsmarthomeplus/controllers/ThermometerApiTest.java create mode 100644 src/test/java/io/patriotframework/virtualsmarthomeplus/house/HouseTest.java create mode 100644 src/test/java/io/patriotframework/virtualsmarthomeplus/house/devices/DeviceMock.java create mode 100644 src/test/java/io/patriotframework/virtualsmarthomeplus/house/devices/DoorTest.java create mode 100644 src/test/java/io/patriotframework/virtualsmarthomeplus/house/devices/FireplaceTest.java create mode 100644 src/test/java/io/patriotframework/virtualsmarthomeplus/house/devices/RGBLightTest.java create mode 100644 src/test/java/io/patriotframework/virtualsmarthomeplus/house/devices/ThermometerTest.java diff --git a/checkstyle.xml b/checkstyle.xml index e55e137..d11576f 100644 --- a/checkstyle.xml +++ b/checkstyle.xml @@ -28,16 +28,16 @@ - + - + - + @@ -116,13 +116,13 @@ - + - + diff --git a/pom.xml b/pom.xml index d985f04..e28d466 100644 --- a/pom.xml +++ b/pom.xml @@ -1,92 +1,97 @@ - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.7.3 - - - io.patriot-framework - virtual-smart-home-plus - 0.0.1-SNAPSHOT - virtual-smart-home-plus - Demo project for Spring Boot - - 17 - - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-test - test - - - org.apache.commons - commons-lang3 - - - org.modelmapper - modelmapper - 3.1.1 - - - org.projectlombok - lombok - 1.18.26 - provided - - - org.springframework.boot - spring-boot-starter-validation - - - com.fasterxml.jackson.datatype - jackson-datatype-jsr310 - + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.7.3 + + + io.patriot-framework + virtual-smart-home-plus + 0.0.1-SNAPSHOT + virtual-smart-home-plus + Demo project for Spring Boot + + 17 + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + test + + + org.apache.commons + commons-lang3 + + + org.modelmapper + modelmapper + 3.1.1 + + + org.projectlombok + lombok + 1.18.26 + provided + + + io.patriot-framework + generator + 2.0.1-SNAPSHOT + + + org.springframework.boot + spring-boot-starter-validation + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + - + - - - - org.springframework.boot - spring-boot-maven-plugin - - - org.apache.maven.plugins - maven-checkstyle-plugin - 3.2.0 - - - com.puppycrawl.tools - checkstyle - 10.5.0 - - - - checkstyle.xml - - - - checkstyle - validate - - check - - - true - false - - - - - - + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-checkstyle-plugin + 3.2.0 + + + com.puppycrawl.tools + checkstyle + 10.5.0 + + + + checkstyle.xml + + + + checkstyle + validate + + check + + + true + false + + + + + + diff --git a/src/main/java/io/patriotframework/virtualsmarthomeplus/APIErrors/APIError.java b/src/main/java/io/patriotframework/virtualsmarthomeplus/APIErrors/APIError.java index c2130ab..0c98bd7 100644 --- a/src/main/java/io/patriotframework/virtualsmarthomeplus/APIErrors/APIError.java +++ b/src/main/java/io/patriotframework/virtualsmarthomeplus/APIErrors/APIError.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonInclude; import org.springframework.http.HttpStatus; + import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @@ -14,15 +15,16 @@ @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) @JsonInclude(JsonInclude.Include.NON_NULL) public class APIError { - private HttpStatus status; - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy hh:mm:ss") - private LocalDateTime timestamp; private final String message; + private final HttpStatus status; + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy hh:mm:ss") + private final LocalDateTime timestamp; private List subErrors; /** * Constructs instance of APIError with current time, error message and - * @param status status for the recipient + * + * @param status status for the recipient * @param message message for the recipient */ public APIError(HttpStatus status, String message) { @@ -33,10 +35,11 @@ public APIError(HttpStatus status, String message) { /** * Adds instance of APISubError to the list of errors which caused this error + * * @param error another sub-error which caused error */ public void addSubError(APISubError error) { - if(subErrors == null) { + if (subErrors == null) { subErrors = new ArrayList<>(); } subErrors.add(error); diff --git a/src/main/java/io/patriotframework/virtualsmarthomeplus/APIErrors/NotValidSubError.java b/src/main/java/io/patriotframework/virtualsmarthomeplus/APIErrors/NotValidSubError.java index 222836c..def20c5 100644 --- a/src/main/java/io/patriotframework/virtualsmarthomeplus/APIErrors/NotValidSubError.java +++ b/src/main/java/io/patriotframework/virtualsmarthomeplus/APIErrors/NotValidSubError.java @@ -13,22 +13,23 @@ public class NotValidSubError extends APISubError { /** * object name */ - private String object; + private final String object; /** * field where the error occurs */ - private String field; + private final String field; /** * rejected value */ - private Object rejectedValue; + private final Object rejectedValue; /** * default message what causes the error */ - private String message; + private final String message; /** * Creates instance of NotValidSubError with initialized attributes. Values are parsed from FieldError + * * @param fieldError instance of FieldError */ public NotValidSubError(FieldError fieldError) { diff --git a/src/main/java/io/patriotframework/virtualsmarthomeplus/APIExceptionHandler.java b/src/main/java/io/patriotframework/virtualsmarthomeplus/APIExceptionHandler.java index 956c2ac..4e7a2b0 100644 --- a/src/main/java/io/patriotframework/virtualsmarthomeplus/APIExceptionHandler.java +++ b/src/main/java/io/patriotframework/virtualsmarthomeplus/APIExceptionHandler.java @@ -8,9 +8,13 @@ import org.springframework.validation.FieldError; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.context.request.WebRequest; import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; +import javax.management.openmbean.KeyAlreadyExistsException; +import java.util.NoSuchElementException; + /** * Handles custom exceptions */ @@ -19,24 +23,69 @@ public class APIExceptionHandler extends ResponseEntityExceptionHandler { /** * Returns proper response entity on MethodArgumentNotValidException. - * @param ex exception which caused this method call + * + * @param ex exception which caused this method call * @param headers http headers - * @param status http status + * @param status http status * @param request web request * @return {@link io.patriotframework.virtualsmarthomeplus.APIErrors.APIError APIError} instance whith list of - * {@link io.patriotframework.virtualsmarthomeplus.APIErrors.NotValidSubError NotValidSubError} instances, which - * informs about specific validity violations + * {@link io.patriotframework.virtualsmarthomeplus.APIErrors.NotValidSubError NotValidSubError} instances, which + * informs about specific validity violations */ @Override protected ResponseEntity handleMethodArgumentNotValid( MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { - String message = "Malformed JSON body"; - APIError apiError = new APIError(status, message); + final String message = "Malformed JSON body"; + final APIError apiError = new APIError(status, message); ex.getBindingResult().getAllErrors().forEach((error) -> - apiError.addSubError(new NotValidSubError((FieldError)error))); + apiError.addSubError(new NotValidSubError((FieldError) error))); return new ResponseEntity<>(apiError, status); } + /** + * Returns proper response entity on NoSuchElementException. + * + * @param ex exception which caused this method call + * @return {@link io.patriotframework.virtualsmarthomeplus.APIErrors.APIError APIError} instance whith list of + * {@link io.patriotframework.virtualsmarthomeplus.APIErrors.NotValidSubError NotValidSubError} instances, which + * informs about specific validity violations + */ + @ExceptionHandler(value = NoSuchElementException.class) + protected ResponseEntity handleNotFound(NoSuchElementException ex) { + final String message = "Device not found"; + final APIError apiError = new APIError(HttpStatus.NOT_FOUND,message); + return new ResponseEntity<>(apiError,HttpStatus.NOT_FOUND); + } + /** + * Returns proper response entity on IllegalArgumentException. + * + * @param ex exception which caused this method call + * @return {@link io.patriotframework.virtualsmarthomeplus.APIErrors.APIError APIError} instance whith list of + * {@link io.patriotframework.virtualsmarthomeplus.APIErrors.NotValidSubError NotValidSubError} instances, which + * informs about specific validity violations + */ + @ExceptionHandler(value = IllegalArgumentException.class) + protected ResponseEntity handleWrongArgument(IllegalArgumentException ex) { + final String message = "Wrong label"; + final APIError apiError = new APIError(HttpStatus.BAD_REQUEST,message); + return new ResponseEntity<>(apiError,HttpStatus.BAD_REQUEST); + } + /** + * Returns proper response entity on KeyAlreadyExistException. + * + * @param ex exception which caused this method call + * @return {@link io.patriotframework.virtualsmarthomeplus.APIErrors.APIError APIError} instance whith list of + * {@link io.patriotframework.virtualsmarthomeplus.APIErrors.NotValidSubError NotValidSubError} instances, which + * informs about specific validity violations + */ + @ExceptionHandler(value = KeyAlreadyExistsException.class) + protected ResponseEntity handleExistingDevice(IllegalArgumentException ex) { + final String message = "Device already exists"; + final APIError apiError = new APIError(HttpStatus.CONFLICT,message); + return new ResponseEntity<>(apiError,HttpStatus.CONFLICT); + } + + } diff --git a/src/main/java/io/patriotframework/virtualsmarthomeplus/APIRoutes.java b/src/main/java/io/patriotframework/virtualsmarthomeplus/APIRoutes.java index b2c1fc1..0d3c972 100644 --- a/src/main/java/io/patriotframework/virtualsmarthomeplus/APIRoutes.java +++ b/src/main/java/io/patriotframework/virtualsmarthomeplus/APIRoutes.java @@ -32,5 +32,15 @@ public class APIRoutes { /** * Route of the final device door. */ - public static final String DOOR_ROUTE = DEVICE_ROUTE + "door/";; + public static final String DOOR_ROUTE = DEVICE_ROUTE + "door/"; + /** + * Route of the final device thermometer. + */ + public static final String THERMOMETER_ROUTE = DEVICE_ROUTE + "thermometer/"; + /** + * Route of the final device RGBLight. + */ + public static final String RGB_LIGHT_ROUTE = DEVICE_ROUTE + "RGBLight/"; + + } diff --git a/src/main/java/io/patriotframework/virtualsmarthomeplus/AppConfig.java b/src/main/java/io/patriotframework/virtualsmarthomeplus/AppConfig.java index c1e562d..4bf3fbd 100644 --- a/src/main/java/io/patriotframework/virtualsmarthomeplus/AppConfig.java +++ b/src/main/java/io/patriotframework/virtualsmarthomeplus/AppConfig.java @@ -1,8 +1,8 @@ package io.patriotframework.virtualsmarthomeplus; +import org.modelmapper.ModelMapper; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.modelmapper.ModelMapper; @Configuration public class AppConfig { diff --git a/src/main/java/io/patriotframework/virtualsmarthomeplus/DTOs/ActuatorDTO.java b/src/main/java/io/patriotframework/virtualsmarthomeplus/DTOs/ActuatorDTO.java new file mode 100644 index 0000000..c16a001 --- /dev/null +++ b/src/main/java/io/patriotframework/virtualsmarthomeplus/DTOs/ActuatorDTO.java @@ -0,0 +1,32 @@ +package io.patriotframework.virtualsmarthomeplus.DTOs; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.util.Objects; +/** + * Base class for actuator devices + */ +@Getter +@Setter +@NoArgsConstructor +public class ActuatorDTO extends DeviceDTO { + /** + * True if actuator is switched on + */ + private Boolean switchedOn; + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof final ActuatorDTO that)) return false; + if (!super.equals(o)) return false; + return Objects.equals(getSwitchedOn(), that.getSwitchedOn()); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), getSwitchedOn()); + } +} diff --git a/src/main/java/io/patriotframework/virtualsmarthomeplus/DTOs/DeviceDTO.java b/src/main/java/io/patriotframework/virtualsmarthomeplus/DTOs/DeviceDTO.java index 9f4bfc4..93df420 100644 --- a/src/main/java/io/patriotframework/virtualsmarthomeplus/DTOs/DeviceDTO.java +++ b/src/main/java/io/patriotframework/virtualsmarthomeplus/DTOs/DeviceDTO.java @@ -1,25 +1,57 @@ package io.patriotframework.virtualsmarthomeplus.DTOs; +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; + import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; +import java.util.Objects; + /** * Base class for all devices */ -@Getter @Setter @NoArgsConstructor +@Getter +@Setter +@NoArgsConstructor +@JsonTypeInfo( + use = JsonTypeInfo.Id.NAME, + property = "kind") +@JsonSubTypes({ + @JsonSubTypes.Type(value = DoorDTO.class), + @JsonSubTypes.Type(value = FireplaceDTO.class), + @JsonSubTypes.Type(value = RGBLightDTO.class), + @JsonSubTypes.Type(value = ThermometerDTO.class), +}) public class DeviceDTO { /** * Each device has unique label. Label represents id of the device. */ + @NotEmpty(message = "label cannot be empty") + private String label; + /** + * Type of the device + */ @NotEmpty - public String label; - + private String deviceType; /** * True if device is enabled */ - @NotNull - public Boolean enabled; + private Boolean enabled; + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof final DeviceDTO deviceDTO)) return false; + return Objects.equals(getLabel(), deviceDTO.getLabel()) + && Objects.equals(getDeviceType(), deviceDTO.getDeviceType()) + && Objects.equals(getEnabled(), deviceDTO.getEnabled()); + } + + @Override + public int hashCode() { + return Objects.hash(getLabel(), getDeviceType(), getEnabled()); + } } diff --git a/src/main/java/io/patriotframework/virtualsmarthomeplus/DTOs/DoorDTO.java b/src/main/java/io/patriotframework/virtualsmarthomeplus/DTOs/DoorDTO.java index 5b0b04d..d5a3284 100644 --- a/src/main/java/io/patriotframework/virtualsmarthomeplus/DTOs/DoorDTO.java +++ b/src/main/java/io/patriotframework/virtualsmarthomeplus/DTOs/DoorDTO.java @@ -1,22 +1,39 @@ package io.patriotframework.virtualsmarthomeplus.DTOs; import lombok.Getter; -import lombok.NoArgsConstructor; import lombok.Setter; +import java.util.Objects; + /** * DTO for Door device */ -@Getter @Setter @NoArgsConstructor +@Getter +@Setter public class DoorDTO extends DeviceDTO { - /** - * specifies device ty by string value "Door" - */ - public final String deviceType = "Door"; + /** * In response to request this attribute has value * {@link io.patriotframework.virtualsmarthomeplus.house.devices.finalDevices.Door#CLOSED} or * {@link io.patriotframework.virtualsmarthomeplus.house.devices.finalDevices.Door#OPENED}. */ - public String status; + private String status; + + public DoorDTO() { + this.setDeviceType("Door"); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof final DoorDTO doorDTO)) return false; + if (!super.equals(o)) return false; + return Objects.equals(getDeviceType(), doorDTO.getDeviceType()) + && Objects.equals(getStatus(), doorDTO.getStatus()); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), getDeviceType(), getStatus()); + } } diff --git a/src/main/java/io/patriotframework/virtualsmarthomeplus/DTOs/FireplaceDTO.java b/src/main/java/io/patriotframework/virtualsmarthomeplus/DTOs/FireplaceDTO.java index abb266d..e6177c2 100644 --- a/src/main/java/io/patriotframework/virtualsmarthomeplus/DTOs/FireplaceDTO.java +++ b/src/main/java/io/patriotframework/virtualsmarthomeplus/DTOs/FireplaceDTO.java @@ -1,23 +1,40 @@ package io.patriotframework.virtualsmarthomeplus.DTOs; import lombok.Getter; -import lombok.NoArgsConstructor; import lombok.Setter; +import java.util.Objects; + /** * DTO for Fireplace device */ -@Getter @Setter @NoArgsConstructor +@Getter +@Setter public class FireplaceDTO extends DeviceDTO { - /** - * specifies device ty by string value "Fireplace" - */ - public final String deviceType = "Fireplace"; + /** * in response to request this attribute has value * {@link io.patriotframework.virtualsmarthomeplus.house.devices.finalDevices.Fireplace#ON_FIRE} or * {@link io.patriotframework.virtualsmarthomeplus.house.devices.finalDevices.Fireplace#EXTINGUISHED}. */ - public String status; + private String status; + + + public FireplaceDTO() { + this.setDeviceType("Fireplace"); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof final FireplaceDTO that)) return false; + if (!super.equals(o)) return false; + return Objects.equals(getDeviceType(), that.getDeviceType()) + && Objects.equals(getStatus(), that.getStatus()); + } + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), getDeviceType(), getStatus()); + } } diff --git a/src/main/java/io/patriotframework/virtualsmarthomeplus/DTOs/HouseDTO.java b/src/main/java/io/patriotframework/virtualsmarthomeplus/DTOs/HouseDTO.java index c6d6a2e..2aae540 100644 --- a/src/main/java/io/patriotframework/virtualsmarthomeplus/DTOs/HouseDTO.java +++ b/src/main/java/io/patriotframework/virtualsmarthomeplus/DTOs/HouseDTO.java @@ -3,17 +3,20 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; + import javax.validation.constraints.NotEmpty; import java.util.List; /** * DTO for whole house */ -@Getter @Setter @NoArgsConstructor +@Getter +@Setter +@NoArgsConstructor public class HouseDTO { /** * contains all devices present in the house */ @NotEmpty - public List devices; + private List devices; } diff --git a/src/main/java/io/patriotframework/virtualsmarthomeplus/DTOs/RGBLightDTO.java b/src/main/java/io/patriotframework/virtualsmarthomeplus/DTOs/RGBLightDTO.java new file mode 100644 index 0000000..0e0e6a8 --- /dev/null +++ b/src/main/java/io/patriotframework/virtualsmarthomeplus/DTOs/RGBLightDTO.java @@ -0,0 +1,56 @@ +package io.patriotframework.virtualsmarthomeplus.DTOs; + +import lombok.Getter; +import lombok.Setter; + +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; +import java.util.Objects; + +/** + * DTO for RGBLight device + */ +@Getter +@Setter +public class RGBLightDTO extends ActuatorDTO { + /** + * this attribute contains intensity of red color in RGB + */ + @Min(0) + @Max(255) + private Integer red; + /** + * this attribute contains intensity of green color in RGB + */ + @Min(0) + @Max(255) + private Integer green; + /** + * this attribute contains intensity of blue color in RGB + */ + @Min(0) + @Max(255) + private Integer blue; + + /** + * constructor sets deviceType of device + */ + public RGBLightDTO() { + this.setDeviceType("RGBLight"); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof final RGBLightDTO that)) return false; + if (!super.equals(o)) return false; + return Objects.equals(getRed(), that.getRed()) + && Objects.equals(getGreen(), that.getGreen()) + && Objects.equals(getBlue(), that.getBlue()); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), getRed(), getGreen(), getBlue()); + } +} diff --git a/src/main/java/io/patriotframework/virtualsmarthomeplus/DTOs/SensorDTO.java b/src/main/java/io/patriotframework/virtualsmarthomeplus/DTOs/SensorDTO.java new file mode 100644 index 0000000..7330b8e --- /dev/null +++ b/src/main/java/io/patriotframework/virtualsmarthomeplus/DTOs/SensorDTO.java @@ -0,0 +1,6 @@ +package io.patriotframework.virtualsmarthomeplus.DTOs; +/** + * Base class for sensor devices DTOs + */ +public class SensorDTO { +} diff --git a/src/main/java/io/patriotframework/virtualsmarthomeplus/DTOs/ThermometerDTO.java b/src/main/java/io/patriotframework/virtualsmarthomeplus/DTOs/ThermometerDTO.java new file mode 100644 index 0000000..de52ec3 --- /dev/null +++ b/src/main/java/io/patriotframework/virtualsmarthomeplus/DTOs/ThermometerDTO.java @@ -0,0 +1,41 @@ +package io.patriotframework.virtualsmarthomeplus.DTOs; + +import lombok.Getter; +import lombok.Setter; + +import java.util.Objects; + +/** + * DTO for thermometer device + */ +@Getter +@Setter +public class ThermometerDTO extends DeviceDTO { + + /** + * specifies temperature measurement unit + */ + private String unit; + /** + * value of actual temperature + */ + private Float temperature; + + public ThermometerDTO() { + this.setDeviceType("Thermometer"); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof final ThermometerDTO that)) return false; + if (!super.equals(o)) return false; + return Objects.equals(getDeviceType(), that.getDeviceType()) + && Objects.equals(getUnit(), that.getUnit()); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), getDeviceType(), getUnit(), getTemperature()); + } +} diff --git a/src/main/java/io/patriotframework/virtualsmarthomeplus/Mapper/DTOMapper.java b/src/main/java/io/patriotframework/virtualsmarthomeplus/Mapper/DTOMapper.java index 8e915c6..43b3f50 100644 --- a/src/main/java/io/patriotframework/virtualsmarthomeplus/Mapper/DTOMapper.java +++ b/src/main/java/io/patriotframework/virtualsmarthomeplus/Mapper/DTOMapper.java @@ -1,112 +1,149 @@ package io.patriotframework.virtualsmarthomeplus.Mapper; +import io.patriotframework.virtualsmarthomeplus.DTOs.ThermometerDTO; +import io.patriotframework.virtualsmarthomeplus.DTOs.HouseDTO; +import io.patriotframework.virtualsmarthomeplus.DTOs.RGBLightDTO; import io.patriotframework.virtualsmarthomeplus.DTOs.DeviceDTO; import io.patriotframework.virtualsmarthomeplus.DTOs.DoorDTO; import io.patriotframework.virtualsmarthomeplus.DTOs.FireplaceDTO; -import io.patriotframework.virtualsmarthomeplus.DTOs.HouseDTO; import io.patriotframework.virtualsmarthomeplus.house.House; import io.patriotframework.virtualsmarthomeplus.house.devices.Device; import io.patriotframework.virtualsmarthomeplus.house.devices.finalDevices.Door; import io.patriotframework.virtualsmarthomeplus.house.devices.finalDevices.Fireplace; +import io.patriotframework.virtualsmarthomeplus.house.devices.finalDevices.RGBLight; +import io.patriotframework.virtualsmarthomeplus.house.devices.finalDevices.Thermometer; import org.modelmapper.ModelMapper; import org.modelmapper.TypeMap; import org.springframework.stereotype.Component; import java.util.HashMap; +import java.util.stream.Collectors; /** * Class responsible for mapping model objects to DTOs */ @Component public class DTOMapper { - private final ModelMapper modelMapper; + private static final HashMap, Class> CLASS_TO_DTO; + private static final HashMap, Class> DTO_TO_CLASS; - private static final HashMap, Class>classToDto; static { - classToDto = new HashMap<>(); - classToDto.put(Device.class, DeviceDTO.class); - classToDto.put(Fireplace.class, FireplaceDTO.class); - classToDto.put(Door.class, DoorDTO.class); + CLASS_TO_DTO = new HashMap<>(); + CLASS_TO_DTO.put(Device.class, DeviceDTO.class); + CLASS_TO_DTO.put(Fireplace.class, FireplaceDTO.class); + CLASS_TO_DTO.put(Door.class, DoorDTO.class); + CLASS_TO_DTO.put(Thermometer.class, ThermometerDTO.class); + CLASS_TO_DTO.put(RGBLight.class, RGBLightDTO.class); } - private static final HashMap, Class> dtoToClass; static { - dtoToClass = new HashMap<>(); - dtoToClass.put(DeviceDTO.class, Device.class); - dtoToClass.put(FireplaceDTO.class, Fireplace.class); - dtoToClass.put(DoorDTO.class, Door.class); + DTO_TO_CLASS = new HashMap<>(); + DTO_TO_CLASS.put(DeviceDTO.class, Device.class); + DTO_TO_CLASS.put(FireplaceDTO.class, Fireplace.class); + DTO_TO_CLASS.put(DoorDTO.class, Door.class); + DTO_TO_CLASS.put(ThermometerDTO.class, Thermometer.class); + DTO_TO_CLASS.put(RGBLightDTO.class, RGBLight.class); + } + private final ModelMapper modelMapper; + /** * Constructs DTOMapper for all instances of the House interface + * * @param modelMapper instance of ModelMapper */ public DTOMapper(ModelMapper modelMapper) { this.modelMapper = modelMapper; - TypeMap fireplaceTypeMap = this.modelMapper + final TypeMap fireplaceTypeMap = this.modelMapper .createTypeMap(FireplaceDTO.class, Fireplace.class); fireplaceTypeMap.setProvider(request -> { - FireplaceDTO fireplaceDTO = (FireplaceDTO) request.getSource(); + final FireplaceDTO fireplaceDTO = (FireplaceDTO) request.getSource(); return new Fireplace(fireplaceDTO.getLabel()); }); - TypeMap doorTypeMap = this.modelMapper.createTypeMap(DoorDTO.class, Door.class); + final TypeMap doorTypeMap = this.modelMapper.createTypeMap(DoorDTO.class, Door.class); doorTypeMap.setProvider(request -> { - DoorDTO doorDTO = (DoorDTO) request.getSource(); + final DoorDTO doorDTO = (DoorDTO) request.getSource(); return new Door(doorDTO.getLabel()); }); + + final TypeMap rgbLightTypeMap = this.modelMapper.createTypeMap( + RGBLightDTO.class, + RGBLight.class + ); + rgbLightTypeMap.setProvider(request -> { + final RGBLightDTO rgbLightDTO = (RGBLightDTO) request.getSource(); + return new RGBLight(rgbLightDTO.getLabel()); + }); + + final TypeMap thermometerTypeMap = this.modelMapper.createTypeMap( + ThermometerDTO.class, + Thermometer.class + ); + thermometerTypeMap.setProvider(request -> { + final ThermometerDTO thermometerDTO = (ThermometerDTO) request.getSource(); + return new Thermometer(thermometerDTO.getLabel()); + }); } /** * Returns DTO of House + * * @param house house to be mapped * @return DTO of house */ - public HouseDTO map (House house) { - HouseDTO dto = modelMapper.map(house, HouseDTO.class); - dto.setDevices(house.getDevicesOfType(DeviceDTO.class).values().stream().toList()); + public HouseDTO map(House house) { + final HouseDTO dto = modelMapper.map(house, HouseDTO.class); + dto.setDevices((house.getDevicesOfType(Device.class)) + .stream() + .map(this::map) + .collect(Collectors.toList())); return dto; } /** * Returns DTO of device. + * * @param device device to be mapped * @return DTO of device * @throws DeviceMappingNotSupportedException if class of DTO is unknown for the mapper */ public DeviceDTO map(Device device) throws DeviceMappingNotSupportedException { - if(!classToDto.containsKey(device.getClass())) { + if (!CLASS_TO_DTO.containsKey(device.getClass())) { throw new DeviceMappingNotSupportedException( String.format("Device %s is not supported by DeviceMapper", device.getClass())); } - return modelMapper.map(device, classToDto.get(device.getClass())); + return modelMapper.map(device, CLASS_TO_DTO.get(device.getClass())); } /** * Returns device from DTO + * * @param dto dto to be mapped * @return device of class which corresponds to type of device in DTO * @throws DeviceMappingNotSupportedException if class of DTO is unknown for the mapper */ public Device map(DeviceDTO dto) throws DeviceMappingNotSupportedException { - if(!dtoToClass.containsKey(dto.getClass())) { + if (!DTO_TO_CLASS.containsKey(dto.getClass())) { throw new DeviceMappingNotSupportedException( String.format("DeviceDTO %s is not supported by DeviceMapper", dto.getClass())); } - return modelMapper.map(dto, dtoToClass.get(dto.getClass())); + return modelMapper.map(dto, DTO_TO_CLASS.get(dto.getClass())); } /** * Returns class of the device corresponding to DTO class; + * * @param dto class of the dto * @return class of the corresponding device * @throws DeviceMappingNotSupportedException if class of DTO is unknown for the mapper */ - public Class mapDtoClassType(Class dto) + public Class mapDtoClassType(Class dto) throws DeviceMappingNotSupportedException { - Class result = dtoToClass.get(dto); - if(result == null) { + final Class result = DTO_TO_CLASS.get(dto); + if (result == null) { throw new DeviceMappingNotSupportedException( String.format("DeviceDTO %s is not supported by DeviceMapper", dto)); } @@ -115,13 +152,14 @@ public Class mapDtoClassType(Class dto) /** * Returns class of the DTO corresponding to device class; + * * @param device class of the device * @return class of the corresponding DTO * @throws DeviceMappingNotSupportedException if class of device is unknown for the mapper */ - public Class mapDeviceClassType(Class device) { - Class result = classToDto.get(device); - if(result == null) { + public Class mapDeviceClassType(Class device) { + final Class result = CLASS_TO_DTO.get(device); + if (result == null) { throw new DeviceMappingNotSupportedException( String.format("Device %s is not supported by DeviceMapper", device)); } diff --git a/src/main/java/io/patriotframework/virtualsmarthomeplus/VirtualSmartHomePlusApplication.java b/src/main/java/io/patriotframework/virtualsmarthomeplus/VirtualSmartHomePlusApplication.java index 850c463..9ab9fa7 100644 --- a/src/main/java/io/patriotframework/virtualsmarthomeplus/VirtualSmartHomePlusApplication.java +++ b/src/main/java/io/patriotframework/virtualsmarthomeplus/VirtualSmartHomePlusApplication.java @@ -10,11 +10,12 @@ @SpringBootApplication public class VirtualSmartHomePlusApplication { - /** - * Main method, where the Spring Boot container is executed. - * @param args args given to Spring Boot application - */ - public static void main(String[] args) { - SpringApplication.run(VirtualSmartHomePlusApplication.class, args); - } + /** + * Main method, where the Spring Boot container is executed. + * + * @param args args given to Spring Boot application + */ + public static void main(String[] args) { + SpringApplication.run(VirtualSmartHomePlusApplication.class, args); + } } diff --git a/src/main/java/io/patriotframework/virtualsmarthomeplus/controllers/DeviceController.java b/src/main/java/io/patriotframework/virtualsmarthomeplus/controllers/DeviceController.java index 3289a4f..f6a1867 100644 --- a/src/main/java/io/patriotframework/virtualsmarthomeplus/controllers/DeviceController.java +++ b/src/main/java/io/patriotframework/virtualsmarthomeplus/controllers/DeviceController.java @@ -3,14 +3,21 @@ import io.patriotframework.virtualsmarthomeplus.APIRoutes; import io.patriotframework.virtualsmarthomeplus.APIVersions; import io.patriotframework.virtualsmarthomeplus.DTOs.DeviceDTO; +import io.patriotframework.virtualsmarthomeplus.Mapper.DTOMapper; import io.patriotframework.virtualsmarthomeplus.house.House; +import io.patriotframework.virtualsmarthomeplus.house.devices.Device; +import org.modelmapper.ModelMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.server.ResponseStatusException; + import java.util.ArrayList; +import java.util.NoSuchElementException; +import java.util.stream.Collectors; /** @@ -18,23 +25,28 @@ */ @RestController public class DeviceController { - private final House house; private static final String DEVICE_ID_ROUTE = APIRoutes.DEVICE_ROUTE + "{label}"; - + private final House house; + private final DTOMapper dtoMapper; @Autowired public DeviceController(House house) { this.house = house; + dtoMapper = new DTOMapper(new ModelMapper()); } /** * Returns the list of all devices + * * @param apiVersion api version specified in the route * @return list of all devices in the house */ @GetMapping(APIRoutes.DEVICE_ROUTE) - public ArrayList getDevices(@PathVariable String apiVersion) { - if(apiVersion.equals(APIVersions.V0_1)) { - return new ArrayList<>((house.getDevicesOfType(DeviceDTO.class).values())); + public ResponseEntity> getDevices(@PathVariable String apiVersion) { + if (apiVersion.equals(APIVersions.V0_1)) { + return new ResponseEntity<>(new ArrayList<>((house.getDevicesOfType(Device.class) + .stream() + .map(dtoMapper::map) + .collect(Collectors.toList()))), HttpStatus.OK); } throw new ResponseStatusException( @@ -44,21 +56,19 @@ public ArrayList getDevices(@PathVariable String apiVersion) { /** * Returns the device specified by it`s label - * @param label label of the requested device specified in route + * + * @param label label of the requested device specified in route * @param apiVersion api version specified in route * @return device of any type with given label from the house, */ @GetMapping(DEVICE_ID_ROUTE) public DeviceDTO getDevice(@PathVariable String label, @PathVariable String apiVersion) { - if(apiVersion.equals(APIVersions.V0_1)) { - DeviceDTO retrievedDevice = house.getDevice(label); - if(retrievedDevice == null) { - throw new ResponseStatusException( - HttpStatus.NOT_FOUND, "device with given label not found" // 404 - ); + if (apiVersion.equals(APIVersions.V0_1)) { + final Device retrievedDevice = house.getDevice(label); + if (retrievedDevice == null) { + throw new NoSuchElementException("Device not found"); } - - return retrievedDevice; + return dtoMapper.map(retrievedDevice); } throw new ResponseStatusException( diff --git a/src/main/java/io/patriotframework/virtualsmarthomeplus/controllers/DoorController.java b/src/main/java/io/patriotframework/virtualsmarthomeplus/controllers/DoorController.java index 6976ce3..3019d63 100644 --- a/src/main/java/io/patriotframework/virtualsmarthomeplus/controllers/DoorController.java +++ b/src/main/java/io/patriotframework/virtualsmarthomeplus/controllers/DoorController.java @@ -1,12 +1,26 @@ package io.patriotframework.virtualsmarthomeplus.controllers; import io.patriotframework.virtualsmarthomeplus.APIRoutes; +import io.patriotframework.virtualsmarthomeplus.APIVersions; import io.patriotframework.virtualsmarthomeplus.DTOs.DeviceDTO; import io.patriotframework.virtualsmarthomeplus.DTOs.DoorDTO; -import io.patriotframework.virtualsmarthomeplus.Mapper.DTOMapper; import io.patriotframework.virtualsmarthomeplus.house.House; -import org.springframework.web.bind.annotation.*; +import io.patriotframework.virtualsmarthomeplus.house.devices.finalDevices.Door; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RestController; + +import org.springframework.web.server.ResponseStatusException; + import javax.validation.Valid; +import javax.validation.constraints.NotNull; /** @@ -16,51 +30,89 @@ public class DoorController extends FinalDeviceHandling { private static final String DOOR_ID_ROUTE = APIRoutes.DOOR_ROUTE + "{label}"; - DoorController(House house, DTOMapper dtoMapper) { - super(house, dtoMapper); + DoorController(House house) { + super(house); } /** * Returns the door - * @param label label specified in route + * + * @param label label specified in route * @param apiVersion api version specified in route * @return door if present in the house */ @GetMapping(DOOR_ID_ROUTE) - public DeviceDTO getDoor(@PathVariable String label, @PathVariable String apiVersion) { - return handleGet(label, DoorDTO.class, apiVersion); + public ResponseEntity getDoor(@NotNull @PathVariable String label, @PathVariable String apiVersion) { + if (apiVersion.equals(APIVersions.V0_1)) { + return new ResponseEntity<>(handleGet(label, Door.class), HttpStatus.OK); + } + + throw new ResponseStatusException( + HttpStatus.NOT_FOUND, String.format("Unknown api version: %s", apiVersion) // 404 + ); } /** * Creates the door - * @param device new door + * + * @param device new door * @param apiVersion api version specified in route * @return door added to the house */ @PostMapping(APIRoutes.DOOR_ROUTE) - public DeviceDTO postDoor(@Valid @RequestBody DoorDTO device, @PathVariable String apiVersion) { - return handlePost(device, apiVersion); + public ResponseEntity postDoor( + @Valid @RequestBody DoorDTO device, + @NotNull @PathVariable String apiVersion + ) { + if (apiVersion.equals(APIVersions.V0_1)) { + return new ResponseEntity<>(handlePost(device), HttpStatus.OK); + } + + throw new ResponseStatusException( + HttpStatus.NOT_FOUND, String.format("Unknown api version: %s", apiVersion) // 404 + ); } /** * Updates or creates the door - * @param device updated door + * + * @param device updated door * @param apiVersion api version specified in route + * @param label label of the new device * @return door updated or added to the house */ - @PutMapping(APIRoutes.DOOR_ROUTE) - public DeviceDTO putDoor(@Valid @RequestBody DoorDTO device, @PathVariable String apiVersion) { - return handlePut(device, apiVersion); + @PutMapping(DOOR_ID_ROUTE) + public ResponseEntity putDoor( + @Valid @RequestBody DoorDTO device, + @NotNull @PathVariable String label, + @PathVariable String apiVersion + ) { + if (apiVersion.equals(APIVersions.V0_1)) { + return new ResponseEntity<>(handlePut(label, device), HttpStatus.OK); + } + + throw new ResponseStatusException( + HttpStatus.NOT_FOUND, String.format("Unknown api version: %s", apiVersion) // 404 + ); } /** * Deletes the door - * @param label label of the door to be deleted + * + * @param label label of the door to be deleted * @param apiVersion api version specified in route * @return "OK" if door exists in the house and was deleted */ @DeleteMapping(DOOR_ID_ROUTE) - public String deleteDoor(@PathVariable String label, @PathVariable String apiVersion) { - return handleDelete(label, DoorDTO.class, apiVersion); + public ResponseEntity deleteDoor(@NotNull @PathVariable String label, @PathVariable String apiVersion) { + if (apiVersion.equals(APIVersions.V0_1)) { + handleDelete(label, Door.class); + + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + throw new ResponseStatusException( + HttpStatus.NOT_FOUND, String.format("Unknown api version: %s", apiVersion) // 404 + ); } } diff --git a/src/main/java/io/patriotframework/virtualsmarthomeplus/controllers/FinalDeviceHandling.java b/src/main/java/io/patriotframework/virtualsmarthomeplus/controllers/FinalDeviceHandling.java index 9088a4a..aeb1cc1 100644 --- a/src/main/java/io/patriotframework/virtualsmarthomeplus/controllers/FinalDeviceHandling.java +++ b/src/main/java/io/patriotframework/virtualsmarthomeplus/controllers/FinalDeviceHandling.java @@ -1,140 +1,119 @@ package io.patriotframework.virtualsmarthomeplus.controllers; -import io.patriotframework.virtualsmarthomeplus.APIVersions; import io.patriotframework.virtualsmarthomeplus.DTOs.DeviceDTO; import io.patriotframework.virtualsmarthomeplus.Mapper.DTOMapper; +import io.patriotframework.virtualsmarthomeplus.factory.DeviceFactory; import io.patriotframework.virtualsmarthomeplus.house.House; -import org.modelmapper.MappingException; -import org.springframework.http.HttpStatus; +import io.patriotframework.virtualsmarthomeplus.house.devices.Device; +import io.patriotframework.virtualsmarthomeplus.house.devices.finalDevices.RGBLight; +import org.modelmapper.ModelMapper; import org.springframework.stereotype.Component; import org.springframework.web.server.ResponseStatusException; +import javax.management.openmbean.KeyAlreadyExistsException; +import java.util.NoSuchElementException; @Component public class FinalDeviceHandling { - private final House house; - private final DTOMapper dtoMapper; - /** * string that will be returned after successful deletion */ public static final String DELETED_RESPONSE = "OK"; + private final House house; + private final DTOMapper dtoMapper; - FinalDeviceHandling(House house, DTOMapper dtoMapper) { + FinalDeviceHandling(House house) { this.house = house; - this.dtoMapper = dtoMapper; + this.dtoMapper = new DTOMapper(new ModelMapper()); } /** * Serving method for get requests on the final device. - * @param label label of the requested device + * + * @param label label of the requested device * @param deviceClass class of the requested device - * @param apiVersion used api version + * @return device DTO of specified class with given label if present in the house * @throws ResponseStatusException 404 if device is not present in the house or invalid API version is demanded - * @return device of specified class with given label if present in the house */ - public DeviceDTO handleGet(String label, Class deviceClass, String apiVersion) { - if(apiVersion.equals(APIVersions.V0_1)) { - final DeviceDTO retrievedDevice = house.getDevicesOfType(deviceClass).get(label); - - if (retrievedDevice == null) { - throw new ResponseStatusException( - HttpStatus.NOT_FOUND, "device with given label not found" // 404 - ); - } - return retrievedDevice; - } + public DeviceDTO handleGet(String label, Class deviceClass) + throws NoSuchElementException, IllegalArgumentException { + final Device retrievedDevice = house.getDeviceOfType(deviceClass, label); - throw new ResponseStatusException( - HttpStatus.NOT_FOUND, String.format("Unknown api version: %s", apiVersion) // 404 - ); + if (retrievedDevice == null) { + throw new NoSuchElementException("Device not found!"); + } + return dtoMapper.map(retrievedDevice); } /** * Serving method for post requests on the final device. + * * @param device device to add to the house - * @param apiVersion used api version - * @throws ResponseStatusException 409 if device already exists in the house, 404 if invalid API version is demanded * @return device of specified class with given label if present in the house + * @throws ResponseStatusException 409 if device already exists in the house, 404 if invalid API version is demanded */ - public DeviceDTO handlePost(DeviceDTO device, String apiVersion) { - if(apiVersion.equals(APIVersions.V0_1)) { - final DeviceDTO checkForConflict = house - .getDevicesOfType(device.getClass()) - .get(device.getLabel()); - if (checkForConflict != null) { - throw new ResponseStatusException( - HttpStatus.CONFLICT, "device with given label already exists" // 409 - ); - } - - try { - house.addDevice(device); - } catch (MappingException exc) { - throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Label cannot be null", exc); - } - - return house.getDevice(device.getLabel()); + public DeviceDTO handlePost(DeviceDTO device) throws IllegalArgumentException { + final Device checkForConflict = house + .getDeviceOfType(dtoMapper.mapDtoClassType(device.getClass()), device.getLabel()); + if (checkForConflict != null) { + throw new KeyAlreadyExistsException("Device already exists"); } + final DeviceFactory factory = new DeviceFactory(); + final Device newDevice = factory.createDevice(device); + house.addDevice(newDevice); + newDevice.update(device); - throw new ResponseStatusException( - HttpStatus.NOT_FOUND, String.format("Unknown api version: %s", apiVersion) // 404 - ); + return dtoMapper.map(house.getDevice(device.getLabel())); } /** * Serving method for put requests on the final device. + * * @param device device to update or add to the house - * @param apiVersion used api version - * @throws ResponseStatusException 404 if invalid API version is demanded - * @return updated device of specified class with given label if present in the house + * @param label label of the device to be updated + * @return updated device DTO of specified class with given label if present in the house + * @throws IllegalArgumentException if label is null + * @throws NoSuchElementException if device we want to update is not in the house */ - public DeviceDTO handlePut(DeviceDTO device, String apiVersion) { - if(apiVersion.equals(APIVersions.V0_1)) { - final DeviceDTO deviceInHouse = house - .getDevicesOfType(device.getClass()) - .get(device.getLabel()); - if (deviceInHouse == null) { - house.addDevice(device); - } else { - house.updateDevice(device); - } - - return house.getDevice(device.getLabel()); + public DeviceDTO handlePut(String label, DeviceDTO device) + throws IllegalArgumentException, NoSuchElementException { + if (device == null) throw new IllegalArgumentException(); + Device deviceToUpdate = house + .getDeviceOfType(dtoMapper.mapDtoClassType(device.getClass()), label); + if (deviceToUpdate == null) { + final RGBLight rgbLight = new RGBLight(device.getLabel()); + deviceToUpdate = rgbLight; + house.addDevice(rgbLight); } + deviceToUpdate.update(device); - throw new ResponseStatusException( - HttpStatus.NOT_FOUND, String.format("Unknown api version: %s", apiVersion) // 404 - ); + if (!label.equals(deviceToUpdate.getLabel())) { + house.removeDevice(label); + house.addDevice(deviceToUpdate); + } + + return dtoMapper.map(deviceToUpdate); } /** * Serving method for delete requests on the final device. - * @param label label of the device to delete - * @param deviceDtoClass class of the device requested to delete - * @param apiVersion used api version - * @throws ResponseStatusException 404 if invalid API version is demanded - * @return {@link FinalDeviceHandling#DELETED_RESPONSE} if device of specified class with given label was deleted - * from the house + * + * @param label label of the device to delete + * @param deviceClass class of the device requested to delete + * @throws NoSuchElementException if required device is not in house */ - public String handleDelete(String label, Class deviceDtoClass, String apiVersion) { - if(apiVersion.equals(APIVersions.V0_1)) { + public void handleDelete( + String label, + Class deviceClass + ) throws NoSuchElementException, IllegalArgumentException { + final Device retrievedDevice = house.getDeviceOfType(deviceClass, label); - final DeviceDTO retrievedDevice = house.getDevicesOfType(deviceDtoClass).get(label); + if (retrievedDevice == null) { - if (retrievedDevice == null) { - throw new ResponseStatusException( - HttpStatus.NOT_FOUND, "device with given label not found" // 404 - ); - } - house.removeDevice(label); - return DELETED_RESPONSE; + throw new NoSuchElementException("Device not found!"); } - - throw new ResponseStatusException( - HttpStatus.NOT_FOUND, String.format("Unknown api version: %s", apiVersion) // 404 - ); + house.removeDevice(label); } } diff --git a/src/main/java/io/patriotframework/virtualsmarthomeplus/controllers/FireplaceController.java b/src/main/java/io/patriotframework/virtualsmarthomeplus/controllers/FireplaceController.java index f3fb485..3f445cc 100644 --- a/src/main/java/io/patriotframework/virtualsmarthomeplus/controllers/FireplaceController.java +++ b/src/main/java/io/patriotframework/virtualsmarthomeplus/controllers/FireplaceController.java @@ -1,12 +1,24 @@ package io.patriotframework.virtualsmarthomeplus.controllers; import io.patriotframework.virtualsmarthomeplus.APIRoutes; +import io.patriotframework.virtualsmarthomeplus.APIVersions; import io.patriotframework.virtualsmarthomeplus.DTOs.DeviceDTO; import io.patriotframework.virtualsmarthomeplus.DTOs.FireplaceDTO; -import io.patriotframework.virtualsmarthomeplus.Mapper.DTOMapper; import io.patriotframework.virtualsmarthomeplus.house.House; -import org.springframework.web.bind.annotation.*; +import io.patriotframework.virtualsmarthomeplus.house.devices.finalDevices.Fireplace; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.server.ResponseStatusException; + import javax.validation.Valid; +import javax.validation.constraints.NotNull; /** * Handles the POST, GET, PUT and DELETE requests on Fireplace route: {@link APIRoutes#FIREPLACE_ROUTE} @@ -16,51 +28,86 @@ public class FireplaceController extends FinalDeviceHandling { private static final String FIREPLACE_ID_ROUTE = APIRoutes.FIREPLACE_ROUTE + "{label}"; - FireplaceController(House house, DTOMapper AbstractDeviceDTO) { - super(house, AbstractDeviceDTO); + FireplaceController(House house) { + super(house); } /** * Returns the fireplace - * @param label label specified in route + * + * @param label label specified in route * @param apiVersion api version specified in route * @return Fireplace if present in the house */ @GetMapping(FIREPLACE_ID_ROUTE) - public DeviceDTO getFireplace(@PathVariable String label, @PathVariable String apiVersion) { - return handleGet(label, FireplaceDTO.class, apiVersion); + public DeviceDTO getFireplace(@NotNull @PathVariable String label, @PathVariable String apiVersion) { + if (apiVersion.equals(APIVersions.V0_1)) { + return handleGet(label, Fireplace.class); + } + throw new ResponseStatusException( + HttpStatus.NOT_FOUND, String.format("Unknown api version: %s", apiVersion) // 404 + ); } /** * Creates the fireplace - * @param device new fireplace + * + * @param device new fireplace DTO * @param apiVersion api version specified in route * @return fireplace added to the house */ @PostMapping(APIRoutes.FIREPLACE_ROUTE) public DeviceDTO postFireplace(@Valid @RequestBody FireplaceDTO device, @PathVariable String apiVersion) { - return handlePost(device, apiVersion); + if (apiVersion.equals(APIVersions.V0_1)) { + + return handlePost(device); + } + throw new ResponseStatusException( + HttpStatus.NOT_FOUND, String.format("Unknown api version: %s", apiVersion) // 404 + ); } /** * Updates or creates the fireplace - * @param device updated fireplace + * + * @param device updated fireplace DTO * @param apiVersion api version specified in route + * @param label label of the device to be created * @return fireplace updated or added to the house */ - @PutMapping(APIRoutes.FIREPLACE_ROUTE) - public DeviceDTO putFireplace(@Valid @RequestBody FireplaceDTO device, @PathVariable String apiVersion) { - return handlePut(device, apiVersion); + @PutMapping(FIREPLACE_ID_ROUTE) + public DeviceDTO putFireplace( + @Valid @RequestBody FireplaceDTO device, + @NotNull @PathVariable String label, + @PathVariable String apiVersion + ) { + if (apiVersion.equals(APIVersions.V0_1)) { + return handlePut(label, device); + } + throw new ResponseStatusException( + HttpStatus.NOT_FOUND, String.format("Unknown api version: %s", apiVersion) // 404 + ); } /** * Deletes the fireplace - * @param label label of the fireplace to be deleted + * + * @param label label of the fireplace to be deleted * @param apiVersion api version specified in route * @return "OK" if fireplace exists in the house and was deleted */ @DeleteMapping(FIREPLACE_ID_ROUTE) - public String deleteFireplace(@PathVariable String label, @PathVariable String apiVersion) { - return handleDelete(label, FireplaceDTO.class, apiVersion); + public ResponseEntity deleteFireplace( + @NotNull @PathVariable String label, + @PathVariable String apiVersion + ) { + if (apiVersion.equals(APIVersions.V0_1)) { + handleDelete(label, Fireplace.class); + + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + throw new ResponseStatusException( + HttpStatus.NOT_FOUND, String.format("Unknown api version: %s", apiVersion) // 404 + ); } } diff --git a/src/main/java/io/patriotframework/virtualsmarthomeplus/controllers/HouseController.java b/src/main/java/io/patriotframework/virtualsmarthomeplus/controllers/HouseController.java index 744ff0e..54c7d5d 100644 --- a/src/main/java/io/patriotframework/virtualsmarthomeplus/controllers/HouseController.java +++ b/src/main/java/io/patriotframework/virtualsmarthomeplus/controllers/HouseController.java @@ -5,7 +5,6 @@ import io.patriotframework.virtualsmarthomeplus.DTOs.HouseDTO; import io.patriotframework.virtualsmarthomeplus.Mapper.DTOMapper; import io.patriotframework.virtualsmarthomeplus.house.House; - import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -13,7 +12,6 @@ import org.springframework.web.server.ResponseStatusException; - /** * Handles the GET requests on House route: {@link APIRoutes#HOUSE_ROUTE} */ @@ -31,9 +29,10 @@ public class HouseController { /** * Serving method for get requests on the house. + * * @param apiVersion used api version - * @throws ResponseStatusException 404 if invalid API version is demanded * @return house with it`s devices + * @throws ResponseStatusException 404 if invalid API version is demanded */ @GetMapping(APIRoutes.HOUSE_ROUTE) public HouseDTO getHouse(@PathVariable String apiVersion) { diff --git a/src/main/java/io/patriotframework/virtualsmarthomeplus/controllers/RGBLightController.java b/src/main/java/io/patriotframework/virtualsmarthomeplus/controllers/RGBLightController.java new file mode 100644 index 0000000..eafd600 --- /dev/null +++ b/src/main/java/io/patriotframework/virtualsmarthomeplus/controllers/RGBLightController.java @@ -0,0 +1,110 @@ +package io.patriotframework.virtualsmarthomeplus.controllers; + +import io.patriotframework.virtualsmarthomeplus.APIRoutes; +import io.patriotframework.virtualsmarthomeplus.APIVersions; +import io.patriotframework.virtualsmarthomeplus.DTOs.DeviceDTO; +import io.patriotframework.virtualsmarthomeplus.DTOs.RGBLightDTO; +import io.patriotframework.virtualsmarthomeplus.house.House; +import io.patriotframework.virtualsmarthomeplus.house.devices.finalDevices.RGBLight; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.server.ResponseStatusException; + +import javax.validation.Valid; +import javax.validation.constraints.NotNull; + + +@RestController +public class RGBLightController extends FinalDeviceHandling { + private static final String RGB_LIGHT_ID_ROUTE = APIRoutes.RGB_LIGHT_ROUTE + "{label}"; + + RGBLightController(House house) { + super(house); + } + + /** + * Creates the RGBLight + * + * @param device new RGBLight DTO + * @param apiVersion api version specified in route + * @return RGBLight added to the house + */ + @PostMapping(APIRoutes.RGB_LIGHT_ROUTE) + public ResponseEntity postLed(@Valid @RequestBody RGBLightDTO device, @PathVariable String apiVersion) { + if (apiVersion.equals(APIVersions.V0_1)) { + return new ResponseEntity<>(handlePost(device), HttpStatus.OK); + } + throw new ResponseStatusException( + HttpStatus.NOT_FOUND, String.format("Unknown api version: %s", apiVersion) // 404 + ); + } + + /** + * Returns the RGBLight + * + * @param label label specified in route + * @param apiVersion api version specified in route + * @return RGBlight if present in the house + */ + @GetMapping(RGB_LIGHT_ID_ROUTE) + public ResponseEntity getLed(@PathVariable @NotNull String label, @PathVariable String apiVersion) { + if (apiVersion.equals(APIVersions.V0_1)) { + return new ResponseEntity<>(handleGet(label, RGBLight.class), HttpStatus.OK); + } + throw new ResponseStatusException( + HttpStatus.NOT_FOUND, String.format("Unknown api version: %s", apiVersion) // 404 + ); + } + + /** + * Updates or creates the RGBLight + * + * @param device updated RGBLight DTO + * @param apiVersion api version specified in route + * @param label label of the RGBLight to be created + * @return RGBLight updated or added to the house + */ + @PutMapping(RGB_LIGHT_ID_ROUTE) + public ResponseEntity putLed( + @Valid @RequestBody RGBLightDTO device, + @PathVariable @NotNull String label, + @PathVariable String apiVersion + ) { + if (apiVersion.equals(APIVersions.V0_1)) { + return new ResponseEntity<>(handlePut(label, device), HttpStatus.OK); + } + throw new ResponseStatusException( + HttpStatus.NOT_FOUND, String.format("Unknown api version: %s", apiVersion) // 404 + ); + } + + + /** + * Deletes the RGBLight + * + * @param label label of the RGBLight to be deleted + * @param apiVersion api version specified in route + * @return "OK" if RGBLight exists in the house and was deleted + */ + @DeleteMapping(RGB_LIGHT_ID_ROUTE) + public ResponseEntity deleteRGBLight( + @PathVariable @NotNull String label, + @PathVariable String apiVersion + ) { + if (apiVersion.equals(APIVersions.V0_1)) { + handleDelete(label, RGBLight.class); + + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + throw new ResponseStatusException( + HttpStatus.NOT_FOUND, String.format("Unknown api version: %s", apiVersion) // 404 + ); + } +} diff --git a/src/main/java/io/patriotframework/virtualsmarthomeplus/controllers/ThermometerController.java b/src/main/java/io/patriotframework/virtualsmarthomeplus/controllers/ThermometerController.java new file mode 100644 index 0000000..b49c17c --- /dev/null +++ b/src/main/java/io/patriotframework/virtualsmarthomeplus/controllers/ThermometerController.java @@ -0,0 +1,118 @@ +package io.patriotframework.virtualsmarthomeplus.controllers; + +import io.patriotframework.virtualsmarthomeplus.APIRoutes; +import io.patriotframework.virtualsmarthomeplus.APIVersions; +import io.patriotframework.virtualsmarthomeplus.DTOs.DeviceDTO; +import io.patriotframework.virtualsmarthomeplus.DTOs.ThermometerDTO; +import io.patriotframework.virtualsmarthomeplus.house.House; +import io.patriotframework.virtualsmarthomeplus.house.devices.finalDevices.Thermometer; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.server.ResponseStatusException; + +import javax.validation.constraints.NotNull; + +@RestController +public class ThermometerController extends FinalDeviceHandling { + public static final String THERMOMETER_ID_ROUTE = APIRoutes.THERMOMETER_ROUTE + "{label}"; + + public static final String THERMOMETER_GET_TEMPERATURE = THERMOMETER_ID_ROUTE + "/getTemperature"; + + public static final String THERMOMETER_GET_UNIT = THERMOMETER_ID_ROUTE + "/getUnit"; + + public static final String THERMOMETER_SET_UNIT = THERMOMETER_ID_ROUTE + "/setUnit"; + + @Autowired + ThermometerController(House house) { + super(house); + } + + /** + * Returns the thermometer + * + * @param label label specified in route + * @param apiVersion api version specified in route + * @return thermometer if present in the house + */ + @GetMapping(THERMOMETER_ID_ROUTE) + public DeviceDTO getThermometer(@PathVariable String label, @PathVariable String apiVersion) { + if (apiVersion.equals(APIVersions.V0_1)) { + return handleGet(label, Thermometer.class); + } + throw new ResponseStatusException( + HttpStatus.NOT_FOUND, String.format("Unknown api version: %s", apiVersion) // 404 + ); + } + + /** + * Creates the thermometer + * + * @param device new thermometer DTO + * @param apiVersion api version specified in route + * @return thermometer added to the house + */ + @PostMapping(APIRoutes.THERMOMETER_ROUTE) + public DeviceDTO postThermometer( + @RequestBody ThermometerDTO device, + @PathVariable String apiVersion) { + if (apiVersion.equals(APIVersions.V0_1)) { + return handlePost(device); + } + throw new ResponseStatusException( + HttpStatus.NOT_FOUND, String.format("Unknown api version: %s", apiVersion) // 404 + ); + } + + /** + * Updates or creates the thermometer + * + * @param thermometer updated thermometer DTO + * @param apiVersion api version specified in route + * @param label label of the thermometer to be updated + * @return thermometer updated or added to the house + */ + @PutMapping(THERMOMETER_ID_ROUTE) + public DeviceDTO putThermometer( + @RequestBody ThermometerDTO thermometer, + @NotNull @PathVariable String label, + @PathVariable String apiVersion + ) { + if (apiVersion.equals(APIVersions.V0_1)) { + return handlePut(label, thermometer); + } + throw new ResponseStatusException( + HttpStatus.NOT_FOUND, String.format("Unknown api version: %s", apiVersion) // 404 + ); + } + + /** + * Deletes the thermometer + * + * @param label label of the thermometer to be deleted + * @param apiVersion api version specified in route + * @return "OK" if thermometer exists in the house and was deleted + */ + @DeleteMapping(THERMOMETER_ID_ROUTE) + public ResponseEntity deleteThermometer( + @NotNull @PathVariable String label, + @PathVariable String apiVersion + ) { + if (apiVersion.equals(APIVersions.V0_1)) { + handleDelete(label, Thermometer.class); + + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + throw new ResponseStatusException( + HttpStatus.NOT_FOUND, String.format("Unknown api version: %s", apiVersion) // 404 + ); + } +} diff --git a/src/main/java/io/patriotframework/virtualsmarthomeplus/factory/DeviceFactory.java b/src/main/java/io/patriotframework/virtualsmarthomeplus/factory/DeviceFactory.java new file mode 100644 index 0000000..e5b1cac --- /dev/null +++ b/src/main/java/io/patriotframework/virtualsmarthomeplus/factory/DeviceFactory.java @@ -0,0 +1,33 @@ +package io.patriotframework.virtualsmarthomeplus.factory; + +import io.patriotframework.virtualsmarthomeplus.DTOs.DeviceDTO; +import io.patriotframework.virtualsmarthomeplus.house.devices.Device; +import io.patriotframework.virtualsmarthomeplus.house.devices.finalDevices.Door; +import io.patriotframework.virtualsmarthomeplus.house.devices.finalDevices.Fireplace; +import io.patriotframework.virtualsmarthomeplus.house.devices.finalDevices.RGBLight; +import io.patriotframework.virtualsmarthomeplus.house.devices.finalDevices.Thermometer; + +/** + * Class for creation of Devices + */ +public class DeviceFactory { + public DeviceFactory() { + } + + /** + * Creates an instance of device using DeviceDTO. + * + * @param device DTO of device to be created + * @return devices of certain type + */ + public Device createDevice( DeviceDTO device) { + final String deviceType = device.getClass().getSimpleName(); + return switch (deviceType) { + case "RGBLightDTO" -> new RGBLight(device.getLabel()); + case "ThermometerDTO" -> new Thermometer(device.getLabel()); + case "FireplaceDTO" -> new Fireplace(device.getLabel()); + case "DoorDTO" -> new Door(device.getLabel()); + default -> throw new IllegalArgumentException(); + }; + } +} diff --git a/src/main/java/io/patriotframework/virtualsmarthomeplus/house/House.java b/src/main/java/io/patriotframework/virtualsmarthomeplus/house/House.java index de413a4..679e480 100644 --- a/src/main/java/io/patriotframework/virtualsmarthomeplus/house/House.java +++ b/src/main/java/io/patriotframework/virtualsmarthomeplus/house/House.java @@ -1,12 +1,12 @@ package io.patriotframework.virtualsmarthomeplus.house; -import io.patriotframework.virtualsmarthomeplus.DTOs.DeviceDTO; -import io.patriotframework.virtualsmarthomeplus.Mapper.DTOMapper; import io.patriotframework.virtualsmarthomeplus.house.devices.Device; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; + import javax.management.openmbean.KeyAlreadyExistsException; +import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.concurrent.ConcurrentHashMap; @@ -18,26 +18,23 @@ @Service public class House { - DTOMapper dtoMapper; private static final Logger LOGGER = LoggerFactory.getLogger(House.class); private final Map devices = new ConcurrentHashMap<>(); - public House(DTOMapper dtoMapper) { - this.dtoMapper = dtoMapper; + public House() { } /** * Puts new device to the house object. * - * @param deviceDto actual instance of device - * @throws IllegalArgumentException if device is null + * @param device actual instance of device + * @throws IllegalArgumentException if device is null * @throws KeyAlreadyExistsException if device with given label is already present in the house */ - public void addDevice(DeviceDTO deviceDto) throws IllegalArgumentException, KeyAlreadyExistsException { - if(deviceDto == null) { + public void addDevice(Device device) throws IllegalArgumentException, KeyAlreadyExistsException { + if (device == null) { throw new IllegalArgumentException("Device cannot be null"); } - Device device = dtoMapper.map(deviceDto); final Device origDevice = devices.putIfAbsent(device.getLabel(), device); if (origDevice != null) { throw new KeyAlreadyExistsException( @@ -53,51 +50,27 @@ public void addDevice(DeviceDTO deviceDto) throws IllegalArgumentException, KeyA * @return instance of device with given label, null if device is not present in the house * @throws IllegalArgumentException if label is null */ - public DeviceDTO getDevice(String label) throws IllegalArgumentException { - if(label == null) { + public Device getDevice(String label) throws IllegalArgumentException { + if (label == null) { throw new IllegalArgumentException("Label can't be null."); } - //return deviceMapper.deviceToDto(devices.get(label)); - return dtoMapper.map(devices.get(label)); + return devices.get(label); } - /** - * Updates device from the house. - * - * @param deviceDto device with updated values (device is specified by its label) - * @throws IllegalArgumentException if device is null - * @throws NoSuchElementException if no device with given label is not present in the house - */ - public void updateDevice(DeviceDTO deviceDto) throws IllegalArgumentException, NoSuchElementException { - if(deviceDto == null) { - throw new IllegalArgumentException("Device can't be null"); - } - Device device = dtoMapper.map(deviceDto); - final Device origDevice = devices.get(device.getLabel()); - if(origDevice== null) { - throw new NoSuchElementException( - String.format("Device with label: %s is not present in the house", device.getLabel())); - } - devices.put(device.getLabel(), device); - if(!LOGGER.isDebugEnabled()) { - LOGGER.info(String.format("Device with label:%s updated.", device.getLabel())); - } - LOGGER.debug(String.format("Device:%s updated to: %s", origDevice, device)); - } /** * Removes given device from the house. (Removes device with the same label.) * * @param label label of the device to be removed * @throws IllegalArgumentException if label is null - * @throws NoSuchElementException if house doesn't contain device with given label + * @throws NoSuchElementException if house doesn't contain device with given label */ - public void removeDevice(String label) throws IllegalArgumentException, NoSuchElementException{ - if(label == null) { + public void removeDevice(String label) throws IllegalArgumentException, NoSuchElementException { + if (label == null) { throw new IllegalArgumentException("label can't be null"); } final Device origDevice = devices.remove(label); - if(origDevice == null) { + if (origDevice == null) { throw new NoSuchElementException( String.format("Device with label: %s can't be removed from the house because it does not contain" + " such device", label)); @@ -107,18 +80,33 @@ public void removeDevice(String label) throws IllegalArgumentException, NoSuchEl } /** - * Provides devices of certain type which are stored in house. + * Provide device of certain type which is stored in house. * - * @param deviceDtoType type of requested devices - * @return map of labels and devices of requested type, Empty set if such device does not exist + * @param deviceType type of requested device + * @param label label of requested device + * @return device of requested type */ - public Map getDevicesOfType(Class deviceDtoType) { - Class deviceType = dtoMapper.mapDtoClassType(deviceDtoType); + public Device getDeviceOfType(Class deviceType, String label) throws IllegalArgumentException { + + final Device foundDevice = getDevice(label); + if (foundDevice != null) { + if (deviceType.isAssignableFrom(foundDevice.getClass())) { + return foundDevice; + } + return null; + } + return null; + } - Map res = devices.entrySet().stream() - .filter(x -> deviceType.isAssignableFrom(x.getValue().getClass())) - .collect(Collectors.toMap(Map.Entry::getKey, e -> dtoMapper.map(e.getValue()))); - System.out.println(res); - return res; + /** + * Provide devices of certain type which are stored in house. + * + * @param deviceClass type of requested devices + * @return devices of requested type + */ + public List getDevicesOfType(Class deviceClass) { + return devices.values().stream() + .filter(device -> deviceClass.isAssignableFrom(device.getClass())) + .collect(Collectors.toList()); } } diff --git a/src/main/java/io/patriotframework/virtualsmarthomeplus/house/devices/Actuator.java b/src/main/java/io/patriotframework/virtualsmarthomeplus/house/devices/Actuator.java new file mode 100644 index 0000000..6612f0a --- /dev/null +++ b/src/main/java/io/patriotframework/virtualsmarthomeplus/house/devices/Actuator.java @@ -0,0 +1,85 @@ +package io.patriotframework.virtualsmarthomeplus.house.devices; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.patriotframework.virtualsmarthomeplus.DTOs.ActuatorDTO; +import io.patriotframework.virtualsmarthomeplus.DTOs.DeviceDTO; +import io.patriotframework.virtualsmarthomeplus.house.House; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) +public abstract class Actuator extends Device { + private static final Logger LOGGER = LoggerFactory.getLogger(House.class); + private boolean switchedOn = false; + + /** + * Creates new Actuator. + * + * @param label of the new Actuator + * @throws IllegalArgumentException if given label is null or blank + */ + @JsonCreator + public Actuator(String label) { + super(label); + } + + /** + * Creates new Actuator with the same values of the attributes as given Actuator except label. + * Label of the new Actuator is given by parameter. + * + * @param newLabel label creates identity of the thermometer and is compared in the equals method + * @param origDevice template for the new Actuator + * @throws IllegalArgumentException if given label is null or blank + */ + public Actuator(Device origDevice, String newLabel) { + super(origDevice, newLabel); + } + + /** + * Switches actuator ON + */ + public void switchOn() { + if (!switchedOn) { + this.switchedOn = true; + LOGGER.debug(String.format("Actuator %s is switched on", getLabel())); + } + } + + /** + * Switches actuator OF + */ + public void switchOf() { + if (switchedOn) { + this.switchedOn = false; + LOGGER.debug(String.format("Actuator %s is switched on", getLabel())); + } + } + + /** + * Gets status of actuator + * + * @return intensity of blue color as int + */ + public boolean getSwitchedOn() { + return this.switchedOn; + } + + /** + * Updates the Actuator object with the values from provided DTO. + * + * @param deviceDTO actuator DTO containing the updated values or null if value was not updated + */ + @Override + public void update(DeviceDTO deviceDTO) { + final ActuatorDTO actuatorDTO = (ActuatorDTO) deviceDTO; + if (actuatorDTO.getSwitchedOn() != null) { + if (actuatorDTO.getSwitchedOn()) { + this.switchOn(); + } else { + this.switchOf(); + } + } + super.update(deviceDTO); + } +} diff --git a/src/main/java/io/patriotframework/virtualsmarthomeplus/house/devices/Device.java b/src/main/java/io/patriotframework/virtualsmarthomeplus/house/devices/Device.java index 67c3f57..97596d5 100644 --- a/src/main/java/io/patriotframework/virtualsmarthomeplus/house/devices/Device.java +++ b/src/main/java/io/patriotframework/virtualsmarthomeplus/house/devices/Device.java @@ -1,5 +1,8 @@ package io.patriotframework.virtualsmarthomeplus.house.devices; +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.patriotframework.virtualsmarthomeplus.DTOs.DeviceDTO; import io.patriotframework.virtualsmarthomeplus.house.House; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -9,10 +12,11 @@ /** * From this class will be derived Actuators and Sensors. From them will be then derived final devices. */ +@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) public abstract class Device implements Comparable { - private final String label; - private Boolean enabled = false; private static final Logger LOGGER = LoggerFactory.getLogger(House.class); + private String label; + private Boolean enabled = false; /** * Creates new device with given label. @@ -20,11 +24,12 @@ public abstract class Device implements Comparable { * @param label label creates identity of the device and is compared in the equals method * @throws IllegalArgumentException if given label is null or blank */ + @JsonCreator public Device(String label) { - if(label == null) { + if (label == null) { throw new IllegalArgumentException("Parameter 'label' for the new device can't be null"); } - if(label.isBlank()) { + if (label.isBlank()) { throw new IllegalArgumentException("Parameter 'label' for the new device can't blank"); } this.label = label; @@ -40,13 +45,13 @@ public Device(String label) { * @throws IllegalArgumentException if given label is null or blank */ public Device(Device origDevice, String newLabel) { - if(origDevice == null) { + if (origDevice == null) { throw new IllegalArgumentException("Parameter 'origDevice' can't be null"); } - if(newLabel == null) { + if (newLabel == null) { throw new IllegalArgumentException("Parameter 'label' can't be null"); } - if(newLabel.isBlank()) { + if (newLabel.isBlank()) { throw new IllegalArgumentException("Parameter 'label' can't blank"); } this.label = newLabel; @@ -78,18 +83,19 @@ public Boolean isEnabled() { * @param enabled if true, device will react to commands */ public void setEnabled(Boolean enabled) { - if(enabled != this.enabled) { + if (enabled == null) return; + if (enabled != this.enabled) { LOGGER.debug(String .format("Device %s changed it's property enabled from: %s to: %s", label, this.enabled, enabled)); } this.enabled = enabled; - } /** * Method responsible for creation new devices with the same values of attributes except the label * * @param newLabel label of the new device + * @return returns created device */ public abstract Device createWithSameAttributes(String newLabel); @@ -98,6 +104,7 @@ public void setEnabled(Boolean enabled) { * * @param device device to which this object will be compared * @throws IllegalArgumentException if parameter device is null + * @return return true if objects have same attributes and false otherwise */ public abstract boolean hasSameAttributes(Device device) throws IllegalArgumentException; @@ -105,14 +112,14 @@ public void setEnabled(Boolean enabled) { * Compares device with given device based on the lexicographic arrangement of their names * * @param compared the object to be compared with. - * @return 0 if the devices label is equal to the other compared devices label. - * < 0 if the label is lexicographically less than the other label - * > 0 if the label is lexicographically greater than the other string + * @return 0 if the devices label is equal to the other compared devices label. + * < 0 if the label is lexicographically less than the other label + * > 0 if the label is lexicographically greater than the other string * @throws IllegalArgumentException if the compared device is null */ @Override public int compareTo(Device compared) { - if(compared == null) { + if (compared == null) { throw new IllegalArgumentException("Compared device must not be null"); } return label.compareTo(compared.getLabel()); @@ -122,7 +129,7 @@ public int compareTo(Device compared) { public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - Device device = (Device) o; + final Device device = (Device) o; return getLabel().equals(device.getLabel()); } @@ -130,4 +137,18 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(getLabel()); } + + /** + * Updates the Device object with the values from provided DTO. + * + * @param deviceDTO device DTO containing the updated values or null if value was not updated + */ + public void update(DeviceDTO deviceDTO) { + if (deviceDTO.getEnabled() != null) { + this.setEnabled(deviceDTO.getEnabled()); + } + if (deviceDTO.getLabel() != null) { + this.label = deviceDTO.getLabel(); + } + } } diff --git a/src/main/java/io/patriotframework/virtualsmarthomeplus/house/devices/Sensor.java b/src/main/java/io/patriotframework/virtualsmarthomeplus/house/devices/Sensor.java new file mode 100644 index 0000000..2612cc7 --- /dev/null +++ b/src/main/java/io/patriotframework/virtualsmarthomeplus/house/devices/Sensor.java @@ -0,0 +1,12 @@ +package io.patriotframework.virtualsmarthomeplus.house.devices; + +public abstract class Sensor extends Device { + + public Sensor(String label) { + super(label); + } + + public Sensor(Device origDevice, String newLabel) { + super(origDevice, newLabel); + } +} diff --git a/src/main/java/io/patriotframework/virtualsmarthomeplus/house/devices/finalDevices/Door.java b/src/main/java/io/patriotframework/virtualsmarthomeplus/house/devices/finalDevices/Door.java index 31b419c..005e199 100644 --- a/src/main/java/io/patriotframework/virtualsmarthomeplus/house/devices/finalDevices/Door.java +++ b/src/main/java/io/patriotframework/virtualsmarthomeplus/house/devices/finalDevices/Door.java @@ -2,6 +2,8 @@ import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonCreator; +import io.patriotframework.virtualsmarthomeplus.DTOs.DeviceDTO; +import io.patriotframework.virtualsmarthomeplus.DTOs.DoorDTO; import io.patriotframework.virtualsmarthomeplus.house.House; import io.patriotframework.virtualsmarthomeplus.house.devices.Device; import org.slf4j.Logger; @@ -14,11 +16,10 @@ @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) public class Door extends Device { - private boolean opened = false; - private static final Logger LOGGER = LoggerFactory.getLogger(House.class); - public static final String OPENED = "opened"; public static final String CLOSED = "closed"; + private static final Logger LOGGER = LoggerFactory.getLogger(House.class); + private boolean opened = false; /** * Creates new door with given label. @@ -35,7 +36,7 @@ public Door(String label) { * Label of the new door is given by parameter. * * @param origDoor new door copies values of given device - * @param newLabel label creates identity of the door and is compared in the equals method + * @param newLabel label creates identity of the door and is compared in the equals method * @throws IllegalArgumentException if given label is null or blank */ public Door(Door origDoor, String newLabel) { @@ -85,18 +86,34 @@ public Door createWithSameAttributes(String newLabel) { */ @Override public boolean hasSameAttributes(Device door) throws IllegalArgumentException { - if(door == null) { + if (door == null) { throw new IllegalArgumentException("Door cannot be null"); } - if(getClass() != door.getClass()) { + if (getClass() != door.getClass()) { throw new IllegalArgumentException("device must be of class Door"); } - Door typedDoor = (Door)door; + final Door typedDoor = (Door) door; - if(isEnabled() != typedDoor.isEnabled()) { + if (isEnabled() != typedDoor.isEnabled()) { return false; } return typedDoor.opened == opened; } + /** + * Updates the door object with the values from provided DTO. + * + * @param deviceDTO door DTO containing the updated values or null if value was not updated + */ + public void update(DeviceDTO deviceDTO) { + final DoorDTO doorDTO = (DoorDTO) deviceDTO; + if (doorDTO.getStatus() != null) { + if (doorDTO.getStatus().equals(OPENED)) { + this.open(); + } else if (doorDTO.getStatus().equals(CLOSED)) { + this.close(); + } + } + super.update(doorDTO); + } } diff --git a/src/main/java/io/patriotframework/virtualsmarthomeplus/house/devices/finalDevices/Fireplace.java b/src/main/java/io/patriotframework/virtualsmarthomeplus/house/devices/finalDevices/Fireplace.java index 86a2b27..651f8bc 100644 --- a/src/main/java/io/patriotframework/virtualsmarthomeplus/house/devices/finalDevices/Fireplace.java +++ b/src/main/java/io/patriotframework/virtualsmarthomeplus/house/devices/finalDevices/Fireplace.java @@ -3,6 +3,8 @@ import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; +import io.patriotframework.virtualsmarthomeplus.DTOs.DeviceDTO; +import io.patriotframework.virtualsmarthomeplus.DTOs.FireplaceDTO; import io.patriotframework.virtualsmarthomeplus.house.House; import io.patriotframework.virtualsmarthomeplus.house.devices.Device; import org.slf4j.Logger; @@ -14,10 +16,10 @@ @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) public class Fireplace extends Device { - private Boolean onFire = false; - private static final Logger LOGGER = LoggerFactory.getLogger(House.class); public static final String ON_FIRE = "on_fire"; public static final String EXTINGUISHED = "extinguished"; + private static final Logger LOGGER = LoggerFactory.getLogger(House.class); + private Boolean onFire = false; /** * Creates new fireplace with given label. @@ -34,7 +36,7 @@ public Fireplace(String label) { * Label of the new fireplace is given by parameter. * * @param origFireplace new fireplace copies values of given fireplace - * @param newLabel label creates identity of the fireplace and is compared in the equals method + * @param newLabel label creates identity of the fireplace and is compared in the equals method * @throws IllegalArgumentException if given label is null or blank */ public Fireplace(Fireplace origFireplace, String newLabel) { @@ -46,7 +48,7 @@ public Fireplace(Fireplace origFireplace, String newLabel) { * Fires up the fireplace. */ public void fireUp() { - if(!onFire) { + if (!onFire) { onFire = true; LOGGER.debug(String.format("Fireplace %s fired up", getLabel())); } @@ -56,7 +58,7 @@ public void fireUp() { * Extinguishes the fireplace. */ public void extinguish() { - if(onFire) { + if (onFire) { onFire = false; LOGGER.debug(String.format("Fireplace %s extinguished", getLabel())); } @@ -85,18 +87,34 @@ public Fireplace createWithSameAttributes(String newLabel) { */ @Override public boolean hasSameAttributes(Device fireplace) throws IllegalArgumentException { - if(fireplace == null) { + if (fireplace == null) { throw new IllegalArgumentException("Fireplace cannot be null"); } - if(getClass() != fireplace.getClass()) { + if (getClass() != fireplace.getClass()) { throw new IllegalArgumentException("device must be of class Fireplace"); } - Fireplace typedFireplace = (Fireplace)fireplace; + final Fireplace typedFireplace = (Fireplace) fireplace; - if(isEnabled() != typedFireplace.isEnabled()) { + if (isEnabled() != typedFireplace.isEnabled()) { return false; } return typedFireplace.onFire == onFire; } + /** + * Updates the fireplace object with the values from provided DTO. + * + * @param deviceDTO fireplace DTO containing the updated values or null if value was not updated + */ + public void update(DeviceDTO deviceDTO) { + final FireplaceDTO fireplaceDTO = (FireplaceDTO) deviceDTO; + if (fireplaceDTO.getStatus() != null) { + if (fireplaceDTO.getStatus().equals(EXTINGUISHED)) { + this.extinguish(); + } else if (fireplaceDTO.getStatus().equals(ON_FIRE)) { + this.fireUp(); + } + } + super.update(fireplaceDTO); + } } diff --git a/src/main/java/io/patriotframework/virtualsmarthomeplus/house/devices/finalDevices/RGBLight.java b/src/main/java/io/patriotframework/virtualsmarthomeplus/house/devices/finalDevices/RGBLight.java new file mode 100644 index 0000000..6b8386f --- /dev/null +++ b/src/main/java/io/patriotframework/virtualsmarthomeplus/house/devices/finalDevices/RGBLight.java @@ -0,0 +1,243 @@ +package io.patriotframework.virtualsmarthomeplus.house.devices.finalDevices; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.patriotframework.virtualsmarthomeplus.DTOs.DeviceDTO; +import io.patriotframework.virtualsmarthomeplus.DTOs.RGBLightDTO; +import io.patriotframework.virtualsmarthomeplus.house.House; +import io.patriotframework.virtualsmarthomeplus.house.devices.Actuator; +import io.patriotframework.virtualsmarthomeplus.house.devices.Device; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.awt.Color; + + +@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) +public class RGBLight extends Actuator { + + private static final Logger LOGGER = LoggerFactory.getLogger(House.class); + private int red; + private int green; + private int blue; + + /** + * Creates new RGBLight with given label and sets intensity of RGB light to zero. + * + * @param label label creates identity of the RGBLight and is compared in the equals method + * @throws IllegalArgumentException if given label is null or blank + */ + @JsonCreator + public RGBLight(String label) { + super(label); + setRGB(0, 0, 0); + } + + /** + * Creates new RGBLight with given label. + * Color of the new RGBLight is given by parameters. + * + * @param label label of the new RGBLight + * @param red intensity of red in new RGB light + * @param green intensity of green in new RGB light + * @param blue intensity of blue in new RGB light + * @throws IllegalArgumentException if given label is null or blank + */ + public RGBLight(String label, int red, int green, int blue) { + super(label); + setRGB(red, green, blue); + } + + /** + * Creates new RGBLight with the same values of the attributes as given RGBLight except label. + * Label of the new RGBLight is given by parameter. + * + * @param origRGBLight new RGBlight copies values of given thermometer + * @param newLabel label creates identity of the thermometer and is compared in the equals method + * @throws IllegalArgumentException if given label is null or blank + */ + public RGBLight(RGBLight origRGBLight, String newLabel) { + super(origRGBLight, newLabel); + setRGB(0, 0, 0); + } + + /** + * Creates new RGBLight with the same values of the attributes as given RGBLight except label. + * Label and color of the new RGBLight is given by parameters. + * + * @param origRGBLight new RGBLight copies values of given RGBLight + * @param newLabel name of new RGB light + * @param red intensity of red in new RGB light + * @param green intensity of green in new RGB light + * @param blue intensity of blue in new RGB light + * @throws IllegalArgumentException if given label is null or blank + */ + public RGBLight(RGBLight origRGBLight, String newLabel, int red, int green, int blue) { + super(origRGBLight, newLabel); + setRGB(red, green, blue); + } + + /** + * Set new color of RGB light. + * + * @param red new intensity of red RGB light + * @param green new intensity of green RGB light + * @param blue new intensity of blue RGB light + */ + public void setRGB(int red, int green, int blue) { + setRed(red); + setGreen(green); + setBlue(blue); + } + + /** + * Gets color of RGB light + * + * @return color of RGB light as Color + */ + public Color getRGB() { + return new Color(this.red, this.green, this.blue); + } + + /** + * Gets intensity of red color + * + * @return intensity of red color as int + */ + public int getRed() { + return this.red; + } + + /** + * Sets intensity of red color + * + * @param red new value of red + */ + public void setRed(int red) { + if (red < 0) { + LOGGER.debug(String.format("Red value %d out of bound", red)); + this.red = 0; + LOGGER.debug(String.format("Red value changed to %d", this.red)); + return; + } + if (red > 100) { + LOGGER.debug(String.format("Red value %d out of bound", red)); + this.red = 100; + LOGGER.debug(String.format("Red value changed to %d", this.red)); + return; + } + this.red = red; + LOGGER.debug(String.format("Red value changed to %d", red)); + } + + /** + * Gets intensity of green color + * + * @return intensity of green color as int + */ + public int getGreen() { + return this.green; + } + + /** + * Sets intensity of green color + * + * @param green new value of green + */ + public void setGreen(int green) { + if (green < 0) { + LOGGER.debug(String.format("Green value %d out of bound", green)); + this.green = 0; + LOGGER.debug(String.format("Green value changed to %d", this.green)); + return; + } + if (green > 100) { + LOGGER.debug(String.format("Green value %d out of bound", green)); + this.green = 100; + LOGGER.debug(String.format("Green value changed to %d", this.green)); + return; + } + this.green = green; + LOGGER.debug(String.format("Green value changed to %d", green)); + } + + /** + * Gets intensity of blue color + * + * @return intensity of blue color as int + */ + public int getBlue() { + return this.blue; + } + + /** + * Sets intensity of blue color + * + * @param blue new value of blue + */ + public void setBlue(int blue) { + if (blue < 0) { + LOGGER.debug(String.format("Blue value %d out of bound", blue)); + this.blue = 0; + LOGGER.debug(String.format("Blue value changed to %d", this.blue)); + return; + } + if (blue > 100) { + LOGGER.debug(String.format("Blue value %d out of bound", blue)); + this.blue = 100; + LOGGER.debug(String.format("Blue value changed to %d", this.blue)); + return; + } + this.blue = blue; + LOGGER.debug(String.format("Blue value changed to %d", blue)); + } + + /** + * {@inheritDoc} + */ + @Override + public RGBLight createWithSameAttributes(String newLabel) { + return new RGBLight(this, newLabel); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean hasSameAttributes(Device rgbLight) throws IllegalArgumentException { + if (rgbLight == null) { + throw new IllegalArgumentException("RGBLight cannot be null"); + } + if (this.getClass() != rgbLight.getClass()) { + throw new IllegalArgumentException("device must be of class RGBLight"); + } + + final RGBLight typedRGB = (RGBLight) rgbLight; + + if (this.isEnabled() != typedRGB.isEnabled()) { + return false; + } + + return typedRGB.getRGB().equals(this.getRGB()); + } + + /** + * Updates the rgbLight object with the values from provided DTO. + * + * @param deviceDTO rgbLight DTO containing the updated values or null if value was not updated + */ + @Override + public void update(DeviceDTO deviceDTO) { + final RGBLightDTO rgbLightDTO = (RGBLightDTO) deviceDTO; + if (rgbLightDTO.getRed() != null) { + setRed(rgbLightDTO.getRed()); + } + if (rgbLightDTO.getGreen() != null) { + setGreen(rgbLightDTO.getGreen()); + } + if (rgbLightDTO.getBlue() != null) { + setBlue(rgbLightDTO.getBlue()); + } + super.update(rgbLightDTO); + } +} diff --git a/src/main/java/io/patriotframework/virtualsmarthomeplus/house/devices/finalDevices/Thermometer.java b/src/main/java/io/patriotframework/virtualsmarthomeplus/house/devices/finalDevices/Thermometer.java new file mode 100644 index 0000000..6e3c717 --- /dev/null +++ b/src/main/java/io/patriotframework/virtualsmarthomeplus/house/devices/finalDevices/Thermometer.java @@ -0,0 +1,145 @@ +package io.patriotframework.virtualsmarthomeplus.house.devices.finalDevices; + +import com.fasterxml.jackson.annotation.JsonCreator; +import io.patriot_framework.generator.dataFeed.NormalDistVariateDataFeed; +import io.patriotframework.virtualsmarthomeplus.DTOs.DeviceDTO; +import io.patriotframework.virtualsmarthomeplus.DTOs.ThermometerDTO; +import io.patriotframework.virtualsmarthomeplus.house.House; +import io.patriotframework.virtualsmarthomeplus.house.devices.Device; +import io.patriotframework.virtualsmarthomeplus.house.devices.Sensor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Thermometer extends Sensor { + + public static final String CELSIUS = "C"; + public static final String FAHRENHEIT = "F"; + //public static final String KELVIN = "K"; private Float temperature; + public static final String DEFAULT_UNIT = CELSIUS; + private static final Logger LOGGER = LoggerFactory.getLogger(House.class); + private final io.patriot_framework.generator.device.Device device; + private String unit; + + /** + * Creates new Thermometer with given label. + * + * @param label label creates identity of the Thermometer and is compared in the equals method + * @throws IllegalArgumentException if given label is null or blank + */ + public Thermometer(String label) { + this(label, DEFAULT_UNIT); + } + + /** + * Creates new thermometer with given label and given unit. + * + * @param unit measuring unit + * @param label label of the new thermometer + * @throws IllegalArgumentException if given label is null or blank + */ + @JsonCreator + public Thermometer(String label, String unit) { + super(label); + device = new io.patriot_framework.generator.device.impl.basicSensors.Thermometer( + getLabel(), + new NormalDistVariateDataFeed(25, 1) + ); + this.unit = unit; + } + + /** + * Creates new thermometer with the same values of the attributes as given thermometer except label. + * Label of the new thermometer is given by parameter. + * + * @param origThermometer new thermometer copies values of given thermometer + * @param newLabel label of new device + * @throws IllegalArgumentException if given label is null or blank + */ + + public Thermometer(Thermometer origThermometer, String newLabel) { + this(origThermometer, newLabel, DEFAULT_UNIT); + unit = origThermometer.unit; + } + + /** + * Creates new thermometer with the same values of the attributes as given thermometer except label. + * Label of the new thermometer is given by parameter. + * + * @param origThermometer new thermometer copies values of given thermometer + * @param newLabel label of new device + * @param unit measuring unit + * @throws IllegalArgumentException if given label is null or blank + */ + public Thermometer(Thermometer origThermometer, String newLabel, String unit) { + this(newLabel, unit); + Thermometer.this.unit = origThermometer.unit; + } + + /** + * Method to get temperature value + * + * @return temperature value + */ + public Float getTemperature() { + return device.requestData().get(0).get(Double.class).floatValue(); + } + + /** + * Method sets new measuring unit + * + * @param unit change measuring unit to unit + */ + public void setUnit(String unit) { + Thermometer.this.unit = unit; + LOGGER.debug(String.format("Measuring unit changed to %s", unit)); + } + + /** + * Method gets type of measuring unit + * + * @return measuring unit + */ + public String getUnit() { + return unit; + } + + /** + * {@inheritDoc} + */ + @Override + public Device createWithSameAttributes(String newLabel) { + return new Thermometer(this, newLabel); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean hasSameAttributes(Device thermometer) throws IllegalArgumentException { + if (thermometer == null) { + throw new IllegalArgumentException("Fireplace cannot be null"); + } + if (getClass() != thermometer.getClass()) { + throw new IllegalArgumentException("device must be of class Fireplace"); + } + + final Thermometer typedThermometer = (Thermometer) thermometer; + + if (isEnabled() != typedThermometer.isEnabled()) { + return false; + } + return typedThermometer.unit.equals(unit); + } + /** + * Updates the thermometer object with the values from provided DTO. + * + * @param deviceDTO thermometer DTO containing the updated values or null if value was not updated + */ + public void update(DeviceDTO deviceDTO) { + final ThermometerDTO thermometerDTO = (ThermometerDTO) deviceDTO; + if (thermometerDTO.getUnit() != null) { + this.setUnit(thermometerDTO.getUnit()); + } + super.update(thermometerDTO); + } +} diff --git a/src/test/java/io/patriotframework/virtualsmarthomeplus/VirtualSmartHomePlusApplicationTests.java b/src/test/java/io/patriotframework/virtualsmarthomeplus/VirtualSmartHomePlusApplicationTests.java index 45355b2..9a1164b 100644 --- a/src/test/java/io/patriotframework/virtualsmarthomeplus/VirtualSmartHomePlusApplicationTests.java +++ b/src/test/java/io/patriotframework/virtualsmarthomeplus/VirtualSmartHomePlusApplicationTests.java @@ -6,8 +6,8 @@ @SpringBootTest class VirtualSmartHomePlusApplicationTests { - @Test - void contextLoads() { - } + @Test + void contextLoads() { + } } diff --git a/src/test/java/io/patriotframework/virtualsmarthomeplus/controllers/DoorApiTest.java b/src/test/java/io/patriotframework/virtualsmarthomeplus/controllers/DoorApiTest.java new file mode 100644 index 0000000..194cddb --- /dev/null +++ b/src/test/java/io/patriotframework/virtualsmarthomeplus/controllers/DoorApiTest.java @@ -0,0 +1,200 @@ +package io.patriotframework.virtualsmarthomeplus.controllers; + +import com.fasterxml.jackson.databind.ObjectMapper; +import io.patriotframework.virtualsmarthomeplus.DTOs.DeviceDTO; +import io.patriotframework.virtualsmarthomeplus.DTOs.DoorDTO; +import io.patriotframework.virtualsmarthomeplus.Mapper.DTOMapper; +import io.patriotframework.virtualsmarthomeplus.VirtualSmartHomePlusApplication; +import io.patriotframework.virtualsmarthomeplus.house.House; +import io.patriotframework.virtualsmarthomeplus.house.devices.finalDevices.Door; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.modelmapper.ModelMapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import static io.patriotframework.virtualsmarthomeplus.house.devices.finalDevices.Door.CLOSED; +import static io.patriotframework.virtualsmarthomeplus.house.devices.finalDevices.Door.OPENED; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +@ContextConfiguration(classes = VirtualSmartHomePlusApplication.class) +@SpringBootTest +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +public class DoorApiTest { + private static final Logger LOGGER = LoggerFactory.getLogger(House.class); + + + private final DTOMapper dtoMapper = new DTOMapper(new ModelMapper()); + @Autowired + public House house = new House(); + private MockMvc mockMvc; + @Autowired + private WebApplicationContext wac; + + @BeforeAll + public void setUp() { + this.mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); + Door door = new Door("door1"); + door.setEnabled(true); + house.addDevice(door); + } + + @Test + public void shouldFetchDevice() throws Exception { + ObjectMapper objectMapper = new ObjectMapper(); + Door door = new Door("door1"); + house.addDevice(door); + DoorDTO DoorDTO = (DoorDTO) dtoMapper.map(house.getDevice("door1")); + MvcResult result = this.mockMvc.perform(MockMvcRequestBuilders.get("/api/v0.1/house/device/door/door1") + .accept(MediaType.APPLICATION_JSON)) + .andDo(print()) + .andExpect(status().is(200)) + .andReturn(); + + String responseBody = result.getResponse().getContentAsString(); + DoorDTO responseDTO = objectMapper.readValue(responseBody, DoorDTO.class); + + assertEquals(DoorDTO, responseDTO); + + + } + + @Test + public void shouldPostDoor() throws Exception { + DoorDTO door = new DoorDTO(); + door.setLabel("door2"); + + door.setEnabled(false); + door.setStatus(OPENED); + + ObjectMapper objectMapper = new ObjectMapper(); + this.mockMvc.perform(post("/api/v0.1/house/device/door/") + .contentType("application/json") + .content(objectMapper.writeValueAsString(door))) + .andExpect(status().isOk()); + DeviceDTO deviceDTO = dtoMapper.map(house.getDevice("door2")); + assertEquals(door, deviceDTO); + + DoorDTO door1 = new DoorDTO(); + door1.setLabel("door3"); + door1.setEnabled(false); + door1.setStatus(CLOSED); + + + this.mockMvc.perform(post("/api/v0.1/house/device/door/") + .contentType("application/json") + .content(objectMapper.writeValueAsString(door1))) + .andExpect(status().isOk()); + deviceDTO = dtoMapper.map(house.getDevice("door3")); + assertEquals(door1, deviceDTO); + } + + @Test + public void shouldUpdatedoor() throws Exception { + DoorDTO door = new DoorDTO(); + door.setLabel("door1"); + door.setStatus(OPENED); + + ObjectMapper objectMapper = new ObjectMapper(); + this.mockMvc.perform(MockMvcRequestBuilders.put("/api/v0.1/house/device/door/door1") + .contentType("application/json") + .content(objectMapper.writeValueAsString(door)) + ) + .andExpect(status().isOk()); + DoorDTO DoorDTO2 = (DoorDTO) dtoMapper.map(house.getDevice("door1")); + assertEquals(DoorDTO2.getStatus(), OPENED); + + + door = new DoorDTO(); + door.setLabel("d2"); + + this.mockMvc.perform(MockMvcRequestBuilders.put("/api/v0.1/house/device/door/door1") + .contentType("application/json") + .content(objectMapper.writeValueAsString(door)) + ) + .andExpect(status().isOk()); + DoorDTO2 = (DoorDTO) dtoMapper.map(house.getDevice("d2")); + assertEquals(DoorDTO2.getStatus(), OPENED); + + door = new DoorDTO(); + door.setLabel("d2"); + door.setStatus(CLOSED); + + this.mockMvc.perform(MockMvcRequestBuilders.put("/api/v0.1/house/device/door/d2") + .contentType("application/json") + .content(objectMapper.writeValueAsString(door)) + ) + .andExpect(status().isOk()); + DoorDTO2 = (DoorDTO) dtoMapper.map(house.getDevice("d2")); + assertEquals(DoorDTO2.getStatus(), CLOSED); + } + + @Test + public void shouldDeleteMapping() throws Exception { + Door door = new Door("1"); + house.addDevice(door); + this.mockMvc.perform(MockMvcRequestBuilders.delete("/api/v0.1/house/device/door/1") + .accept(MediaType.APPLICATION_JSON)) + .andDo(print()) + .andExpect(status().is(204)) + .andReturn(); + } + + @Test + public void deviceAlreadyExists() throws Exception { + DoorDTO door = new DoorDTO(); + door.setLabel("door1"); + door.setEnabled(false); + + ObjectMapper objectMapper = new ObjectMapper(); + this.mockMvc.perform(post("/api/v0.1/house/device/door/") + .contentType("application/json") + .content(objectMapper.writeValueAsString(door))) + .andExpect(status().is(409)); + } + + @Test + public void wrongApiVersion() throws Exception { + MvcResult result = this.mockMvc.perform(MockMvcRequestBuilders.get("/api/v0/house/device/door/thermometer1") + .accept(MediaType.APPLICATION_JSON)) + .andDo(print()) + .andExpect(status().is(404)) + .andReturn(); + } + + @Test + public void noSuchElementException() throws Exception { + MvcResult result = this.mockMvc.perform(MockMvcRequestBuilders.get("/api/v0.1/house/device/door/door8") + .accept(MediaType.APPLICATION_JSON)) + .andDo(print()) + .andExpect(status().is(404)) + .andReturn(); + } + + @Test + public void wrongLabel() throws Exception { + ObjectMapper objectMapper = new ObjectMapper(); + + DoorDTO door = new DoorDTO(); + door.setLabel(null); + door.setEnabled(false); + + this.mockMvc.perform(post("/api/v0.1/house/device/door/") + .contentType("application/json") + .content(objectMapper.writeValueAsString(door))) + .andExpect(status().is(400)); + } +} + diff --git a/src/test/java/io/patriotframework/virtualsmarthomeplus/controllers/FireplaceApiTest.java b/src/test/java/io/patriotframework/virtualsmarthomeplus/controllers/FireplaceApiTest.java new file mode 100644 index 0000000..88cbfff --- /dev/null +++ b/src/test/java/io/patriotframework/virtualsmarthomeplus/controllers/FireplaceApiTest.java @@ -0,0 +1,207 @@ +package io.patriotframework.virtualsmarthomeplus.controllers; + +import com.fasterxml.jackson.databind.ObjectMapper; +import io.patriotframework.virtualsmarthomeplus.DTOs.DeviceDTO; +import io.patriotframework.virtualsmarthomeplus.DTOs.FireplaceDTO; +import io.patriotframework.virtualsmarthomeplus.Mapper.DTOMapper; +import io.patriotframework.virtualsmarthomeplus.VirtualSmartHomePlusApplication; +import io.patriotframework.virtualsmarthomeplus.house.House; +import io.patriotframework.virtualsmarthomeplus.house.devices.finalDevices.Fireplace; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.modelmapper.ModelMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import static io.patriotframework.virtualsmarthomeplus.house.devices.finalDevices.Fireplace.EXTINGUISHED; +import static io.patriotframework.virtualsmarthomeplus.house.devices.finalDevices.Fireplace.ON_FIRE; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +@ContextConfiguration(classes = VirtualSmartHomePlusApplication.class) +@SpringBootTest +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +public class FireplaceApiTest { + + + private final DTOMapper dtoMapper = new DTOMapper(new ModelMapper()); + @Autowired + public House house = new House(); + private MockMvc mockMvc; + @Autowired + private WebApplicationContext wac; + + @BeforeAll + public void setUp() { + this.mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); + Fireplace fireplace = new Fireplace("fireplace1"); + fireplace.setEnabled(true); + house.addDevice(fireplace); + } + + @Test + public void shouldFetchDevice() throws Exception { + ObjectMapper objectMapper = new ObjectMapper(); + Fireplace fireplace = new Fireplace("fireplace1"); + house.addDevice(fireplace); + FireplaceDTO FireplaceDTO = (FireplaceDTO) dtoMapper.map(house.getDevice("fireplace1")); + MvcResult result = this.mockMvc.perform(MockMvcRequestBuilders.get("/api/v0.1/house/device/fireplace/fireplace1") + .accept(MediaType.APPLICATION_JSON)) + .andDo(print()) + .andExpect(status().is(200)) + .andReturn(); + + String responseBody = result.getResponse().getContentAsString(); + FireplaceDTO responseDTO = objectMapper.readValue(responseBody, FireplaceDTO.class); + + assertEquals(EXTINGUISHED, FireplaceDTO.getStatus()); + + assertEquals(FireplaceDTO, responseDTO); + } + + @Test + public void shouldPostFireplace() throws Exception { + FireplaceDTO fireplace = new FireplaceDTO(); + fireplace.setLabel("fireplace2"); + fireplace.setStatus(EXTINGUISHED); + fireplace.setEnabled(false); + + ObjectMapper objectMapper = new ObjectMapper(); + this.mockMvc.perform(post("/api/v0.1/house/device/fireplace/") + .contentType("application/json") + .content(objectMapper.writeValueAsString(fireplace))) + .andExpect(status().isOk()); + DeviceDTO deviceDTO = dtoMapper.map(house.getDevice("fireplace2")); + assertEquals(fireplace, deviceDTO); + + FireplaceDTO fireplace1 = new FireplaceDTO(); + fireplace1.setLabel("fireplace3"); + fireplace1.setStatus(EXTINGUISHED); + fireplace1.setEnabled(false); + + this.mockMvc.perform(post("/api/v0.1/house/device/fireplace/") + .contentType("application/json") + .content(objectMapper.writeValueAsString(fireplace1))) + .andExpect(status().isOk()); + deviceDTO = dtoMapper.map(house.getDevice("fireplace3")); + assertEquals(fireplace1, deviceDTO); + } + + @Test + public void shouldUpdateFireplace() throws Exception { + FireplaceDTO fireplace = new FireplaceDTO(); + fireplace.setLabel("fireplace1"); + fireplace.setStatus(ON_FIRE); + ObjectMapper objectMapper = new ObjectMapper(); + this.mockMvc.perform(MockMvcRequestBuilders.put("/api/v0.1/house/device/fireplace/fireplace1") + .contentType("application/json") + .content(objectMapper.writeValueAsString(fireplace)) + ) + .andExpect(status().isOk()); + FireplaceDTO fireplaceDTO2 = (FireplaceDTO) dtoMapper.map(house.getDevice("fireplace1")); + assertEquals(fireplaceDTO2.getStatus(),ON_FIRE); + + fireplace = new FireplaceDTO(); + fireplace.setLabel("fireplace1"); + fireplace.setStatus(EXTINGUISHED); + fireplace.setEnabled(true); + + this.mockMvc.perform(MockMvcRequestBuilders.put("/api/v0.1/house/device/fireplace/fireplace1") + .contentType("application/json") + .content(objectMapper.writeValueAsString(fireplace)) + ) + .andExpect(status().isOk()); + fireplaceDTO2 = (FireplaceDTO) dtoMapper.map(house.getDevice("fireplace1")); + assertEquals(fireplaceDTO2.getStatus(),EXTINGUISHED); + assertEquals(fireplaceDTO2.getEnabled(), true); + + fireplace = new FireplaceDTO(); + fireplace.setLabel("2"); + + this.mockMvc.perform(MockMvcRequestBuilders.put("/api/v0.1/house/device/fireplace/fireplace1") + .contentType("application/json") + .content(objectMapper.writeValueAsString(fireplace)) + ) + .andExpect(status().isOk()); + fireplaceDTO2 = (FireplaceDTO) dtoMapper.map(house.getDevice("2")); + assertEquals(fireplaceDTO2.getStatus(),EXTINGUISHED); + + fireplace = new FireplaceDTO(); + fireplace.setLabel("2"); + fireplace.setStatus(ON_FIRE); + + this.mockMvc.perform(MockMvcRequestBuilders.put("/api/v0.1/house/device/fireplace/2") + .contentType("application/json") + .content(objectMapper.writeValueAsString(fireplace)) + ) + .andExpect(status().isOk()); + fireplaceDTO2 = (FireplaceDTO) dtoMapper.map(house.getDevice("2")); + assertEquals(fireplaceDTO2.getStatus(),ON_FIRE); + assertEquals(fireplaceDTO2.getEnabled(), true); + } + + @Test + public void shouldDeleteMapping() throws Exception { + Fireplace fireplace = new Fireplace("1"); + house.addDevice(fireplace); + this.mockMvc.perform(MockMvcRequestBuilders.delete("/api/v0.1/house/device/fireplace/1") + .accept(MediaType.APPLICATION_JSON)) + .andDo(print()) + .andExpect(status().is2xxSuccessful()) + .andReturn(); + } + + @Test + public void deviceAlreadyExists() throws Exception { + FireplaceDTO fireplace = new FireplaceDTO(); + fireplace.setLabel("fireplace1"); + fireplace.setEnabled(false); + + ObjectMapper objectMapper = new ObjectMapper(); + this.mockMvc.perform(post("/api/v0.1/house/device/fireplace/") + .contentType("application/json") + .content(objectMapper.writeValueAsString(fireplace))) + .andExpect(status().is(409)); + } + + @Test + public void wrongApiVersion() throws Exception { + MvcResult result = this.mockMvc.perform(MockMvcRequestBuilders.get("/api/v0/house/device/fireplace/thermometer1") + .accept(MediaType.APPLICATION_JSON)) + .andDo(print()) + .andExpect(status().is(404)) + .andReturn(); + } + + @Test + public void noSuchElementException() throws Exception { + this.mockMvc.perform(MockMvcRequestBuilders.get("/api/v0.1/house/device/fireplace/fireplace8") + .accept(MediaType.APPLICATION_JSON)) + .andDo(print()) + .andExpect(status().is(404)) + .andReturn(); + } + + @Test + public void wrongLabel() throws Exception { + ObjectMapper objectMapper = new ObjectMapper(); + + FireplaceDTO fireplace = new FireplaceDTO(); + fireplace.setLabel(null); + fireplace.setEnabled(false); + + this.mockMvc.perform(post("/api/v0.1/house/device/fireplace/") + .contentType("application/json") + .content(objectMapper.writeValueAsString(fireplace))) + .andExpect(status().is(400)); + } +} diff --git a/src/test/java/io/patriotframework/virtualsmarthomeplus/controllers/HouseApiTest.java b/src/test/java/io/patriotframework/virtualsmarthomeplus/controllers/HouseApiTest.java new file mode 100644 index 0000000..bfde141 --- /dev/null +++ b/src/test/java/io/patriotframework/virtualsmarthomeplus/controllers/HouseApiTest.java @@ -0,0 +1,70 @@ +package io.patriotframework.virtualsmarthomeplus.controllers; + +import com.fasterxml.jackson.databind.ObjectMapper; +import io.patriotframework.virtualsmarthomeplus.DTOs.HouseDTO; +import io.patriotframework.virtualsmarthomeplus.Mapper.DTOMapper; +import io.patriotframework.virtualsmarthomeplus.VirtualSmartHomePlusApplication; +import io.patriotframework.virtualsmarthomeplus.house.House; +import io.patriotframework.virtualsmarthomeplus.house.devices.finalDevices.RGBLight; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.modelmapper.ModelMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@ContextConfiguration(classes = VirtualSmartHomePlusApplication.class) +@SpringBootTest +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +public class HouseApiTest { + private final DTOMapper dtoMapper = new DTOMapper(new ModelMapper()); + private MockMvc mockMvc; + @Autowired + public House house = new House(); + @Autowired + private WebApplicationContext wac; + @BeforeAll + public void setUp() { + this.mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); + } + @Test + @Order(1) + public void shouldFetchHouse() throws Exception { + ObjectMapper objectMapper = new ObjectMapper(); + this.house.addDevice(new RGBLight("rg1")); + HouseDTO houseDTO = dtoMapper.map(house); + MvcResult result = this.mockMvc.perform(MockMvcRequestBuilders.get("/api/v0.1/house/") + .accept(MediaType.APPLICATION_JSON)) + .andDo(print()) + .andExpect(status().is(200)) + .andReturn(); + + + String responseBody = result.getResponse().getContentAsString(); + HouseDTO responseDTO = objectMapper.readValue(responseBody,HouseDTO.class); + + for (int i=0;i house.addDevice(door1)); + } + + @Test + public void nullLabelInputParam() { + assertThrows(IllegalArgumentException.class, () -> house.removeDevice(null)); + assertThrows(IllegalArgumentException.class, () -> house.getDevice(null)); + assertThrows(IllegalArgumentException.class, () -> house.addDevice(null)); + assertThrows(IllegalArgumentException.class, () -> house.getDeviceOfType(Door.class,null)); + } + + @Test + public void noSuchElementRemove() { + assertThrows(NoSuchElementException.class, () -> house.removeDevice("HouseDoor4")); + } +} diff --git a/src/test/java/io/patriotframework/virtualsmarthomeplus/house/devices/DeviceMock.java b/src/test/java/io/patriotframework/virtualsmarthomeplus/house/devices/DeviceMock.java new file mode 100644 index 0000000..c1cf921 --- /dev/null +++ b/src/test/java/io/patriotframework/virtualsmarthomeplus/house/devices/DeviceMock.java @@ -0,0 +1,23 @@ +package io.patriotframework.virtualsmarthomeplus.house.devices; + + +public class DeviceMock extends Device { + + public DeviceMock(String label) { + super(label); + } + + public DeviceMock(Device origDevice, String newLabel) { + super(origDevice, newLabel); + } + + @Override + public Device createWithSameAttributes(String newLabel) { + return null; + } + + @Override + public boolean hasSameAttributes(Device device) throws IllegalArgumentException { + return false; + } +} diff --git a/src/test/java/io/patriotframework/virtualsmarthomeplus/house/devices/DoorTest.java b/src/test/java/io/patriotframework/virtualsmarthomeplus/house/devices/DoorTest.java new file mode 100644 index 0000000..cb38dbf --- /dev/null +++ b/src/test/java/io/patriotframework/virtualsmarthomeplus/house/devices/DoorTest.java @@ -0,0 +1,68 @@ +package io.patriotframework.virtualsmarthomeplus.house.devices; + +import io.patriotframework.virtualsmarthomeplus.DTOs.RGBLightDTO; +import io.patriotframework.virtualsmarthomeplus.Mapper.DTOMapper; +import io.patriotframework.virtualsmarthomeplus.house.devices.finalDevices.Door; +import io.patriotframework.virtualsmarthomeplus.house.devices.finalDevices.RGBLight; +import org.junit.jupiter.api.Test; + +import static io.patriotframework.virtualsmarthomeplus.house.devices.finalDevices.Door.CLOSED; +import static io.patriotframework.virtualsmarthomeplus.house.devices.finalDevices.Door.OPENED; +import static org.junit.jupiter.api.Assertions.*; + +public class DoorTest { + + Door door1 = new Door("door1"); + Door door2 = new Door("door2"); + + @Test + public void constructorTest() { + + Door device1 = new Door("door"); + assertDoesNotThrow(() -> { + Door device2 = new Door("door1"); + }); + assertThrows(IllegalArgumentException.class, () -> new Door("")); + assertThrows(IllegalArgumentException.class, () -> new Door(null)); + } + + @Test + public void OpenCloseTest() { + door1.setEnabled(true); + assertEquals(door1.getStatus(),CLOSED); + door1.open(); + assertEquals(door1.getStatus(),OPENED); + door1.close(); + assertEquals(door1.getStatus(),CLOSED); + door1.open(); + door1.open(); + assertEquals(door1.getStatus(),OPENED); + + door1.close(); + door1.close(); + assertEquals(door1.getStatus(),CLOSED); + } + + @Test + public void createWithSameAttributes() { + door1.setEnabled(true); + Door door3 = door1.createWithSameAttributes("rgb3"); + assertEquals(door3.isEnabled(), door1.isEnabled()); + assertTrue(door3.hasSameAttributes(door1)); + } + + @Test + public void testHasSameAttributes() { + DeviceMock device1 = new DeviceMock("door1"); + assertThrows(IllegalArgumentException.class, () -> door1.hasSameAttributes(device1)); + + assertThrows(IllegalArgumentException.class, () -> door1.hasSameAttributes(null)); + + assertTrue(door1.hasSameAttributes(door2)); + door1.open(); + assertFalse(door1.hasSameAttributes(door2)); + door1.close(); + assertTrue(door1.hasSameAttributes(door2)); + } + +} diff --git a/src/test/java/io/patriotframework/virtualsmarthomeplus/house/devices/FireplaceTest.java b/src/test/java/io/patriotframework/virtualsmarthomeplus/house/devices/FireplaceTest.java new file mode 100644 index 0000000..feffc20 --- /dev/null +++ b/src/test/java/io/patriotframework/virtualsmarthomeplus/house/devices/FireplaceTest.java @@ -0,0 +1,67 @@ +package io.patriotframework.virtualsmarthomeplus.house.devices; + +import io.patriotframework.virtualsmarthomeplus.house.devices.finalDevices.Door; +import io.patriotframework.virtualsmarthomeplus.house.devices.finalDevices.Fireplace; +import io.patriotframework.virtualsmarthomeplus.house.devices.finalDevices.Fireplace; +import org.junit.jupiter.api.Test; + +import static io.patriotframework.virtualsmarthomeplus.house.devices.finalDevices.Door.CLOSED; +import static io.patriotframework.virtualsmarthomeplus.house.devices.finalDevices.Door.OPENED; +import static io.patriotframework.virtualsmarthomeplus.house.devices.finalDevices.Fireplace.EXTINGUISHED; +import static io.patriotframework.virtualsmarthomeplus.house.devices.finalDevices.Fireplace.ON_FIRE; +import static org.junit.jupiter.api.Assertions.*; + +public class FireplaceTest { + Fireplace fireplace1 = new Fireplace("fireplace1"); + Fireplace fireplace2 = new Fireplace("fireplace2"); + + @Test + public void constructorTest() { + + Fireplace device1 = new Fireplace("fireplacex"); + assertDoesNotThrow(() -> { + Fireplace device2 = new Fireplace("fireplacexy"); + }); + assertThrows(IllegalArgumentException.class, () -> new Fireplace("")); + assertThrows(IllegalArgumentException.class, () -> new Fireplace(null)); + } + + @Test + public void fireUpExtinguishTest() { + fireplace1.setEnabled(true); + assertEquals(fireplace1.getStatus(),EXTINGUISHED); + fireplace1.fireUp(); + assertEquals(fireplace1.getStatus(),ON_FIRE); + fireplace1.extinguish(); + assertEquals(fireplace1.getStatus(),EXTINGUISHED); + fireplace1.fireUp(); + fireplace1.fireUp(); + assertEquals(fireplace1.getStatus(),ON_FIRE); + + fireplace1.extinguish(); + fireplace1.extinguish(); + assertEquals(fireplace1.getStatus(),EXTINGUISHED); + } + + @Test + public void createWithSameAttributes() { + fireplace1.setEnabled(true); + Fireplace fireplace3 = fireplace1.createWithSameAttributes("rgb3"); + assertEquals(fireplace3.isEnabled(), fireplace1.isEnabled()); + assertTrue(fireplace3.hasSameAttributes(fireplace1)); + } + + @Test + public void testHasSameAttributes() { + DeviceMock device1 = new DeviceMock("fireplace1"); + assertThrows(IllegalArgumentException.class, () -> fireplace1.hasSameAttributes(device1)); + + assertThrows(IllegalArgumentException.class, () -> fireplace1.hasSameAttributes(null)); + + assertTrue(fireplace1.hasSameAttributes(fireplace2)); + fireplace1.fireUp(); + assertFalse(fireplace1.hasSameAttributes(fireplace2)); + fireplace1.extinguish(); + assertTrue(fireplace1.hasSameAttributes(fireplace2)); + } +} diff --git a/src/test/java/io/patriotframework/virtualsmarthomeplus/house/devices/RGBLightTest.java b/src/test/java/io/patriotframework/virtualsmarthomeplus/house/devices/RGBLightTest.java new file mode 100644 index 0000000..d416760 --- /dev/null +++ b/src/test/java/io/patriotframework/virtualsmarthomeplus/house/devices/RGBLightTest.java @@ -0,0 +1,149 @@ +package io.patriotframework.virtualsmarthomeplus.house.devices; + +import io.patriotframework.virtualsmarthomeplus.DTOs.RGBLightDTO; +import io.patriotframework.virtualsmarthomeplus.Mapper.DTOMapper; +import io.patriotframework.virtualsmarthomeplus.house.devices.finalDevices.RGBLight; +import org.junit.jupiter.api.Test; +import org.modelmapper.ModelMapper; + +import java.awt.*; + +import static org.junit.jupiter.api.Assertions.*; + +public class RGBLightTest { + + ModelMapper modelMapper = new ModelMapper(); + DTOMapper dtoMapper; + RGBLight rgb1 = new RGBLight("rgb1"); + RGBLight rgb2 = new RGBLight("rgb2"); + + @Test + public void constructorTest() { + dtoMapper = new DTOMapper(modelMapper); + RGBLightDTO rgbLightDTO = new RGBLightDTO(); + rgbLightDTO.setLabel("rgb"); + Device device = dtoMapper.map(rgbLightDTO); + RGBLight rgb1 = new RGBLight("rgb4"); + assertDoesNotThrow(() -> { + RGBLight rgb = new RGBLight("rgb3"); + rgb.switchOf(); + }); + assertThrows(IllegalArgumentException.class, () -> new RGBLight("")); + assertThrows(IllegalArgumentException.class, () -> new RGBLight(null)); + } + + @Test + public void switchOn() { + rgb1.setEnabled(true); + assertFalse(rgb1.getSwitchedOn()); + rgb1.switchOn(); + assertTrue(rgb1.getSwitchedOn()); + rgb1.switchOn(); + rgb1.switchOf(); + rgb1.switchOn(); + assertTrue(rgb1.getSwitchedOn()); + + rgb2.setEnabled(true); + assertFalse(rgb2.getSwitchedOn()); + rgb2.switchOn(); + assertTrue(rgb2.getSwitchedOn()); + rgb2.switchOn(); + rgb2.switchOf(); + rgb2.switchOn(); + assertTrue(rgb2.getSwitchedOn()); + } + + @Test + public void switchOf() { + rgb1.setEnabled(true); + assertFalse(rgb1.getSwitchedOn()); + rgb1.switchOf(); + assertFalse(rgb1.getSwitchedOn()); + rgb1.switchOf(); + rgb1.switchOn(); + rgb1.switchOf(); + assertFalse(rgb1.getSwitchedOn()); + + rgb2.setEnabled(true); + assertFalse(rgb2.getSwitchedOn()); + rgb2.switchOf(); + assertFalse(rgb2.getSwitchedOn()); + rgb2.switchOf(); + rgb2.switchOn(); + rgb2.switchOf(); + assertFalse(rgb2.getSwitchedOn()); + } + + @Test + public void getRGB() { + Color color = new Color(0, 0, 0); + assertEquals(rgb1.getRGB(), color); + } + + @Test + public void getRed() { + assertEquals(rgb1.getRed(), 0); + } + + @Test + public void getGreen() { + assertEquals(rgb1.getGreen(), 0); + } + + @Test + public void getBlue() { + assertEquals(rgb1.getBlue(), 0); + } + + @Test + public void setRGB() { + rgb1.setRGB(5, 4, 3); + Color color = new Color(5, 4, 3); + assertEquals(rgb1.getRGB(), color); + } + + @Test + public void setRed() { + rgb1.setRed(4); + Color color = new Color(4, 0, 0); + assertEquals(rgb1.getRGB(), color); + } + + @Test + public void setGreen() { + rgb1.setGreen(4); + Color color = new Color(0, 4, 0); + assertEquals(rgb1.getRGB(), color); + } + + @Test + public void setBlue() { + rgb1.setBlue(4); + Color color = new Color(0, 0, 4); + assertEquals(rgb1.getRGB(), color); + } + + @Test + public void createWithSameAttributes() { + rgb1.setEnabled(true); + RGBLight rgbLight3 = rgb1.createWithSameAttributes("rgb3"); + assertEquals(rgbLight3.isEnabled(), rgb1.isEnabled()); + assertTrue(rgbLight3.hasSameAttributes(rgb1)); + } + + @Test + + public void testHasSameAttributes() { + DeviceMock device1 = new DeviceMock("door1"); + assertThrows(IllegalArgumentException.class, () -> rgb1.hasSameAttributes(device1)); + + assertThrows(IllegalArgumentException.class, () -> rgb1.hasSameAttributes(null)); + + assertTrue(rgb1.hasSameAttributes(rgb2)); + rgb1.setRed(36); + assertFalse(rgb1.hasSameAttributes(rgb2)); + rgb1.setRed(rgb2.getRed()); + assertTrue(rgb1.hasSameAttributes(rgb2)); + } + +} diff --git a/src/test/java/io/patriotframework/virtualsmarthomeplus/house/devices/ThermometerTest.java b/src/test/java/io/patriotframework/virtualsmarthomeplus/house/devices/ThermometerTest.java new file mode 100644 index 0000000..2749023 --- /dev/null +++ b/src/test/java/io/patriotframework/virtualsmarthomeplus/house/devices/ThermometerTest.java @@ -0,0 +1,67 @@ +package io.patriotframework.virtualsmarthomeplus.house.devices; + +import io.patriotframework.virtualsmarthomeplus.house.devices.finalDevices.Thermometer; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + + +public class ThermometerTest { + Thermometer thermometer1 = new Thermometer("thermometer1", Thermometer.CELSIUS); + Thermometer thermometer2 = new Thermometer("thermometer2", Thermometer.FAHRENHEIT); + + @Test + public void constructorTest() { + assertDoesNotThrow(() -> { + new Thermometer("thermometer3"); + }); + assertDoesNotThrow(() -> { + new Thermometer("thermometer4", Thermometer.FAHRENHEIT); + }); + assertThrows(IllegalArgumentException.class, () -> new Thermometer("")); + assertThrows(IllegalArgumentException.class, () -> new Thermometer(null)); + } + + @Test + public void getUnit() { + assertEquals(thermometer1.getUnit(), Thermometer.CELSIUS); + assertEquals(thermometer2.getUnit(), Thermometer.FAHRENHEIT); + } + + @Test + public void getTemperature() { + float temperature = thermometer1.getTemperature(); + assertTrue(temperature < 40 && temperature > 0); + } + + @Test + public void setUnit() { + thermometer1.setUnit(Thermometer.FAHRENHEIT); + assertEquals(thermometer1.getUnit(), Thermometer.FAHRENHEIT); + thermometer2.setUnit(Thermometer.CELSIUS); + assertEquals(thermometer2.getUnit(), Thermometer.CELSIUS); + } + + @Test + public void createWithSameAttributes() { + Thermometer thermometer3 = (Thermometer) thermometer1.createWithSameAttributes("thermometer3"); + assertEquals(thermometer1.getUnit(), thermometer3.getUnit()); + assertNotEquals(thermometer3.getUnit(), thermometer2.getUnit()); + + Thermometer thermometer4 = (Thermometer) thermometer2.createWithSameAttributes("thermometer4"); + assertNotEquals(thermometer1.getUnit(), thermometer4.getUnit()); + assertEquals(thermometer4.getUnit(), thermometer2.getUnit()); + } + + @Test + public void hasSameAttributes() { + DeviceMock device1 = new DeviceMock("door1"); + assertThrows(IllegalArgumentException.class, () -> thermometer1.hasSameAttributes(device1)); + + assertThrows(IllegalArgumentException.class, () -> thermometer1.hasSameAttributes(null)); + + assertFalse(thermometer1.hasSameAttributes(thermometer2)); + thermometer1.setUnit(Thermometer.FAHRENHEIT); + assertTrue(thermometer1.hasSameAttributes(thermometer2)); + } +}