1 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 ; 27 import java.io.StringReader ; 28 import java.io.InputStream ; 29 import java.io.BufferedInputStream ; 30 import java.util.Map ; 31 import java.util.HashMap ; 32 import java.util.Stack ; 33 import java.lang.reflect.InvocationTargetException ; 34 import java.lang.reflect.Constructor ; 35 36 41 public class NavigationFactory { 42 private static String [] PART_NAMES = {"NavigationDescription", "BookDefinitionDescription"}; 43 44 private static Map NAVIGATION_BUILDERS; 45 static { 46 NAVIGATION_BUILDERS = new HashMap (); 47 try { 48 NAVIGATION_BUILDERS.put(new QName ("http://outerx.org/daisy/1.0#navigationspec", "navigationTree"), DefaultNavigationBuilder.class.getConstructor(new Class [0])); 49 NAVIGATION_BUILDERS.put(new QName ("http://outerx.org/daisy/1.0#bookdef", "book"), BookNavigationBuilder.class.getConstructor(new Class [0])); 50 } catch (Exception e) { 51 throw new RuntimeException ("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 importStack) throws RepositoryException; 58 59 SchemaType getSchemaType(); 60 } 61 62 65 public static Node build(String navigationXml, long branchId, long languageId, NavigationVersionMode versionMode, 66 CommonNavigationManager.Context context, Counter counter, Stack importStack) throws NavigationException { 67 try { 68 XmlOptions xmlOptions = new XmlOptions().setLoadUseXMLReader(LocalSAXParserFactory.newXmlReader()); 69 XmlObject navTreeXml = XmlObject.Factory.parse(new StringReader (navigationXml), xmlOptions); 70 return build(navTreeXml, branchId, languageId, versionMode, context, counter, importStack); 71 } catch (Throwable 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 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 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 is = part.getDataStream(); 107 try { 108 XmlOptions xmlOptions = new XmlOptions().setLoadUseXMLReader(LocalSAXParserFactory.newXmlReader()); 109 xmlObject = XmlObject.Factory.parse(new BufferedInputStream (is), xmlOptions); 110 } finally { 111 is.close(); 112 } 113 114 return build(xmlObject, navigationDoc.getBranchId(), navigationDoc.getLanguageId(), versionMode, context, counter, importStack); 115 } catch (Throwable 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 importStack) throws NavigationException { 122 XmlObject[] result = xmlObject.selectPath("*"); 124 QName rootEl = result[0].newCursor().getName(); 125 126 Constructor buildConstructor = (Constructor )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 [0]); 134 } catch (IllegalAccessException e) { 135 throw new NavigationException("Unexpected IllegalAccessException.", e); 136 } catch (InvocationTargetException e) { 137 throw new NavigationException("Error building navigation tree.", e.getTargetException()); 138 } catch (InstantiationException 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 |