📄 symboltable.java
字号:
/* * $RCSfile: SymbolTable.java,v $ * * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed, licensed or * intended for use in the design, construction, operation or * maintenance of any nuclear facility. * * $Revision: 1.5 $ * $Date: 2007/02/09 17:20:29 $ * $State: Exp $ */package com.sun.j3d.utils.scenegraph.io.retained;import java.io.IOException;import java.io.DataOutput;import java.io.DataInput;import java.util.HashMap;import java.util.ArrayList;import java.util.ListIterator;import java.util.LinkedList;import java.util.Iterator;import java.util.HashSet;import java.util.Collection;import java.util.Stack;import javax.media.j3d.SceneGraphObject;import com.sun.j3d.utils.scenegraph.io.state.javax.media.j3d.SceneGraphObjectState;import com.sun.j3d.utils.scenegraph.io.state.javax.media.j3d.NullSceneGraphObjectState;import com.sun.j3d.utils.scenegraph.io.state.javax.media.j3d.NodeComponentState;import com.sun.j3d.utils.scenegraph.io.NamedObjectException;import com.sun.j3d.utils.scenegraph.io.ObjectNotLoadedException;import com.sun.j3d.utils.scenegraph.io.SceneGraphObjectReferenceControl;/** * SymbolTable class for SceneGraph I/O. */public class SymbolTable extends java.lang.Object implements SceneGraphObjectReferenceControl { private int nodeID = 1; // ID of zero represents null private HashMap j3dNodeIndex; // Index by SceneGraphObject private ArrayList nodeIDIndex; // Index by NodeID of Nodes private HashMap danglingReferences; // Java3D objects without a current State object private Stack unsavedNodeComponentsStack; private LinkedList sharedNodes; // Nodes and NodeComponents referenced more than once private HashMap namedObjects; private ArrayList branchGraphs; // Root of each branch graph private ArrayList branchGraphDependencies; // Dependencies between the branchgraphs // For a graph branchGraphDep[graph] will contain a set of all nodes (in other graphs) on which the graph is dependent private Controller control; private int currentBranchGraphID = -1; // ID's start at 0, -1 is null, -2 is during read, -3 is dangling private int nextBranchGraphID = 0; /** Creates new SymbolTable */ public SymbolTable( Controller control ) { this.control = control; j3dNodeIndex = new HashMap(); danglingReferences = new HashMap(); nodeIDIndex = new ArrayList(); nodeIDIndex.add( null ); // Element zero is null sharedNodes = new LinkedList(); namedObjects = new HashMap(); branchGraphs = new ArrayList(); branchGraphDependencies = new ArrayList(); unsavedNodeComponentsStack = new Stack(); } /** * At this stage their should be no dangling references * */ private void checkforDanglingReferences() { ListIterator list = sharedNodes.listIterator(); while(list.hasNext()) { SymbolTableData data = (SymbolTableData)list.next(); if (data.branchGraphID==-3) { System.err.println("Warning : node "+data.j3dNode+" is referenced but is not attached to a BranchGraph"); System.err.println("Setting reference to null. This scene may not look correct when loaded"); } } } /** * Remove dependencies on objects which are not attached to a * branchgraph */ private void removeNullDependencies( HashSet set ) { Iterator it = set.iterator(); while( it.hasNext() ) { SymbolTableData symbol = (SymbolTableData)it.next(); if (symbol.branchGraphID==-3) it.remove(); } } public void writeTable( DataOutput out ) throws IOException { // At this stage their should be no dangling references checkforDanglingReferences(); ListIterator list = sharedNodes.listIterator(); out.writeInt( sharedNodes.size() ); out.writeInt( nodeID ); while(list.hasNext()) { SymbolTableData data = (SymbolTableData)list.next(); data.writeObject( out ); } // Write Named objects String[] names = getNames(); out.writeInt( names.length ); for(int i=0; i<names.length; i++) { out.writeUTF( names[i] ); SceneGraphObject node = (SceneGraphObject)namedObjects.get(names[i]); SymbolTableData symbol = getSymbol( node ); if (symbol!=null) out.writeInt( symbol.nodeID ); else out.writeInt( 0 ); // Null } // Write BranchGraph roots out.writeInt( branchGraphs.size() ); for(int i=0; i<branchGraphs.size(); i++) ((SymbolTableData)branchGraphs.get(i)).writeObject( out ); for(int i=0; i<branchGraphDependencies.size(); i++) { HashSet set = (HashSet)branchGraphDependencies.get( i ); if (set==null) { out.writeInt( 0 ); } else { removeNullDependencies( set ); out.writeInt( set.size() ); Iterator it = set.iterator(); while( it.hasNext() ) { SymbolTableData symbol = (SymbolTableData)it.next(); out.writeInt( symbol.nodeID ); } } } } /** * Read and store the entire symbol table * * @param streamRead - true if reading from a Stream in which case only the * branchGraphs and named objects are read. */ public void readTable( java.io.DataInput in, boolean streamRead ) throws IOException { int size = in.readInt(); nodeID = in.readInt(); nodeIDIndexEnsureCapacity( nodeID ); for(int i=0; i<size; i++) { SymbolTableData symbol = new SymbolTableData(0,null,null,-1); symbol.readObject( in ); // If we are loading from a stream then the NodeComponents have // already been loaded and their symbols created. Therefore // the symbols loaded here are discarded. if (!streamRead) { sharedNodes.add( symbol ); nodeIDIndex.set( symbol.nodeID, symbol ); } } // Read Named objects size = in.readInt(); for(int j=0; j<size; j++) { String name = in.readUTF(); int id = in.readInt(); namedObjects.put( name, new Integer(id) ); } size = in.readInt(); //System.out.println("Symbol table BranchGraph size "+size ); for(int i=0; i<size; i++) branchGraphs.add( null); // Read each branchgraph symbol and check that the symbol is not // already in the symbol table. for(int j=0; j<size; j++) { SymbolTableData tmp = new SymbolTableData(0,null,null,-1); tmp.readObject( in ); SymbolTableData symbol = getSymbol( tmp.nodeID ); if (symbol==null) { symbol = tmp; if (symbol.referenceCount>1) sharedNodes.add( symbol ); nodeIDIndex.set( symbol.nodeID, symbol ); } branchGraphs.set( j, symbol ); } for(int i=0; i<size; i++) { int setSize = in.readInt(); if (setSize==0) branchGraphDependencies.add( null ); else { HashSet set = new HashSet(); branchGraphDependencies.add( set ); for( int j=0; j<setSize; j++) { set.add( getSymbol(in.readInt())); } } } } /** * Mark the node referenced by this Symbol as a branch graph root * *The filePointer is the position of the BranchGraph in the file, this *is not the same as the BranchGroups position due to the extra data stored *for a graph. */ public void setBranchGraphRoot( SymbolTableData symbol, long filePointer ) { if (symbol.branchGraphID<0 ) { symbol.branchGraphID = nextBranchGraphID++; } currentBranchGraphID = symbol.branchGraphID; for(int i=branchGraphs.size(); i<currentBranchGraphID+1; i++) { branchGraphs.add( null); branchGraphDependencies.add( null ); } branchGraphs.set( currentBranchGraphID, symbol ); symbol.branchGraphFilePointer = filePointer; } public SymbolTableData getBranchGraphRoot( int graphID ) { //System.out.println("BranchGraph root "+graphID+" "+(SymbolTableData)branchGraphs.get(graphID) ); return (SymbolTableData)branchGraphs.get(graphID); } /** * Set the branchGraphID in the symbol to the current branch graph ID */ public void setBranchGraphID( SymbolTableData symbol ) { symbol.branchGraphID = currentBranchGraphID; } /** * Return an array of each BranchGraph on which graphID is dependent for * closure of the graph * * Only Nodes (not node components) cause dependencies * * If there are no dependencies int[0] is returned */ public int[] getBranchGraphDependencies( int graphID ) { HashSet set = (HashSet)branchGraphDependencies.get(graphID); if (set==null) return new int[0]; int[] ret = new int[ set.size() ]; Iterator it = set.iterator(); int i=0; while( it.hasNext() ) ret[i++] = ((SymbolTableData)it.next()).branchGraphID; return ret; } /** * Return true if the graph is dependent on nodes in * other graphs * * Only Nodes (not node components) cause dependencies * */ public boolean branchGraphHasDependencies( int graphID ) { HashSet set = (HashSet)branchGraphDependencies.get(graphID); if (set==null || set.size()==0) return false; else return true; } public int getBranchGraphCount() { return branchGraphs.size(); } public long getBranchGraphFilePosition( int graphID ) { SymbolTableData symbol = (SymbolTableData)branchGraphs.get( graphID ); return symbol.branchGraphFilePointer; } /** * Create a new symbol and provide a new nodeID * This is used during the save process */ public SymbolTableData createSymbol( SceneGraphObject node ) { // TODO : Remove this get, it's here to provide debug consistancy check SymbolTableData data = (SymbolTableData)j3dNodeIndex.get( node ); SymbolTableData dangling = (SymbolTableData)danglingReferences.get( node ); //System.out.println("Checking for dangling "+dangling+" "+node); if (dangling!=null) { data = dangling; data.branchGraphID = currentBranchGraphID; danglingReferences.remove( dangling ); //System.out.println("Updating dangling ref count"); // TODO - remove } else if (data==null) { data = new SymbolTableData( nodeID++, node, null, currentBranchGraphID ); j3dNodeIndex.put( node, data ); nodeIDIndex.add( data ); } else if (data.j3dNode instanceof javax.media.j3d.Node) { throw new RuntimeException( "Object already in Symbol table "+ node ); } return data; } /** * Create a new symbol using the specified nodeID * This is used during the load process. */ public SymbolTableData createSymbol( SceneGraphObjectState state, SceneGraphObject node, int nodeID ) { // TODO : Remove this get, it's here to provide debug consistancy check SymbolTableData data = (SymbolTableData)j3dNodeIndex.get( node ); if (data==null) { nodeIDIndexEnsureCapacity( nodeID ); data = (SymbolTableData)nodeIDIndex.get( nodeID ); if (data==null) { data = new SymbolTableData( nodeID, node, state, -2 ); j3dNodeIndex.put( node, data ); nodeIDIndex.set( data.getNodeID(), data ); } else if (data.getJ3dNode()==null) { // Only use state and node if data.j3dNode = node; // this is the first instantiation data.nodeState = state; // of the node j3dNodeIndex.put( node, data ); } } else throw new SGIORuntimeException( "Object already in Symbol table "); return data; } private void nodeIDIndexEnsureCapacity( int size ) { nodeIDIndex.ensureCapacity( size ); int adjust = size - nodeIDIndex.size(); for(int i=0; i<=adjust; i++) nodeIDIndex.add( null ); } /** * Create or return the SymbolTableData for a node which does not * necessary have a State object yet * */ private SymbolTableData createDanglingSymbol( SceneGraphObject node ) { SymbolTableData data = (SymbolTableData)j3dNodeIndex.get( node ); if (data==null) { data = new SymbolTableData( nodeID++, node, null, -3 ); j3dNodeIndex.put( node, data ); nodeIDIndex.add( data ); danglingReferences.put( node, data ); } else if ( data.nodeState==null) { if (data.referenceCount==1) sharedNodes.add( data ); data.referenceCount++; } else throw new SGIORuntimeException( "Object already in Symbol table "); return data; } private SymbolTableData createNodeComponentSymbol( SceneGraphObject node ) { SymbolTableData symbol = new SymbolTableData( nodeID++, node, null, currentBranchGraphID ); symbol.isNodeComponent = true; j3dNodeIndex.put( node, symbol ); nodeIDIndex.add( symbol ); ((LinkedList)unsavedNodeComponentsStack.peek()).add( symbol ); control.createState( symbol );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -