/* ****************************************************************************** * Copyright (c) 2006-2012 XMind Ltd. and others. * * This file is a part of XMind 3. XMind releases 3 and * above are dual-licensed under the Eclipse Public License (EPL), * which is available at http://www.eclipse.org/legal/epl-v10.html * and the GNU Lesser General Public License (LGPL), * which is available at http://www.gnu.org/licenses/lgpl.html * See http://www.xmind.net/license.html for details. * * Contributors: * XMind Ltd. - initial API and implementation *******************************************************************************/ package org.xmind.ui.internal.wizards; import static org.xmind.core.internal.dom.DOMConstants.ATTR_ALIGN; import static org.xmind.core.internal.dom.DOMConstants.ATTR_HEIGHT; import static org.xmind.core.internal.dom.DOMConstants.ATTR_HREF; import static org.xmind.core.internal.dom.DOMConstants.ATTR_ID; import static org.xmind.core.internal.dom.DOMConstants.ATTR_LINE_TAPERED; import static org.xmind.core.internal.dom.DOMConstants.ATTR_MULTI_LINE_COLORS; import static org.xmind.core.internal.dom.DOMConstants.ATTR_NUMBER_FORMAT; import static org.xmind.core.internal.dom.DOMConstants.ATTR_SRC; import static org.xmind.core.internal.dom.DOMConstants.ATTR_STRUCTURE_CLASS; import static org.xmind.core.internal.dom.DOMConstants.ATTR_STYLE_FAMILY; import static org.xmind.core.internal.dom.DOMConstants.ATTR_STYLE_ID; import static org.xmind.core.internal.dom.DOMConstants.ATTR_THEME; import static org.xmind.core.internal.dom.DOMConstants.ATTR_TYPE; import static org.xmind.core.internal.dom.DOMConstants.ATTR_WIDTH; import static org.xmind.core.internal.dom.DOMConstants.ATTR_X; import static org.xmind.core.internal.dom.DOMConstants.ATTR_Y; import static org.xmind.core.internal.dom.DOMConstants.TAG_BOUNDARIES; import static org.xmind.core.internal.dom.DOMConstants.TAG_BOUNDARY; import static org.xmind.core.internal.dom.DOMConstants.TAG_IMG; import static org.xmind.core.internal.dom.DOMConstants.TAG_LABEL; import static org.xmind.core.internal.dom.DOMConstants.TAG_LABELS; import static org.xmind.core.internal.dom.DOMConstants.TAG_MARKER; import static org.xmind.core.internal.dom.DOMConstants.TAG_NOTES; import static org.xmind.core.internal.dom.DOMConstants.TAG_NUMBERING; import static org.xmind.core.internal.dom.DOMConstants.TAG_POSITION; import static org.xmind.core.internal.dom.DOMConstants.TAG_PREFIX; import static org.xmind.core.internal.dom.DOMConstants.TAG_RELATIONSHIP; import static org.xmind.core.internal.dom.DOMConstants.TAG_RELATIONSHIPS; import static org.xmind.core.internal.dom.DOMConstants.TAG_SUFFIX; import static org.xmind.core.internal.dom.DOMConstants.TAG_TITLE; import static org.xmind.core.internal.dom.DOMConstants.TAG_TOPIC; import static org.xmind.core.internal.dom.DOMConstants.VAL_NONE; import static org.xmind.core.internal.dom.DOMConstants.VAL_TAPERED; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.InvocationTargetException; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.Text; import org.xmind.core.Core; import org.xmind.core.IAdaptable; import org.xmind.core.IBoundary; import org.xmind.core.IFileEntry; import org.xmind.core.IHtmlNotesContent; import org.xmind.core.IImage; import org.xmind.core.IImageSpan; import org.xmind.core.IManifest; import org.xmind.core.INotes; import org.xmind.core.INumbering; import org.xmind.core.IParagraph; import org.xmind.core.IPlainNotesContent; import org.xmind.core.IRelationship; import org.xmind.core.ISheet; import org.xmind.core.ITextSpan; import org.xmind.core.ITitled; import org.xmind.core.ITopic; import org.xmind.core.IWorkbook; import org.xmind.core.internal.dom.DOMConstants; import org.xmind.core.internal.dom.MarkerGroupImpl; import org.xmind.core.internal.dom.MarkerImpl; import org.xmind.core.internal.dom.MarkerSheetImpl; import org.xmind.core.internal.dom.NumberUtils; import org.xmind.core.internal.dom.StyleSheetImpl; import org.xmind.core.internal.dom.WorkbookImpl; import org.xmind.core.io.DirectoryStorage; import org.xmind.core.io.IStorage; import org.xmind.core.marker.IMarker; import org.xmind.core.marker.IMarkerGroup; import org.xmind.core.style.IStyle; import org.xmind.core.style.IStyleSheet; import org.xmind.core.style.IStyled; import org.xmind.core.util.DOMUtils; import org.xmind.core.util.HyperlinkUtils; import org.xmind.ui.mindmap.MindMapUI; import org.xmind.ui.wizards.MindMapImporter; import org.xml.sax.ErrorHandler; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; public class XMind2008Importer extends MindMapImporter implements ErrorHandler { private static final String TAG_MAP = "map"; //$NON-NLS-1$ private static final String TAG_ROOT_TOPIC = "root-topic"; //$NON-NLS-1$ private static final String TAG_MARKERS = "markers"; //$NON-NLS-1$ private static final String TAG_ATTACHED_TOPICS = "attached-topics"; //$NON-NLS-1$ private static final String TAG_DETACHED_TOPICS = "detached-topics"; //$NON-NLS-1$ private static final String TAG_PLAIN = "plain"; //$NON-NLS-1$ private static final String TAG_RICH = "rich"; //$NON-NLS-1$ private static final String ATTR_FOLDED = "folded"; //$NON-NLS-1$ private static final String ATTR_FLOATING_TYPE = "floating-type"; //$NON-NLS-1$ private static final String ATTR_INHERITED = "inherited"; //$NON-NLS-1$ private static final String ATTR_FROM = "from-id"; //$NON-NLS-1$ private static final String ATTR_TO = "to-id"; //$NON-NLS-1$ private static final String ATTR_END_INDEX = "end-index"; //$NON-NLS-1$ private static final String ATTR_START_INDEX = "start-index"; //$NON-NLS-1$ private static final String ATTR_RAINBOWCOLOR = "rainbowcolor"; //$NON-NLS-1$ private static final String ATTR_SPINYLINES = "spinylines"; //$NON-NLS-1$ private static final String ATTR_FROM_POINT = "control-point1"; //$NON-NLS-1$ private static final String ATTR_TO_POINT = "control-point2"; //$NON-NLS-1$ private static final String VAL_CENTRAL = "central"; //$NON-NLS-1$ private static final String VAL_MULTI_LINE_COLORS = "#ac6060 #acac60 #60ac60 #60acac #6060ac #ac60ac"; //$NON-NLS-1$ private static final String VAL_USER = "User"; //$NON-NLS-1$ private static final String VAL_ATTACHMENT = "Attachment"; //$NON-NLS-1$ private static final String PROP_BACKGROUND = "background"; //$NON-NLS-1$ private IWorkbook sourceWorkbook; private IWorkbook targetWorkbook; private IStorage storage; private DocumentBuilder builder; private MarkerSheetImpl markerSheet; private String defaultMarkerGroupId; public XMind2008Importer(String sourcePath, IWorkbook targetWorkbook) { super(sourcePath, targetWorkbook); } public void build() throws InvocationTargetException, InterruptedException { try { storage = createStorage(); sourceWorkbook = Core.getWorkbookBuilder().loadFromPath( getSourcePath(), storage, null); targetWorkbook = getTargetWorkbook(); readStyles(); Document contentDoc = parseStyles("content.xml"); //$NON-NLS-1$ loadWorkbook((WorkbookImpl) targetWorkbook, contentDoc); } catch (Exception e) { throw new InvocationTargetException(e); } } private void readStyles() { Document styleDoc = parseStyles("styles.xml"); //$NON-NLS-1$ if (styleDoc == null) return; upgradeStyleSheet(styleDoc); StyleSheetImpl ss = new StyleSheetImpl(styleDoc); ((WorkbookImpl) targetWorkbook).setStyleSheet(ss); ss.getAllStyles(); } private void upgradeStyleSheet(Document styleDoc) { Element element = styleDoc.getDocumentElement(); if (element != null) upgradeStyles(element); } private void upgradeStyles(Element element) { upgradeStyle(element); Iterator<Element> it = DOMUtils.childElementIter(element); while (it.hasNext()) { Element subElement = it.next(); upgradeStyles(subElement); } } private void upgradeStyle(Element element) { NamedNodeMap attributes = element.getAttributes(); Map<String, String> added = null; for (int i = 0; i < attributes.getLength(); i++) { Attr attr = (Attr) attributes.item(i); String name = attr.getName(); String value = attr.getValue(); if (ATTR_TYPE.equals(name)) { attr.setValue(value.toLowerCase()); } else if (ATTR_STYLE_FAMILY.equals(name)) { attr.setValue(value.toLowerCase()); } else if (ATTR_RAINBOWCOLOR.equals(name)) { if (Boolean.TRUE.toString().equalsIgnoreCase(value)) { added = add(added, ATTR_MULTI_LINE_COLORS, VAL_MULTI_LINE_COLORS); } } else if (ATTR_SPINYLINES.equals(name)) { if (Boolean.TRUE.toString().equalsIgnoreCase(value)) { added = add(added, ATTR_LINE_TAPERED, VAL_TAPERED); } } if ("floatingMainTopic".equals(value)) { //$NON-NLS-1$ attr.setValue("floatingTopic"); //$NON-NLS-1$ } else if ("$none$".equals(value)) { //$NON-NLS-1$ attr.setValue(VAL_NONE); } } if (added != null) { for (Entry<String, String> e : added.entrySet()) { element.setAttribute(e.getKey(), e.getValue()); } } } private Map<String, String> add(Map<String, String> map, String key, String value) { if (map == null) map = new HashMap<String, String>(); map.put(key, value); return map; } private void loadWorkbook(WorkbookImpl workbook, Document wbDocument) { Element wbEle = wbDocument.getDocumentElement(); Iterator<Element> sheetIter = DOMUtils.childElementIterByTag(wbEle, TAG_MAP); boolean primary = true; while (sheetIter.hasNext()) { Element sheetEle = sheetIter.next(); ISheet sheet; if (primary) { sheet = workbook.getPrimarySheet(); primary = false; } else { sheet = workbook.createSheet(); workbook.addSheet(sheet); } loadSheet(sheet, sheetEle, workbook); } } private void loadTitle(ITitled titled, Element oldElement) { String title = DOMUtils.getTextContentByTag(oldElement, TAG_TITLE); titled.setTitleText(title); } private void loadId(IAdaptable elementAdaptable, Element oldElement, WorkbookImpl workbook) { Element newElement = getElement(elementAdaptable); if (newElement != null) { String id = DOMUtils.getAttribute(oldElement, ATTR_ID); if (id != null) { // workbook.getElementRegistry().unregisterByKey(id); Document doc = newElement.getOwnerDocument(); workbook.getAdaptableRegistry() .unregisterById(elementAdaptable, newElement.getAttribute(ATTR_ID), doc); DOMUtils.replaceId(newElement, id); workbook.getAdaptableRegistry().registerById(elementAdaptable, id, doc); // workbook.getElementRegistry().registerByKey(id, // elementAdaptable); } } } private Element getElement(IAdaptable elementAdaptable) { return (Element) elementAdaptable.getAdapter(Element.class); } private void loadStyle(IStyled styled, Element oldElement) { String styleId = DOMUtils.getAttribute(oldElement, ATTR_STYLE_ID); styled.setStyleId(styleId); } private void loadSheet(ISheet sheet, Element sheetEle, WorkbookImpl workbook) { loadId(sheet, sheetEle, workbook); loadTitle(sheet, sheetEle); loadSheetStyle(sheet, sheetEle); String themeId = DOMUtils.getAttribute(sheetEle, ATTR_THEME); sheet.setThemeId(themeId); Element topicEle = DOMUtils.getFirstChildElementByTag(sheetEle, TAG_ROOT_TOPIC); if (topicEle != null) { loadTopic(sheet.getRootTopic(), topicEle, workbook); } Element relsEle = DOMUtils.getFirstChildElementByTag(sheetEle, TAG_RELATIONSHIPS); if (relsEle != null) { Iterator<Element> relIter = DOMUtils.childElementIterByTag(relsEle, TAG_RELATIONSHIP); while (relIter.hasNext()) { Element relEle = relIter.next(); IRelationship rel = workbook.createRelationship(); sheet.addRelationship(rel); loadRelationship(rel, relEle, workbook); } } } private void loadSheetStyle(ISheet sheet, Element sheetEle) { String styleId = DOMUtils.getAttribute(sheetEle, ATTR_STYLE_ID); IStyleSheet styleSheet = targetWorkbook.getStyleSheet(); IStyle style = styleSheet.findStyle(styleId); String type = style.getType(); if ("map".equals(type)) { //$NON-NLS-1$ String p = style.getProperty(PROP_BACKGROUND); String url = findAttachmentUrl(p); style.setProperty(PROP_BACKGROUND, url); } sheet.setStyleId(styleId); } private void loadTopic(ITopic topic, Element topicEle, WorkbookImpl workbook) { loadId(topic, topicEle, workbook); loadTitle(topic, topicEle); loadStyle(topic, topicEle); loadFolded(topic, topicEle); loadPosition(topic, topicEle); loadHyperlink(topic, topicEle); loadStructureClass(topic, topicEle); loadLabels(topic, topicEle); loadImage(topic, topicEle, workbook); loadMarkers(topic, topicEle, workbook); loadNotes(topic, topicEle, workbook); loadNumbering(topic, topicEle); loadSubTopics(topic, topicEle, TAG_ATTACHED_TOPICS, ITopic.ATTACHED, workbook); loadSubTopics(topic, topicEle, TAG_DETACHED_TOPICS, ITopic.DETACHED, workbook); loadBoundaries(topic, topicEle, workbook); } private void loadHyperlink(ITopic topic, Element topicEle) { String url = DOMUtils.getAttribute(topicEle, ATTR_HREF); if (url != null) { url = readAttachment(url); } topic.setHyperlink(url); } private String readAttachment(String url) { String path = HyperlinkUtils.toAttachmentPath(url); if (path.startsWith("#")) //$NON-NLS-1$ path = path.substring(1); IFileEntry entry = findAttachmentEntry(path); if (entry != null) { if (entry != null) { InputStream is = entry.getInputStream(); String entryName = entry.getPath(); try { IFileEntry fileEntry = targetWorkbook.getManifest() .createAttachmentFromStream(is, entryName); return HyperlinkUtils.toAttachmentURL(fileEntry.getPath()); } catch (IOException e) { log(e, "failed to create attachment from: " + path); //$NON-NLS-1$ } } } return path; } private void loadFolded(ITopic topic, Element topicEle) { String folded = DOMUtils.getAttribute(topicEle, ATTR_FOLDED); topic.setFolded(Boolean.TRUE.toString().equalsIgnoreCase(folded)); } private void loadPosition(ITopic topic, Element topicEle) { Element positionEle = DOMUtils.getFirstChildElementByTag(topicEle, TAG_POSITION); if (positionEle != null) { String x = DOMUtils.getAttribute(positionEle, ATTR_X); String y = DOMUtils.getAttribute(positionEle, ATTR_Y); if (x != null && y != null) { try { int xValue = Integer.parseInt(x); int yValue = Integer.parseInt(y); topic.setPosition(xValue, yValue); } catch (NumberFormatException e) { } } if (x != null || y != null) { Element newPositionEle = DOMUtils.ensureChildElement( getElement(topic), TAG_POSITION); DOMUtils.setAttribute(newPositionEle, ATTR_X, x); DOMUtils.setAttribute(newPositionEle, ATTR_Y, y); } } } private void loadBoundaries(ITopic topic, Element topicEle, WorkbookImpl workbook) { Element boundariesEle = DOMUtils.getFirstChildElementByTag(topicEle, TAG_BOUNDARIES); if (boundariesEle == null) return; Iterator<Element> boundaryIter = DOMUtils.childElementIterByTag( boundariesEle, TAG_BOUNDARY); while (boundaryIter.hasNext()) { Element boundaryEle = boundaryIter.next(); IBoundary boundary = workbook.createBoundary(); topic.addBoundary(boundary); loadBoundary(boundary, boundaryEle, workbook); } } private void loadBoundary(IBoundary boundary, Element boundaryEle, WorkbookImpl workbook) { String startIndex = DOMUtils .getAttribute(boundaryEle, ATTR_START_INDEX); String endIndex = DOMUtils.getAttribute(boundaryEle, ATTR_END_INDEX); Element newBoundaryEle = getElement(boundary); DOMUtils.setAttribute(newBoundaryEle, ATTR_START_INDEX, startIndex); DOMUtils.setAttribute(newBoundaryEle, ATTR_END_INDEX, endIndex); loadStyle(boundary, boundaryEle); } private void loadSubTopics(ITopic topic, Element topicEle, String topicsTag, String topicType, WorkbookImpl workbook) { Element subTopicsEle = DOMUtils.getFirstChildElementByTag(topicEle, topicsTag); if (subTopicsEle == null) return; Iterator<Element> subTopicIter = DOMUtils.childElementIterByTag( subTopicsEle, TAG_TOPIC); while (subTopicIter.hasNext()) { Element subTopicEle = subTopicIter.next(); ITopic subTopic = workbook.createTopic(); topic.add(subTopic, topicType); loadTopic(subTopic, subTopicEle, workbook); } } private void loadNumbering(ITopic topic, Element topicEle) { Element numberingEle = DOMUtils.getFirstChildElementByTag(topicEle, TAG_NUMBERING); if (numberingEle == null) return; INumbering numbering = topic.getNumbering(); String format = DOMUtils.getAttribute(numberingEle, ATTR_NUMBER_FORMAT); String prefix = DOMUtils.getAttribute(numberingEle, TAG_PREFIX); String suffix = DOMUtils.getAttribute(numberingEle, TAG_SUFFIX); String inherited = DOMUtils.getAttribute(numberingEle, ATTR_INHERITED); numbering.setFormat(format); numbering.setPrefix(prefix); numbering.setSuffix(suffix); boolean prependParentNumbering = inherited == null || Boolean.parseBoolean(inherited); numbering.setPrependsParentNumbers(prependParentNumbering); } private void loadNotes(ITopic topic, Element topicEle, WorkbookImpl workbook) { Element notesEle = DOMUtils.getFirstChildElementByTag(topicEle, TAG_NOTES); if (notesEle == null) return; INotes notes = topic.getNotes(); Element plainEle = DOMUtils.getFirstChildElementByTag(notesEle, TAG_PLAIN); if (plainEle != null) { IPlainNotesContent content = (IPlainNotesContent) workbook .createNotesContent(INotes.PLAIN); content.setTextContent(plainEle.getTextContent()); notes.setContent(INotes.PLAIN, content); } Element richEle = DOMUtils .getFirstChildElementByTag(notesEle, TAG_RICH); if (richEle != null) { IHtmlNotesContent content = (IHtmlNotesContent) workbook .createNotesContent(INotes.HTML); loadRichNotes(topic, topicEle, richEle, content, workbook); notes.setContent(INotes.HTML, content); } } private void loadRichNotes(ITopic topic, Element topicEle, Element richEle, IHtmlNotesContent content, WorkbookImpl workbook) { Iterator<Element> it = DOMUtils.childElementIterByTag(richEle, DOMConstants.TAG_P); while (it.hasNext()) { Element pEle = it.next(); IParagraph p = content.createParagraph(); loadParagraph(topic, topicEle, pEle, p, content, workbook); content.addParagraph(p); } } private void loadParagraph(ITopic topic, Element topicEle, Element pEle, IParagraph p, IHtmlNotesContent content, WorkbookImpl workbook) { NodeList ns = pEle.getChildNodes(); for (int i = 0; i < ns.getLength(); i++) { Node n = ns.item(i); if (n instanceof Text) { ITextSpan span = content.createTextSpan(n.getTextContent()); p.addSpan(span); } else if (n instanceof Element) { Element e = (Element) n; String tag = e.getTagName(); if (TAG_IMG.equals(tag)) { String url = findImageUrl(e, workbook); if (url != null) { IImageSpan span = content.createImageSpan(url); p.addSpan(span); } } else { ITextSpan span = content.createTextSpan(e.getTextContent()); span.setStyleId(DOMUtils.getAttribute(e, ATTR_STYLE_ID)); p.addSpan(span); } } } } private void loadMarkers(ITopic topic, Element topicEle, WorkbookImpl workbook) { Element markersEle = DOMUtils.getFirstChildElementByTag(topicEle, TAG_MARKERS); if (markersEle == null) return; Iterator<Element> markerIter = DOMUtils.childElementIterByTag( markersEle, TAG_MARKER); while (markerIter.hasNext()) { Element markerEle = markerIter.next(); loadMarker(topic, markerEle, workbook); } } private void loadMarker(ITopic topic, Element markerEle, WorkbookImpl workbook) { String id = DOMUtils.getAttribute(markerEle, ATTR_ID); if (id == null) return; String type = DOMUtils.getAttribute(markerEle, ATTR_TYPE); int sepIndex = id.indexOf('/'); String markerId; String markerGroupId; if (sepIndex >= 0) { markerId = id.substring(sepIndex + 1); if (VAL_USER.equals(type)) { if (id.startsWith("#")) { //$NON-NLS-1$ markerGroupId = id.substring(1, sepIndex); } else { markerGroupId = id.substring(0, sepIndex); } } else { markerGroupId = null; } } else { markerId = id; if (VAL_USER.equals(type) || VAL_ATTACHMENT.equals(type)) { markerGroupId = getDefaultMarkerGroupId(); } else { markerGroupId = null; } } if (markerGroupId != null) { if (markerSheet == null) { markerSheet = (MarkerSheetImpl) workbook.getMarkerSheet(); } IMarkerGroup group = markerSheet.findMarkerGroup(markerGroupId); if (group == null) { group = markerSheet.createMarkerGroup(false); markerSheet.getElementRegistry().unregister(group); DOMUtils.replaceId( ((MarkerGroupImpl) group).getImplementation(), markerGroupId); markerSheet.getElementRegistry().register(group); markerSheet.addMarkerGroup(group); } IMarker marker = group.getMarker(markerId); if (marker == null) { IFileEntry markerEntry = findAttachmentEntry(markerId, workbook.getManifest()); if (markerEntry != null) { String path = markerEntry.getPath(); if (!path.startsWith("/")) //$NON-NLS-1$ path = "/" + path; //$NON-NLS-1$ marker = markerSheet.createMarker(path); markerSheet.getElementRegistry().unregister(marker); DOMUtils.replaceId( ((MarkerImpl) marker).getImplementation(), markerId); markerSheet.getElementRegistry().register(marker); } } } topic.addMarker(markerId); } private IFileEntry findAttachmentEntry(String attId, IManifest manifest) { List<IFileEntry> fileEntries = manifest.getFileEntries(); for (IFileEntry entry : fileEntries) { if (entry.getPath().contains(attId)) return entry; } return null; } private String getDefaultMarkerGroupId() { if (defaultMarkerGroupId == null) { defaultMarkerGroupId = Core.getIdFactory().createId(); } return defaultMarkerGroupId; } private void loadImage(ITopic topic, Element topicEle, WorkbookImpl workbook) { Element imgEle = DOMUtils.getFirstChildElementByTag(topicEle, TAG_IMG); if (imgEle == null) return; IImage image = topic.getImage(); String url = findImageUrl(imgEle, workbook); image.setSource(url); String width = DOMUtils.getAttribute(imgEle, ATTR_WIDTH); if (width != null) { int w = NumberUtils.safeParseInt(width, -1); if (w >= 0) { image.setWidth(w); } } String height = DOMUtils.getAttribute(imgEle, ATTR_HEIGHT); if (height != null) { int h = NumberUtils.safeParseInt(height, -1); if (h >= 0) { image.setHeight(h); } } String alignment = DOMUtils.getAttribute(imgEle, ATTR_ALIGN); image.setAlignment(alignment); } private String findImageUrl(Element imgEle, WorkbookImpl workbook) { String url = DOMUtils.getAttribute(imgEle, ATTR_SRC); return findAttachmentUrl(url); } private void loadLabels(ITopic topic, Element topicEle) { Iterator<Element> labelsIter = DOMUtils.childElementIterByTag(topicEle, TAG_LABELS); while (labelsIter.hasNext()) { Element labelsEle = labelsIter.next(); Iterator<Element> labelIter = DOMUtils.childElementIterByTag( labelsEle, TAG_LABEL); while (labelIter.hasNext()) { Element labelEle = labelIter.next(); String label = labelEle.getTextContent(); topic.addLabel(label); } } } private void loadStructureClass(ITopic topic, Element topicEle) { String floatingType = DOMUtils.getAttribute(topicEle, ATTR_FLOATING_TYPE); String structureClass; if (VAL_CENTRAL.equals(floatingType)) { structureClass = "org.xmind.branchPolicy.map.floating"; //$NON-NLS-1$ } else { structureClass = upgradeStructureClass(DOMUtils.getAttribute( topicEle, ATTR_STRUCTURE_CLASS)); } topic.setStructureClass(structureClass); } private String upgradeStructureClass(String structureClass) { if (structureClass == null) return null; if ("org.xmind.branchPolicy.org-chart.left".equals(structureClass)) { //$NON-NLS-1$ structureClass = "org.xmind.ui.logic.left"; //$NON-NLS-1$ } else if ("org.xmind.branchPolicy.org-chart.right".equals(structureClass)) { //$NON-NLS-1$ structureClass = "org.xmind.ui.logic.right"; //$NON-NLS-1$ } else if ("org.xmind.branchPolicy.chart2d".equals(structureClass)) { //$NON-NLS-1$ structureClass = "org.xmind.ui.spreadsheet"; //$NON-NLS-1$ } else if (structureClass.startsWith("org.xmind.branchPolicy.")) { //$NON-NLS-1$ structureClass = "org.xmind.ui." + structureClass.substring(23); //$NON-NLS-1$ } return structureClass; } private void loadRelationship(IRelationship rel, Element relEle, WorkbookImpl workbook) { loadId(rel, relEle, workbook); loadStyle(rel, relEle); loadTitle(rel, relEle); rel.setEnd1Id(DOMUtils.getAttribute(relEle, ATTR_FROM)); rel.setEnd2Id(DOMUtils.getAttribute(relEle, ATTR_TO)); loadControlPoint(rel, 0, relEle, ATTR_FROM_POINT); loadControlPoint(rel, 1, relEle, ATTR_TO_POINT); } private void loadControlPoint(IRelationship rel, int index, Element relEle, String pointAttr) { String p = DOMUtils.getAttribute(relEle, pointAttr); if (p != null) { String[] xy = p.split(", "); //$NON-NLS-1$ if (xy.length == 2) { int x; int y; try { x = Integer.parseInt(xy[0]); y = Integer.parseInt(xy[1]); } catch (Throwable e) { return; } rel.getControlPoint(index).setPosition(x, y); } } } private String findAttachmentUrl(String url) { if (HyperlinkUtils.isAttachmentURL(url)) { String attId = HyperlinkUtils.toAttachmentPath(url); if (attId.startsWith("#")) { //$NON-NLS-1$ attId = attId.substring(1, attId.length()); } IFileEntry entry = findAttachmentEntry(attId); if (entry != null) { InputStream is = entry.getInputStream(); String path = entry.getPath(); try { IFileEntry fileEntry = targetWorkbook.getManifest() .createAttachmentFromStream(is, path); return HyperlinkUtils.toAttachmentURL(fileEntry.getPath()); } catch (IOException e) { log(e, "failed to create attachment from: " + path); //$NON-NLS-1$ } } } return url; } private IFileEntry findAttachmentEntry(String attId) { IManifest manifest = sourceWorkbook.getManifest(); List<IFileEntry> fileEntries = manifest.getFileEntries(); for (IFileEntry entry : fileEntries) { if (entry.getPath().contains(attId)) return entry; } return null; } private Document parseStyles(String content) { DocumentBuilder builder = getDocumentBuilder(); builder.setErrorHandler(this); List<IFileEntry> entries = sourceWorkbook.getManifest() .getFileEntries(); for (IFileEntry entry : entries) { if (content.equals(entry.getPath())) { InputStream is = entry.getInputStream(); try { return builder.parse(is); } catch (SAXException e) { } catch (IOException e) { } break; } } return null; } private IStorage createStorage() { String tempFile = Core.getIdFactory().createId() + MindMapUI.FILE_EXT_XMIND_TEMP; String tempLocation = Core.getWorkspace().getTempDir( "workbooks" + "/" + tempFile); //$NON-NLS-1$ //$NON-NLS-2$ File tempDir = new File(tempLocation); return new DirectoryStorage(tempDir); } private DocumentBuilder getDocumentBuilder() { if (builder == null) { DocumentBuilderFactory factory = DocumentBuilderFactory .newInstance(); factory.setAttribute( "http://apache.org/xml/features/continue-after-fatal-error", //$NON-NLS-1$ true); try { builder = factory.newDocumentBuilder(); } catch (ParserConfigurationException e) { e.printStackTrace(); } } return builder; } public void error(SAXParseException exception) throws SAXException { log(exception, null); } public void fatalError(SAXParseException exception) throws SAXException { log(exception, null); } public void warning(SAXParseException exception) throws SAXException { log(exception, null); } }