/* * Freeplane - mind map editor * Copyright (C) 2008 Dimitry Polivaev * * This file author is Dimitry Polivaev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.freeplane.features.map; import java.util.List; import java.util.Map; import org.freeplane.core.io.IAttributeHandler; import org.freeplane.core.io.IElementDOMHandler; import org.freeplane.core.io.IReadCompletionListener; import org.freeplane.core.io.ReadManager; import org.freeplane.core.io.UnknownElements; import org.freeplane.core.io.xml.TreeXmlReader; import org.freeplane.core.resources.ResourceController; import org.freeplane.features.map.MapWriter.Hint; import org.freeplane.features.map.MapWriter.Mode; import org.freeplane.n3.nanoxml.XMLElement; public class NodeBuilder implements IElementDOMHandler { static class IconProperties { String iconName; } public static final String FOLDING_LOADED = "folding_loaded"; public static final String RESOURCES_ALWAYS_FOLD_ALL_AFTER_LOAD = "always_fold_all_after_load"; public static final String RESOURCES_ALWAYS_SAVE_FOLDING = "always_save_folding"; public static final String RESOURCES_ALWAYS_UNFOLD_ALL_AFTER_LOAD = "always_unfold_all_after_load"; public static final String RESOURCES_LOAD_FOLDING = "load_folding"; public static final String RESOURCES_LOAD_FOLDING_FROM_MAP_DEFAULT_FOLD_ALL = "load_folding_from_map_default_fold_all"; public static final String RESOURCES_LOAD_FOLDING_FROM_MAP_DEFAULT_UNFOLD_ALL = "load_folding_from_map_default_unfold_all"; protected static final String MAX_DISPLAYED_NODE_COUNT = "max_displayed_node_count"; public static final String RESOURCES_NEVER_SAVE_FOLDING = "never_save_folding"; public static final String RESOURCES_SAVE_FOLDING = "save_folding"; public static final String RESOURCES_SAVE_FOLDING_IF_MAP_IS_CHANGED = "save_folding_if_map_is_changed"; public static final String RESOURCES_SAVE_MODIFICATION_TIMES = "save_modification_times"; public static final String XML_NODE = "node"; public static final String XML_STYLENODE = "stylenode"; public static final String XML_NODE_ADDITIONAL_INFO = "ADDITIONAL_INFO"; public static final String XML_NODE_CLASS = "AA_NODE_CLASS"; public static final String XML_NODE_ENCRYPTED_CONTENT = "ENCRYPTED_CONTENT"; public static final String XML_NODE_HISTORY_CREATED_AT = "CREATED"; public static final String XML_NODE_HISTORY_LAST_MODIFIED_AT = "MODIFIED"; private final MapReader mapReader; NodeBuilder(final MapReader mapReader) { this.mapReader = mapReader; } public Object createElement(final Object parent, final String tag, final XMLElement attributes) { final NodeModel userObject = createNode(); if (getMapChild() == null) { setMapChild(userObject); } return userObject; } public NodeModel createNode() { return new NodeModel(getMap()); } public void endElement(final Object parentObject, final String tag, final Object userObject, final XMLElement dom) { final NodeModel node = (NodeModel) userObject; if (dom.getAttributeCount() != 0 || dom.hasChildren()) { node.addExtension(new UnknownElements(dom)); } if (parentObject instanceof MapModel) { setMapChild(node); return; } if (parentObject instanceof NodeModel) { final NodeModel parentNode = (NodeModel) parentObject; if (userObject instanceof NodeModel) { parentNode.insert(node, -1); } return; } } private MapModel getMap() { return mapReader.getCurrentNodeTreeCreator().getCreatedMap(); } public NodeModel getMapChild() { return mapReader.getCurrentNodeTreeCreator().getMapChild(); } private void registerAttributeHandlers(final ReadManager reader) { reader.addAttributeHandler(NodeBuilder.XML_NODE, NodeBuilder.XML_NODE_ENCRYPTED_CONTENT, new IAttributeHandler() { private void createEncryptedNode(final NodeModel node, final String additionalInfo) { final EncryptionModel encryptionModel = new EncryptionModel(node, additionalInfo); node.addExtension(encryptionModel); } public void setAttribute(final Object userObject, final String value) { final NodeModel node = (NodeModel) userObject; createEncryptedNode(node, value); node.setFolded(true); } }); reader.addAttributeHandler(NodeBuilder.XML_NODE, NodeBuilder.XML_NODE_HISTORY_CREATED_AT, new IAttributeHandler() { public void setAttribute(final Object userObject, final String value) { final NodeModel node = (NodeModel) userObject; if (node.getHistoryInformation() == null) { node.setHistoryInformation(new HistoryInformationModel()); } node.getHistoryInformation().setCreatedAt(TreeXmlReader.xmlToDate(value)); } }); reader.addAttributeHandler(NodeBuilder.XML_NODE, NodeBuilder.XML_NODE_HISTORY_LAST_MODIFIED_AT, new IAttributeHandler() { public void setAttribute(final Object userObject, final String value) { final NodeModel node = (NodeModel) userObject; if (node.getHistoryInformation() == null) { node.setHistoryInformation(new HistoryInformationModel()); } node.getHistoryInformation().setLastModifiedAt(TreeXmlReader.xmlToDate(value)); } }); reader.addAttributeHandler(NodeBuilder.XML_STYLENODE, "FOLDED", new IAttributeHandler() { public void setAttribute(Object userObject, String value) { } }); reader.addAttributeHandler(NodeBuilder.XML_NODE, "FOLDED", new IAttributeHandler() { public void setAttribute(final Object userObject, final String value) { final NodeModel node = (NodeModel) userObject; final Object mode = mapReader.getCurrentNodeTreeCreator().getHint(Hint.MODE); if (mode.equals(Mode.FILE)) { final String loadFolding = ResourceController.getResourceController().getProperty( NodeBuilder.RESOURCES_LOAD_FOLDING); if (loadFolding.equals(NodeBuilder.RESOURCES_ALWAYS_FOLD_ALL_AFTER_LOAD) || loadFolding.equals(NodeBuilder.RESOURCES_ALWAYS_UNFOLD_ALL_AFTER_LOAD)) { return; } mapReader.getCurrentNodeTreeCreator().setHint(FOLDING_LOADED, Boolean.TRUE); } if (value.equals("true")) { node.setFolded(true); } } }); reader.addReadCompletionListener(new IReadCompletionListener() { private int foldAll(final NodeModel node, int nodeCount) { if (node.getChildCount() == 0) { return nodeCount; } if (nodeCount <= 0) { node.setFolded(true); } else{ nodeCount -= node.getChildCount(); } for (final NodeModel child : node.getChildren()) { nodeCount = foldAll(child, nodeCount); } return nodeCount; } public void readingCompleted(final NodeModel topNode, final Map<String, String> newIds) { if (!Mode.FILE.equals(mapReader.getCurrentNodeTreeCreator().getHint(Hint.MODE))) { return; } if (Boolean.TRUE.equals(mapReader.getCurrentNodeTreeCreator().getHint(NodeBuilder.FOLDING_LOADED))) { return; } final ResourceController resourceController = ResourceController.getResourceController(); final String loadFolding = resourceController.getProperty(NodeBuilder.RESOURCES_LOAD_FOLDING); if (loadFolding.equals(NodeBuilder.RESOURCES_ALWAYS_FOLD_ALL_AFTER_LOAD) || loadFolding.equals(NodeBuilder.RESOURCES_LOAD_FOLDING_FROM_MAP_DEFAULT_FOLD_ALL)) { int nodeCount = resourceController.getIntProperty(NodeBuilder.MAX_DISPLAYED_NODE_COUNT, 20); final List<NodeModel> children = topNode.getChildren(); nodeCount = nodeCount - 1 - children.size(); for (final NodeModel child : children) { nodeCount = foldAll(child, nodeCount); } } } }); final IAttributeHandler positionHandler = new IAttributeHandler() { public void setAttribute(final Object userObject, final String value) { final NodeModel node = (NodeModel) userObject; node.setLeft(value.equals("left")); } }; reader.addAttributeHandler(NodeBuilder.XML_NODE, "POSITION", positionHandler); reader.addAttributeHandler(NodeBuilder.XML_STYLENODE, "POSITION", positionHandler); reader.addAttributeHandler(NodeBuilder.XML_NODE, "ID", new IAttributeHandler() { public void setAttribute(final Object userObject, final String value) { final NodeModel node = (NodeModel) userObject; final String realId = getMap().generateNodeID(value); node.setID(realId); if (!realId.equals(value)) { mapReader.getCurrentNodeTreeCreator().substituteNodeID(value, realId); } } }); } /** */ public void registerBy(final ReadManager reader) { registerAttributeHandlers(reader); reader.addElementHandler(NodeBuilder.XML_NODE, this); reader.addElementHandler(NodeBuilder.XML_STYLENODE, this); } public void reset() { setMapChild(null); } public void setAttributes(final String tag, final Object node, final XMLElement attributes) { } private void setMapChild(final NodeModel mapChild) { mapReader.getCurrentNodeTreeCreator().setMapChild(mapChild); } }