/* * Copyright (c) 1998-2011 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source 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. * * Resin Open Source 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, or any warranty * of NON-INFRINGEMENT. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the * * Free Software Foundation, Inc. * 59 Temple Place, Suite 330 * Boston, MA 02111-1307 USA * * @author Emil Ong */ package com.caucho.xtpdoc; import com.caucho.config.Config; import com.caucho.vfs.Path; import javax.annotation.PostConstruct; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamWriter; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Locale; import java.util.logging.Logger; public class NavigationItem { private static final Logger log = Logger.getLogger(NavigationItem.class.getName()); private Navigation _navigation; private NavigationItem _parent; private String _uri; private String _refUri; private int _maxDepth = 3; private int _depth; private boolean _isRelative; private String _link; private String _ref; private String _title; private String _product; private Document _document; private String _description; private ContentItem _fullDescription; private boolean _atocDescend; private Navigation _child; private ArrayList<NavigationItem> _items = new ArrayList<NavigationItem>(); public NavigationItem(Navigation navigation, NavigationItem parent, int depth) { _navigation = navigation; _parent = parent; _document = navigation.getDocument(); _depth = depth; } public Navigation getNavigation() { return _navigation; } NavigationItem getParent() { return _parent; } void setParent(NavigationItem parent) { _parent = parent; } NavigationItem getPrevious() { NavigationItem parent = getParent(); if (parent != null) { int p = parent._items.indexOf(this); if (p > 0) { NavigationItem ptr = _parent._items.get(p - 1); while (ptr != null && ptr._items.size() > 0) { ptr = ptr._items.get(ptr._items.size() - 1); } return ptr; } else return parent; } return null; } NavigationItem getNext() { NavigationItem ptr = this; NavigationItem child = null; while (ptr != null) { int p = ptr._items.indexOf(child); if (p < 0 && ptr._items.size() > 0) return ptr._items.get(0); else if (p + 1 < ptr._items.size()) return ptr._items.get(p + 1); child = ptr; ptr = ptr.getParent(); } return null; } ArrayList<NavigationItem> getChildren() { return _items; } void addChildren(ArrayList<NavigationItem> children) { _items.addAll(children); } String getUri() { return _uri; } protected void initSummary() { if (_child != null || _fullDescription != null) return; Path rootPath = _document.getDocumentPath().getParent(); if (_uri != null) { Path linkPath = _document.getRealPath(_uri); if (linkPath.exists() && linkPath.getPath().endsWith(".xtp")) { Config config = new Config(); config.setEL(false); try { config.configure(_document, linkPath); if (_document.getHeader() != null) _fullDescription = _document.getHeader().getDescription(); else _fullDescription = new Description(_document); } catch (NullPointerException e) { log.info("error configuring " + linkPath + ": " + e); } catch (Exception e) { log.info("error configuring " + linkPath + ": " + e); } if (_atocDescend) { Path linkRoot = linkPath.getParent(); if (linkRoot.equals(_navigation.getRootPath().getParent())) return; Path subToc = linkPath.getParent().lookup("toc.xml"); if (subToc.exists()) { _child = new Navigation(_navigation, _uri, linkRoot, _depth + 1); try { config.configure(_child, subToc); } catch (Exception e) { log.info("Failed to configure " + subToc + ": " + e); } } else { log.info(subToc + " does not exist!"); } } } } } public void setATOCDescend(boolean atocDescend) { _atocDescend = atocDescend; } public void setLink(String link) { _link = link; _isRelative = (_link.indexOf(':') < 0); } public String getLink() { return _link; } public void setReference(String ref) { _ref = ref; } public String getReference() { return _ref; } public String getReferenceUri() { return _refUri; } public void setTitle(String title) { _title = title; } public String getTitle() { return _title; } public void setDescription(String description) { _description = description; } public void setProduct(String product) { _product = product; } public NavigationItem createItem() { NavigationItem item = new NavigationItem(_navigation, this, _depth + 1); _items.add(item); return item; } @PostConstruct public void init() { if (_isRelative) { _uri = _navigation.getUri() + _link; if (_ref != null) _refUri = _navigation.getUri() + _ref; } else { _uri = _link; if (_ref != null) _refUri = _ref; } _navigation.putItem(_uri, this); } public void writeHtml(XMLStreamWriter out, String path) throws XMLStreamException { initSummary(); out.writeStartElement("div"); out.writeAttribute("class", "atoc-top"); for (NavigationItem item : _items) item.writeHtmlImpl(out, path, 0, 0, 3); out.writeEndElement(); // div } public void writeHtml(XMLStreamWriter out, String path, int depth, int styleDepth, int maxDepth) throws XMLStreamException { if (depth + styleDepth <= 1) initSummary(); for (NavigationItem item : _items) item.writeHtmlImpl(out, path, depth, styleDepth, maxDepth); } protected void writeHtmlImpl(XMLStreamWriter out, String path, int depth, int styleDepth, int maxDepth) throws XMLStreamException { if (maxDepth <= depth) return; if (depth + styleDepth <= 1) initSummary(); if (_child != null && depth + 1 < maxDepth) _child.initSummary(); if (depth <= 1) { out.writeStartElement("h2"); out.writeAttribute("class", "section"); if (_link != null) { out.writeStartElement("a"); if (_isRelative) out.writeAttribute("href", path + _link); else out.writeAttribute("href", _link); out.writeCharacters(_title); out.writeEndElement(); // a } else out.writeCharacters(_title); out.writeEndElement(); // h2 } else { out.writeStartElement("div"); out.writeStartElement("b"); if (_link != null) { out.writeStartElement("a"); if (_isRelative) out.writeAttribute("href", path + _link); else out.writeAttribute("href", _link); out.writeCharacters(_title); out.writeEndElement(); // a if (_ref != null) { out.writeStartElement("span"); out.writeAttribute("class", "ref"); out.writeCharacters(" "); out.writeEntityRef("laquo"); out.writeStartElement("a"); if (_isRelative) out.writeAttribute("href", path + _ref); else out.writeAttribute("href", _ref); out.writeCharacters("ref"); out.writeEndElement(); // a out.writeEntityRef("raquo"); out.writeEndElement(); // span } } out.writeEndElement(); // b if (_fullDescription != null && depth + styleDepth <= 1) { } else if (_description != null && depth > 1) { out.writeCharacters(" - "); out.writeCharacters(_description); } out.writeEndElement(); // div } out.writeStartElement("div"); out.writeAttribute("class", "nav-item"); // XXX: brief/paragraph/none if (_fullDescription != null && depth + styleDepth <= 1) { _fullDescription.writeHtml(out); } if (_link != null) { int p = _link.lastIndexOf('/'); String tail; if (p >= 0) tail = path + _link.substring(0, p + 1); else tail = path; String depthString = (depth == 0) ? "top" : ("" + depth); boolean hasDL = false; if (_child != null || _items.size() > 0) { out.writeStartElement("div"); out.writeAttribute("class", "atoc-" + (depth + 1)); if (_child != null) _child.writeHtml(out, tail, depth + 1, styleDepth, maxDepth); else { for (NavigationItem item : _items) item.writeHtmlImpl(out, tail, depth + 1, styleDepth, maxDepth); } out.writeEndElement(); //div } } out.writeEndElement(); // div } public void writeLeftNav(XMLStreamWriter out) throws XMLStreamException { if (_parent != null) _parent.writeLeftNavPre(out, this, 1); writeLeftNavItem(out, this); if (_items.size() > 0) { out.writeStartElement("div"); out.writeAttribute("class", "leftnav"); for (NavigationItem item : _items) item.writeLeftNavNoParent(out, this); out.writeEndElement(); // div } if (_parent != null) _parent.writeLeftNavPost(out, this); } public int writeLeftNavPre(XMLStreamWriter out, NavigationItem caller, int padding) throws XMLStreamException { if (_parent != null) padding = _parent.writeLeftNavPre(out, this, padding); writeLeftNavItem(out, caller); if (_items.size() > 0) { out.writeStartElement("div"); out.writeAttribute("class", "leftnav"); for (NavigationItem item : _items) { if (item.getUri().equals(caller.getUri())) return padding + 1; item.writeLeftNavItem(out, caller); } return padding + 1; } else { return padding; } } public void writeLeftNavPost(XMLStreamWriter out, NavigationItem caller) throws XMLStreamException { if (_items.size() > 0) { boolean found = false; for (NavigationItem item : _items) { if (found) item.writeLeftNavItem(out, caller); if (item.getUri().equals(caller.getUri())) found = true; } out.writeEndElement(); // div } if (_parent != null) { _parent.writeLeftNavPost(out, this); } } public void writeLeftNavNoParent(XMLStreamWriter out, NavigationItem caller) throws XMLStreamException { writeLeftNavItem(out, caller); if (_items.size() > 0) { out.writeStartElement("div"); out.writeAttribute("class", "leftnav"); for (NavigationItem item : _items) item.writeLeftNavNoParent(out, this); out.writeEndElement(); // div } } private void writeLeftNavItem(XMLStreamWriter out, NavigationItem caller) throws XMLStreamException { out.writeStartElement("div"); if (caller != null && _uri.equals(caller.getUri())) { out.writeAttribute("class", "selected"); } else { out.writeAttribute("class", "not-selected"); } out.writeStartElement("a"); out.writeAttribute("href", _uri); out.writeAttribute("class", "leftnav"); out.writeCharacters(_title.toLowerCase(Locale.ENGLISH)); out.writeEndElement(); // a if (_refUri != null) { out.writeStartElement("span"); out.writeAttribute("class", "ref"); out.writeCharacters(" "); out.writeEntityRef("laquo"); out.writeStartElement("a"); out.writeAttribute("href", _refUri); out.writeAttribute("class", "leftnav"); out.writeCharacters("ref"); out.writeEndElement(); // a out.writeEntityRef("raquo"); out.writeEndElement(); // span } out.writeEndElement(); // div } public void writeLink(XMLStreamWriter out) throws XMLStreamException { out.writeStartElement("a"); out.writeAttribute("href", _uri); out.writeCharacters(_title.toLowerCase(Locale.ENGLISH)); out.writeEndElement(); // a } public void writeLaTeX(PrintWriter writer) throws IOException { } public String toString() { return getClass().getSimpleName() + "[" + getTitle() + "]"; } }