Package bm.vm

Source Code of bm.vm.ScriptingClass

package bm.vm;

/* -----------------------------------------------------------------------------
    bmScript Scripting language for Mobile Devices
    Copyright (C) 2004-2008 Elondra S.L.

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.
    If not, see <a href="http://www.gnu.org/licenses">http://www.gnu.org/licenses</a>.
----------------------------------------------------------------------------- */

import bm.core.io.Serializable;
import bm.core.io.SerializationException;
import bm.core.io.SerializerInputStream;
import bm.core.io.SerializerOutputStream;
import bm.core.tools.EnumerationUnion;
import bm.vm.sys.ScriptingObject;

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
/*
* File Information
*
* Created on       : 07-oct-2007 0:50:37
* Created by       : narciso
* Last modified by : $Author$
* Last modified on : $Date$
* Revision         : $Revision$
*/

/**
* A ScriptingClass is a definition of objects with certain properties and
* methods that can be invoked.<br/>
* Everything is case sensitive.
*
* @author <a href="mailto:narciso@elondra.com">Narciso Cerezo</a>
* @version $Revision$
*/
public class ScriptingClass
        implements Serializable
{
    protected Hashtable         properties;
    protected Hashtable         methods;
    protected String            name;
    protected boolean           systemClass;
    protected Vector            ancestors;
    protected VirtualMachine    vm;

    /**
     * Constructor.
     *
     * @param vm virtual machine
     */
    public ScriptingClass( final VirtualMachine vm )
    {
        this.vm = vm;
    }

    /**
     * Check if the class is a core system class.
     *
     * @return true if so
     */
    public boolean isSystemClass()
    {
        return systemClass;
    }

    void setSystemClass( final boolean systemClass )
    {
        this.systemClass = systemClass;
    }

    /**
     * Get the virtual machine under which this class exists.
     *
     * @return virtual machine
     */
    public VirtualMachine getVirtualMachine()
    {
        return vm;
    }

    /**
     * Get the name of the class to be used for serialization/deserialization
     * of complex/nested objects.
     *
     * @return class name
     */
    public String getSerializableClassName()
    {
        return "bm.vm.ScriptingClass";
    }

    /**
     * Get this class name.
     *
     * @return class name
     */
    public String getName()
    {
        return name;
    }

    /**
     * Get the class loader assigned to this class.
     *
     * @return class loader
     */
    public ScriptingClassLoader getClassLoader()
    {
        return vm.getClassLoader();
    }

    /**
     * Write object status to stream.
     *
     * @param out output stream
     * @throws bm.core.io.SerializationException on errors
     */
    public void serialize( final SerializerOutputStream out )
            throws SerializationException
    {
        out.writeByte( (byte) 1 ); // version
        out.writeString( name );
        if( properties != null && properties.size() > 0 )
        {
            out.writeInt( properties.size() );
            for( final Enumeration i = properties.keys(); i.hasMoreElements(); )
            {
                final String name = (String) i.nextElement();
                final ScriptingClass clazz = (ScriptingClass)
                        properties.get( name );
                out.writeString( name );
                out.writeString( clazz.getName() );
            }
        }
        else
        {
            out.writeInt( 0 );
        }
        if( methods != null && methods.size() > 0 )
        {
            out.writeInt( methods.size() );
            for( final Enumeration i = methods.keys(); i.hasMoreElements(); )
            {
                final String name = (String) i.nextElement();
                final Method method = (Method) methods.get( name );
                out.writeString( name );
                method.serialize( out );
            }
        }
        else
        {
            out.writeInt( 0 );
        }
        if( ancestors != null && ancestors.size() > 0 )
        {
            final int size = ancestors.size();
            out.writeInt( size );
            for( int i = 0; i < size; i++ )
            {
                final ScriptingClass clazz = (ScriptingClass)
                        ancestors.elementAt( i );
                out.writeString( clazz.getName() );
            }
        }
        else
        {
            out.writeInt( 0 );
        }
    }

    /**
     * Read object status from stream.
     *
     * @param in input stream
     * @throws bm.core.io.SerializationException on errors
     */
    public void deserialize( final SerializerInputStream in )
            throws SerializationException
    {
        final ScriptingClassLoader classLoader = vm.getClassLoader();
        in.readByte(); // skip version
        name = in.readString();
        final int propCount = in.readInt();
        if( propCount > 0 )
        {
            properties = new Hashtable( propCount );
            for( int i = 0; i < propCount; i++ )
            {
                final String name = in.readString();
                final String className = in.readString();
                final ScriptingClass clazz;
                if(
                    className.equals( name ) ||
                        ( classLoader.getAlias( name ) != null &&
                          className.equals( classLoader.getAlias( name ) ) )
                )
                {
                    clazz = this;
                }
                else
                {
                    try
                    {
                        clazz = classLoader.load( className );
                    }
                    catch( ScriptingClassNotFoundException e )
                    {
                        throw new SerializationException(
                                Constants.ERR_SCL_CLASS_NOT_FOUND,
                                e
                        );
                    }
                }
                properties.put( name, clazz );
            }
        }
        else
        {
            properties = null;
        }
        final int methodCount = in.readInt();
        if( methodCount > 0 )
        {
            methods = new Hashtable( methodCount );
            for( int i = 0; i < methodCount; i++ )
            {
                final String name = in.readString();
                final Method method = new MethodImpl( this );
                method.deserialize( in );
                methods.put( name, method );
            }
        }
        else
        {
            methods = null;
        }
        final int ancestorCount = in.readInt();
        if( ancestorCount > 0 )
        {
            ancestors = new Vector( ancestorCount );
            for( int i = 0; i < ancestorCount; i++ )
            {
                final String name = in.readString();
                ScriptingClass clazz;
                try
                {
                    clazz = classLoader.load( name );
                }
                catch( ScriptingClassNotFoundException e )
                {
                    throw new SerializationException(
                            Constants.ERR_SCL_CLASS_NOT_FOUND,
                            e
                    );
                }
                ancestors.addElement( clazz );
            }
        }
        else
        {
            ancestors = null;
        }
    }

    /**
     * Get the property names defined in this class.
     *
     * @return enumeration of strings with property names
     */
    public Enumeration getPropertyNames()
    {
        final EnumerationUnion eu = new EnumerationUnion();
        if( properties != null )
        {
            eu.add( properties.keys() );
        }
        if( ancestors != null )
        {
            final int size = ancestors.size();
            for( int i = 0; i < size; i++ )
            {
                final ScriptingClass clazz = (ScriptingClass)
                        ancestors.elementAt( i );
                eu.add( clazz.getPropertyNames() );
            }
        }
        try
        {
            final ScriptingClass object = getClassLoader().load( "object" );
            eu.add( object.getPropertyNames() );
        }
        catch( ScriptingClassNotFoundException e )
        {
        }
        return eu;
    }

    /**
     * Get the method names defined in this class.
     *
     * @return enumeration of strings with method names
     */
    public Enumeration getMethodNames()
    {
        final EnumerationUnion eu = new EnumerationUnion();
        if( methods != null )
        {
            eu.add( methods.keys() );
        }
        if( ancestors != null )
        {
            final int size = ancestors.size();
            for( int i = 0; i < size; i++ )
            {
                final ScriptingClass clazz = (ScriptingClass)
                        ancestors.elementAt( i );
                eu.add( clazz.getMethodNames() );
            }
        }
        try
        {
            final ScriptingClass object = getClassLoader().load( "object" );
            eu.add( object.getMethodNames() );
        }
        catch( ScriptingClassNotFoundException e )
        {
        }
        return eu;
    }

    /**
     * Get the class of a given property.
     *
     * @param name property name
     * @return class or null if property is not defined in this class
     */
    public ScriptingClass getPropertyClass( final String name )
    {
        ScriptingClass propClass = null;
        if( properties != null )
        {
            propClass = (ScriptingClass) properties.get( name );
        }
        if( propClass == null && ancestors != null )
        {
            final int size = ancestors.size();
            for( int i = 0; i < size && propClass == null; i++ )
            {
                final ScriptingClass clazz = (ScriptingClass)
                        ancestors.elementAt( i );
                propClass = clazz.getPropertyClass( name );
            }
        }
        if( propClass == null )
        {
            try
            {
                final ScriptingClass object = getClassLoader().load( "object" );
                propClass = object.getPropertyClass( name );
            }
            catch( ScriptingClassNotFoundException e )
            {
            }
        }
        return propClass;
    }

    /**
     * Get a method.
     *
     * @param name method name
     * @return method or null if method is not defined in this class
     */
    public Method getMethod( final String name )
    {
        return getMethod( null, name );
    }

    /**
     * Get a method.
     *
     * @param targetClass target class, if null the current class
     * @param methodName method name
     * @return method or null if method is not defined in this class
     */
    public Method getMethod( final String targetClass, final String methodName )
    {
        Method method = null;
        if( (targetClass == null || targetClass.equals( name ) ) &&
            methods != null
                )
        {
            method = ( Method) methods.get( methodName );
        }
        if( method == null && ancestors != null )
        {
            final int size = ancestors.size();
            for( int i = 0; i < size && method == null; i++ )
            {
                final ScriptingClass clazz = (ScriptingClass)
                        ancestors.elementAt( i );
                method = clazz.getMethod( targetClass, methodName );
            }
        }
        if( method == null && !(this instanceof ScriptingObject ) )
        {
            try
            {
                final ScriptingClass object = getClassLoader().load( "object" );
                method = object.getMethod( methodName );
            }
            catch( ScriptingClassNotFoundException e )
            {
            }
        }
        return method;
    }

    /**
     * Check if the class has a property.
     *
     * @param name property name
     * @return true if so
     */
    public boolean hasProperty( final String name )
    {
        return getPropertyClass( name ) != null;
    }

    /**
     * Check if the class has a method.
     *
     * @param name name
     * @return true if so
     */
    public boolean hasMethod( final String name )
    {
        return getMethod( name ) != null;
    }

    public boolean equals( final Object o )
    {
        if( this == o )
        {
            return true;
        }
        if( o == null || getClass() != o.getClass() )
        {
            return false;
        }
        final ScriptingClass that = (ScriptingClass) o;
        return name.equals( that.name );
    }

    public int hashCode()
    {
        return name.hashCode();
    }

    public Vector getAncestors()
    {
        return ancestors;
    }
}
TOP

Related Classes of bm.vm.ScriptingClass

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.