/*
 * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */


/*
 * The Original Code is HAT. The Initial Developer of the
 * Original Code is Bill Foote, with contributions from others
 * at JavaSoft/Sun.
 */

package com.sun.tools.hat.internal.model;

import java.util.Vector;
import java.util.Enumeration;
import com.sun.tools.hat.internal.util.CompositeEnumeration;
import com.sun.tools.hat.internal.parser.ReadBuffer;

/**
 *
 * @author      Bill Foote
 */


public class JavaClass extends JavaHeapObject {
    // my id
    private long id;
    // my name
    private String name;

    // These are JavaObjectRef before resolve
    private JavaThing superclass;
    private JavaThing loader;
    private JavaThing signers;
    private JavaThing protectionDomain;

    // non-static fields
    private JavaField[] fields;
    // static fields
    private JavaStatic[] statics;

    private static final JavaClass[] EMPTY_CLASS_ARRAY = new JavaClass[0];
    // my subclasses
    private JavaClass[] subclasses = EMPTY_CLASS_ARRAY;

    // my instances
    private Vector<JavaHeapObject> instances = new Vector<JavaHeapObject>();

    // Who I belong to.  Set on resolve.
    private Snapshot mySnapshot;

    // Size of an instance, including VM overhead
    private int instanceSize;
    // Total number of fields including inherited ones
    private int totalNumFields;


    public JavaClass(long id, String name, long superclassId, long loaderId,
                     long signersId, long protDomainId,
                     JavaField[] fields, JavaStatic[] statics,
                     int instanceSize) {
        this.id = id;
        this.name = name;
        this.superclass = new JavaObjectRef(superclassId);
        this.loader = new JavaObjectRef(loaderId);
        this.signers = new JavaObjectRef(signersId);
        this.protectionDomain = new JavaObjectRef(protDomainId);
        this.fields = fields;
        this.statics = statics;
        this.instanceSize = instanceSize;
    }

    public JavaClass(String name, long superclassId, long loaderId,
                     long signersId, long protDomainId,
                     JavaField[] fields, JavaStatic[] statics,
                     int instanceSize) {
        this(-1L, name, superclassId, loaderId, signersId,
             protDomainId, fields, statics, instanceSize);
    }

    public final JavaClass getClazz() {
        return mySnapshot.getJavaLangClass();
    }

    public final int getIdentifierSize() {
        return mySnapshot.getIdentifierSize();
    }

    public final int getMinimumObjectSize() {
        return mySnapshot.getMinimumObjectSize();
    }

    public void resolve(Snapshot snapshot) {
        if (mySnapshot != null) {
            return;
        }
        mySnapshot = snapshot;
        resolveSuperclass(snapshot);
        if (superclass != null) {
            ((JavaClass) superclass).addSubclass(this);
        }

        loader  = loader.dereference(snapshot, null);
        signers  = signers.dereference(snapshot, null);
        protectionDomain  = protectionDomain.dereference(snapshot, null);

        for (int i = 0; i < statics.length; i++) {
            statics[i].resolve(this, snapshot);
        }
        snapshot.getJavaLangClass().addInstance(this);
        super.resolve(snapshot);
        return;
    }

    /**
     * Resolve our superclass.  This might be called well before
     * all instances are available (like when reading deferred
     * instances in a 1.2 dump file :-)  Calling this is sufficient
     * to be able to explore this class' fields.
     */
    public void resolveSuperclass(Snapshot snapshot) {
        if (superclass == null) {
            // We must be java.lang.Object, so we have no superclass.
        } else {
            totalNumFields = fields.length;
            superclass = superclass.dereference(snapshot, null);
            if (superclass == snapshot.getNullThing()) {
                superclass = null;
            } else {
                try {
                    JavaClass sc = (JavaClass) superclass;
                    sc.resolveSuperclass(snapshot);
                    totalNumFields += sc.totalNumFields;
                } catch (ClassCastException ex) {
                    System.out.println("Warning!  Superclass of " + name + " is " + superclass);
                    superclass = null;
                }
            }
        }
    }

    public boolean isString() {
        return mySnapshot.getJavaLangString() == this;
    }

