Subject: [PATCH] 6_jaxb_filter --- Index: src/test/java/ru/javaops/docjava/TestData.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/src/test/java/ru/javaops/docjava/TestData.java b/src/test/java/ru/javaops/docjava/TestData.java --- a/src/test/java/ru/javaops/docjava/TestData.java (revision 42b9e1ab07bf421841ee5e99a7249ba165232968) +++ b/src/test/java/ru/javaops/docjava/TestData.java (date 1695983014739) @@ -4,39 +4,58 @@ import ru.javaops.docjava.schema.Meals; import ru.javaops.docjava.schema.RoleTypes; import ru.javaops.docjava.schema.User; +import ru.javaops.docjava.util.Util; import java.io.File; import java.time.Month; import java.util.Calendar; import java.util.Date; import java.util.List; +import java.util.Map; import static java.time.LocalDateTime.of; public class TestData { public static final File inputFile = new File("in/usersWithMeals.xml"); + public static final Map paramsMap = + Util.parseParams(List.of("startDate=2023-01-30", "endDate=2023-01-30", "startTime=11:00", "endTime=19:00")); + public static final Date registered = new Date(123, Calendar.JANUARY, 1, 13, 0, 0); + public static final Meal userLunch = new Meal("Обед", 1000, of(2023, Month.JANUARY, 30, 13, 0, 0), false); public static final Meals userMeals = new Meals(List.of( - new Meal("Завтрак", 500, of(2023, Month.JANUARY, 30, 10, 0, 0), null), - new Meal("Обед", 1000, of(2023, Month.JANUARY, 30, 13, 0, 0), null), - new Meal("Ужин", 500, of(2023, Month.JANUARY, 30, 20, 0, 0), null), - new Meal("Еда на граничное значение", 100, of(2023, Month.JANUARY, 31, 0, 0, 0), null), - new Meal("Завтрак", 500, of(2023, Month.JANUARY, 31, 10, 0, 0), null), - new Meal("Обед", 1000, of(2023, Month.JANUARY, 31, 13, 0, 0), null), - new Meal("Ужин", 510, of(2023, Month.JANUARY, 31, 20, 0, 0), null) + new Meal("Завтрак", 500, of(2023, Month.JANUARY, 30, 10, 0, 0), false), + userLunch, + new Meal("Ужин", 500, of(2023, Month.JANUARY, 30, 20, 0, 0), false), + new Meal("Еда на граничное значение", 100, of(2023, Month.JANUARY, 31, 0, 0, 0), true), + new Meal("Завтрак", 500, of(2023, Month.JANUARY, 31, 10, 0, 0), true), + new Meal("Обед", 1000, of(2023, Month.JANUARY, 31, 13, 0, 0), true), + new Meal("Ужин", 510, of(2023, Month.JANUARY, 31, 20, 0, 0), true) )); public static final User user = new User("User", "user@yandex.ru", "password", 2005, registered, true, - List.of(RoleTypes.USER), userMeals); + List.of(RoleTypes.USER), null); + public static final Meal adminLunch = new Meal("Админ ланч", 510, of(2023, Month.JANUARY, 30, 14, 0, 0), false); public static final Meals adminMeals = new Meals(List.of( - new Meal("Админ ланч", 510, of(2023, Month.JANUARY, 30, 14, 0, 0), null), - new Meal("Админ ужин", 730, of(2023, Month.JANUARY, 30, 21, 0, 0), null) + adminLunch, + new Meal("Админ ужин", 730, of(2023, Month.JANUARY, 30, 21, 0, 0), false) )); public static final User admin = new User("Admin", "admin@gmail.com", "admin", 1900, registered, true, - List.of(RoleTypes.ADMIN, RoleTypes.USER), adminMeals); + List.of(RoleTypes.ADMIN, RoleTypes.USER), null); public static final User guest = new User("Guest", "guest@gmail.com", "guest", 2000, registered, false, List.of(), null); + + public static List getUsers() { + user.setMeals(userMeals); + admin.setMeals(adminMeals); + return List.of(user, admin, guest); + } + + public static List getFilteredUsers() { + user.setMeals(new Meals(List.of(userLunch))); + admin.setMeals(new Meals(List.of(adminLunch))); + return List.of(user, admin, guest); + } } \ No newline at end of file Index: src/test/java/ru/javaops/docjava/xml/jaxb/JaxbUtilTest.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/src/test/java/ru/javaops/docjava/xml/jaxb/JaxbUtilTest.java b/src/test/java/ru/javaops/docjava/xml/jaxb/JaxbUtilTest.java --- a/src/test/java/ru/javaops/docjava/xml/jaxb/JaxbUtilTest.java (revision 42b9e1ab07bf421841ee5e99a7249ba165232968) +++ b/src/test/java/ru/javaops/docjava/xml/jaxb/JaxbUtilTest.java (date 1695983014733) @@ -7,7 +7,7 @@ import java.io.File; import java.io.IOException; -import java.util.List; +import java.util.Map; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -16,13 +16,19 @@ public class JaxbUtilTest { @Test - public void unmarshalOK() throws JAXBException, IOException { - UsersWithMeals usersWithMeals = JaxbUtil.unmarshal(inputFile); - assertEquals(new UsersWithMeals.Users(List.of(user, admin, guest)), usersWithMeals.getUsers()); + public void processOK() throws JAXBException, IOException { + UsersWithMeals usersWithMeals = JaxbUtil.process(inputFile, Map.of()); + assertEquals(new UsersWithMeals.Users(getUsers()), usersWithMeals.getUsers()); } @Test - void unmarshalNOK() { + void processFiltered() throws IOException, JAXBException { + UsersWithMeals usersWithMeals = JaxbUtil.process(inputFile, paramsMap); + assertEquals(new UsersWithMeals.Users(getFilteredUsers()), usersWithMeals.getUsers()); + } + + @Test + void processNOK() { assertThrows(UnmarshalException.class, () -> JaxbUtil.unmarshal(new File("in/badXmlFile.xml")), "Except bad format exception"); } Index: src/main/java/ru/javaops/docjava/xml/jaxb/JaxbUtil.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/src/main/java/ru/javaops/docjava/xml/jaxb/JaxbUtil.java b/src/main/java/ru/javaops/docjava/xml/jaxb/JaxbUtil.java --- a/src/main/java/ru/javaops/docjava/xml/jaxb/JaxbUtil.java (revision 42b9e1ab07bf421841ee5e99a7249ba165232968) +++ b/src/main/java/ru/javaops/docjava/xml/jaxb/JaxbUtil.java (date 1695983138502) @@ -5,12 +5,14 @@ import lombok.experimental.UtilityClass; import ru.javaops.docjava.schema.ObjectFactory; import ru.javaops.docjava.schema.UsersWithMeals; +import ru.javaops.docjava.util.MealsUtil; import ru.javaops.docjava.xml.xsd.Schemas; import java.io.File; import java.io.IOException; import java.io.Reader; import java.nio.file.Files; +import java.util.Map; @UtilityClass public class JaxbUtil { @@ -26,6 +28,18 @@ } } + public static UsersWithMeals process(File inputXml, Map params) throws IOException, JAXBException { + UsersWithMeals users = unmarshalAndFilter(inputXml, params); + System.out.println("JAXB processing completed successfully"); + return users; + } + + public static UsersWithMeals unmarshalAndFilter(File inputXml, Map params) throws IOException, JAXBException { + UsersWithMeals users = unmarshal(inputXml); + MealsUtil.filterAndAddExcess(users, params); + return users; + } + public static UsersWithMeals unmarshal(File inputXml) throws IOException, JAXBException { try (Reader reader = Files.newBufferedReader(inputXml.toPath())) { return unmarshaller.unmarshal(reader); Index: src/main/java/ru/javaops/docjava/util/Util.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/src/main/java/ru/javaops/docjava/util/Util.java b/src/main/java/ru/javaops/docjava/util/Util.java new file mode 100644 --- /dev/null (date 1695982990520) +++ b/src/main/java/ru/javaops/docjava/util/Util.java (date 1695982990520) @@ -0,0 +1,34 @@ +package ru.javaops.docjava.util; + +import lombok.experimental.UtilityClass; +import org.springframework.lang.Nullable; + +import java.time.LocalDate; +import java.time.LocalTime; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@UtilityClass +public class Util { + public static > boolean isBetweenHalfOpen(T value, @Nullable T start, @Nullable T end) { + return (start == null || value.compareTo(start) >= 0) && (end == null || value.compareTo(end) < 0); + } + + public static Map parseParams(List params) { + Map map = new HashMap<>(); + for (String parameter : params) { + String[] param = parameter.split("="); + String key = param[0].trim(); + String value = param[1].trim(); + if (key.endsWith("Date")) { + map.put(key, LocalDate.parse(value)); + } else if (key.endsWith("Time")) { + map.put(key, LocalTime.parse(value)); + } else { + throw new IllegalArgumentException("Unknown filter parameter: '" + key + "'"); + } + } + return map; + } +} Index: src/main/java/ru/javaops/docjava/util/MealsUtil.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/src/main/java/ru/javaops/docjava/util/MealsUtil.java b/src/main/java/ru/javaops/docjava/util/MealsUtil.java new file mode 100644 --- /dev/null (date 1695982990517) +++ b/src/main/java/ru/javaops/docjava/util/MealsUtil.java (date 1695982990517) @@ -0,0 +1,50 @@ +package ru.javaops.docjava.util; + +import lombok.experimental.UtilityClass; +import org.springframework.lang.Nullable; +import ru.javaops.docjava.schema.Meal; +import ru.javaops.docjava.schema.Meals; +import ru.javaops.docjava.schema.User; +import ru.javaops.docjava.schema.UsersWithMeals; + +import java.time.LocalDate; +import java.time.LocalTime; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@UtilityClass +public class MealsUtil { + + public static void filterAndAddExcess(UsersWithMeals users, Map params) { + users.getUsers().getUser().forEach(user -> MealsUtil.filterAndAddExcess(user, params)); + } + + public static void filterAndAddExcess(User user, Map params) { + if (user.getMeals() != null) { + List meals = filterAndAddExcess(user.getMeals().getMeal(), user.getCaloriesPerDay(), + (LocalDate) params.get("startDate"), (LocalDate) params.get("endDate"), + (LocalTime) params.get("startTime"), (LocalTime) params.get("endTime")); + user.setMeals(new Meals(meals)); + } + } + + public static List filterAndAddExcess(List meals, int caloriesPerDay, + @Nullable LocalDate startDate, @Nullable LocalDate endDate, + @Nullable LocalTime startTime, @Nullable LocalTime endTime) { + + LocalDate adaptStartDate = (startDate == null ? LocalDate.MIN : startDate); + LocalDate adaptEndDate = (endDate == null || endDate.equals(LocalDate.MAX) ? LocalDate.MAX : endDate.plusDays(1)); + + List mealsFilteredByDate = meals.stream() + .filter(meal -> Util.isBetweenHalfOpen(meal.getDate(), adaptStartDate, adaptEndDate)).toList(); + + Map caloriesSumByDate = mealsFilteredByDate.stream() + .collect(Collectors.groupingBy(Meal::getDate, Collectors.summingInt(Meal::getCalories))); + + return mealsFilteredByDate.stream() + .filter(meal -> Util.isBetweenHalfOpen(meal.getTime(), startTime, endTime)) + .peek(meal -> meal.setExcess(caloriesSumByDate.get(meal.getDate()) > caloriesPerDay)) + .toList(); + } +} Index: src/main/java/ru/javaops/docjava/Commands.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/src/main/java/ru/javaops/docjava/Commands.java b/src/main/java/ru/javaops/docjava/Commands.java --- a/src/main/java/ru/javaops/docjava/Commands.java (revision 42b9e1ab07bf421841ee5e99a7249ba165232968) +++ b/src/main/java/ru/javaops/docjava/Commands.java (date 1695983014721) @@ -13,6 +13,8 @@ import java.io.IOException; import java.util.List; +import static ru.javaops.docjava.util.Util.parseParams; + @ShellComponent public class Commands { @ShellMethod(key = "xsd", value = "Validate XML file against XSD (XML Schema)") @@ -26,8 +28,7 @@ @ShellOption(value = {"input", "-i"}, help = "Input file") File inputFile, @ShellOption(value = {"filter", "-f"}, help = "Filter params", defaultValue = "") List params, @ShellOption(value = {"output", "-o"}, help = "Output file") File outputFile) throws JAXBException, IOException { - UsersWithMeals users = JaxbUtil.unmarshal(inputFile); - System.out.println(users); + JaxbUtil.process(inputFile, parseParams(params)); } @ShellMethod(key = "stax", value = "Process XML file via StAX") Index: src/main/java/ru/javaops/docjava/schema/Meal.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/src/main/java/ru/javaops/docjava/schema/Meal.java b/src/main/java/ru/javaops/docjava/schema/Meal.java --- a/src/main/java/ru/javaops/docjava/schema/Meal.java (revision 42b9e1ab07bf421841ee5e99a7249ba165232968) +++ b/src/main/java/ru/javaops/docjava/schema/Meal.java (date 1695982990513) @@ -6,7 +6,9 @@ import lombok.Data; import lombok.NoArgsConstructor; +import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.LocalTime; @XmlAccessorType(XmlAccessType.FIELD) @XmlRootElement(name = "Meal", namespace = "http://javaops.ru") @@ -23,4 +25,12 @@ protected LocalDateTime dateTime; @XmlAttribute(name = "excess") protected Boolean excess; + + public LocalDate getDate() { + return dateTime.toLocalDate(); + } + + public LocalTime getTime() { + return dateTime.toLocalTime(); + } }