chore: add minimal implementations for all portfolio API endpoints

This commit is contained in:
Pablo de la Torre Jamardo 2025-08-25 23:04:20 +02:00
parent df24350bd3
commit 7f12034174
100 changed files with 2048 additions and 7 deletions

View File

@ -0,0 +1,26 @@
package com.pablotj.portfolio.application.about;
import com.pablotj.portfolio.domain.about.About;
import com.pablotj.portfolio.domain.about.port.AboutRepositoryPort;
public class CreateAboutUseCase {
private final AboutRepositoryPort repository;
public CreateAboutUseCase(AboutRepositoryPort repository) {
this.repository = repository;
}
public About handle(Command cmd) {
var about = About.builder()
.id(null)
.title(cmd.title())
.description(cmd.description())
.url(cmd.url())
.build();
return repository.save(about);
}
public record Command(String title, String description, String url) {
}
}

View File

@ -0,0 +1,24 @@
package com.pablotj.portfolio.application.about;
import com.pablotj.portfolio.domain.about.About;
import com.pablotj.portfolio.domain.about.AboutId;
import com.pablotj.portfolio.domain.about.port.AboutRepositoryPort;
import java.util.List;
import java.util.Optional;
public class GetAboutUseCase {
private final AboutRepositoryPort repository;
public GetAboutUseCase(AboutRepositoryPort repository) {
this.repository = repository;
}
public Optional<About> byId(Long id) {
return repository.findById(new AboutId(id));
}
public List<About> all() {
return repository.findAll();
}
}

View File

@ -0,0 +1,26 @@
package com.pablotj.portfolio.application.certification;
import com.pablotj.portfolio.domain.certification.Certification;
import com.pablotj.portfolio.domain.certification.port.CertificationRepositoryPort;
public class CreateCertificationUseCase {
private final CertificationRepositoryPort repository;
public CreateCertificationUseCase(CertificationRepositoryPort repository) {
this.repository = repository;
}
public Certification handle(Command cmd) {
var certification = Certification.builder()
.id(null)
.title(cmd.title())
.description(cmd.description())
.url(cmd.url())
.build();
return repository.save(certification);
}
public record Command(String title, String description, String url) {
}
}

View File

@ -0,0 +1,24 @@
package com.pablotj.portfolio.application.certification;
import com.pablotj.portfolio.domain.certification.Certification;
import com.pablotj.portfolio.domain.certification.CertificationId;
import com.pablotj.portfolio.domain.certification.port.CertificationRepositoryPort;
import java.util.List;
import java.util.Optional;
public class GetCertificationUseCase {
private final CertificationRepositoryPort repository;
public GetCertificationUseCase(CertificationRepositoryPort repository) {
this.repository = repository;
}
public Optional<Certification> byId(Long id) {
return repository.findById(new CertificationId(id));
}
public List<Certification> all() {
return repository.findAll();
}
}

View File

@ -0,0 +1,26 @@
package com.pablotj.portfolio.application.contact;
import com.pablotj.portfolio.domain.contact.Contact;
import com.pablotj.portfolio.domain.contact.port.ContactRepositoryPort;
public class CreateContactUseCase {
private final ContactRepositoryPort repository;
public CreateContactUseCase(ContactRepositoryPort repository) {
this.repository = repository;
}
public Contact handle(Command cmd) {
var contact = Contact.builder()
.id(null)
.title(cmd.title())
.description(cmd.description())
.url(cmd.url())
.build();
return repository.save(contact);
}
public record Command(String title, String description, String url) {
}
}

View File

@ -0,0 +1,24 @@
package com.pablotj.portfolio.application.contact;
import com.pablotj.portfolio.domain.contact.Contact;
import com.pablotj.portfolio.domain.contact.ContactId;
import com.pablotj.portfolio.domain.contact.port.ContactRepositoryPort;
import java.util.List;
import java.util.Optional;
public class GetContactUseCase {
private final ContactRepositoryPort repository;
public GetContactUseCase(ContactRepositoryPort repository) {
this.repository = repository;
}
public Optional<Contact> byId(Long id) {
return repository.findById(new ContactId(id));
}
public List<Contact> all() {
return repository.findAll();
}
}

View File

@ -0,0 +1,26 @@
package com.pablotj.portfolio.application.education;
import com.pablotj.portfolio.domain.education.Education;
import com.pablotj.portfolio.domain.education.port.EducationRepositoryPort;
public class CreateEducationUseCase {
private final EducationRepositoryPort repository;
public CreateEducationUseCase(EducationRepositoryPort repository) {
this.repository = repository;
}
public Education handle(Command cmd) {
var education = Education.builder()
.id(null)
.title(cmd.title())
.description(cmd.description())
.url(cmd.url())
.build();
return repository.save(education);
}
public record Command(String title, String description, String url) {
}
}

View File

@ -0,0 +1,24 @@
package com.pablotj.portfolio.application.education;
import com.pablotj.portfolio.domain.education.Education;
import com.pablotj.portfolio.domain.education.EducationId;
import com.pablotj.portfolio.domain.education.port.EducationRepositoryPort;
import java.util.List;
import java.util.Optional;
public class GetEducationUseCase {
private final EducationRepositoryPort repository;
public GetEducationUseCase(EducationRepositoryPort repository) {
this.repository = repository;
}
public Optional<Education> byId(Long id) {
return repository.findById(new EducationId(id));
}
public List<Education> all() {
return repository.findAll();
}
}

View File

@ -0,0 +1,26 @@
package com.pablotj.portfolio.application.experience;
import com.pablotj.portfolio.domain.experience.Experience;
import com.pablotj.portfolio.domain.experience.port.ExperienceRepositoryPort;
public class CreateExperienceUseCase {
private final ExperienceRepositoryPort repository;
public CreateExperienceUseCase(ExperienceRepositoryPort repository) {
this.repository = repository;
}
public Experience handle(Command cmd) {
var experience = Experience.builder()
.id(null)
.title(cmd.title())
.description(cmd.description())
.url(cmd.url())
.build();
return repository.save(experience);
}
public record Command(String title, String description, String url) {
}
}

View File

@ -0,0 +1,24 @@
package com.pablotj.portfolio.application.experience;
import com.pablotj.portfolio.domain.experience.Experience;
import com.pablotj.portfolio.domain.experience.ExperienceId;
import com.pablotj.portfolio.domain.experience.port.ExperienceRepositoryPort;
import java.util.List;
import java.util.Optional;
public class GetExperienceUseCase {
private final ExperienceRepositoryPort repository;
public GetExperienceUseCase(ExperienceRepositoryPort repository) {
this.repository = repository;
}
public Optional<Experience> byId(Long id) {
return repository.findById(new ExperienceId(id));
}
public List<Experience> all() {
return repository.findAll();
}
}

View File

@ -0,0 +1,26 @@
package com.pablotj.portfolio.application.home;
import com.pablotj.portfolio.domain.home.Home;
import com.pablotj.portfolio.domain.home.port.HomeRepositoryPort;
public class CreateHomeUseCase {
private final HomeRepositoryPort repository;
public CreateHomeUseCase(HomeRepositoryPort repository) {
this.repository = repository;
}
public Home handle(Command cmd) {
var home = Home.builder()
.id(null)
.title(cmd.title())
.description(cmd.description())
.url(cmd.url())
.build();
return repository.save(home);
}
public record Command(String title, String description, String url) {
}
}

View File

