1 /* 2 * Grapht, an open source dependency injector. 3 * Copyright 2014-2015 various contributors (see CONTRIBUTORS.txt) 4 * Copyright 2010-2014 Regents of the University of Minnesota 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU Lesser General Public License as 8 * published by the Free Software Foundation; either version 2.1 of the 9 * License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 13 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 14 * details. 15 * 16 * You should have received a copy of the GNU General Public License along with 17 * this program; if not, write to the Free Software Foundation, Inc., 51 18 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 */ 20 package org.grouplens.grapht.solver; 21 22 import org.grouplens.grapht.CachePolicy; 23 import org.grouplens.grapht.util.Preconditions; 24 25 import javax.annotation.Nonnull; 26 import java.util.Arrays; 27 import java.util.Collections; 28 import java.util.LinkedList; 29 import java.util.List; 30 31 /** 32 * A builder for {@link DependencySolver}s. 33 * 34 * @see org.grouplens.grapht.solver.DependencySolver#newBuilder() 35 * @since 0.6 36 * @author <a href="http://grouplens.org">GroupLens Research</a> 37 */ 38 public class DependencySolverBuilder { 39 private List<BindingFunction> bindingFunctions = new LinkedList<BindingFunction>(); 40 private List<BindingFunction> triggerFunctions = new LinkedList<BindingFunction>(); 41 private CachePolicy defaultPolicy = CachePolicy.NO_PREFERENCE; 42 private int maxDepth = 100; 43 44 /** 45 * Get the current list of binding functions. 46 * @return The current list of binding functions. 47 */ 48 public List<BindingFunction> getBindingFunctions() { 49 return Collections.unmodifiableList(bindingFunctions); 50 } 51 52 /** 53 * Get the current list of trigger binding functions. These are the binding functions for which 54 * {@code canTriggerRewrite} is {@code true} in {@link #addBindingFunction(BindingFunction,boolean)}. 55 * 56 * @return The current list of trigger binding functions. 57 */ 58 public List<BindingFunction> getTriggerFunctions() { 59 return Collections.unmodifiableList(triggerFunctions); 60 } 61 62 /** 63 * Add a binding function to the dependency solver. 64 * @param func The binding function. 65 * @return The builder (for chaining). 66 */ 67 public DependencySolverBuilder addBindingFunction(@Nonnull BindingFunction func) { 68 return addBindingFunction(func, true); 69 } 70 71 /** 72 * Add a binding function to the dependency solver. 73 * @param func The binding function. 74 * @param canTriggerRewrite Controls whether this binding function can activate re-resolution 75 * when doing a graph rewrite. If {@code true} (the value passed by 76 * all other binding function adders), this binding function returning 77 * a binding will cause a graph rewrite; if {@code false}, it will be 78 * ignored during rewrites until the rewrite has been triggered by some 79 * other binding function. Register the default binding function with 80 * {@code false} here to keep default bindings from triggering rewrites. 81 * @return The builder (for chaining). 82 */ 83 public DependencySolverBuilder addBindingFunction(@Nonnull BindingFunction func, 84 boolean canTriggerRewrite) { 85 Preconditions.notNull("binding function", func); 86 bindingFunctions.add(func); 87 if (canTriggerRewrite) { 88 triggerFunctions.add(func); 89 } 90 return this; 91 } 92 93 /** 94 * Add multiple binding function to the dependency solver. 95 * @param funcs The binding functions. 96 * @return The builder (for chaining). 97 */ 98 public DependencySolverBuilder addBindingFunctions(@Nonnull BindingFunction... funcs) { 99 return addBindingFunctions(Arrays.asList(funcs)); 100 } 101 102 /** 103 * Add multiple binding function to the dependency solver. 104 * @param funcs The binding functions. 105 * @return The builder (for chaining). 106 */ 107 public DependencySolverBuilder addBindingFunctions(@Nonnull Iterable<BindingFunction> funcs) { 108 for (BindingFunction fn: funcs) { 109 addBindingFunction(fn); 110 } 111 return this; 112 } 113 114 /** 115 * Get the current default policy. 116 * @return The builder's current default policy. 117 */ 118 public CachePolicy getDefaultPolicy() { 119 return defaultPolicy; 120 } 121 122 /** 123 * Set the default policy for the solver. This policy will be used when a satisfaction has a 124 * policy of {@link CachePolicy#NO_PREFERENCE}. The default is {@link CachePolicy#NO_PREFERENCE}, 125 * so the injector will make final caching decisions. 126 * @param policy The default policy for the solver. 127 * @return The builder (for chaining). 128 */ 129 public DependencySolverBuilder setDefaultPolicy(CachePolicy policy) { 130 defaultPolicy = policy; 131 return this; 132 } 133 134 /** 135 * Get the maximum depth. 136 * @return The maximum object graph depth. 137 */ 138 public int getMaxDepth() { 139 return maxDepth; 140 } 141 142 /** 143 * Set the maximum object graph depth, for cycle detection. 144 * @param depth The maximum object graph depth that the solver is allowed to produce. 145 * @return The builder (for chaining). 146 */ 147 public DependencySolverBuilder setMaxDepth(int depth) { 148 if (depth < 1) { 149 throw new IllegalArgumentException("max depth must be at least 1"); 150 } 151 maxDepth = depth; 152 return this; 153 } 154 155 /** 156 * Build a dependency solver. 157 * @return The dependency solver. 158 */ 159 public DependencySolver build() { 160 return new DependencySolver(bindingFunctions, triggerFunctions, defaultPolicy, maxDepth); 161 } 162 }