/* ******************************************************************************
* 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.core.internal.dom;
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_NUMBER_SEPARATOR;
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_VERSION;
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_A;
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 static org.xmind.core.internal.zip.ArchiveConstants.CONTENT_XML;
import static org.xmind.core.internal.zip.ArchiveConstants.META_XML;
import static org.xmind.core.internal.zip.ArchiveConstants.STYLES_XML;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
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.CoreException;
import org.xmind.core.IAdaptable;
import org.xmind.core.IBoundary;
import org.xmind.core.IFileEntry;
import org.xmind.core.IHtmlNotesContent;
import org.xmind.core.IHyperlinkSpan;
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.ISpanList;
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.compatibility.FileFormat;
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;
public class FileFormat_1 extends FileFormat {
private static final String VERSION = "1.0"; //$NON-NLS-1$
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 = "#017c98 #00b2a1 #ffdd00 #fc8f00 #ff1500 #00b04c"; //$NON-NLS-1$
private static final String VAL_USER = "User"; //$NON-NLS-1$
private static final String VAL_ATTACHMENT = "Attachment"; //$NON-NLS-1$
private MarkerSheetImpl markerSheet;
private String defaultMarkerGroupId;
public FileFormat_1(DeserializerImpl deserializer) {
super(deserializer);
}
public boolean identifies() throws CoreException, IOException {
Document document = deserializer.loadDocumentFromEntry(CONTENT_XML);
if (document == null)
return false;
Element ele = document.getDocumentElement();
String version = DOMUtils.getAttribute(ele, ATTR_VERSION);
return version == null || VERSION.equals(version);
}
public WorkbookImpl load() throws CoreException, IOException {
WorkbookImpl workbook = new WorkbookImpl(deserializer.createDocument(),
deserializer.getManifest());
DOMUtils.setAttribute(workbook.getWorkbookElement(), ATTR_VERSION,
VERSION);
Document metaDocument = deserializer.loadDocumentFromEntry(META_XML);
if (metaDocument != null) {
MetaImpl meta = new MetaImpl(metaDocument);
workbook.setMeta(meta);
}
Document ssDocument = deserializer.loadDocumentFromEntry(STYLES_XML);
if (ssDocument != null) {
upgradeStyleSheet(ssDocument);
StyleSheetImpl ss = new StyleSheetImpl(ssDocument);
workbook.setStyleSheet(ss);
ss.getAllStyles();
}
Document contentDocument = deserializer
.loadDocumentFromEntry(CONTENT_XML);
assert contentDocument != null;
loadWorkbookContent(workbook, contentDocument);
return workbook;
}
// private void copyEntry(IInputSource source, IOutputTarget target,
// String entryPath) throws CoreException {
// try {
// InputStream in = getInputStream(source, entryPath);
// if (in != null) {
// long time = source.getEntryTime(entryPath);
// if (time >= 0) {
// target.setEntryTime(entryPath, time);
// }
// OutputStream out = getOutputStream(target, entryPath);
// if (out != null) {
// FileUtils.transfer(in, out, true);
// }
// }
// } catch (IOException e) {
// Core.getLogger().log(e);
// } catch (CoreException e) {
// if (e.getType() == Core.ERROR_WRONG_PASSWORD
// || e.getType() == Core.ERROR_CANCELLATION)
// throw e;
// Core.getLogger().log(e);
// }
// }
// private InputStream getInputStream(IInputSource source, String entryPath)
// throws IOException, CoreException {
// if (!source.hasEntry(entryPath))
// return null;
//
// return source.openEntryStream(entryPath);
// }
//
// private OutputStream getOutputStream(IOutputTarget target, String entryPath)
// throws IOException {
// if (!target.isEntryAvaialble(entryPath))
// return null;
//
// return target.openEntryStream(entryPath);
// }
private void upgradeStyleSheet(Document ssDocument) {
Element element = ssDocument.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 loadWorkbookContent(WorkbookImpl workbook, Document wbDocument)
throws CoreException {
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 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.getElementRegistry().registerByKey(id,
// elementAdaptable);
workbook.getAdaptableRegistry().registerById(elementAdaptable,
id, doc);
}
}
}
private Element getElement(IAdaptable elementAdaptable) {
return (Element) elementAdaptable.getAdapter(Element.class);
}
private void loadTitle(ITitled titled, Element oldElement) {
String title = DOMUtils.getTextContentByTag(oldElement, TAG_TITLE);
titled.setTitleText(title);
}
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, workbook);
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,
IWorkbook workbook) {
String styleId = DOMUtils.getAttribute(sheetEle, ATTR_STYLE_ID);
IStyleSheet styleSheet = workbook.getStyleSheet();
IStyle style = styleSheet.findStyle(styleId);
if (style != null) {
String type = style.getType();
if ("map".equals(type)) { //$NON-NLS-1$
String p = style.getProperty("background"); //$NON-NLS-1$
String url = findAttachmentUrl(p, workbook);
style.setProperty("background", url); //$NON-NLS-1$
}
}
sheet.setStyleId(styleId);
}
private String findAttachmentUrl(String url, IWorkbook workbook) {
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,
workbook.getManifest());
if (entry != null) {
try {
InputStream is = entry.openInputStream();
try {
String path = entry.getPath();
IFileEntry fileEntry = workbook.getManifest()
.createAttachmentFromStream(is, path);
return HyperlinkUtils
.toAttachmentURL(fileEntry.getPath());
} finally {
is.close();
}
} catch (IOException e) {
}
}
}
return url;
}
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(topic, url);
}
topic.setHyperlink(url);
}
/**
* Read attachment content.
*
* @param topic
* @param url
* @return
*/
private String readAttachment(ITopic topic, String url) {
String path = HyperlinkUtils.toAttachmentPath(url);
if (path.startsWith("#")) //$NON-NLS-1$
path = path.substring(1);
IFileEntry entry = findAttachmentEntry(path,
topic.getOwnedWorkbook().getManifest());
if (entry != null) {
url = HyperlinkUtils.toAttachmentURL(entry.getPath());
}
return url;
}
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 separator = DOMUtils.getAttribute(numberingEle,
ATTR_NUMBER_SEPARATOR);
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.setSeparator(separator);
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();
loadSpanList(topic, topicEle, pEle, p, content, workbook);
content.addParagraph(p);
}
}
private void loadSpanList(ITopic topic, Element topicEle, Element listEle,
ISpanList list, IHtmlNotesContent content, WorkbookImpl workbook) {
NodeList ns = listEle.getChildNodes();
for (int i = 0; i < ns.getLength(); i++) {
Node n = ns.item(i);
if (n instanceof Text) {
ITextSpan span = content.createTextSpan(n.getTextContent());
list.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);
list.addSpan(span);
}
} else if (TAG_A.equals(tag)) {
String href = e.getAttribute(ATTR_HREF);
if (href != null) {
IHyperlinkSpan hyperlinkSpan = content
.createHyperlinkSpan(href);
list.addSpan(hyperlinkSpan);
loadSpanList(topic, topicEle, e, hyperlinkSpan, content,
workbook);
}
} else {
ITextSpan span = content.createTextSpan(e.getTextContent());
span.setStyleId(DOMUtils.getAttribute(e, ATTR_STYLE_ID));
list.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);
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,
workbook.getManifest());
if (entry != null) {
url = HyperlinkUtils.toAttachmentURL(entry.getPath());
}
}
return 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" //$NON-NLS-1$
.equals(structureClass)) {
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);
}
}
}
}