1   
28  package demo.view.mindmap;
29  
30  import org.w3c.dom.NamedNodeMap;
31  import org.w3c.dom.Node;
32  import org.xml.sax.SAXException;
33  import y.base.EdgeCursor;
34  import y.io.IOHandler;
35  import y.view.Graph2D;
36  import y.view.LineType;
37  import y.view.NodeRealizer;
38  
39  import java.awt.Color;
40  import java.io.BufferedWriter;
41  import java.io.IOException;
42  import java.io.InputStream;
43  import java.io.OutputStream;
44  import java.io.OutputStreamWriter;
45  import javax.xml.parsers.DocumentBuilderFactory;
46  import javax.xml.parsers.ParserConfigurationException;
47  
48  
53  public class FreeMindIOHandler extends IOHandler {
54    private static final String ENCODING = "UTF-8" ;
55    private static final String ATTRIBUTE_COLOR = "COLOR";
56    private static final String ATTRIBUTE_POSITION = "POSITION";
57    private static final String ATTRIBUTE_WIDTH = "WIDTH";
58    private static final String ATTRIBUTE_TEXT = "TEXT";
59    private static final String TAG_EDGE = "edge";
60    private static final String TAG_NODE = "node";
61  
62    
65    public void write( final Graph2D graph, final OutputStream out ) throws IOException {
66      final BufferedWriter bufferedWriter = new BufferedWriter(
67              new OutputStreamWriter(new OutputStreamGuardian(out), ENCODING));
68      try {
69        bufferedWriter.write("<map version=\"0.9.0\">");
70        bufferedWriter.newLine();
71        writeNode(graph, ViewModel.instance.getRoot(), bufferedWriter);
72        bufferedWriter.write("</map>");
73        bufferedWriter.flush();
74      } finally {
75        bufferedWriter.close();
76      }
77    }
78  
79    
86    private static void writeNode(
87            final Graph2D graph, final y.base.Node node, final BufferedWriter writer
88    ) throws IOException {
89          
92      final NodeRealizer nodeRealizer = graph.getRealizer(node);
93      writer.write("<" + TAG_NODE + " " + ATTRIBUTE_TEXT + "=\"" + nodeRealizer.getLabelText() + "\"");
94  
95      final boolean isSecondLevel = node.inDegree() > 0 && node.firstInEdge().source().inDegree() == 0;
96      final boolean isLeftSide = ViewModel.instance.isLeft(node);
97          if (isSecondLevel && isLeftSide) {
99        writer.write(" " + ATTRIBUTE_POSITION + "=\"left\" ");
100     }
101     writer.write(" >");
102     writer.newLine();
103     writeEdge(nodeRealizer, writer);
104 
105     for (EdgeCursor ec = MindMapUtil.outEdges(node).edges(); ec.ok(); ec.next()) {
106       writeNode(graph, ec.edge().target(), writer);
107     }
108 
109     writer.write("</" + TAG_NODE + ">");
110     writer.newLine();
111   }
112 
113   private static void writeEdge(
114           final NodeRealizer target, final BufferedWriter writer
115   ) throws IOException {
116     writer.write("<" + TAG_EDGE + " ");
117     String value = Integer.toHexString(target.getFillColor().getRGB());
118     writer.write(ATTRIBUTE_COLOR + "=\"#" + value.substring(2, 8) + "\" ");
119     writer.write(ATTRIBUTE_WIDTH + "=\"" + ((int) target.getLineType().getLineWidth()) + "\"");
120     writer.write("/>");
121     writer.newLine();
122   }
123 
124 
125   
128   public void read( final Graph2D graph, final InputStream in ) throws IOException {
129     try {
130       readNode(
131               DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(in),
132               graph,
133               null);
134     } catch (SAXException e) {
135       final IOException ioe = new IOException();
136       ioe.initCause(ioe);
137       throw ioe;
138     } catch (ParserConfigurationException e) {
139       final IOException ioe = new IOException();
140       ioe.initCause(ioe);
141       throw ioe;
142     }
143   }
144 
145 
146   
152   private static void readNode(final Node node, final Graph2D graph, final y.base.Node parent) {
153     final String nodeName = node.getNodeName();
154     y.base.Node n = parent;
155     if (nodeName.equals(TAG_NODE)) {
156       final NamedNodeMap attributes = node.getAttributes();
157       Node attr = attributes.getNamedItem(ATTRIBUTE_TEXT);
158       String name = "";
159       boolean side = false;
160       if (attr != null) {
161         name = attr.getNodeValue();
162       }
163       attr = attributes.getNamedItem(ATTRIBUTE_POSITION);
164       if (attr != null) {
165         side = attr.getNodeValue().equalsIgnoreCase("left");
166       }
167       if (parent == null) {
168                                 n = graph.createNode(0,0,name);
172       } else {
173                 n = MindMapUtil.addNode(graph, parent, name, side);
175       }
176       if (parent != null && attr == null) {
177         MindMapUtil.updateVisuals(graph, n, ViewModel.instance.isLeft(parent));
178       } else {
179         MindMapUtil.updateVisuals(graph, n, side);
180       }
181     } else if (nodeName.equals(TAG_EDGE)) {
182       final NamedNodeMap attributes = node.getAttributes();
183       Node attr = attributes.getNamedItem(ATTRIBUTE_COLOR);
184                   final NodeRealizer nodeRealizer = graph.getRealizer(parent);
187       if (attr != null) {
188         nodeRealizer.setFillColor(Color.decode(attr.getNodeValue()));
189       }
190       attr = attributes.getNamedItem(ATTRIBUTE_WIDTH);
191       if (attr != null) {
192         int lineWidth = Integer.parseInt(attr.getNodeValue());
193         if (lineWidth == 2) {
194           nodeRealizer.setLineType(LineType.LINE_3);
195         } else {
196           nodeRealizer.setLineType(LineType.LINE_6);
197         }
198       }
199     }
200 
201         for (Node child = node.getFirstChild(); child != null; child = child.getNextSibling()) {
203       readNode(child, graph, n);
204     }
205   }
206 
207 
208   
212   public String getFileFormatString() {
213     return "FreeMind file";
214   }
215 
216   
220   public String getFileNameExtension() {
221     return "mm";
222   }
223 
224 
225   
229   private static final class OutputStreamGuardian extends OutputStream {
230     private final OutputStream os;
231 
232     OutputStreamGuardian( final OutputStream os ) {
233       this.os = os;
234     }
235 
236     public void close() throws IOException {
237           }
239 
240     public void flush() throws IOException {
241       os.flush();
242     }
243 
244     public void write( final int b ) throws IOException {
245       os.write(b);
246     }
247 
248     public void write( final byte[] b ) throws IOException {
249       os.write(b);
250     }
251 
252     public void write( final byte[] b, final int off, final int len ) throws IOException {
253       os.write(b, off, len);
254     }
255   }
256 }
257