diff --git a/resources/WEB-INF/jsp/email.jsp b/resources/WEB-INF/jsp/email.jsp new file mode 100644 index 0000000..e3c4048 --- /dev/null +++ b/resources/WEB-INF/jsp/email.jsp @@ -0,0 +1,26 @@ +<%@ page contentType="text/html;charset=UTF-8" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + Charm Profiles + <%@ include file="style.html" %> + + + <%@ include file="header.jsp" %> +
+

${requestScope.wordBundle.getWord("email-warning")}

+
+ + + + + + + +

${requestScope.wordBundle.getWord("email")}

+ +
+
+ <%@ include file="footer.jsp" %> + + \ No newline at end of file diff --git a/resources/WEB-INF/jsp/error400.jsp b/resources/WEB-INF/jsp/error400.jsp new file mode 100644 index 0000000..6c495ba --- /dev/null +++ b/resources/WEB-INF/jsp/error400.jsp @@ -0,0 +1,15 @@ +<%@ page contentType="text/html;charset=UTF-8" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + Charm Bad Request + <%@ include file="style.html" %> + + + <%@ include file="header.jsp" %> +
+

400 - ${requestScope.wordBundle.getWord("page-bad-request")}

+
+ <%@ include file="footer.jsp" %> + + \ No newline at end of file diff --git a/resources/WEB-INF/jsp/error404.jsp b/resources/WEB-INF/jsp/error404.jsp new file mode 100644 index 0000000..a880cd5 --- /dev/null +++ b/resources/WEB-INF/jsp/error404.jsp @@ -0,0 +1,15 @@ +<%@ page contentType="text/html;charset=UTF-8" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + Charm Not Found + <%@ include file="style.html" %> + + + <%@ include file="header.jsp" %> +
+

404 - ${requestScope.wordBundle.getWord("page-not-found")}

+
+ <%@ include file="footer.jsp" %> + + \ No newline at end of file diff --git a/resources/WEB-INF/jsp/footer.jsp b/resources/WEB-INF/jsp/footer.jsp index 6bdce1e..127c7d9 100644 --- a/resources/WEB-INF/jsp/footer.jsp +++ b/resources/WEB-INF/jsp/footer.jsp @@ -1,5 +1,5 @@ - +<%@ page contentType="text/html;charset=UTF-8" %>

-

All rights reserved 2024

+ ${requestScope.wordBundle.getWord("all-rights-reserved")} 2024
\ No newline at end of file diff --git a/resources/WEB-INF/jsp/header.jsp b/resources/WEB-INF/jsp/header.jsp index 681bdf6..e62fc07 100644 --- a/resources/WEB-INF/jsp/header.jsp +++ b/resources/WEB-INF/jsp/header.jsp @@ -1,14 +1,9 @@ <%@ page contentType="text/html;charset=UTF-8" %>

Charm <3

+
+ + +

- -
- - -
- -

My current language: ${cookie["lang"].value}

- -
\ No newline at end of file diff --git a/resources/WEB-INF/jsp/profile.jsp b/resources/WEB-INF/jsp/profile.jsp index d4b5069..6b941c9 100644 --- a/resources/WEB-INF/jsp/profile.jsp +++ b/resources/WEB-INF/jsp/profile.jsp @@ -1,66 +1,59 @@ <%@ page contentType="text/html;charset=UTF-8" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> - - Charm Profile - - -<%@ include file="header.jsp" %> -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

${requestScope.wordBundle.getWord("email")}

${requestScope.wordBundle.getWord("name")}

${requestScope.wordBundle.getWord("surname")}

${requestScope.wordBundle.getWord("birth-date")}

${requestScope.wordBundle.getWord("age")}

${requestScope.profile.age}

${requestScope.wordBundle.getWord("about")}

${requestScope.wordBundle.getWord("gender")}

- -
- -
- -
- - - -
-
-
-<%@ include file="footer.jsp" %> - + + Charm Profile + <%@ include file="style.html" %> + + + <%@ include file="header.jsp" %> +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +

${requestScope.wordBundle.getWord("email")}

${requestScope.profile.email}

${requestScope.wordBundle.getWord("name")}

${requestScope.wordBundle.getWord("surname")}

${requestScope.wordBundle.getWord("birth-date")}

${requestScope.wordBundle.getWord("about")}

${requestScope.wordBundle.getWord("gender")}

+ +
+ +
+
+ + + +
+
+ <%@ include file="footer.jsp" %> + \ No newline at end of file diff --git a/resources/WEB-INF/jsp/profiles.jsp b/resources/WEB-INF/jsp/profiles.jsp index 2aa5102..922c73b 100644 --- a/resources/WEB-INF/jsp/profiles.jsp +++ b/resources/WEB-INF/jsp/profiles.jsp @@ -3,12 +3,7 @@ Charm Profiles - + <%@ include file="style.html" %> <%@ include file="header.jsp" %> @@ -20,14 +15,30 @@

