Skip to content
Snippets Groups Projects
Node.java 5.68 KiB
Newer Older
import cz.muni.fi.disa.similarityoperators.cover.AbstractRepresentation.PrecomputedDistances;
import cz.muni.fi.disa.similarityoperators.cover.HullOptimizedRepresentationV3;
import messif.buckets.BucketStorageException;
import messif.objects.LocalAbstractObject;

import java.io.Serializable;
David Procházka's avatar
David Procházka committed
import java.util.Collection;
import java.util.Collections;
David Procházka's avatar
David Procházka committed
import java.util.List;
import java.util.stream.Collectors;
public abstract class Node implements Serializable {
    /**
     * Serialization ID
     */
    private static final long serialVersionUID = 420L;
    private final InsertType insertType;
    public ObjectToNodeDistance objectToNodeDistance;
    private InternalNode parent;
    private HullOptimizedRepresentationV3 hull;
    protected Node(PrecomputedDistances distances, InsertType insertType, ObjectToNodeDistance objectToNodeDistance) {
        this.hull = new HullOptimizedRepresentationV3(distances);
        this.hull.build();
        this.insertType = insertType;
        this.objectToNodeDistance = objectToNodeDistance;
    protected Node(HullOptimizedRepresentationV3 hull, InsertType insertType, ObjectToNodeDistance objectToNodeDistance) {
        this.hull = hull;
        this.insertType = insertType;
        this.objectToNodeDistance = objectToNodeDistance;
    }

    protected static InternalNode createParent(List<Node> nodes, PrecomputedDistances distances, InsertType insertType, 
                                                ObjectToNodeDistance objectToNodeDistance, MergingMethod mergingMethod) {
        List<LocalAbstractObject> objects = nodes
                .stream()
                .map(mergingMethod::getObjects)
                .flatMap(Collection::stream)
        if (nodes.size() == distances.getObjectCount()) {
            return new InternalNode(distances, insertType, objectToNodeDistance, nodes);
        }

        return new InternalNode(distances.getSubset(objects), insertType, objectToNodeDistance, nodes);
    /**
     * Returns a list of hull objects.
     *
     * @return a list of hull objects
     */
    public List<LocalAbstractObject> getHullObjects() {
        return hull.getHull();
    }

    /**
     * Returns true if the {@code object} is covered.
     *
     * @param object the object to be checked
     * @return true if the {@code object} is covered.
     */
    public boolean isCovered(LocalAbstractObject object) {
        return hull.isExternalCovered(object);
    }

    public HullOptimizedRepresentationV3 getHull() {
        return hull;
    }

    public InternalNode getParent() {
        return parent;
    }

    public void setParent(InternalNode parent) {
        this.parent = parent;
    }

    @Override
    public String toString() {
        return "Node{hull=" + hull + '}';
    }

    protected double getDistance(LocalAbstractObject object) {
        return objectToNodeDistance.getDistance(object, this);
    protected double getDistance(LocalAbstractObject object, PrecomputedDistances distances) {
        return objectToNodeDistance.getDistance(object, this, distances);
    protected boolean isInternal() {
        return (this instanceof InternalNode);
    }

        return hull.getRepresentativesCount();
    protected void addObjectIntoHull(LocalAbstractObject object) {
        if (isCovered(object)) return;

        switch (insertType) {
            case GREEDY:
                insertGreedy(object);
                break;
            case INCREMENTAL:
                insertIncremental(object);
                break;
            case ADD_HULL_OBJECT:
                insertHullRebuild(object);
                break;
            default:
                throw new IllegalStateException("Unexpected value: " + insertType);
    /**
     * Adds {@code object} into this node, possibly adding {@code object} to the bucket.
     *
     * @param object object to be added
     * @throws BucketStorageException bucket exception
     */
    protected abstract void addObject(LocalAbstractObject object) throws BucketStorageException;
    /**
     * Returns objects from buckets, such that the leaf node is descendants of the current node.
     *
     * @return objects from buckets, such that the leaf node is descendants of the current node.
     */
    protected abstract List<LocalAbstractObject> getObjects();
    /**
     * Returns the height of this node.
     *
     * @return the height of this node
     */
    /**
     * Adds this node and descendants into {@code nodes}.
     *
     * @param nodes list of nodes
     */
    protected abstract void gatherNodes(List<Node> nodes);
    /**
     * Adds every descendant leaf node into {@code leafNodes}.
     *
     * @param leafNodes list of leaf nodes
     */
    protected abstract void gatherLeafNodes(List<LeafNode> leafNodes);
    private void insertGreedy(LocalAbstractObject object) {
        List<LocalAbstractObject> objectsFromLeafNodes = getObjects();
        objectsFromLeafNodes.add(object);
        hull = new HullOptimizedRepresentationV3(objectsFromLeafNodes);
        hull.build();
    }
    private void insertIncremental(LocalAbstractObject object) {
        //hull.addHullObject(object);
        hull.setHullObjects((List<LocalAbstractObject>) Collections.singleton(object));

    private void insertHullRebuild(LocalAbstractObject object) {
        List<LocalAbstractObject> hull = this.hull.getHull();
        hull.add(object);

        this.hull = new HullOptimizedRepresentationV3(hull);
        this.hull.build();
    }