org.molgenis.data.index.IndexDependencyModel Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of molgenis-data-index Show documentation
Show all versions of molgenis-data-index Show documentation
Data layer indexing framework.
package org.molgenis.data.index;
import static com.google.common.collect.Maps.uniqueIndex;
import static com.google.common.collect.Streams.stream;
import static java.util.Collections.emptySet;
import static org.molgenis.data.meta.model.EntityTypeMetadata.ATTRIBUTES;
import static org.molgenis.data.meta.model.EntityTypeMetadata.EXTENDS;
import static org.molgenis.data.meta.model.EntityTypeMetadata.ID;
import static org.molgenis.data.meta.model.EntityTypeMetadata.INDEXING_DEPTH;
import static org.molgenis.data.meta.model.EntityTypeMetadata.IS_ABSTRACT;
import com.google.common.collect.ImmutableSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Stream;
import org.molgenis.data.Fetch;
import org.molgenis.data.meta.model.Attribute;
import org.molgenis.data.meta.model.AttributeMetadata;
import org.molgenis.data.meta.model.EntityType;
import org.molgenis.data.util.GenericDependencyResolver;
/**
* Models the dependencies between {@link EntityType}s for the purpose of indexing. These
* dependencies depend on the indexing depth of the entity types.
*/
class IndexDependencyModel {
private final Map entityTypes;
private final GenericDependencyResolver genericDependencyResolver =
new GenericDependencyResolver();
/** The fetch to use when retrieving the {@link EntityType}s fed to this DependencyModel. */
static final Fetch ENTITY_TYPE_FETCH =
new Fetch()
.field(ID)
.field(IS_ABSTRACT)
.field(INDEXING_DEPTH)
.field(EXTENDS, new Fetch().field(ID))
.field(
ATTRIBUTES,
new Fetch()
.field(AttributeMetadata.ID)
.field(AttributeMetadata.NAME)
.field(AttributeMetadata.TYPE)
.field(AttributeMetadata.REF_ENTITY_TYPE, new Fetch().field(ID)));
/**
* Creates an IndexDependencyModel for a list of EntityTypes.
*
* @param entityTypes the EntityTypes for which the DependencyModel is created
*/
IndexDependencyModel(List entityTypes) {
this.entityTypes = uniqueIndex(entityTypes, EntityType::getId);
}
private Set getReferencingEntities(String entityTypeId) {
ImmutableSet.Builder result = ImmutableSet.builder();
EntityType entityType = entityTypes.get(entityTypeId);
if (entityType == null) {
return emptySet();
}
for (Map.Entry candidate : entityTypes.entrySet()) {
EntityType candidateEntityType = candidate.getValue();
if (hasAttributeThatReferences(candidateEntityType, entityTypeId)) {
if (candidateEntityType.isAbstract()) {
result.addAll(getDescendants(candidate.getKey()));
} else {
result.add(candidate.getKey());
}
}
}
return result.build();
}
private Set getDescendants(String entityTypeId) {
ImmutableSet.Builder result = ImmutableSet.builder();
for (Map.Entry candidate : entityTypes.entrySet()) {
EntityType candidateEntityType = candidate.getValue();
if (extendsFrom(candidateEntityType, entityTypeId)) {
if (candidateEntityType.isAbstract()) {
result.addAll(getDescendants(candidate.getKey()));
} else {
result.add(candidate.getKey());
}
}
}
return result.build();
}
@SuppressWarnings("squid:S2259") // getExtends() doesn't return null here
private boolean extendsFrom(EntityType candidateEntityType, String entityTypeId) {
return candidateEntityType.getExtends() != null
&& entityTypeId.equals(candidateEntityType.getExtends().getId());
}
/**
* Determines if an entityType has an attribute that references another entity
*
* @param candidate the EntityType that is examined
* @param entityTypeId the ID of the entity that may be referenced
* @return indication if candidate references entityTypeID
*/
private boolean hasAttributeThatReferences(EntityType candidate, String entityTypeId) {
Iterable attributes = candidate.getOwnAtomicAttributes();
return stream(attributes)
.filter(Attribute::hasRefEntity)
.map(attribute -> attribute.getRefEntity().getId())
.anyMatch(entityTypeId::equals);
}
Stream getEntityTypesDependentOn(String entityTypeId) {
return genericDependencyResolver
.getAllDependants(
entityTypeId,
id -> entityTypes.get(id).getIndexingDepth(),
this::getReferencingEntities)
.stream();
}
}