1. Project Clover database Tue Dec 20 2016 21:24:09 CET
  2. Package org.xwiki.context

File ExecutionContext.java

 

Coverage histogram

../../../img/srcFileCovDistChart10.png
0% of files have more coverage

Code metrics

18
51
18
2
315
143
29
0.57
2.83
9
1.61

Classes

Class Line # Actions
ExecutionContext 36 37 0% 21 7
0.892307789.2%
ExecutionContext.DeclarationBuilder 205 14 0% 8 0
1.0100%
 

Contributing tests

This file is covered by 865 tests. .

Source view

1    /*
2    * See the NOTICE file distributed with this work for additional
3    * information regarding copyright ownership.
4    *
5    * This is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU Lesser General Public License as
7    * published by the Free Software Foundation; either version 2.1 of
8    * the License, or (at your option) any later version.
9    *
10    * This software is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13    * Lesser General Public License for more details.
14    *
15    * You should have received a copy of the GNU Lesser General Public
16    * License along with this software; if not, write to the Free
17    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19    */
20    package org.xwiki.context;
21   
22    import java.util.HashMap;
23    import java.util.Map;
24   
25    import org.slf4j.Logger;
26    import org.slf4j.LoggerFactory;
27    import org.xwiki.context.internal.ExecutionContextProperty;
28   
29    /**
30    * Contains all state data related to the current user action. Note that the execution context is independent of the
31    * environment and all environment-dependent data are stored in the Container component instead.
32    *
33    * @version $Id: 68003104a09f9752b97949565e9445dfd65090c2 $
34    * @since 1.5M2
35    */
 
