KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > outerj > daisy > navigation > impl > NavigationFactory


1 /*
2  * Copyright 2004 Outerthought bvba and Schaubroeck nv
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.outerj.daisy.navigation.impl;
17
18 import org.apache.xmlbeans.XmlObject;
19 import org.apache.xmlbeans.SchemaType;
20 import org.apache.xmlbeans.XmlOptions;
21 import org.outerj.daisy.navigation.NavigationException;
22 import org.outerj.daisy.navigation.NavigationVersionMode;
23 import org.outerj.daisy.repository.*;
24 import org.outerj.daisy.xmlutil.LocalSAXParserFactory;
25
26 import javax.xml.namespace.QName JavaDoc;
27 import java.io.StringReader JavaDoc;
28 import java.io.InputStream JavaDoc;
29 import java.io.BufferedInputStream JavaDoc;
30 import java.util.Map JavaDoc;
31 import java.util.HashMap JavaDoc;
32 import java.util.Stack JavaDoc;
33 import java.lang.reflect.InvocationTargetException JavaDoc;
34 import java.lang.reflect.Constructor JavaDoc;
35
36 /**
37  * Builds a tree of navigation {Node}s based on an XML description.
38  *
39  * <p>This is a use-once, non-reusable (and non-threadsafe) class.
40  */

41 public class NavigationFactory {
42     private static String JavaDoc[] PART_NAMES = {"NavigationDescription", "BookDefinitionDescription"};
43
44     private static Map JavaDoc NAVIGATION_BUILDERS;
45     static {
46         NAVIGATION_BUILDERS = new HashMap JavaDoc();
47         try {
48             NAVIGATION_BUILDERS.put(new QName JavaDoc("http://outerx.org/daisy/1.0#navigationspec", "navigationTree"), DefaultNavigationBuilder.class.getConstructor(new Class JavaDoc[0]));
49             NAVIGATION_BUILDERS.put(new QName JavaDoc("http://outerx.org/daisy/1.0#bookdef", "book"), BookNavigationBuilder.class.getConstructor(new Class JavaDoc[0]));
50         } catch (Exception JavaDoc e) {
51             throw new RuntimeException JavaDoc("Error initializing navigation builders map.", e);
52         }
53     }
54
55     static interface NavigationBuilder {
56         Node build(XmlObject xmlObject, long branchId, long languageId, NavigationVersionMode versionMode,
57                 CommonNavigationManager.Context context, Counter counter, Stack JavaDoc importStack) throws RepositoryException;
58
59         SchemaType getSchemaType();
60     }
61
62     /**
63      * Builds a navigation tree from an XML navigation description provided as a string argument.
64      */

65     public static Node build(String JavaDoc navigationXml, long branchId, long languageId, NavigationVersionMode versionMode,
66             CommonNavigationManager.Context context, Counter counter, Stack JavaDoc importStack) throws NavigationException {
67         try {
68             XmlOptions xmlOptions = new XmlOptions().setLoadUseXMLReader(LocalSAXParserFactory.newXmlReader());
69             XmlObject navTreeXml = XmlObject.Factory.parse(new StringReader JavaDoc(navigationXml), xmlOptions);
70             return build(navTreeXml, branchId, languageId, versionMode, context, counter, importStack);
71         } catch (Throwable JavaDoc e) {
72             throw new NavigationException("Error building navigation tree.", e);
73         }
74     }
75
76     public static Node build(VariantKey navigationDoc, NavigationVersionMode versionMode,
77             CommonNavigationManager.Context context, Counter counter, Stack JavaDoc importStack) throws NavigationException {
78         try {
79             Document document = context.getRepository().getDocument(navigationDoc.getDocumentId(), navigationDoc.getBranchId(), navigationDoc.getLanguageId(), false);
80
81             Version version;
82             if (versionMode == NavigationVersionMode.LIVE) {
83                 version = document.getLiveVersion();
84                 if (version == null)
85                     throw new NavigationException(navigationDoc + " does not have a live version.");
86             } else if (versionMode == NavigationVersionMode.LAST) {
87                 version = document.getLastVersion();
88             } else {
89                 throw new NavigationException("Unexepected NavigationVersionMode: " + versionMode);
90             }
91
92             String JavaDoc partName = null;
93             for (int i = 0; i < PART_NAMES.length; i++) {
94                 if (version.hasPart(PART_NAMES[i])) {
95                     partName = PART_NAMES[i];
96                     break;
97                 }
98             }
99
100             if (partName == null)
101                 throw new NavigationException(navigationDoc + " (version mode: " + versionMode + ") does not contain a part from which a navigation tree can be build.");
102
103             Part part = version.getPart(partName);
104
105             XmlObject xmlObject;
106             InputStream JavaDoc is = part.getDataStream();
107             try {
108                 XmlOptions xmlOptions = new XmlOptions().setLoadUseXMLReader(LocalSAXParserFactory.newXmlReader());
109                 xmlObject = XmlObject.Factory.parse(new BufferedInputStream JavaDoc(is), xmlOptions);
110             } finally {
111                 is.close();
112             }
113
114             return build(xmlObject, navigationDoc.getBranchId(), navigationDoc.getLanguageId(), versionMode, context, counter, importStack);
115         } catch (Throwable JavaDoc e) {
116             throw new NavigationException("Error building navigation tree.", e);
117         }
118     }
119
120     private static Node build(XmlObject xmlObject, long branchId, long languageId, NavigationVersionMode versionMode,
121             CommonNavigationManager.Context context, Counter counter, Stack JavaDoc importStack) throws NavigationException {
122         // XMLBeans type inference doesn't seem to work, so do our own detection based on the root element
123
XmlObject[] result = xmlObject.selectPath("*");
124         QName JavaDoc rootEl = result[0].newCursor().getName();
125
126         Constructor JavaDoc buildConstructor = (Constructor JavaDoc)NAVIGATION_BUILDERS.get(rootEl);
127         if (buildConstructor == null) {
128             throw new NavigationException("Provided XML does not contain a recognized navigation format.");
129         }
130
131         NavigationBuilder navigationBuilder;
132         try {
133             navigationBuilder = (NavigationBuilder)buildConstructor.newInstance(new Object JavaDoc[0]);
134         } catch (IllegalAccessException JavaDoc e) {
135             throw new NavigationException("Unexpected IllegalAccessException.", e);
136         } catch (InvocationTargetException JavaDoc e) {
137             throw new NavigationException("Error building navigation tree.", e.getTargetException());
138         } catch (InstantiationException JavaDoc e) {
139             throw new NavigationException("Error instantiating navigation tree builder.", e);
140         }
141
142         XmlObject typedXmlObject = xmlObject.changeType(navigationBuilder.getSchemaType());
143         if (!typedXmlObject.validate()) {
144             throw new NavigationException("Provided XML does is not valid.");
145         }
146
147         try {
148             return navigationBuilder.build(typedXmlObject, branchId, languageId, versionMode, context, counter, importStack);
149         } catch (RepositoryException e) {
150             throw new NavigationException("Error building navigation tree.", e);
151         }
152     }
153 }
154
Popular Tags