/*
 * Copyright (c) 2003, 2013, 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.
 *
 * 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.
 *
 */

package sun.jvm.hotspot.utilities.soql;

import java.util.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.utilities.*;

/**
   This is JavaScript wrapper for InstanceKlass.
*/
public class JSJavaInstanceKlass extends JSJavaKlass {
   private static final int FIELD_SOURCE_FILE        = 1;
   private static final int FIELD_INTERFACES         = 2;
   private static final int FIELD_FIELDS             = 3;
   private static final int FIELD_METHODS            = 4;
   private static final int FIELD_IS_PRIVATE         = 5;
   private static final int FIELD_IS_PUBLIC          = 6;
   private static final int FIELD_IS_PROTECTED       = 7;
   private static final int FIELD_IS_PACKAGE_PRIVATE = 8;
   private static final int FIELD_IS_STATIC          = 9;
   private static final int FIELD_IS_FINAL           = 10;
   private static final int FIELD_IS_ABSTRACT        = 11;
   private static final int FIELD_IS_STRICT          = 12;
   private static final int FIELD_IS_SYNTHETIC       = 13;
   private static final int FIELD_IS_INTERFACE       = 14;
   private static final int FIELD_CLASS_LOADER       = 15;
   private static final int FIELD_STATICS            = 18;
   private static final int FIELD_UNDEFINED          = -1;

   public JSJavaInstanceKlass(InstanceKlass kls, JSJavaFactory fac) {
      super(kls, fac);
      this.instanceFields = new HashMap();
      this.staticFields = new HashMap();
   }

   public final InstanceKlass getInstanceKlass() {
      return (InstanceKlass) getKlass();
   }

   public Object getMetaClassFieldValue(String name) {
      int fieldID = getFieldID(name);
      InstanceKlass ik = getInstanceKlass();
      switch (fieldID) {
      case FIELD_SOURCE_FILE: {
         Symbol sourceFile = ik.getSourceFileName();
         return (sourceFile != null)? sourceFile.asString() : "<unknown>";
      }
      case FIELD_INTERFACES:
         return getInterfaces();
      case FIELD_FIELDS:
         return factory.newJSList(ik.getImmediateFields());
      case FIELD_METHODS:
         return factory.newJSList(ik.getImmediateMethods());
      case FIELD_IS_PRIVATE:
         return Boolean.valueOf(getAccessFlags().isPrivate());
      case FIELD_IS_PUBLIC:
         return Boolean.valueOf(getAccessFlags().isPublic());
      case FIELD_IS_PROTECTED:
         return Boolean.valueOf(getAccessFlags().isProtected());
      case FIELD_IS_PACKAGE_PRIVATE: {
         AccessFlags acc = getAccessFlags();
         return Boolean.valueOf(!acc.isPrivate() && !acc.isPublic() && !acc.isProtected());
      }
      case FIELD_IS_STATIC:
         return Boolean.valueOf(getAccessFlags().isStatic());
      case FIELD_IS_FINAL:
         return Boolean.valueOf(getAccessFlags().isFinal());
      case FIELD_IS_ABSTRACT:
         return Boolean.valueOf(getAccessFlags().isAbstract());
      case FIELD_IS_STRICT:
         return Boolean.valueOf(getAccessFlags().isStrict());
      case FIELD_IS_SYNTHETIC:
         return Boolean.valueOf(getAccessFlags().isSynthetic());
      case FIELD_IS_INTERFACE:
         return Boolean.valueOf(ik.isInterface());
      case FIELD_CLASS_LOADER:
         return factory.newJSJavaObject(ik.getClassLoader());
      case FIELD_STATICS:
         return getStatics();
      case FIELD_UNDEFINED:
      default:
         return super.getMetaClassFieldValue(name);
      }
   }

   public boolean hasMetaClassField(String name) {
      if (getFieldID(name) != FIELD_UNDEFINED) {
          return true;
      } else {
          return super.hasMetaClassField(name);
      }
   }

   public String getName() {
      return getInstanceKlass().getName().asString().replace('/', '.');
   }

   public boolean isArray() {
      return false;
   }

   public String[] getMetaClassFieldNames() {
      String[] superFields = super.getMetaClassFieldNames();
      Set k = fields.keySet();
      String[] res = new String[k.size() + superFields.length];
      System.arraycopy(superFields, 0, res, 0, superFields.length);
      int i = superFields.length;
      for (Iterator itr = k.iterator(); itr.hasNext();) {
          res[i] = (String) itr.next();
          i++;
      }
      return res;
   }

