001package org.cpsolver.ifs.assignment.context;
002
003import org.cpsolver.ifs.assignment.Assignment;
004import org.cpsolver.ifs.assignment.InheritedAssignment;
005import org.cpsolver.ifs.model.Value;
006import org.cpsolver.ifs.model.Variable;
007
008public class AssignmentContextHelper {
009
010    /**
011     * Returns an assignment context associated with the given object. If there is no 
012     * assignment context associated with the object yet, one is created using the
013     * {@link HasAssignmentContext#createAssignmentContext(Assignment)} method.
014     * @param source given object
015     * @param assignment given assignment, also implementing {@link CanHoldContext}
016     * @return assignment context associated with the given object and the given assignment
017     */
018    @SuppressWarnings("unchecked")
019    public static <V extends Variable<V, T>, T extends Value<V, T>, C extends AssignmentContext> C getContext(HasAssignmentContext<V, T, C> source, Assignment<V, T> assignment) {
020        if (assignment.getIndex() >= 0 && assignment.getIndex() < CanHoldContext.sMaxSize) {
021            AssignmentContext[] contexts = ((CanHoldContext)source).getContext();
022            if (assignment.getIndex() > 0 && assignment instanceof InheritedAssignment) {
023                long version = ((InheritedAssignment<V, T>)assignment).getVersion();
024                
025                InheritedAssignmentContextHolder.VersionedContext<C> context = (InheritedAssignmentContextHolder.VersionedContext<C>)contexts[assignment.getIndex()];
026                if (context == null) {
027                    context = new InheritedAssignmentContextHolder.VersionedContext<C>();
028                    contexts[assignment.getIndex()] = context;
029                }
030                
031                if (!context.isCurrent(version)) {
032                    if (source instanceof CanInheritContext && contexts[0] != null)
033                        context.setContent(((CanInheritContext<V, T, C>)source).inheritAssignmentContext(assignment, (C)contexts[0]), version);
034                    else
035                        context.setContent(source.createAssignmentContext(assignment), version);
036                }
037                
038                return context.getContent();
039            } else {
040                AssignmentContext context = contexts[assignment.getIndex()];
041                if (context == null) {
042                    context = source.createAssignmentContext(assignment);
043                    contexts[assignment.getIndex()] = context;
044                }
045                return (C) context;
046            }
047        }
048        return assignment.getAssignmentContext(source.getAssignmentContextReference());
049    }
050}