package org.molgenis.data.annotation.core.utils; import com.google.common.collect.Lists; import org.molgenis.data.Entity; import org.molgenis.data.Repository; import org.molgenis.data.annotation.core.EffectBasedAnnotator; import org.molgenis.data.annotation.core.RepositoryAnnotator; import org.molgenis.data.annotation.core.exception.UnresolvedAnnotatorDependencyException; import org.molgenis.data.meta.model.Attribute; import org.molgenis.data.meta.model.EntityType; import org.molgenis.data.meta.model.EntityTypeFactory; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Queue; import java.util.stream.Collectors; import static org.molgenis.data.meta.AttributeType.STRING; import static org.molgenis.data.meta.AttributeType.TEXT; public class AnnotatorDependencyOrderResolver { private RepositoryAnnotator requestedAnnotator; public Queue<RepositoryAnnotator> getAnnotatorSelectionDependencyList( List<RepositoryAnnotator> availableAnnotatorList, List<RepositoryAnnotator> requestedAnnotatorList, Repository<Entity> repo, EntityTypeFactory entityTypeFactory) { Queue<RepositoryAnnotator> sortedList = new LinkedList<>(); for (RepositoryAnnotator annotator : requestedAnnotatorList) { if (annotator instanceof EffectBasedAnnotator) { // FIXME: implement correct dependency resolving for Effect annotator sortedList.add(annotator); } else if (!sortedList.contains(annotator)) { requestedAnnotator = annotator; sortedList = getSingleAnnotatorDependencyList(annotator, availableAnnotatorList, sortedList, repo.getEntityType(), entityTypeFactory); } } return sortedList; } private Queue<RepositoryAnnotator> getSingleAnnotatorDependencyList(RepositoryAnnotator selectedAnnotator, List<RepositoryAnnotator> annotatorList, Queue<RepositoryAnnotator> queue, EntityType emd, EntityTypeFactory entityTypeFactory) { EntityType entityType = entityTypeFactory.create(emd); resolveAnnotatorDependencies(selectedAnnotator, annotatorList, queue, entityType); return queue; } private void resolveAnnotatorDependencies(RepositoryAnnotator selectedAnnotator, List<RepositoryAnnotator> annotatorList, Queue<RepositoryAnnotator> annotatorQueue, EntityType entityType) { if (!areRequiredAttributesAvailable(Lists.newArrayList(entityType.getAtomicAttributes()), selectedAnnotator.getRequiredAttributes())) { selectedAnnotator.getRequiredAttributes().stream() .filter(requiredInputAttribute -> !areRequiredAttributesAvailable( Lists.newArrayList(entityType.getAtomicAttributes()), Collections.singletonList(requiredInputAttribute))).forEachOrdered(requiredInputAttribute -> { annotatorList.stream().filter(a -> !a.equals(selectedAnnotator)).collect(Collectors.toList()).forEach( annotator -> resolveAnnotatorDependencies(selectedAnnotator, annotatorList, annotatorQueue, entityType, requiredInputAttribute, annotator)); }); } else { if (!annotatorQueue.contains(selectedAnnotator)) annotatorQueue.add(selectedAnnotator); if (!selectedAnnotator.equals(requestedAnnotator)) resolveAnnotatorDependencies(requestedAnnotator, annotatorList, annotatorQueue, entityType); } if (annotatorQueue.size() == 0) { // FIXME: what to do for ref entity annotator. throw new UnresolvedAnnotatorDependencyException("unsolved for: " + requestedAnnotator); } } private void resolveAnnotatorDependencies(RepositoryAnnotator selectedAnnotator, List<RepositoryAnnotator> annotatorList, Queue<RepositoryAnnotator> annotatorQueue, EntityType entityType, Attribute requiredAttribute, RepositoryAnnotator annotator) { if (isRequiredAttributeAvailable(annotator.getInfo().getOutputAttributes(), requiredAttribute)) { if (areRequiredAttributesAvailable(Lists.newArrayList(entityType.getAtomicAttributes()), annotator.getRequiredAttributes())) { if (!annotatorQueue.contains(selectedAnnotator)) { annotatorQueue.add(annotator); } annotator.getInfo().getOutputAttributes().forEach(((EntityType) entityType)::addAttribute); annotatorList.remove(annotator); resolveAnnotatorDependencies(requestedAnnotator, annotatorList, annotatorQueue, entityType); } else { resolveAnnotatorDependencies(annotator, annotatorList, annotatorQueue, entityType); } } } private boolean areRequiredAttributesAvailable(List<Attribute> availableAttributes, List<Attribute> requiredAttributes) { for (Attribute attr : requiredAttributes) { if (!isRequiredAttributeAvailable(availableAttributes, attr)) { return false; } } return true; } private boolean isRequiredAttributeAvailable(List<Attribute> availableAttributes, Attribute requiredAttribute) { for (Attribute availableAttribute : availableAttributes) { if (requiredAttribute.getName().equals(availableAttribute.getName())) { if (requiredAttribute.getDataType() == TEXT) { return availableAttribute.getDataType() == TEXT || availableAttribute.getDataType() == STRING; } else return requiredAttribute.getDataType() == availableAttribute.getDataType(); } } return false; } }