@ -0,0 +1,24 @@
package com.pablotj.portfolio.application.home;
import com.pablotj.portfolio.domain.home.Home;
import com.pablotj.portfolio.domain.home.HomeId;
import com.pablotj.portfolio.domain.home.port.HomeRepositoryPort;
import java.util.List;
import java.util.Optional;
public class GetHomeUseCase {
private final HomeRepositoryPort repository;
public GetHomeUseCase(HomeRepositoryPort repository) {
this.repository = repository;
}
public Optional<Home> byId(Long id) {
return repository.findById(new HomeId(id));
}
public List<Home> all() {
return repository.findAll();
}
}

View File

@ -0,0 +1,26 @@
package com.pablotj.portfolio.application.skill;
import com.pablotj.portfolio.domain.skill.Skill;
import com.pablotj.portfolio.domain.skill.port.SkillRepositoryPort;
public class CreateSkillUseCase {
private final SkillRepositoryPort repository;
public CreateSkillUseCase(SkillRepositoryPort repository) {
this.repository = repository;
}
public Skill handle(Command cmd) {
var skill = Skill.builder()
.id(null)
.title(cmd.title())
.description(cmd.description())
.url(cmd.url())
.build();
return repository.save(skill);
}
public record Command(String title, String description, String url) {
}
}

View File

@ -0,0 +1,24 @@
package com.pablotj.portfolio.application.skill;
import com.pablotj.portfolio.domain.skill.Skill;
import com.pablotj.portfolio.domain.skill.SkillId;
import com.pablotj.portfolio.domain.skill.port.SkillRepositoryPort;
import java.util.List;
import java.util.Optional;
public class GetSkillUseCase {
private final SkillRepositoryPort repository;
public GetSkillUseCase(SkillRepositoryPort repository) {
this.repository = repository;
}
public Optional<Skill> byId(Long id) {
return repository.findById(new SkillId(id));
}
public List<Skill> all() {
return repository.findAll();
}
}

View File

