KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jface > bindings > CachedBindingSet


1 /*******************************************************************************
2  * Copyright (c) 2004, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jface.bindings;
12
13 import java.util.Map JavaDoc;
14
15 import org.eclipse.jface.util.Util;
16
17 /**
18  * <p>
19  * A resolution of bindings for a given state. To see if we already have a
20  * cached binding set, just create one of these binding sets and then look it up
21  * in a map. If it is not already there, then add it and set the cached binding
22  * resolution.
23  * </p>
24  *
25  * @since 3.1
26  */

27 final class CachedBindingSet {
28
29     /**
30      * A factor for computing the hash code for all cached binding sets.
31      */

32     private final static int HASH_FACTOR = 89;
33
34     /**
35      * The seed for the hash code for all cached binding sets.
36      */

37     private final static int HASH_INITIAL = CachedBindingSet.class.getName()
38             .hashCode();
39
40     /**
41      * <p>
42      * A representation of the tree of active contexts at the time this cached
43      * binding set was computed. It is a map of context id (<code>String</code>)
44      * to context id (<code>String</code>). Each key represents one of the
45      * active contexts or one of its ancestors, while each value represents its
46      * parent. This is a way of perserving information about what the hierarchy
47      * looked like.
48      * </p>
49      * <p>
50      * This value will be <code>null</code> if the contexts were disregarded
51      * in the computation. It may also be empty. All of the keys are guaranteed
52      * to be non- <code>null</code>, but the values can be <code>null</code>
53      * (i.e., no parent).
54      * </p>
55      */

56     private final Map JavaDoc activeContextTree;
57
58     /**
59      * The map representing the resolved state of the bindings. This is a map of
60      * a trigger (<code>TriggerSequence</code>) to binding (<code>Binding</code>).
61      * This value may be <code>null</code> if it has not yet been initialized.
62      */

63     private Map JavaDoc bindingsByTrigger = null;
64
65     /**
66      * A map of triggers to collections of bindings. If this binding set
67      * contains conflicts, they are logged here.
68      *
69      * @since 3.3
70      */

71     private Map JavaDoc conflictsByTrigger = null;
72
73     /**
74      * The hash code for this object. This value is computed lazily, and marked
75      * as invalid when one of the values on which it is based changes.
76      */

77     private transient int hashCode;
78
79     /**
80      * Whether <code>hashCode</code> still contains a valid value.
81      */

82     private transient boolean hashCodeComputed = false;
83
84     /**
85      * <p>
86      * The list of locales that were active at the time this binding set was
87      * computed. This list starts with the most specific representation of the
88      * locale, and moves to more general representations. For example, this
89      * array might look like ["en_US", "en", "", null].
90      * </p>
91      * <p>
92      * This value will never be <code>null</code>, and it will never be
93      * empty. It must contain at least one element, but its elements can be
94      * <code>null</code>.
95      * </p>
96      */

97     private final String JavaDoc[] locales;
98
99     /**
100      * <p>
101      * The list of platforms that were active at the time this binding set was
102      * computed. This list starts with the most specific representation of the
103      * platform, and moves to more general representations. For example, this
104      * array might look like ["gtk", "", null].
105      * </p>
106      * <p>
107      * This value will never be <code>null</code>, and it will never be
108      * empty. It must contain at least one element, but its elements can be
109      * <code>null</code>.
110      * </p>
111      */

112     private final String JavaDoc[] platforms;
113
114     /**
115      * A map of prefixes (<code>TriggerSequence</code>) to a map of
116      * available completions (possibly <code>null</code>, which means there
117      * is an exact match). The available completions is a map of trigger (<code>TriggerSequence</code>)
118      * to command identifier (<code>String</code>). This value is
119      * <code>null</code> if it has not yet been initialized.
120      */

121     private Map JavaDoc prefixTable = null;
122
123     /**
124      * <p>
125      * The list of schemes that were active at the time this binding set was
126      * computed. This list starts with the active scheme, and then continues
127      * with all of its ancestors -- in order. For example, this might look like
128      * ["emacs", "default"].
129      * </p>
130      * <p>
131      * This value will never be <code>null</code>, and it will never be
132      * empty. It must contain at least one element. Its elements cannot be
133      * <code>null</code>.
134      * </p>
135      */

136     private final String JavaDoc[] schemeIds;
137
138     /**
139      * The map representing the resolved state of the bindings. This is a map of
140      * a command id (<code>String</code>) to triggers (<code>Collection</code>
141      * of <code>TriggerSequence</code>). This value may be <code>null</code>
142      * if it has not yet been initialized.
143      */

144     private Map JavaDoc triggersByCommandId = null;
145
146     /**
147      * Constructs a new instance of <code>CachedBindingSet</code>.
148      *
149      * @param activeContextTree
150      * The set of context identifiers that were active when this
151      * binding set was calculated; may be empty. If it is
152      * <code>null</code>, then the contexts were disregarded in
153      * the computation. This is a map of context id (
154      * <code>String</code>) to parent context id (
155      * <code>String</code>). This is a way of caching the look of
156      * the context tree at the time the binding set was computed.
157      * @param locales
158      * The locales that were active when this binding set was
159      * calculated. The first element is the currently active locale,
160      * and it is followed by increasingly more general locales. This
161      * must not be <code>null</code> and must contain at least one
162      * element. The elements can be <code>null</code>, though.
163      * @param platforms
164      * The platform that were active when this binding set was
165      * calculated. The first element is the currently active
166      * platform, and it is followed by increasingly more general
167      * platforms. This must not be <code>null</code> and must
168      * contain at least one element. The elements can be
169      * <code>null</code>, though.
170      * @param schemeIds
171      * The scheme that was active when this binding set was
172      * calculated, followed by its ancestors. This may be
173      * <code>null</code or empty. The
174      * elements cannot be <code>null</code>.
175      */

176     CachedBindingSet(final Map JavaDoc activeContextTree, final String JavaDoc[] locales,
177             final String JavaDoc[] platforms, final String JavaDoc[] schemeIds) {
178         if (locales == null) {
179             throw new NullPointerException JavaDoc("The locales cannot be null."); //$NON-NLS-1$
180
}
181
182         if (locales.length == 0) {
183             throw new NullPointerException JavaDoc("The locales cannot be empty."); //$NON-NLS-1$
184
}
185
186         if (platforms == null) {
187             throw new NullPointerException JavaDoc("The platforms cannot be null."); //$NON-NLS-1$
188
}
189
190         if (platforms.length == 0) {
191             throw new NullPointerException JavaDoc("The platforms cannot be empty."); //$NON-NLS-1$
192
}
193
194         this.activeContextTree = activeContextTree;
195         this.locales = locales;
196         this.platforms = platforms;
197         this.schemeIds = schemeIds;
198     }
199
200     /**
201      * Compares this binding set with another object. The objects will be equal
202      * if they are both instance of <code>CachedBindingSet</code> and have
203      * equivalent values for all of their properties.
204      *
205      * @param object
206      * The object with which to compare; may be <code>null</code>.
207      * @return <code>true</code> if they are both instances of
208      * <code>CachedBindingSet</code> and have the same values for all
209      * of their properties; <code>false</code> otherwise.
210      */

211     public final boolean equals(final Object JavaDoc object) {
212         if (!(object instanceof CachedBindingSet)) {
213             return false;
214         }
215
216         final CachedBindingSet other = (CachedBindingSet) object;
217
218         if (!Util.equals(activeContextTree, other.activeContextTree)) {
219             return false;
220         }
221         if (!Util.equals(locales, other.locales)) {
222             return false;
223         }
224         if (!Util.equals(platforms, other.platforms)) {
225             return false;
226         }
227         return Util.equals(schemeIds, other.schemeIds);
228     }
229
230     /**
231      * Returns the map of command identifiers indexed by trigger sequence.
232      *
233      * @return A map of triggers (<code>TriggerSequence</code>) to bindings (<code>Binding</code>).
234      * This value may be <code>null</code> if this was not yet
235      * initialized.
236      */

237     final Map JavaDoc getBindingsByTrigger() {
238         return bindingsByTrigger;
239     }
240
241     /**
242      * Returns a map of conflicts for this set of contexts.
243      *
244      * @return A map of trigger to a collection of Bindings. May be
245      * <code>null</code>.
246      * @since 3.3
247      */

248     final Map JavaDoc getConflictsByTrigger() {
249         return conflictsByTrigger;
250     }
251
252     /**
253      * Returns the map of prefixes to a map of trigger sequence to command
254      * identifiers.
255      *
256      * @return A map of prefixes (<code>TriggerSequence</code>) to a map of
257      * available completions (possibly <code>null</code>, which means
258      * there is an exact match). The available completions is a map of
259      * trigger (<code>TriggerSequence</code>) to command identifier (<code>String</code>).
260      * This value may be <code>null</code> if it has not yet been
261      * initialized.
262      */

263     final Map JavaDoc getPrefixTable() {
264         return prefixTable;
265     }
266
267     /**
268      * Returns the map of triggers indexed by command identifiers.
269      *
270      * @return A map of command identifiers (<code>String</code>) to
271      * triggers (<code>Collection</code> of
272      * <code>TriggerSequence</code>). This value may be
273      * <code>null</code> if this was not yet initialized.
274      */

275     final Map JavaDoc getTriggersByCommandId() {
276         return triggersByCommandId;
277     }
278
279     /**
280      * Computes the hash code for this cached binding set. The hash code is
281      * based only on the immutable values. This allows the set to be created and
282      * checked for in a hashed collection <em>before</em> doing any
283      * computation.
284      *
285      * @return The hash code for this cached binding set.
286      */

287     public final int hashCode() {
288         if (!hashCodeComputed) {
289             hashCode = HASH_INITIAL;
290             hashCode = hashCode * HASH_FACTOR
291                     + Util.hashCode(activeContextTree);
292             hashCode = hashCode * HASH_FACTOR + Util.hashCode(locales);
293             hashCode = hashCode * HASH_FACTOR + Util.hashCode(platforms);
294             hashCode = hashCode * HASH_FACTOR + Util.hashCode(schemeIds);
295             hashCodeComputed = true;
296         }
297
298         return hashCode;
299     }
300
301     /**
302      * Sets the map of command identifiers indexed by trigger.
303      *
304      * @param commandIdsByTrigger
305      * The map to set; must not be <code>null</code>. This is a
306      * map of triggers (<code>TriggerSequence</code>) to binding (<code>Binding</code>).
307      */

308     final void setBindingsByTrigger(final Map JavaDoc commandIdsByTrigger) {
309         if (commandIdsByTrigger == null) {
310             throw new NullPointerException JavaDoc(
311                     "Cannot set a null binding resolution"); //$NON-NLS-1$
312
}
313
314         this.bindingsByTrigger = commandIdsByTrigger;
315     }
316
317     /**
318      * Sets the map of conflicting bindings by trigger.
319      *
320      * @param conflicts
321      * The map to set; must not be <code>null</code>.
322      * @since 3.3
323      */

324     final void setConflictsByTrigger(final Map JavaDoc conflicts) {
325         if (conflicts == null) {
326             throw new NullPointerException JavaDoc(
327                     "Cannot set a null binding conflicts"); //$NON-NLS-1$
328
}
329         conflictsByTrigger = conflicts;
330     }
331
332     /**
333      * Sets the map of prefixes to a map of trigger sequence to command
334      * identifiers.
335      *
336      * @param prefixTable
337      * A map of prefixes (<code>TriggerSequence</code>) to a map
338      * of available completions (possibly <code>null</code>, which
339      * means there is an exact match). The available completions is a
340      * map of trigger (<code>TriggerSequence</code>) to command
341      * identifier (<code>String</code>). Must not be
342      * <code>null</code>.
343      */

344     final void setPrefixTable(final Map JavaDoc prefixTable) {
345         if (prefixTable == null) {
346             throw new NullPointerException JavaDoc("Cannot set a null prefix table"); //$NON-NLS-1$
347
}
348
349         this.prefixTable = prefixTable;
350     }
351
352     /**
353      * Sets the map of triggers indexed by command identifiers.
354      *
355      * @param triggersByCommandId
356      * The map to set; must not be <code>null</code>. This is a
357      * map of command identifiers (<code>String</code>) to
358      * triggers (<code>Collection</code> of
359      * <code>TriggerSequence</code>).
360      */

361     final void setTriggersByCommandId(final Map JavaDoc triggersByCommandId) {
362         if (triggersByCommandId == null) {
363             throw new NullPointerException JavaDoc(
364                     "Cannot set a null binding resolution"); //$NON-NLS-1$
365
}
366
367         this.triggersByCommandId = triggersByCommandId;
368     }
369 }
370
Popular Tags