1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 package net.sf.jtreemap.swing.example;
34
35 import java.io.BufferedReader;
36 import java.io.File;
37 import java.io.FileReader;
38 import java.io.IOException;
39 import java.io.Serializable;
40 import java.text.ParseException;
41 import java.text.SimpleDateFormat;
42 import java.util.Date;
43 import java.util.Enumeration;
44 import java.util.HashMap;
45 import java.util.LinkedList;
46 import java.util.StringTokenizer;
47 import java.util.TreeSet;
48
49 import net.sf.jtreemap.swing.DefaultValue;
50 import net.sf.jtreemap.swing.TreeMapNode;
51 import net.sf.jtreemap.swing.TreeMapNodeBuilder;
52
53
54
55 /**
56 * Parse a TM3 file to build the tree. <BR>
57 * See <a href=http://www.cs.umd.edu/hcil/treemap/doc4.1/create_TM3_file.html>
58 * how to create your own TM3 data file </a> from hcil Treemap site.
59 *
60 * @author Laurent DUTHEIL
61 */
62 public class BuilderTM3 implements Serializable {
63 /**
64 *
65 */
66 private static final long serialVersionUID = -991159075093937695L;
67
68 /**
69 * label "DATE" to identify Date in TM3 data file
70 */
71 public static final String DATE = "DATE";
72
73 /**
74 * label "FLOAT" to identify float in TM3 data file
75 */
76 public static final String FLOAT = "FLOAT";
77
78 /**
79 * label "INTEGER" to identify int in TM3 data file
80 */
81 public static final String INTEGER = "INTEGER";
82
83 /**
84 * label "STRING" to identify String in TM3 data file
85 */
86 public static final String STRING = "STRING";
87
88 private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MM/dd/yyyy");
89
90 private static final LinkedList<String> FIELD_NAMES = new LinkedList<String>();
91
92 private static final LinkedList<String> FIELD_TYPES = new LinkedList<String>();
93
94 private final HashMap<TreeMapNode, HashMap<String, Object>> values = new HashMap<TreeMapNode, HashMap<String, Object>>();
95
96 private TreeMapNodeBuilder builder;
97
98 /**
99 * Constructor
100 *
101 * @param tm3File
102 * tm3 file
103 * @throws IOException
104 */
105 public BuilderTM3(final File tm3File) throws IOException {
106 this.builder = new TreeMapNodeBuilder();
107 parse(new BufferedReader(new FileReader(tm3File)));
108 }
109
110 /**
111 * Constructor
112 *
113 * @param reader
114 * reader associated with tm3 file
115 * @throws IOException
116 */
117 public BuilderTM3(final BufferedReader reader) throws IOException {
118 this.builder = new TreeMapNodeBuilder();
119 parse(reader);
120 }
121
122 /**
123 * @return the number fields (ie INTEGER and FLOAT)
124 */
125 public String[] getNumberFields() {
126 final TreeSet<String> result = new TreeSet<String>();
127 for (int i = 0; i < FIELD_NAMES.size(); i++) {
128 final String type = FIELD_TYPES.get(i);
129 if (INTEGER.equals(type) || FLOAT.equals(type)) {
130 result.add(FIELD_NAMES.get(i));
131 }
132 }
133 return result.toArray(new String[1]);
134 }
135
136 /**
137 * get the build root.
138 *
139 * @return the build root
140 */
141 public TreeMapNode getRoot() {
142 return this.builder.getRoot();
143 }
144
145 /**
146 * Set the VALUES of all the JTreeMapNode with the VALUES of the fieldName.
147 *
148 * @param fieldName
149 * name of the field to set the VALUES
150 */
151 public void setValues(final String fieldName) {
152 if ("".equals(fieldName)) {
153 for (final TreeMapNode node : values.keySet()) {
154 node.setValue(new DefaultValue(0));
155 }
156 } else {
157 for (final TreeMapNode node : values.keySet()) {
158 final HashMap<String, Object> mapNodeValues = values.get(node);
159 final Object value = mapNodeValues.get(fieldName);
160 if (value instanceof Number) {
161 final Number number = (Number) value;
162 node.setValue(new DefaultValue(number.doubleValue()));
163 } else if (value instanceof Date) {
164 final Date date = (Date) value;
165 node.setValue(new DefaultValue(date.getTime()));
166 }
167 }
168 }
169 }
170
171 /**
172 * Set the weights of all the JTreeMapNode with the VALUES of the fieldName.
173 *
174 * @param fieldName
175 * name of the field to set the weights
176 */
177 public void setWeights(final String fieldName) {
178 if ("".equals(fieldName)) {
179 for (final TreeMapNode node : values.keySet()) {
180 node.setWeight(1);
181 }
182 } else {
183 for (final TreeMapNode node : values.keySet()) {
184 final HashMap<String, Object> mapNodeValues = values.get(node);
185 final Object value = mapNodeValues.get(fieldName);
186 if (value instanceof Number) {
187 final Number number = (Number) value;
188 node.setWeight(number.doubleValue());
189 } else if (value instanceof Date) {
190 final Date date = (Date) value;
191 node.setWeight(date.getTime());
192 }
193 }
194 }
195 }
196
197 /**
198 * @param st
199 * StringTokenizer which contains the hierarchy path
200 * @param mapNodeValues
201 * HashMap with fields and their VALUES
202 */
203 private void createNodes(final StringTokenizer st, final HashMap<String, Object> mapNodeValues) {
204
205 final LinkedList<String> hierarchyPath = new LinkedList<String>();
206 while (st.hasMoreTokens()) {
207 hierarchyPath.add(st.nextToken());
208 }
209
210 TreeMapNode node = this.builder.getRoot();
211 if (node == null) {
212 node = this.builder.buildBranch(hierarchyPath.get(0), null);
213 }
214 for (int i = 1; i < hierarchyPath.size() - 1; i++) {
215
216 boolean found = false;
217 TreeMapNode child = null;
218 for (final Enumeration iter = node.children(); iter.hasMoreElements();) {
219 child = (TreeMapNode) iter.nextElement();
220 if (child.getLabel().equals(hierarchyPath.get(i))) {
221 found = true;
222 break;
223 }
224 }
225 if (found) {
226 node = child;
227 } else {
228 node = this.builder.buildBranch(hierarchyPath.get(i), node);
229 }
230 }
231
232
233 final TreeMapNode leaf = this.builder.buildLeaf(hierarchyPath.getLast(), 1, new DefaultValue(), node);
234
235 values.put(leaf, mapNodeValues);
236 }
237
238 /**
239 * @param reader The <code>BufferedReader</code>.
240 * @throws IOException
241 */
242 private void parse(final BufferedReader reader) throws IOException {
243 try {
244 String line = "";
245
246 line = reader.readLine();
247 StringTokenizer st = new StringTokenizer(line, "\t");
248 FIELD_NAMES.clear();
249 while (st.hasMoreTokens()) {
250 FIELD_NAMES.add(st.nextToken());
251 }
252
253
254 line = reader.readLine();
255 st = new StringTokenizer(line, "\t");
256 FIELD_TYPES.clear();
257 while (st.hasMoreTokens()) {
258 FIELD_TYPES.add(st.nextToken());
259 }
260
261
262 values.clear();
263 while ((line = reader.readLine()) != null) {
264 st = new StringTokenizer(line, "\t");
265 final HashMap<String, Object> mapNodeValues = new HashMap<String, Object>();
266
267 for (int i = 0; i < FIELD_NAMES.size(); i++) {
268 Object value;
269 if (FLOAT.equals(FIELD_TYPES.get(i))) {
270 value = new Double(Double.parseDouble(st.nextToken()));
271 } else if (INTEGER.equals(FIELD_TYPES.get(i))) {
272 value = new Integer(Integer.parseInt(st.nextToken()));
273 } else if (DATE.equals(FIELD_TYPES.get(i))) {
274 try {
275 value = DATE_FORMAT.parse(st.nextToken());
276 } catch (final ParseException e) {
277 value = null;
278 }
279 } else {
280 value = st.nextToken();
281 }
282 mapNodeValues.put(FIELD_NAMES.get(i), value);
283 }
284
285
286 if (!st.hasMoreTokens()) {
287
288 throw new IOException("the file didn't contains the hierarchy path");
289 }
290
291
292 createNodes(st, mapNodeValues);
293 }
294 } finally {
295 if (reader != null) {
296 reader.close();
297 }
298 }
299 }
300 }
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316