mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-12 00:15:44 +01:00
Introduce interface to be used by dto mappers with Instant fields
This commit is contained in:
@@ -3,14 +3,8 @@ package sonia.scm.api.v2.resources;
|
|||||||
import de.otto.edison.hal.HalRepresentation;
|
import de.otto.edison.hal.HalRepresentation;
|
||||||
import org.mapstruct.Mapping;
|
import org.mapstruct.Mapping;
|
||||||
|
|
||||||
import java.time.Instant;
|
public abstract class BaseMapper<T, D extends HalRepresentation> implements InstantAttributeMapper {
|
||||||
|
|
||||||
public abstract class BaseMapper<T, D extends HalRepresentation> {
|
|
||||||
|
|
||||||
@Mapping(target = "attributes", ignore = true) // We do not map HAL attributes
|
@Mapping(target = "attributes", ignore = true) // We do not map HAL attributes
|
||||||
public abstract D map(T modelObject);
|
public abstract D map(T modelObject);
|
||||||
|
|
||||||
protected Instant mapTime(Long epochMilli) {
|
|
||||||
return epochMilli == null? null: Instant.ofEpochMilli(epochMilli);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package sonia.scm.api.v2.resources;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
public interface InstantAttributeMapper {
|
||||||
|
default Instant mapTime(Long epochMilli) {
|
||||||
|
return epochMilli == null? null: Instant.ofEpochMilli(epochMilli);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,73 +1,21 @@
|
|||||||
package sonia.scm.api.v2.resources;
|
package sonia.scm.api.v2.resources;
|
||||||
|
|
||||||
import de.otto.edison.hal.Embedded;
|
|
||||||
import de.otto.edison.hal.HalRepresentation;
|
import de.otto.edison.hal.HalRepresentation;
|
||||||
import de.otto.edison.hal.Links;
|
|
||||||
import de.otto.edison.hal.paging.NumberedPaging;
|
|
||||||
import de.otto.edison.hal.paging.PagingRel;
|
|
||||||
import sonia.scm.ModelObject;
|
import sonia.scm.ModelObject;
|
||||||
import sonia.scm.PageResult;
|
import sonia.scm.PageResult;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import java.util.EnumSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
import static com.damnhandy.uri.template.UriTemplate.fromTemplate;
|
public class BasicCollectionToDtoMapper<E extends ModelObject, D extends HalRepresentation, M extends BaseMapper<E, D>> extends PagedCollectionToDtoMapper<E, D> {
|
||||||
import static de.otto.edison.hal.Embedded.embeddedBuilder;
|
|
||||||
import static de.otto.edison.hal.Link.link;
|
|
||||||
import static de.otto.edison.hal.Links.linkingTo;
|
|
||||||
import static de.otto.edison.hal.paging.NumberedPaging.zeroBasedNumberedPaging;
|
|
||||||
import static java.util.stream.Collectors.toList;
|
|
||||||
|
|
||||||
abstract class BasicCollectionToDtoMapper<E extends ModelObject, D extends HalRepresentation, M extends BaseMapper<E, D>> {
|
|
||||||
|
|
||||||
private final String collectionName;
|
|
||||||
|
|
||||||
private final M entityToDtoMapper;
|
private final M entityToDtoMapper;
|
||||||
|
|
||||||
@Inject
|
|
||||||
public BasicCollectionToDtoMapper(String collectionName, M entityToDtoMapper) {
|
public BasicCollectionToDtoMapper(String collectionName, M entityToDtoMapper) {
|
||||||
this.collectionName = collectionName;
|
super(collectionName);
|
||||||
this.entityToDtoMapper = entityToDtoMapper;
|
this.entityToDtoMapper = entityToDtoMapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
CollectionDto map(int pageNumber, int pageSize, PageResult<E> pageResult, String selfLink, Optional<String> createLink) {
|
CollectionDto map(int pageNumber, int pageSize, PageResult<E> pageResult, String selfLink, Optional<String> createLink) {
|
||||||
return map(pageNumber, pageSize, pageResult, selfLink, createLink, entityToDtoMapper::map);
|
return map(pageNumber, pageSize, pageResult, selfLink, createLink, entityToDtoMapper::map);
|
||||||
}
|
}
|
||||||
|
|
||||||
CollectionDto map(int pageNumber, int pageSize, PageResult<E> pageResult, String selfLink, Optional<String> createLink, Function<E, ? extends HalRepresentation> mapper) {
|
|
||||||
NumberedPaging paging = zeroBasedNumberedPaging(pageNumber, pageSize, pageResult.getOverallCount());
|
|
||||||
List<HalRepresentation> dtos = pageResult.getEntities().stream().map(mapper).collect(toList());
|
|
||||||
CollectionDto collectionDto = new CollectionDto(
|
|
||||||
createLinks(paging, selfLink, createLink),
|
|
||||||
embedDtos(dtos));
|
|
||||||
collectionDto.setPage(pageNumber);
|
|
||||||
collectionDto.setPageTotal(computePageTotal(pageSize, pageResult));
|
|
||||||
return collectionDto;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int computePageTotal(int pageSize, PageResult<E> pageResult) {
|
|
||||||
if (pageResult.getOverallCount() % pageSize > 0) {
|
|
||||||
return pageResult.getOverallCount() / pageSize + 1;
|
|
||||||
} else {
|
|
||||||
return pageResult.getOverallCount() / pageSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Links createLinks(NumberedPaging page, String selfLink, Optional<String> createLink) {
|
|
||||||
Links.Builder linksBuilder = linkingTo()
|
|
||||||
.with(page.links(
|
|
||||||
fromTemplate(selfLink + "{?page,pageSize}"),
|
|
||||||
EnumSet.allOf(PagingRel.class)));
|
|
||||||
createLink.ifPresent(link -> linksBuilder.single(link("create", link)));
|
|
||||||
return linksBuilder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Embedded embedDtos(List<HalRepresentation> dtos) {
|
|
||||||
return embeddedBuilder()
|
|
||||||
.with(collectionName, dtos)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,14 +8,14 @@ import javax.inject.Inject;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class ChangesetCollectionToDtoMapper extends BasicCollectionToDtoMapper<Changeset, ChangesetDto, ChangesetToChangesetDtoMapper> {
|
public class ChangesetCollectionToDtoMapper extends PagedCollectionToDtoMapper<Changeset, ChangesetDto> {
|
||||||
|
|
||||||
private final ChangesetToChangesetDtoMapper changesetToChangesetDtoMapper;
|
private final ChangesetToChangesetDtoMapper changesetToChangesetDtoMapper;
|
||||||
protected final ResourceLinks resourceLinks;
|
protected final ResourceLinks resourceLinks;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public ChangesetCollectionToDtoMapper(ChangesetToChangesetDtoMapper changesetToChangesetDtoMapper, ResourceLinks resourceLinks) {
|
public ChangesetCollectionToDtoMapper(ChangesetToChangesetDtoMapper changesetToChangesetDtoMapper, ResourceLinks resourceLinks) {
|
||||||
super("changesets", changesetToChangesetDtoMapper);
|
super("changesets");
|
||||||
this.changesetToChangesetDtoMapper = changesetToChangesetDtoMapper;
|
this.changesetToChangesetDtoMapper = changesetToChangesetDtoMapper;
|
||||||
this.resourceLinks = resourceLinks;
|
this.resourceLinks = resourceLinks;
|
||||||
}
|
}
|
||||||
@@ -32,3 +32,4 @@ public class ChangesetCollectionToDtoMapper extends BasicCollectionToDtoMapper<C
|
|||||||
return resourceLinks.changeset().all(repository.getNamespace(), repository.getName());
|
return resourceLinks.changeset().all(repository.getNamespace(), repository.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import static de.otto.edison.hal.Link.link;
|
|||||||
import static de.otto.edison.hal.Links.linkingTo;
|
import static de.otto.edison.hal.Links.linkingTo;
|
||||||
|
|
||||||
@Mapper
|
@Mapper
|
||||||
public abstract class ChangesetToChangesetDtoMapper extends BaseMapper<Changeset, ChangesetDto> {
|
public abstract class ChangesetToChangesetDtoMapper implements InstantAttributeMapper {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private RepositoryServiceFactory serviceFactory;
|
private RepositoryServiceFactory serviceFactory;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import static de.otto.edison.hal.Link.link;
|
|||||||
import static de.otto.edison.hal.Links.linkingTo;
|
import static de.otto.edison.hal.Links.linkingTo;
|
||||||
|
|
||||||
@Mapper
|
@Mapper
|
||||||
public abstract class ChangesetToParentDtoMapper extends BaseMapper<Changeset, ParentChangesetDto> {
|
public abstract class ChangesetToParentDtoMapper {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private ResourceLinks resourceLinks;
|
private ResourceLinks resourceLinks;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import de.otto.edison.hal.Links;
|
|||||||
import org.mapstruct.AfterMapping;
|
import org.mapstruct.AfterMapping;
|
||||||
import org.mapstruct.Context;
|
import org.mapstruct.Context;
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
import org.mapstruct.MappingTarget;
|
import org.mapstruct.MappingTarget;
|
||||||
import sonia.scm.repository.FileObject;
|
import sonia.scm.repository.FileObject;
|
||||||
import sonia.scm.repository.NamespaceAndName;
|
import sonia.scm.repository.NamespaceAndName;
|
||||||
@@ -14,11 +15,12 @@ import javax.inject.Inject;
|
|||||||
import static de.otto.edison.hal.Link.link;
|
import static de.otto.edison.hal.Link.link;
|
||||||
|
|
||||||
@Mapper
|
@Mapper
|
||||||
public abstract class FileObjectToFileObjectDtoMapper extends BaseMapper<FileObject, FileObjectDto> {
|
public abstract class FileObjectToFileObjectDtoMapper implements InstantAttributeMapper {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private ResourceLinks resourceLinks;
|
private ResourceLinks resourceLinks;
|
||||||
|
|
||||||
|
@Mapping(target = "attributes", ignore = true) // We do not map HAL attributes
|
||||||
protected abstract FileObjectDto map(FileObject fileObject, @Context NamespaceAndName namespaceAndName, @Context String revision);
|
protected abstract FileObjectDto map(FileObject fileObject, @Context NamespaceAndName namespaceAndName, @Context String revision);
|
||||||
|
|
||||||
abstract SubRepositoryDto mapSubrepository(SubRepository subRepository);
|
abstract SubRepositoryDto mapSubrepository(SubRepository subRepository);
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
package sonia.scm.api.v2.resources;
|
||||||
|
|
||||||
|
import de.otto.edison.hal.Embedded;
|
||||||
|
import de.otto.edison.hal.HalRepresentation;
|
||||||
|
import de.otto.edison.hal.Links;
|
||||||
|
import de.otto.edison.hal.paging.NumberedPaging;
|
||||||
|
import de.otto.edison.hal.paging.PagingRel;
|
||||||
|
import sonia.scm.ModelObject;
|
||||||
|
import sonia.scm.PageResult;
|
||||||
|
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import static com.damnhandy.uri.template.UriTemplate.fromTemplate;
|
||||||
|
import static de.otto.edison.hal.Embedded.embeddedBuilder;
|
||||||
|
import static de.otto.edison.hal.Link.link;
|
||||||
|
import static de.otto.edison.hal.Links.linkingTo;
|
||||||
|
import static de.otto.edison.hal.paging.NumberedPaging.zeroBasedNumberedPaging;
|
||||||
|
import static java.util.stream.Collectors.toList;
|
||||||
|
|
||||||
|
abstract class PagedCollectionToDtoMapper<E extends ModelObject, D extends HalRepresentation> {
|
||||||
|
|
||||||
|
private final String collectionName;
|
||||||
|
|
||||||
|
PagedCollectionToDtoMapper(String collectionName) {
|
||||||
|
this.collectionName = collectionName;
|
||||||
|
}
|
||||||
|
|
||||||
|
CollectionDto map(int pageNumber, int pageSize, PageResult<E> pageResult, String selfLink, Optional<String> createLink, Function<E, ? extends HalRepresentation> mapper) {
|
||||||
|
NumberedPaging paging = zeroBasedNumberedPaging(pageNumber, pageSize, pageResult.getOverallCount());
|
||||||
|
List<HalRepresentation> dtos = pageResult.getEntities().stream().map(mapper).collect(toList());
|
||||||
|
CollectionDto collectionDto = new CollectionDto(
|
||||||
|
createLinks(paging, selfLink, createLink),
|
||||||
|
embedDtos(dtos));
|
||||||
|
collectionDto.setPage(pageNumber);
|
||||||
|
collectionDto.setPageTotal(computePageTotal(pageSize, pageResult));
|
||||||
|
return collectionDto;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int computePageTotal(int pageSize, PageResult<E> pageResult) {
|
||||||
|
if (pageResult.getOverallCount() % pageSize > 0) {
|
||||||
|
return pageResult.getOverallCount() / pageSize + 1;
|
||||||
|
} else {
|
||||||
|
return pageResult.getOverallCount() / pageSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Links createLinks(NumberedPaging page, String selfLink, Optional<String> createLink) {
|
||||||
|
Links.Builder linksBuilder = linkingTo()
|
||||||
|
.with(page.links(
|
||||||
|
fromTemplate(selfLink + "{?page,pageSize}"),
|
||||||
|
EnumSet.allOf(PagingRel.class)));
|
||||||
|
createLink.ifPresent(link -> linksBuilder.single(link("create", link)));
|
||||||
|
return linksBuilder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Embedded embedDtos(List<HalRepresentation> dtos) {
|
||||||
|
return embeddedBuilder()
|
||||||
|
.with(collectionName, dtos)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,8 +10,6 @@ import java.util.Optional;
|
|||||||
import static java.util.Optional.empty;
|
import static java.util.Optional.empty;
|
||||||
import static java.util.Optional.of;
|
import static java.util.Optional.of;
|
||||||
|
|
||||||
// Mapstruct does not support parameterized (i.e. non-default) constructors. Thus, we need to use field injection.
|
|
||||||
@SuppressWarnings("squid:S3306")
|
|
||||||
public class RepositoryCollectionToDtoMapper extends BasicCollectionToDtoMapper<Repository, RepositoryDto, RepositoryToRepositoryDtoMapper> {
|
public class RepositoryCollectionToDtoMapper extends BasicCollectionToDtoMapper<Repository, RepositoryDto, RepositoryToRepositoryDtoMapper> {
|
||||||
|
|
||||||
private final ResourceLinks resourceLinks;
|
private final ResourceLinks resourceLinks;
|
||||||
|
|||||||
@@ -10,8 +10,6 @@ import java.util.Optional;
|
|||||||
import static java.util.Optional.empty;
|
import static java.util.Optional.empty;
|
||||||
import static java.util.Optional.of;
|
import static java.util.Optional.of;
|
||||||
|
|
||||||
// Mapstruct does not support parameterized (i.e. non-default) constructors. Thus, we need to use field injection.
|
|
||||||
@SuppressWarnings("squid:S3306")
|
|
||||||
public class UserCollectionToDtoMapper extends BasicCollectionToDtoMapper<User, UserDto, UserToUserDtoMapper> {
|
public class UserCollectionToDtoMapper extends BasicCollectionToDtoMapper<User, UserDto, UserToUserDtoMapper> {
|
||||||
|
|
||||||
private final ResourceLinks resourceLinks;
|
private final ResourceLinks resourceLinks;
|
||||||
|
|||||||
Reference in New Issue
Block a user