   public Object getInstanceFieldValue(String name, Instance instance) throws NoSuchFieldException {
      Field fld = findInstanceField(name);
      if (fld != null) {
         return getFieldValue(fld, name, instance);
      } else {
         throw new NoSuchFieldException(name + " is not field of "
                + getInstanceKlass().getName().asString().replace('/', '.'));
      }
   }

   public Object getStaticFieldValue(String name) throws NoSuchFieldException {
      Field fld = findStaticField(name);
      if (fld != null) {
         return getFieldValue(fld, name, getInstanceKlass());
      } else {
         throw new NoSuchFieldException(name + " is not field of "
                + getInstanceKlass().getName().asString().replace('/', '.'));
      }
   }

   public String[] getInstanceFieldNames() {
      if (instanceFieldNames == null) {
         InstanceKlass current = getInstanceKlass();
         while (current != null) {
            List tmp = current.getImmediateFields();
            for (Iterator itr = tmp.iterator(); itr.hasNext();) {
               Field fld = (Field) itr.next();
               if (!fld.isStatic()) {
                  String name = fld.getID().getName();
                  if (instanceFields.get(name) == null) {
                     instanceFields.put(name, fld);
                  }
               }
            }
            current = (InstanceKlass) current.getSuper();
         }

         Set s = instanceFields.keySet();
         instanceFieldNames = new String[s.size()];
         int i = 0;
         for (Iterator itr = s.iterator(); itr.hasNext(); i++) {
            instanceFieldNames[i] = (String) itr.next();
         }
      }
      return instanceFieldNames;
   }

   public boolean hasInstanceField(String name) {
      Field fld = findInstanceField(name);
      return (fld != null)? true: false;
   }

   public String[] getStaticFieldNames() {
      if (staticFieldNames == null) {
         InstanceKlass current = getInstanceKlass();
         List tmp = current.getImmediateFields();
         for (Iterator itr = tmp.iterator(); itr.hasNext();) {
            Field fld = (Field) itr.next();
            if (fld.isStatic()) {
               staticFields.put(fld.getID().getName(), fld);
            }
         }

         Set s = staticFields.keySet();
         staticFieldNames = new String[s.size()];
         int i = 0;
         for (Iterator itr = s.iterator(); itr.hasNext(); i++) {
            staticFieldNames[i] = (String) itr.next();
         }
      }
      return staticFieldNames;
   }

   public boolean hasStaticField(String name) {
      Field fld = findStaticField(name);
      return (fld != null)? true: false;
   }

   //-- Intenals only below this point
   private static Map fields = new HashMap();
   private static void addField(String name, int fieldId) {
      fields.put(name, new Integer(fieldId));
   }

   private static int getFieldID(String name) {
      Integer res = (Integer) fields.get(name);
      return (res != null)? res.intValue() : FIELD_UNDEFINED;
   }

   static {
      addField("sourceFile", FIELD_SOURCE_FILE);
      addField("interfaces", FIELD_INTERFACES);
      addField("fields", FIELD_FIELDS);
      addField("methods", FIELD_METHODS);
      addField("isPrivate", FIELD_IS_PRIVATE);
      addField("isPublic", FIELD_IS_PUBLIC);
      addField("isProtected", FIELD_IS_PROTECTED);
      addField("isPackagePrivate", FIELD_IS_PACKAGE_PRIVATE);
      addField("isStatic", FIELD_IS_STATIC);
      addField("isFinal", FIELD_IS_FINAL);
      addField("isAbstract", FIELD_IS_ABSTRACT);
      addField("isStrict", FIELD_IS_STRICT);
      addField("isSynthetic", FIELD_IS_SYNTHETIC);
      addField("isInterface", FIELD_IS_INTERFACE);
      addField("classLoader", FIELD_CLASS_LOADER);
      addField("statics", FIELD_STATICS);
   }

   private AccessFlags getAccessFlags() {
      if (accFlags == null) {
         accFlags = new AccessFlags(getInstanceKlass().computeModifierFlags());
      }
      return accFlags;
   }

