/*
* $Id: NativeNamespace.java,v 1.5 2002/09/16 08:05:04 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.script.compiler;
import anvil.core.Any;
import anvil.core.runtime.AnyFunction;
import anvil.core.runtime.AnyScope;
import anvil.core.runtime.AnyType;
import anvil.core.Modules;
import anvil.Log;
import anvil.doc.Doc;
import anvil.script.Context;
import anvil.script.CompilableFunction;
import anvil.script.ConstantVariableType;
import anvil.script.Grammar;
import anvil.script.Type;
import anvil.script.NativeJava;
import anvil.script.ClassType;
import anvil.script.InterfaceType;
import anvil.script.Function;
import anvil.script.Scope;
import anvil.java.util.BindingEnumeration;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Enumeration;
import java.util.Hashtable;
/**
* class NativeNamespace
*
* @author: Jani Lehtim�ki
*/
public class NativeNamespace implements Scope, NativeJava
{
private Any _wrapper;
private Class _class;
private String _classname;
private String _name;
private String _qname;
private Doc _document;
private Scope _parent;
private Hashtable _types = new Hashtable();
private static Class[] loadClasses(String[] classnames)
{
int n = classnames.length;
Class[] classes = new Class[n];
for(int i=0; i<n; i++) {
try {
classes[i] = Class.forName(classnames[i]);
} catch (Throwable t) {
anvil.Log.log().error(t);
}
}
return classes;
}
public NativeNamespace(String moduleName, Class module, String[] classnames)
{
this(moduleName, module, loadClasses(classnames), "");
}
public NativeNamespace(String moduleName, Class module, String[] classnames, String document)
{
this(moduleName, module, loadClasses(classnames), document);
}
public NativeNamespace(String moduleName, Class module, Class[] classes)
{
this(moduleName, module, classes, "");
}
public NativeNamespace(String moduleName, Class module, Class[] classes, String document)
{
try {
//_wrapper = new AnyScope(this);
_class = module;
_classname = module.getName();
_name = moduleName;
_document = anvil.doc.DocParser.parse(document);
if (classes != null) {
int n = classes.length;
for(int i=0; i<n; i++) {
Class cls = classes[i];
if (Any.class.isAssignableFrom(cls)) {
NativeClass classtype = (NativeClass)Compiled.getstatic(classes[i], "__class__");
if (classtype != null) {
_types.put(classtype.getName(), classtype);
classtype.setParent(this);
}
} else {
NativeNamespace scope = (NativeNamespace)Compiled.getstatic(classes[i], "__module__");
if (scope != null) {
_types.put(scope.getName(), scope);
scope.setParent(this);
}
}
}
}
/* methods */ {
Method[] methods = module.getDeclaredMethods();
Object[] parameters;
CompilableFunction function;
int n = methods.length;
for(int i=0; i<n; i++) {
Method method = methods[i];
String name = method.getName();
int mod = method.getModifiers();
if (Modifier.isPublic(mod) && Modifier.isStatic(mod)) {
if (method.getReturnType().equals(Any.class)) {
Doc doc = _document.findFirst(Doc.T_FUNCTION, name);
parameters = (Object[])Compiled.getstatic(module, "p_"+name);
function = new NativeFunction(this, method, name, parameters, doc);
_types.put(function.getName(), function);
}
}
}
}
/* fields */ {
Field[] fields = module.getDeclaredFields();
int n = fields.length;
for(int i=0; i<n; i++) {
Field field = fields[i];
String name = field.getName();
int mod = field.getModifiers();
if (name.startsWith("p_")) {
continue;
}
if (name.startsWith("_")) {
continue;
}
if (Modifier.isPublic(mod) && Modifier.isStatic(mod) && Modifier.isFinal(mod)) {
try {
Object obj = field.get(null);
if (obj instanceof Any) {
Doc doc = _document.findFirst(Doc.T_CONST, name);
Any value = (Any)obj;
_types.put(name, new NativeConstantVariable(this, name, field, doc));
}
} catch (Exception e) {
anvil.Log.log().error("Couldn't get field '"+field+"' from "+module.getName());
}
}
}
}
} catch (Throwable t) {
anvil.Log.log().error(t);
}
}
public void setParent(Scope parent)
{
_parent = parent;
}
public String toString()
{
return "namespace "+getQualifiedName();
}
public String getName()
{
return _name;
}
public final String getQualifiedName()
{
if (_qname == null) {
_qname = Grammar.buildQualifiedName(this);
}
return _qname;
}
public int getType()
{
return NAMESPACE;
}
public Scope getParent()
{
if (_parent == null) {
_parent = Modules.getInstance();
}
return _parent;
}
public Doc getDocument()
{
return _document;
}
public Enumeration getDeclarations()
{
return _types.elements();
}
public Type lookupDeclaration(String name)
{
return (Type)_types.get(name);
}
public final Any execute(Context context, String name, Any[] parameters)
{
Type type = (Type)_types.get(name);
if (type != null) {
if (type.getType() == FUNCTION) {
return ((Function)type).execute(context, parameters);
}
}
throw context.NoSuchFunction(_name + '.' + name);
}
public Any getFunction(Context context, String name)
{
Type type = (Type)_types.get(name);
if (type != null) {
if (type.getType() == FUNCTION) {
return new AnyFunction((Function)type);
}
}
throw context.NoSuchFunction(_name + '.' + name);
}
public Any getType(Context context, String name)
{
Type type = (Type)_types.get(name);
if (type != null) {
return new AnyType(type);
}
throw context.NoSuchEntity(_name + '.' + name);
}
public Type getDeclaration(Context context, String name)
{
Type type = (Type)_types.get(name);
if (type != null) {
return type;
}
throw context.NoSuchEntity(_name + '.' + name);
}
public Any newInstance(Context context, String name, Any[] parameters)
{
Type type = (Type)_types.get(name);
if (type != null) {
if (type.getType() == CLASS) {
ClassType clazz = (ClassType)type;
return clazz.getConstructor().execute(context, parameters);
}
}
throw context.NoSuchClass(_name + '.' + name);
}
public Any getWrapper()
{
if (_wrapper == null) {
_wrapper = new AnyType(this);
}
return _wrapper;
}
public int getTypeRef(anvil.codec.ConstantPool pool)
{
return pool.addClass(_class.getName().replace('.', '/'));
}
}