/*
* $Id: AnyType.java,v 1.25 2002/09/16 08:05:03 jkl Exp $
*
* Copyright (c) 2002 Njet Communications Ltd. All Rights Reserved.
*
* Use is subject to license terms, as defined in
* Anvil Sofware License, Version 1.1. See LICENSE
* file, or http://njet.org/license-1.1.txt
*/
package anvil.core.runtime;
import java.io.IOException;
import java.util.Enumeration;
import java.net.URL;
import anvil.java.util.BindingEnumeration;
import anvil.core.Any;
import anvil.core.AnyString;
import anvil.core.Array;
import anvil.core.AnyTuple;
import anvil.core.AnyAbstractClass;
import anvil.core.Serializer;
import anvil.core.Unserializer;
import anvil.core.UnserializationException;
import anvil.core.net.AnyURL;
import anvil.doc.Doc;
import anvil.script.ClassRef;
import anvil.script.ClassType;
import anvil.script.CompilableFunction;
import anvil.script.Context;
import anvil.script.Function;
import anvil.script.Import;
import anvil.script.InterfaceRef;
import anvil.script.InterfaceType;
import anvil.script.MethodType;
import anvil.script.StaticVariableType;
import anvil.script.MemberVariableType;
import anvil.script.Scope;
import anvil.script.Module;
import anvil.script.Type;
import anvil.script.Type;
import anvil.script.VariableType;
import anvil.server.Address;
/// @class Type
/// Type is a generic representation of all the entities declared
/// with anvil.
/**
* class AnyType
*
* @author: Jani Lehtim�ki
*/
public class AnyType extends AnyAbstractClass
{
public static final Any MODULE = Any.create(Type.MODULE);
public static final Any NAMESPACE = Any.create(Type.NAMESPACE);
public static final Any CLASS = Any.create(Type.CLASS);
public static final Any INTERFACE = Any.create(Type.INTERFACE);
public static final Any GLOBAL_NAMESPACE = Any.create(Type.GLOBAL_NAMESPACE);
public static final Any SYSTEM_NAMESPACE = Any.create(Type.SYSTEM_NAMESPACE);
public static final Any FUNCTION = Any.create(Type.FUNCTION);
public static final Any METHOD = Any.create(Type.METHOD);
public static final Any INTERFACE_METHOD = Any.create(Type.INTERFACE_METHOD);
public static final Any CONSTRUCTOR = Any.create(Type.CONSTRUCTOR);
public static final Any CONSTANT_VARIABLE = Any.create(Type.CONSTANT_VARIABLE);
public static final Any STATIC_VARIABLE = Any.create(Type.STATIC_VARIABLE);
public static final Any MEMBER_VARIABLE = Any.create(Type.MEMBER_VARIABLE);
public static final Any FUNCTION_PARAMETER = Any.create(Type.FUNCTION_PARAMETER);
public static final Any LOCAL_VARIABLE = Any.create(Type.LOCAL_VARIABLE);
public static final Any IMPORT = Any.create(Type.IMPORT);
private Type _type;
private int _typecode;
public AnyType(Type type)
{
_type = type;
_typecode = type.getType();
}
private String getTypeAsString()
{
return getTypeAsString(_typecode);
}
private String getTypeAsString(int type)
{
return Type.TYPE_NAMES[type];
}
public final anvil.script.ClassType classOf() {
return __class__;
}
public Object toObject()
{
return _type;
}
public String toString()
{
return "Type("+_type.toString()+")";
}
public int hashCode()
{
return _type.hashCode();
}
public boolean equals(Object obj)
{
if (this == obj) {
return true;
}
if (obj instanceof AnyType) {
return _type == ((AnyType)obj)._type;
}
return false;
}
public Any getAttribute(Context context, String name)
{
if (_type instanceof Scope) {
Type type = ((Scope)_type).lookupDeclaration(name);
return (type != null) ? new AnyType(type) : UNDEFINED;
} else if (_type instanceof CompilableFunction) {
Any value = ((CompilableFunction)_type).getAttribute(name);
if (value != null) {
return value;
}
}
return UNDEFINED;
}
public Any checkAttribute(Context context, String name)
{
return getAttribute(context, name);
}
public Any getReference(Context context, Any index)
{
return getAttribute(context, index.toString());
}
public Any checkReference(Context context, Any index)
{
return getAttribute(context, index.toString());
}
public BindingEnumeration enumeration()
{
if (_type instanceof Scope) {
return new TypeEnumeration(
((Scope)_type).getDeclarations());
}
return BindingEnumeration.EMPTY;
}
public Any execute(Context context, Any[] parameters)
{
switch(_typecode) {
case Type.CLASS:
{
ClassType type = (ClassType)_type;
Function ctor = type.getConstructor();
if (ctor != null) {
return ctor.execute(context, parameters);
}
throw context.InstantiationError("No constructor for "+type);
}
case Type.FUNCTION:
case Type.CONSTRUCTOR:
{
CompilableFunction function = (CompilableFunction)_type;
if (function.isInnerFunction()) {
throw context.CallError("Cannot call inner function: " + _type.toString());
}
return function.execute(context, parameters);
}
case Type.INTERFACE_METHOD:
{
throw context.CallError("Cannot call interface method: " + _type.toString());
}
case Type.METHOD:
{
CompilableFunction function = (CompilableFunction)_type;
if (function.isInnerFunction()) {
throw context.CallError("Cannot call inner method: " + _type.toString());
}
int length = parameters.length;
if (length == 0) {
throw context.NoInstance(_type.toString());
}
Any self = parameters[0];
Type target = function.getParent();
if (!self.isInstanceOf(target)) {
throw context.BadParameter("Instance of '"+target+"' expected");
}
Any[] params = Any.ARRAY0;
if (length > 1) {
params = new Any[--length];
System.arraycopy(parameters, 1, params, 0, length);
}
return function.execute(context, self, params);
}
default:
return Any.UNDEFINED;
}
}
public final void serialize(Serializer serializer) throws IOException
{
if (serializer.register(this)) {
return;
}
serializer.write('T');
serializeType(serializer, _type);
}
public static final Any unserialize(Unserializer unserializer) throws UnserializationException
{
Type type = unserializeType(unserializer);
AnyType anytype = new AnyType(type);
unserializer.register(anytype);
return anytype;
}
public static final void serializeType(Serializer serializer, Type stype) throws IOException
{
int size = 0;
Type type = stype;
while(type != null) {
size++;
type = type.getParent();
}
Type[] types = new Type[size];
type = stype;
int i = 0;
while(type != null) {
types[i++] = type;
type = type.getParent();
}
serializer.write(size);
serializer.write(':');
for(i=size-1; i>=0; i--) {
type = types[i];
serializer.write(type.getName());
}
}
public static final Type unserializeType(Unserializer unserializer) throws UnserializationException
{
int size = (int)unserializer.getLong();
if (size < 1) {
throw new UnserializationException();
}
unserializer.consume('s');
String source = unserializer.getUTF16String();
Type type = unserializer.getContext().import_(source);
for(int i=1; i<size; i++) {
unserializer.consume('s');
String name = unserializer.getUTF16String();
if (type instanceof Scope) {
type = ((Scope)type).lookupDeclaration(name);
} else {
type = null;
break;
}
}
if (type == null) {
throw new UnserializationException();
}
return type;
}
/// @method getName
/// Returns the name of type.
/// @synopsis string getName()
public Any m_getName()
{
return Any.create(_type.getName());
}
/// @method getQualifiedName
/// Returns the qualified name (dotted name starting from module) of type.
/// @synopsis string getQualifiedName()
public Any m_getQualifiedName()
{
return Any.create(_type.getQualifiedName());
}
/// @method getType
/// Returns the type as string.
/// Type is one of: <ul>
/// <li>module
/// <li>namespace
/// <li>class
/// <li>interface
/// <li>namespace
/// <li>namespace
/// <li>library
/// <li>function
/// <li>method
/// <li>prototype
/// <li>constructor
/// <li>constant
/// <li>variable
/// <li>member
/// <li>variable
/// <li>variable
/// <li>import
/// </ul>
/// @synopsis string getType()
public Any m_getType()
{
return new AnyString(getTypeAsString());
}
/// @method getTypeCode
/// Returns type as int.
/// @synopsis int getTypeCode()
public Any m_getTypeCode()
{
return Any.create(_type.getType());
}
/// @method getDeclarations
/// Returns array of declarations contained in this type.
/// Declarations are mapped to array their names.
/// @synopsis array getDeclarations()
/// @synopsis array getDeclarations(string type)
/// @synopsis array getDeclarations(int type)
/// @param type Optional parameter restricting returned
/// declarations to be of given type.
public static final Object[] p_getDeclarations = { "*type", null };
public Any m_getDeclarations(Any ofType_)
{
if (_type instanceof Scope) {
int ofType = 0;
if (ofType_ != null) {
if (ofType_.isInt()) {
ofType = ofType_.toInt();
}
String t = ofType_.toString();
String[] s = Type.TYPE_NAMES;
int n = s.length;
for(int i=1; i<n; i++) {
if (s[i].equalsIgnoreCase(t)) {
ofType = i;
break;
}
}
}
Enumeration e = ((Scope)_type).getDeclarations();
Array types = new Array();
while(e.hasMoreElements()) {
Type type = (Type)e.nextElement();
if ((ofType == 0) || (type.getType() == ofType)) {
types.put(new AnyString(type.getName()), new AnyType(type));
}
}
return types;
}
return UNDEFINED;
}
/// @method lookup
/// Looks up declaration with given name.
/// @synopsis Type lookup(string name)
/// @return Type or undefined, if there was not a declaration with that name
public static final Object[] p_lookup = { "name" };
public Any m_lookup(String name)
{
if (_type instanceof Scope) {
Type type = ((Scope)_type).lookupDeclaration(name);
return (type != null) ? new AnyType(type) : UNDEFINED;
}
return UNDEFINED;
}
/// @method lookupInherited
/// Looks up inherited declaration with given name from class or interface.
/// @synopsis Type lookupInherited(string name)
/// @return Type or undefined, if there was not a declaration with that name
public static final Object[] p_lookupInherited = { "name" };
public Any m_lookupInherited(String name)
{
Type type = null;
switch(_typecode) {
case Type.CLASS:
type = ((ClassType)_type).lookupInheritedDeclaration(name);
case Type.INTERFACE:
type = ((InterfaceType)_type).lookupInheritedDeclaration(name);
}
return (type != null) ? new AnyType(type) : UNDEFINED;
}
/// @method getBaseClass
/// Returns the base class of this class.
/// @synopsis Type getBaseClass()
public Any m_getBaseClass()
{
if (_typecode == Type.CLASS) {
ClassRef ref = ((ClassType)_type).getBase();
if (ref != null) {
Type type = ref.getType();
return (type != null) ? new AnyType(type) : UNDEFINED;
}
}
return UNDEFINED;
}
/// @method getInterfaces
/// Returns the tuple of interfaces of this class or interfaces.
/// @synopsis tuple getInterfaces()
public Any m_getInterfaces()
{
InterfaceRef[] refs = null;
if (_typecode == Type.CLASS) {
refs = ((ClassType)_type).getInterfaces();
} else if (_typecode == Type.INTERFACE) {
refs = ((InterfaceType)_type).getBases();
}
if (refs != null) {
Type type;
int n = refs.length;
Any[] list = new Any[n];
for(int i=0; i<n; i++) {
type = refs[i].getType();
list[i] = (type != null) ? new AnyType(type) : UNDEFINED;
}
return new AnyTuple(list);
}
return UNDEFINED;
}
/// @method getConstructor
/// Returns the constructor of class.
/// @synopsis Function getConstructor()
public Any m_getConstructor()
{
if (_typecode == Type.CLASS) {
Function ctor = ((ClassType)_type).getConstructor();
if (ctor != null) {
return new AnyFunction(ctor);
}
}
return UNDEFINED;
}
/// @method newInstance
/// Creates and returns a new instance from class with given parameters.
/// @synopsis object newInstance(parameters...)
public static final Object[] p_newInstance = { null, "parameters" };
public Any m_newInstance(Context context, Any[] parameters)
{
if (_typecode == Type.CLASS) {
Function ctor = ((ClassType)_type).getConstructor();
if (ctor != null) {
return ctor.execute(context, parameters);
}
}
return UNDEFINED;
}
private static final Any DOTDOT = new AnyString("..");
/// @method getParameterList
/// Returns array containing a function's parameters list.
/// For each parameter there exists an tuple
/// <code>(required, defaultValue, docText, docTypeText)</code>.
/// These tuples are mapped to array with parameters names.
/// If parameter name is <code>..</code> it indicates that
/// this function accepts variable length arguments and mapped tuple
/// contains <code>(restName, docText, docTypeText)</code>.
/// @synopsis array getParameterList()
public Any m_getParameterList()
{
if (_type instanceof CompilableFunction) {
CompilableFunction function = (CompilableFunction)_type;
int max = function.getParameterCount();
int min = function.getMinimumParameterCount();
Array list = new Array();
Any value;
int count = 0;
boolean required;
Doc doc;
for(int i=0; i<max; i++) {
switch(function.getParameterType(i)) {
case CompilableFunction.PARAMETER_CONTEXT:
break;
case CompilableFunction.PARAMETER_ANY:
case CompilableFunction.PARAMETER_STRING:
case CompilableFunction.PARAMETER_OBJECT:
case CompilableFunction.PARAMETER_DOUBLE:
case CompilableFunction.PARAMETER_INT:
case CompilableFunction.PARAMETER_LONG:
case CompilableFunction.PARAMETER_BOOLEAN:
required = (count < min);
if (count >= min) {
value = function.getParameterDefault(i);
if (value == null) {
value = UNDEFINED;
}
} else {
value = UNDEFINED;
}
doc = function.getParameterDoc(i);
list.append(new AnyString(function.getParameterName(i)),
new AnyTuple(new Any[] {
required ? Any.TRUE : Any.FALSE,
value,
Any.create((doc != null) ? doc.getText() : null),
Any.create((doc != null) ? doc.getChildText(doc.T_TYPE, null) : null)
}));
count++;
break;
case CompilableFunction.PARAMETER_ARRAY:
case CompilableFunction.PARAMETER_ANYLIST:
case CompilableFunction.PARAMETER_LIST:
doc = function.getParameterDoc(i);
list.append(DOTDOT, new AnyTuple(new Any[] {
new AnyString(function.getParameterName(i)),
Any.create((doc != null) ? doc.getText() : null),
Any.create((doc != null) ? doc.getChildText(doc.T_TYPE, null) : null)
}));
break;
}
}
return list;
}
return UNDEFINED;
}
/// @method getFunction
/// Returns this function as anvil.runtime.Function.
/// @synopsis Function getFunction()
public Any m_getFunction()
{
if (_typecode == Type.FUNCTION) {
return new AnyFunction((Function)_type);
}
return UNDEFINED;
}
/// @method getPathinfo
/// Returns the pathinfo where this type is declared.
/// If it is located on a library, returns the name of library.
/// @synopsis string getPathinfo()
public Any m_getPathinfo()
{
Type type = _type;
while(type != null) {
if (type instanceof Module) {
return new AnyString(((Module)type).getPathinfo());
}
type = type.getParent();
}
return UNDEFINED;
}
/// @method getURL
/// Returns the url where this type is declared.
/// If it is located on a library, undefined.
/// @synopsis URL getURL()
public Any m_getURL()
{
Type type = _type;
while(type != null) {
if (type instanceof Module) {
URL url = ((Module)type).getAddress().getURL();
if (url != null) {
return new AnyURL(url);
}
}
type = type.getParent();
}
return UNDEFINED;
}
/// @method getModule
/// Returns the script where this type is declared.
/// @synopsis Type getModule()
public Any m_getModule()
{
Type type = _type;
while(type != null) {
if (type instanceof Module) {
return new AnyType(type);
}
type = type.getParent();
}
return UNDEFINED;
}
/// @method getZone
/// Returns the Zone where this type is declared.
/// @synopsis Configurable getZone()
/// @throws AccessDenied If security policy denies this operation.
public Any m_getZone(Context context)
{
context.checkAccess(anvil.core.system.AnyConfigurable.CAN_READ);
Type type = _type;
while(type != null) {
if (type instanceof Module) {
Module script = (Module)type;
Address addr = script.getAddress();
if (addr != null) {
return new anvil.core.system.AnyConfigurable(addr.getZone());
}
}
type = type.getParent();
}
return UNDEFINED;
}
/// @method getClass
/// Returns the class where this type is declared.
/// @synopsis Type getClass()
public Any m_getClass()
{
Type parent = _type.getParent();
if (parent != null && parent.getType() == Type.CLASS) {
return new AnyType(parent);
}
return UNDEFINED;
}
/// @method getParent
/// Returns the parent type for this type.
/// @synopsis Scope getParent()
public Any m_getParent()
{
Type type = _type.getParent();
if (type != null) {
return new AnyType(type);
}
return UNDEFINED;
}
/// @method getValue
/// Returns the value contained in variable.
/// @synopsis object getValue()
/// @synopsis object getValue(object instance)
/// @param instance Instance of class, required if the type is a member variable
public static final Object[] p_getValue = { null, "*instance", null };
public Any m_getValue(Context context, Any instance)
{
if (_type instanceof MemberVariableType) {
if (instance == null) {
throw context.NoInstance(_type.toString());
}
return ((MemberVariableType)_type).getValue(instance);
} else if (_type instanceof VariableType) {
return ((VariableType)_type).getValue();
}
return UNDEFINED;
}
/// @method setValue
/// Sets the value contained in variable.
/// @synopsis object setValue(object value)
/// @synopsis object setValue(object value, object instance)
/// @param instance Instance of class, required if the type is a member variable
public static final Object[] p_setValue = { null, "value", "*instance", null };
public Any m_setValue(Context context, Any value, Any instance)
{
if (_type instanceof MemberVariableType) {
if (instance == null) {
throw context.NoInstance(_type.toString());
}
return ((MemberVariableType)_type).setValue(instance, value);
} else if (_type instanceof VariableType) {
return ((VariableType)_type).setValue(instance);
}
return UNDEFINED;
}
/// @method hasDoc
/// Checks if this type has a document.
/// @synopsis boolean hasDoc()
public Any m_hasDoc()
{
return (_type.getDocument() != null) ? TRUE : FALSE;
}
/// @method getDoc
/// Returns a document for this type.
/// @synopsis Doc getDoc()
public Any m_getDoc()
{
Doc doc = _type.getDocument();
return new AnyDoc((doc != null) ? doc : Doc.EMPTY_DOC);
}
/// @method isInstanceOf
/// Checks if this type a super class or same as the given type.
/// @synopsis boolean isInstanceOf(Type type)
public static final Object[] p_isInstanceOf = { null, "type" };
public Any m_isInstanceOf(Context context, Any clazz)
{
if (!(clazz instanceof AnyType)) {
throw context.BadParameter("Type expected");
}
if (_typecode == Type.CLASS) {
ClassType self = (ClassType)_type;
Type other = (Type)clazz.toObject();
return self.isInstanceOf(other) ? TRUE : FALSE;
}
return FALSE;
}
private class TypeEnumeration implements BindingEnumeration
{
private Enumeration _enum;
private Type _element = null;
public TypeEnumeration(Enumeration enum)
{
_enum = enum;
}
public boolean hasMoreElements()
{
return (_element != null) || _enum.hasMoreElements();
}
public Object nextKey()
{
if (_element == null) {
_element = (Type)_enum.nextElement();
}
return new AnyString(_element.getName());
}
public Object nextElement()
{
Object o;
if (_element != null) {
o = new AnyType(_element);
_element = null;
} else {
o = new AnyType((Type)_enum.nextElement());
}
return o;
}
}
public static final anvil.script.compiler.NativeClass __class__ =
new anvil.script.compiler.NativeClass("Type", AnyType.class,
//DOC{{
""+
" @class Type\n" +
" Type is a generic representation of all the entities declared\n" +
" with anvil.\n" +
" @method getName\n" +
" Returns the name of type.\n" +
" @synopsis string getName()\n" +
" @method getQualifiedName\n" +
" Returns the qualified name (dotted name starting from module) of type.\n" +
" @synopsis string getQualifiedName()\n" +
" @method getType\n" +
" Returns the type as string.\n" +
" Type is one of: <ul>\n" +
" <li>module\n" +
" <li>namespace\n" +
" <li>class\n" +
" <li>interface\n" +
" <li>namespace\n" +
" <li>namespace\n" +
" <li>library\n" +
" <li>function\n" +
" <li>method\n" +
" <li>prototype\n" +
" <li>constructor\n" +
" <li>constant\n" +
" <li>variable\n" +
" <li>member\n" +
" <li>variable\n" +
" <li>variable\n" +
" <li>import\n" +
" </ul>\n" +
" @synopsis string getType()\n" +
" @method getTypeCode\n" +
" Returns type as int.\n" +
" @synopsis int getTypeCode()\n" +
" @method getDeclarations\n" +
" Returns array of declarations contained in this type. \n" +
" Declarations are mapped to array their names.\n" +
" @synopsis array getDeclarations()\n" +
" @synopsis array getDeclarations(string type)\n" +
" @synopsis array getDeclarations(int type)\n" +
" @param type Optional parameter restricting returned\n" +
" declarations to be of given type.\n" +
" @method lookup\n" +
" Looks up declaration with given name.\n" +
" @synopsis Type lookup(string name)\n" +
" @return Type or undefined, if there was not a declaration with that name\n" +
" @method lookupInherited\n" +
" Looks up inherited declaration with given name from class or interface.\n" +
" @synopsis Type lookupInherited(string name)\n" +
" @return Type or undefined, if there was not a declaration with that name\n" +
" @method getBaseClass\n" +
" Returns the base class of this class.\n" +
" @synopsis Type getBaseClass()\n" +
" @method getInterfaces\n" +
" Returns the tuple of interfaces of this class or interfaces.\n" +
" @synopsis tuple getInterfaces()\n" +
" @method getConstructor\n" +
" Returns the constructor of class.\n" +
" @synopsis Function getConstructor()\n" +
" @method newInstance\n" +
" Creates and returns a new instance from class with given parameters.\n" +
" @synopsis object newInstance(parameters...)\n" +
" @method getParameterList\n" +
" Returns array containing a function's parameters list.\n" +
" For each parameter there exists an tuple\n" +
" <code>(required, defaultValue, docText, docTypeText)</code>.\n" +
" These tuples are mapped to array with parameters names.\n" +
" If parameter name is <code>..</code> it indicates that\n" +
" this function accepts variable length arguments and mapped tuple\n" +
" contains <code>(restName, docText, docTypeText)</code>.\n" +
" @synopsis array getParameterList()\n" +
" @method getFunction\n" +
" Returns this function as anvil.runtime.Function.\n" +
" @synopsis Function getFunction()\n" +
" @method getPathinfo\n" +
" Returns the pathinfo where this type is declared.\n" +
" If it is located on a library, returns the name of library.\n" +
" @synopsis string getPathinfo()\n" +
" @method getURL\n" +
" Returns the url where this type is declared.\n" +
" If it is located on a library, undefined.\n" +
" @synopsis URL getURL()\n" +
" @method getModule\n" +
" Returns the script where this type is declared.\n" +
" @synopsis Type getModule()\n" +
" @method getZone\n" +
" Returns the Zone where this type is declared.\n" +
" @synopsis Configurable getZone()\n" +
" @throws AccessDenied If security policy denies this operation.\n" +
" @method getClass\n" +
" Returns the class where this type is declared. \n" +
" @synopsis Type getClass()\n" +
" @method getParent\n" +
" Returns the parent type for this type. \n" +
" @synopsis Scope getParent()\n" +
" @method getValue\n" +
" Returns the value contained in variable.\n" +
" @synopsis object getValue()\n" +
" @synopsis object getValue(object instance)\n" +
" @param instance Instance of class, required if the type is a member variable\n" +
" @method setValue\n" +
" Sets the value contained in variable.\n" +
" @synopsis object setValue(object value)\n" +
" @synopsis object setValue(object value, object instance)\n" +
" @param instance Instance of class, required if the type is a member variable\n" +
" @method hasDoc\n" +
" Checks if this type has a document.\n" +
" @synopsis boolean hasDoc()\n" +
" @method getDoc\n" +
" Returns a document for this type.\n" +
" @synopsis Doc getDoc()\n" +
" @method isInstanceOf\n" +
" Checks if this type a super class or same as the given type.\n" +
" @synopsis boolean isInstanceOf(Type type)\n"
//}}DOC
);
static {
RuntimeModule.class.getName();
}
}