    public boolean isClassLoader() {
        return mySnapshot.getJavaLangClassLoader().isAssignableFrom(this);
    }

    /**
     * Get a numbered field from this class
     */
    public JavaField getField(int i) {
        if (i < 0 || i >= fields.length) {
            throw new Error("No field " + i + " for " + name);
        }
        return fields[i];
    }

    /**
     * Get the total number of fields that are part of an instance of
     * this class.  That is, include superclasses.
     */
    public int getNumFieldsForInstance() {
        return totalNumFields;
    }

    /**
     * Get a numbered field from all the fields that are part of instance
     * of this class.  That is, include superclasses.
     */
    public JavaField getFieldForInstance(int i) {
        if (superclass != null) {
            JavaClass sc = (JavaClass) superclass;
            if (i < sc.totalNumFields) {
                return sc.getFieldForInstance(i);
            }
            i -= sc.totalNumFields;
        }
        return getField(i);
    }

    /**
     * Get the class responsible for field i, where i is a field number that
     * could be passed into getFieldForInstance.
     *
     * @see JavaClass.getFieldForInstance()
     */
    public JavaClass getClassForField(int i) {
        if (superclass != null) {
            JavaClass sc = (JavaClass) superclass;
            if (i < sc.totalNumFields) {
                return sc.getClassForField(i);
            }
        }
        return this;
    }

    public long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public boolean isArray() {
        return name.indexOf('[') != -1;
    }

    public Enumeration getInstances(boolean includeSubclasses) {
        if (includeSubclasses) {
            Enumeration res = instances.elements();
            for (int i = 0; i < subclasses.length; i++) {
                res = new CompositeEnumeration(res,
                              subclasses[i].getInstances(true));
            }
            return res;
        } else {
            return instances.elements();
        }
    }

    /**
     * @return a count of the instances of this class
     */
    public int getInstancesCount(boolean includeSubclasses) {
        int result = instances.size();
        if (includeSubclasses) {
            for (int i = 0; i < subclasses.length; i++) {
                result += subclasses[i].getInstancesCount(includeSubclasses);
            }
        }
        return result;
    }

    public JavaClass[] getSubclasses() {
        return subclasses;
    }

    /**
     * This can only safely be called after resolve()
     */
    public JavaClass getSuperclass() {
        return (JavaClass) superclass;
    }

    /**
     * This can only safely be called after resolve()
     */
    public JavaThing getLoader() {
        return loader;
    }

    /**
     * This can only safely be called after resolve()
     */
    public boolean isBootstrap() {
        return loader == mySnapshot.getNullThing();
    }

    /**
     * This can only safely be called after resolve()
     */
    public JavaThing getSigners() {
        return signers;
    }

    /**
     * This can only safely be called after resolve()
     */
    public JavaThing getProtectionDomain() {
        return protectionDomain;
    }

    public JavaField[] getFields() {
        return fields;
    }

    /**
     * Includes superclass fields
     */
    public JavaField[] getFieldsForInstance() {
        Vector<JavaField> v = new Vector<JavaField>();
        addFields(v);
        JavaField[] result = new JavaField[v.size()];
        for (int i = 0; i < v.size(); i++) {
            result[i] =  v.elementAt(i);
        }
        return result;
    }


    public JavaStatic[] getStatics() {
        return statics;
    }

    // returns value of static field of given name
    public JavaThing getStaticField(String name) {
        for (int i = 0; i < statics.length; i++) {
            JavaStatic s = statics[i];
            if (s.getField().getName().equals(name)) {
                return s.getValue();
            }
        }
        return null;
    }

    public String toString() {
        return "class " + name;
    }

    public int compareTo(JavaThing other) {
        if (other instanceof JavaClass) {
            return name.compareTo(((JavaClass) other).name);
        }
        return super.compareTo(other);
    }


    /**
     * @return true iff a variable of type this is assignable from an instance
     *          of other
     */
    public boolean isAssignableFrom(JavaClass other) {
        if (this == other) {
            return true;
        } else if (other == null) {
            return false;
        } else {
            return isAssignableFrom((JavaClass) other.superclass);
            // Trivial tail recursion:  I have faith in javac.
        }
    }

