# Coverage details for edu.uci.ics.jung.utils.UnifiedUserData

Line | Hits | Source
--- | --- | ---
1 |  | `/*`
2 |  | `* Created on Jul 30, 2005`
3 |  | `*`
4 |  | `* Copyright (c) 2005, the JUNG Project and the Regents of the University`
5 |  | `* of California`
6 |  | `* All rights reserved.`
7 |  | `*`
8 |  | `* This software is open-source under the BSD license; see either`
9 |  | `* "license.txt" or`
10 |  | `* http://jung.sourceforge.net/license.txt for a description.`
11 |  | `*/`
12 |  | `package edu.uci.ics.jung.utils;`
13 |  | ``
14 |  | `import java.util.HashMap;`
15 |  | `import java.util.Iterator;`
16 |  | `import java.util.LinkedList;`
17 |  | `import java.util.List;`
18 |  | `import java.util.Map;`
19 |  | `import java.util.WeakHashMap;`
20 |  | ``
21 |  | `import org.apache.commons.collections.IteratorUtils;`
22 |  | ``
23 |  | `import edu.uci.ics.jung.exceptions.FatalException;`
24 |  | ``
25 |  | `/**`
26 |  | `* Represents custom user- and system-level information to extend the definition`
27 |  | `* of a node. This is the easiest way to extend the class without subclassing.`
28 |  | `*`
29 |  | `* This works as a dictionary in order to help ensure that there are`
30 |  | `* possibilities for extending user information to a variety of different sorts`
31 |  | `* of data. (Each provider of information can register their own enhanced`
32 |  | `* information without interfering with other providers.)`
33 |  | `*`
34 |  | `* Some suggested uses of UserData include`
35 |  | `* <ul>`
36 |  | `* <li/>Underlying data references, such as pointers to data sources</li>`
37 |  | `* <li/>Raw data which can be analyzed or used by the constraint and filter systems`
38 |  | `* <li/>Temporary enhanced information which can be used for visualization`
39 |  | `* </ul>`
40 |  | `*`
41 |  | `* Consider a series of nodes that has, among other things, enhanced information`
42 |  | `* about 3D coordinates. This might be stored in the 3DData data structure,`
43 |  | `* which generates itself with an input from a node.`
44 |  | `*`
45 |  | `* Thus the relevant call might be <code>n.addUserDatum("3DData", new 3DData (`
46 |  | `* ))</code>.`
47 |  | `* Later, to access this information, the call might be <code>3DData dd =`
48 |  | `* (3DData) n.getUserDatum("3DData").</code>`
49 |  | `*`
50 |  | `* <h3>Shared and Individual Data</h3>`
51 |  | `* Note that the there are no required semantics for the key or the information.`
52 |  | `* However, it is necessary to specify information that is used for SHARED and`
53 |  | `* for INDIVIDUAL data elements. When a new View of a graph is`
54 |  | `* generated, the Node elements inside it are all shallow-copied. The UserData`
55 |  | `* that they use, however, is <em>not</em> copied, by default. This is the`
56 |  | `* correct and logical behavior if the UserData contains source information.`
57 |  | `*`
58 |  | `* But what when the UserData contains transient information, specific to the`
59 |  | `* view, such as graph metrics or coordinates? In that case, the UserData would`
60 |  | `* be quite inappropriate to share that information between copies.`
61 |  | `*`
62 |  | `* The solution to this is to add a third flag, "shared", which tells whether`
63 |  | `* the currect data is shared or not. This flag is assigned when the data is`
64 |  | `* added.`
65 |  | `*/`
66 | 0 | `public class UnifiedUserData extends UserData implements UserDataFactory`
67 |  | `{`
68 |  | `// maps a Key to a Pair( UserData, CopyAction )`
69 |  | `// private Map userDataStorage;`
70 | 0 | `protected final static Map key_meta_map = new HashMap();`
71 |  | `// private final static Object NO_GRAPH = "NO_GRAPH";`
72 |  | ``
73 |  | `// private Map getStorage() {`
74 |  | `// if (userDataStorage == null) {`
75 |  | `// userDataStorage = new HashMap();`
76 |  | `// }`
77 |  | `// return userDataStorage;`
78 |  | `// }`
79 |  | ``
80 |  | `// /**`
81 |  | `// * This class actually clones by removing the reference to the copyAction`
82 |  | `// * and userData`
83 |  | `// */`
84 |  | `// protected Object clone() throws CloneNotSupportedException {`
85 |  | `// UserData ud = (UserData) super.clone();`
86 |  | `//// ud.userDataStorage = null;`
87 |  | `// return ud;`
88 |  | `// }`
89 |  | ``
90 |  | `protected Map getKeyMap(Object key)`
91 |  | `{`
92 | 0 | `Map key_map = (Map)key_meta_map.get(key);`
93 | 0 | `if (key_map == null)`
94 |  | `{`
95 | 0 | `key_map = new WeakHashMap();`
96 |  | `// key_map = new HashMap();`
97 | 0 | `key_meta_map.put(key, key_map);`
98 |  | `}`
99 | 0 | `return key_map;`
100 |  | `}`
101 |  | ``
102 |  | `// protected Pair getObjectKey()`
103 |  | `// {`
104 |  | `// Object container = this;`
105 |  | `// if (this instanceof Element)`
106 |  | `// {`
107 |  | `// container = ((Element)this).getGraph();`
108 |  | `// if (container == null)`
109 |  | `// container = NO_GRAPH;`
110 |  | `// }`
111 |  | `//// return new Pair(new WeakReference(this), new WeakReference(container));`
112 |  | `// return new Pair(this, container);`
113 |  | `// }`
114 |  | ``
115 |  | `/**`
116 |  | `* Adds user-level information to the node. Throws an exception if the node`
117 |  | `* already has information associated with it.`
118 |  | `*`
119 |  | `* @param key`
120 |  | `* A unique (per type, not per node) key into the information`
121 |  | `* @param value`
122 |  | `* The extended information associated with the node`
123 |  | `*/`
124 |  | `public void addUserDatum(Object key, Object value, CopyAction shared) {`
125 | 0 | `if (key == null)`
126 | 0 | `throw new IllegalArgumentException("Key must not be null");`
127 |  | ``
128 | 0 | `Map key_map = getKeyMap(key);`
129 |  | ``
130 |  | `// Pair object_key = getObjectKey();`
131 |  | `// if (key_map.containsKey(object_key))`
132 | 0 | `if (key_map.containsKey(this))`
133 | 0 | `throw new IllegalArgumentException("Key <" + key`
134 |  | `+ "> had already been added to object " + this);`
135 |  | ``
136 | 0 | `Pair object_value = new Pair(value, shared);`
137 |  | ``
138 |  | `// key_map.put(object_key, object_value);`
139 | 0 | `key_map.put(this, object_value);`
140 |  | ``
141 |  | `// if (!getStorage().containsKey(key)) {`
142 |  | `// getStorage().put(key, new Pair(value, shared));`
143 |  | `// } else {`
144 |  | `// throw new IllegalArgumentException("Key <" + key`
145 |  | `// + "> had already been added to an object with keys "`
146 |  | `// + getKeys());`
147 |  | `// }`
148 | 0 | `}`
149 |  | ``
150 |  | `/**`
151 |  | `* @return`
152 |  | `*/`
153 |  | `// private Set getKeys() {`
154 |  | `// return getStorage().keySet();`
155 |  | `// }`
156 |  | ``
157 |  | `/**`
158 |  | `* Uses the CopyAction to determine how each of the user datum elements in`
159 |  | `* udc should be carried over to the this UserDataContiner`
160 |  | `*`
161 |  | `* @param udc`
162 |  | `* The UserDataContainer whose user data is being imported`
163 |  | `*/`
164 |  | `public void importUserData(UserDataContainer udc) {`
165 | 0 | `for (Iterator keyIt = udc.getUserDatumKeyIterator(); keyIt.hasNext();) {`
166 | 0 | `Object key = keyIt.next();`
167 | 0 | `Object value = udc.getUserDatum(key);`
168 | 0 | `CopyAction action = udc.getUserDatumCopyAction(key);`
169 | 0 | `Object newValue = action.onCopy(value, udc, this);`
170 |  | `try {`
171 | 0 | `if (newValue != null) addUserDatum(key, newValue, action);`
172 |  | ``
173 | 0 | `} catch (IllegalArgumentException iae) {`
174 | 0 | `List userDataKeys = IteratorUtils.toList(udc`
175 |  | `.getUserDatumKeyIterator());`
176 | 0 | `throw new FatalException("Copying <" + key + "> of "`
177 |  | `+ userDataKeys`
178 |  | `+ " into a container that started with some keys ",`
179 |  | `iae);`
180 | 0 | `}`
181 |  | `}`
182 |  | ``
183 | 0 | `}`
184 |  | ``
185 |  | `/**`
186 |  | `* Changes the user-level information to the object. Equivalent to calling`
187 |  | `*`
188 |  | `* <pre>`
189 |  | `* removeUserDatum( key );`
190 |  | `* addUserDatum(key, value)`
191 |  | `* </pre>`
192 |  | `*`
193 |  | `* @param key`
194 |  | `* @param value`
195 |  | `*/`
196 |  | `public void setUserDatum(Object key, Object value, CopyAction shared) {`
197 |  | `// removeUserDatum(key);`
198 |  | `// addUserDatum(key, value, shared);`
199 |  | `// getKeyMap(key).put(getObjectKey(), new Pair(value, shared));`
200 | 0 | `getKeyMap(key).put(this, new Pair(value, shared));`
201 |  | `// getStorage().put(key, new Pair(value, shared));`
202 | 0 | `}`
203 |  | ``
204 |  | `/**`
205 |  | `* Returns UserData (if any) for this key, or <em>null</em> if not`
206 |  | `* known.`
207 |  | `*`
208 |  | `* @param key`
209 |  | `*/`
210 |  | `public Object getUserDatum(Object key)`
211 |  | `{`
212 | 0 | `Pair value_pair = this.getUserDatumValuePair(key);`
213 |  | `// Pair p = (Pair) getStorage().get(key);`
214 | 0 | `if (value_pair == null)`
215 | 0 | `return null;`
216 | 0 | `return value_pair.getFirst();`
217 |  | `}`
218 |  | ``
219 |  | `protected Pair getUserDatumValuePair(Object key)`
220 |  | `{`
221 |  | `// return (Pair)(getKeyMap(key).get(getObjectKey()));`
222 | 0 | `return (Pair)(getKeyMap(key).get(this));`
223 |  | `}`
224 |  | ``
225 |  | `/**`
226 |  | `* Removes the Datum (if any) for this key, and returns it.`
227 |  | `*`
228 |  | `* @param key`
229 |  | `*/`
230 |  | `public Object removeUserDatum(Object key) {`
231 | 0 | `Object o = getUserDatum(key);`
232 | 0 | `Map key_map = getKeyMap(key);`
233 |  | `// key_map.remove(getObjectKey());`
234 | 0 | `key_map.remove(this);`
235 | 0 | `if (key_map.isEmpty())`
236 | 0 | `key_meta_map.remove(key_map);`
237 |  | `// getStorage().remove(key);`
238 |  | `// return value_pair.getFirst();`
239 | 0 | `return o;`
240 |  | `}`
241 |  | ``
242 |  | `/**`
243 |  | `* Returns an <code>Iterator</code> which can be used to iterate over`
244 |  | `* all the user data repository keys for this object.`
245 |  | `*`
246 |  | `* @return Iterator`
247 |  | `*/`
248 |  | `public Iterator getUserDatumKeyIterator() {`
249 | 0 | `List keys = new LinkedList();`
250 |  | `// Pair key_pair = getObjectKey();`
251 | 0 | `for (Iterator iter = key_meta_map.keySet().iterator(); iter.hasNext(); )`
252 |  | `{`
253 | 0 | `Object key = iter.next();`
254 | 0 | `Map key_map = getKeyMap(key);`
255 |  | `// if (key_map.containsKey(key_pair))`
256 | 0 | `if (key_map.containsKey(this))`
257 | 0 | `keys.add(key);`
258 |  | `}`
259 | 0 | `return keys.iterator();`
260 |  | `// return getStorage().keySet().iterator();`
261 |  | `}`
262 |  | ``
263 |  | `/**`
264 |  | `* @see UserDataContainer#containsUserDatumKey(Object)`
265 |  | `*/`
266 |  | `public boolean containsUserDatumKey(Object key)`
267 |  | `{`
268 |  | `// return ((Map)key_meta_map.get(key)).containsKey(getObjectKey());`
269 | 0 | `return ((Map)key_meta_map.get(key)).containsKey(this);`
270 |  | `// return getStorage().containsKey(key);`
271 |  | `}`
272 |  | ``
273 |  | `/**`
274 |  | `* Returns the CopyAction associated with this key.`
275 |  | `*`
276 |  | `* @param key`
277 |  | `* @return CopyAction`
278 |  | `*/`
279 |  | `public CopyAction getUserDatumCopyAction(Object key) {`
280 | 0 | `Pair value_pair = this.getUserDatumValuePair(key);`
281 | 0 | `if (value_pair == null) return null;`
282 |  | `// Pair p = (Pair) getStorage().get(key);`
283 | 0 | `return (CopyAction) value_pair.getSecond();`
284 |  | `}`
285 |  | ``
286 |  | `public UserDataContainer getInstance()`
287 |  | `{`
288 | 0 | `return new UnifiedUserData();`
289 |  | `}`
290 |  | ``
291 |  | `public Object clone() throws CloneNotSupportedException`
292 |  | `{`
293 | 0 | `return super.clone();`
294 |  | `}`
295 |  | ``
296 |  | `}`

this report was generated by version 1.0.5 of jcoverage. visit www.jcoverage.com for updates. | copyright © 2003, jcoverage ltd. all rights reserved. Java is a trademark of Sun Microsystems, Inc. in the United States and other countries.