/* * Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License, * Version 1.0, and under the Eclipse Public License, Version 1.0 * (http://h2database.com/html/license.html). * Initial Developer: H2 Group */ package org.h2.java; import java.util.ArrayList; import java.util.LinkedHashMap; /** * A class or interface. */ public class ClassObj { /** * The super class (null for java.lang.Object or primitive types). */ String superClassName; /** * The list of interfaces that this class implements. */ ArrayList<String> interfaceNames = new ArrayList<String>(); /** * The fully qualified class name. */ String className; /** * Whether this is an interface. */ boolean isInterface; /** * Whether this class is public. */ boolean isPublic; /** * Whether this is a primitive class (int, char,...) */ boolean isPrimitive; /** * The primitive type (higher types are more complex) */ int primitiveType; /** * The imported classes. */ ArrayList<ClassObj> imports = new ArrayList<ClassObj>(); /** * The per-instance fields. */ LinkedHashMap<String, FieldObj> instanceFields = new LinkedHashMap<String, FieldObj>(); /** * The static fields of this class. */ LinkedHashMap<String, FieldObj> staticFields = new LinkedHashMap<String, FieldObj>(); /** * The methods. */ LinkedHashMap<String, ArrayList<MethodObj>> methods = new LinkedHashMap<String, ArrayList<MethodObj>>(); /** * The list of native statements. */ ArrayList<Statement> nativeCode = new ArrayList<Statement>(); /** * The class number. */ int id; /** * Get the base type of this class. */ Type baseType; ClassObj() { baseType = new Type(); baseType.classObj = this; } /** * Add a method. * * @param method the method */ void addMethod(MethodObj method) { ArrayList<MethodObj> list = methods.get(method.name); if (list == null) { list = new ArrayList<MethodObj>(); methods.put(method.name, list); } else { // for overloaded methods // method.name = method.name + "_" + (list.size() + 1); } list.add(method); } /** * Add an instance field. * * @param field the field */ void addInstanceField(FieldObj field) { instanceFields.put(field.name, field); } /** * Add a static field. * * @param field the field */ void addStaticField(FieldObj field) { staticFields.put(field.name, field); } public String toString() { if (isPrimitive) { return "j" + className; } return JavaParser.toC(className); } /** * Get the method. * * @param find the method name in the source code * @param args the parameters * @return the method */ MethodObj getMethod(String find, ArrayList<Expr> args) { ArrayList<MethodObj> list = methods.get(find); if (list == null) { throw new RuntimeException("Method not found: " + className + " " + find); } if (list.size() == 1) { return list.get(0); } for (MethodObj m : list) { if (!m.isVarArgs && m.parameters.size() != args.size()) { continue; } boolean match = true; int i = 0; for (FieldObj f : m.parameters.values()) { Expr a = args.get(i++); Type t = a.getType(); if (!t.equals(f.type)) { match = false; break; } } if (match) { return m; } } throw new RuntimeException("Method not found: " + className); } /** * Get the field with the given name. * * @param name the field name * @return the field */ FieldObj getField(String name) { return instanceFields.get(name); } public int hashCode() { return className.hashCode(); } public boolean equals(Object other) { if (other instanceof ClassObj) { ClassObj c = (ClassObj) other; return c.className.equals(className); } return false; } } /** * A method. */ class MethodObj { /** * Whether the last parameter is a var args parameter. */ boolean isVarArgs; /** * Whether this method is static. */ boolean isStatic; /** * Whether this method is private. */ boolean isPrivate; /** * Whether this method is overridden. */ boolean isVirtual; /** * Whether this method is to be ignored (using the Ignore annotation). */ boolean isIgnore; /** * The name. */ String name; /** * The statement block (if any). */ Statement block; /** * The return type. */ Type returnType; /** * The parameter list. */ LinkedHashMap<String, FieldObj> parameters = new LinkedHashMap<String, FieldObj>(); /** * Whether this method is final. */ boolean isFinal; /** * Whether this method is public. */ boolean isPublic; /** * Whether this method is native. */ boolean isNative; /** * Whether this is a constructor. */ boolean isConstructor; public String toString() { return name; } } /** * A field. */ class FieldObj { /** * The type. */ Type type; /** * Whether this is a variable or parameter. */ boolean isVariable; /** * Whether this is a local field (not separately garbage collected). */ boolean isLocalField; /** * The field name. */ String name; /** * Whether this field is static. */ boolean isStatic; /** * Whether this field is final. */ boolean isFinal; /** * Whether this field is private. */ boolean isPrivate; /** * Whether this field is public. */ boolean isPublic; /** * Whether this method is to be ignored (using the Ignore annotation). */ boolean isIgnore; /** * The initial value expression (may be null). */ Expr value; /** * The class where this field is declared. */ ClassObj declaredClass; public String toString() { return name; } } /** * A type. */ class Type { /** * The class. */ ClassObj classObj; /** * The array nesting level. 0 if not an array. */ int arrayLevel; /** * Whether this is a var args parameter. */ boolean isVarArgs; /** * Use ref-counting. */ boolean refCount = JavaParser.REF_COUNT; /** * Whether this is a array or an non-primitive type. * * @return true if yes */ public boolean isObject() { return arrayLevel > 0 || !classObj.isPrimitive; } public String toString() { return asString(); } /** * Get the C++ code. * * @return the C++ code */ public String asString() { StringBuilder buff = new StringBuilder(); for (int i = 0; i < arrayLevel; i++) { if (refCount) { buff.append("ptr< "); } buff.append("array< "); } if (refCount) { if (!classObj.isPrimitive) { buff.append("ptr< "); } } buff.append(classObj.toString()); if (refCount) { if (!classObj.isPrimitive) { buff.append(" >"); } } for (int i = 0; i < arrayLevel; i++) { if (refCount) { buff.append(" >"); } else { if (!classObj.isPrimitive) { buff.append("*"); } } buff.append(" >"); } if (!refCount) { if (isObject()) { buff.append("*"); } } return buff.toString(); } public int hashCode() { return toString().hashCode(); } public boolean equals(Object other) { if (other instanceof Type) { Type t = (Type) other; return t.classObj.equals(classObj) && t.arrayLevel == arrayLevel && t.isVarArgs == isVarArgs; } return false; } /** * Get the default value, for primitive types (0 usually). * * @param context the context * @return the expression */ public Expr getDefaultValue(JavaParser context) { if (classObj.isPrimitive) { LiteralExpr literal = new LiteralExpr(context, classObj.className); literal.literal = "0"; CastExpr cast = new CastExpr(); cast.type = this; cast.expr = literal; cast.type = this; return cast; } LiteralExpr literal = new LiteralExpr(context, classObj.className); literal.literal = "null"; return literal; } }