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 com.google.common.base.Preconditions;
23 import org.grouplens.grapht.CachePolicy;
24 import org.grouplens.grapht.reflect.QualifierMatcher;
25 import org.grouplens.grapht.reflect.Qualifiers;
26 import org.grouplens.grapht.reflect.Satisfaction;
27
28 import java.util.EnumSet;
29
30 /**
31 * Builder for bind rules.
32 *
33 * @since 0.7
34 * @author <a href="http://www.grouplens.org">GroupLens Research</a>
35 */
36 public class BindRuleBuilder {
37 private Class<?> dependencyType;
38 private QualifierMatcher qualifierMatcher = Qualifiers.matchAny();
39
40 private Satisfaction satisfaction;
41 private Class<?> implementation;
42
43 private CachePolicy cachePolicy = CachePolicy.NO_PREFERENCE;
44 private EnumSet<BindingFlag> flags = BindingFlag.emptySet();
45
46 public static BindRuleBuilder create() {
47 return new BindRuleBuilder();
48 }
49
50 /**
51 * Get the dependency type to match.
52 * @return The dependency type to match.
53 */
54 public Class<?> getDependencyType() {
55 return dependencyType;
56 }
57
58 /**
59 * Set the dependency type to match.
60 * @param type The dependency type to match.
61 */
62 public BindRuleBuilder setDependencyType(Class<?> type) {
63 dependencyType = type;
64 return this;
65 }
66
67 /**
68 * Get the configured qualifer matcher. The initial qualifier matcher is {@link org.grouplens.grapht.reflect.Qualifiers#matchAny()}.
69 * @return The qualifier matcher.
70 */
71 public QualifierMatcher getQualifierMatcher() {
72 return qualifierMatcher;
73 }
74
75 /**
76 * Set the qualifier matcher.
77 * @param qm The qualifier matcher.
78 */
79 public BindRuleBuilder setQualifierMatcher(QualifierMatcher qm) {
80 qualifierMatcher = qm;
81 return this;
82 }
83
84 /**
85 * Get the target satisfaction.
86 * @return The configured satisfaction, or {@code null} if none is configured.
87 */
88 public Satisfaction getSatisfaction() {
89 return satisfaction;
90 }
91
92 /**
93 * Set the satisfaction to bind to. This will unset the implementation class and result in
94 * a satisfaction binding.
95 *
96 * @param sat The satisfaction.
97 */
98 public BindRuleBuilder setSatisfaction(Satisfaction sat) {
99 satisfaction = sat;
100 return this;
101 }
102
103 /**
104 * Get the target implementation.
105 * @return The target implementation, or {@code null} if none is configured.
106 */
107 public Class<?> getImplementation() {
108 return implementation;
109 }
110
111 /**
112 * Set the target implementation. This will unset the satisfaction and result in an implementation
113 * class binding.
114 *
115 * @param type The implementation class.
116 */
117 public BindRuleBuilder setImplementation(Class<?> type) {
118 implementation = type;
119 return this;
120 }
121
122 /**
123 * Query whether the binding will be terminal.
124 * @return {@code true} if the binding will be terminal.
125 */
126 public boolean isTerminal() {
127 return flags.contains(BindingFlag.TERMINAL);
128 }
129
130 /**
131 * Set whether the binding will be terminal.
132 *
133 * @param term {@code true} to create a terminal binding.
134 * @see BindingFlag#TERMINAL
135 */
136 public BindRuleBuilder setTerminal(boolean term) {
137 if (term) {
138 flags.add(BindingFlag.TERMINAL);
139 } else {
140 flags.remove(BindingFlag.TERMINAL);
141 }
142 return this;
143 }
144
145 /**
146 * Set the flags on this bind rule.
147 * @param fs The flags.
148 * @return The builder (for chaining).
149 */
150 public BindRuleBuilder setFlags(EnumSet<BindingFlag> fs) {
151 flags = fs.clone();
152 return this;
153 }
154
155 /**
156 * Add a flag to the constructed bind rule.
157 * @param flag The flag to add.
158 * @return The builder (for chaining).
159 */
160 public BindRuleBuilder addFlag(BindingFlag flag) {
161 flags.add(flag);
162 return this;
163 }
164
165 /**
166 * Get the cache policy.
167 * @return The cache policy.
168 */
169 public CachePolicy getCachePolicy() {
170 return cachePolicy;
171 }
172
173 /**
174 * Set the cache policy.
175 * @param policy The cache policy.
176 */
177 public BindRuleBuilder setCachePolicy(CachePolicy policy) {
178 cachePolicy = policy;
179 return this;
180 }
181
182 public BindRule build() {
183 Preconditions.checkState(dependencyType != null, "no dependency type specified");
184 if (implementation != null) {
185 assert satisfaction == null;
186 return new BindRuleImpl(dependencyType, implementation, cachePolicy, qualifierMatcher, flags);
187 } else if (satisfaction != null) {
188 return new BindRuleImpl(dependencyType, satisfaction, cachePolicy, qualifierMatcher, flags);
189 } else {
190 throw new IllegalStateException("no binding target specified");
191 }
192 }
193 }