package io.katharsis.resource.registry; import io.katharsis.locator.JsonServiceLocator; import io.katharsis.repository.RelationshipRepository; import io.katharsis.repository.RepositoryInstanceBuilder; import io.katharsis.repository.ResourceRepository; import io.katharsis.repository.exception.RepositoryInstanceNotFoundException; import io.katharsis.resource.registry.repository.DirectResponseRelationshipEntry; import io.katharsis.resource.registry.repository.DirectResponseResourceEntry; import io.katharsis.resource.registry.repository.ResourceEntry; import io.katharsis.resource.registry.repository.ResponseRelationshipEntry; import net.jodah.typetools.TypeResolver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Set; /** * Repository entries builder for classes implementing repository interfaces. */ public class DirectRepositoryEntryBuilder implements RepositoryEntryBuilder { private static final Logger LOGGER = LoggerFactory.getLogger(DirectRepositoryEntryBuilder.class); private final JsonServiceLocator jsonServiceLocator; public DirectRepositoryEntryBuilder(JsonServiceLocator jsonServiceLocator) { this.jsonServiceLocator = jsonServiceLocator; } @Override public ResourceEntry<?, ?> buildResourceRepository(ResourceLookup lookup, Class<?> resourceClass) { Class<?> repoClass = getRepoClassType(lookup.getResourceRepositoryClasses(), resourceClass); if (repoClass == null) { return null; } @SuppressWarnings("unchecked") DirectResponseResourceEntry directResourceEntry = new DirectResponseResourceEntry( new RepositoryInstanceBuilder(jsonServiceLocator, repoClass)); return directResourceEntry; } private Class<?> getRepoClassType(Set<Class<?>> repositoryClasses, Class<?> resourceClass) { for (Class<?> repoClass : repositoryClasses) { if (ResourceRepository.class.isAssignableFrom(repoClass)) { Class<?>[] typeArgs = TypeResolver.resolveRawArguments(ResourceRepository.class, repoClass); if (typeArgs[0] == resourceClass) { return repoClass; } } } return null; } @Override public List<ResponseRelationshipEntry<?, ?>> buildRelationshipRepositories(ResourceLookup lookup, Class<?> resourceClass) { Set<Class<?>> relationshipRepositoryClasses = lookup.getResourceRepositoryClasses(); Set<Class<?>> relationshipRepositories = findRelationshipRepositories(resourceClass, relationshipRepositoryClasses); List<ResponseRelationshipEntry<?, ?>> relationshipEntries = new LinkedList<>(); for (Class<?> relationshipRepositoryClass : relationshipRepositories) { RelationshipRepository relationshipRepository = (RelationshipRepository) jsonServiceLocator.getInstance(relationshipRepositoryClass); if (relationshipRepository == null) { throw new RepositoryInstanceNotFoundException(relationshipRepositoryClass.getCanonicalName()); } LOGGER.debug("Assigned {} RelationshipRepository to {} resource class", relationshipRepositoryClass.getCanonicalName(), resourceClass.getCanonicalName()); @SuppressWarnings("unchecked") DirectResponseRelationshipEntry<Object, Object> relationshipEntry = new DirectResponseRelationshipEntry<>( new RepositoryInstanceBuilder<>(jsonServiceLocator, (Class<RelationshipRepository>) relationshipRepositoryClass)); relationshipEntries.add(relationshipEntry); } return relationshipEntries; } private Set<Class<?>> findRelationshipRepositories(Class resourceClass, Set<Class<?>> relationshipRepositoryClasses) { Set<Class<?>> relationshipRepositories = new HashSet<>(); for (Class<?> repoClass : relationshipRepositoryClasses) { if (RelationshipRepository.class.isAssignableFrom(repoClass)) { Class<?>[] typeArgs = TypeResolver.resolveRawArguments(RelationshipRepository.class, repoClass); if (typeArgs[0] == resourceClass) { relationshipRepositories.add(repoClass); } } } return relationshipRepositories; } }