@ -6,8 +6,8 @@ import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
@SpringBootApplication(scanBasePackages = "com.pablotj")
@EnableJpaRepositories(basePackages = { "com.pablotj.portfolio.infrastructure.persistence.project.repo" })
@EntityScan(basePackages = { "com.pablotj.portfolio.infrastructure.persistence.project.entity" })
@EnableJpaRepositories(basePackages = {"com.pablotj.portfolio.infrastructure.persistence.*.repo"})
@EntityScan(basePackages = {"com.pablotj.portfolio.infrastructure.persistence.*.entity"})
public class PortfolioApplication {
public static void main(String[] args) {

View File

@ -0,0 +1,21 @@
package com.pablotj.portfolio.bootstrap.about;
import com.pablotj.portfolio.application.about.CreateAboutUseCase;
import com.pablotj.portfolio.application.about.GetAboutUseCase;
import com.pablotj.portfolio.domain.about.port.AboutRepositoryPort;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AboutApplicationConfig {
@Bean
public GetAboutUseCase getAboutUseCase(AboutRepositoryPort repo) {
return new GetAboutUseCase(repo);
}
@Bean
public CreateAboutUseCase createAboutUseCase(AboutRepositoryPort repo) {
return new CreateAboutUseCase(repo);
}
}

View File

@ -0,0 +1,21 @@
package com.pablotj.portfolio.bootstrap.certification;
import com.pablotj.portfolio.application.certification.CreateCertificationUseCase;
import com.pablotj.portfolio.application.certification.GetCertificationUseCase;
import com.pablotj.portfolio.domain.certification.port.CertificationRepositoryPort;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class CertificationApplicationConfig {
@Bean
public GetCertificationUseCase getCertificationUseCase(CertificationRepositoryPort repo) {
return new GetCertificationUseCase(repo);
}
@Bean
public CreateCertificationUseCase createCertificationUseCase(CertificationRepositoryPort repo) {
return new CreateCertificationUseCase(repo);
}
}

View File

@ -0,0 +1,21 @@
package com.pablotj.portfolio.bootstrap.contact;
import com.pablotj.portfolio.application.contact.CreateContactUseCase;
import com.pablotj.portfolio.application.contact.GetContactUseCase;
import com.pablotj.portfolio.domain.contact.port.ContactRepositoryPort;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ContactApplicationConfig {
@Bean
public GetContactUseCase getContactUseCase(ContactRepositoryPort repo) {
return new GetContactUseCase(repo);
}
@Bean
public CreateContactUseCase createContactUseCase(ContactRepositoryPort repo) {
return new CreateContactUseCase(repo);
}
}

View File

@ -0,0 +1,21 @@
package com.pablotj.portfolio.bootstrap.education;
import com.pablotj.portfolio.application.education.CreateEducationUseCase;
import com.pablotj.portfolio.application.education.GetEducationUseCase;
import com.pablotj.portfolio.domain.education.port.EducationRepositoryPort;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class EducationApplicationConfig {
@Bean
public GetEducationUseCase getEducationUseCase(EducationRepositoryPort repo) {
return new GetEducationUseCase(repo);
}
@Bean
public CreateEducationUseCase createEducationUseCase(EducationRepositoryPort repo) {
return new CreateEducationUseCase(repo);
}
}

View File

@ -0,0 +1,21 @@
package com.pablotj.portfolio.bootstrap.experience;
import com.pablotj.portfolio.application.experience.CreateExperienceUseCase;
import com.pablotj.portfolio.application.experience.GetExperienceUseCase;
import com.pablotj.portfolio.domain.experience.port.ExperienceRepositoryPort;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ExperienceApplicationConfig {
@Bean
public GetExperienceUseCase getExperienceUseCase(ExperienceRepositoryPort repo) {
return new GetExperienceUseCase(repo);
}
@Bean
public CreateExperienceUseCase createExperienceUseCase(ExperienceRepositoryPort repo) {
return new CreateExperienceUseCase(repo);
}
}

View File

@ -0,0 +1,21 @@
package com.pablotj.portfolio.bootstrap.home;
import com.pablotj.portfolio.application.home.CreateHomeUseCase;
import com.pablotj.portfolio.application.home.GetHomeUseCase;
import com.pablotj.portfolio.domain.home.port.HomeRepositoryPort;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class HomeApplicationConfig {
@Bean
public GetHomeUseCase getHomeUseCase(HomeRepositoryPort repo) {
return new GetHomeUseCase(repo);
}
@Bean
public CreateHomeUseCase createHomeUseCase(HomeRepositoryPort repo) {
return new CreateHomeUseCase(repo);
}
}

View File

@ -0,0 +1,21 @@
package com.pablotj.portfolio.bootstrap.skill;
import com.pablotj.portfolio.application.skill.CreateSkillUseCase;
import com.pablotj.portfolio.application.skill.GetSkillUseCase;
import com.pablotj.portfolio.domain.skill.port.SkillRepositoryPort;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SkillApplicationConfig {
@Bean
public GetSkillUseCase getSkillUseCase(SkillRepositoryPort repo) {
return new GetSkillUseCase(repo);
}
@Bean
public CreateSkillUseCase createSkillUseCase(SkillRepositoryPort repo) {
return new CreateSkillUseCase(repo);
}
}

View File

@ -0,0 +1,13 @@
package com.pablotj.portfolio.domain.about;
import lombok.Builder;
import lombok.Getter;
@Getter
@Builder
public class About {
private final AboutId id;
private final String title;
private final String description;
private final String url;
}

View File

@ -0,0 +1,7 @@
package com.pablotj.portfolio.domain.about;
public record AboutId(Long value) {
public AboutId {
if (value != null && value < 0) throw new IllegalArgumentException("AboutId must be positive");
}
}

View File

@ -0,0 +1,15 @@
package com.pablotj.portfolio.domain.about.port;
import com.pablotj.portfolio.domain.about.About;
import com.pablotj.portfolio.domain.about.AboutId;
import java.util.List;
import java.util.Optional;
public interface AboutRepositoryPort {
About save(About p);
Optional<About> findById(AboutId id);
List<About> findAll();
}

View File

@ -0,0 +1,13 @@
package com.pablotj.portfolio.domain.certification;
import lombok.Builder;
import lombok.Getter;
@Getter
@Builder
public class Certification {
private final CertificationId id;
private final String title;
private final String description;
private final String url;
}

View File

@ -0,0 +1,7 @@
package com.pablotj.portfolio.domain.certification;
public record CertificationId(Long value) {
public CertificationId {
if (value != null && value < 0) throw new IllegalArgumentException("CertificationId must be positive");
}
}

View File

@ -0,0 +1,14 @@
package com.pablotj.portfolio.domain.certification.port;
import com.pablotj.portfolio.domain.certification.Certification;
import com.pablotj.portfolio.domain.certification.CertificationId;
import java.util.List;
import java.util.Optional;
public interface CertificationRepositoryPort {
Certification save(Certification p);
Optional<Certification> findById(CertificationId id);
List<Certification> findAll();
}

View File

@ -0,0 +1,13 @@
package com.pablotj.portfolio.domain.contact;
import lombok.Builder;
import lombok.Getter;
@Getter
@Builder
public class Contact {
private final ContactId id;
private final String title;
private final String description;
private final String url;
}

View File

@ -0,0 +1,7 @@
package com.pablotj.portfolio.domain.contact;
public record ContactId(Long value) {
public ContactId {
if (value != null && value < 0) throw new IllegalArgumentException("ContactId must be positive");
}
}

View File

@ -0,0 +1,14 @@
package com.pablotj.portfolio.domain.contact.port;
import com.pablotj.portfolio.domain.contact.Contact;
import com.pablotj.portfolio.domain.contact.ContactId;
import java.util.List;
import java.util.Optional;
public interface ContactRepositoryPort {
Contact save(Contact p);
Optional<Contact> findById(ContactId id);
List<Contact> findAll();
}

View File

@ -0,0 +1,13 @@
package com.pablotj.portfolio.domain.education;
import lombok.Builder;
import lombok.Getter;
@Getter
@Builder
public class Education {
private final EducationId id;
private final String title;
private final String description;
private final String url;
}

View File

@ -0,0 +1,7 @@
package com.pablotj.portfolio.domain.education;
public record EducationId(Long value) {
public EducationId {
if (value != null && value < 0) throw new IllegalArgumentException("EducationId must be positive");
}
}

View File

@ -0,0 +1,14 @@
package com.pablotj.portfolio.domain.education.port;
import com.pablotj.portfolio.domain.education.Education;
import com.pablotj.portfolio.domain.education.EducationId;
import java.util.List;
import java.util.Optional;
public interface EducationRepositoryPort {
Education save(Education p);
Optional<Education> findById(EducationId id);
List<Education> findAll();
}

View File

@ -0,0 +1,13 @@
package com.pablotj.portfolio.domain.experience;
import lombok.Builder;
import lombok.Getter;
@Getter
@Builder
public class Experience {
private final ExperienceId id;
private final String title;
private final String description;
private final String url;
}

View File

@ -0,0 +1,7 @@
package com.pablotj.portfolio.domain.experience;
public record ExperienceId(Long value) {
public ExperienceId {
if (value != null && value < 0) throw new IllegalArgumentException("ExperienceId must be positive");
}
}

View File

@ -0,0 +1,14 @@
package com.pablotj.portfolio.domain.experience.port;
import com.pablotj.portfolio.domain.experience.Experience;
import com.pablotj.portfolio.domain.experience.ExperienceId;
import java.util.List;
import java.util.Optional;
public interface ExperienceRepositoryPort {
Experience save(Experience p);
Optional<Experience> findById(ExperienceId id);
List<Experience> findAll();
}

View File

@ -0,0 +1,13 @@
package com.pablotj.portfolio.domain.home;
import lombok.Builder;
import lombok.Getter;
@Getter
@Builder
public class Home {
private final HomeId id;
private final String title;
private final String description;
private final String url;
}

View File

@ -0,0 +1,7 @@
package com.pablotj.portfolio.domain.home;
public record HomeId(Long value) {
public HomeId {
if (value != null && value < 0) throw new IllegalArgumentException("HomeId must be positive");
}
}

View File

@ -0,0 +1,14 @@
package com.pablotj.portfolio.domain.home.port;
import com.pablotj.portfolio.domain.home.Home;
import com.pablotj.portfolio.domain.home.HomeId;
import java.util.List;
import java.util.Optional;
public interface HomeRepositoryPort {
Home save(Home p);
Optional<Home> findById(HomeId id);
List<Home> findAll();
}

View File

@ -0,0 +1,13 @@
package com.pablotj.portfolio.domain.skill;
import lombok.Builder;
import lombok.Getter;
@Getter
@Builder
public class Skill {
private final SkillId id;
private final String title;
private final String description;
private final String url;
}

View File

@ -0,0 +1,7 @@
package com.pablotj.portfolio.domain.skill;
public record SkillId(Long value) {
public SkillId {
if (value != null && value < 0) throw new IllegalArgumentException("SkillId must be positive");
}
}

View File

@ -0,0 +1,14 @@
package com.pablotj.portfolio.domain.skill.port;
import com.pablotj.portfolio.domain.skill.Skill;
import com.pablotj.portfolio.domain.skill.SkillId;
import java.util.List;
import java.util.Optional;
public interface SkillRepositoryPort {
Skill save(Skill p);
Optional<Skill> findById(SkillId id);
List<Skill> findAll();
}

View File

@ -0,0 +1,40 @@
package com.pablotj.portfolio.infrastructure.persistence.about.adapter;
import com.pablotj.portfolio.domain.about.About;
import com.pablotj.portfolio.domain.about.AboutId;
import com.pablotj.portfolio.domain.about.port.AboutRepositoryPort;
import com.pablotj.portfolio.infrastructure.persistence.about.entity.AboutJpaEntity;
import com.pablotj.portfolio.infrastructure.persistence.about.mapper.AboutJpaMapper;
import com.pablotj.portfolio.infrastructure.persistence.about.repo.SpringDataAboutRepository;
import java.util.List;
import java.util.Optional;
import org.springframework.stereotype.Repository;
@Repository
public class AboutRepositoryAdapter implements AboutRepositoryPort {
private final SpringDataAboutRepository repo;
private final AboutJpaMapper mapper;
public AboutRepositoryAdapter(SpringDataAboutRepository repo, AboutJpaMapper mapper) {
this.repo = repo;
this.mapper = mapper;
}
@Override
public About save(About p) {
AboutJpaEntity entity = mapper.toEntity(p);
AboutJpaEntity saved = repo.save(entity);
return mapper.toDomain(saved);
}
@Override
public Optional<About> findById(AboutId id) {
return repo.findById(id.value()).map(mapper::toDomain);
}
@Override
public List<About> findAll() {
return repo.findAll().stream().map(mapper::toDomain).toList();
}
}

View File

@ -0,0 +1,29 @@
package com.pablotj.portfolio.infrastructure.persistence.about.entity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.Getter;
import lombok.Setter;
@Entity
@Table(name = "abouts")
@Getter
@Setter
public class AboutJpaEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String title;
@Column(columnDefinition = "text")
private String description;
private String url;
}

View File

@ -0,0 +1,24 @@
package com.pablotj.portfolio.infrastructure.persistence.about.mapper;
import com.pablotj.portfolio.domain.about.About;
import com.pablotj.portfolio.domain.about.AboutId;
import com.pablotj.portfolio.infrastructure.persistence.about.entity.AboutJpaEntity;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
@Mapper(componentModel = "spring")
public interface AboutJpaMapper {
@Mapping(target = "id", ignore = true)
AboutJpaEntity toEntity(About domain);
default About toDomain(AboutJpaEntity e) {
if (e == null) return null;
return About.builder()
.id(e.getId() == null ? null : new AboutId(e.getId()))
.title(e.getTitle())
.description(e.getDescription())
.url(e.getUrl())
.build();
}
}

View File

@ -0,0 +1,7 @@
package com.pablotj.portfolio.infrastructure.persistence.about.repo;
import com.pablotj.portfolio.infrastructure.persistence.about.entity.AboutJpaEntity;
import org.springframework.data.jpa.repository.JpaRepository;
public interface SpringDataAboutRepository extends JpaRepository<AboutJpaEntity, Long> {
}

View File

@ -0,0 +1,40 @@
package com.pablotj.portfolio.infrastructure.persistence.certification.adapter;
import com.pablotj.portfolio.domain.certification.Certification;
import com.pablotj.portfolio.domain.certification.CertificationId;
import com.pablotj.portfolio.domain.certification.port.CertificationRepositoryPort;
import com.pablotj.portfolio.infrastructure.persistence.certification.entity.CertificationJpaEntity;
import com.pablotj.portfolio.infrastructure.persistence.certification.mapper.CertificationJpaMapper;
import com.pablotj.portfolio.infrastructure.persistence.certification.repo.SpringDataCertificationRepository;
import java.util.List;
import java.util.Optional;
import org.springframework.stereotype.Repository;
@Repository
public class CertificationRepositoryAdapter implements CertificationRepositoryPort {
private final SpringDataCertificationRepository repo;
private final CertificationJpaMapper mapper;
public CertificationRepositoryAdapter(SpringDataCertificationRepository repo, CertificationJpaMapper mapper) {
this.repo = repo;
this.mapper = mapper;
}
@Override
public Certification save(Certification p) {
CertificationJpaEntity entity = mapper.toEntity(p);
CertificationJpaEntity saved = repo.save(entity);
return mapper.toDomain(saved);
}
@Override
public Optional<Certification> findById(CertificationId id) {
return repo.findById(id.value()).map(mapper::toDomain);
}
@Override
public List<Certification> findAll() {
return repo.findAll().stream().map(mapper::toDomain).toList();
}
}

View File

@ -0,0 +1,29 @@
package com.pablotj.portfolio.infrastructure.persistence.certification.entity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.Getter;
import lombok.Setter;
@Entity
@Table(name = "certifications")
@Getter
@Setter
public class CertificationJpaEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String title;
@Column(columnDefinition = "text")
private String description;
private String url;
}

