Skip to content
Snippets Groups Projects

Ozg 3936 refactor user profile url provider

Merged Felix Reichenbach requested to merge OZG-3936-refactor-UserProfileUrlProvider into main
6 files
+ 44
78
Compare changes
  • Side-by-side
  • Inline
Files
6
/*
* Copyright (C) 2025 Das Land Schleswig-Holstein vertreten durch den
* Ministerpräsidenten des Landes Schleswig-Holstein
* Staatskanzlei
* Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
*
* Lizenziert unter der EUPL, Version 1.2 oder - sobald
* diese von der Europäischen Kommission genehmigt wurden -
* Folgeversionen der EUPL ("Lizenz");
* Sie dürfen dieses Werk ausschließlich gemäß
* dieser Lizenz nutzen.
* Eine Kopie der Lizenz finden Sie hier:
*
* https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
*
* Sofern nicht durch anwendbare Rechtsvorschriften
* gefordert oder in schriftlicher Form vereinbart, wird
* die unter der Lizenz verbreitete Software "so wie sie
* ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
* ausdrücklich oder stillschweigend - verbreitet.
* Die sprachspezifischen Genehmigungen und Beschränkungen
* unter der Lizenz sind dem Lizenztext zu entnehmen.
*/
package de.ozgcloud.alfa.common;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Collection;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Stream;
import org.apache.commons.lang3.StringUtils;
import org.springframework.hateoas.EntityModel;
import org.springframework.hateoas.Link;
import org.springframework.hateoas.server.RepresentationModelProcessor;
import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder;
import org.springframework.stereotype.Component;
import de.ozgcloud.alfa.common.user.UserManagerUrlProvider;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
@Log4j2
@Component
@RequiredArgsConstructor
public class LinkedResourceProcessor<T> implements RepresentationModelProcessor<EntityModel<T>> {
private final UserManagerUrlProvider userManagerUrlProvider;
@Override
public EntityModel<T> process(EntityModel<T> model) {
addResourceLinks(model);
addUserProfileLinks(model);
return model;
}
void addResourceLinks(EntityModel<T> model) {
getAnnotatedFields(LinkedResource.class, model.getContent())
.filter(field -> shouldAddLink(model, field))
.forEach(field -> addLinkForLinkedResourceField(model, field));
}
void addLinkForLinkedResourceField(EntityModel<T> model, Field field) {
getEntityFieldValue(model.getContent(), field).map(Object::toString).filter(StringUtils::isNotBlank)
.ifPresent(val -> model
.add(WebMvcLinkBuilder.linkTo(field.getAnnotation(LinkedResource.class).controllerClass()).slash(val)
.withRel(getResourceName(field))));
}
void addUserProfileLinks(EntityModel<T> model) {
getAnnotatedFields(LinkedUserProfileResource.class, model.getContent())
.filter(field -> shouldAddLink(model, field))
.forEach(field -> addLinkForLinkedUserProfileResourceField(model, field));
}
Stream<Field> getAnnotatedFields(Class<? extends Annotation> annotationClass, T content) {
if (Objects.isNull(content)) {
return Stream.empty();
}
return Arrays.stream(content.getClass().getDeclaredFields())
.filter(field -> field.isAnnotationPresent(annotationClass));
}
boolean shouldAddLink(EntityModel<T> model, Field field) {
return !(field.getType().isArray() || Collection.class.isAssignableFrom(field.getType())
|| model.hasLink(getResourceName(field)));
}
void addLinkForLinkedUserProfileResourceField(EntityModel<T> model, Field field) {
getEntityFieldValue(model.getContent(), field).map(Object::toString).filter(StringUtils::isNotBlank)
.ifPresent(value -> addUserProfileLink(model, field, value));
}
private void addUserProfileLink(EntityModel<T> model, Field field, String value) {
Optional.ofNullable(userManagerUrlProvider.getUserProfileTemplate()).filter(StringUtils::isNotBlank)
.ifPresent(template -> model.add(Link.of(template.formatted(value)).withRel(getResourceName(field))));
}
private Optional<Object> getEntityFieldValue(T content, Field field) {
try {
field.setAccessible(true);
Optional<Object> value = Optional.ofNullable(field.get(content));
field.setAccessible(false);
return value;
} catch (IllegalArgumentException | IllegalAccessException e) {
LOG.warn("Cannot access field value of LinkedResource field.", e);
}
return Optional.empty();
}
private String getResourceName(Field field) {
var fieldName = field.getName();
if (fieldName.endsWith("Id")) {
return fieldName.substring(0, fieldName.indexOf("Id"));
}
return fieldName;
}
}
Loading