mxVsdxExporter.java 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  1. package com.mxgraph.io.vsdx.export;
  2. import java.io.File;
  3. import java.io.IOException;
  4. import java.io.InputStream;
  5. import java.io.OutputStream;
  6. import java.io.OutputStreamWriter;
  7. import java.io.UnsupportedEncodingException;
  8. import java.net.URLDecoder;
  9. import java.util.ArrayList;
  10. import java.util.LinkedHashMap;
  11. import java.util.Map.Entry;
  12. import java.util.zip.ZipEntry;
  13. import java.util.zip.ZipOutputStream;
  14. import javax.xml.parsers.DocumentBuilder;
  15. import javax.xml.parsers.DocumentBuilderFactory;
  16. import javax.xml.transform.Source;
  17. import javax.xml.transform.Transformer;
  18. import javax.xml.transform.TransformerConfigurationException;
  19. import javax.xml.transform.TransformerException;
  20. import javax.xml.transform.TransformerFactory;
  21. import javax.xml.transform.TransformerFactoryConfigurationError;
  22. import javax.xml.transform.dom.DOMSource;
  23. import javax.xml.transform.stream.StreamResult;
  24. import org.w3c.dom.Document;
  25. import org.w3c.dom.Element;
  26. import com.mxgraph.io.mxCodec;
  27. import com.mxgraph.io.vsdx.mxVsdxUtils;
  28. import com.mxgraph.model.mxCell;
  29. import com.mxgraph.model.mxGeometry;
  30. import com.mxgraph.model.mxGraphModel;
  31. import com.mxgraph.online.Utils;
  32. import com.mxgraph.online.mxBase64;
  33. import com.mxgraph.util.mxXmlUtils;
  34. import com.mxgraph.view.mxGraph;
  35. import com.mxgraph.view.mxGraphHeadless;
  36. public class mxVsdxExporter
  37. {
  38. private static final String PAGES_TYPE = "http://schemas.microsoft.com/visio/2010/relationships/page";
  39. private static final String RELS_XMLNS = "http://schemas.openxmlformats.org/package/2006/relationships";
  40. private static final String XML_SPACE = "preserve";
  41. private static final String XMLNS_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
  42. private static final String XMLNS = "http://schemas.microsoft.com/office/visio/2012/main";
  43. private static final String VISIO_PAGES = "visio/pages/";
  44. private static final String PREFEX = "com/mxgraph/io/vsdx/resources/export/";
  45. private static final String VSDX_ENC = "ISO-8859-1";
  46. private static final String OVERRIDE = "Override";
  47. private static final String PART_NAME = "PartName";
  48. private static final String DOC_PROPS_CUSTOM_XML = "docProps/custom.xml";
  49. private static final String DOC_PROPS_CORE_XML = "docProps/core.xml";
  50. private static final String DOC_PROPS_APP_XML = "docProps/app.xml";
  51. private static final String _RELS_RELS_FILE = "_rels/.rels";
  52. private static final String CONTENT_TYPES_XML = "[Content_Types].xml";
  53. private static final String VISIO_MASTERS_RELS_MASTERS_XML_RELS = "visio/masters/_rels/masters.xml.rels";
  54. private static final String VISIO_MASTERS_MASTERS_XML = "visio/masters/masters.xml";
  55. private static final String VISIO_RELS_DOCUMENT_XML_RELS = "visio/_rels/document.xml.rels";
  56. private static final String VISIO_WINDOWS_XML = "visio/windows.xml";
  57. private static final String VISIO_DOCUMENT_XML = "visio/document.xml";
  58. private static final String VISIO_PAGES_RELS = "visio/pages/_rels/";
  59. private static byte[] documentFile;
  60. private static byte[] windowsFile;
  61. private static byte[] visioRelsFile;
  62. private static byte[] mastersFile;
  63. private static byte[] mastersRelsFile;
  64. private static byte[] contentTypeFile;
  65. private static byte[] _relsFile;
  66. private static byte[] appFile;
  67. private static byte[] coreFile;
  68. private static byte[] customFile;
  69. private static byte[] pageRelFile;
  70. //Load the constant vsdx files statically so it can be used faster for all export operations
  71. static
  72. {
  73. try
  74. {
  75. ClassLoader classLoader = mxVsdxExporter.class.getClassLoader();
  76. String file = PREFEX + VISIO_DOCUMENT_XML;
  77. int size = (int) new File(classLoader.getResource(file).getFile()).length();
  78. InputStream in = classLoader.getResourceAsStream(file);
  79. documentFile = new byte[size];
  80. in.read(documentFile);
  81. file = PREFEX + VISIO_WINDOWS_XML;
  82. size = (int) new File(classLoader.getResource(file).getFile()).length();
  83. in = classLoader.getResourceAsStream(file);
  84. windowsFile = new byte[size];
  85. in.read(windowsFile);
  86. file = PREFEX + VISIO_RELS_DOCUMENT_XML_RELS;
  87. size = (int) new File(classLoader.getResource(file).getFile()).length();
  88. in = classLoader.getResourceAsStream(file);
  89. visioRelsFile = new byte[size];
  90. in.read(visioRelsFile);
  91. file = PREFEX + VISIO_MASTERS_MASTERS_XML;
  92. size = (int) new File(classLoader.getResource(file).getFile()).length();
  93. in = classLoader.getResourceAsStream(file);
  94. mastersFile = new byte[size];
  95. in.read(mastersFile);
  96. file = PREFEX + VISIO_MASTERS_RELS_MASTERS_XML_RELS;
  97. size = (int) new File(classLoader.getResource(file).getFile()).length();
  98. in = classLoader.getResourceAsStream(file);
  99. mastersRelsFile = new byte[size];
  100. in.read(mastersRelsFile);
  101. file = PREFEX + CONTENT_TYPES_XML;
  102. size = (int) new File(URLDecoder.decode(classLoader.getResource(file).getFile(), "UTF8")).length();
  103. in = classLoader.getResourceAsStream(file);
  104. contentTypeFile = new byte[size];
  105. in.read(contentTypeFile);
  106. file = PREFEX + _RELS_RELS_FILE;
  107. size = (int) new File(classLoader.getResource(file).getFile()).length();
  108. in = classLoader.getResourceAsStream(file);
  109. _relsFile = new byte[size];
  110. in.read(_relsFile);
  111. file = PREFEX + DOC_PROPS_APP_XML;
  112. size = (int) new File(classLoader.getResource(file).getFile()).length();
  113. in = classLoader.getResourceAsStream(file);
  114. appFile = new byte[size];
  115. in.read(appFile);
  116. file = PREFEX + DOC_PROPS_CORE_XML;
  117. size = (int) new File(classLoader.getResource(file).getFile()).length();
  118. in = classLoader.getResourceAsStream(file);
  119. coreFile = new byte[size];
  120. in.read(coreFile);
  121. file = PREFEX + DOC_PROPS_CUSTOM_XML;
  122. size = (int) new File(classLoader.getResource(file).getFile()).length();
  123. in = classLoader.getResourceAsStream(file);
  124. customFile = new byte[size];
  125. in.read(customFile);
  126. file = PREFEX + VISIO_PAGES_RELS + "page1.xml.rels";
  127. size = (int) new File(classLoader.getResource(file).getFile()).length();
  128. in = classLoader.getResourceAsStream(file);
  129. pageRelFile = new byte[size];
  130. in.read(pageRelFile);
  131. }
  132. catch (Exception e) //We shouldn't get any exception as long as files exist.
  133. {
  134. e.printStackTrace();
  135. }
  136. }
  137. /**
  138. * Fill the required files in vsdx format which are constants in our exporter
  139. * @param zip ZipOutputStream of vsdx file
  140. * @param pageCount The number of pages in the mxFile
  141. * @throws IOException
  142. */
  143. private void createVsdxSkeleton(ZipOutputStream zip, int pageCount) throws IOException
  144. {
  145. zip.putNextEntry(new ZipEntry(VISIO_PAGES_RELS + "page1.xml.rels"));
  146. zip.write(pageRelFile);
  147. if (pageCount == 1)
  148. {
  149. zip.putNextEntry(new ZipEntry(CONTENT_TYPES_XML));
  150. zip.write(contentTypeFile);
  151. }
  152. else
  153. {
  154. //Add the remaining pages
  155. Document doc = mxXmlUtils.parseXml(new String(contentTypeFile));
  156. Element root = doc.getDocumentElement();
  157. ArrayList<Element> overrides = mxVsdxUtils.getDirectChildNamedElements(root, OVERRIDE);
  158. Element page1 = null;
  159. for (Element override : overrides)
  160. {
  161. if ("/visio/pages/page1.xml".equals(override.getAttribute(PART_NAME)))
  162. {
  163. page1 = override;
  164. }
  165. }
  166. for (int i = 2; i <= pageCount; i++)
  167. {
  168. zip.putNextEntry(new ZipEntry(VISIO_PAGES_RELS + "page" + i + ".xml.rels"));
  169. zip.write(pageRelFile);
  170. Element newPage = (Element) page1.cloneNode(false);
  171. newPage.setAttribute(PART_NAME, "/visio/pages/page" + i + ".xml");
  172. root.appendChild(newPage);
  173. }
  174. zip.putNextEntry(new ZipEntry(CONTENT_TYPES_XML));
  175. zip.write(("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" + mxXmlUtils.getXml(doc)).getBytes(VSDX_ENC));
  176. }
  177. zip.putNextEntry(new ZipEntry(_RELS_RELS_FILE));
  178. zip.write(_relsFile);
  179. zip.putNextEntry(new ZipEntry(DOC_PROPS_APP_XML));
  180. zip.write(appFile);
  181. zip.putNextEntry(new ZipEntry(DOC_PROPS_CORE_XML));
  182. zip.write(coreFile);
  183. zip.putNextEntry(new ZipEntry(DOC_PROPS_CUSTOM_XML));
  184. zip.write(customFile);
  185. zip.putNextEntry(new ZipEntry(VISIO_DOCUMENT_XML));
  186. zip.write(documentFile);
  187. zip.putNextEntry(new ZipEntry(VISIO_WINDOWS_XML));
  188. zip.write(windowsFile);
  189. zip.putNextEntry(new ZipEntry(VISIO_RELS_DOCUMENT_XML_RELS));
  190. zip.write(visioRelsFile);
  191. zip.putNextEntry(new ZipEntry(VISIO_MASTERS_MASTERS_XML));
  192. zip.write(mastersFile);
  193. zip.putNextEntry(new ZipEntry(VISIO_MASTERS_RELS_MASTERS_XML_RELS));
  194. zip.write(mastersRelsFile);
  195. zip.flush();
  196. }
  197. /**
  198. *
  199. * Convert mxFile into a vdsx file
  200. * @param mxFileXML mxFile xml string
  201. * @param out output stream where vsdx file is written to
  202. * @return true if successful, false otherwise (stream should be discarded and closed)
  203. */
  204. public boolean exportMxFile(String mxFileXML, OutputStream out)
  205. {
  206. try
  207. {
  208. ZipOutputStream zip = new ZipOutputStream(out);
  209. DocumentBuilder docBuilder = mxXmlUtils.getDocumentBuilder();
  210. LinkedHashMap<String, Document> pages = new LinkedHashMap<>();
  211. LinkedHashMap<String, ModelExtAttrib> modelsAttr = new LinkedHashMap<>();
  212. Document doc = mxXmlUtils.parseXml(mxFileXML);
  213. ArrayList<Element> diagrams = mxVsdxUtils.getDirectChildNamedElements(doc.getDocumentElement(), "diagram");
  214. mxCodec codec = new mxCodec();
  215. for (Element diagram : diagrams)
  216. {
  217. String diagramName = diagram.getAttribute("name");
  218. String diagramB64 = diagram.getFirstChild().getTextContent();
  219. byte[] deflated = mxBase64.decodeFast(diagramB64);
  220. String uriEncoded = Utils.inflate(deflated);
  221. String xml = URLDecoder.decode(uriEncoded, Utils.CHARSET_FOR_URL_ENCODING);
  222. Element modelNode = mxXmlUtils.parseXml(xml).getDocumentElement();
  223. ModelExtAttrib modelAttrib = getModelExtAttributes(modelNode);
  224. mxGraphModel model = (mxGraphModel) codec.decode(modelNode);
  225. pages.put(diagramName, convertMxModel2Page(docBuilder, model, diagramName, modelAttrib));
  226. modelsAttr.put(diagramName, modelAttrib);
  227. }
  228. createVsdxSkeleton(zip, pages.size());
  229. addPagesXML(docBuilder, zip, pages, modelsAttr);
  230. zip.close();
  231. return true;
  232. }
  233. catch(Exception e)
  234. {
  235. e.printStackTrace();
  236. return false;
  237. }
  238. }
  239. private Double getDouble(String val)
  240. {
  241. try
  242. {
  243. if (val != null && !val.isEmpty())
  244. {
  245. return Double.valueOf(val);
  246. }
  247. }
  248. catch (Exception e)
  249. {
  250. //fallback to null
  251. }
  252. return null;
  253. }
  254. private ModelExtAttrib getModelExtAttributes(Element modelNode)
  255. {
  256. ModelExtAttrib attr = new ModelExtAttrib();
  257. try
  258. {
  259. String grid = modelNode.getAttribute("grid");
  260. if (!grid.isEmpty()) attr.setGridEnabled("1".equals(grid));
  261. Double gridSize = getDouble(modelNode.getAttribute("gridSize"));
  262. if (gridSize != null) attr.setGridSize(gridSize);
  263. String guides = modelNode.getAttribute("guides");
  264. if (!guides.isEmpty()) attr.setGuidesEnabled("1".equals(guides));
  265. String page = modelNode.getAttribute("page");
  266. if (!page.isEmpty()) attr.setPageVisible("1".equals(page));
  267. Double pageScale = getDouble(modelNode.getAttribute("pageScale"));
  268. if (pageScale != null) attr.setPageScale(pageScale);
  269. Double pageWidth = getDouble(modelNode.getAttribute("pageWidth"));
  270. if (pageWidth != null) attr.setPageWidth(pageWidth);
  271. Double pageHeight = getDouble(modelNode.getAttribute("pageHeight"));
  272. if (pageHeight != null) attr.setPageHeight(pageHeight);
  273. String background = modelNode.getAttribute("background");
  274. if (!background.isEmpty()) attr.setBackgroundClr(background);
  275. String math = modelNode.getAttribute("math");
  276. if (!math.isEmpty()) attr.setMathEnabled("1".equals(math));
  277. String shadow = modelNode.getAttribute("shadow");
  278. if (!shadow.isEmpty()) attr.setShadowVisible("1".equals(shadow));
  279. //these most probably not needed in vsdx
  280. String tooltips = modelNode.getAttribute("tooltips");
  281. if (!tooltips.isEmpty()) attr.setTooltips("1".equals(tooltips));
  282. String connect = modelNode.getAttribute("connect");
  283. if (!connect.isEmpty()) attr.setConnect("1".equals(connect));
  284. String arrows = modelNode.getAttribute("arrows");
  285. if (!arrows.isEmpty()) attr.setArrows("1".equals(arrows));
  286. String fold = modelNode.getAttribute("fold");
  287. if (!fold.isEmpty()) attr.setFoldingEnabled("1".equals(fold));
  288. }
  289. catch(Exception e)
  290. {
  291. //nothing, fallback to defaults
  292. }
  293. return attr;
  294. }
  295. private void addPagesXML(DocumentBuilder docBuilder, ZipOutputStream zip, LinkedHashMap<String, Document> pages, LinkedHashMap<String, ModelExtAttrib> modelsAttr)
  296. throws TransformerFactoryConfigurationError, TransformerException, IOException
  297. {
  298. Document pagesXmlDoc = docBuilder.newDocument();
  299. Document pagesRelsXmlDoc = docBuilder.newDocument();
  300. Element pagesRoot = pagesXmlDoc.createElement("Pages");
  301. pagesRoot.setAttribute("xmlns", XMLNS);
  302. pagesRoot.setAttribute("xmlns:r", XMLNS_R);
  303. pagesRoot.setAttribute("xml:space", XML_SPACE);
  304. Element pagesRelsRoot = pagesRelsXmlDoc.createElement("Relationships");
  305. pagesRelsRoot.setAttribute("xmlns", RELS_XMLNS);
  306. int i = 1;
  307. for (Entry<String, Document> pair : pages.entrySet())
  308. {
  309. String name = pair.getKey();
  310. String pageName = "page" + i + ".xml";
  311. Element pageE = pagesXmlDoc.createElement("Page");
  312. pageE.setAttribute("ID", String.valueOf(i-1));
  313. pageE.setAttribute("NameU", name);
  314. pageE.setAttribute("Name", name);
  315. Element pageSheet = pagesXmlDoc.createElement("PageSheet");
  316. ModelExtAttrib modelAttr = modelsAttr.get(name);
  317. pageSheet.appendChild(createCellElemScaled("PageWidth", modelAttr.getPageWidth(), pagesXmlDoc));
  318. pageSheet.appendChild(createCellElemScaled("PageHeight", modelAttr.getPageHeight(), pagesXmlDoc));
  319. pageSheet.appendChild(createCellElem("PageScale", modelAttr.getPageScale(), pagesXmlDoc));
  320. pageSheet.appendChild(createCellElem("DrawingScale", 1, pagesXmlDoc));
  321. Element relE = pagesXmlDoc.createElement("Rel");
  322. relE.setAttribute("r:id", "rId" + i);
  323. pageE.appendChild(pageSheet);
  324. pageE.appendChild(relE);
  325. pagesRoot.appendChild(pageE);
  326. Element relationship = pagesRelsXmlDoc.createElement("Relationship");
  327. relationship.setAttribute("Id", "rId" + i);
  328. relationship.setAttribute("Type", PAGES_TYPE);
  329. relationship.setAttribute("Target", pageName);
  330. pagesRelsRoot.appendChild(relationship);
  331. //Note:Each page rels is created with the skeleton as they are constants
  332. //write the page docs
  333. Document xmlDoc = pair.getValue();
  334. writeXmlDoc2Zip(zip, VISIO_PAGES + pageName, xmlDoc);
  335. i++;
  336. }
  337. pagesXmlDoc.appendChild(pagesRoot);
  338. pagesRelsXmlDoc.appendChild(pagesRelsRoot);
  339. writeXmlDoc2Zip(zip, VISIO_PAGES + "pages.xml", pagesXmlDoc);
  340. writeXmlDoc2Zip(zip, VISIO_PAGES + "_rels/pages.xml.rels", pagesRelsXmlDoc);
  341. }
  342. private void writeXmlDoc2Zip(ZipOutputStream zip, String name, Document xmlDoc)
  343. throws IOException, UnsupportedEncodingException, TransformerConfigurationException,
  344. TransformerFactoryConfigurationError, TransformerException {
  345. zip.putNextEntry(new ZipEntry(name));
  346. Source source = new DOMSource(xmlDoc);
  347. StreamResult result = new StreamResult(new OutputStreamWriter(zip, VSDX_ENC));
  348. Transformer xformer = TransformerFactory.newInstance().newTransformer();
  349. xformer.transform(source, result);
  350. }
  351. private Element createCellElemScaled(String name, double val, Document xmlDoc)
  352. {
  353. return createCellElem(name, val / mxVsdxUtils.conversionFactor, xmlDoc);
  354. }
  355. private Element createCellElem(String name, double val, Document xmlDoc)
  356. {
  357. Element cell = xmlDoc.createElement("Cell");
  358. cell.setAttribute("N", name);
  359. cell.setAttribute("V", String.valueOf(val));
  360. return cell;
  361. }
  362. protected Element createRow(String type, String index, double x, double y, Document xmlDoc)
  363. {
  364. Element row = xmlDoc.createElement("Row");
  365. row.setAttribute("T", type);
  366. row.setAttribute("IX", index);
  367. row.appendChild(createCellElem("X", x, xmlDoc));
  368. row.appendChild(createCellElem("Y", y, xmlDoc));
  369. return row;
  370. }
  371. private Element createGeoElem(mxCell cell, Document xmlDoc)
  372. {
  373. Element geoSec = xmlDoc.createElement("Section");
  374. geoSec.setAttribute("N", "Geometry");
  375. geoSec.setAttribute("IX", "0");
  376. //now just create a rectangle
  377. geoSec.appendChild(createRow("MoveTo", "1", 0, 0, xmlDoc));
  378. geoSec.appendChild(createRow("RelLineTo", "2", 1, 0, xmlDoc));
  379. geoSec.appendChild(createRow("RelLineTo", "3", 1, 1, xmlDoc));
  380. geoSec.appendChild(createRow("RelLineTo", "4", 0, 1, xmlDoc));
  381. geoSec.appendChild(createRow("RelLineTo", "5", 0, 0, xmlDoc));
  382. return geoSec;
  383. }
  384. private Element convertMxCell2Shape(mxCell cell, mxGraphModel model, Document xmlDoc, double parentHeight)
  385. {
  386. mxGeometry geo = model.getGeometry(cell);
  387. if (geo != null)
  388. {
  389. Element shape = xmlDoc.createElement("Shape");
  390. shape.setAttribute("ID", cell.getId());
  391. shape.setAttribute("NameU", "NotYet");
  392. shape.setAttribute("Type", "Shape");
  393. double hw = geo.getWidth()/2, hh = geo.getHeight()/2;
  394. shape.appendChild(createCellElemScaled("PinX", geo.getX() + hw, xmlDoc));
  395. shape.appendChild(createCellElemScaled("PinY", parentHeight - geo.getY() - hh, xmlDoc));
  396. shape.appendChild(createCellElemScaled("Width", geo.getWidth(), xmlDoc));
  397. shape.appendChild(createCellElemScaled("Height", geo.getHeight(), xmlDoc));
  398. shape.appendChild(createCellElemScaled("LocPinX", hw, xmlDoc));
  399. shape.appendChild(createCellElemScaled("LocPinY", hh, xmlDoc));
  400. shape.appendChild(createGeoElem(cell, xmlDoc));
  401. return shape;
  402. }
  403. return null;
  404. }
  405. private Document convertMxModel2Page(DocumentBuilder docBuilder, mxGraphModel model, String name, ModelExtAttrib modelAttrib)
  406. {
  407. Document xmlDoc = docBuilder.newDocument();
  408. Element root = xmlDoc.createElement("PageContents");
  409. root.setAttribute("xmlns", XMLNS);
  410. root.setAttribute("xmlns:r", XMLNS_R);
  411. root.setAttribute("xml:space", XML_SPACE);
  412. Element shapes = xmlDoc.createElement("Shapes");
  413. root.appendChild(shapes);
  414. mxGraph graph = new mxGraphHeadless(model);
  415. Object defParent = graph.getDefaultParent();
  416. for (Object c : model.getCells().values())
  417. {
  418. //top-most cells
  419. if (model.getParent(c) == defParent)
  420. {
  421. Element shape = convertMxCell2Shape((mxCell) c, model, xmlDoc, modelAttrib.getPageHeight());
  422. if (shape != null)
  423. shapes.appendChild(shape);
  424. }
  425. }
  426. xmlDoc.appendChild(root);
  427. return xmlDoc;
  428. }
  429. // public static void main(String[] args)
  430. // {
  431. // try {
  432. // String mxFileXML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><mxfile><diagram name=\"Page-1\">7ZZbk5owFMc/DTPtixPC/VG87G697Ky43t4CREgFwkAE3E/fIFGhzs5uO+1Lpzij8sv/5JCT849KyiCuHjKUhjPq40iCwK8kZShBKMtA5x81OTVEM60GBBnxhegGHPKGBQSCHomP846QURoxknahR5MEe6zDUJbRsivb06ibNUUBvgOOh6J7uiY+C6/rAreBR0yCUKQ2NTHgIu8QZPSYiHwSVPbnqxmO0XWuBuQh8mnZoPMUykgCfan+DiRlkFHKOugyEFcDHNU1v5SzyT/+nPi6vAwn7DfioXh4droULMiQT/hkAxrR7IwURTFN1ZUUe0+iqMVVzdV1lfMi96unIYcyv4mQiyP7Wr2LPqEJz2DzMqV1ppzhxCPRl2I1tod0Fowey/miohPzZbPmTx/Pl6vTOtqGO2Tt8Xg6cR/SiRcXnvL81lfdRRrow+EgBIN0ZPK+cRf549bRBugtf3aG2/jbqPy+nMtamRqmBystIX1jpmTqCmhbPJKg7a/mxgId1xqkQXZUx0cHLYnMVnHKk2+exjO222/lV6Iux/bhwANesgV/n9q41KitR88HDS4T6lS76fYVeX6xKGweaShF/4XrNpa10wyiFRs9n0RjL4cJ/lqvnmX0gFsl5IZyFViPpMgjSTDF+3obQQ9A0Llk8yayKWM0/lC2EF39jipkcSS2TAQsafq+/LyZuG4b3kh2GRKGHR5W72XJj47r4i4uk3sW0Di9b1DRswXOGK5a6L5hb237gGmMWXbi95cQaDTznC4HjtzTrNYl0pQ312vAbFjYMrxhGj1VnDfirAmuyd41Ut2ijZc+ZTPlQ5sJe/zkMAMgXzXaDoP/HfZrDrPOr3/RYaCnK3/TYYYs92DHYzqwuh67s1jtQv3eZFDXe8YfMtmZt35Oha71/+XMfwA=</diagram><diagram name=\"Page-2\">nZTbkqIwEIafhqrdGwuIEbwUlJldD1Mjjqe7CAGyBkKFCDhPv0HigbWmdmtzofD132nS6W4NuGn9wlGezFmIqWbqYa2BsWaahqEP5F9Dzi2B9rAFMSehEt2BTz6xgrqiJxLioiMUjFFB8i4MWJbhQHQY4pxVXVnEaDdqjmL8BPwA0We6IaFIbufS74ZXTOJEhbahMhxQcIw5O2UqnmaC6LJac4pue7WgSFDIqhZdtgATTR9pzbOuAZczJjroakhrF9Mm59d0tvG9fxPfjsdxJv7D31QfL87XhMUchURu5jLKuEQZy6TFiQilVyRTcQBRKFMBnLII6x9jCQ35QtEBU+eWuD+2kBnKmyCFwFlA6Ldy7TljNo8nr9ViWbOp/b7dyA9PF6v1eUN3yR4NI+zNpoeXfBqkZQDePkf9wzKPB+Oxm+huPrFlyRyWxevOhy76LN788S79Oal+rRYGrHLLDswaZmRkzQHvr3W4wxPNdML1wlqi0waaLOanvnfy0YoYYp3mMvj2hzcX+2hnfJD+ynOOR+nwzpfyd+bgCjJnQN+O0FxlzK/3s90HCsJyWTrS0wLl6F3qtsPhHloElttBMaVeUJgZ/t6cXnB2xA8pBBjacNhYchSQLJ7hqLlBvaebemcZ9l3kMCFY+lfZUhX0F6pEpFRdmXJYsfxr+eUycVMxsoacKiEC+9KtuctKTo3b4a4NZvSgbUGJn4tT1WuJucD1A3ou1nvJvmCWYsHP8v3qYlk9u91JjSUDmj0wfFjKXN17HkDYU8MseWh4s2/0gJo3atbEt4BfNlJTp20vddtc8odOV7qH0XrhvwE=</diagram><diagram name=\"Page-3\">7VhZc6pIFP41Vs08jNWs4qMgCmJwwS2+ITTQgjQiCvjrp1GMEuNNcm9y52EuVZb0x1n6LN9hqTHSJuvGZuQ9YRsGNRrYWY1p12iaEliG/BVIfkaaAn0G3BjZpdAVMNARliAo0T2y4a4imGAcJCiqghYOQ2glFcyMY5xWxRwcVL1GpgvvAMMyg3t0juzEK1EKgOsFBSLXK10LXHlhZVq+G+N9WPqr0YxzOs6XN+aLrTOw80wbp2foZIKRa6BVK85BjZFijJMKdLmwySQYFDm/pPPsv/Mx4ZfwYhgmP6FfFnOX5JeEubFpI2JMwgGOCRTikFwRHRQEr6DDzs7UNllTZBGYKxiILzl7JbpLYuzD12BkWih0+9Apdv4PXQdNtnlzCFcZEScJ3rwnNS7L+EOhCY4einjJJijjOUUBiyyRvImphxJoEANFklLClJeYLk1F1Rs8Ae/LUVboAOMEZjfQfXmuRepCvIFJnJN1qUIas87dbrdxNluyssHXqdtYyrKm147naFAvdbybdqd5UGe4km4l1dwX7w/7iOBlK32oy5if6TJCOAbwvMXcthr9fqt5ZlQ42SUwtFDw1/Q4o/s7Tu3L3kyfqLiPQu0I2OQI0iiftSg7kKmnXfyUAzfJUSruAkNfzOZ6aA9zRPUniMTa6wuU6pITtSf7Mh5pZMrRnXZ3LIlTw3GXrGioNVocj4zplklpNJCsYxtsMm2kzAiuAlqX2rrVOlLbp+d11JXNiewfFQpwviqrvanbUoW95+XeSBLVVbZlW3/fkYakg6ZYpmH9fubc0OIDJPoy5tC/xpySGjxXBwK4HtRHqUExoE4J300N9suowXyaGsms329jNZWHualsQjP2XBIvqUQHDccuBjN/O98e1kwnsRR52PUTet7dQMr3hC4fL8brjdhLRoqQdri9gnbdrjZfxPm2pVtzLV2uWvthDxvEmBkO+NVhTM6W5Ne0h5OQ2crrcGxIiOKDrDcf6a1+vt5nKlZkZ75Ie67U7LmtZicKPQ1trXgiA8VsRLLdWOqgZdmxRvbZcxqdwTO9MfZtNQol1ul1lCRbehvCJsjP06bRnhdVojvhYDO2nhcsyIxlkOtPPmg6WVM9tqC0h+CoUz0rRkvF97I5Bm1nciDWQ01YeAtrIg18q6kc+hPWN1WjGAKr7uk2z7T/kPSXSVqqNKk6Rd+QlLkjKcMIdZb/r25g3JexlP80S8OlMpax6spy0c2eb1miMuMTco6HvaC7lHr5DBzIHBFNzbfC+cZkomXjSE8XAfb4xmDuSl24Fhl77tOcMBEMaGlcEoN2Yyp2MlXr7RXTHTD6lIYi5/e6OmWtbDZlc07bESeaun1m9/zAeOLMLGL6sqt3aHmBls6JgiwEqUYdJW2BRlZf6SM3ygzlyDUODkmA2PQKNUXacf2Yo/S+LR/lddQZgaHZJQ2rdeJ1pBupbw9U7KwF29zr6WxaBOfM9i4eNzrPlvKHZ/8XnvHf+fzMVx6ZKZaq08JNufjvDq7xXcFRdPVtgOGZOsf8ztCEu/n4MvAapJ1hePkyQB7GHg/A6yt2QQszTlrFB4CbF06SJkRe7VsBckMCb5BtF/4K+xfRVYAt/615QTU5brW6mxegDm4JUTwgvjUwHokVu6yE9mqGPNCDtguNMlllcI/mygML1cHyeojQp6xnKFmcLZSr58pqCGNE+gDGpRHSlXF+o1Asn6vLqsqjdt7hfWzBCqNJnlyYVHhQ5ODzLR/DwEzQofp1563GfmTvYpU0jJnf6EYYhcnufc3rroaFxk+MmLcY9yEPr3l+st/8Wpun2cF+yOZpSpzT+J7g1W3phvQUuLlZChTN0tVaYsfZkY758UbKQfXSHx8fZSf85qPcxdL1K+gJ/xc=</diagram></mxfile>";
  433. // //"<?xml version=\"1.0\" encoding=\"UTF-8\"?><mxfile><diagram name=\"Page-1\">7VhZk6JIEP41Ruw+jFEUp4+CKFfjgVf7hlAcghQiCvjrt1C7G7XdmZ7Y2d2HIcKIyqzKrDy+ryhs0dK2HGR2GrxgF8UtCPZ5FaMW3WtB6CLPPsT5t7MKEkWLllu0lGGcX0bbUkJxbRS6FwtQL4L9J7PUeRakdoaS/EcM4KPB1UcjSj+z3ZDMSzjGGVElOCEzohfG8Z3quHdLtUdkigixvUaxaDuRn+FD4t4t3ecZjtC9MrWdMPEN5NXBfINt0GE6jUf4WCPiPMfb762ahH7wXVdTnD5dEuTb+JrPOQtUFw4QqQjCHFnEQV2kgvT3PadF6OZBbdPmOaK8lPOIshyVjQpf+zFAeIvyrCJL7P213O+q2jBA1xTqbnGgTbMXfXHdhUgsBG3+or3uAKHQZpupXKeryzTPtalmnrCJETK4wuRzyNCPkIE/A5kWpGnAcQ7dxA38Pm4CO6032ecoccL4j9lpDo09qxpyMDenKjbCRD8BJj+BIq3mXcqNZepln71UwM+rsBD3sWUu5wszcUdVSBnTkOSrGQKl+mSganIk47F+QkToDSaSOLM8f8WIltqC4mRszXZ0AcOh5Jx6YFvqY2VO9CqAptQzne6J2r28btKBbE/l6KRQgI1UWdVmflcVDkFQBWNJVNfljun++cAAUg5IMTTv/Ps0aGD8Bxjx39OAokGbEv6OBlecc2wbCODjob6Cc+ZX4pz+Ms7zuWH0sFrIo8pWtomdBT4pASlrPxxNfAzm0W6xO27ofu4o8mgQ5XAx2CIqCoQBly0nm62o5WNFKPrsQQn3g4G+WGbVrms6C71YrbuHkYYt4sxOhtz6OCGjFfl13NE0oXfyJplYUkhxcaktxmbXqDaHUsWK7C2WheZLHc3vdvppEujhzsmmMlBsPpVdfmWCruNmOolT8/j+8BVurUNPTROJ8bS+kperYEuogbhF0bF6i7o1sJ8MtxPndcmA0lrFlfkSgY5XdtRTF0kHBE4mpTlZuFKioFxg0POmR+I90YVlsHSm0jByOsrRmDKRrVo1o9eDou4B3fvNuH/+xUPTQpvhbt48HapNwQbl6K9Qjv2VlOO+TLlkpUxkrPqyXEMziBxHVOZcTsZ4pMWDlaRVc3Ak54Ro65GTLLY2na74E5wtYxxw/HDhSwO0EWl3EUFWmAoWcnQ2z0CPn4n9UtW1g2L7Q9qcQSSykTYwKWftMgVTsfqebKKru1fmwA2tF9YuU9qQfbMP5WW48s58YhAodOok6ctw7BiKEfppaSknlj96pABiJ6jNFGnPGhlLmYYrn+RN2h+DkT0g6NP72SY1rSJyhyr2NoJrH8xiPquT8+YHH0/4/quj/CbN/5803NMr/E9n0bhFcjcvVIqh2lBoVJr7SqT8L4uUgnwb3ERKc3Sbpb8aKXJ9dBPYW+jC8+8kfMgcdNOKxmH1fvrwBFsoca3wVM+Qe8nz04hQzDs/Z4zaWd7NMlw0PrJIsULHjrtx6CdEvQ1dt96v9v+2dB1jJ/qMvFSHZdfrB/KCNmgCsL4rfcbeZ8vqKG9SuyP0E7u63Na1WNfknpH8iYdblt8zGp6rXob58uLhKr3eSCOUhQRRKLs6IQ3OqoZBLb7eircm556TCvgob+D8RxGcodjOw2MTdmdT0km7aZXiMMn3Dc+jWvHzZH1w8Mihs4POF43OxGPuyHZJ5s7FW2bY8/akdE0npNagcaILFGQev1HfS/sZpYn48S/KZfnHfzC0/Bc=</diagram><diagram name=\"Page-2\">jVPbcpswEP0aZtqHMiBZBj+am5P6NsHENn6TQVxqgRiQAefrKwxOaDtpqwcNe3bPrpY9K0EzaxclLpI1CwmVgFLxGyUStCQAQhLhK+Xf7hAQgARtCZolY7z/ylqT0I6Uhj1D6YKA84lXvXuVApck5/9DAH8ShhyjV8YlDlPhNxllpYBylguPEaWUPiAJwDOMwigSeF2F7bMlQFUYFJ8JNXBwiUt2zcPfUlQJLroiFSd5kNIv9d4xLLaO7adm47Zsqb8cD+Lx2cbb3w7UT054FhFntTwvimWQ1QHcvs0nZ7eIp5ZlJopZ2HpOgrNbPfk7ZOK3aruz/Oy73fzwNipqCk0PQIvydK6tYTnZK8gntgSMcL/RXHw9IMDi8jpxrjvspSrfZ4Uofnx21vwU+eprOvEc43IRhJfSFffKIA1ixpRuLwh4Odu1p5X/ioOwdmtDMDVYz19E3HE2OyEtRfVxWi2pE1QgJ1+77nnJLmT0CyFBOpp1ngIHaR6vSNQNRZEVoPxyVP0jyGCcs+yfYW4aJ39JlvCMDiMbCB4rPg+/D5N0IlKE1SQpJztB62bZCK2/N3dIQ550eWWka0jAvbhqUnLSjvQ2qHNBWEZ4eRMhuBrE9w51xIQMbXTanagy7OFmKCMsiJA87dFHAU2T9R65DQgCMpyNjj5ekk5w/Z48zI99vPtG2wztnw==</diagram><diagram name=\"Page-3\">7VVdb5swFP01SNvDkLExkMdCQtvloypJ8/VmwAEWgxE4QPrraxLaknXtPrSnaSAh7rn3+HLxObKCnLS5LkgeT3lImQJBKY6MKmioQBjSHTkw8eUEQQkoaKQgp+BcnN/SxqGsJSXhmQHaIui+k9VOWZCTgmbiVwjwLaFbo/eVUUHCROYdznhxghBClqX7CrJ3CWM9XMe+YegSr8qwuR1KUJMBIz5lNgn2UcEPWfhcn/FMdrDLmORtp1LQLEjYp2rp2kM+jUY39cxr+Ni6X6/kBOlssTyu2CbeksGOupOxf52Pg7QK0N3jle57eWQMh04MnHxkZTTwvfJmM8cOeSzv5sNN+nVUf1vMNFznphXABmfJlTlFhb4EeENHCrTD5cz0yGGFIY+Kg+4e5mSRaGKZ5rL5+tadiu1uoz0k+sK193tJuC88+ZzYtMbcNtjdHsNFxufNdrJ5IEFYeZUtmSaqru5l3Xow2GIzwdXaKMfMDUqY0c/t9KLge9r7hRBiH8E2k5MgyaIJ3bU7A1QAwcWlWa9FNheCpz8t85Io/mCxWKSs27KOsOD5++WnzaStkoCM6jgRdC5p7V7WUvAvw62SUMTtuuoAYImeBVbRQtCmp7lOodeUp1QUR1lCyk6AL1BLjGk3hQxNy1T1M1x3XWSEgaWedQ+eG0DzGTl2CNBUPOhdWt8ord7OXvmxb9Cf+KbT+3eWMQEJdbNvGfjfMr9nmcHp/hctA1QD/WXLQMNQzTeWae1gXFjG1DQVXljGAINLy3zgGBm+nmKnXO8MRKMn</diagram></mxfile>";
  434. // //"<?xml version=\"1.0\" encoding=\"UTF-8\"?><mxfile><diagram name=\"Page-1\">3ZZZs6JGFMc/za1KHnKLfXkEAUFARAWFN5Zm33f89Gm8zuROMpOkUqk8BAW7/6fP6fX85A3flcu+85pEr0NQvGFIP6wFeMOFNwwLQeSNxfDLU8Kg8IaLb/iuq+vho1QuO1BsTmn44YFsjTDpB1b0aUUarwPV8HccsD86vGJ8GmXceWEK7bu6qDsoVXUFLXyUFsUX6Q3DSZ/1QxLqUx8uigBFFFa8Io0rWA6gP4At+cLzQcF7QR539ViFv4vZJ16z9doPoArS4qfFjvy86WfhhHhyaywH6Q3jo4Gd4JQcrc4dt91nokFjNNQnCz1eS7Ng1W52L46XYaRUQ92w4cMv2dCEv5uwjFLHshSMkQGwPz1sERaje7DcSb0h3GiPE6TQifQCZJq9wBWUcLaVSXBC/ChbgH6UpzZIEEO/tC7rOpxSs+i0GuGIM9Z0WfoKmEFWBv5B5ptGzIlcTmCvqv3YC7orH+oTjNjRiklmBiz5whH0dquu7HCSLTlUZIEJNUC21u0ORy7RdOffsQMjJOKgHsx4tTSTS82M3x1NpbG7khKQWbLqW2jVgqPiXGsJdYzySpKOTIJyTmcCru8vXNcX59jrdemguvbtyvkP/VifQqE8OiRfHw0uX4z97pAHaCCwfY6t1NX3Zt3d7bk1MClG6rFh9ru2nKvcDQrK4ps41B4VHOMycZla9L3icLs7rAOBW3NR5JMRmcXGw7RoyeZg9K4SemEjD4ujc3y1b2fQEPA4SuQSw+dcZEb/yNhjEmlV7sGtlrDHzRlb/WjpqMcYN7iK8HtDcHdiKftKc0KRnpSbJ9/4WbFPkxg+WiM0DuZhCbJhVr26uw/VDg+sjrfo6SF2F9ViuSATH3xzjgKqHU/xeTUIRqDsoxLu+KwtTgEIkGoRb6mnsIdJOsAuO31YdZXRBs0FnoY6Gv2IHCDZV7xciT5BWpk952m2nZRJ6LR5Swlc+HnLBtANaeAV3CsRyjQMi+dRH7o6B58SiH1+NkvjBWkVayDaUhJ5RzDkmwtlfmvE18NQl3/Z7JzGyZ8ES4ayeCXsy+FaNz9u/sxcsCEEgbU5SQdwgW5b4s6QdF8nd0vDIXmGoaH2wZXJK8YXV14CXCCwfGLPi1R7UJdg6FbYxOtfIPoqbY4JeE0KVgkWfUfoD31+9QprNE69Ux/qlx4o8h1hP10vp/XFQ4x5J9lP88U/4xMWXgT9Pk3xf0JTuPNU4LNR9EekRiCKnvpXpGL/HUHJPOVliWSyfUWRFTv4KLmjMlwmsA7H/Q2rJGExR+vOsCEtRghVJShkZ5af+mslE1GFa9O2dIMCH4cFOmQ+A7RHojxguVJCIVPszdYzomgZFE7eDeMZ904q6HVSDHOGNd3K5hkpPccUZlpSyYovd1WOyDTCInqwVH6fYBOmooILsCprr2N+esyBBj3RJij9DUY+3vkQUrzLXAuIUN6MU1MzzXFDqG4qhSUPvdiYYLz0ZXsuc3PirVo+88OO1/jgeJ84Xs3YM+9kieBoV3F1lNvZSseuNB+x6wcuLTvOTGl3T+cPqS7yF2LpyapymqHAsNuSuRdR46w5QWs5YqpD16t0G2YH0nAVo+Cd+hTBUTbwXp3YWvsu4ySTqRlZmXtX2guOkB6T0fekaF0Iwz01RXHGATvsQLcryzxmPSaHzhKYtz21VvlmUdtfDLhdUD8jKiwf2v4AEXqBotr5QGPtbbulc2GNM9dYZ3JHXyjT4NIDS2dBm1WXi7UL7godqGWropU7D0ihzrZBM4uqp8XJlJVFnz3rjoytM7S5aJyxIjZcC0kQZT+2FouS2gXkZ+9YC6sN9lfY3c29lg46295tZRCNhRDFXQcc7WvVzoSe4O2VPOdrw8A0kk619vP3IEkQNMFG/0dIQoBRv1Hy34AiiqBf6PeJiSiJvRPfMJFgyXf8GwwSGPlOkH+Cvu0F5utL6tP26RUXF38F</diagram></mxfile>";
  435. //
  436. // FileOutputStream fileWriter = null;
  437. // fileWriter = new FileOutputStream("g:/work/test.vsdx");
  438. //
  439. // new mxVsdxExporter().exportMxFile(mxFileXML, fileWriter);
  440. // } catch (Exception e) {
  441. // e.printStackTrace();
  442. // }
  443. // }
  444. }