   private Object getFieldValue(Field fld, String name, Oop oop) {
       FieldType fd = fld.getFieldType();
       if (fd.isObject() || fd.isArray()) {
         return factory.newJSJavaObject(((OopField)fld).getValue(oop));
       } else if (fd.isByte()) {
          return new Byte(((ByteField)fld).getValue(oop));
       } else if (fd.isChar()) {
          return new String(new char[] { ((CharField)fld).getValue(oop) });
       } else if (fd.isDouble()) {
          return new Double(((DoubleField)fld).getValue(oop));
       } else if (fd.isFloat()) {
          return new Float(((FloatField)fld).getValue(oop));
       } else if (fd.isInt()) {
          return new Integer(((IntField)fld).getValue(oop));
       } else if (fd.isLong()) {
          return new Long(((LongField)fld).getValue(oop));
       } else if (fd.isShort()) {
          return new Short(((ShortField)fld).getValue(oop));
       } else if (fd.isBoolean()) {
          return Boolean.valueOf(((BooleanField)fld).getValue(oop));
       } else {
          if (Assert.ASSERTS_ENABLED) {
             Assert.that(false, "invalid field type for " + name);
          }
          return null;
       }
   }

   private Object getFieldValue(Field fld, String name, InstanceKlass oop) {
       FieldType fd = fld.getFieldType();
       if (fd.isObject() || fd.isArray()) {
         return factory.newJSJavaObject(((OopField)fld).getValue(oop));
       } else if (fd.isByte()) {
          return new Byte(((ByteField)fld).getValue(oop));
       } else if (fd.isChar()) {
          return new String(new char[] { ((CharField)fld).getValue(oop) });
       } else if (fd.isDouble()) {
          return new Double(((DoubleField)fld).getValue(oop));
       } else if (fd.isFloat()) {
          return new Float(((FloatField)fld).getValue(oop));
       } else if (fd.isInt()) {
          return new Integer(((IntField)fld).getValue(oop));
       } else if (fd.isLong()) {
          return new Long(((LongField)fld).getValue(oop));
       } else if (fd.isShort()) {
          return new Short(((ShortField)fld).getValue(oop));
       } else if (fd.isBoolean()) {
          return Boolean.valueOf(((BooleanField)fld).getValue(oop));
       } else {
          if (Assert.ASSERTS_ENABLED) {
             Assert.that(false, "invalid field type for " + name);
          }
          return null;
       }
   }

   private Field findInstanceField(String name) {
      Field fld = (Field) instanceFields.get(name);
      if (fld != null) {
         return fld;
      } else {
         InstanceKlass current = getInstanceKlass();
         while (current != null) {
            List tmp = current.getImmediateFields();
            for (Iterator itr = tmp.iterator(); itr.hasNext();) {
               fld = (Field) itr.next();
               if (fld.getID().getName().equals(name) && !fld.isStatic()) {
                   instanceFields.put(name, fld);
                   return fld;
               }
            }
            // lookup in super class.
            current = (InstanceKlass) current.getSuper();
         }
      }
      // no match
      return null;
   }

   private Field findStaticField(String name) {
      Field fld = (Field) staticFields.get(name);
      if (fld != null) {
         return fld;
      } else {
         // static fields are searched only in current.
         // Direct/indirect super classes and interfaces
         // are not included in search.
         InstanceKlass current = getInstanceKlass();
         List tmp = current.getImmediateFields();
         for (Iterator itr = tmp.iterator(); itr.hasNext();) {
            fld = (Field) itr.next();
            if (fld.getID().getName().equals(name) && fld.isStatic()) {
               staticFields.put(name, fld);
               return fld;
            }
         }
         // no match
         return null;
      }
   }

   private JSList getInterfaces() {
      InstanceKlass ik = getInstanceKlass();
      List intfs = ik.getDirectImplementedInterfaces();
      List res = new ArrayList(0);
      for (Iterator itr = intfs.iterator(); itr.hasNext();) {
          Klass k = (Klass) itr.next();
          res.add(k.getJavaMirror());
      }
      return factory.newJSList(res);
   }

   private JSMap getStatics() {
      String[] names = getStaticFieldNames();
      Map map = new HashMap();
      for (int i=0; i < names.length; i++) {
         try {
            map.put(names[i], getStaticFieldValue(names[i]));
         } catch (NoSuchFieldException exp) {}
      }
      return factory.newJSMap(map);
  }

   private Map           instanceFields;
   private Map           staticFields;
   private String[]      instanceFieldNames;
   private String[]      staticFieldNames;
   private AccessFlags   accFlags;
}