View File

@ -0,0 +1,24 @@
package com.pablotj.portfolio.infrastructure.persistence.certification.mapper;
import com.pablotj.portfolio.domain.certification.Certification;
import com.pablotj.portfolio.domain.certification.CertificationId;
import com.pablotj.portfolio.infrastructure.persistence.certification.entity.CertificationJpaEntity;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
@Mapper(componentModel = "spring")
public interface CertificationJpaMapper {
@Mapping(target = "id", ignore = true)
CertificationJpaEntity toEntity(Certification domain);
default Certification toDomain(CertificationJpaEntity e) {
if (e == null) return null;
return Certification.builder()
.id(e.getId() == null ? null : new CertificationId(e.getId()))
.title(e.getTitle())
.description(e.getDescription())
.url(e.getUrl())
.build();
}
}

View File

@ -0,0 +1,7 @@
package com.pablotj.portfolio.infrastructure.persistence.certification.repo;
import com.pablotj.portfolio.infrastructure.persistence.certification.entity.CertificationJpaEntity;
import org.springframework.data.jpa.repository.JpaRepository;
public interface SpringDataCertificationRepository extends JpaRepository<CertificationJpaEntity, Long> {
}

View File

@ -0,0 +1,40 @@
package com.pablotj.portfolio.infrastructure.persistence.contact.adapter;
import com.pablotj.portfolio.domain.contact.Contact;
import com.pablotj.portfolio.domain.contact.ContactId;
import com.pablotj.portfolio.domain.contact.port.ContactRepositoryPort;
import com.pablotj.portfolio.infrastructure.persistence.contact.entity.ContactJpaEntity;
import com.pablotj.portfolio.infrastructure.persistence.contact.mapper.ContactJpaMapper;
import com.pablotj.portfolio.infrastructure.persistence.contact.repo.SpringDataContactRepository;
import java.util.List;
import java.util.Optional;
import org.springframework.stereotype.Repository;
@Repository
public class ContactRepositoryAdapter implements ContactRepositoryPort {
private final SpringDataContactRepository repo;
private final ContactJpaMapper mapper;
public ContactRepositoryAdapter(SpringDataContactRepository repo, ContactJpaMapper mapper) {
this.repo = repo;
this.mapper = mapper;
}
@Override
public Contact save(Contact p) {
ContactJpaEntity entity = mapper.toEntity(p);
ContactJpaEntity saved = repo.save(entity);
return mapper.toDomain(saved);
}
@Override
public Optional<Contact> findById(ContactId id) {
return repo.findById(id.value()).map(mapper::toDomain);
}
@Override
public List<Contact> findAll() {
return repo.findAll().stream().map(mapper::toDomain).toList();
}
}

View File

@ -0,0 +1,29 @@
package com.pablotj.portfolio.infrastructure.persistence.contact.entity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.Getter;
import lombok.Setter;
@Entity
@Table(name = "contacts")
@Getter
@Setter
public class ContactJpaEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String title;
@Column(columnDefinition = "text")
private String description;
private String url;
}

View File

@ -0,0 +1,24 @@
package com.pablotj.portfolio.infrastructure.persistence.contact.mapper;
import com.pablotj.portfolio.domain.contact.Contact;
import com.pablotj.portfolio.domain.contact.ContactId;
import com.pablotj.portfolio.infrastructure.persistence.contact.entity.ContactJpaEntity;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
@Mapper(componentModel = "spring")
public interface ContactJpaMapper {
@Mapping(target = "id", ignore = true)
ContactJpaEntity toEntity(Contact domain);
default Contact toDomain(ContactJpaEntity e) {
if (e == null) return null;
return Contact.builder()
.id(e.getId() == null ? null : new ContactId(e.getId()))
.title(e.getTitle())
.description(e.getDescription())
.url(e.getUrl())
.build();
}
}

View File

@ -0,0 +1,7 @@
package com.pablotj.portfolio.infrastructure.persistence.contact.repo;
import com.pablotj.portfolio.infrastructure.persistence.contact.entity.ContactJpaEntity;
import org.springframework.data.jpa.repository.JpaRepository;
public interface SpringDataContactRepository extends JpaRepository<ContactJpaEntity, Long> {
}

View File

