Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package dev.flima.infrastructure.config;

import jakarta.ws.rs.ApplicationPath;
import jakarta.ws.rs.core.Application;

@ApplicationPath("api/v1")
public class ApplicationDefault extends Application {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package dev.flima.infrastructure.contents;

import dev.flima.domain.contents.SectionType;
import io.quarkus.hibernate.orm.panache.PanacheEntityBase;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import org.hibernate.annotations.JdbcTypeCode;
import org.hibernate.type.SqlTypes;

import java.util.UUID;

@Entity(name = "contents")
public class ContentPanacheEntity extends PanacheEntityBase {
@Id
public UUID id;

@Enumerated(EnumType.STRING)
@JdbcTypeCode(SqlTypes.NAMED_ENUM)
@Column(name = "section_type", nullable = false)
@NotNull
public SectionType sectionType;

@Embedded
@Column(nullable = false)
public SectionContentEmbeddable content;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package dev.flima.infrastructure.contents;

import dev.flima.domain.contents.Content;
import dev.flima.domain.contents.ContentRepository;
import dev.flima.domain.contents.SectionContent;
import dev.flima.domain.exceptions.EntityNotFoundException;
import io.quarkus.hibernate.orm.panache.PanacheRepositoryBase;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.ws.rs.NotFoundException;

import java.util.List;
import java.util.Optional;
import java.util.ResourceBundle;
import java.util.UUID;

@ApplicationScoped
public class ContentRepositoryImpl implements ContentRepository, PanacheRepositoryBase<ContentPanacheEntity, UUID> {

private final ResourceBundle messages = ResourceBundle.getBundle("messages");

@Override
public void save(Content content) {
ContentPanacheEntity entity = new ContentPanacheEntity();

entity.id = content.getId();
entity.sectionType = content.getSectionType();

if(content.getSectionContent() != null) {
entity.content = new SectionContentEmbeddable();
entity.content.title = content.getSectionContent().title();
entity.content.subtitle = content.getSectionContent().subtitle();
}

persist(entity);
}

@Override
public void modify(Content content) {
ContentPanacheEntity entity = findById(content.getId());

if (entity == null) {
throw new EntityNotFoundException(messages.getString("content.not_found"));
}

entity.sectionType = content.getSectionType();

if(content.getSectionContent() != null) {
entity.content = new SectionContentEmbeddable();
entity.content.title = content.getSectionContent().title();
entity.content.subtitle = content.getSectionContent().subtitle();
}
}

@Override
public Optional<Content> getById(UUID id) {
ContentPanacheEntity entity = findById(id);

if (entity == null) {
throw new EntityNotFoundException(messages.getString("content.not_found"));
}

String contentTitle = entity.content.title;
String contentSubtitle = entity.content.subtitle;
SectionContent content = new SectionContent(contentTitle, contentSubtitle);

return Optional.of(new Content(entity.id, entity.sectionType, content));
}

@Override
public List<Content> getAll() {
return findAll().list().stream()
.map(entity -> new Content(
entity.id,
entity.sectionType,
new SectionContent(entity.content.title, entity.content.subtitle)
))
.toList();
}

@Override
public void remove(Content content) {
ContentPanacheEntity entity = findById(content.getId());

if (entity == null) {
throw new EntityNotFoundException(messages.getString("content.not_found"));
}

delete(entity);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package dev.flima.infrastructure.contents;

import jakarta.persistence.Embeddable;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;

@Embeddable
public class SectionContentEmbeddable {
@NotNull(message = "Title cannot be null.")
@NotBlank(message = "Title cannot be blank.")
public String title;

@NotNull(message = "Subtitle cannot be null.")
@NotBlank(message = "Subtitle cannot be blank.")
public String subtitle;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package dev.flima.infrastructure.educations;

import dev.flima.domain.educations.TypeEducation;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import org.hibernate.annotations.JdbcTypeCode;
import org.hibernate.type.SqlTypes;

import java.util.List;
import java.util.UUID;

@Entity(name = "educations")
public class EducationPanacheEntity {

@Id
public UUID id;

@Enumerated(EnumType.STRING)
@JdbcTypeCode(SqlTypes.NAMED_ENUM)
@Column(name = "education_type", nullable = false)
@NotNull
public TypeEducation typeEducation;

@Column(nullable = false)
@NotBlank
public String degree;

@Column(nullable = false)
@NotBlank
public String title;

@Column(nullable = false)
@NotBlank
public String institution;

@Column(nullable = false)
@NotBlank
public String period;

@Column(nullable = false)
@NotBlank
public String specialization;

@ElementCollection
@CollectionTable(name = "education_skills", joinColumns = @JoinColumn(name = "education_id"))
@Column(name = "skill")
@NotEmpty
public List<String> skills;

@ElementCollection
@CollectionTable(name = "education_architectures", joinColumns = @JoinColumn(name = "education_id"))
@Column(name = "architecture")
@NotEmpty
public List<String> architectures;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package dev.flima.infrastructure.educations;

import dev.flima.domain.educations.Education;
import dev.flima.domain.educations.EducationRepository;
import dev.flima.domain.exceptions.EntityNotFoundException;
import io.quarkus.hibernate.orm.panache.PanacheRepositoryBase;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.ws.rs.NotFoundException;

import java.util.List;
import java.util.Optional;
import java.util.ResourceBundle;
import java.util.UUID;

@ApplicationScoped
public class EducationRepositoryImpl implements EducationRepository, PanacheRepositoryBase<EducationPanacheEntity, UUID> {

private final ResourceBundle messages = ResourceBundle.getBundle("messages");

@Override
public void save(Education education) {
EducationPanacheEntity entity = new EducationPanacheEntity();

entity.id = education.getId();
entity.typeEducation = education.getTypeEducation();
entity.degree = education.getDegree();
entity.title = education.getTitle();
entity.institution = education.getInstitution();
entity.period = education.getPeriod();
entity.specialization = education.getSpecialization();
entity.skills = education.getSkills();
entity.architectures = education.getArchitectures();

persist(entity);
}

@Override
public void modify(Education education) {
EducationPanacheEntity entity = findById(education.getId());

if (entity == null) {
throw new EntityNotFoundException(messages.getString("education.not_found"));
}

entity.typeEducation = education.getTypeEducation();
entity.degree = education.getDegree();
entity.title = education.getTitle();
entity.institution = education.getInstitution();
entity.period = education.getPeriod();
entity.specialization = education.getSpecialization();
entity.skills = education.getSkills();
entity.architectures = education.getArchitectures();
}

@Override
public Optional<Education> getById(UUID id) {
EducationPanacheEntity entity = findById(id);

if (entity == null) {
throw new EntityNotFoundException(messages.getString("education.not_found"));
}

return Optional.of(new Education(
entity.id,
entity.typeEducation,
entity.degree,
entity.title,
entity.institution,
entity.period,
entity.specialization,
entity.skills,
entity.architectures
));
}

@Override
public List<Education> getAll() {
return findAll().list().stream()
.map(entity -> new Education(
entity.id,
entity.typeEducation,
entity.degree,
entity.title,
entity.institution,
entity.period,
entity.specialization,
entity.skills,
entity.architectures
))
.toList();
}

@Override
public void remove(Education education) {
EducationPanacheEntity entity = findById(education.getId());

if (entity == null) {
throw new EntityNotFoundException(messages.getString("education.not_found"));
}

delete(entity);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package dev.flima.infrastructure.exceptions;

import dev.flima.presentation.rest.dto.ErrorResponse;
import jakarta.validation.ConstraintViolationException;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.ExceptionMapper;
import jakarta.ws.rs.ext.Provider;
import java.util.List;

@Provider
public class ConstraintViolationExceptionHandler implements ExceptionMapper<ConstraintViolationException> {

@Override
public Response toResponse(ConstraintViolationException ex) {
List<String> details = ex.getConstraintViolations().stream()
.map(v -> v.getPropertyPath() + ": " + v.getMessage())
.toList();

return Response.status(400)
.entity(ErrorResponse.of("Validation failed", 400, details))
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package dev.flima.infrastructure.exceptions;

import dev.flima.presentation.rest.dto.ErrorResponse;
import jakarta.persistence.PersistenceException;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.ExceptionMapper;
import jakarta.ws.rs.ext.Provider;
import org.hibernate.exception.ConstraintViolationException;

@Provider
public class DatabaseExceptionHandler implements ExceptionMapper<PersistenceException> {

@Override
public Response toResponse(PersistenceException ex) {
Throwable cause = ex;
while (cause != null) {
if (cause instanceof ConstraintViolationException) {
return Response.status(409)
.entity(ErrorResponse.of("Record already exists with this unique identifier.", 409))
.build();
}
cause = cause.getCause();
}

return Response.status(500)
.entity(ErrorResponse.of("Database error occurred.", 500))
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package dev.flima.infrastructure.exceptions;

import dev.flima.domain.exceptions.DomainException;
import dev.flima.presentation.rest.dto.ErrorResponse;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.ExceptionMapper;
import jakarta.ws.rs.ext.Provider;

@Provider
public class DomainExceptionHandler implements ExceptionMapper<DomainException> {

@Override
public Response toResponse(DomainException ex) {
return Response.status(ex.getStatusCode())
.entity(ErrorResponse.of(ex.getMessage(), ex.getStatusCode()))
.build();
}
}
Loading