001: /*
002: * This file is part of PFIXCORE.
003: *
004: * PFIXCORE is free software; you can redistribute it and/or modify
005: * it under the terms of the GNU Lesser General Public License as published by
006: * the Free Software Foundation; either version 2 of the License, or
007: * (at your option) any later version.
008: *
009: * PFIXCORE is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012: * GNU Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public License
015: * along with PFIXCORE; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: *
018: */
019:
020: package de.schlund.pfixcore.workflow;
021:
022: import java.io.IOException;
023: import java.io.StringReader;
024: import java.util.ArrayList;
025: import java.util.HashMap;
026: import java.util.HashSet;
027: import java.util.List;
028: import java.util.Map;
029: import java.util.Set;
030:
031: import javax.xml.transform.TransformerConfigurationException;
032: import javax.xml.transform.TransformerException;
033: import javax.xml.transform.TransformerFactory;
034: import javax.xml.transform.dom.DOMResult;
035: import javax.xml.transform.sax.SAXTransformerFactory;
036: import javax.xml.transform.sax.TransformerHandler;
037:
038: import org.w3c.dom.Document;
039: import org.w3c.dom.Element;
040: import org.w3c.dom.Node;
041: import org.xml.sax.InputSource;
042: import org.xml.sax.SAXException;
043: import org.xml.sax.XMLReader;
044: import org.xml.sax.helpers.DefaultHandler;
045: import org.xml.sax.helpers.XMLReaderFactory;
046:
047: import de.schlund.pfixxml.config.CustomizationHandler;
048: import de.schlund.pfixxml.config.includes.FileIncludeEvent;
049: import de.schlund.pfixxml.config.includes.FileIncludeEventListener;
050: import de.schlund.pfixxml.config.includes.IncludesResolver;
051: import de.schlund.pfixxml.resources.FileResource;
052: import de.schlund.pfixxml.util.TransformerHandlerAdapter;
053: import de.schlund.pfixxml.util.XPath;
054: import de.schlund.pfixxml.util.Xml;
055: import de.schlund.pfixxml.util.XsltVersion;
056:
057: public class Navigation {
058: private NavigationElement pageroot = new NavigationElement(
059: "__NONE__", "__NONE__");
060: private Map<String, NavigationElement> pagetonavi;
061:
062: private Set<FileResource> fileDependencies = new HashSet<FileResource>();
063: private long loadTime = 0;
064:
065: private Element navigationXMLElement = null;
066:
067: public Navigation(FileResource navifile, XsltVersion xsltVersion)
068: throws IOException, SAXException, TransformerException,
069: TransformerConfigurationException {
070: loadTime = System.currentTimeMillis();
071: Document navitree = Xml.parseMutable(navifile);
072:
073: IncludesResolver iresolver = new IncludesResolver(null,
074: "config-include");
075: // Make sure list of dependencies only contains the file itself
076: fileDependencies.clear();
077: fileDependencies.add(navifile);
078: FileIncludeEventListener listener = new FileIncludeEventListener() {
079:
080: public void fileIncluded(FileIncludeEvent event) {
081: fileDependencies.add(event.getIncludedFile());
082: }
083:
084: };
085: iresolver.registerListener(listener);
086: iresolver.resolveIncludes(navitree);
087:
088: TransformerFactory tf = TransformerFactory.newInstance();
089: if (tf.getFeature(SAXTransformerFactory.FEATURE)) {
090: SAXTransformerFactory stf = (SAXTransformerFactory) tf;
091: TransformerHandler th = stf.newTransformerHandler();
092: DOMResult dr = new DOMResult();
093: th.setResult(dr);
094: DefaultHandler dh = new TransformerHandlerAdapter(th);
095: DefaultHandler ch = new CustomizationHandler(dh);
096: XMLReader xreader = XMLReaderFactory.createXMLReader();
097: xreader.setContentHandler(ch);
098: xreader.setDTDHandler(ch);
099: xreader.setEntityResolver(ch);
100: xreader.setErrorHandler(ch);
101: xreader.parse(new InputSource(new StringReader(Xml
102: .serialize(navitree, false, true))));
103: navitree = dr.getNode().getOwnerDocument();
104: if (navitree == null) {
105: if (dr.getNode() instanceof Document) {
106: navitree = (Document) dr.getNode();
107: } else {
108: throw new RuntimeException(
109: "XML result is not a Document though it should be");
110: }
111: }
112: } else {
113: throw new RuntimeException(
114: "TransformerFactory instance does not provide SAXTransformerFactory!");
115: }
116:
117: // We need a Saxon node here
118: navigationXMLElement = (Element) XPath.selectOne(Xml.parse(
119: xsltVersion, navitree), "/make/navigation");
120:
121: List<Node> nl = XPath.select(navitree, "/make/navigation/page");
122: pagetonavi = new HashMap<String, NavigationElement>();
123: recursePagetree(pageroot, nl);
124: }
125:
126: public boolean needsReload() {
127: for (FileResource file : fileDependencies) {
128: long lastModified = file.lastModified();
129: if (lastModified > loadTime) {
130: return true;
131: }
132: }
133: return false;
134: }
135:
136: public Element getNavigationXMLElement() {
137: return navigationXMLElement;
138: }
139:
140: private void recursePagetree(NavigationElement parent, List<Node> nl)
141: throws TransformerException {
142: for (int i = 0; i < nl.size(); i++) {
143: Element page = (Element) nl.get(i);
144: String name = page.getAttribute("name");
145: String handler = page.getAttribute("handler");
146:
147: NavigationElement elem = new NavigationElement(name,
148: handler);
149: pagetonavi.put(name, elem);
150: parent.addChild(elem);
151: List<Node> tmp = XPath.select(page, "./page");
152: if (tmp.size() > 0) {
153: recursePagetree(elem, tmp);
154: }
155: }
156: }
157:
158: public NavigationElement[] getNavigationElements() {
159: return pageroot.getChildren();
160: }
161:
162: public NavigationElement getNavigationElementForPageRequest(
163: PageRequest page) {
164: return pagetonavi.get(page.getRootName());
165: }
166:
167: public class NavigationElement {
168: private ArrayList<NavigationElement> children = new ArrayList<NavigationElement>();
169: private String name;
170: private String handler;
171:
172: public NavigationElement(String name, String handler) {
173: this .name = name;
174: this .handler = handler;
175: }
176:
177: public void addChild(NavigationElement elem) {
178: children.add(elem);
179: }
180:
181: public String getName() {
182: return name;
183: }
184:
185: public String getHandler() {
186: return handler;
187: }
188:
189: public boolean hasChildren() {
190: return !children.isEmpty();
191: }
192:
193: public NavigationElement[] getChildren() {
194: return children.toArray(new NavigationElement[] {});
195: }
196: } // NavigationElement
197: }
|