holy fuck.

This commit is contained in:
Laurent
2025-03-21 17:57:07 +01:00
parent 02ce43e7b7
commit be5e86c10d
49 changed files with 475 additions and 517 deletions

View File

@@ -8,6 +8,7 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.annotation.web.configurers.LogoutConfigurer; import org.springframework.security.config.annotation.web.configurers.LogoutConfigurer;
import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.SecurityFilterChain;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter; import org.springframework.web.filter.CorsFilter;
@@ -16,6 +17,7 @@ import java.util.Arrays;
@Configuration @Configuration
@EnableWebSecurity @EnableWebSecurity
@EnableTransactionManagement
public class AppSecurity { public class AppSecurity {
private final AppConfigurations conf; private final AppConfigurations conf;
@@ -29,7 +31,8 @@ public class AppSecurity {
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http return http
.cors(cors -> {}) .cors(cors -> {
})
.csrf(AbstractHttpConfigurer::disable) .csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests((requests) -> requests .authorizeHttpRequests((requests) -> requests
.requestMatchers("/**").permitAll() .requestMatchers("/**").permitAll()

View File

@@ -1,9 +1,6 @@
package be.naaturel.letsmeet.configurations; package be.naaturel.letsmeet.configurations;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

View File

@@ -4,8 +4,6 @@ import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.HandlerInterceptor;
import java.io.Console;
public class Interceptor implements HandlerInterceptor { public class Interceptor implements HandlerInterceptor {
// Request is intercepted by this method before reaching the Controller // Request is intercepted by this method before reaching the Controller

View File

@@ -0,0 +1,20 @@
package be.naaturel.letsmeet.core.models;
public class Attendance {
private EventDate date;
private Attendee attendee;
public Attendance(EventDate date, Attendee attendee) {
this.date = date;
this.attendee = attendee;
}
public Attendee getAttendee() {
return attendee;
}
public EventDate getDate() {
return date;
}
}

View File

@@ -1,38 +1,19 @@
package be.naaturel.letsmeet.core.models; package be.naaturel.letsmeet.core.models;
import java.util.HashSet;
import java.util.Objects; import java.util.Objects;
import java.util.Set;
public class Attendee { public class Attendee {
private String name; private String name;
private Set<EventDate> dates;
public Attendee(String name) { public Attendee(String name) {
this(name, new HashSet<>());
}
public Attendee(String name, Set<EventDate> dates){
this.name = name; this.name = name;
this.dates = dates;
} }
public String getName() { public String getName() {
return name; return name;
} }
public Set<EventDate> getDates() {
return new HashSet<>(this.dates);
}
public void replaceDate(EventDate oldDate, EventDate newDate){
dates.remove(oldDate);
dates.add(newDate);
}
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (this == obj) return true; if (this == obj) return true;

View File

@@ -1,30 +1,24 @@
package be.naaturel.letsmeet.core.models; package be.naaturel.letsmeet.core.models;
import java.util.*; import java.util.Set;
public class Event { public class Event {
private String name; private String name;
private Set<Attendee> attendees;
public Event(String name, Set<Attendee> attendees){ private Set<Attendance> attendances;
public Event(String name, Set<Attendance> attendances) {
this.name = name; this.name = name;
this.attendees = attendees; this.attendances = attendances;
} }
public String getName() { public String getName() {
return name; return name;
} }
public Set<Attendee> getAttendees(){ public Set<Attendance> getAttendances() {
return new HashSet<>(this.attendees); return this.attendances;
} }
public Set<EventDate> getDates() {
Set<EventDate> dates = new HashSet<>();
for (Attendee p : this.attendees) {
dates.addAll(p.getDates());
}
return dates;
}
} }

View File

@@ -1,7 +1,5 @@
package be.naaturel.letsmeet.core.models; package be.naaturel.letsmeet.core.models;
import java.util.Objects;
public class EventDate { public class EventDate {
private long timeStamp; private long timeStamp;

View File

@@ -0,0 +1,34 @@
package be.naaturel.letsmeet.dto.database;
import jakarta.persistence.*;
import java.util.Objects;
@Entity(name = "Attendances")
public class AttendanceEntity {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
public String id;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "event_date_id", nullable = false)
public EventDateEntity date;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "attendee_id", nullable = false)
public AttendeeEntity attendee;
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
AttendanceEntity a = (AttendanceEntity) obj;
return a.date.timeStamp == ((AttendanceEntity) obj).date.timeStamp &&
a.attendee.name == ((AttendanceEntity) obj).attendee.name;
}
@Override
public int hashCode() {
return Objects.hash(date, attendee);
}
}

View File

@@ -2,7 +2,7 @@ package be.naaturel.letsmeet.dto.database;
import jakarta.persistence.*; import jakarta.persistence.*;
import java.util.Set; import java.util.Objects;
@Entity(name = "Attendees") @Entity(name = "Attendees")
public class AttendeeEntity { public class AttendeeEntity {
@@ -14,12 +14,17 @@ public class AttendeeEntity {
@Column @Column
public String name; public String name;
@ManyToMany(cascade = {CascadeType.ALL}) @Override
@JoinTable public boolean equals(Object obj) {
public Set<EventDateEntity> dates; if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
AttendeeEntity a = (AttendeeEntity) obj;
return Objects.equals(name, a.name);
}
@ManyToOne @Override
@JoinColumn(nullable=true) public int hashCode() {
public EventEntity event; return Objects.hash(name);
}
} }

View File

@@ -3,7 +3,6 @@ package be.naaturel.letsmeet.dto.database;
import jakarta.persistence.*; import jakarta.persistence.*;
import java.util.Objects; import java.util.Objects;
import java.util.Set;
@Entity(name = "Dates") @Entity(name = "Dates")
@Table(uniqueConstraints = { @Table(uniqueConstraints = {
@@ -18,13 +17,6 @@ public class EventDateEntity {
@Column @Column
public long timeStamp; public long timeStamp;
@ManyToOne
@JoinColumn(nullable=true)
public EventEntity event;
@ManyToMany(mappedBy = "dates")
public Set<AttendeeEntity> attendees;
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (this == obj) return true; if (this == obj) return true;

View File

@@ -2,7 +2,7 @@ package be.naaturel.letsmeet.dto.database;
import jakarta.persistence.*; import jakarta.persistence.*;
import java.util.*; import java.util.Set;
@Entity(name = "Events") @Entity(name = "Events")
public class EventEntity { public class EventEntity {
@@ -17,36 +17,9 @@ public class EventEntity {
@Column(unique = true) @Column(unique = true)
public String token; public String token;
@Column @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@OneToMany(targetEntity=EventDateEntity.class, cascade=CascadeType.ALL, mappedBy="event") @JoinColumn(name = "event_id")
public Set<EventDateEntity> dates; public Set<AttendanceEntity> attendances;
@Column
@OneToMany(targetEntity=AttendeeEntity.class, cascade=CascadeType.ALL, mappedBy="event")
public Set<AttendeeEntity> attendees;
public void linkDates(){
for (EventDateEntity date : this.dates) {
date.event = this;
}
}
public void linkAttendees(){
for (AttendeeEntity attendee : this.attendees) {
attendee.event = this;
}
}
public void removeDuplicatedDates(){
for (EventDateEntity ede: dates) {
for (AttendeeEntity pe : attendees) {
if(pe.dates.contains(ede)){
pe.dates.remove(ede);
pe.dates.add(ede);
}
}
}
}
} }

View File

@@ -1,42 +0,0 @@
package be.naaturel.letsmeet.dto.database.factories;
import be.naaturel.letsmeet.core.helpers.TokenGenerator;
import be.naaturel.letsmeet.dto.database.EventDateEntity;
import be.naaturel.letsmeet.dto.database.EventEntity;
import be.naaturel.letsmeet.dto.database.AttendeeEntity;
import java.util.HashSet;
import java.util.Set;
public class DatabasePropsFactory {
public static EventEntity createEvent(String name, Set<AttendeeEntity> attendees){
EventEntity entity = new EventEntity();
entity.name = name;
entity.token = TokenGenerator.generate();
entity.attendees = attendees;
entity.dates = new HashSet<>();
for (AttendeeEntity pe : entity.attendees) {
entity.dates.addAll(pe.dates);
}
entity.linkDates();
entity.linkAttendees();
entity.removeDuplicatedDates();
return entity;
}
public static AttendeeEntity createAttendee(String name, Set<EventDateEntity> dates){
AttendeeEntity entity = new AttendeeEntity();
entity.name = name;
entity.dates = dates;
return entity;
}
public static EventDateEntity createDate(long timestamp){
EventDateEntity entity = new EventDateEntity();
entity.timeStamp = timestamp;
return entity;
}
}

View File

@@ -0,0 +1,21 @@
package be.naaturel.letsmeet.dto.httpRequest;
import java.util.Objects;
public class AttendanceDTO {
public EventDateDTO date;
public AttendeeDTO attendee;
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
AttendanceDTO a = (AttendanceDTO) obj;
return a.date.timestamp == ((AttendanceDTO) obj).date.timestamp &&
a.attendee.name == ((AttendanceDTO) obj).attendee.name;
}
@Override
public int hashCode() {
return Objects.hash(date, attendee);
}
}

View File

@@ -1,7 +1,5 @@
package be.naaturel.letsmeet.dto.httpRequest; package be.naaturel.letsmeet.dto.httpRequest;
import java.util.Set;
public class AttendeeDTO { public class AttendeeDTO {
public String name; public String name;

View File

@@ -1,12 +1,11 @@
package be.naaturel.letsmeet.dto.httpRequest; package be.naaturel.letsmeet.dto.httpRequest;
import java.util.Map;
import java.util.Set; import java.util.Set;
public class EventDTO { public class EventDTO {
public String name; public String name;
public String token; public String token;
public Map<String, Set<AttendeeDTO>> dates; public Set<AttendanceDTO> attendances;
} }

View File

@@ -0,0 +1,51 @@
package be.naaturel.letsmeet.mappers.database;
import be.naaturel.letsmeet.core.models.Attendance;
import be.naaturel.letsmeet.core.models.Attendee;
import be.naaturel.letsmeet.core.models.EventDate;
import be.naaturel.letsmeet.dto.database.AttendanceEntity;
import be.naaturel.letsmeet.dto.database.AttendeeEntity;
import be.naaturel.letsmeet.dto.database.EventDateEntity;
import be.naaturel.letsmeet.mappers.Mapper;
import java.util.Collection;
import java.util.function.Supplier;
public class AttendanceMapper implements Mapper<Attendance, AttendanceEntity> {
private final Mapper<Attendee, AttendeeEntity> attendeeMapper;
private final Mapper<EventDate, EventDateEntity> dateMapper;
public AttendanceMapper() {
this.attendeeMapper = new AttendeeMapper();
this.dateMapper = new EventDateMapper();
}
@Override
public AttendanceEntity toEntity(Attendance d) {
AttendanceEntity dto = new AttendanceEntity();
dto.attendee = attendeeMapper.toEntity(d.getAttendee());
dto.date = dateMapper.toEntity(d.getDate());
return dto;
}
@Override
public Attendance toModel(AttendanceEntity d) {
Attendee attendee = attendeeMapper.toModel(d.attendee);
EventDate date = dateMapper.toModel(d.date);
return new Attendance(date, attendee);
}
@Override
public <C extends Collection<AttendanceEntity>> C toEntities(Collection<Attendance> attendances, Supplier<C> collectionSupplier) {
C result = collectionSupplier.get();
attendances.forEach(p -> result.add(toEntity(p)));
return result;
}
@Override
public <C extends Collection<Attendance>> C toModels(Collection<AttendanceEntity> attendances, Supplier<C> collectionSupplier) {
C result = collectionSupplier.get();
attendances.forEach(p -> result.add(toModel(p)));
return result;
}
}

View File

@@ -1,14 +1,12 @@
package be.naaturel.letsmeet.mappers.database; package be.naaturel.letsmeet.mappers.database;
import be.naaturel.letsmeet.dto.database.EventDateEntity;
import be.naaturel.letsmeet.dto.database.AttendeeEntity;
import be.naaturel.letsmeet.dto.database.factories.DatabasePropsFactory;
import be.naaturel.letsmeet.mappers.Mapper;
import be.naaturel.letsmeet.core.models.EventDate;
import be.naaturel.letsmeet.core.models.Attendee; import be.naaturel.letsmeet.core.models.Attendee;
import be.naaturel.letsmeet.core.models.EventDate;
import be.naaturel.letsmeet.dto.database.AttendeeEntity;
import be.naaturel.letsmeet.dto.database.EventDateEntity;
import be.naaturel.letsmeet.mappers.Mapper;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet;
import java.util.function.Supplier; import java.util.function.Supplier;
public class AttendeeMapper implements Mapper<Attendee, AttendeeEntity> { public class AttendeeMapper implements Mapper<Attendee, AttendeeEntity> {
@@ -21,13 +19,16 @@ public class AttendeeMapper implements Mapper<Attendee, AttendeeEntity> {
} }
@Override @Override
public AttendeeEntity toEntity(Attendee d) { public AttendeeEntity toEntity(Attendee a) {
return DatabasePropsFactory.createAttendee(d.getName(), dateMapper.toEntities(d.getDates(), HashSet::new)); //return DatabasePropsFactory.createAttendee(d.getName(), dateMapper.toEntities(d.getDates(), HashSet::new));
AttendeeEntity ae = new AttendeeEntity();
ae.name = a.getName();
return ae;
} }
@Override @Override
public Attendee toModel(AttendeeEntity d) { public Attendee toModel(AttendeeEntity d) {
return new Attendee(d.name, dateMapper.toModels(d.dates, HashSet::new)); return new Attendee(d.name);
} }
@Override @Override

View File

@@ -1,9 +1,8 @@
package be.naaturel.letsmeet.mappers.database; package be.naaturel.letsmeet.mappers.database;
import be.naaturel.letsmeet.dto.database.EventDateEntity;
import be.naaturel.letsmeet.dto.database.factories.DatabasePropsFactory;
import be.naaturel.letsmeet.mappers.Mapper;
import be.naaturel.letsmeet.core.models.EventDate; import be.naaturel.letsmeet.core.models.EventDate;
import be.naaturel.letsmeet.dto.database.EventDateEntity;
import be.naaturel.letsmeet.mappers.Mapper;
import java.util.Collection; import java.util.Collection;
import java.util.function.Supplier; import java.util.function.Supplier;
@@ -13,7 +12,9 @@ public class EventDateMapper implements Mapper<EventDate, EventDateEntity> {
@Override @Override
public EventDateEntity toEntity(EventDate d) { public EventDateEntity toEntity(EventDate d) {
return DatabasePropsFactory.createDate(d.getTimeStamp()); EventDateEntity ede = new EventDateEntity();
ede.timeStamp = d.getTimeStamp();
return ede;
} }
@Override @Override

View File

@@ -1,33 +1,41 @@
package be.naaturel.letsmeet.mappers.database; package be.naaturel.letsmeet.mappers.database;
import be.naaturel.letsmeet.dto.database.EventEntity; import be.naaturel.letsmeet.core.helpers.TokenGenerator;
import be.naaturel.letsmeet.dto.database.AttendeeEntity; import be.naaturel.letsmeet.core.models.Attendance;
import be.naaturel.letsmeet.dto.database.factories.DatabasePropsFactory;
import be.naaturel.letsmeet.mappers.Mapper;
import be.naaturel.letsmeet.core.models.Event; import be.naaturel.letsmeet.core.models.Event;
import be.naaturel.letsmeet.core.models.Attendee; import be.naaturel.letsmeet.dto.database.AttendanceEntity;
import be.naaturel.letsmeet.dto.database.EventEntity;
import be.naaturel.letsmeet.mappers.Mapper;
import java.util.*; import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Supplier; import java.util.function.Supplier;
public class EventMapper implements Mapper<Event, EventEntity> { public class EventMapper implements Mapper<Event, EventEntity> {
private final Mapper<Attendee, AttendeeEntity> attendeeMapper; private final Mapper<Attendance, AttendanceEntity> attendanceMapper;
public EventMapper() { public EventMapper() {
this.attendeeMapper = new AttendeeMapper(); this.attendanceMapper = new AttendanceMapper();
} }
@Override @Override
public EventEntity toEntity(Event event) { public EventEntity toEntity(Event event) {
return DatabasePropsFactory.createEvent(event.getName(), attendeeMapper.toEntities(event.getAttendees(), HashSet::new)); EventEntity entity = new EventEntity();
entity.name = event.getName();
entity.token = TokenGenerator.generate();
entity.attendances = attendanceMapper.toEntities(event.getAttendances(), HashSet::new);
return entity;
} }
@Override @Override
public Event toModel(EventEntity eventEntity) { public Event toModel(EventEntity eventEntity) {
return new Event(eventEntity.name, attendeeMapper.toModels(eventEntity.attendees, HashSet::new)); Set<Attendance> attendances = attendanceMapper.toModels(eventEntity.attendances, HashSet::new);
return new Event(eventEntity.name, attendances);
} }
@Override @Override
public <C extends Collection<EventEntity>> C toEntities(Collection<Event> events, Supplier<C> collectionSupplier) { public <C extends Collection<EventEntity>> C toEntities(Collection<Event> events, Supplier<C> collectionSupplier) {
C result = collectionSupplier.get(); C result = collectionSupplier.get();

View File

@@ -0,0 +1,52 @@
package be.naaturel.letsmeet.mappers.requests;
import be.naaturel.letsmeet.core.models.Attendance;
import be.naaturel.letsmeet.core.models.Attendee;
import be.naaturel.letsmeet.core.models.EventDate;
import be.naaturel.letsmeet.dto.httpRequest.AttendanceDTO;
import be.naaturel.letsmeet.dto.httpRequest.AttendeeDTO;
import be.naaturel.letsmeet.dto.httpRequest.EventDateDTO;
import be.naaturel.letsmeet.mappers.Mapper;
import java.util.Collection;
import java.util.function.Supplier;
public class AttendanceDTOMapper implements Mapper<Attendance, AttendanceDTO> {
private final Mapper<Attendee, AttendeeDTO> attendeeMapper;
private final Mapper<EventDate, EventDateDTO> dateMapper;
public AttendanceDTOMapper() {
this.attendeeMapper = new AttendeeDTOMapper();
this.dateMapper = new EventDateDTOMapper();
}
@Override
public AttendanceDTO toEntity(Attendance d) {
AttendanceDTO dto = new AttendanceDTO();
dto.attendee = attendeeMapper.toEntity(d.getAttendee());
dto.date = dateMapper.toEntity(d.getDate());
return dto;
}
@Override
public Attendance toModel(AttendanceDTO d) {
Attendee attendee = attendeeMapper.toModel(d.attendee);
EventDate date = dateMapper.toModel(d.date);
return new Attendance(date, attendee);
}
@Override
public <C extends Collection<AttendanceDTO>> C toEntities(Collection<Attendance> attendances, Supplier<C> collectionSupplier) {
C result = collectionSupplier.get();
attendances.forEach(p -> result.add(toEntity(p)));
return result;
}
@Override
public <C extends Collection<Attendance>> C toModels(Collection<AttendanceDTO> attendances, Supplier<C> collectionSupplier) {
C result = collectionSupplier.get();
attendances.forEach(p -> result.add(toModel(p)));
return result;
}
}

View File

@@ -1,13 +1,12 @@
package be.naaturel.letsmeet.mappers.requests; package be.naaturel.letsmeet.mappers.requests;
import be.naaturel.letsmeet.dto.httpRequest.EventDateDTO;
import be.naaturel.letsmeet.dto.httpRequest.AttendeeDTO;
import be.naaturel.letsmeet.mappers.Mapper;
import be.naaturel.letsmeet.core.models.EventDate;
import be.naaturel.letsmeet.core.models.Attendee; import be.naaturel.letsmeet.core.models.Attendee;
import be.naaturel.letsmeet.core.models.EventDate;
import be.naaturel.letsmeet.dto.httpRequest.AttendeeDTO;
import be.naaturel.letsmeet.dto.httpRequest.EventDateDTO;
import be.naaturel.letsmeet.mappers.Mapper;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet;
import java.util.function.Supplier; import java.util.function.Supplier;
public class AttendeeDTOMapper implements Mapper<Attendee, AttendeeDTO> { public class AttendeeDTOMapper implements Mapper<Attendee, AttendeeDTO> {
@@ -27,7 +26,7 @@ public class AttendeeDTOMapper implements Mapper<Attendee, AttendeeDTO> {
@Override @Override
public Attendee toModel(AttendeeDTO d) { public Attendee toModel(AttendeeDTO d) {
return null; return new Attendee(d.name);
} }
@Override @Override

View File

@@ -1,58 +1,36 @@
package be.naaturel.letsmeet.mappers.requests; package be.naaturel.letsmeet.mappers.requests;
import be.naaturel.letsmeet.core.models.EventDate; import be.naaturel.letsmeet.core.models.Attendance;
import be.naaturel.letsmeet.dto.httpRequest.EventDTO;
import be.naaturel.letsmeet.dto.httpRequest.AttendeeDTO;
import be.naaturel.letsmeet.dto.httpRequest.EventDateDTO;
import be.naaturel.letsmeet.mappers.Mapper;
import be.naaturel.letsmeet.core.models.Event; import be.naaturel.letsmeet.core.models.Event;
import be.naaturel.letsmeet.core.models.Attendee; import be.naaturel.letsmeet.dto.httpRequest.AttendanceDTO;
import be.naaturel.letsmeet.dto.httpRequest.EventDTO;
import be.naaturel.letsmeet.mappers.Mapper;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.function.Supplier; import java.util.function.Supplier;
public class EventDTOMapper implements Mapper<Event, EventDTO> { public class EventDTOMapper implements Mapper<Event, EventDTO> {
private final Mapper<Attendee, AttendeeDTO> attendeeMapper = new AttendeeDTOMapper(); private final Mapper<Attendance, AttendanceDTO> attendanceMapper;
private final Mapper<EventDate, EventDateDTO> dateMapper = new EventDateDTOMapper();
public EventDTOMapper() {
this.attendanceMapper = new AttendanceDTOMapper();
}
@Override @Override
public EventDTO toEntity(Event event) { public EventDTO toEntity(Event event) {
EventDTO eventDTO = new EventDTO(); EventDTO eventDTO = new EventDTO();
eventDTO.name = event.getName(); eventDTO.name = event.getName();
//eventDTO.dates = attendeeMapper.toEntities(event.getAttendees(), HashSet::new); eventDTO.attendances = attendanceMapper.toEntities(event.getAttendances(), HashSet::new);
//TODO : MUST BE CLEANED
eventDTO.dates = new HashMap<>();
event.getAttendees().forEach(a -> {
a.getDates().forEach(d -> {
EventDateDTO dtoD = dateMapper.toEntity(d);
AttendeeDTO dtoA = attendeeMapper.toEntity(a);
String key = String.valueOf(d.getTimeStamp());
if(eventDTO.dates.containsKey(key)){
eventDTO.dates.get(key).add(dtoA);
} else {
Set<AttendeeDTO> s = new HashSet<>();
s.add(dtoA);
eventDTO.dates.put(key, s);
}
});
});
return eventDTO; return eventDTO;
} }
@Override @Override
public Event toModel(EventDTO dto) { public Event toModel(EventDTO dto) {
//return new Event(dto.name, attendeeMapper.toModels(dto.dates, HashSet::new)); Set<Attendance> attendances = attendanceMapper.toModels(dto.attendances, HashSet::new);
Set<Attendee> set = new HashSet<>(); return new Event(dto.name, attendances);
for (String key : dto.dates.keySet()) {
set.addAll(attendeeMapper.toModels(dto.dates.get(key), HashSet::new));
}
return new Event(dto.name, set);
} }
@Override @Override

View File

@@ -1,8 +1,8 @@
package be.naaturel.letsmeet.mappers.requests; package be.naaturel.letsmeet.mappers.requests;
import be.naaturel.letsmeet.core.models.EventDate;
import be.naaturel.letsmeet.dto.httpRequest.EventDateDTO; import be.naaturel.letsmeet.dto.httpRequest.EventDateDTO;
import be.naaturel.letsmeet.mappers.Mapper; import be.naaturel.letsmeet.mappers.Mapper;
import be.naaturel.letsmeet.core.models.EventDate;
import java.util.Collection; import java.util.Collection;
import java.util.function.Supplier; import java.util.function.Supplier;

View File

@@ -1,15 +1,88 @@
package be.naaturel.letsmeet.repositories; package be.naaturel.letsmeet.repositories;
import be.naaturel.letsmeet.core.models.Event;
import be.naaturel.letsmeet.dto.database.AttendanceEntity;
import be.naaturel.letsmeet.dto.database.AttendeeEntity;
import be.naaturel.letsmeet.dto.database.EventDateEntity;
import be.naaturel.letsmeet.dto.database.EventEntity; import be.naaturel.letsmeet.dto.database.EventEntity;
import org.springframework.data.jpa.repository.JpaRepository; import be.naaturel.letsmeet.mappers.Mapper;
import org.springframework.data.jpa.repository.Query; import be.naaturel.letsmeet.mappers.database.EventMapper;
import org.springframework.data.repository.query.Param; import be.naaturel.letsmeet.repositories.interfaces.AttendanceEntityRepo;
import be.naaturel.letsmeet.repositories.interfaces.AttendeeEntityRepo;
import be.naaturel.letsmeet.repositories.interfaces.EventDateEntityRepo;
import be.naaturel.letsmeet.repositories.interfaces.EventEntityRepo;
import jakarta.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List; import java.util.HashMap;
import java.util.Map;
@Component
public class EventRepo {
private final EventEntityRepo eventRepo;
private final AttendeeEntityRepo attendeeRepo;
private final EventDateEntityRepo dateRepo;
private final AttendanceEntityRepo attendanceRepo;
private final Mapper<Event, EventEntity> mapper;
@Autowired
public EventRepo(EventEntityRepo eventRepo, AttendeeEntityRepo attendeeRepo,
EventDateEntityRepo dateRepo, AttendanceEntityRepo attendanceRepo) {
this.eventRepo = eventRepo;
this.attendeeRepo = attendeeRepo;
this.dateRepo = dateRepo;
this.attendanceRepo = attendanceRepo;
this.mapper = new EventMapper();
}
@Transactional
public String save(Event e) {
//Hacky way to avoid duplication through relationship insertion.
//I didn't want to do that, but after going through the five stages
// of grief and spending many hours (like way too much) looking for a cleaner
// solution, it seems JPA has no built-in way to achieve it
EventEntity event = getAsEntity(e);
Map<AttendeeEntity, AttendeeEntity> insertedAttendees = new HashMap<>();
Map<EventDateEntity, EventDateEntity> insertedDates = new HashMap<>();
for (AttendanceEntity attendance : event.attendances) {
AttendeeEntity attendee = attendance.attendee;
EventDateEntity date = attendance.date;
if (!insertedAttendees.containsKey(attendee)) {
insertedAttendees.put(attendee, attendee);
attendeeRepo.save(attendee);
} else {
attendance.attendee = insertedAttendees.get(attendee);
}
if (!insertedDates.containsKey(date)) {
insertedDates.put(date, date);
dateRepo.save(date);
} else {
attendance.date = insertedDates.get(date);
}
}
EventEntity result = eventRepo.save(event);
return result.token;
}
public Event getByToken(String token) {
EventEntity entity = this.eventRepo.findEventEntityByToken(token);
return mapper.toModel(entity);
}
public void delete(Event event) {
}
private EventEntity getAsEntity(Event e) {
return mapper.toEntity(e);
}
public interface EventRepo
extends JpaRepository<EventEntity, String> {
@Query(value = "SELECT * FROM events e WHERE e.token = :#{#token};", nativeQuery = true)
EventEntity findEventEntityByToken(@Param("token") String token);
} }

View File

@@ -0,0 +1,13 @@
package be.naaturel.letsmeet.repositories.interfaces;
import be.naaturel.letsmeet.dto.database.AttendanceEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface AttendanceEntityRepo extends JpaRepository<AttendanceEntity, String> {
//@Query(value = "SELECT * FROM events e WHERE e.token = :#{#token};", nativeQuery = true)
//EventEntity findEventEntityByToken(@Param("token") String token);
}

View File

@@ -0,0 +1,13 @@
package be.naaturel.letsmeet.repositories.interfaces;
import be.naaturel.letsmeet.dto.database.AttendeeEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface AttendeeEntityRepo extends JpaRepository<AttendeeEntity, String> {
//@Query(value = "SELECT * FROM events e WHERE e.token = :#{#token};", nativeQuery = true)
//EventEntity findEventEntityByToken(@Param("token") String token);
}

View File

@@ -0,0 +1,13 @@
package be.naaturel.letsmeet.repositories.interfaces;
import be.naaturel.letsmeet.dto.database.EventDateEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface EventDateEntityRepo extends JpaRepository<EventDateEntity, String> {
//@Query(value = "SELECT * FROM events e WHERE e.token = :#{#token};", nativeQuery = true)
//EventEntity findEventEntityByToken(@Param("token") String token);
}

View File

@@ -0,0 +1,15 @@
package be.naaturel.letsmeet.repositories.interfaces;
import be.naaturel.letsmeet.dto.database.EventEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
@Repository
public interface EventEntityRepo extends JpaRepository<EventEntity, String> {
@Query(value = "SELECT * FROM events e WHERE e.token = :#{#token};", nativeQuery = true)
EventEntity findEventEntityByToken(@Param("token") String token);
}

View File

@@ -14,6 +14,7 @@ public abstract class AbstractService<T, T_ENTITY, T_DTO> {
} }
public abstract Result<?> save(T_DTO prop) throws Exception; public abstract Result<?> save(T_DTO prop) throws Exception;
public abstract boolean delete(T_DTO prop); public abstract boolean delete(T_DTO prop);

View File

@@ -1,11 +1,11 @@
package be.naaturel.letsmeet.services; package be.naaturel.letsmeet.services;
import be.naaturel.letsmeet.core.Result; import be.naaturel.letsmeet.core.Result;
import be.naaturel.letsmeet.core.models.Event;
import be.naaturel.letsmeet.dto.database.EventEntity; import be.naaturel.letsmeet.dto.database.EventEntity;
import be.naaturel.letsmeet.dto.httpRequest.EventDTO; import be.naaturel.letsmeet.dto.httpRequest.EventDTO;
import be.naaturel.letsmeet.mappers.database.EventMapper; import be.naaturel.letsmeet.mappers.database.EventMapper;
import be.naaturel.letsmeet.mappers.requests.EventDTOMapper; import be.naaturel.letsmeet.mappers.requests.EventDTOMapper;
import be.naaturel.letsmeet.core.models.Event;
import be.naaturel.letsmeet.repositories.EventRepo; import be.naaturel.letsmeet.repositories.EventRepo;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.OptimisticLockingFailureException; import org.springframework.dao.OptimisticLockingFailureException;
@@ -25,21 +25,19 @@ public class EventService extends AbstractService<Event, EventEntity, EventDTO>
@Override @Override
public Result<String> save(EventDTO dto) throws Exception { public Result<String> save(EventDTO dto) throws Exception {
Event event = this.requestMapper.toModel(dto); Event event = this.requestMapper.toModel(dto);
EventEntity entity = this.dataBaseMapper.toEntity(event);
try { try {
this.repo.save(entity); String res = this.repo.save(event);
return new Result<>(entity.token); return new Result<>(res);
} catch (Exception e) { } catch (Exception e) {
throw new Exception("Something went wrong"); throw new Exception("Something went wrong : " + e.getMessage());
} }
} }
@Override @Override
public boolean delete(EventDTO dto) { public boolean delete(EventDTO dto) {
Event event = this.requestMapper.toModel(dto); Event event = this.requestMapper.toModel(dto);
EventEntity entity = this.dataBaseMapper.toEntity(event);
try { try {
this.repo.delete(entity); this.repo.delete(event);
return true; return true;
} catch (IllegalArgumentException iae) { } catch (IllegalArgumentException iae) {
return false; return false;
@@ -50,10 +48,8 @@ public class EventService extends AbstractService<Event, EventEntity, EventDTO>
public EventDTO getEvent(String token) { public EventDTO getEvent(String token) {
try { try {
EventEntity entity = this.repo.findEventEntityByToken(token); Event event = this.repo.getByToken(token);
Event model = dataBaseMapper.toModel(entity); return requestMapper.toEntity(event);
EventDTO dto = requestMapper.toEntity(model);
return dto;
} catch (Exception e) { } catch (Exception e) {
return null; return null;
} }

View File

@@ -1,56 +0,0 @@
package be.naaturel.letsmeet.mappers;
import be.naaturel.letsmeet.dto.database.EventDateEntity;
import be.naaturel.letsmeet.mappers.Mapper;
import be.naaturel.letsmeet.mappers.database.EventDateMapper;
import be.naaturel.letsmeet.core.models.EventDate;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.util.HashSet;
import java.util.Set;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class DateMapperTest {
private static final Mapper<EventDate, EventDateEntity> mapper = new EventDateMapper();
private static final EventDate model = new EventDate(0);
private static final Set<EventDate> models = Set.of(new EventDate(0), new EventDate(1), new EventDate(2));
private static final EventDateEntity entity = new EventDateEntity();
private static final Set<EventDateEntity> entities = new HashSet<>();
@BeforeAll
static void setup(){
entity.timeStamp = 0;
entities.add(new EventDateEntity());
entities.add(new EventDateEntity());
entities.add(new EventDateEntity());
}
@Test
void single_model_to_entity() {
EventDateEntity converted = mapper.toEntity(model);
assertEquals(converted.timeStamp, model.getTimeStamp());
}
@Test
void single_entity_to_model() {
EventDate converted = mapper.toModel(entity);
assertEquals(converted.getTimeStamp(), entity.timeStamp);
}
@Test
void multiple_entities_to_models() {
Set<EventDate> dates = mapper.toModels(entities, HashSet::new);
assertEquals(dates.size(), entities.size());
}
@Test
void multiple_models_to_entities() {
Set<EventDateEntity> dates = mapper.toEntities(models, HashSet::new);
assertEquals(dates.size(), models.size());
}
}

View File

@@ -1,68 +0,0 @@
package be.naaturel.letsmeet.mappers;
import be.naaturel.letsmeet.core.models.Event;
import be.naaturel.letsmeet.core.models.EventDate;
import be.naaturel.letsmeet.dto.database.EventDateEntity;
import be.naaturel.letsmeet.dto.database.EventEntity;
import be.naaturel.letsmeet.mappers.database.EventMapper;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class EventMapperTest {
/*private static final Mapper<Event, EventEntity> mapper = new EventMapper();
private static final Set<EventDate> dates = Set.of(new EventDate(0, new HashSet<>()));
private static final Event model = new Event("Event for tests", dates);
private static final List<Event> models = List.of(model, model, model);
private static final EventEntity entity = new EventEntity();
private static final List<EventEntity> entities = new ArrayList<>();
@BeforeAll
static void setup(){
entity.id = "BLA BLA BLA FAKE ID";
entity.name = "Event entity for tests";
entity.dates = Set.of(new EventDateEntity(), new EventDateEntity(), new EventDateEntity());
entities.add(entity);
entities.add(entity);
entities.add(entity);
}
@Test
void single_model_to_entity() {
EventEntity converted = mapper.toEntity(model);
assertEquals(converted.name, model.getName());
assertEquals(converted.dates.size(), model.getDates().size());
}
@Test
void single_entity_to_model() {
Event converted = mapper.toModel(entity);
assertEquals(converted.getName(), entity.name);
//assertEquals(converted.getDates().size(), entity.dates.size());
}
@Test
void multiple_entities_to_models() {
List<Event> events = mapper.toModels(entities, ArrayList::new);
assertEquals(events.size(), entities.size());
}
@Test
void multiple_models_to_entities() {
List<EventEntity> eventEntities = mapper.toEntities(models, ArrayList::new);
assertEquals(eventEntities.size(), models.size());
}*/
}

View File

@@ -1,56 +0,0 @@
package be.naaturel.letsmeet.mappers.dto;
import be.naaturel.letsmeet.core.models.Event;
import be.naaturel.letsmeet.dto.httpRequest.EventDTO;
import be.naaturel.letsmeet.mappers.Mapper;
import be.naaturel.letsmeet.mappers.requests.EventDTOMapper;
import be.naaturel.letsmeet.mock.dto.MockEventDTO;
import be.naaturel.letsmeet.mock.models.MockEventModel;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class EventDTOMapperTest {
private static MockEventDTO mockDto;
private static MockEventModel mockModel;
private static Mapper<Event, EventDTO> mapper;
@BeforeAll
static void setup(){
mockDto = new MockEventDTO();
mockModel = new MockEventModel();
mapper = new EventDTOMapper();
}
@Test
void single_dto_to_model_test(){
Event res = mapper.toModel(mockDto);
assertEquals(res.getName(), mockDto.name);
}
@Test
void single_model_to_dto_test(){
EventDTO res = mapper.toEntity(mockModel);
assertEquals(res.name, mockModel.getName());
}
@Test
void multiple_dto_to_models_test(){
List<Event> res = mapper.toModels(Set.of(mockDto), ArrayList::new);
assertEquals(res.size(), 1);
assertEquals(res.getFirst().getName(), mockDto.name);
}
@Test
void mulitple_models_to_dto_test(){
List<EventDTO> res = mapper.toEntities(Set.of(mockModel), ArrayList::new);
assertEquals(res.size(), 1);
assertEquals(res.getFirst().name, mockModel.getName());
}
}

View File

@@ -1,11 +0,0 @@
package be.naaturel.letsmeet.mock.dto;
import be.naaturel.letsmeet.dto.httpRequest.AttendeeDTO;
public class MockAttendeeDTO extends AttendeeDTO {
public MockAttendeeDTO(){
}
}

View File

@@ -1,24 +0,0 @@
package be.naaturel.letsmeet.mock.dto;
import be.naaturel.letsmeet.core.models.Attendee;
import be.naaturel.letsmeet.dto.httpRequest.AttendeeDTO;
import be.naaturel.letsmeet.dto.httpRequest.EventDTO;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
public class MockEventDTO extends EventDTO {
public MockEventDTO() {
this.name = "Mocked event";
this.dates = new HashMap<>();
populate(0, new HashSet<>());
populate(1, new HashSet<>());
populate(2, new HashSet<>());
}
private void populate(long timestamp, Set<AttendeeDTO> attendees){
this.dates.put(String.valueOf(timestamp), attendees);
}
}

View File

@@ -1,11 +0,0 @@
package be.naaturel.letsmeet.mock.jpa;
import be.naaturel.letsmeet.dto.database.EventEntity;
public class MockEventEntity extends EventEntity {
public MockEventEntity(){
}
}

View File

@@ -1,13 +0,0 @@
package be.naaturel.letsmeet.mock.models;
import be.naaturel.letsmeet.core.models.Attendee;
import be.naaturel.letsmeet.core.models.Event;
import java.util.HashSet;
import java.util.Set;
public class MockEventModel extends Event {
public MockEventModel() {
super("Mock event model", new HashSet<>());
}
}

View File

@@ -1,4 +0,0 @@
package be.naaturel.letsmeet.repositories;
public class EventRepoTest {
}

View File

@@ -1,20 +0,0 @@
package be.naaturel.letsmeet.repositories;
import be.naaturel.letsmeet.dto.database.EventEntity;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Bean;
@TestConfiguration
public class Seeder {
@Bean
public CommandLineRunner seedDatabase(EventRepo eventRepo) {
return args -> {
if (eventRepo.count() == 0) {
eventRepo.save(new EventEntity());
eventRepo.save(new EventEntity());
}
};
}
}

View File

@@ -0,0 +1,15 @@
import type {AttendeeDto} from "@/dto/AttendeeDto.ts";
import type {TimeStampDto} from "@/dto/TimeStampDto.ts";
export class AttendanceDto {
public date : TimeStampDto
public attendee : AttendeeDto
public constructor(date : TimeStampDto, attendee : AttendeeDto) {
this.date = date;
this.attendee = attendee;
}
}

View File

@@ -1,17 +1,18 @@
import type {Attendee} from "@/models/Attendee.ts"; import type {Attendee} from "@/models/Attendee.ts";
import type {EventDate} from "@/models/EventDate.ts"; import type {EventDate} from "@/models/EventDate.ts";
import type {AttendeeDto} from "@/dto/AttendeeDto.ts"; import type {AttendeeDto} from "@/dto/AttendeeDto.ts";
import { AttendanceDto } from "./AttendanceDto.ts";
export class EventDto { export class EventDto {
public name: string; public name: string;
public token: string; public token: string;
public dates : Map<number, AttendeeDto[]> public attendances : AttendanceDto[];
public constructor(name: string, token: string, dates: Map<number, AttendeeDto[]>) { public constructor(name: string, token: string, attendances : AttendanceDto[]) {
this.name = name; this.name = name;
this.token = token; this.token = token;
this.dates = dates; this.attendances = attendances;
} }
} }

View File

@@ -0,0 +1,12 @@
import type {EventDate} from "@/models/EventDate.ts";
import type {Attendee} from "@/models/Attendee.ts";
export class Attendance {
public date : EventDate
public attendee : Attendee
public constructor(date : EventDate, attendee : Attendee) {
this.date = date;
this.attendee = attendee;
}
}

View File

@@ -25,7 +25,8 @@ export class EventRequests {
return fetch(url) return fetch(url)
.then(response => response.json()) .then(response => response.json())
.then(data => { .then(data => {
return new EventDto(data.name, data.token, data.dates) console.log(data);
return new EventDto(data.name, data.token, data.attendances);
}) })
.catch(error => console.error(error)); .catch(error => console.error(error));
} }

View File

@@ -3,14 +3,17 @@ import {EventRequests} from "@/requests/EventRequests.ts";
import {EventDto} from "@/dto/EventDto.ts"; import {EventDto} from "@/dto/EventDto.ts";
import {Event, type EventState} from "@/models/Event.ts"; import {Event, type EventState} from "@/models/Event.ts";
import {Attendee, type AttendeeState} from "@/models/Attendee.ts"; import {Attendee, type AttendeeState} from "@/models/Attendee.ts";
import type {AttendeeDto} from "@/dto/AttendeeDto.ts"; import {AttendanceDto} from "@/dto/AttendanceDto.ts";
import {TimeStampDto} from "@/dto/TimeStampDto.ts";
import {AttendeeDto} from "@/dto/AttendeeDto.ts";
const requests = new EventRequests(); const requests = new EventRequests();
function mapToDto(state : EventState) : EventDto{ function mapToDto(state : EventState) : EventDto{
let dates : Map<number, AttendeeDto[]> = new Map<number, AttendeeDto[]>(); let dates : AttendanceDto[] = [];
for (let [date, attendeesState] of state.dates.entries()) { for (let [date, attendeesState] of state.dates.entries()) {
dates.set(date, []); let attendance : AttendanceDto = new AttendanceDto(new TimeStampDto(new Date(date)), new AttendeeDto(""));
dates.push(attendance);
} }
return new EventDto(state.name, state.token, dates); return new EventDto(state.name, state.token, dates);
} }
@@ -30,9 +33,12 @@ function mapToState(dto : EventDto) : EventState {
let event : EventState = { name : "", token : "", dates: new Map<number, AttendeeState[]>() }; let event : EventState = { name : "", token : "", dates: new Map<number, AttendeeState[]>() };
event.name = dto.name; event.name = dto.name;
event.token = dto.token; event.token = dto.token;
Object.entries(dto.dates).forEach(([key, attendees]) => { dto.attendances.forEach(value => {
})
/*Object.entries(dto.dates).forEach(([key, attendees]) => {
event.dates.set(Number(key), attendees); event.dates.set(Number(key), attendees);
}); });*/
return event; return event;
} }
@@ -90,14 +96,15 @@ export const eventCreationStore = defineStore('eventStore', {
async createEvent() : Promise<string> { async createEvent() : Promise<string> {
try { try {
let event = mapToDto(this.event); let event = mapToDto(this.event);
let res = await requests.createEvent(event) console.log(JSON.stringify(event));
//let res = await requests.createEvent(event)
let res = "";
if(res) return res; if(res) return res;
throw new Error("Unable to create event"); throw new Error("Unable to create event");
} catch (error){ } catch (error){
console.error(error); console.error(error);
throw new Error("Unable to post. " + error); throw new Error("Unable to post. " + error);
} }
} }
}, },
}); });