36    public class ExecutionContext
37    {
38    /** Logger object. */
39    private static final Logger LOGGER = LoggerFactory.getLogger(ExecutionContext.class);
40   
41    /**
42    * @see #getProperty(String)
43    */
44    private Map<String, ExecutionContextProperty> properties = new HashMap<String, ExecutionContextProperty>();
45   
46    /**
47    * @param key the key under which is stored the property to retrieve
48    * @return the property matching the passed key
49    */
 
50  38627955 toggle public Object getProperty(String key)
51    {
52  38627983 ExecutionContextProperty property = this.properties.get(key);
53   
54  38629399 if (property == null) {
55  360421 LOGGER.debug("Getting undefined property {} from execution context.", key);
56  360450 return null;
57    }
58   
59  38268990 return property.getValue();
60    }
61   
62    /**
63    * @param key the key of the property.
64    * @return a builder object for performing the declaration. The property will not be declared until the declare
65    * method is called on the builder object.
66    */
 
67  284123 toggle public DeclarationBuilder newProperty(String key)
68    {
69  284142 return new DeclarationBuilder(key);
70    }
71   
72    /**
73    * @param key the key under which is stored the property to retrieve
74    * @return {@code true} if there is a property declared for the given key.
75    */
 
76  123080 toggle public boolean hasProperty(String key)
77    {
78  123150 return this.properties.containsKey(key);
79    }
80   
81    /**
82    * @return all the context properties
83    */
 
84  2 toggle public Map<String, Object> getProperties()
85    {
86  2 Map<String, Object> map = new HashMap<String, Object>();
87   
88  2 for (Map.Entry<String, ExecutionContextProperty> entry : this.properties.entrySet()) {
89  2 map.put(entry.getKey(), entry.getValue().getValue());
90    }
91   
92  2 return map;
93    }
94   
95    /**
96    * @param key remove the property whose key matches the passed key
97    */
 
98  84006 toggle public void removeProperty(String key)
99    {
100  84017 ExecutionContextProperty property = this.properties.get(key);
101   
102  84016 if (property != null && property.isFinal()) {
103  0 throw new PropertyIsFinalException(key);
104    }
105   
106  84020 this.properties.remove(key);
107    }
108   
109    /**
110    * @param key the key under which to save the passed property value
111    * @param value the value to set
112    */
 
113  310503 toggle public void setProperty(String key, Object value)
114    {
115  310503 ExecutionContextProperty property = this.properties.get(key);
116   
117  310515 if (property == null) {
118  227870 LOGGER.debug("Implicit declaration of property {}.", key);
119  227872 newProperty(key).declare();
120  227890 property = this.properties.get(key);
121  82630 } else if (property.isFinal()) {
122  0 throw new PropertyIsFinalException(key);
123    }
124   
125  310504 property.setValue(value);
126    }
127   
128    /**
129    * @param properties the properties to add to the context
130    */
 
131  65 toggle public void setProperties(Map<String, Object> properties)
132    {
133  65 for (Map.Entry<String, Object> entry : properties.entrySet()) {
134  2 setProperty(entry.getKey(), entry.getValue());
135    }
136    }
137   
138    /**
139    * Declare a property.
140    *
141    * @param property The property with configured metadata attributes.
142    * @throws PropertyAlreadyExistsException if the property alread exists in this execution context.
143    * @since 4.3M1
144    */
 
145  340984 toggle private void declareProperty(ExecutionContextProperty property)
146    {
147  340998 if (this.properties.containsKey(property.getKey())) {
148  0 throw new PropertyAlreadyExistsException(property.getKey());
149    }
150   
151  340993 this.properties.put(property.getKey(), property);
152    }
153   
154    /**
155    * Inherit properties marked for inheritance from the given execution context.
156    * <p>
157    * Inheritance is performed both in {@link Execution#setContext(ExecutionContext)} and in
158    * {@link Execution#pushContext(ExecutionContext)} if there is a current execution context.
159    * <p>
160    * All properties marked as 'inherited' will be copied into this context, unless the property already is declared in
161    * this context.
162    * <p>
163    * It is an error if this context contain a value that was declared as 'inherited' and 'final' in the inherited
164    * execution context and an exception will be thrown.
165    *
166    * @param executionContext The execution to inherit.
167    * @throws IllegalStateException if the execution context cannot be inherited.
168    * @since 4.3M1
169    */
 
170  47220 toggle public void inheritFrom(ExecutionContext executionContext)
171    {
172  47226 for (ExecutionContextProperty property : executionContext.properties.values()) {
173  426523 if (property.isInherited()) {
174  124666 if (this.properties.containsKey(property.getKey())) {
175  67886 checkIfInheritedPropertyMayBeIgnored(property);
176    } else {
177  56770 declareProperty(property.clone());
178    }
179    }
180    }
181    }
182   
183    /**
184    * @param property Property to check.
185    * @throws IllegalStateException if the property may not be ignored.
186    */
 
187  67843 toggle private void checkIfInheritedPropertyMayBeIgnored(ExecutionContextProperty property)
188    {
189  67884 if (property.isFinal()) {
190  1 ExecutionContextProperty shadowingProperty = this.properties.get(property.getKey());
191  1 if (!(shadowingProperty == property || shadowingProperty.isClonedFrom(property))) {
192  1 throw new IllegalStateException(
193    String.format("Execution context cannot be inherited because it already contains"
194    + " property [%s] which must be inherited because it is an inherited"
195    + " final property.", property.getKey()));
196    }
197    }
198    }
199   
200    /**
201    * Builder class for declaring a new proprety.
202    *
203    * @since 4.3M2
204    */
 
205    public final class DeclarationBuilder
206    {
207   
208    /** @see ExecutionContextProperty#key */
209    private final String key;
210   
211    /** @see ExecutionContextProperty#value */
212    private Object value;
213   
214    /** @see ExecutionContextProperty#cloneValue */
215    private boolean cloneValue;
216   
217    /** @see ExecutionContextProperty#isFinal */
218    private boolean isFinal;
219   
220    /** @see ExecutionContextProperty#inherited */
221    private boolean inherited;
222   
223    /** @see ExecutionContextProperty#nonNull */
224    private boolean nonNull;
225   
226    /** @see ExecutionContextProperty#type */
227    private Class<?> type;
228   
229    /**
230    * Start building a property for the given key.
231    *
232    * @param key The property key.
233    */
 
234  284231 toggle private DeclarationBuilder(String key)
235    {
236  284218 this.key = key;
237    }
238   
239    /**
240    * Finish the building by declaring the property in this execution context.
241    */
 
242  284168 toggle public void declare()
243    {
244  284178 ExecutionContext.this.declareProperty(
245    new ExecutionContextProperty(this.key, this.value, this.cloneValue, this.isFinal, this.inherited,
246    this.nonNull, this.type));
247    }
248   
249    /**
250    * @param value The initial value.
251    * @return this declaration builder.
252    */
 
253  56272 toggle public DeclarationBuilder initial(Object value)
254    {
255  56296 this.value = value;
256  56318 return this;
257    }
258   
259    /**
260    * Make the initial value the final value.
261    *
262    * @return this declaration builder.
263    */
 
264  4 toggle public DeclarationBuilder makeFinal()
265    {
266  4 this.isFinal = true;
267  4 return this;
268    }
269   
270    /**
271    * Indicate that the value should be cloned when the property is cloned.
272    *
273    * @return this declaration builder.
274    */
 
275  21925 toggle public DeclarationBuilder cloneValue()
276    {
277  21937 this.cloneValue = true;
278  21965 return this;
279    }
280   
281    /**
282    * Set the type of the value.
283    *
284    * @param type The type to declare for the property.
285    * @return this declaration builder.
286    */
 
287  2 toggle public DeclarationBuilder type(Class<?> type)
288    {
289  2 this.type = type;
290  2 return this;
291    }
292   
293    /**
294    * Indicate that the property should be inherited.
295    *
296    * @return this declaration builder.
297    */
 
298  56263 toggle public DeclarationBuilder inherited()
299    {
300  56294 this.inherited = true;
301  56310 return this;
302    }
303   
304    /**
305    * Indicate that the property value may not be {@literal null}.
306    *
307    * @return this declaration builder.
308    */
 
309  1 toggle public DeclarationBuilder nonNull()
310    {
311  1 this.nonNull = true;
312  1 return this;
313    }
314    }
315    }