    /**
     * Describe the reference that this thing has to target.  This will only
     * be called if target is in the array returned by getChildrenForRootset.
     */
     public String describeReferenceTo(JavaThing target, Snapshot ss) {
        for (int i = 0; i < statics.length; i++) {
            JavaField f = statics[i].getField();
            if (f.hasId()) {
                JavaThing other = statics[i].getValue();
                if (other == target) {
                    return "static field " + f.getName();
                }
            }
        }
        return super.describeReferenceTo(target, ss);
    }

    /**
     * @return the size of an instance of this class.  Gives 0 for an array
     *          type.
     */
    public int getInstanceSize() {
        return instanceSize + mySnapshot.getMinimumObjectSize();
    }


    /**
     * @return The size of all instances of this class.  Correctly handles
     *          arrays.
     */
    public long getTotalInstanceSize() {
        int count = instances.size();
        if (count == 0 || !isArray()) {
            return count * instanceSize;
        }

        // array class and non-zero count, we have to
        // get the size of each instance and sum it
        long result = 0;
        for (int i = 0; i < count; i++) {
            JavaThing t = (JavaThing) instances.elementAt(i);
            result += t.getSize();
        }
        return result;
    }

    /**
     * @return the size of this object
     */
    public int getSize() {
        JavaClass cl = mySnapshot.getJavaLangClass();
        if (cl == null) {
            return 0;
        } else {
            return cl.getInstanceSize();
        }
    }

    public void visitReferencedObjects(JavaHeapObjectVisitor v) {
        super.visitReferencedObjects(v);
        JavaHeapObject sc = getSuperclass();
        if (sc != null) v.visit(getSuperclass());

        JavaThing other;
        other = getLoader();
        if (other instanceof JavaHeapObject) {
            v.visit((JavaHeapObject)other);
        }
        other = getSigners();
        if (other instanceof JavaHeapObject) {
            v.visit((JavaHeapObject)other);
        }
        other = getProtectionDomain();
        if (other instanceof JavaHeapObject) {
            v.visit((JavaHeapObject)other);
        }

        for (int i = 0; i < statics.length; i++) {
            JavaField f = statics[i].getField();
            if (!v.exclude(this, f) && f.hasId()) {
                other = statics[i].getValue();
                if (other instanceof JavaHeapObject) {
                    v.visit((JavaHeapObject) other);
                }
            }
        }
    }

    // package-privates below this point
    final ReadBuffer getReadBuffer() {
        return mySnapshot.getReadBuffer();
    }

    final void setNew(JavaHeapObject obj, boolean flag) {
        mySnapshot.setNew(obj, flag);
    }

    final boolean isNew(JavaHeapObject obj) {
        return mySnapshot.isNew(obj);
    }

    final StackTrace getSiteTrace(JavaHeapObject obj) {
        return mySnapshot.getSiteTrace(obj);
    }

    final void addReferenceFromRoot(Root root, JavaHeapObject obj) {
        mySnapshot.addReferenceFromRoot(root, obj);
    }

    final Root getRoot(JavaHeapObject obj) {
        return mySnapshot.getRoot(obj);
    }

    final Snapshot getSnapshot() {
        return mySnapshot;
    }

    void addInstance(JavaHeapObject inst) {
        instances.addElement(inst);
    }

    // Internals only below this point
    private void addFields(Vector<JavaField> v) {
        if (superclass != null) {
            ((JavaClass) superclass).addFields(v);
        }
        for (int i = 0; i < fields.length; i++) {
            v.addElement(fields[i]);
        }
    }

    private void addSubclassInstances(Vector<JavaHeapObject> v) {
        for (int i = 0; i < subclasses.length; i++) {
            subclasses[i].addSubclassInstances(v);
        }
        for (int i = 0; i < instances.size(); i++) {
            v.addElement(instances.elementAt(i));
        }
    }

    private void addSubclass(JavaClass sub) {
        JavaClass newValue[] = new JavaClass[subclasses.length + 1];
        System.arraycopy(subclasses, 0, newValue, 0, subclasses.length);
        newValue[subclasses.length] = sub;
        subclasses = newValue;
    }
}