@ -0,0 +1,40 @@
package com.pablotj.portfolio.infrastructure.persistence.education.adapter;
import com.pablotj.portfolio.domain.education.Education;
import com.pablotj.portfolio.domain.education.EducationId;
import com.pablotj.portfolio.domain.education.port.EducationRepositoryPort;
import com.pablotj.portfolio.infrastructure.persistence.education.entity.EducationJpaEntity;
import com.pablotj.portfolio.infrastructure.persistence.education.mapper.EducationJpaMapper;
import com.pablotj.portfolio.infrastructure.persistence.education.repo.SpringDataEducationRepository;
import java.util.List;
import java.util.Optional;
import org.springframework.stereotype.Repository;
@Repository
public class EducationRepositoryAdapter implements EducationRepositoryPort {
private final SpringDataEducationRepository repo;
private final EducationJpaMapper mapper;
public EducationRepositoryAdapter(SpringDataEducationRepository repo, EducationJpaMapper mapper) {
this.repo = repo;
this.mapper = mapper;
}
@Override
public Education save(Education p) {
EducationJpaEntity entity = mapper.toEntity(p);
EducationJpaEntity saved = repo.save(entity);
return mapper.toDomain(saved);
}
@Override
public Optional<Education> findById(EducationId id) {
return repo.findById(id.value()).map(mapper::toDomain);
}
@Override
public List<Education> findAll() {
return repo.findAll().stream().map(mapper::toDomain).toList();
}
}

View File

@ -0,0 +1,29 @@
package com.pablotj.portfolio.infrastructure.persistence.education.entity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.Getter;
import lombok.Setter;
@Entity
@Table(name = "educations")
@Getter
@Setter
public class EducationJpaEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String title;
@Column(columnDefinition = "text")
private String description;
private String url;
}

View File

@ -0,0 +1,24 @@
package com.pablotj.portfolio.infrastructure.persistence.education.mapper;
import com.pablotj.portfolio.domain.education.Education;
import com.pablotj.portfolio.domain.education.EducationId;
import com.pablotj.portfolio.infrastructure.persistence.education.entity.EducationJpaEntity;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
@Mapper(componentModel = "spring")
public interface EducationJpaMapper {
@Mapping(target = "id", ignore = true)
EducationJpaEntity toEntity(Education domain);
default Education toDomain(EducationJpaEntity e) {
if (e == null) return null;
return Education.builder()
.id(e.getId() == null ? null : new EducationId(e.getId()))
.title(e.getTitle())
.description(e.getDescription())
.url(e.getUrl())
.build();
}
}

View File

@ -0,0 +1,7 @@
package com.pablotj.portfolio.infrastructure.persistence.education.repo;
import com.pablotj.portfolio.infrastructure.persistence.education.entity.EducationJpaEntity;
import org.springframework.data.jpa.repository.JpaRepository;
public interface SpringDataEducationRepository extends JpaRepository<EducationJpaEntity, Long> {
}

View File

@ -0,0 +1,40 @@
package com.pablotj.portfolio.infrastructure.persistence.experience.adapter;
import com.pablotj.portfolio.domain.experience.Experience;
import com.pablotj.portfolio.domain.experience.ExperienceId;
import com.pablotj.portfolio.domain.experience.port.ExperienceRepositoryPort;
import com.pablotj.portfolio.infrastructure.persistence.experience.entity.ExperienceJpaEntity;
import com.pablotj.portfolio.infrastructure.persistence.experience.mapper.ExperienceJpaMapper;
import com.pablotj.portfolio.infrastructure.persistence.experience.repo.SpringDataExperienceRepository;
import java.util.List;
import java.util.Optional;
import org.springframework.stereotype.Repository;
@Repository
public class ExperienceRepositoryAdapter implements ExperienceRepositoryPort {
private final SpringDataExperienceRepository repo;
private final ExperienceJpaMapper mapper;
public ExperienceRepositoryAdapter(SpringDataExperienceRepository repo, ExperienceJpaMapper mapper) {
this.repo = repo;
this.mapper = mapper;
}
@Override
public Experience save(Experience p) {
ExperienceJpaEntity entity = mapper.toEntity(p);
ExperienceJpaEntity saved = repo.save(entity);
return mapper.toDomain(saved);
}
@Override
public Optional<Experience> findById(ExperienceId id) {
return repo.findById(id.value()).map(mapper::toDomain);
}
@Override
public List<Experience> findAll() {
return repo.findAll().stream().map(mapper::toDomain).toList();
}
}

View File

@ -0,0 +1,29 @@
package com.pablotj.portfolio.infrastructure.persistence.experience.entity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.Getter;
import lombok.Setter;
@Entity
@Table(name = "experiences")
@Getter
@Setter
public class ExperienceJpaEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String title;
@Column(columnDefinition = "text")
private String description;
private String url;
}

View File

@ -0,0 +1,24 @@
package com.pablotj.portfolio.infrastructure.persistence.experience.mapper;
import com.pablotj.portfolio.domain.experience.Experience;
import com.pablotj.portfolio.domain.experience.ExperienceId;
import com.pablotj.portfolio.infrastructure.persistence.experience.entity.ExperienceJpaEntity;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
@Mapper(componentModel = "spring")
public interface ExperienceJpaMapper {
@Mapping(target = "id", ignore = true)
ExperienceJpaEntity toEntity(Experience domain);
default Experience toDomain(ExperienceJpaEntity e) {
if (e == null) return null;
return Experience.builder()
.id(e.getId() == null ? null : new ExperienceId(e.getId()))
.title(e.getTitle())
.description(e.getDescription())
.url(e.getUrl())
.build();
}
}

View File

@ -0,0 +1,7 @@
package com.pablotj.portfolio.infrastructure.persistence.experience.repo;
import com.pablotj.portfolio.infrastructure.persistence.experience.entity.ExperienceJpaEntity;
import org.springframework.data.jpa.repository.JpaRepository;
public interface SpringDataExperienceRepository extends JpaRepository<ExperienceJpaEntity, Long> {
}

View File

@ -0,0 +1,40 @@
package com.pablotj.portfolio.infrastructure.persistence.home.adapter;
import com.pablotj.portfolio.domain.home.Home;
import com.pablotj.portfolio.domain.home.HomeId;
import com.pablotj.portfolio.domain.home.port.HomeRepositoryPort;
import com.pablotj.portfolio.infrastructure.persistence.home.entity.HomeJpaEntity;
import com.pablotj.portfolio.infrastructure.persistence.home.mapper.HomeJpaMapper;
import com.pablotj.portfolio.infrastructure.persistence.home.repo.SpringDataHomeRepository;
import java.util.List;
import java.util.Optional;
import org.springframework.stereotype.Repository;
@Repository
public class HomeRepositoryAdapter implements HomeRepositoryPort {
private final SpringDataHomeRepository repo;
private final HomeJpaMapper mapper;
public HomeRepositoryAdapter(SpringDataHomeRepository repo, HomeJpaMapper mapper) {
this.repo = repo;
this.mapper = mapper;
}
@Override
public Home save(Home p) {
HomeJpaEntity entity = mapper.toEntity(p);
HomeJpaEntity saved = repo.save(entity);
return mapper.toDomain(saved);
}
@Override
public Optional<Home> findById(HomeId id) {
return repo.findById(id.value()).map(mapper::toDomain);
}
@Override
public List<Home> findAll() {
return repo.findAll().stream().map(mapper::toDomain).toList();
}
}

View File

@ -0,0 +1,29 @@
package com.pablotj.portfolio.infrastructure.persistence.home.entity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.Getter;
import lombok.Setter;
@Entity
@Table(name = "homes")
@Getter
@Setter
public class HomeJpaEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String title;
@Column(columnDefinition = "text")
private String description;
private String url;
}

View File

@ -0,0 +1,24 @@
package com.pablotj.portfolio.infrastructure.persistence.home.mapper;
import com.pablotj.portfolio.domain.home.Home;
import com.pablotj.portfolio.domain.home.HomeId;
import com.pablotj.portfolio.infrastructure.persistence.home.entity.HomeJpaEntity;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
@Mapper(componentModel = "spring")
public interface HomeJpaMapper {
@Mapping(target = "id", ignore = true)
HomeJpaEntity toEntity(Home domain);
default Home toDomain(HomeJpaEntity e) {
if (e == null) return null;
return Home.builder()
.id(e.getId() == null ? null : new HomeId(e.getId()))
.title(e.getTitle())
.description(e.getDescription())
.url(e.getUrl())
.build();
}
}

