/***************************************************************************** * Web3d.org Copyright (c) 2001 * Java Source * * This source is licensed under the GNU LGPL v2.1 * Please read http://www.gnu.org/copyleft/lgpl.html for more information * * This software comes with the standard NO WARRANTY disclaimer for any * purpose. Use it at your own risk. If there's a problem you get to fix it. * ****************************************************************************/ // Standard library imports import org.j3d.ui.navigation.*; import java.awt.BorderLayout; import java.awt.Container; import java.io.File; import java.io.InputStream; import java.io.IOException; import java.net.MalformedURLException; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import javax.media.j3d.BranchGroup; import javax.media.j3d.Canvas3D; import javax.media.j3d.TransformGroup; import javax.media.j3d.View; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.Source; import javax.xml.transform.Result; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.sax.SAXResult; import javax.xml.transform.sax.SAXSource; import javax.xml.transform.stream.StreamSource; import javax.xml.transform.stream.StreamResult; import org.ietf.uri.*; import java.net.URL; // Application specific imports import org.web3d.vrml.sav.*; import org.web3d.vrml.nodes.*; import org.web3d.vrml.nodes.runtime.*; import org.web3d.vrml.nodes.loader.*; import org.web3d.vrml.renderer.j3d.input.*; import org.web3d.browser.BrowserCore; import org.web3d.vrml.lang.VRMLException; import org.web3d.vrml.lang.TypeConstants; import org.web3d.vrml.parser.VRMLParserFactory; import org.web3d.vrml.parser.FactoryConfigurationError; import org.web3d.vrml.renderer.common.input.LinkSelectionListener; import org.web3d.vrml.renderer.common.input.NavigationStateListener; import org.web3d.vrml.renderer.j3d.J3DSceneBuilderFactory; import org.web3d.vrml.renderer.j3d.browser.OverlayHandler; import org.web3d.vrml.renderer.j3d.browser.VRMLUniverse; import org.web3d.vrml.renderer.j3d.nodes.J3DVRMLNode; import org.web3d.vrml.renderer.j3d.nodes.J3DViewpointNodeType; import org.web3d.vrml.scripting.ScriptEngine; import org.web3d.vrml.scripting.jsai.VRML97ScriptEngine; import org.web3d.vrml.scripting.ecmascript.ECMAScriptEngine; import org.web3d.x3d.jaxp.X3DEntityResolver; import org.web3d.x3d.jaxp.X3DErrorHandler; import org.web3d.x3d.jaxp.X3DSAVAdapter; /** * A demonstration application that shows how to transform an XML file * into an X3D file and view the results. *
* * @author Alan Hudson * @version $Revision: 1.1.1.1 $ */ public class XSLTViewer extends DemoFrame implements ViewpointSelectionListener, LinkSelectionListener, OverlayHandler { /** Name of the property to set the lexical handler in the XMLReader */ private static final String LEXICAL_HANDLER_PROP = "http://xml.org/sax/properties/lexical-handler"; // Constants for the URN setup /** Set this to the install directory that UMEL uses */ private static final String UMEL_INSTALL_DIR = null; /** Set this to the install directory that GEOVRML uses */ private static final String GEOVRML_INSTALL_DIR = null; /** NSS prefix used by UMEL */ private static final String UMEL_PREFIX = "umel"; /** NSS prefix used by GeoVRML */ private static final String GEOVRML_PREFIX = "geovrml"; /** The universe to place our scene into */ private VRMLUniverse universe; /** The toolbar holding viewpoint information */ private ViewpointToolbar vpToolbar; /** The toolbar holding navigation information */ private NavigationToolbar navToolbar; /** Flag to indicate we are in the setup of the scene currently */ private boolean inSetup; /** Mapping of def'd Viewpoints to their real implementation */ private HashMap viewpointDefMap; /** The current viewpoint model */ private VRMLViewpointNodeType currentViewpoint; /** Place for error messages to go */ private ConsoleWindow console; /** Global clock */ private VRMLClock clock; /** World load manager to help us load files */ private WorldLoaderManager worldLoader; /** The global canvas for rendering */ private Canvas3D canvas; J3DSceneBuilderFactory builder_fac; private static boolean debug = false; private static String xsltFile; /** The factory to generate SAX parser instances */ private SAXParserFactory parserFactory; /** Common entity resolver instance */ private X3DEntityResolver resolver; /** SAX Error handler for the system */ private X3DErrorHandler x3dErrors; /** * Create an instance of the demo class. */ public XSLTViewer() { super("XSLTViewer"); JPopupMenu.setDefaultLightWeightPopupEnabled(false); viewpointDefMap = new HashMap(); builder_fac = new J3DSceneBuilderFactory(false, true, true, true, true, true, true); VRMLParserFactory parser_fac = null; try { parser_fac = VRMLParserFactory.newVRMLParserFactory(); } catch(FactoryConfigurationError fce) { throw new RuntimeException("Failed to load factory"); } Container content_pane = getContentPane(); JPanel p1 = new JPanel(new BorderLayout()); content_pane.add(p1, BorderLayout.CENTER); console = new ConsoleWindow(); // We also need a canvas to display stuff with and a universe to set // the content in. canvas = new Canvas3D(gfxConfig); View view = new View(); view.setMinimumFrameCycleTime(30); view.addCanvas3D(canvas); /* Uncomment this section and comment out the line below if you want to use Event handling coming directly from the canvas rather than using the Java3D behaviour to do so. AWTListenerEventBuffer i_buf = new AWTListenerEventBuffer(); canvas.addMouseListener(i_buf); canvas.addMouseMotionListener(i_buf); canvas.addKeyListener(i_buf); */ UserInputBehavior i_buf = new UserInputBehavior(); // ExternalLoadManager lm = new SimpleLoadManager(); ExternalLoadManager load_manager = new MemCacheLoadManager(); ScriptLoader script_loader = new DefaultScriptLoader(); ScriptManager script_manager = new DefaultScriptManager(); script_manager.setScriptLoader(script_loader); FrameStateManager state_manager = new GeneralisedFrameStateManager(); J3DSensorManager sensor_manager = new DefaultSensorManager(); sensor_manager.setInputBuffer(i_buf); RouteManager route_manager = new DefaultRouteManager(); // route_manager.setRouterFactory(new SimpleRouterFactory()); route_manager.setRouterFactory(new ListsRouterFactory()); worldLoader = new DefaultWorldLoaderManager(state_manager); worldLoader.setErrorReporter(console); worldLoader.registerBuilderFactory(BrowserCore.JAVA3D_RENDERER, builder_fac); worldLoader.registerParserFactory(BrowserCore.JAVA3D_RENDERER, parser_fac); EventModelEvaluator event_model = new GeneralisedEventModelEvaluator(); event_model.initialize(script_manager, route_manager, sensor_manager, state_manager, load_manager); event_model.setErrorReporter(console); universe = new VRMLUniverse(event_model, this); universe.setPrimaryView(view); universe.setLinkSelectionListener(this); // If using the canvas AWTEventListener handler then comment out // these lines. BranchGroup extra_behaviors = new BranchGroup(); extra_behaviors.addChild(i_buf); universe.addSceneGraphExtras(extra_behaviors); clock = universe.getVRMLClock(); ScriptEngine jsai = new VRML97ScriptEngine(universe, route_manager, worldLoader); jsai.setErrorReporter(console); ScriptEngine ecma = new ECMAScriptEngine(universe, route_manager, worldLoader); ecma.setErrorReporter(console); script_loader.registerScriptingEngine(jsai); script_loader.registerScriptingEngine(ecma); p1.add(canvas, BorderLayout.CENTER); JPanel p2 = new JPanel(new BorderLayout()); p1.add(p2, BorderLayout.SOUTH); navToolbar = new NavigationToolbar(); p2.add(navToolbar, BorderLayout.WEST); vpToolbar = new ViewpointToolbar(); vpToolbar.setEnabled(false); vpToolbar.setViewpointSelectionListener(this); p2.add(vpToolbar, BorderLayout.CENTER); // universe.setNavigationStateListener(navToolbar); universe.setLinkSelectionListener(this); setupProperties(universe, worldLoader); console.setVisible(true); DownloadProgressListener dl_list = new DownloadProgressListener(statusLabel, console); ResourceConnection.addGlobalProgressListener(dl_list); } //---------------------------------------------------------- // Methods required by the OverlayHandler interface. //---------------------------------------------------------- /** * Fetch the canvas that will be responsible for having the overlays * composited on them. * * @return The canvas instance to use */ public Canvas3D getPrimaryCanvas() { return canvas; } //---------------------------------------------------------- // Methods required by the LinkSelectionListener interface. //---------------------------------------------------------- /** * Invoked when a link node has been activated. This is the node that has * been selected. * * @param node The selected node */ public void linkSelected(VRMLLinkNodeType node) { String[] url_list = node.getUrl(); boolean success = false; for(int i = 0; i < url_list.length; i++) { if(url_list[i].charAt(0) == '#') { // move to the viewpoint. String def_name = url_list[i].substring(1); VRMLViewpointNodeType vp = (VRMLViewpointNodeType)viewpointDefMap.get(def_name); if(vp != null) { double time = clock.getTime(); if(currentViewpoint != null) currentViewpoint.setBind(false, true, time); vp.setBind(true, true, time); currentViewpoint = vp; } else { statusLabel.setText("Unknown Viewpoint " + def_name); console.warningReport("Unknown Viewpoint " + def_name, null); } } else { // load the world. try { URL url = new URL(url_list[i]); InputSource is = new InputSource(url); if(success = load(is)) break; } catch(MalformedURLException mue) { statusLabel.setText("Invalid URL"); console.warningReport("Invalid URL: " + url_list[i], mue); } } } if(!success) console.errorReport("No valid URLs were found", null); } //---------------------------------------------------------- // Methods required by the ViewpointSelectionListener interface. //---------------------------------------------------------- /** * A new viewpoint has been selected and this is it. Move to this viewpoint * location according to the requested means. * * @param vp The new viewpoint to use */ public void viewpointSelected(ViewpointData vp) { if(inSetup) return; double time = clock.getTime(); if(currentViewpoint != null) currentViewpoint.setBind(false, true, time); VRMLViewpointNodeType vp_node = (VRMLViewpointNodeType)vp.userData; vp_node.setBind(true, true, time); currentViewpoint = vp_node; } //---------------------------------------------------------- // Implmentation of base class abstract methods //---------------------------------------------------------- /** * Go to the named URL location. No checking is done other than to make * sure it is a valid URL. * * @param url The URL to open */ public void gotoLocation(URL url) { InputSource is = new InputSource(url); load(is); } /** * Load the named file. The file is checked to make sure that it exists * before calling this method. * * @param file The file to load */ public void gotoLocation(File file) { InputSource is = new InputSource(file); load(is); } protected void setWarning(String msg) { statusLabel.setText(msg); console.warningReport(msg, null); } protected void setError(String msg) { statusLabel.setText(msg); console.errorReport(msg, null); } //---------------------------------------------------------- // Local convenience methods //---------------------------------------------------------- /** * Do all the parsing work. Convenience method for all to call internally * * @param is The inputsource for this reader * @return true if the world loaded correctly */ private boolean load(InputSource is) { inSetup = true; boolean ret_val = false; VRMLScene parsed_scene = null; try { SceneBuilder sb = builder_fac.createBuilder(); X3DSAVAdapter adap = new X3DSAVAdapter(); // Need a better way todo this String path = System.getProperty("user.dir"); path = "file://" + path.substring(3); adap.setLoadState(path, true); try { parserFactory = SAXParserFactory.newInstance(); } catch(javax.xml.parsers.FactoryConfigurationError fce) { throw new FactoryConfigurationError("No SAX parser defined"); } x3dErrors = new X3DErrorHandler(); resolver = new X3DEntityResolver(); parserFactory.setValidating(false); parserFactory.setNamespaceAware(true); org.xml.sax.XMLReader reader = null; try { SAXParser parser = parserFactory.newSAXParser(); reader = parser.getXMLReader(); reader.setContentHandler(adap); reader.setProperty(LEXICAL_HANDLER_PROP, adap); reader.setErrorHandler(x3dErrors); reader.setEntityResolver(resolver); } catch(Exception e) { throw new IOException("Unable to configure factory as required"); } // Convert our InputSource, to their InputSource.... org.xml.sax.InputSource xis = new org.xml.sax.InputSource(); xis.setCharacterStream(is.getCharacterStream()); xis.setEncoding(is.getEncoding()); Source xmlSource = new SAXSource(reader,xis); File transform = new File(xsltFile); Source xsltSource = new StreamSource(transform); Result outres=null; if (debug) outres = new StreamResult(System.out); SAXResult result = new SAXResult(adap); adap.setContentHandler(sb); adap.setProtoHandler(sb); adap.setRouteHandler(sb); adap.setScriptHandler(sb); // create an instance of TransformerFactory TransformerFactory transFact = TransformerFactory.newInstance( ); Transformer trans = transFact.newTransformer(xsltSource); if (!debug) System.out.println("Transforming input to X3D"); if (debug) { trans.transform(xmlSource, outres); System.exit(0); } else trans.transform(xmlSource, result); if (!debug) System.out.println("Transformation complete"); parsed_scene = sb.getScene(); } catch(Exception e) { System.out.println("Exception in transforming file: " + e.getMessage()); e.printStackTrace(); } if (parsed_scene == null) return false; universe.setScene(parsed_scene); ret_val = true; // Grab the list of viewpoints and place them into the toolbar. ArrayList vp_list = parsed_scene.getByPrimaryType(TypeConstants.ViewpointNodeType); if(vp_list.size() == 0) { vpToolbar.setEnabled(false); return ret_val; } else { vpToolbar.setEnabled(true); } VRMLViewpointNodeType active_vp = universe.getViewpoint(); currentViewpoint = active_vp; ViewpointData active_data = null; J3DVRMLNode node; ViewpointData[] data = new ViewpointData[vp_list.size()]; int count = 0; String desc; TransformGroup tg; int size = vp_list.size(); for(int i = 0; i < size; i++) { node = (J3DVRMLNode)vp_list.get(i); if(node.getPrimaryType() == TypeConstants.ProtoInstance) node = (J3DVRMLNode)((VRMLProtoInstance)node).getImplementationNode(); desc = ((VRMLViewpointNodeType)node).getDescription(); if((desc == null) || (desc.length() == 0)) { desc = "Viewpoint " + count; } tg = ((J3DViewpointNodeType)node).getPlatformGroup(); data[count] = new ViewpointData(desc, count, tg); data[count].userData = node; if(node == active_vp) active_data = data[count]; count++; } vpToolbar.setViewpoints(data); if(active_data != null) vpToolbar.selectViewpoint(active_data); // Finally set up the viewpoint def name list. Have to start from // the list of DEF names as the Viewpoint nodes don't store the DEF // name locally. viewpointDefMap.clear(); Map def_map = parsed_scene.getDEFNodes(); Iterator itr = def_map.keySet().iterator(); while(itr.hasNext()) { String key = (String)itr.next(); Object vp = def_map.get(key); if(vp instanceof VRMLViewpointNodeType) viewpointDefMap.put(key, vp); } inSetup = false; return ret_val; } /** * Create an instance of this class and run it. The single argument, if * supplied is the name of the file to load initially. If not supplied it * will start with a blank document. * * @param argv The list of arguments for this application. */ public static void main(String[] args) { XSLTViewer viewer = new XSLTViewer(); String filename = null; boolean dispUsage=true; viewer.show(); if (args.length > 0) { for(int i=0; i < args.length; i++) { if (args[i].equals("-debug")) { debug = true; } else { if (xsltFile == null) { xsltFile = args[i]; dispUsage=false; } else { filename = args[i]; if (filename.startsWith("http://")) { try { URL url = new URL(filename); viewer.gotoLocation(url); } catch(MalformedURLException mfe) { System.out.println("Malformed URL: " + filename); } } else { File fil = new File(filename); viewer.gotoLocation(fil); } } } } } if (dispUsage) { System.out.println("Usage XSLTViewer [OPTION] TRANSFORMER [SOURCE]"); System.out.println("\n -debug Display the transformed document instead of viewing in 3D"); System.exit(0); } } }