All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.optaplanner.constraint.streams.bavet.common.NodeBuildHelper Maven / Gradle / Ivy

package org.optaplanner.constraint.streams.bavet.common;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;

import org.optaplanner.constraint.streams.common.AbstractConstraintStream;
import org.optaplanner.constraint.streams.common.inliner.AbstractScoreInliner;
import org.optaplanner.core.api.score.Score;
import org.optaplanner.core.api.score.stream.Constraint;
import org.optaplanner.core.api.score.stream.ConstraintStream;

public final class NodeBuildHelper> {

    private final Set activeStreamSet;
    private final Map constraintWeightMap;
    private final AbstractScoreInliner scoreInliner;
    private final Map> tupleLifecycleMap;
    private final Map storeIndexMap;

    private List reversedNodeList;

    public NodeBuildHelper(Set activeStreamSet, Map constraintWeightMap,
            AbstractScoreInliner scoreInliner) {
        this.activeStreamSet = activeStreamSet;
        this.constraintWeightMap = constraintWeightMap;
        this.scoreInliner = scoreInliner;
        int activeStreamSetSize = activeStreamSet.size();
        this.tupleLifecycleMap = new HashMap<>(Math.max(16, activeStreamSetSize));
        this.storeIndexMap = new HashMap<>(Math.max(16, activeStreamSetSize / 2));
        this.reversedNodeList = new ArrayList<>(activeStreamSetSize);
    }

    public boolean isStreamActive(ConstraintStream stream) {
        return activeStreamSet.contains(stream);
    }

    public AbstractScoreInliner getScoreInliner() {
        return scoreInliner;
    }

    public Score_ getConstraintWeight(Constraint constraint) {
        return constraintWeightMap.get(constraint);
    }

    public void addNode(AbstractNode node) {
        reversedNodeList.add(node);
    }

    public void addNode(AbstractNode node, ConstraintStream parent) {
        addNode(node);
        putInsertUpdateRetract(parent, (TupleLifecycle) node);
    }

    public void addNode(AbstractNode node, ConstraintStream leftParent, ConstraintStream rightParent) {
        addNode(node);
        putInsertUpdateRetract(leftParent, TupleLifecycle.ofLeft((LeftTupleLifecycle) node));
        putInsertUpdateRetract(rightParent, TupleLifecycle.ofRight((RightTupleLifecycle) node));
    }

    public  void putInsertUpdateRetract(ConstraintStream stream, TupleLifecycle tupleLifecycle) {
        tupleLifecycleMap.put(stream, tupleLifecycle);
    }

    public  void putInsertUpdateRetract(ConstraintStream stream,
            List childStreamList,
            Function, AbstractConditionalTupleLifecycle> tupleLifecycleFunction) {
        TupleLifecycle tupleLifecycle = getAggregatedTupleLifecycle(childStreamList);
        putInsertUpdateRetract(stream, tupleLifecycleFunction.apply(tupleLifecycle));
    }

    public  TupleLifecycle getAggregatedTupleLifecycle(
            List streamList) {
        TupleLifecycle[] tupleLifecycles = streamList.stream()
                .filter(this::isStreamActive)
                .map(s -> getTupleLifecycle(s, tupleLifecycleMap))
                .toArray(TupleLifecycle[]::new);
        switch (tupleLifecycles.length) {
            case 0:
                throw new IllegalStateException("Impossible state: None of the streamList (" + streamList
                        + ") are active.");
            case 1:
                return tupleLifecycles[0];
            default:
                return new AggregatedTupleLifecycle<>(tupleLifecycles);
        }
    }

    private static  TupleLifecycle getTupleLifecycle(ConstraintStream stream,
            Map> tupleLifecycleMap) {
        TupleLifecycle tupleLifecycle = (TupleLifecycle) tupleLifecycleMap.get(stream);
        if (tupleLifecycle == null) {
            throw new IllegalStateException("Impossible state: the stream (" + stream + ") hasn't built a node yet.");
        }
        return tupleLifecycle;
    }

    public int reserveTupleStoreIndex(ConstraintStream tupleSourceStream) {
        return storeIndexMap.compute(tupleSourceStream, (k, index) -> {
            if (index == null) {
                return 0;
            } else if (index < 0) {
                throw new IllegalStateException("Impossible state: the tupleSourceStream (" + k
                        + ") is reserving a store after it has been extracted.");
            } else {
                return index + 1;
            }
        });
    }

    public int extractTupleStoreSize(ConstraintStream tupleSourceStream) {
        Integer lastIndex = storeIndexMap.put(tupleSourceStream, Integer.MIN_VALUE);
        return (lastIndex == null) ? 0 : lastIndex + 1;
    }

    public List destroyAndGetNodeList() {
        List nodeList = this.reversedNodeList;
        Collections.reverse(nodeList);
        this.reversedNodeList = null;
        return nodeList;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy