1
28 package demo.view.orgchart;
29
30 import org.w3c.dom.Document;
31 import org.w3c.dom.Element;
32 import org.w3c.dom.NamedNodeMap;
33 import org.w3c.dom.Node;
34 import org.w3c.dom.NodeList;
35 import org.xml.sax.InputSource;
36 import org.xml.sax.SAXException;
37
38 import javax.swing.Icon;
39 import javax.swing.ImageIcon;
40 import javax.swing.tree.DefaultMutableTreeNode;
41 import javax.swing.tree.DefaultTreeModel;
42 import javax.xml.parsers.DocumentBuilder;
43 import javax.xml.parsers.DocumentBuilderFactory;
44 import javax.xml.parsers.ParserConfigurationException;
45 import javax.xml.transform.OutputKeys;
46 import javax.xml.transform.Transformer;
47 import javax.xml.transform.TransformerConfigurationException;
48 import javax.xml.transform.TransformerException;
49 import javax.xml.transform.TransformerFactory;
50 import javax.xml.transform.dom.DOMSource;
51 import javax.xml.transform.stream.StreamResult;
52 import java.awt.Component;
53 import java.awt.Graphics;
54 import java.awt.Graphics2D;
55 import java.awt.Image;
56 import java.awt.RenderingHints;
57 import java.io.File;
58 import java.io.IOException;
59 import java.net.URL;
60 import java.util.Enumeration;
61 import java.util.HashMap;
62 import java.util.Iterator;
63 import java.util.Map;
64 import java.util.Set;
65
66
69 public class OrgChartTreeModel extends DefaultTreeModel {
70
71
74 public OrgChartTreeModel(final Employee root) {
75 super(root);
76 }
77
78
81 public static class Employee extends DefaultMutableTreeNode {
82 public String name;
83 public String email;
84 public String phone;
85 public String fax;
86 public String businessUnit;
87 public String position;
88 public String status;
89 public Icon icon;
90 public boolean assistant;
91 public String layout;
92 public boolean vacant;
93
94
97 public Employee() {
98 name = "";
99 email = "";
100 phone = "";
101 fax = "";
102 businessUnit = "";
103 position = "";
104 status = "";
105 layout = "";
106 }
107
108
112 public void vacate() {
113 vacant = true;
114 name = "";
115 status = "unavailable";
116 fax = "";
117 email = "";
118 phone = "";
119 icon = null;
120 }
121
122
127 public void adoptStructuralData( final Employee otherEmployee ) {
128 layout = otherEmployee.layout;
129 assistant = otherEmployee.assistant;
130 position = otherEmployee.position;
131 businessUnit = otherEmployee.businessUnit;
132 }
133 }
134
135
139 public static OrgChartTreeModel create(final InputSource input) {
140 final OrgChartReader reader = new OrgChartReader();
141 return reader.read(input);
142 }
143
144 static class OrgChartWriter {
145
150 public void write(File selectedFile, final Employee rootElement) {
151 final DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
152 final DocumentBuilder docBuilder;
153 try {
154 docBuilder = docFactory.newDocumentBuilder();
155 final Document doc = docBuilder.newDocument();
156 doc.appendChild(visit(rootElement,doc));
158
159 final TransformerFactory transformerFactory = TransformerFactory.newInstance();
161 final Transformer transformer = transformerFactory.newTransformer();
162 final DOMSource source = new DOMSource(doc);
163 if (!selectedFile.getName().endsWith(".xml")) {
165 selectedFile = new File(selectedFile.getPath() + ".xml");
166 }
167 final StreamResult result = new StreamResult(selectedFile);
168 transformer.setOutputProperty(OutputKeys.INDENT, "yes");
170 transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
171 transformer.transform(source, result);
172 } catch (ParserConfigurationException e) {
173 e.printStackTrace();
174 } catch (TransformerConfigurationException e) {
175 e.printStackTrace();
176 } catch (TransformerException e) {
177 e.printStackTrace();
178 }
179 }
180
181
187 private Element visit(final Employee rootEmployee, final Document doc) {
188 final Element element = doc.createElement("employee");
189 element.setAttribute("name",rootEmployee.name);
190 element.setAttribute("email",rootEmployee.email);
191 element.setAttribute("phone",rootEmployee.phone);
192 element.setAttribute("fax",rootEmployee.fax);
193 element.setAttribute("businessUnit",rootEmployee.businessUnit);
194 element.setAttribute("position",rootEmployee.position);
195 element.setAttribute("status",rootEmployee.status);
196 element.setAttribute("assistant",Boolean.toString(rootEmployee.assistant));
197 element.setAttribute("vacant",Boolean.toString(rootEmployee.vacant));
198 element.setAttribute("layout",rootEmployee.layout);
199 if (rootEmployee.icon != null) {
200 element.setAttribute("icon",getIconName(rootEmployee.icon));
201 }
202 for(final Enumeration children = rootEmployee.children();children.hasMoreElements();) {
203 final Employee child = (Employee) children.nextElement();
204 element.appendChild(visit(child, doc));
205 }
206 return element;
207 }
208
209 private String getIconName(final Icon element) {
210 final Set set = OrgChartReader.userIcons.keySet();
211 for(final Iterator iterator = set.iterator();iterator.hasNext();) {
212 final String iconName = (String) iterator.next();
213 if (OrgChartReader.userIcons.get(iconName) == element) {
214 return iconName;
215 }
216 }
217 return "";
219 }
220 }
221
222
225 static class OrgChartReader {
226
227 static Map userIcons;
228 static {
229 userIcons = new HashMap();
230 for(int type = 0; type <= 1; type++) {
231 final String gender = type == 0 ? "male" : "female";
232 for(int user = 1; user <= 3; user++) {
233 final String key = "usericon_" + gender + user;
234 userIcons.put(key, new FixedSizeImageIcon(
235 getResource("resource/" + key + "_256.png"), 56, 64));
236 }
237 }
238 }
239
240 private static URL getResource( final String name ) {
241 return demo.view.DemoBase.getSharedResource(name);
242 }
243
244 public OrgChartTreeModel read(final InputSource input) {
245 final Document doc;
246
247 try {
248 doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(input);
249 final Employee treeRoot = visit(doc);
250 return new OrgChartTreeModel(treeRoot);
251 } catch (SAXException e) {
252 e.printStackTrace();
253 } catch (IOException e) {
254 e.printStackTrace();
255 } catch (ParserConfigurationException e) {
256 e.printStackTrace();
257 }
258 return null;
259 }
260
261 public Employee visit(final Node node)
262 {
263 final String nodeName = node.getNodeName();
264 Employee employee = null;
265 if("employee".equals(nodeName)) {
266 employee = new Employee();
267
268 final NamedNodeMap attributes = node.getAttributes();
269 Node attr = attributes.getNamedItem("name");
270 if(attr != null) {
271 employee.name = attr.getNodeValue();
272 }
273 attr = attributes.getNamedItem("layout");
274 if(attr != null) {
275 employee.layout = attr.getNodeValue();
276 }
277 attr = attributes.getNamedItem("email");
278 if(attr != null) {
279 employee.email = attr.getNodeValue();
280 }
281 attr = attributes.getNamedItem("phone");
282 if(attr != null) {
283 employee.phone = attr.getNodeValue();
284 }
285 attr = attributes.getNamedItem("position");
286 if(attr != null) {
287 employee.position = attr.getNodeValue();
288 }
289 attr = attributes.getNamedItem("fax");
290 if(attr != null) {
291 employee.fax = attr.getNodeValue();
292 }
293 attr = attributes.getNamedItem("businessUnit");
294 if(attr != null) {
295 employee.businessUnit = attr.getNodeValue();
296 }
297 attr = attributes.getNamedItem("status");
298 if(attr != null) {
299 employee.status = attr.getNodeValue();
300 }
301 attr = attributes.getNamedItem("icon");
302 if(attr != null) {
303 final String iconName = attr.getNodeValue();
304 employee.icon = (Icon) userIcons.get(iconName);
305 }
306 attr = attributes.getNamedItem("assistant");
307 if(attr != null) {
308 employee.assistant = "true".equalsIgnoreCase(attr.getNodeValue());
309 }
310 attr = attributes.getNamedItem("vacant");
311 employee.vacant = (attr != null) && "true".equalsIgnoreCase(attr.getNodeValue());
312 }
313 final NodeList nl = node.getChildNodes();
314 for(int i=0, cnt=nl.getLength(); i<cnt; i++)
315 {
316 final Node n = nl.item(i);
317 final Employee childNode = visit(n);
318 if(childNode != null && employee != null) {
319 employee.add(childNode);
320 }
321 if(childNode != null && employee == null) {
322 return childNode;
323 }
324 }
325 return employee;
326 }
327 }
328
329
333 static class FixedSizeImageIcon extends ImageIcon {
334
335 final int width;
336 final int height;
337
338 public FixedSizeImageIcon(final URL imageURL, final int width, final int height) {
339 super(imageURL);
340 this.width = width;
341 this.height = height;
342 }
343
344 public int getIconHeight() {
345 return height;
346 }
347
348 public int getIconWidth() {
349 return width;
350 }
351
352 public void paintIcon(final Component c, final Graphics gfx, final int x, final int y) {
353 final Image image = getImage();
354 final Graphics2D g2d = (Graphics2D) gfx.create();
355 g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
356 g2d.drawImage(image, x, y, getIconWidth(), getIconHeight(), c);
357 g2d.dispose();
358 }
359 }
360 }
361