View Javadoc

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 }