All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.j3d.utils.scenegraph.io.retained.SymbolTable Maven / Gradle / Ivy

The newest version!
/*
 * 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.
 *
 */

package com.sun.j3d.utils.scenegraph.io.retained;

import java.io.DataOutput;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.ListIterator;
import java.util.Stack;

import javax.media.j3d.SceneGraphObject;

import com.sun.j3d.utils.scenegraph.io.NamedObjectException;
import com.sun.j3d.utils.scenegraph.io.ObjectNotLoadedException;
import com.sun.j3d.utils.scenegraph.io.SceneGraphObjectReferenceControl;
import com.sun.j3d.utils.scenegraph.io.state.javax.media.j3d.NodeComponentState;
import com.sun.j3d.utils.scenegraph.io.state.javax.media.j3d.NullSceneGraphObjectState;
import com.sun.j3d.utils.scenegraph.io.state.javax.media.j3d.SceneGraphObjectState;

/**
 * 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; i1)
                    sharedNodes.add( symbol );
                nodeIDIndex.set( symbol.nodeID, symbol );
            }

            branchGraphs.set( j, symbol );
        }


        for(int i=0; isymbol
     *
     * Only nodes (not nodeComponents) affect intergraph dependencies
     */
    private void addInterGraphDependency( SymbolTableData symbol ) {
        HashSet set = (HashSet)branchGraphDependencies.get( currentBranchGraphID );
        if (set==null) {
            set = new HashSet();
            branchGraphDependencies.set( currentBranchGraphID, set );
        }

        set.add(symbol);
    }

    /**
     * Update the reference count for the node component.
     *
     * Called during NodeComponentState.addSubReference()
     */
    public void incNodeComponentRefCount( int nodeID ) {
        if (nodeID==0) return;

        SymbolTableData symbol = getSymbol( nodeID );

        ((NodeComponentState)symbol.nodeState).addSubReference();

        if (symbol.referenceCount==1)
            sharedNodes.add( symbol );
        symbol.referenceCount++;
    }

    /**
     * Add a refernce to the specified node
     * Also returns the nodes id
     */
    @Override
    public int addReference( SceneGraphObject node ) {
        if (node==null) return 0;

        SymbolTableData symbol = getSymbol( node );

        if (symbol==null) {
            if (node instanceof javax.media.j3d.Node) {
                symbol = createDanglingSymbol( node );
                if (symbol.branchGraphID != currentBranchGraphID  ) {
                    //System.out.println("------------- Adding Reference "+symbol.nodeID+" "+node );  // TODO - remove
                    addInterGraphDependency( symbol );
                    sharedNodes.add( symbol );
                }
            } else {
                symbol = createNodeComponentSymbol( node );
            }
            return symbol.nodeID;
        } else {
            return addReference( symbol );
        }
    }

    /**
     * Add a refernce to the specified node
     * Also returns the nodes id
     */
    public int addReference( SymbolTableData symbol ) {

        if (symbol!=null) {
            if (symbol.referenceCount==1)
                sharedNodes.add( symbol );
            symbol.referenceCount++;

            if (symbol.j3dNode instanceof javax.media.j3d.NodeComponent && symbol.referenceCount>1) {
                ((NodeComponentState)symbol.nodeState).addSubReference();
            }

            if (symbol.branchGraphID != currentBranchGraphID &&
                symbol.j3dNode instanceof javax.media.j3d.Node ) {
                    // System.out.println("------------- Adding Reference "+symbol.nodeID+" "+symbol.j3dNode );    // TODO - remove
                    addInterGraphDependency( symbol );
                }
        } else {
            throw new SGIORuntimeException("Null Symbol");
        }

        return symbol.nodeID;
    }

    /**
     * Add a refernce to the BranchGraph root
     * Also returns the nodes id
     *
     * Used to associate graphs with a locale without storing the graph at the
     * current time.
     */
    public int addBranchGraphReference( SceneGraphObject node, int branchGraphID ) {
        if (node==null) return 0;

        SymbolTableData symbol = getSymbol( node );

        if (symbol!=null) {
            if (symbol.referenceCount==1)
                sharedNodes.add( symbol );
            symbol.referenceCount++;
        } else {
            symbol = new SymbolTableData( nodeID++, node, null, -3 );
            j3dNodeIndex.put( node, symbol );
            nodeIDIndex.add( symbol );
            danglingReferences.put( node, symbol );
        }

        symbol.branchGraphID = branchGraphID;
        for(int i=branchGraphs.size(); inodeIDIndex.size() )
            return null;
        else
            return (SymbolTableData)nodeIDIndex.get( nodeID );
    }

    /** Get the symbol for the shared group
     *  If the sharedgroup has not been loaded then load it before
     *  returning (if we are using RandomAccessFileControl
     */
    public SymbolTableData getSharedGroup( int nodeID ) {
        SymbolTableData symbol = getSymbol( nodeID );

        if (symbol.nodeState==null && control instanceof RandomAccessFileControl) {
            try {
                ((RandomAccessFileControl)control).loadSharedGroup( symbol );
            } catch( java.io.IOException e ) {
                e.printStackTrace();
                throw new SGIORuntimeException("Internal error in getSharedGroup");
            }
        }

        return symbol;
    }

    /**
     * Set the position of the object referenced by state
     */
    public void setFilePosition( long ptr, SceneGraphObjectState state ) {
        if (state instanceof NullSceneGraphObjectState) return;

        SymbolTableData symbol = getSymbol( state.getNodeID() );

        symbol.filePosition = ptr;
    }
    /**
     * Associate the name with the scene graph object
     */
    public void addNamedObject( String name, SceneGraphObject object ) {
        namedObjects.put( name, object );
    }

    /**
     * Add all the named objects in map
     */
    public void addNamedObjects( HashMap map ) {
        if (map!=null)
            namedObjects.putAll( map );
    }

    /**
     * Return the SceneGraphObject associated with the name
     */
    public SceneGraphObject getNamedObject( String name ) throws NamedObjectException, ObjectNotLoadedException {
        Object obj = namedObjects.get( name );
        if (obj==null)
            throw new NamedObjectException( "Unknown name :"+name );

        if (obj instanceof SceneGraphObject)
            return (SceneGraphObject)obj;
        else {
            SymbolTableData symbol = getSymbol( ((Integer)obj).intValue() );
            if (symbol==null || symbol.j3dNode==null)
                throw new ObjectNotLoadedException( ((Integer)obj).toString() );
            return symbol.j3dNode;
        }
    }

    /**
     * Get all the names of the named objects
     */
    public String[] getNames() {
        return (String[])namedObjects.keySet().toArray( new String[] {} );
    }

    /**
     * Add the namedObject mappings to map
     */
    public void getNamedObjectMap( HashMap map ) {
        map.putAll( namedObjects );
    }

    @Override
    public String toString() {
        StringBuffer buf = new StringBuffer();

        for(int i=0; i




© 2015 - 2024 Weber Informatics LLC | Privacy Policy