1 /*
2 * ModeShape (http://www.modeshape.org)
3 * See the COPYRIGHT.txt file distributed with this work for information
4 * regarding copyright ownership. Some portions may be licensed
5 * to Red Hat, Inc. under one or more contributor license agreements.
6 * See the AUTHORS.txt file in the distribution for a full listing of
7 * individual contributors.
8 *
9 * ModeShape is free software. Unless otherwise indicated, all code in ModeShape
10 * is licensed to you under the terms of the GNU Lesser General Public License as
11 * published by the Free Software Foundation; either version 2.1 of
12 * the License, or (at your option) any later version.
13 *
14 * ModeShape is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this software; if not, write to the Free
21 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
23 */
24 package org.modeshape.graph.query;
25
26 import java.util.HashMap;
27 import java.util.Map;
28 import net.jcip.annotations.Immutable;
29 import org.modeshape.common.collection.Problems;
30 import org.modeshape.common.collection.SimpleProblems;
31 import org.modeshape.common.util.CheckArg;
32 import org.modeshape.graph.query.model.BindVariableName;
33 import org.modeshape.graph.query.model.TypeSystem;
34 import org.modeshape.graph.query.plan.PlanHints;
35 import org.modeshape.graph.query.validate.Schemata;
36
37 /**
38 * An immutable context in which queries are to be executed. Each query context defines the information that is available during
39 * query execution.
40 */
41 @Immutable
42 public class QueryContext {
43 private final TypeSystem typeSystem;
44 private final PlanHints hints;
45 private final Schemata schemata;
46 private final Problems problems;
47 private final Map<String, Object> variables;
48
49 /**
50 * Create a new context for query execution.
51 *
52 * @param schemata the schemata
53 * @param typeSystem the types system
54 * @param hints the hints, or null if there are no hints
55 * @param problems the problems container, or null if a new problems container should be created
56 * @param variables the mapping of variables and values, or null if there are no such variables
57 * @throws IllegalArgumentException if the values or schmata are null
58 */
59 public QueryContext( Schemata schemata,
60 TypeSystem typeSystem,
61 PlanHints hints,
62 Problems problems,
63 Map<String, Object> variables ) {
64 CheckArg.isNotNull(typeSystem, "typeSystem");
65 CheckArg.isNotNull(schemata, "schemata");
66 this.typeSystem = typeSystem;
67 this.hints = hints != null ? hints : new PlanHints();
68 this.schemata = schemata;
69 this.problems = problems != null ? problems : new SimpleProblems();
70 this.variables = variables != null ? new HashMap<String, Object>(variables) : new HashMap<String, Object>();
71 assert this.typeSystem != null;
72 assert this.hints != null;
73 assert this.schemata != null;
74 assert this.problems != null;
75 assert this.variables != null;
76 }
77
78 /**
79 * Create a new context for query execution.
80 *
81 * @param schemata the schemata
82 * @param typeSystem the types system
83 * @param hints the hints, or null if there are no hints
84 * @param problems the problems container, or null if a new problems container should be created
85 * @throws IllegalArgumentException if the values or schmata are null
86 */
87 public QueryContext( Schemata schemata,
88 TypeSystem typeSystem,
89 PlanHints hints,
90 Problems problems ) {
91 this(schemata, typeSystem, hints, problems, null);
92 }
93
94 /**
95 * Create a new context for query execution.
96 *
97 * @param schemata the schemata
98 * @param typeSystem the types system
99 * @param hints the hints, or null if there are no hints
100 * @throws IllegalArgumentException if the context or schmata are null
101 */
102 public QueryContext( Schemata schemata,
103 TypeSystem typeSystem,
104 PlanHints hints ) {
105 this(schemata, typeSystem, hints, null, null);
106 }
107
108 /**
109 * Create a new context for query execution.
110 *
111 * @param schemata the schemata
112 * @param typeSystem the types system
113 * @throws IllegalArgumentException if the values or schmata are null
114 */
115 public QueryContext( Schemata schemata,
116 TypeSystem typeSystem ) {
117 this(schemata, typeSystem, null, null, null);
118 }
119
120 /**
121 * Create a new context that is a copy of the supplied context. This constructor is useful for subclasses that wish to add
122 * store additional fields in a QueryContext.
123 *
124 * @param original the original context
125 * @throws IllegalArgumentException if the original is null
126 */
127 protected QueryContext( QueryContext original ) {
128 this(original.schemata, original.typeSystem, original.hints, original.problems, original.variables);
129 }
130
131 /**
132 * Get the interface for working with literal values and types.
133 *
134 * @return the type system; never null
135 */
136 public TypeSystem getTypeSystem() {
137 return typeSystem;
138 }
139
140 /**
141 * Get the plan hints.
142 *
143 * @return the plan hints; never null
144 */
145 public final PlanHints getHints() {
146 return hints;
147 }
148
149 /**
150 * Get the problem container used by this query context. Any problems that have been encountered will be accumlated in this
151 * container.
152 *
153 * @return the problem container; never null
154 */
155 public final Problems getProblems() {
156 return problems;
157 }
158
159 /**
160 * Get the definition of the tables available within this query context.
161 *
162 * @return the schemata; never null
163 */
164 public Schemata getSchemata() {
165 return schemata;
166 }
167
168 /**
169 * Get the variables that are to be substituted into the {@link BindVariableName} used in the query.
170 *
171 * @return immutable map of variable values keyed by their name; never null but possibly empty
172 */
173 public Map<String, Object> getVariables() {
174 return variables;
175 }
176
177 /**
178 * {@inheritDoc}
179 *
180 * @see java.lang.Object#equals(java.lang.Object)
181 */
182 @Override
183 public boolean equals( Object obj ) {
184 if (obj == this) return true;
185 if (obj instanceof QueryContext) {
186 QueryContext that = (QueryContext)obj;
187 if (!this.typeSystem.equals(that.getTypeSystem())) return false;
188 if (!this.schemata.equals(that.getSchemata())) return false;
189 if (!this.variables.equals(that.getVariables())) return false;
190 return true;
191 }
192 return false;
193 }
194
195 /**
196 * Obtain a copy of this context, except that the copy uses the supplied type system.
197 *
198 * @param typeSystem the type system that should be used in the new query context
199 * @return the new context; never null
200 * @throws IllegalArgumentException if the execution context reference is null
201 */
202 public QueryContext with( TypeSystem typeSystem ) {
203 CheckArg.isNotNull(typeSystem, "typeSystem");
204 return new QueryContext(schemata, typeSystem, hints, problems, variables);
205 }
206
207 /**
208 * Obtain a copy of this context, except that the copy uses the supplied schemata.
209 *
210 * @param schemata the schemata that should be used in the new context
211 * @return the new context; never null
212 * @throws IllegalArgumentException if the schemata reference is null
213 */
214 public QueryContext with( Schemata schemata ) {
215 CheckArg.isNotNull(schemata, "schemata");
216 return new QueryContext(schemata, typeSystem, hints, problems, variables);
217 }
218
219 /**
220 * Obtain a copy of this context, except that the copy uses the supplied hints.
221 *
222 * @param hints the hints that should be used in the new context
223 * @return the new context; never null
224 * @throws IllegalArgumentException if the hints reference is null
225 */
226 public QueryContext with( PlanHints hints ) {
227 CheckArg.isNotNull(hints, "hints");
228 return new QueryContext(schemata, typeSystem, hints, problems, variables);
229 }
230
231 /**
232 * Obtain a copy of this context, except that the copy uses the supplied problem container.
233 *
234 * @param problems the problems that should be used in the new context; may be null if a new problem container should be used
235 * @return the new context; never null
236 */
237 public QueryContext with( Problems problems ) {
238 return new QueryContext(schemata, typeSystem, hints, problems, variables);
239 }
240
241 /**
242 * Obtain a copy of this context, except that the copy uses the supplied variables.
243 *
244 * @param variables the variables that should be used in the new context; may be null if there are no such variables
245 * @return the new context; never null
246 */
247 public QueryContext with( Map<String, Object> variables ) {
248 return new QueryContext(schemata, typeSystem, hints, problems, variables);
249 }
250
251 }