View File

@ -0,0 +1,7 @@
package com.pablotj.portfolio.infrastructure.persistence.home.repo;
import com.pablotj.portfolio.infrastructure.persistence.home.entity.HomeJpaEntity;
import org.springframework.data.jpa.repository.JpaRepository;
public interface SpringDataHomeRepository extends JpaRepository<HomeJpaEntity, Long> {
}

View File

@ -0,0 +1,40 @@
package com.pablotj.portfolio.infrastructure.persistence.skill.adapter;
import com.pablotj.portfolio.domain.skill.Skill;
import com.pablotj.portfolio.domain.skill.SkillId;
import com.pablotj.portfolio.domain.skill.port.SkillRepositoryPort;
import com.pablotj.portfolio.infrastructure.persistence.skill.entity.SkillJpaEntity;
import com.pablotj.portfolio.infrastructure.persistence.skill.mapper.SkillJpaMapper;
import com.pablotj.portfolio.infrastructure.persistence.skill.repo.SpringDataSkillRepository;
import java.util.List;
import java.util.Optional;
import org.springframework.stereotype.Repository;
@Repository
public class SkillRepositoryAdapter implements SkillRepositoryPort {
private final SpringDataSkillRepository repo;
private final SkillJpaMapper mapper;
public SkillRepositoryAdapter(SpringDataSkillRepository repo, SkillJpaMapper mapper) {
this.repo = repo;
this.mapper = mapper;
}
@Override
public Skill save(Skill p) {
SkillJpaEntity entity = mapper.toEntity(p);
SkillJpaEntity saved = repo.save(entity);
return mapper.toDomain(saved);
}
@Override
public Optional<Skill> findById(SkillId id) {
return repo.findById(id.value()).map(mapper::toDomain);
}
@Override
public List<Skill> findAll() {
return repo.findAll().stream().map(mapper::toDomain).toList();
}
}

View File

@ -0,0 +1,29 @@
package com.pablotj.portfolio.infrastructure.persistence.skill.entity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.Getter;
import lombok.Setter;
@Entity
@Table(name = "skills")
@Getter
@Setter
public class SkillJpaEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String title;
@Column(columnDefinition = "text")
private String description;
private String url;
}

View File

@ -0,0 +1,24 @@
package com.pablotj.portfolio.infrastructure.persistence.skill.mapper;
import com.pablotj.portfolio.domain.skill.Skill;
import com.pablotj.portfolio.domain.skill.SkillId;
import com.pablotj.portfolio.infrastructure.persistence.skill.entity.SkillJpaEntity;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
@Mapper(componentModel = "spring")
public interface SkillJpaMapper {
@Mapping(target = "id", ignore = true)
SkillJpaEntity toEntity(Skill domain);
default Skill toDomain(SkillJpaEntity e) {
if (e == null) return null;
return Skill.builder()
.id(e.getId() == null ? null : new SkillId(e.getId()))
.title(e.getTitle())
.description(e.getDescription())
.url(e.getUrl())
.build();
}
}

View File

@ -0,0 +1,7 @@
package com.pablotj.portfolio.infrastructure.persistence.skill.repo;
import com.pablotj.portfolio.infrastructure.persistence.skill.entity.SkillJpaEntity;
import org.springframework.data.jpa.repository.JpaRepository;
public interface SpringDataSkillRepository extends JpaRepository<SkillJpaEntity, Long> {
}

View File

