View Javadoc
1   /*
2    * ObjectLab, http://www.objectlab.co.uk/open is supporting JTreeMap.
3    *
4    * Based in London, we are world leaders in the design and development
5    * of bespoke applications for the securities financing markets.
6    *
7    * <a href="http://www.objectlab.co.uk/open">Click here to learn more</a>
8    *           ___  _     _           _   _          _
9    *          / _ \| |__ (_) ___  ___| |_| |    __ _| |__
10   *         | | | | '_ \| |/ _ \/ __| __| |   / _` | '_ \
11   *         | |_| | |_) | |  __/ (__| |_| |__| (_| | |_) |
12   *          \___/|_.__// |\___|\___|\__|_____\__,_|_.__/
13   *                   |__/
14   *
15   *                     www.ObjectLab.co.uk
16   *
17   * $Id$
18   *
19   * Copyright 2006 the original author or authors.
20   *
21   * Licensed under the Apache License, Version 2.0 (the "License"); you may not
22   * use this file except in compliance with the License. You may obtain a copy of
23   * the License at
24   *
25   * http://www.apache.org/licenses/LICENSE-2.0
26   *
27   * Unless required by applicable law or agreed to in writing, software
28   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
29   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
30   * License for the specific language governing permissions and limitations under
31   * the License.
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   * Parse a TM3 file to build the tree. <BR>
55   * See <a href=http://www.cs.umd.edu/hcil/treemap/doc4.1/create_TM3_file.html>;
56   * how to create your own TM3 data file </a> from hcil Treemap site.
57   *
58   * @author Laurent DUTHEIL
59   */
60  public class BuilderTM3 implements Serializable {
61      /**
62       *
63       */
64      private static final long serialVersionUID = -991159075093937695L;
65  
66      /**
67       * label "DATE" to identify Date in TM3 data file
68       */
69      public static final String DATE = "DATE";
70  
71      /**
72       * label "FLOAT" to identify float in TM3 data file
73       */
74      public static final String FLOAT = "FLOAT";
75  
76      /**
77       * label "INTEGER" to identify int in TM3 data file
78       */
79      public static final String INTEGER = "INTEGER";
80  
81      /**
82       * label "STRING" to identify String in TM3 data file
83       */
84      public static final String STRING = "STRING";
85  
86      private final SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy");
87      private static final LinkedList<String> FIELD_NAMES = new LinkedList<>();
88      private static final LinkedList<String> FIELD_TYPES = new LinkedList<>();
89      private final HashMap<TreeMapNode, HashMap<String, Object>> values = new HashMap<>();
90      private final TreeMapNodeBuilder builder;
91  
92      /**
93       * Constructor
94       *
95       * @param tm3File
96       *            tm3 file
97       * @throws IOException
98       */
99      public BuilderTM3(final File tm3File) throws IOException {
100         this.builder = new TreeMapNodeBuilder();
101         parse(new BufferedReader(new FileReader(tm3File)));
102     }
103 
104     /**
105      * Constructor
106      *
107      * @param reader
108      *            reader associated with tm3 file
109      * @throws IOException
110      */
111     public BuilderTM3(final BufferedReader reader) throws IOException {
112         this.builder = new TreeMapNodeBuilder();
113         parse(reader);
114     }
115 
116     /**
117      * @return the number fields (ie INTEGER and FLOAT)
118      */
119     public String[] getNumberFields() {
120         final TreeSet<String> result = new TreeSet<>();
121         for (int i = 0; i < FIELD_NAMES.size(); i++) {
122             final String type = FIELD_TYPES.get(i);
123             if (INTEGER.equals(type) || FLOAT.equals(type)) {
124                 result.add(FIELD_NAMES.get(i));
125             }
126         }
127         return result.toArray(new String[1]);
128     }
129 
130     /**
131      * get the build root.
132      *
133      * @return the build root
134      */
135     public TreeMapNode getRoot() {
136         return this.builder.getRoot();
137     }
138 
139     /**
140      * Set the VALUES of all the JTreeMapNode with the VALUES of the fieldName.
141      *
142      * @param fieldName
143      *            name of the field to set the VALUES
144      */
145     public void setValues(final String fieldName) {
146         if ("".equals(fieldName)) {
147             for (final TreeMapNode node : values.keySet()) {
148                 node.setValue(new DefaultValue(0));
149             }
150         } else {
151             values.entrySet().forEach(e -> {
152                 final Object value = e.getValue().get(fieldName);
153                 if (value instanceof Number) {
154                     final Number number = (Number) value;
155                     e.getKey().setValue(new DefaultValue(number.doubleValue()));
156                 } else if (value instanceof Date) {
157                     final Date date = (Date) value;
158                     e.getKey().setValue(new DefaultValue(date.getTime()));
159                 }
160             });
161         }
162     }
163 
164     /**
165      * Set the weights of all the JTreeMapNode with the VALUES of the fieldName.
166      *
167      * @param fieldName
168      *            name of the field to set the weights
169      */
170     public void setWeights(final String fieldName) {
171         if ("".equals(fieldName)) {
172             for (final TreeMapNode node : values.keySet()) {
173                 node.setWeight(1);
174             }
175         } else {
176             values.entrySet().forEach(e -> {
177                 final Object value = e.getValue().get(fieldName);
178                 if (value instanceof Number) {
179                     final Number number = (Number) value;
180                     e.getKey().setWeight(number.doubleValue());
181                 } else if (value instanceof Date) {
182                     final Date date = (Date) value;
183                     e.getKey().setWeight(date.getTime());
184                 }
185             });
186         }
187     }
188 
189     /**
190      * @param st
191      *            StringTokenizer which contains the hierarchy path
192      * @param mapNodeValues
193      *            HashMap with fields and their VALUES
194      */
195     private void createNodes(final StringTokenizer st, final HashMap<String, Object> mapNodeValues) {
196         // read the hierarchy path
197         final LinkedList<String> hierarchyPath = new LinkedList<>();
198         while (st.hasMoreTokens()) {
199             hierarchyPath.add(st.nextToken());
200         }
201 
202         TreeMapNode node = this.builder.getRoot();
203         if (node == null) {
204             node = this.builder.buildBranch(hierarchyPath.get(0), null);
205         }
206         for (int i = 1; i < hierarchyPath.size() - 1; i++) {
207             // looking for the child
208             boolean found = false;
209             TreeMapNode child = null;
210             for (final Enumeration iter = node.children(); iter.hasMoreElements();) {
211                 child = (TreeMapNode) iter.nextElement();
212                 if (child.getLabel().equals(hierarchyPath.get(i))) {
213                     found = true;
214                     break;
215                 }
216             }
217             if (found) {
218                 node = child;
219             } else {
220                 node = this.builder.buildBranch(hierarchyPath.get(i), node);
221             }
222         }
223 
224         // create the leaf
225         final TreeMapNode leaf = this.builder.buildLeaf(hierarchyPath.getLast(), 1, new DefaultValue(), node);
226         // each leaf is associated to their VALUES
227         values.put(leaf, mapNodeValues);
228     }
229 
230     /**
231      * @param reader The <code>BufferedReader</code>.
232      * @throws IOException
233      */
234     private void parse(final BufferedReader reader) throws IOException {
235         try {
236             String line = reader.readLine();
237             StringTokenizer st = new StringTokenizer(line, "\t");
238             FIELD_NAMES.clear();
239             while (st.hasMoreTokens()) {
240                 FIELD_NAMES.add(st.nextToken());
241             }
242 
243             // read the field types
244             line = reader.readLine();
245             st = new StringTokenizer(line, "\t");
246             FIELD_TYPES.clear();
247             while (st.hasMoreTokens()) {
248                 FIELD_TYPES.add(st.nextToken());
249             }
250 
251             // read the VALUES
252             values.clear();
253             while ((line = reader.readLine()) != null) {
254                 handleALine(line);
255             }
256         } finally {
257             reader.close();
258         }
259     }
260 
261     private void handleALine(String line) throws IOException {
262         StringTokenizer st;
263         st = new StringTokenizer(line, "\t");
264         final HashMap<String, Object> mapNodeValues = new HashMap<>();
265         // the VALUES are formated
266         for (int i = 0; i < FIELD_NAMES.size(); i++) {
267             Object value;
268             if (FLOAT.equals(FIELD_TYPES.get(i))) {
269                 value = Double.valueOf(st.nextToken());
270             } else if (INTEGER.equals(FIELD_TYPES.get(i))) {
271                 value = Integer.valueOf(st.nextToken());
272             } else if (DATE.equals(FIELD_TYPES.get(i))) {
273                 try {
274                     value = dateFormat.parse(st.nextToken());
275                 } catch (final ParseException e) {
276                     value = null;
277                 }
278             } else {
279                 value = st.nextToken();
280             }
281             mapNodeValues.put(FIELD_NAMES.get(i), value);
282         }
283 
284         // if we have not the path (the node names of parents)
285         if (!st.hasMoreTokens()) {
286             // we throw an exception, because we can't build the treemap
287             throw new IOException("the file didn't contains the hierarchy path");
288         }
289 
290         // create the nodes
291         createNodes(st, mapNodeValues);
292     }
293 }
294 /*
295  *                 ObjectLab is supporing JTreeMap
296  *
297  * Based in London, we are world leaders in the design and development
298  * of bespoke applications for the securities financing markets.
299  *
300  * <a href="http://www.objectlab.co.uk/open">Click here to learn more about us</a>
301  *           ___  _     _           _   _          _
302  *          / _ \| |__ (_) ___  ___| |_| |    __ _| |__
303  *         | | | | '_ \| |/ _ \/ __| __| |   / _` | '_ \
304  *         | |_| | |_) | |  __/ (__| |_| |__| (_| | |_) |
305  *          \___/|_.__// |\___|\___|\__|_____\__,_|_.__/
306  *                   |__/
307  *
308  *                     www.ObjectLab.co.uk
309  */