${requestScope.wordBundle.getWord("name")}

${requestScope.wordBundle.getWord("surname")}

${requestScope.wordBundle.getWord("age")}

+

${requestScope.wordBundle.getWord("status")}

-

${profile.id}

-

${profile.email}

-

${profile.name}

-

${profile.surname}

-

${profile.age}

+

${profile.id}

+

${profile.email}

+

${profile.name}

+

${profile.surname}

+

${profile.age}

+ +
+ + + + +
+
diff --git a/resources/WEB-INF/jsp/registration.jsp b/resources/WEB-INF/jsp/registration.jsp new file mode 100644 index 0000000..3d7546e --- /dev/null +++ b/resources/WEB-INF/jsp/registration.jsp @@ -0,0 +1,26 @@ +<%@ page contentType="text/html;charset=UTF-8" %> + + + Charm Registration + <%@ include file="style.html" %> + + + <%@ include file="header.jsp" %> +
+
+ + + + + + + + + +

${requestScope.wordBundle.getWord("email")}

${requestScope.wordBundle.getWord("password")}

+ +
+
+ <%@ include file="footer.jsp" %> + + \ No newline at end of file diff --git a/resources/WEB-INF/jsp/style.html b/resources/WEB-INF/jsp/style.html new file mode 100644 index 0000000..0837443 --- /dev/null +++ b/resources/WEB-INF/jsp/style.html @@ -0,0 +1,57 @@ + + + + \ No newline at end of file diff --git a/resources/WEB-INF/web.xml b/resources/WEB-INF/web.xml index 2a3867d..76c1445 100644 --- a/resources/WEB-INF/web.xml +++ b/resources/WEB-INF/web.xml @@ -20,4 +20,13 @@ xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd" version="6.0"> + + + 404 + /WEB-INF/jsp/error404.jsp + + + 400 + /WEB-INF/jsp/error400.jsp + diff --git a/resources/words.properties b/resources/words.properties index d3206f1..ac8383d 100644 --- a/resources/words.properties +++ b/resources/words.properties @@ -1,13 +1,21 @@ about=About +active=Active age=Age all-rights-reserved=All rights reserved birth-date=Birth date +confirm-password=Confirm password delete=Delete email=Email +email-warning=Changing your mail may have negative effects female=Female gender=Gender +inactive=Inactive male=Male name=Name other=Other +page-bad-request=Bad request +page-not-found=Page not found +password=Password save=Save +status=Status surname=Surname \ No newline at end of file diff --git a/resources/words_en.properties b/resources/words_en.properties index d3206f1..ac8383d 100644 --- a/resources/words_en.properties +++ b/resources/words_en.properties @@ -1,13 +1,21 @@ about=About +active=Active age=Age all-rights-reserved=All rights reserved birth-date=Birth date +confirm-password=Confirm password delete=Delete email=Email +email-warning=Changing your mail may have negative effects female=Female gender=Gender +inactive=Inactive male=Male name=Name other=Other +page-bad-request=Bad request +page-not-found=Page not found +password=Password save=Save +status=Status surname=Surname \ No newline at end of file diff --git a/resources/words_ru.properties b/resources/words_ru.properties index ec51110..1cf55c7 100644 --- a/resources/words_ru.properties +++ b/resources/words_ru.properties @@ -1,13 +1,21 @@ about=\u041E \u0441\u0435\u0431\u0435 +active=\u0410\u043A\u0442\u0438\u0432\u043D\u044B\u0439 age=\u0412\u043E\u0437\u0440\u0430\u0441\u0442 all-rights-reserved=\u0412\u0441\u0435 \u043F\u0440\u0430\u0432\u0430 \u0437\u0430\u0449\u0438\u0449\u0435\u043D\u044B birth-date=\u0414\u0430\u0442\u0430 \u0440\u043E\u0436\u0434\u0435\u043D\u0438\u044F +confirm-password=\u041F\u043E\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0435 \u043F\u0430\u0440\u043E\u043B\u044C delete=\u0423\u0434\u0430\u043B\u0438\u0442\u044C email=\u041F\u043E\u0447\u0442\u0430 +email-warning=\u0421\u043C\u0435\u043D\u0430 \u043F\u043E\u0447\u0442\u044B \u043C\u043E\u0436\u0435\u0442 \u043F\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u043A \u043D\u0435\u0436\u0435\u043B\u0430\u0442\u0435\u043B\u044C\u043D\u044B\u043C \u043F\u043E\u0441\u043B\u0435\u0434\u0441\u0442\u0432\u0438\u044F\u043C female=\u0416\u0435\u043D\u0449\u0438\u043D\u0430 gender=\u041F\u043E\u043B +inactive=\u041D\u0435\u0430\u043A\u0442\u0438\u0432\u043D\u044B\u0439 male=\u041C\u0443\u0436\u0447\u0438\u043D\u0430 name=\u0418\u043C\u044F other=\u0414\u0440\u0443\u0433\u043E\u0435 +page-bad-request=\u041D\u0435\u043A\u043E\u0440\u0440\u0435\u043A\u0442\u043D\u044B\u0439 \u0437\u0430\u043F\u0440\u043E\u0441 +page-not-found=\u0421\u0442\u0440\u0430\u043D\u0438\u0446\u0430 \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u0430 +password=\u041F\u0430\u0440\u043E\u043B\u044C save=\u0421\u043E\u0445\u0440\u0430\u043D\u0438\u0442\u044C +status=\u0421\u0442\u0430\u0442\u0443\u0441 surname=\u0424\u0430\u043C\u0438\u043B\u0438\u044F \ No newline at end of file diff --git a/src/ru/charm/back/controller/EmailController.java b/src/ru/charm/back/controller/EmailController.java new file mode 100644 index 0000000..13dc7f9 --- /dev/null +++ b/src/ru/charm/back/controller/EmailController.java @@ -0,0 +1,52 @@ + package ru.charm.back.controller; + +import jakarta.servlet.ServletException; +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import ru.charm.back.dto.ProfileGetDto; +import ru.charm.back.dto.ProfileUpdateDto; +import ru.charm.back.mapper.RequestToProfileUpdateDtoMapper; +import ru.charm.back.model.Gender; +import ru.charm.back.model.Profile; +import ru.charm.back.model.exception.DuplicateEmailException; +import ru.charm.back.service.ProfileService; + +import java.io.IOException; +import java.time.LocalDate; +import java.util.Optional; + +import static jakarta.servlet.http.HttpServletResponse.SC_BAD_REQUEST; + +@WebServlet("/email") +public class EmailController extends HttpServlet { + private final ProfileService service = ProfileService.getInstance(); + private final RequestToProfileUpdateDtoMapper requestToProfileUpdateDtoMapper = RequestToProfileUpdateDtoMapper.getInstance(); + + @Override + protected void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + + String sId = req.getParameter("id"); + String forwardUri = "/notFound"; + if (sId != null) { + Optional optProfileGetDto = service.findById(Long.parseLong(sId)); + if (optProfileGetDto.isPresent()) { + req.setAttribute("profile", optProfileGetDto.get()); + forwardUri = "/WEB-INF/jsp/email.jsp"; + } + } + req.getRequestDispatcher(forwardUri).forward(req, resp); + } + + @Override + protected void doPut (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + ProfileUpdateDto dto = requestToProfileUpdateDtoMapper.map(req, new ProfileUpdateDto()); + try { + service.update(dto); + resp.sendRedirect(String.format("/profile?id=%s", dto.getId())); + } catch (DuplicateEmailException e) { + resp.sendError(SC_BAD_REQUEST); + } + } +} diff --git a/src/ru/charm/back/controller/ProfileController.java b/src/ru/charm/back/controller/ProfileController.java index bb03feb..450bcdf 100644 --- a/src/ru/charm/back/controller/ProfileController.java +++ b/src/ru/charm/back/controller/ProfileController.java @@ -6,73 +6,47 @@ import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import ru.charm.back.dto.ProfileGetDto; -import ru.charm.back.model.Gender; -import ru.charm.back.model.Profile; +import ru.charm.back.dto.ProfileUpdateDto; +import ru.charm.back.mapper.RequestToProfileUpdateDtoMapper; import ru.charm.back.service.ProfileService; import java.io.IOException; -import java.time.LocalDate; import java.util.Optional; +import static jakarta.servlet.http.HttpServletResponse.SC_NOT_FOUND; + @WebServlet("/profile") public class ProfileController extends HttpServlet { private final ProfileService service = ProfileService.getInstance(); + private final RequestToProfileUpdateDtoMapper requestToProfileUpdateDtoMapper = RequestToProfileUpdateDtoMapper.getInstance(); + @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String sId = req.getParameter("id"); - String forwardUri = "/notFound"; + String forwardUri = null; if (sId != null) { - Optional optProfileGetDto = service.findById(Long.parseLong(sId)); - if (optProfileGetDto.isPresent()) { - req.setAttribute("profile", optProfileGetDto.get()); + Optional optProfileDto = service.findById(Long.parseLong(sId)); + if (optProfileDto.isPresent()) { + req.setAttribute("profile", optProfileDto.get()); forwardUri = "/WEB-INF/jsp/profile.jsp"; } } else { req.setAttribute("profiles", service.findAll()); forwardUri = "/WEB-INF/jsp/profiles.jsp"; } - req.getRequestDispatcher(forwardUri).forward(req, resp); - } - - @Override - protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - Profile profile = getProfile(req); - service.save(profile); - resp.sendRedirect(String.format("/profile?id=%s", profile.getId())); - } - - @Override - protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - Profile profile = getProfile(req); - service.update(profile); - resp.sendRedirect(String.format("/profile?id=%s", profile.getId())); - - } - - @Override - protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - String sId = req.getParameter("id"); - if (!sId.isBlank()) { - service.delete(Long.parseLong(sId)); + if (forwardUri == null) { + resp.sendError(SC_NOT_FOUND); + } else { + req.getRequestDispatcher(forwardUri).forward(req, resp); } - resp.sendRedirect("/registration"); } - private Profile getProfile(HttpServletRequest req) { - Profile profile = new Profile(); - String sId = req.getParameter("id"); - - if (!sId.isBlank()) { - profile.setId(Long.parseLong(sId)); - } - - profile.setEmail(req.getParameter("email")); - profile.setName(req.getParameter("name")); - profile.setSurname(req.getParameter("surname")); - profile.setAbout(req.getParameter("about")); - profile.setGender(Gender.valueOf(req.getParameter("gender"))); - profile.setBirthday(LocalDate.parse(req.getParameter("birthDate"))); - return profile; + @Override + protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws IOException { + ProfileUpdateDto dto = requestToProfileUpdateDtoMapper.map(req); + service.update(dto); + String referer = req.getHeader("referer"); + resp.sendRedirect(referer); } -} +} \ No newline at end of file diff --git a/src/ru/charm/back/dao/ProfileDao.java b/src/ru/charm/back/dao/ProfileDao.java index a340367..c74329b 100644 --- a/src/ru/charm/back/dao/ProfileDao.java +++ b/src/ru/charm/back/dao/ProfileDao.java @@ -2,41 +2,49 @@ package ru.charm.back.dao; import ru.charm.back.model.Gender; import ru.charm.back.model.Profile; +import ru.charm.back.model.Status; import java.time.LocalDate; import java.util.ArrayList; import java.util.List; import java.util.Optional; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicLong; +import java.util.stream.Collectors; public class ProfileDao { - private final ConcurrentHashMap storage; - private final AtomicLong idStorage; private static final ProfileDao INSTANCE = new ProfileDao(); + private final AtomicLong idStorage; + private final ConcurrentHashMap storage; + private ProfileDao() { this.storage = new ConcurrentHashMap<>(); Profile profile = new Profile(); profile.setId(1L); profile.setEmail("ivanov@mail.ru"); + profile.setPassword("123"); profile.setName("Ivan"); profile.setSurname("Ivanov"); + profile.setBirthDate(LocalDate.parse("2001-12-03")); profile.setAbout("I am QA"); profile.setGender(Gender.MALE); - profile.setBirthday(LocalDate.parse("2000-01-01")); + profile.setStatus(Status.ACTIVE); this.storage.put(1L, profile); Profile profile1 = new Profile(); profile1.setId(2L); profile1.setEmail("sidorova@mail.ru"); + profile1.setPassword("456"); profile1.setName("Elena"); profile1.setSurname("Sidorova"); + profile1.setBirthDate(LocalDate.parse("1999-09-01")); profile1.setAbout("I am Java Dev"); - profile1.setBirthday(LocalDate.parse("2000-01-01")); profile1.setGender(Gender.FEMALE); + profile1.setStatus(Status.INACTIVE); this.storage.put(2L, profile1); - this.idStorage = new AtomicLong(2L); + this.idStorage = new AtomicLong(3L); } public static ProfileDao getInstance() { @@ -44,30 +52,32 @@ public class ProfileDao { } public Profile save(Profile profile) { - long id = idStorage.incrementAndGet(); - profile.setId(id); - storage.put(id, profile); - + profile.setId(idStorage.getAndIncrement()); + storage.put(profile.getId(), profile); return profile; } public Optional findById(Long id) { + if (id == null) return Optional.empty(); return Optional.ofNullable(storage.get(id)); } - public void update(Profile profile) { - Long id = profile.getId(); - if (id == null) { - return; - } - storage.put(id, profile); - } - public List findAll() { return new ArrayList<>(storage.values()); } - public Boolean delete(Long id) { + public void update(Profile profile) { + Long id = profile.getId(); + if (id == null) return; + storage.put(id, profile); + } + + public boolean delete(Long id) { + if (id == null) return false; return storage.remove(id) != null; } + + public Set getAllEmails() { + return storage.values().stream().map(Profile::getEmail).collect(Collectors.toSet()); + } } diff --git a/src/ru/charm/back/dto/ProfileGetDto.java b/src/ru/charm/back/dto/ProfileGetDto.java index a1569e3..9b572af 100644 --- a/src/ru/charm/back/dto/ProfileGetDto.java +++ b/src/ru/charm/back/dto/ProfileGetDto.java @@ -1,34 +1,20 @@ package ru.charm.back.dto; import ru.charm.back.model.Gender; +import ru.charm.back.model.Status; import java.time.LocalDate; -public class ProfileGetDto { +public class ProfileGetDto { private Long id; private String email; private String name; private String surname; + private LocalDate birthDate; + private Integer age; private String about; private Gender gender; - private LocalDate birthDate; - private int age; - - public int getAge() { - return age; - } - - public void setAge(int age) { - this.age = age; - } - - public LocalDate getBirthDate() { - return birthDate; - } - - public void setBirthDate(LocalDate birthDate) { - this.birthDate = birthDate; - } + private Status status; public Long getId() { return id; @@ -62,6 +48,22 @@ public class ProfileGetDto { this.surname = surname; } + public LocalDate getBirthDate() { + return birthDate; + } + + public void setBirthDate(LocalDate birthDate) { + this.birthDate = birthDate; + } + + public Integer getAge() { + return age; + } + + public void setAge(Integer age) { + this.age = age; + } + public String getAbout() { return about; } @@ -78,14 +80,11 @@ public class ProfileGetDto { this.gender = gender; } - @Override - public String toString() { - return "Profile{" + - "id=" + id + - ", email='" + email + '\'' + - ", name='" + name + '\'' + - ", surname='" + surname + '\'' + - ", about='" + about + '\'' + - '}'; + public Status getStatus() { + return status; + } + + public void setStatus(Status status) { + this.status = status; } } diff --git a/src/ru/charm/back/dto/ProfileUpdateDto.java b/src/ru/charm/back/dto/ProfileUpdateDto.java new file mode 100644 index 0000000..7f51187 --- /dev/null +++ b/src/ru/charm/back/dto/ProfileUpdateDto.java @@ -0,0 +1,91 @@ +package ru.charm.back.dto; + + +import ru.charm.back.model.Gender; +import ru.charm.back.model.Status; + +import java.time.LocalDate; + +public class ProfileUpdateDto { + private Long id; + private String email; + private String password; + private String name; + private String surname; + private LocalDate birthDate; + private String about; + private Gender gender; + private Status status; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getSurname() { + return surname; + } + + public void setSurname(String surname) { + this.surname = surname; + } + + public LocalDate getBirthDate() { + return birthDate; + } + + public void setBirthDate(LocalDate birthDate) { + this.birthDate = birthDate; + } + + public String getAbout() { + return about; + } + + public void setAbout(String about) { + this.about = about; + } + + public Gender getGender() { + return gender; + } + + public void setGender(Gender gender) { + this.gender = gender; + } + + public Status getStatus() { + return status; + } + + public void setStatus(Status status) { + this.status = status; + } +} diff --git a/src/ru/charm/back/dto/RegistrationDto.java b/src/ru/charm/back/dto/RegistrationDto.java new file mode 100644 index 0000000..ffeac3f --- /dev/null +++ b/src/ru/charm/back/dto/RegistrationDto.java @@ -0,0 +1,22 @@ +package ru.charm.back.dto; + +public class RegistrationDto { + private String email; + private String password; + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } +} diff --git a/src/ru/charm/back/mapper/Mapper.java b/src/ru/charm/back/mapper/Mapper.java index c87d933..1142af3 100644 --- a/src/ru/charm/back/mapper/Mapper.java +++ b/src/ru/charm/back/mapper/Mapper.java @@ -3,4 +3,5 @@ package ru.charm.back.mapper; public interface Mapper { To map(From from); + To map(From from, To to); } diff --git a/src/ru/charm/back/mapper/ProfileGetDtoMapper.java b/src/ru/charm/back/mapper/ProfileGetDtoMapper.java deleted file mode 100644 index 3efe777..0000000 --- a/src/ru/charm/back/mapper/ProfileGetDtoMapper.java +++ /dev/null @@ -1,32 +0,0 @@ -package ru.charm.back.mapper; - -import ru.charm.back.dto.ProfileGetDto; -import ru.charm.back.model.Profile; - -import java.time.LocalDate; -import java.time.temporal.ChronoUnit; - -public class ProfileGetDtoMapper implements Mapper { - private static final ProfileGetDtoMapper INSTANCE = new ProfileGetDtoMapper(); - - - public static ProfileGetDtoMapper getInstance() { - return INSTANCE; - } - - @Override - public ProfileGetDto map(Profile profile) { - ProfileGetDto dto = new ProfileGetDto(); - - dto.setId(profile.getId()); - dto.setEmail(profile.getEmail()); - dto.setName(profile.getName()); - dto.setSurname(profile.getSurname()); - dto.setBirthDate(profile.getBirthday()); - dto.setAge(Math.toIntExact(ChronoUnit.YEARS.between(profile.getBirthday(), LocalDate.now()))); - dto.setGender(profile.getGender()); - dto.setAbout(profile.getAbout()); - - return dto; - } -} diff --git a/src/ru/charm/back/mapper/ProfileToProfileGetDtoMapper.java b/src/ru/charm/back/mapper/ProfileToProfileGetDtoMapper.java new file mode 100644 index 0000000..b8453b8 --- /dev/null +++ b/src/ru/charm/back/mapper/ProfileToProfileGetDtoMapper.java @@ -0,0 +1,41 @@ +package ru.charm.back.mapper; + + +import ru.charm.back.dto.ProfileGetDto; +import ru.charm.back.model.Profile; + +import java.time.LocalDate; +import java.time.temporal.ChronoUnit; + +public class ProfileToProfileGetDtoMapper implements Mapper { + + private static final ProfileToProfileGetDtoMapper INSTANCE = new ProfileToProfileGetDtoMapper(); + + private ProfileToProfileGetDtoMapper() { + } + + public static ProfileToProfileGetDtoMapper getInstance() { + return INSTANCE; + } + + @Override + public ProfileGetDto map(Profile profile) { + return map(profile, new ProfileGetDto()); + } + + @Override + public ProfileGetDto map(Profile profile, ProfileGetDto dto) { + dto.setId(profile.getId()); + dto.setEmail(profile.getEmail()); + dto.setName(profile.getName()); + dto.setSurname(profile.getSurname()); + dto.setBirthDate(profile.getBirthDate()); + if (profile.getBirthDate() != null) { + dto.setAge(Math.toIntExact(ChronoUnit.YEARS.between(profile.getBirthDate(), LocalDate.now()))); + } + dto.setAbout(profile.getAbout()); + dto.setGender(profile.getGender()); + dto.setStatus(profile.getStatus()); + return dto; + } +} diff --git a/src/ru/charm/back/mapper/ProfileUpdateDtoToProfileMapper.java b/src/ru/charm/back/mapper/ProfileUpdateDtoToProfileMapper.java new file mode 100644 index 0000000..acd697b --- /dev/null +++ b/src/ru/charm/back/mapper/ProfileUpdateDtoToProfileMapper.java @@ -0,0 +1,49 @@ +package ru.charm.back.mapper; + + +import ru.charm.back.dto.ProfileUpdateDto; +import ru.charm.back.model.Profile; + +public class ProfileUpdateDtoToProfileMapper implements Mapper { + + private static final ProfileUpdateDtoToProfileMapper INSTANCE = new ProfileUpdateDtoToProfileMapper(); + + private ProfileUpdateDtoToProfileMapper() { + } + + public static ProfileUpdateDtoToProfileMapper getInstance() { + return INSTANCE; + } + + @Override + public Profile map(ProfileUpdateDto dto) { + return map(dto, new Profile()); + } + + @Override + public Profile map(ProfileUpdateDto dto, Profile profile) { + profile.setId(dto.getId()); + if (dto.getEmail() != null) { + profile.setEmail(dto.getEmail()); + } + if (dto.getName() != null) { + profile.setName(dto.getName()); + } + if (dto.getSurname() != null) { + profile.setSurname(dto.getSurname()); + } + if (dto.getBirthDate() != null) { + profile.setBirthDate(dto.getBirthDate()); + } + if (dto.getAbout() != null) { + profile.setAbout(dto.getAbout()); + } + if (dto.getGender() != null) { + profile.setGender(dto.getGender()); + } + if (dto.getStatus() != null) { + profile.setStatus(dto.getStatus()); + } + return profile; + } +} diff --git a/src/ru/charm/back/mapper/RegistrationDtoToProfileMapper.java b/src/ru/charm/back/mapper/RegistrationDtoToProfileMapper.java new file mode 100644 index 0000000..5de88fe --- /dev/null +++ b/src/ru/charm/back/mapper/RegistrationDtoToProfileMapper.java @@ -0,0 +1,30 @@ +package ru.charm.back.mapper; + +import ru.charm.back.dto.RegistrationDto; +import ru.charm.back.model.Profile; +import ru.charm.back.model.Status; + +public class RegistrationDtoToProfileMapper implements Mapper { + + private static final RegistrationDtoToProfileMapper INSTANCE = new RegistrationDtoToProfileMapper(); + + private RegistrationDtoToProfileMapper() { + } + + public static RegistrationDtoToProfileMapper getInstance() { + return INSTANCE; + } + + @Override + public Profile map(RegistrationDto dto) { + return map(dto, new Profile()); + } + + @Override + public Profile map(RegistrationDto dto, Profile profile) { + profile.setEmail(dto.getEmail()); + profile.setPassword(dto.getPassword()); + profile.setStatus(Status.INACTIVE); + return profile; + } +} diff --git a/src/ru/charm/back/mapper/RequestToProfileUpdateDtoMapper.java b/src/ru/charm/back/mapper/RequestToProfileUpdateDtoMapper.java new file mode 100644 index 0000000..3ae8a3f --- /dev/null +++ b/src/ru/charm/back/mapper/RequestToProfileUpdateDtoMapper.java @@ -0,0 +1,55 @@ +package ru.charm.back.mapper; + +import jakarta.servlet.http.HttpServletRequest; +import ru.charm.back.dto.ProfileUpdateDto; +import ru.charm.back.model.Gender; +import ru.charm.back.model.Status; + +import java.time.LocalDate; + +import static ru.charm.back.utils.StringUtils.isBlank; + +public class RequestToProfileUpdateDtoMapper implements Mapper { + + private static final RequestToProfileUpdateDtoMapper INSTANCE = new RequestToProfileUpdateDtoMapper(); + + private RequestToProfileUpdateDtoMapper() { + } + + public static RequestToProfileUpdateDtoMapper getInstance() { + return INSTANCE; + } + + @Override + public ProfileUpdateDto map(HttpServletRequest req) { + return map(req, new ProfileUpdateDto()); + } + + @Override + public ProfileUpdateDto map(HttpServletRequest req, ProfileUpdateDto dto) { + String id = req.getParameter("id"); + if (!isBlank(id)) { + dto.setId(Long.parseLong(id)); + } + String email = req.getParameter("email"); + if (!isBlank(email)) { + dto.setEmail(email); + } + dto.setName(req.getParameter("name")); + dto.setSurname(req.getParameter("surname")); + String birthDate = req.getParameter("birthDate"); + if (!isBlank(birthDate)) { + dto.setBirthDate(LocalDate.parse(birthDate)); + } + dto.setAbout(req.getParameter("about")); + String gender = req.getParameter("gender"); + if (!isBlank(gender)) { + dto.setGender(Gender.valueOf(gender)); + } + String status = req.getParameter("status"); + if (!isBlank(status)) { + dto.setStatus(Status.valueOf(status)); + } + return dto; + } +} diff --git a/src/ru/charm/back/mapper/RequestToRegistrationDtoMapper.java b/src/ru/charm/back/mapper/RequestToRegistrationDtoMapper.java new file mode 100644 index 0000000..6d2aae8 --- /dev/null +++ b/src/ru/charm/back/mapper/RequestToRegistrationDtoMapper.java @@ -0,0 +1,28 @@ +package ru.charm.back.mapper; + +import jakarta.servlet.http.HttpServletRequest; +import ru.charm.back.dto.RegistrationDto; + +public class RequestToRegistrationDtoMapper implements Mapper { + + private static final RequestToRegistrationDtoMapper INSTANCE = new RequestToRegistrationDtoMapper(); + + private RequestToRegistrationDtoMapper() { + } + + public static RequestToRegistrationDtoMapper getInstance() { + return INSTANCE; + } + + @Override + public RegistrationDto map(HttpServletRequest req) { + return map(req, new RegistrationDto()); + } + + @Override + public RegistrationDto map(HttpServletRequest req, RegistrationDto dto) { + dto.setEmail(req.getParameter("email")); + dto.setPassword(req.getParameter("password")); + return dto; + } +} diff --git a/src/ru/charm/back/model/Profile.java b/src/ru/charm/back/model/Profile.java index 77d6a93..588bfe3 100644 --- a/src/ru/charm/back/model/Profile.java +++ b/src/ru/charm/back/model/Profile.java @@ -5,19 +5,13 @@ import java.time.LocalDate; public class Profile { private Long id; private String email; + private String password; private String name; private String surname; + private LocalDate birthDate; private String about; private Gender gender; - private LocalDate birthday; - - public LocalDate getBirthday() { - return birthday; - } - - public void setBirthday(LocalDate birthday) { - this.birthday = birthday; - } + private Status status; public Long getId() { return id; @@ -35,6 +29,14 @@ public class Profile { this.email = email; } + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + public String getName() { return name; } @@ -51,6 +53,14 @@ public class Profile { this.surname = surname; } + public LocalDate getBirthDate() { + return birthDate; + } + + public void setBirthDate(LocalDate birthDate) { + this.birthDate = birthDate; + } + public String getAbout() { return about; } @@ -67,14 +77,11 @@ public class Profile { this.gender = gender; } - @Override - public String toString() { - return "Profile{" + - "id=" + id + - ", email='" + email + '\'' + - ", name='" + name + '\'' + - ", surname='" + surname + '\'' + - ", about='" + about + '\'' + - '}'; + public Status getStatus() { + return status; } -} + + public void setStatus(Status status) { + this.status = status; + } +} \ No newline at end of file diff --git a/src/ru/charm/back/model/Status.java b/src/ru/charm/back/model/Status.java new file mode 100644 index 0000000..0b369c7 --- /dev/null +++ b/src/ru/charm/back/model/Status.java @@ -0,0 +1,5 @@ +package ru.charm.back.model; + +public enum Status { + ACTIVE, INACTIVE +} diff --git a/src/ru/charm/back/model/exception/DuplicateEmailException.java b/src/ru/charm/back/model/exception/DuplicateEmailException.java new file mode 100644 index 0000000..b1f52c4 --- /dev/null +++ b/src/ru/charm/back/model/exception/DuplicateEmailException.java @@ -0,0 +1,4 @@ +package ru.charm.back.model.exception; + +public class DuplicateEmailException extends RuntimeException { +} diff --git a/src/ru/charm/back/service/ProfileService.java b/src/ru/charm/back/service/ProfileService.java index a177d95..389bdfd 100644 --- a/src/ru/charm/back/service/ProfileService.java +++ b/src/ru/charm/back/service/ProfileService.java @@ -2,47 +2,68 @@ package ru.charm.back.service; import ru.charm.back.dao.ProfileDao; import ru.charm.back.dto.ProfileGetDto; -import ru.charm.back.mapper.ProfileGetDtoMapper; -import ru.charm.back.model.Profile; +import ru.charm.back.dto.ProfileUpdateDto; +import ru.charm.back.dto.RegistrationDto; +import ru.charm.back.mapper.ProfileToProfileGetDtoMapper; +import ru.charm.back.mapper.ProfileUpdateDtoToProfileMapper; +import ru.charm.back.mapper.RegistrationDtoToProfileMapper; +import ru.charm.back.model.exception.DuplicateEmailException; import java.util.List; +import java.util.Objects; import java.util.Optional; +import java.util.Set; public class ProfileService { + private static final ProfileService INSTANCE = new ProfileService(); + private final ProfileDao dao = ProfileDao.getInstance(); - private final ProfileGetDtoMapper profileGetDtoMapper = ProfileGetDtoMapper.getInstance(); + private final ProfileToProfileGetDtoMapper profileToProfileGetDtoMapper = ProfileToProfileGetDtoMapper.getInstance(); - public static ProfileService getInstance() { - return INSTANCE; + private final ProfileUpdateDtoToProfileMapper profileUpdateDtoToProfileMapper = ProfileUpdateDtoToProfileMapper.getInstance(); + + private final RegistrationDtoToProfileMapper registrationDtoToProfileMapper = RegistrationDtoToProfileMapper.getInstance(); + + private ProfileService() { } - public Profile save(Profile profile) { - return dao.save(profile); + public static ProfileService getInstance() { + return INSTANCE; + } + + public Long save(RegistrationDto dto) { + return dao.save(registrationDtoToProfileMapper.map(dto)).getId(); } public Optional findById(Long id) { - if (id == null) { - return Optional.empty(); - } - - return dao.findById(id).map(profileGetDtoMapper::map); - } - - public Boolean delete(Long id) { - if (id == null) { - return false; - } - - return dao.delete(id); - } - - public void update(Profile profile) { - dao.update(profile); + return dao.findById(id).map(profileToProfileGetDtoMapper::map); } public List findAll() { - return dao.findAll().stream().map(profileGetDtoMapper::map).toList(); + return dao.findAll().stream().map(profileToProfileGetDtoMapper::map).toList(); } -} + + public void update(ProfileUpdateDto dto) { + dao.findById(dto.getId()) + .ifPresent(profile -> { + checkEmail(profile.getEmail(), dto.getEmail()); + dao.update(profileUpdateDtoToProfileMapper.map(dto, profile)); + } + ); + } + + private void checkEmail(String oldEmail, String newEmail) { + if (newEmail == null) return; + Set emails = dao.getAllEmails(); + if (!Objects.equals(oldEmail, newEmail) && + emails.contains(newEmail)) { + throw new DuplicateEmailException(); + } + } + + public boolean delete(Long id) { + return dao.delete(id); + } +} \ No newline at end of file diff --git a/src/ru/charm/back/utils/StringUtils.java b/src/ru/charm/back/utils/StringUtils.java new file mode 100644 index 0000000..13713ae --- /dev/null +++ b/src/ru/charm/back/utils/StringUtils.java @@ -0,0 +1,7 @@ +package ru.charm.back.utils; + +public class StringUtils { + public static boolean isBlank(String str) { + return str == null || str.isBlank(); + } +}