refactor: rename layers

This commit is contained in:
Ilkka Seppälä
2024-05-26 11:13:13 +03:00
parent 88101fc4eb
commit e12085f158
29 changed files with 2 additions and 2 deletions
@@ -0,0 +1,98 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.layers;
import dto.CakeInfo;
import dto.CakeLayerInfo;
import dto.CakeToppingInfo;
import exception.CakeBakingException;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import service.CakeBakingService;
import view.CakeViewImpl;
/**
* The Runner class is the entry point of the application.
* It implements CommandLineRunner, which means it will execute the run method after the application context is loaded.
*
* <p>The Runner class is responsible for initializing the cake baking service with sample data and creating a view to render the cakes.
* It uses the CakeBakingService to save new layers and toppings and to bake new cakes.
* It also handles exceptions that might occur during the cake baking process.</p>
*/
@Component
@Slf4j
public class Runner implements CommandLineRunner {
private final CakeBakingService cakeBakingService;
public static final String STRAWBERRY = "strawberry";
@Autowired
public Runner(CakeBakingService cakeBakingService) {
this.cakeBakingService = cakeBakingService;
}
@Override
public void run(String... args) {
//initialize sample data
initializeData();
// create view and render it
var cakeView = new CakeViewImpl(cakeBakingService);
cakeView.render();
}
/**
* Initializes the example data.
*/
private void initializeData() {
cakeBakingService.saveNewLayer(new CakeLayerInfo("chocolate", 1200));
cakeBakingService.saveNewLayer(new CakeLayerInfo("banana", 900));
cakeBakingService.saveNewLayer(new CakeLayerInfo(STRAWBERRY, 950));
cakeBakingService.saveNewLayer(new CakeLayerInfo("lemon", 950));
cakeBakingService.saveNewLayer(new CakeLayerInfo("vanilla", 950));
cakeBakingService.saveNewLayer(new CakeLayerInfo(STRAWBERRY, 950));
cakeBakingService.saveNewTopping(new CakeToppingInfo("candies", 350));
cakeBakingService.saveNewTopping(new CakeToppingInfo("cherry", 350));
var cake1 = new CakeInfo(new CakeToppingInfo("candies", 0),
List.of(new CakeLayerInfo("chocolate", 0), new CakeLayerInfo("banana", 0),
new CakeLayerInfo(STRAWBERRY, 0)));
try {
cakeBakingService.bakeNewCake(cake1);
} catch (CakeBakingException e) {
LOGGER.error("Cake baking exception", e);
}
var cake2 = new CakeInfo(new CakeToppingInfo("cherry", 0),
List.of(new CakeLayerInfo("vanilla", 0), new CakeLayerInfo("lemon", 0),
new CakeLayerInfo(STRAWBERRY, 0)));
try {
cakeBakingService.bakeNewCake(cake2);
} catch (CakeBakingException e) {
LOGGER.error("Cake baking exception", e);
}
}
}
@@ -0,0 +1,52 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.layers.app;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
/**
* The Layers pattern is a structural design pattern that organizes system architecture into
* distinct layers, each with a specific responsibility and abstraction level. This separation
* allows for increased modularity, facilitating independent development, maintenance, and reuse
* of each layer. Commonly, layers interact with each other through well-defined interfaces, with
* higher layers (more abstract) depending on lower layers (more concrete), but not vice versa,
* promoting a clear hierarchy and separation of concerns.
*/
@SpringBootApplication
@EnableJpaRepositories(basePackages = "dao")
@EntityScan(basePackages = "entity")
@ComponentScan(basePackages = {"com.iluwatar.layers", "service", "dto", "exception", "view", "dao"})
public class LayersApp {
public static void main(String[] args) {
SpringApplication.run(LayersApp.class, args);
}
}
@@ -0,0 +1,35 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package dao;
import entity.Cake;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
/**
* CRUD repository for cakes.
*/
@Repository
public interface CakeDao extends JpaRepository<Cake, Long> {}
@@ -0,0 +1,37 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package dao;
import entity.CakeLayer;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
/**
* CRUD repository for cake layers.
*/
@Repository
public interface CakeLayerDao extends JpaRepository<CakeLayer, Long> {
}
@@ -0,0 +1,39 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package dao;
import entity.CakeTopping;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
/**
* CRUD repository cake toppings.
*/
@Repository
public interface CakeToppingDao extends JpaRepository<CakeTopping, Long> {
}
@@ -0,0 +1,72 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package dto;
import java.util.List;
import java.util.Optional;
/**
* DTO for cakes.
*/
public class CakeInfo {
public final Optional<Long> id;
public final CakeToppingInfo cakeToppingInfo;
public final List<CakeLayerInfo> cakeLayerInfos;
/**
* Constructor.
*/
public CakeInfo(Long id, CakeToppingInfo cakeToppingInfo, List<CakeLayerInfo> cakeLayerInfos) {
this.id = Optional.of(id);
this.cakeToppingInfo = cakeToppingInfo;
this.cakeLayerInfos = cakeLayerInfos;
}
/**
* Constructor.
*/
public CakeInfo(CakeToppingInfo cakeToppingInfo, List<CakeLayerInfo> cakeLayerInfos) {
this.id = Optional.empty();
this.cakeToppingInfo = cakeToppingInfo;
this.cakeLayerInfos = cakeLayerInfos;
}
/**
* Calculate calories.
*/
public int calculateTotalCalories() {
var total = cakeToppingInfo != null ? cakeToppingInfo.calories : 0;
total += cakeLayerInfos.stream().mapToInt(c -> c.calories).sum();
return total;
}
@Override
public String toString() {
return String.format("CakeInfo id=%d topping=%s layers=%s totalCalories=%d", id.orElse(-1L),
cakeToppingInfo, cakeLayerInfos, calculateTotalCalories());
}
}
@@ -0,0 +1,61 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package dto;
import java.util.Optional;
/**
* DTO for cake layers.
*/
public class CakeLayerInfo {
public final Optional<Long> id;
public final String name;
public final int calories;
/**
* Constructor.
*/
public CakeLayerInfo(Long id, String name, int calories) {
this.id = Optional.of(id);
this.name = name;
this.calories = calories;
}
/**
* Constructor.
*/
public CakeLayerInfo(String name, int calories) {
this.id = Optional.empty();
this.name = name;
this.calories = calories;
}
@Override
public String toString() {
return String.format("CakeLayerInfo id=%d name=%s calories=%d", id.orElse(-1L), name, calories);
}
}
@@ -0,0 +1,63 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package dto;
import java.util.Optional;
/**
* DTO for cake toppings.
*/
public class CakeToppingInfo {
public final Optional<Long> id;
public final String name;
public final int calories;
/**
* Constructor.
*/
public CakeToppingInfo(Long id, String name, int calories) {
this.id = Optional.of(id);
this.name = name;
this.calories = calories;
}
/**
* Constructor.
*/
public CakeToppingInfo(String name, int calories) {
this.id = Optional.empty();
this.name = name;
this.calories = calories;
}
@Override
public String toString() {
return String.format("CakeToppingInfo id=%d name=%s calories=%d", id.orElse(-1L), name,
calories);
}
}
@@ -0,0 +1,70 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package entity;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.OneToMany;
import jakarta.persistence.OneToOne;
import java.util.HashSet;
import java.util.Set;
import lombok.Getter;
import lombok.Setter;
/**
* Cake entity.
*/
@Entity
@Getter
@Setter
public class Cake {
@Id
@GeneratedValue
private Long id;
@OneToOne(cascade = CascadeType.REMOVE)
private CakeTopping topping;
@OneToMany(cascade = CascadeType.REMOVE, fetch = FetchType.EAGER)
private Set<CakeLayer> layers;
public Cake() {
setLayers(new HashSet<>());
}
public void addLayer(CakeLayer layer) {
this.layers.add(layer);
}
@Override
public String toString() {
return String.format("id=%s topping=%s layers=%s", id, topping, layers.toString());
}
}
@@ -0,0 +1,73 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package entity;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToOne;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
/**
* CakeLayer entity.
*/
@Entity
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@EqualsAndHashCode
public class CakeLayer {
@Id
@GeneratedValue
private Long id;
private String name;
private int calories;
@ManyToOne(cascade = CascadeType.ALL)
private Cake cake;
public CakeLayer(String name, int calories) {
this.setName(name);
this.setCalories(calories);
}
@Override
public String toString() {
return String.format("id=%s name=%s calories=%d", id, name, calories);
}
}
@@ -0,0 +1,74 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package entity;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.OneToOne;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
/**
* CakeTopping entity.
*/
@Entity
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@EqualsAndHashCode
public class CakeTopping {
@Id
@GeneratedValue
private Long id;
private String name;
private int calories;
@OneToOne(cascade = CascadeType.ALL)
private Cake cake;
public CakeTopping(String name, int calories) {
this.setName(name);
this.setCalories(calories);
}
@Override
public String toString() {
return String.format("id=%s name=%s calories=%d", id, name, calories);
}
}
@@ -0,0 +1,46 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package exception;
import java.io.Serial;
import org.springframework.stereotype.Component;
/**
* Custom exception used in cake baking.
*/
@Component
public class CakeBakingException extends Exception {
@Serial
private static final long serialVersionUID = 1L;
public CakeBakingException() {
}
public CakeBakingException(String message) {
super(message);
}
}
@@ -0,0 +1,77 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package service;
import dto.CakeInfo;
import dto.CakeLayerInfo;
import dto.CakeToppingInfo;
import exception.CakeBakingException;
import java.util.List;
import org.springframework.stereotype.Service;
/**
* Service for cake baking operations.
*/
@Service
public interface CakeBakingService {
/**
* Bakes new cake according to parameters.
*/
void bakeNewCake(CakeInfo cakeInfo) throws CakeBakingException;
/**
* Get all cakes.
*/
List<CakeInfo> getAllCakes();
/**
* Store new cake topping.
*/
void saveNewTopping(CakeToppingInfo toppingInfo);
/**
* Get available cake toppings.
*/
List<CakeToppingInfo> getAvailableToppings();
/**
* Add new cake layer.
*/
void saveNewLayer(CakeLayerInfo layerInfo);
/**
* Get available cake layers.
*/
List<CakeLayerInfo> getAvailableLayers();
void deleteAllCakes();
void deleteAllLayers();
void deleteAllToppings();
}
@@ -0,0 +1,198 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package service;
import dao.CakeDao;
import dao.CakeLayerDao;
import dao.CakeToppingDao;
import dto.CakeInfo;
import dto.CakeLayerInfo;
import dto.CakeToppingInfo;
import entity.Cake;
import entity.CakeLayer;
import entity.CakeTopping;
import exception.CakeBakingException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* Implementation of CakeBakingService.
*/
@Service
@Transactional
public class CakeBakingServiceImpl implements CakeBakingService {
private final CakeDao cakeDao;
private final CakeLayerDao cakeLayerDao;
private final CakeToppingDao cakeToppingDao;
/**
* Constructs a new instance of CakeBakingServiceImpl.
*
* @param cakeDao the DAO for cake-related operations
* @param cakeLayerDao the DAO for cake layer-related operations
* @param cakeToppingDao the DAO for cake topping-related operations
*/
@Autowired
public CakeBakingServiceImpl(CakeDao cakeDao, CakeLayerDao cakeLayerDao,
CakeToppingDao cakeToppingDao) {
this.cakeDao = cakeDao;
this.cakeLayerDao = cakeLayerDao;
this.cakeToppingDao = cakeToppingDao;
}
@Override
public void bakeNewCake(CakeInfo cakeInfo) throws CakeBakingException {
var allToppings = getAvailableToppingEntities();
var matchingToppings =
allToppings.stream().filter(t -> t.getName().equals(cakeInfo.cakeToppingInfo.name))
.toList();
if (matchingToppings.isEmpty()) {
throw new CakeBakingException(
String.format("Topping %s is not available", cakeInfo.cakeToppingInfo.name));
}
var allLayers = getAvailableLayerEntities();
Set<CakeLayer> foundLayers = new HashSet<>();
for (var info : cakeInfo.cakeLayerInfos) {
var found = allLayers.stream().filter(layer -> layer.getName().equals(info.name)).findFirst();
if (found.isEmpty()) {
throw new CakeBakingException(String.format("Layer %s is not available", info.name));
} else {
foundLayers.add(found.get());
}
}
var topping = cakeToppingDao.findById(matchingToppings.iterator().next().getId());
if (topping.isPresent()) {
var cake = new Cake();
cake.setTopping(topping.get());
cake.setLayers(foundLayers);
cakeDao.save(cake);
topping.get().setCake(cake);
cakeToppingDao.save(topping.get());
Set<CakeLayer> foundLayersToUpdate =
new HashSet<>(foundLayers); // copy set to avoid a ConcurrentModificationException
for (var layer : foundLayersToUpdate) {
layer.setCake(cake);
cakeLayerDao.save(layer);
}
} else {
throw new CakeBakingException(
String.format("Topping %s is not available", cakeInfo.cakeToppingInfo.name));
}
}
@Override
public void saveNewTopping(CakeToppingInfo toppingInfo) {
cakeToppingDao.save(new CakeTopping(toppingInfo.name, toppingInfo.calories));
}
@Override
public void saveNewLayer(CakeLayerInfo layerInfo) {
cakeLayerDao.save(new CakeLayer(layerInfo.name, layerInfo.calories));
}
private List<CakeTopping> getAvailableToppingEntities() {
List<CakeTopping> result = new ArrayList<>();
for (CakeTopping topping : cakeToppingDao.findAll()) {
if (topping.getCake() == null) {
result.add(topping);
}
}
return result;
}
@Override
public List<CakeToppingInfo> getAvailableToppings() {
List<CakeToppingInfo> result = new ArrayList<>();
for (CakeTopping next : cakeToppingDao.findAll()) {
if (next.getCake() == null) {
result.add(new CakeToppingInfo(next.getId(), next.getName(), next.getCalories()));
}
}
return result;
}
private List<CakeLayer> getAvailableLayerEntities() {
List<CakeLayer> result = new ArrayList<>();
for (CakeLayer next : cakeLayerDao.findAll()) {
if (next.getCake() == null) {
result.add(next);
}
}
return result;
}
@Override
public List<CakeLayerInfo> getAvailableLayers() {
List<CakeLayerInfo> result = new ArrayList<>();
for (CakeLayer next : cakeLayerDao.findAll()) {
if (next.getCake() == null) {
result.add(new CakeLayerInfo(next.getId(), next.getName(), next.getCalories()));
}
}
return result;
}
@Override
public void deleteAllCakes() {
cakeDao.deleteAll();
}
@Override
public void deleteAllLayers() {
cakeLayerDao.deleteAll();
}
@Override
public void deleteAllToppings() {
cakeToppingDao.deleteAll();
}
@Override
public List<CakeInfo> getAllCakes() {
List<CakeInfo> result = new ArrayList<>();
for (Cake cake : cakeDao.findAll()) {
var cakeToppingInfo =
new CakeToppingInfo(cake.getTopping().getId(), cake.getTopping().getName(),
cake.getTopping().getCalories());
List<CakeLayerInfo> cakeLayerInfos = new ArrayList<>();
for (var layer : cake.getLayers()) {
cakeLayerInfos.add(new CakeLayerInfo(layer.getId(), layer.getName(), layer.getCalories()));
}
var cakeInfo = new CakeInfo(cake.getId(), cakeToppingInfo, cakeLayerInfos);
result.add(cakeInfo);
}
return result;
}
}
@@ -0,0 +1,48 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package view;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import service.CakeBakingService;
/**
* View implementation for displaying cakes.
*/
public class CakeViewImpl implements View {
private final CakeBakingService cakeBakingService;
private static final Logger LOGGER = LoggerFactory.getLogger(CakeViewImpl.class);
public CakeViewImpl(CakeBakingService cakeBakingService) {
this.cakeBakingService = cakeBakingService;
}
public void render() {
cakeBakingService.getAllCakes().forEach(cake -> LOGGER.info(cake.toString()));
}
}
@@ -0,0 +1,35 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package view;
/**
* View interface.
*/
public interface View {
void render();
}
@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
The MIT License
Copyright © 2014-2021 Ilkka Seppälä
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
<configuration>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>layers.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>layers-%d.log</fileNamePattern>
<maxHistory>5</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%-5p [%d{ISO8601,UTC}] %c: %m%n</pattern>
</encoder>
</appender>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%-5p [%d{ISO8601,UTC}] %c: %m%n</pattern>
</encoder>
</appender>
<logger name="com.iluwatar" additivity="false">
<level value="DEBUG" />
<appender-ref ref="FILE" />
</logger>
<logger name="org.hibernate" additivity="false">
<level value="ERROR" />
<appender-ref ref="STDOUT" />
</logger>
<root level="WARN">
<appender-ref ref="STDOUT" />
</root>
</configuration>
@@ -0,0 +1,12 @@
spring.main.web-application-type=none
#datasource settings
spring.datasource.url=jdbc:h2:mem:databases-cake
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=sa
#data settings
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto=create-drop
@@ -0,0 +1,49 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.layers.app;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
@SpringBootTest(classes = LayersApp.class)
class LayersAppTests {
private final ApplicationContext applicationContext;
@Autowired
LayersAppTests(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Test
void contextLoads() {
assertNotNull(applicationContext);
}
}
@@ -0,0 +1,121 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.layers.entity;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import entity.Cake;
import entity.CakeLayer;
import entity.CakeTopping;
import java.util.HashSet;
import java.util.Set;
import org.junit.jupiter.api.Test;
/**
* This class contains unit tests for the Cake class.
* It tests the functionality of setting and getting the id, topping, and layers of a Cake object.
* It also tests the functionality of adding a layer to a Cake object and converting a Cake object to a string.
*/
class CakeTest {
@Test
void testSetId() {
final var cake = new Cake();
assertNull(cake.getId());
final var expectedId = 1234L;
cake.setId(expectedId);
assertEquals(expectedId, cake.getId());
}
@Test
void testSetTopping() {
final var cake = new Cake();
assertNull(cake.getTopping());
final var expectedTopping = new CakeTopping("DummyTopping", 1000);
cake.setTopping(expectedTopping);
assertEquals(expectedTopping, cake.getTopping());
}
@Test
void testSetLayers() {
final var cake = new Cake();
assertNotNull(cake.getLayers());
assertTrue(cake.getLayers().isEmpty());
final var expectedLayers = Set.of(new CakeLayer("layer1", 1000), new CakeLayer("layer2", 2000),
new CakeLayer("layer3", 3000));
cake.setLayers(expectedLayers);
assertEquals(expectedLayers, cake.getLayers());
}
@Test
void testAddLayer() {
final var cake = new Cake();
assertNotNull(cake.getLayers());
assertTrue(cake.getLayers().isEmpty());
final Set<CakeLayer> initialLayers = new HashSet<>();
initialLayers.add(new CakeLayer("layer1", 1000));
initialLayers.add(new CakeLayer("layer2", 2000));
cake.setLayers(initialLayers);
assertEquals(initialLayers, cake.getLayers());
final var newLayer = new CakeLayer("layer3", 3000);
cake.addLayer(newLayer);
final Set<CakeLayer> expectedLayers = new HashSet<>();
expectedLayers.addAll(initialLayers);
expectedLayers.addAll(initialLayers);
expectedLayers.add(newLayer);
assertEquals(expectedLayers, cake.getLayers());
}
@Test
void testToString() {
final var topping = new CakeTopping("topping", 20);
topping.setId(2345L);
final var layer = new CakeLayer("layer", 100);
layer.setId(3456L);
final var cake = new Cake();
cake.setId(1234L);
cake.setTopping(topping);
cake.addLayer(layer);
final var expected = "id=1234 topping=id=2345 name=topping calories=20 "
+ "layers=[id=3456 name=layer calories=100]";
assertEquals(expected, cake.toString());
}
}
@@ -0,0 +1,69 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.layers.exception;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import exception.CakeBakingException;
import org.junit.jupiter.api.Test;
/**
* Tests for the {@link CakeBakingException} class.
* This class contains unit tests to verify the correct functionality
* of the {@code CakeBakingException} class constructors, including the default constructor
* and the constructor that accepts a message parameter.
*/
class CakeBakingExceptionTest {
/**
* Tests the default constructor of {@link CakeBakingException}.
* Ensures that an exception created with the default constructor has
* {@code null} as its message and cause.
*/
@Test
void testConstructor() {
final var exception = new CakeBakingException();
assertNull(exception.getMessage(), "The message should be null for the default constructor.");
assertNull(exception.getCause(), "The cause should be null for the default constructor.");
}
/**
* Tests the constructor of {@link CakeBakingException} that accepts a message.
* Ensures that an exception created with this constructor correctly stores the provided message
* and has {@code null} as its cause.
*/
@Test
void testConstructorWithMessage() {
final var expectedMessage = "message";
final var exception = new CakeBakingException(expectedMessage);
assertEquals(expectedMessage, exception.getMessage(),
"The stored message should match the expected message.");
assertNull(exception.getCause(),
"The cause should be null when an exception is created with only a message.");
}
}
@@ -0,0 +1,197 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.layers.service;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import com.iluwatar.layers.app.LayersApp;
import dto.CakeInfo;
import dto.CakeLayerInfo;
import dto.CakeToppingInfo;
import exception.CakeBakingException;
import java.util.Collections;
import java.util.List;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import service.CakeBakingServiceImpl;
/**
* Constructs a new instance of CakeBakingServiceImplTest.
*
*/
@SpringBootTest(classes = LayersApp.class)
class CakeBakingServiceImplTest {
private final CakeBakingServiceImpl cakeBakingService;
@Autowired
CakeBakingServiceImplTest(CakeBakingServiceImpl cakeBakingService) {
this.cakeBakingService = cakeBakingService;
}
@BeforeEach
void setUp() {
cakeBakingService.deleteAllCakes();
cakeBakingService.deleteAllLayers();
cakeBakingService.deleteAllToppings();
}
@Test
void testLayers() {
final var initialLayers = cakeBakingService.getAvailableLayers();
assertNotNull(initialLayers);
assertTrue(initialLayers.isEmpty());
cakeBakingService.saveNewLayer(new CakeLayerInfo("Layer1", 1000));
cakeBakingService.saveNewLayer(new CakeLayerInfo("Layer2", 2000));
final var availableLayers = cakeBakingService.getAvailableLayers();
assertNotNull(availableLayers);
assertEquals(2, availableLayers.size());
for (final var layer : availableLayers) {
assertNotNull(layer.id);
assertNotNull(layer.name);
assertNotNull(layer.toString());
assertTrue(layer.calories > 0);
}
}
@Test
void testToppings() {
final var initialToppings = cakeBakingService.getAvailableToppings();
assertNotNull(initialToppings);
assertTrue(initialToppings.isEmpty());
cakeBakingService.saveNewTopping(new CakeToppingInfo("Topping1", 1000));
cakeBakingService.saveNewTopping(new CakeToppingInfo("Topping2", 2000));
final var availableToppings = cakeBakingService.getAvailableToppings();
assertNotNull(availableToppings);
assertEquals(2, availableToppings.size());
for (final var topping : availableToppings) {
assertNotNull(topping.id);
assertNotNull(topping.name);
assertNotNull(topping.toString());
assertTrue(topping.calories > 0);
}
}
@Test
void testBakeCakes() throws CakeBakingException {
final var initialCakes = cakeBakingService.getAllCakes();
assertNotNull(initialCakes);
assertTrue(initialCakes.isEmpty());
final var topping1 = new CakeToppingInfo("Topping1", 1000);
final var topping2 = new CakeToppingInfo("Topping2", 2000);
cakeBakingService.saveNewTopping(topping1);
cakeBakingService.saveNewTopping(topping2);
final var layer1 = new CakeLayerInfo("Layer1", 1000);
final var layer2 = new CakeLayerInfo("Layer2", 2000);
final var layer3 = new CakeLayerInfo("Layer3", 2000);
cakeBakingService.saveNewLayer(layer1);
cakeBakingService.saveNewLayer(layer2);
cakeBakingService.saveNewLayer(layer3);
cakeBakingService.bakeNewCake(new CakeInfo(topping1, List.of(layer1, layer2)));
cakeBakingService.bakeNewCake(new CakeInfo(topping2, Collections.singletonList(layer3)));
final var allCakes = cakeBakingService.getAllCakes();
assertNotNull(allCakes);
assertEquals(2, allCakes.size());
for (final var cakeInfo : allCakes) {
assertNotNull(cakeInfo.id);
assertNotNull(cakeInfo.cakeToppingInfo);
assertNotNull(cakeInfo.cakeLayerInfos);
assertNotNull(cakeInfo.toString());
assertFalse(cakeInfo.cakeLayerInfos.isEmpty());
assertTrue(cakeInfo.calculateTotalCalories() > 0);
}
}
@Test
void testBakeCakeMissingTopping() {
final var layer1 = new CakeLayerInfo("Layer1", 1000);
final var layer2 = new CakeLayerInfo("Layer2", 2000);
cakeBakingService.saveNewLayer(layer1);
cakeBakingService.saveNewLayer(layer2);
final var missingTopping = new CakeToppingInfo("Topping1", 1000);
assertThrows(CakeBakingException.class,
() -> cakeBakingService.bakeNewCake(new CakeInfo(missingTopping, List.of(layer1, layer2))));
}
@Test
void testBakeCakeMissingLayer() {
final var initialCakes = cakeBakingService.getAllCakes();
assertNotNull(initialCakes);
assertTrue(initialCakes.isEmpty());
final var topping1 = new CakeToppingInfo("Topping1", 1000);
cakeBakingService.saveNewTopping(topping1);
final var layer1 = new CakeLayerInfo("Layer1", 1000);
cakeBakingService.saveNewLayer(layer1);
final var missingLayer = new CakeLayerInfo("Layer2", 2000);
assertThrows(CakeBakingException.class,
() -> cakeBakingService.bakeNewCake(new CakeInfo(topping1, List.of(layer1, missingLayer))));
}
@Test
void testBakeCakesUsedLayer() throws CakeBakingException {
final var initialCakes = cakeBakingService.getAllCakes();
assertNotNull(initialCakes);
assertTrue(initialCakes.isEmpty());
final var topping1 = new CakeToppingInfo("Topping1", 1000);
final var topping2 = new CakeToppingInfo("Topping2", 2000);
cakeBakingService.saveNewTopping(topping1);
cakeBakingService.saveNewTopping(topping2);
final var layer1 = new CakeLayerInfo("Layer1", 1000);
final var layer2 = new CakeLayerInfo("Layer2", 2000);
cakeBakingService.saveNewLayer(layer1);
cakeBakingService.saveNewLayer(layer2);
cakeBakingService.bakeNewCake(new CakeInfo(topping1, List.of(layer1, layer2)));
assertThrows(CakeBakingException.class, () -> cakeBakingService.bakeNewCake(
new CakeInfo(topping2, Collections.singletonList(layer2))));
}
}
@@ -0,0 +1,113 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.layers.view;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.AppenderBase;
import dto.CakeInfo;
import dto.CakeLayerInfo;
import dto.CakeToppingInfo;
import java.util.LinkedList;
import java.util.List;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.slf4j.LoggerFactory;
import service.CakeBakingService;
import view.CakeViewImpl;
/**
* This class contains unit tests for the CakeViewImpl class.
* It tests the functionality of rendering cakes using the CakeViewImpl class.
* It also tests the logging functionality of the CakeViewImpl class.
*/
class CakeViewImplTest {
private InMemoryAppender appender;
@BeforeEach
void setUp() {
appender = new InMemoryAppender(CakeViewImpl.class);
}
@AfterEach
void tearDown() {
appender.stop();
}
/**
* Verify if the cake view renders the expected result.
*/
@Test
void testRender() {
final var layers = List.of(new CakeLayerInfo("layer1", 1000), new CakeLayerInfo("layer2", 2000),
new CakeLayerInfo("layer3", 3000));
final var cake = new CakeInfo(new CakeToppingInfo("topping", 1000), layers);
final var cakes = List.of(cake);
final var bakingService = mock(CakeBakingService.class);
when(bakingService.getAllCakes()).thenReturn(cakes);
final var cakeView = new CakeViewImpl(bakingService);
assertEquals(0, appender.getLogSize());
cakeView.render();
assertEquals(cake.toString(), appender.getLastMessage());
}
private static class InMemoryAppender extends AppenderBase<ILoggingEvent> {
private final List<ILoggingEvent> log = new LinkedList<>();
public InMemoryAppender(Class clazz) {
((Logger) LoggerFactory.getLogger(clazz)).addAppender(this);
start();
}
@Override
protected void append(ILoggingEvent eventObject) {
log.add(eventObject);
}
public String getLastMessage() {
return log.get(log.size() - 1).getFormattedMessage();
}
public int getLogSize() {
return log.size();
}
}
}