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 008/** 009 * A variant of the {@link AssignmentContextHolderMap} that is used by the {@link InheritedAssignment} 010 * class. If a {@link HasAssignmentContext} class implements the {@link CanInheritContext} interface, 011 * this class will use the {@link CanInheritContext#inheritAssignmentContext(Assignment, AssignmentContext)} method 012 * instead of the {@link HasAssignmentContext#createAssignmentContext(Assignment)} method to create 013 * a new context. 014 * 015 * @see HasAssignmentContext 016 * @see InheritedAssignment 017 * @see CanInheritContext 018 * 019 * @version IFS 1.3 (Iterative Forward Search)<br> 020 * Copyright (C) 2014 Tomáš Müller<br> 021 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br> 022 * <a href="http://muller.unitime.org">http://muller.unitime.org</a><br> 023 * <br> 024 * This library is free software; you can redistribute it and/or modify 025 * it under the terms of the GNU Lesser General Public License as 026 * published by the Free Software Foundation; either version 3 of the 027 * License, or (at your option) any later version. <br> 028 * <br> 029 * This library is distributed in the hope that it will be useful, but 030 * WITHOUT ANY WARRANTY; without even the implied warranty of 031 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 032 * Lesser General Public License for more details. <br> 033 * <br> 034 * You should have received a copy of the GNU Lesser General Public 035 * License along with this library; if not see <a href='http://www.gnu.org/licenses'>http://www.gnu.org/licenses</a>. 036 * @param <V> Variable 037 * @param <T> Value 038 **/ 039public class InheritedAssignmentContextHolder<V extends Variable<V, T>, T extends Value<V, T>> extends DefaultParallelAssignmentContextHolder<V, T> { 040 private long iVersion; 041 042 public InheritedAssignmentContextHolder(int index, long version) { 043 super(index); 044 iVersion = version; 045 } 046 047 /** 048 * If the {@link AssignmentContextReference#getParent()} implements the {@link CanInheritContext} interface, this 049 * method will use the {@link CanInheritContext#inheritAssignmentContext(Assignment, AssignmentContext)} instead of the 050 * {@link HasAssignmentContext#createAssignmentContext(Assignment)} to create a new context. 051 * @param assignment current assignment (must be {@link InheritedAssignment}) 052 * @param reference assignment context reference 053 * @return assignment context for the given assignment and reference 054 */ 055 @Override 056 @SuppressWarnings("unchecked") 057 public <U extends AssignmentContext> U getAssignmentContext(Assignment<V, T> assignment, AssignmentContextReference<V, T, U> reference) { 058 if (iIndex >= 0 && iIndex < CanHoldContext.sMaxSize && reference.getParent() instanceof CanHoldContext) { 059 AssignmentContext[] contexts = ((CanHoldContext)reference.getParent()).getContext(); 060 061 VersionedContext<U> context = (VersionedContext<U>)contexts[iIndex]; 062 if (context == null) { 063 context = new VersionedContext<U>(); 064 if (reference.getParent() instanceof CanInheritContext) 065 context.setContent(((CanInheritContext<V, T, U>)reference.getParent()).inheritAssignmentContext(assignment, 066 ((InheritedAssignment<V, T>)assignment).getParentAssignment().getAssignmentContext(reference)), iVersion); 067 else 068 context.setContent(reference.getParent().createAssignmentContext(assignment), iVersion); 069 contexts[iIndex] = context; 070 } else if (!context.isCurrent(iVersion)) { 071 if (reference.getParent() instanceof CanInheritContext) 072 context.setContent(((CanInheritContext<V, T, U>)reference.getParent()).inheritAssignmentContext(assignment, 073 ((InheritedAssignment<V, T>)assignment).getParentAssignment().getAssignmentContext(reference)), iVersion); 074 else 075 context.setContent(reference.getParent().createAssignmentContext(assignment), iVersion); 076 } 077 078 return context.getContent(); 079 } else { 080 U context = (U) iContexts.get(reference.getIndex()); 081 if (context != null) return context; 082 083 if (reference.getParent() instanceof CanInheritContext) 084 context = ((CanInheritContext<V, T, U>)reference.getParent()).inheritAssignmentContext(assignment, 085 ((InheritedAssignment<V, T>)assignment).getParentAssignment().getAssignmentContext(reference)); 086 else 087 context = reference.getParent().createAssignmentContext(assignment); 088 iContexts.put(reference.getIndex(), context); 089 090 return context; 091 } 092 } 093 094 public static class VersionedContext<U extends AssignmentContext> implements AssignmentContext { 095 U iContent = null; 096 long iContentVersion = -1; 097 098 VersionedContext() {} 099 100 public U getContent() { 101 return iContent; 102 } 103 104 public void setContent(U content, long version) { 105 iContent = content; 106 iContentVersion = version; 107 } 108 109 public boolean isCurrent(long version) { 110 return iContentVersion == version; 111 } 112 } 113}