package io.katharsis.resource.registry; import io.katharsis.repository.RepositoryMethodParameterProvider; import io.katharsis.repository.exception.RelationshipRepositoryNotFoundException; import io.katharsis.resource.information.ResourceInformation; import io.katharsis.resource.registry.repository.AnnotatedRelationshipEntryBuilder; import io.katharsis.resource.registry.repository.AnnotatedResourceEntryBuilder; 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 io.katharsis.resource.registry.responseRepository.RelationshipRepositoryAdapter; import io.katharsis.resource.registry.responseRepository.ResourceRepositoryAdapter; import java.util.LinkedList; import java.util.List; import java.util.Objects; /** * Holds information about a resource of type <i>T</i> and its repositories. * It includes the following information: * - ResourceInformation instance with information about the resource, * - ResourceEntry instance, * - List of all repositories for relationships defined in resource class. * - Parent RegistryEntry if a resource inherits from another resource * * @param <T> resource type */ public class RegistryEntry<T> { private final ResourceInformation resourceInformation; private final ResourceEntry<T, ?> resourceEntry; private final List<ResponseRelationshipEntry<T, ?>> relationshipEntries; private RegistryEntry parentRegistryEntry = null; public RegistryEntry(ResourceInformation resourceInformation, @SuppressWarnings("SameParameterValue") ResourceEntry<T, ?> resourceEntry) { this(resourceInformation, resourceEntry, new LinkedList<ResponseRelationshipEntry<T, ?>>()); } public RegistryEntry(ResourceInformation resourceInformation, ResourceEntry<T, ?> resourceEntry, List<ResponseRelationshipEntry<T, ?>> relationshipEntries) { this.resourceInformation = resourceInformation; this.resourceEntry = resourceEntry; this.relationshipEntries = relationshipEntries; } @SuppressWarnings("unchecked") public ResourceRepositoryAdapter getResourceRepository(RepositoryMethodParameterProvider parameterProvider) { Object repoInstance = null; if (resourceEntry instanceof DirectResponseResourceEntry) { repoInstance = ((DirectResponseResourceEntry<T, ?>) resourceEntry).getResourceRepository(); } else if (resourceEntry instanceof AnnotatedResourceEntryBuilder) { repoInstance = ((AnnotatedResourceEntryBuilder<T, ?>) resourceEntry).build(parameterProvider); } return new ResourceRepositoryAdapter(repoInstance); } public List<ResponseRelationshipEntry<T, ?>> getRelationshipEntries() { return relationshipEntries; } @SuppressWarnings("unchecked") public RelationshipRepositoryAdapter getRelationshipRepositoryForClass(Class clazz, RepositoryMethodParameterProvider parameterProvider) { ResponseRelationshipEntry<T, ?> foundRelationshipEntry = null; for (ResponseRelationshipEntry<T, ?> relationshipEntry : relationshipEntries) { if (clazz == relationshipEntry.getTargetAffiliation()) { foundRelationshipEntry = relationshipEntry; break; } } if (foundRelationshipEntry == null) { throw new RelationshipRepositoryNotFoundException(resourceInformation.getResourceClass(), clazz); } Object repoInstance; if (foundRelationshipEntry instanceof AnnotatedRelationshipEntryBuilder) { repoInstance = ((AnnotatedRelationshipEntryBuilder<T, ?>) foundRelationshipEntry).build(parameterProvider); } else { repoInstance = ((DirectResponseRelationshipEntry<T, ?>) foundRelationshipEntry).getRepositoryInstanceBuilder(); } return new RelationshipRepositoryAdapter(repoInstance); } public ResourceInformation getResourceInformation() { return resourceInformation; } public RegistryEntry getParentRegistryEntry() { return parentRegistryEntry; } /** * To be used only by ResourceRegistryBuilder * * @param parentRegistryEntry parent resource */ void setParentRegistryEntry(RegistryEntry parentRegistryEntry) { this.parentRegistryEntry = parentRegistryEntry; } /** * Check the parameter is a parent of <b>this</b> {@link RegistryEntry} instance * * @param registryEntry parent to check * @return true if the parameter is a parent */ public boolean isParent(RegistryEntry registryEntry) { RegistryEntry parentRegistryEntry = getParentRegistryEntry(); while (parentRegistryEntry != null) { if (parentRegistryEntry.equals(registryEntry)) { return true; } parentRegistryEntry = parentRegistryEntry.getParentRegistryEntry(); } return false; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } RegistryEntry<?> that = (RegistryEntry<?>) o; return Objects.equals(resourceInformation, that.resourceInformation) && Objects.equals(resourceEntry, that.resourceEntry) && Objects.equals(relationshipEntries, that.relationshipEntries) && Objects.equals(parentRegistryEntry, that.parentRegistryEntry); } @Override public int hashCode() { return Objects.hash(resourceInformation, resourceEntry, relationshipEntries, parentRegistryEntry); } }