@ -0,0 +1,56 @@
package com.pablotj.portfolio.infrastructure.rest.about.controller;
import com.pablotj.portfolio.application.about.CreateAboutUseCase;
import com.pablotj.portfolio.application.about.GetAboutUseCase;
import com.pablotj.portfolio.infrastructure.rest.about.dto.AboutDto;
import com.pablotj.portfolio.infrastructure.rest.about.mapper.AboutRestMapper;
import jakarta.validation.Valid;
import java.net.URI;
import java.util.List;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/v1/abouts")
public class AboutController {
private final CreateAboutUseCase createUC;
private final GetAboutUseCase getUC;
private final AboutRestMapper mapper;
public AboutController(CreateAboutUseCase createUC, GetAboutUseCase getUC, AboutRestMapper mapper) {
this.createUC = createUC;
this.getUC = getUC;
this.mapper = mapper;
}
@GetMapping
public List<AboutDto> all() {
return getUC.all().stream().map(mapper::toDto).toList();
}
@GetMapping("/{id}")
public ResponseEntity<AboutDto> byId(@PathVariable Long id) {
return getUC.byId(id)
.map(mapper::toDto)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
@PostMapping
public ResponseEntity<AboutDto> create(@Valid @RequestBody com.pablotj.portfolio.infrastructure.rest.about.dto.CreateAboutRequest request) {
var cmd = new CreateAboutUseCase.Command(
request.title(),
request.description(),
request.url()
);
var created = createUC.handle(cmd);
var body = mapper.toDto(created);
return ResponseEntity.created(URI.create("/api/abouts/" + body.id())).body(body);
}
}

View File

@ -0,0 +1,6 @@
package com.pablotj.portfolio.infrastructure.rest.about.dto;
import jakarta.validation.constraints.NotBlank;
public record AboutDto(Long id, @NotBlank String title, String description, String url) {
}

View File

@ -0,0 +1,10 @@
package com.pablotj.portfolio.infrastructure.rest.about.dto;
import jakarta.validation.constraints.NotBlank;
public record CreateAboutRequest(
@NotBlank String title,
String description,
String url
) {
}

View File

@ -0,0 +1,13 @@
package com.pablotj.portfolio.infrastructure.rest.about.mapper;
import com.pablotj.portfolio.domain.about.About;
import com.pablotj.portfolio.infrastructure.rest.about.dto.AboutDto;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
@Mapper(componentModel = "spring")
public interface AboutRestMapper {
@Mapping(target = "id", source = "id.value")
AboutDto toDto(About domain);
}

View File

@ -1,13 +1,12 @@
package com.pablotj.portfolio.infrastructure.rest.api;
import java.util.List;
import java.util.Map;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping
public class ApiRootController {
@ -20,9 +19,14 @@ public class ApiRootController {
"doc", "/v3/api-docs",
"swagger", "/swagger-ui",
"endpoints", List.of(
Map.of("path", "/v1/homes", "description", "Manage projects"),
Map.of("path", "/v1/certifications", "description", "Manage projects"),
Map.of("path", "/v1/projects", "description", "Manage projects"),
Map.of("path", "/v1/experience", "description", "Experience entries"),
Map.of("path", "/v1/about", "description", "About me")
Map.of("path", "/v1/contacts", "description", "Manage projects"),
Map.of("path", "/v1/educations", "description", "Manage projects"),
Map.of("path", "/v1/experiences", "description", "Manage projects"),
Map.of("path", "/v1/projects", "description", "Manage projects"),
Map.of("path", "/v1/skills", "description", "Experience entries")
)
);

View File

@ -0,0 +1,57 @@
package com.pablotj.portfolio.infrastructure.rest.certification.controller;
import com.pablotj.portfolio.application.certification.CreateCertificationUseCase;
import com.pablotj.portfolio.application.certification.GetCertificationUseCase;
import com.pablotj.portfolio.infrastructure.rest.certification.dto.CertificationDto;
import com.pablotj.portfolio.infrastructure.rest.certification.dto.CreateCertificationRequest;
import com.pablotj.portfolio.infrastructure.rest.certification.mapper.CertificationRestMapper;
import jakarta.validation.Valid;
import java.net.URI;
import java.util.List;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/v1/certifications")
public class CertificationController {
private final CreateCertificationUseCase createUC;
private final GetCertificationUseCase getUC;
private final CertificationRestMapper mapper;
public CertificationController(CreateCertificationUseCase createUC, GetCertificationUseCase getUC, CertificationRestMapper mapper) {
this.createUC = createUC;
this.getUC = getUC;
this.mapper = mapper;
}
@GetMapping
public List<CertificationDto> all() {
return getUC.all().stream().map(mapper::toDto).toList();
}
@GetMapping("/{id}")
public ResponseEntity<CertificationDto> byId(@PathVariable Long id) {
return getUC.byId(id)
.map(mapper::toDto)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
@PostMapping
public ResponseEntity<CertificationDto> create(@Valid @RequestBody CreateCertificationRequest request) {
var cmd = new CreateCertificationUseCase.Command(
request.title(),
request.description(),
request.url()
);
var created = createUC.handle(cmd);
var body = mapper.toDto(created);
return ResponseEntity.created(URI.create("/api/certifications/" + body.id())).body(body);
}
}

View File

@ -0,0 +1,6 @@
package com.pablotj.portfolio.infrastructure.rest.certification.dto;
import jakarta.validation.constraints.NotBlank;
public record CertificationDto(Long id, @NotBlank String title, String description, String url) {
}

View File

@ -0,0 +1,10 @@
package com.pablotj.portfolio.infrastructure.rest.certification.dto;
import jakarta.validation.constraints.NotBlank;
public record CreateCertificationRequest(
@NotBlank String title,
String description,
String url
) {
}

View File

@ -0,0 +1,13 @@
package com.pablotj.portfolio.infrastructure.rest.certification.mapper;
import com.pablotj.portfolio.domain.certification.Certification;
import com.pablotj.portfolio.infrastructure.rest.certification.dto.CertificationDto;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
@Mapper(componentModel = "spring")
public interface CertificationRestMapper {
@Mapping(target = "id", source = "id.value")
CertificationDto toDto(Certification domain);
}

View File

@ -0,0 +1,57 @@
package com.pablotj.portfolio.infrastructure.rest.contact.controller;
import com.pablotj.portfolio.application.contact.CreateContactUseCase;
import com.pablotj.portfolio.application.contact.GetContactUseCase;
import com.pablotj.portfolio.infrastructure.rest.contact.dto.ContactDto;
import com.pablotj.portfolio.infrastructure.rest.contact.dto.CreateContactRequest;
import com.pablotj.portfolio.infrastructure.rest.contact.mapper.ContactRestMapper;
import jakarta.validation.Valid;
import java.net.URI;
import java.util.List;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/v1/contacts")
public class ContactController {
private final CreateContactUseCase createUC;
private final GetContactUseCase getUC;
private final ContactRestMapper mapper;
public ContactController(CreateContactUseCase createUC, GetContactUseCase getUC, ContactRestMapper mapper) {
this.createUC = createUC;
this.getUC = getUC;
this.mapper = mapper;
}
@GetMapping
public List<ContactDto> all() {
return getUC.all().stream().map(mapper::toDto).toList();
}
@GetMapping("/{id}")
public ResponseEntity<ContactDto> byId(@PathVariable Long id) {
return getUC.byId(id)
.map(mapper::toDto)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
@PostMapping
public ResponseEntity<ContactDto> create(@Valid @RequestBody CreateContactRequest request) {
var cmd = new CreateContactUseCase.Command(
request.title(),
request.description(),
request.url()
);
var created = createUC.handle(cmd);
var body = mapper.toDto(created);
return ResponseEntity.created(URI.create("/api/contacts/" + body.id())).body(body);
}
}

View File

@ -0,0 +1,6 @@
package com.pablotj.portfolio.infrastructure.rest.contact.dto;
import jakarta.validation.constraints.NotBlank;
public record ContactDto(Long id, @NotBlank String title, String description, String url) {
}

View File

@ -0,0 +1,10 @@
package com.pablotj.portfolio.infrastructure.rest.contact.dto;
import jakarta.validation.constraints.NotBlank;
public record CreateContactRequest(
@NotBlank String title,
String description,
String url
) {
}

View File

@ -0,0 +1,13 @@
package com.pablotj.portfolio.infrastructure.rest.contact.mapper;
import com.pablotj.portfolio.domain.contact.Contact;
import com.pablotj.portfolio.infrastructure.rest.contact.dto.ContactDto;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
@Mapper(componentModel = "spring")
public interface ContactRestMapper {
@Mapping(target = "id", source = "id.value")
ContactDto toDto(Contact domain);
}

View File

@ -0,0 +1,57 @@
package com.pablotj.portfolio.infrastructure.rest.education.controller;
import com.pablotj.portfolio.application.education.CreateEducationUseCase;
import com.pablotj.portfolio.application.education.GetEducationUseCase;
import com.pablotj.portfolio.infrastructure.rest.education.dto.CreateEducationRequest;
import com.pablotj.portfolio.infrastructure.rest.education.dto.EducationDto;
import com.pablotj.portfolio.infrastructure.rest.education.mapper.EducationRestMapper;
import jakarta.validation.Valid;
import java.net.URI;
import java.util.List;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/v1/educations")
public class EducationController {
private final CreateEducationUseCase createUC;
private final GetEducationUseCase getUC;
private final EducationRestMapper mapper;
public EducationController(CreateEducationUseCase createUC, GetEducationUseCase getUC, EducationRestMapper mapper) {
this.createUC = createUC;
this.getUC = getUC;
this.mapper = mapper;
}
@GetMapping
public List<EducationDto> all() {
return getUC.all().stream().map(mapper::toDto).toList();
}
@GetMapping("/{id}")
public ResponseEntity<EducationDto> byId(@PathVariable Long id) {
return getUC.byId(id)
.map(mapper::toDto)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
@PostMapping
public ResponseEntity<EducationDto> create(@Valid @RequestBody CreateEducationRequest request) {
var cmd = new CreateEducationUseCase.Command(
request.title(),
request.description(),
request.url()
);
var created = createUC.handle(cmd);
var body = mapper.toDto(created);
return ResponseEntity.created(URI.create("/api/educations/" + body.id())).body(body);
}
}

View File

@ -0,0 +1,10 @@
package com.pablotj.portfolio.infrastructure.rest.education.dto;
import jakarta.validation.constraints.NotBlank;
public record CreateEducationRequest(
@NotBlank String title,
String description,
String url
) {
}

View File

@ -0,0 +1,6 @@
package com.pablotj.portfolio.infrastructure.rest.education.dto;
import jakarta.validation.constraints.NotBlank;
public record EducationDto(Long id, @NotBlank String title, String description, String url) {
}

View File

@ -0,0 +1,13 @@
package com.pablotj.portfolio.infrastructure.rest.education.mapper;
import com.pablotj.portfolio.domain.education.Education;
import com.pablotj.portfolio.infrastructure.rest.education.dto.EducationDto;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
@Mapper(componentModel = "spring")
public interface EducationRestMapper {
@Mapping(target = "id", source = "id.value")
EducationDto toDto(Education domain);
}

View File

@ -0,0 +1,57 @@
package com.pablotj.portfolio.infrastructure.rest.experience.controller;
import com.pablotj.portfolio.application.experience.CreateExperienceUseCase;
import com.pablotj.portfolio.application.experience.GetExperienceUseCase;
import com.pablotj.portfolio.infrastructure.rest.experience.dto.CreateExperienceRequest;
import com.pablotj.portfolio.infrastructure.rest.experience.dto.ExperienceDto;
import com.pablotj.portfolio.infrastructure.rest.experience.mapper.ExperienceRestMapper;
import jakarta.validation.Valid;
import java.net.URI;
import java.util.List;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/v1/experiences")
public class ExperienceController {
private final CreateExperienceUseCase createUC;
private final GetExperienceUseCase getUC;
private final ExperienceRestMapper mapper;
public ExperienceController(CreateExperienceUseCase createUC, GetExperienceUseCase getUC, ExperienceRestMapper mapper) {
this.createUC = createUC;
this.getUC = getUC;
this.mapper = mapper;
}
@GetMapping
public List<ExperienceDto> all() {
return getUC.all().stream().map(mapper::toDto).toList();
}
@GetMapping("/{id}")
public ResponseEntity<ExperienceDto> byId(@PathVariable Long id) {
return getUC.byId(id)
.map(mapper::toDto)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
@PostMapping
public ResponseEntity<ExperienceDto> create(@Valid @RequestBody CreateExperienceRequest request) {
var cmd = new CreateExperienceUseCase.Command(
request.title(),
request.description(),
request.url()
);
var created = createUC.handle(cmd);
var body = mapper.toDto(created);
return ResponseEntity.created(URI.create("/api/experiences/" + body.id())).body(body);
}
}

View File

@ -0,0 +1,10 @@
package com.pablotj.portfolio.infrastructure.rest.experience.dto;
import jakarta.validation.constraints.NotBlank;
public record CreateExperienceRequest(
@NotBlank String title,
String description,
String url
) {
}

View File

@ -0,0 +1,6 @@
package com.pablotj.portfolio.infrastructure.rest.experience.dto;
import jakarta.validation.constraints.NotBlank;
public record ExperienceDto(Long id, @NotBlank String title, String description, String url) {
}

View File

@ -0,0 +1,13 @@
package com.pablotj.portfolio.infrastructure.rest.experience.mapper;
import com.pablotj.portfolio.domain.experience.Experience;
import com.pablotj.portfolio.infrastructure.rest.experience.dto.ExperienceDto;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
@Mapper(componentModel = "spring")
public interface ExperienceRestMapper {
@Mapping(target = "id", source = "id.value")
ExperienceDto toDto(Experience domain);
}

View File

@ -0,0 +1,57 @@
package com.pablotj.portfolio.infrastructure.rest.home.controller;
import com.pablotj.portfolio.application.home.CreateHomeUseCase;
import com.pablotj.portfolio.application.home.GetHomeUseCase;
import com.pablotj.portfolio.infrastructure.rest.home.dto.CreateHomeRequest;
import com.pablotj.portfolio.infrastructure.rest.home.dto.HomeDto;
import com.pablotj.portfolio.infrastructure.rest.home.mapper.HomeRestMapper;
import jakarta.validation.Valid;
import java.net.URI;
import java.util.List;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/v1/homes")
public class HomeController {
private final CreateHomeUseCase createUC;
private final GetHomeUseCase getUC;
private final HomeRestMapper mapper;
public HomeController(CreateHomeUseCase createUC, GetHomeUseCase getUC, HomeRestMapper mapper) {
this.createUC = createUC;
this.getUC = getUC;
this.mapper = mapper;
}
@GetMapping
public List<HomeDto> all() {
return getUC.all().stream().map(mapper::toDto).toList();
}
@GetMapping("/{id}")
public ResponseEntity<HomeDto> byId(@PathVariable Long id) {
return getUC.byId(id)
.map(mapper::toDto)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
@PostMapping
public ResponseEntity<HomeDto> create(@Valid @RequestBody CreateHomeRequest request) {
var cmd = new CreateHomeUseCase.Command(
request.title(),
request.description(),
request.url()
);
var created = createUC.handle(cmd);
var body = mapper.toDto(created);
return ResponseEntity.created(URI.create("/api/homes/" + body.id())).body(body);
}
}

View File

@ -0,0 +1,10 @@
package com.pablotj.portfolio.infrastructure.rest.home.dto;
import jakarta.validation.constraints.NotBlank;
public record CreateHomeRequest(
@NotBlank String title,
String description,
String url
) {
}

View File

@ -0,0 +1,6 @@
package com.pablotj.portfolio.infrastructure.rest.home.dto;
import jakarta.validation.constraints.NotBlank;
public record HomeDto(Long id, @NotBlank String title, String description, String url) {
}

View File

@ -0,0 +1,13 @@
package com.pablotj.portfolio.infrastructure.rest.home.mapper;
import com.pablotj.portfolio.domain.home.Home;
import com.pablotj.portfolio.infrastructure.rest.home.dto.HomeDto;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
@Mapper(componentModel = "spring")
public interface HomeRestMapper {
@Mapping(target = "id", source = "id.value")
HomeDto toDto(Home domain);
}

View File

@ -0,0 +1,57 @@
package com.pablotj.portfolio.infrastructure.rest.skill.controller;
import com.pablotj.portfolio.application.skill.CreateSkillUseCase;
import com.pablotj.portfolio.application.skill.GetSkillUseCase;
import com.pablotj.portfolio.infrastructure.rest.skill.dto.CreateSkillRequest;
import com.pablotj.portfolio.infrastructure.rest.skill.dto.SkillDto;
import com.pablotj.portfolio.infrastructure.rest.skill.mapper.SkillRestMapper;
import jakarta.validation.Valid;
import java.net.URI;
import java.util.List;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/v1/skills")
public class SkillController {
private final CreateSkillUseCase createUC;
private final GetSkillUseCase getUC;
private final SkillRestMapper mapper;
public SkillController(CreateSkillUseCase createUC, GetSkillUseCase getUC, SkillRestMapper mapper) {
this.createUC = createUC;
this.getUC = getUC;
this.mapper = mapper;
}
@GetMapping
public List<SkillDto> all() {
return getUC.all().stream().map(mapper::toDto).toList();
}
@GetMapping("/{id}")
public ResponseEntity<SkillDto> byId(@PathVariable Long id) {
return getUC.byId(id)
.map(mapper::toDto)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
@PostMapping
public ResponseEntity<SkillDto> create(@Valid @RequestBody CreateSkillRequest request) {
var cmd = new CreateSkillUseCase.Command(
request.title(),
request.description(),
request.url()
);
var created = createUC.handle(cmd);
var body = mapper.toDto(created);
return ResponseEntity.created(URI.create("/api/skills/" + body.id())).body(body);
}
}

View File

@ -0,0 +1,10 @@
package com.pablotj.portfolio.infrastructure.rest.skill.dto;
import jakarta.validation.constraints.NotBlank;
public record CreateSkillRequest(
@NotBlank String title,
String description,
String url
) {
}

View File

@ -0,0 +1,6 @@
package com.pablotj.portfolio.infrastructure.rest.skill.dto;
import jakarta.validation.constraints.NotBlank;
public record SkillDto(Long id, @NotBlank String title, String description, String url) {
}

View File

@ -0,0 +1,13 @@
package com.pablotj.portfolio.infrastructure.rest.skill.mapper;
import com.pablotj.portfolio.domain.skill.Skill;
import com.pablotj.portfolio.infrastructure.rest.skill.dto.SkillDto;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
@Mapper(componentModel = "spring")
public interface SkillRestMapper {
@Mapping(target = "id", source = "id.value")
SkillDto toDto(Skill domain);
}