1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package com.tomgibara.pronto.config.impl;
19
20 import java.util.HashMap;
21
22 /**
23 * This class can be used to create canonical ConfigKey instances. Factories
24 * guarantee that object equality implies referential equality for all keys
25 * created by a factory or obtained as parents to such keys. Creating new keys
26 * from a factory may be slower than constructing them directly.
27 *
28 * Unless read-only, use of this class must be externally synchronized.
29 *
30 * Note the present implementation maintains a map of configuration key
31 * instances that prevents them from being garbage collected. This means that
32 * the map will grow without bound under some circumstances.
33 *
34 * @author Tom Gibara
35 *
36 */
37
38 class ConfigKeyFactory {
39
40 /**
41 * Maps paths to key instances with matching paths.
42 */
43
44 private final HashMap<String, ConfigKey> keys = new HashMap<String, ConfigKey>();
45
46 /**
47 * Indicates that the factory should not create any more keys. This field is
48 * volatile so that a previously read-only factory can be made read/write
49 * while threads concurrently call the newKey method.
50 */
51
52 private volatile boolean readOnly = false;
53
54
55
56 /**
57 * Whether the factory is in a read-only state. Read-only factories will not
58 * create new keys and as a result may return null from the newKey method.
59 * Conversely, read-only factories are safe for concurrent use.
60 *
61 * @return true if the factory will not create any new keys, false otherwise
62 */
63
64 public boolean isReadOnly() {
65 return readOnly;
66 }
67
68 /**
69 * Changes the read-only status of the factory.
70 *
71 * @param readOnly
72 * whether the factory should be read-only or not
73 */
74
75 public void setReadOnly(final boolean readOnly) {
76 this.readOnly = readOnly;
77 }
78
79
80
81 /**
82 * Creates a new key, or returns a previously created one. If the factory is
83 * in a read-only state, then existing keys will be returned from this
84 * method, but new keys are never created.
85 *
86 * @param path
87 * the path of the key to create, never null
88 * @return a key with that path, or null
89 */
90
91 public ConfigKey newKey(final String path) {
92
93 if (readOnly) return keys.get(path);
94
95 ConfigKey key = keys.get(path);
96 if (key == null) {
97 key = new ConfigKey(this, path);
98 keys.put(path, key);
99 }
100 return key;
101 }
102
103 /**
104 * Resets the factory to its original state. This means that the factory is
105 * not read-only and has no record of any keys it has previously generated.
106 *
107 * Calls to this method must be externally synchronized in all cases.
108 */
109
110 public void reset() {
111 readOnly = false;
112 keys.clear();
113 }
114
115 }