/* ====================================================================
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2001 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Apache" and "Apache Software Foundation" and
 *    "Apache BCEL" must not be used to endorse or promote products
 *    derived from this software without prior written permission. For
 *    written permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    "Apache BCEL", nor may "Apache" appear in their name, without
 *    prior written permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
package org.aspectj.apache.bcel.classfile;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import org.aspectj.apache.bcel.Constants;
import org.aspectj.apache.bcel.generic.ArrayType;
import org.aspectj.apache.bcel.generic.ObjectType;

/**
 * This class represents the constant pool, i.e., a table of constants, of a parsed classfile. It may contain null references, due
 * to the JVM specification that skips an entry after an 8-byte constant (double, long) entry.
 */
public class ConstantPool implements Node {
	private Constant[] pool;
	private int poolSize; // number of entries in the pool (could be < pool.length as the array is resized in 'chunks')

	private Map<String, Integer> utf8Cache = new HashMap<String, Integer>();
	private Map<String, Integer> methodCache = new HashMap<String, Integer>();
	private Map<String, Integer> fieldCache = new HashMap<String, Integer>();

	public int getSize() {
		return poolSize;
	}

	public ConstantPool() {
		pool = new Constant[10];
		poolSize = 0;
	}

	public ConstantPool(Constant[] constants) {
		pool = constants;
		poolSize = (constants == null ? 0 : constants.length);
	}

	ConstantPool(DataInputStream file) throws IOException {
		byte tag;
		poolSize = file.readUnsignedShort();
		pool = new Constant[poolSize];
		// pool[0] is unused by the compiler and may be used freely by the implementation
		for (int i = 1; i < poolSize; i++) {
			pool[i] = Constant.readConstant(file);
			tag = pool[i].getTag();
			if ((tag == Constants.CONSTANT_Double) || (tag == Constants.CONSTANT_Long)) {
				i++;
			}
		}
	}

	public Constant getConstant(int index, byte tag) {
		Constant c = getConstant(index);
		// if (c == null) throw new ClassFormatException("Constant pool at index " + index + " is null.");
		if (c.tag == tag)
			return c;
		throw new ClassFormatException("Expected class '" + Constants.CONSTANT_NAMES[tag] + "' at index " + index + " and found "
				+ c);
	}

	public Constant getConstant(int index) {
		try {
			return pool[index];
		} catch (ArrayIndexOutOfBoundsException aioobe) {
			throw new ClassFormatException("Index " + index + " into constant pool (size:" + poolSize + ") is invalid");
		}
	}

	/**
	 * @return deep copy of this constant pool
	 */
	public ConstantPool copy() {
		Constant[] newConstants = new Constant[poolSize]; // use the correct size
		for (int i = 1; i < poolSize; i++) {
			if (pool[i] != null) {
				newConstants[i] = pool[i].copy();
			}
		}
		return new ConstantPool(newConstants);
	}

	/**
	 * Get string from constant pool and bypass the indirection of `ConstantClass' and `ConstantString' objects. I.e. these classes
	 * have an index field that points to another entry of the constant pool of type `ConstantUtf8' which contains the real data.
	 * 
	 * @param index Index in constant pool
	 * @param tag Tag of expected constant, either ConstantClass or ConstantString
	 * @return Contents of string reference
	 * @see ConstantClass
	 * @see ConstantString
	 * @throws ClassFormatException
	 */
	public String getConstantString(int index, byte tag) throws ClassFormatException {
		Constant c = getConstant(index, tag);
		int i;
		/*
		 * This switch() is not that elegant, since the two classes have the same contents, they just differ in the name of the
		 * index field variable. But we want to stick to the JVM naming conventions closely though we could have solved these more
		 * elegantly by using the same variable name or by subclassing.
		 */
		// OPTIMIZE remove the difference - use the an interface and same index methods for string ref id
		switch (tag) {
		case Constants.CONSTANT_Class:
			i = ((ConstantClass) c).getNameIndex();
			break;
		case Constants.CONSTANT_String:
			i = ((ConstantString) c).getStringIndex();
			break;
		default:
			throw new RuntimeException("getConstantString called with illegal tag " + tag);
		}
		// Finally get the string from the constant pool
		c = getConstant(i, Constants.CONSTANT_Utf8);
		return ((ConstantUtf8) c).getValue();
	}

	/**
	 * Resolve constant to a string representation.
	 */
	public String constantToString(Constant c) {
		String str;
		int i;

		switch (c.tag) {
		case Constants.CONSTANT_Class:
			i = ((ConstantClass) c).getNameIndex();
			c = getConstant(i, Constants.CONSTANT_Utf8);
			str = Utility.compactClassName(((ConstantUtf8) c).getValue(), false);
			break;

		case Constants.CONSTANT_String:
			i = ((ConstantString) c).getStringIndex();
			c = getConstant(i, Constants.CONSTANT_Utf8);
			str = "\"" + escape(((ConstantUtf8) c).getValue()) + "\"";
			break;

		case Constants.CONSTANT_Utf8:
		case Constants.CONSTANT_Double:
		case Constants.CONSTANT_Float:
		case Constants.CONSTANT_Long:
		case Constants.CONSTANT_Integer:
			str = ((SimpleConstant) c).getStringValue();
			break;

		case Constants.CONSTANT_NameAndType:
			str = (constantToString(((ConstantNameAndType) c).getNameIndex(), Constants.CONSTANT_Utf8) + " " + constantToString(
					((ConstantNameAndType) c).getSignatureIndex(), Constants.CONSTANT_Utf8));
			break;

		case Constants.CONSTANT_InterfaceMethodref:
		case Constants.CONSTANT_Methodref:
		case Constants.CONSTANT_Fieldref:
			str = (constantToString(((ConstantCP) c).getClassIndex(), Constants.CONSTANT_Class) + "." + constantToString(
					((ConstantCP) c).getNameAndTypeIndex(), Constants.CONSTANT_NameAndType));
			break;
			
		case Constants.CONSTANT_InvokeDynamic:
			ConstantInvokeDynamic cID = ((ConstantInvokeDynamic)c);
			return "#"+cID.getBootstrapMethodAttrIndex()+"."+constantToString(cID.getNameAndTypeIndex(), Constants.CONSTANT_NameAndType);

		case Constants.CONSTANT_MethodHandle:
			ConstantMethodHandle cMH = ((ConstantMethodHandle)c);
			return cMH.getReferenceKind()+":"+constantToString(cMH.getReferenceIndex(),Constants.CONSTANT_Methodref);

		case Constants.CONSTANT_MethodType:
			ConstantMethodType cMT = (ConstantMethodType)c;
			return constantToString(cMT.getDescriptorIndex(),Constants.CONSTANT_Utf8);

		case Constants.CONSTANT_Module:
			ConstantModule cM = (ConstantModule)c;
			return "Module:"+constantToString(cM.getNameIndex(),Constants.CONSTANT_Utf8);

		case Constants.CONSTANT_Package:
			ConstantPackage cP = (ConstantPackage)c;
			return "Package:"+constantToString(cP.getNameIndex(),Constants.CONSTANT_Utf8);

		default: // Never reached
			throw new RuntimeException("Unknown constant type " + c.tag);
		}

		return str;
	}

	private static final String escape(String str) {
		int len = str.length();
		StringBuffer buf = new StringBuffer(len + 5);
		char[] ch = str.toCharArray();

		for (int i = 0; i < len; i++) {
			switch (ch[i]) {
			case '\n':
				buf.append("\\n");
				break;
			case '\r':
				buf.append("\\r");
				break;
			case '\t':
				buf.append("\\t");
				break;
			case '\b':
				buf.append("\\b");
				break;
			case '"':
				buf.append("\\\"");
				break;
			default:
				buf.append(ch[i]);
			}
		}

		return buf.toString();
	}

	public String constantToString(int index, byte tag) {
		Constant c = getConstant(index, tag);
		return constantToString(c);
	}

	public String constantToString(int index) {
		return constantToString(getConstant(index));
	}

	@Override
	public void accept(ClassVisitor v) {
		v.visitConstantPool(this);
	}

	public Constant[] getConstantPool() {
		return pool;
	} // TEMPORARY, DONT LIKE PASSING THIS DATA OUT!

	public void dump(DataOutputStream file) throws IOException {
		file.writeShort(poolSize);
		for (int i = 1; i < poolSize; i++)
			if (pool[i] != null)
				pool[i].dump(file);
	}

	public ConstantUtf8 getConstantUtf8(int index) {
		Constant c = getConstant(index);
		assert c != null;
		assert c.tag == Constants.CONSTANT_Utf8;
		return (ConstantUtf8) c;
	}
	
	public ConstantModule getConstantModule(int index) {
		Constant c = getConstant(index);
		assert c != null;
		assert c.tag == Constants.CONSTANT_Module;
		return (ConstantModule)c;
	}

	public ConstantPackage getConstantPackage(int index) {
		Constant c = getConstant(index);
		assert c != null;
		assert c.tag == Constants.CONSTANT_Package;
		return (ConstantPackage)c;
	}

	public String getConstantString_CONSTANTClass(int index) {
		ConstantClass c = (ConstantClass) getConstant(index, Constants.CONSTANT_Class);
		index = c.getNameIndex();
		return ((ConstantUtf8) getConstant(index, Constants.CONSTANT_Utf8)).getValue();
	}

	public int getLength() {
		return poolSize;
	}

	@Override
	public String toString() {
		StringBuffer buf = new StringBuffer();

		for (int i = 1; i < poolSize; i++)
			buf.append(i + ")" + pool[i] + "\n");

		return buf.toString();
	}

	public int lookupInteger(int n) {
		for (int i = 1; i < poolSize; i++) {
			if (pool[i] instanceof ConstantInteger) {
				ConstantInteger c = (ConstantInteger) pool[i];
				if (c.getValue() == n)
					return i;
			}
		}
		return -1;
	}

	public int lookupUtf8(String string) {
		Integer pos = utf8Cache.get(string);
		if (pos != null) {
			return pos;
		}
		for (int i = 1; i < poolSize; i++) {
			Constant c = pool[i];
			if (c != null && c.tag == Constants.CONSTANT_Utf8) {
				if (((ConstantUtf8) c).getValue().equals(string)) {
					utf8Cache.put(string, i);
					return i;
				}
			}
		}
		return -1;
	}

	public int lookupClass(String classname) {
		for (int i = 1; i < poolSize; i++) {
			Constant c = pool[i];
			if (c != null && c.tag == Constants.CONSTANT_Class) {
				int cIndex = ((ConstantClass) c).getNameIndex();
				String cName = ((ConstantUtf8) pool[cIndex]).getValue();
				if (cName.equals(classname))
					return i;
			}
		}
		return -1;
	}

	public int addUtf8(String n) {
		int ret = lookupUtf8(n);
		if (ret != -1)
			return ret;
		adjustSize();
		ret = poolSize;
		pool[poolSize++] = new ConstantUtf8(n);
		return ret;
	}

	public int addInteger(int n) {
		int ret = lookupInteger(n);
		if (ret != -1)
			return ret;
		adjustSize();
		ret = poolSize;
		pool[poolSize++] = new ConstantInteger(n);
		return ret;
	}

	public int addArrayClass(ArrayType type) {
		return addClass(type.getSignature());
	}

	public int addClass(ObjectType type) {
		return addClass(type.getClassName());
	}

	public int addClass(String classname) {
		String toAdd = classname.replace('.', '/');
		int ret = lookupClass(toAdd);
		if (ret != -1)
			return ret;
		adjustSize();
		ConstantClass c = new ConstantClass(addUtf8(toAdd));
		ret = poolSize;
		pool[poolSize++] = c;
		return ret;
	}

	private void adjustSize() {
		if (poolSize + 3 >= pool.length) {
			Constant[] cs = pool;
			pool = new Constant[cs.length + 8];
			System.arraycopy(cs, 0, pool, 0, cs.length);
		}
		if (poolSize == 0)
			poolSize = 1; // someone about to do something in here!
	}

	public int addFieldref(String class_name, String field_name, String signature) {
		int ret = lookupFieldref(class_name, field_name, signature);
		int class_index, name_and_type_index;

		if (ret != -1)
			return ret;

		adjustSize();

		class_index = addClass(class_name);
		name_and_type_index = addNameAndType(field_name, signature);
		ret = poolSize;
		pool[poolSize++] = new ConstantFieldref(class_index, name_and_type_index);

		return ret;
	}

	public int lookupFieldref(String searchClassname, String searchFieldname, String searchSignature) {
		searchClassname = searchClassname.replace('.', '/');
		String k = new StringBuffer().append(searchClassname).append(searchFieldname).append(searchSignature).toString();
		Integer pos = fieldCache.get(k);
		if (pos != null)
			return pos.intValue();
		for (int i = 1; i < poolSize; i++) {
			Constant c = pool[i];
			if (c != null && c.tag == Constants.CONSTANT_Fieldref) {
				ConstantFieldref cfr = (ConstantFieldref) c;
				ConstantNameAndType cnat = (ConstantNameAndType) pool[cfr.getNameAndTypeIndex()];

				// check the class
				int cIndex = cfr.getClassIndex();
				ConstantClass cc = (ConstantClass) pool[cIndex];
				String cName = ((ConstantUtf8) pool[cc.getNameIndex()]).getValue();
				if (!cName.equals(searchClassname))
					continue;

				// check the name and type
				String name = ((ConstantUtf8) pool[cnat.getNameIndex()]).getValue();
				if (!name.equals(searchFieldname))
					continue; // not this one
				String typeSignature = ((ConstantUtf8) pool[cnat.getSignatureIndex()]).getValue();
				if (!typeSignature.equals(searchSignature))
					continue;
				fieldCache.put(k, new Integer(i));
				return i;
			}
		}
		return -1;
	}

	public int addNameAndType(String name, String signature) {
		int ret = lookupNameAndType(name, signature);
		if (ret != -1)
			return ret;
		adjustSize();
		int name_index = addUtf8(name);
		int signature_index = addUtf8(signature);
		ret = poolSize;
		pool[poolSize++] = new ConstantNameAndType(name_index, signature_index);
		return ret;
	}

	public int lookupNameAndType(String searchName, String searchTypeSignature) {
		for (int i = 1; i < poolSize; i++) {
			Constant c = pool[i];
			if (c != null && c.tag == Constants.CONSTANT_NameAndType) {
				ConstantNameAndType cnat = (ConstantNameAndType) c;
				String name = ((ConstantUtf8) pool[cnat.getNameIndex()]).getValue();
				if (!name.equals(searchName))
					continue; // not this one
				String typeSignature = ((ConstantUtf8) pool[cnat.getSignatureIndex()]).getValue();
				if (!typeSignature.equals(searchTypeSignature))
					continue;
				return i;
			}
		}
		return -1;
	}

	public int addFloat(float f) {
		int ret = lookupFloat(f);
		if (ret != -1)
			return ret;
		adjustSize();
		ret = poolSize;
		pool[poolSize++] = new ConstantFloat(f);
		return ret;
	}

	public int lookupFloat(float f) {
		int bits = Float.floatToIntBits(f);
		for (int i = 1; i < poolSize; i++) {
			Constant c = pool[i];
			if (c != null && c.tag == Constants.CONSTANT_Float) {
				ConstantFloat cf = (ConstantFloat) c;
				if (Float.floatToIntBits(cf.getValue()) == bits)
					return i;
			}
		}
		return -1;
	}

	public int addDouble(double d) {
		int ret = lookupDouble(d);
		if (ret != -1)
			return ret;
		adjustSize();
		ret = poolSize;
		pool[poolSize] = new ConstantDouble(d);
		poolSize += 2;
		return ret;
	}

	public int lookupDouble(double d) {
		long bits = Double.doubleToLongBits(d);
		for (int i = 1; i < poolSize; i++) {
			Constant c = pool[i];
			if (c != null && c.tag == Constants.CONSTANT_Double) {
				ConstantDouble cf = (ConstantDouble) c;
				if (Double.doubleToLongBits(cf.getValue()) == bits)
					return i;
			}
		}
		return -1;
	}

	public int addLong(long l) {
		int ret = lookupLong(l);
		if (ret != -1)
			return ret;
		adjustSize();
		ret = poolSize;
		pool[poolSize] = new ConstantLong(l);
		poolSize += 2;
		return ret;
	}

	public int lookupString(String s) {
		for (int i = 1; i < poolSize; i++) {
			Constant c = pool[i];
			if (c != null && c.tag == Constants.CONSTANT_String) {
				ConstantString cs = (ConstantString) c;
				ConstantUtf8 cu8 = (ConstantUtf8) pool[cs.getStringIndex()];
				if (cu8.getValue().equals(s))
					return i;
			}
		}
		return -1;
	}

	public int addString(String str) {
		int ret = lookupString(str);
		if (ret != -1)
			return ret;
		int utf8 = addUtf8(str);
		adjustSize();
		ConstantString s = new ConstantString(utf8);
		ret = poolSize;
		pool[poolSize++] = s;
		return ret;
	}

	public int lookupLong(long l) {
		for (int i = 1; i < poolSize; i++) {
			Constant c = pool[i];
			if (c != null && c.tag == Constants.CONSTANT_Long) {
				ConstantLong cf = (ConstantLong) c;
				if (cf.getValue() == l)
					return i;
			}
		}
		return -1;
	}

	public int addConstant(Constant c, ConstantPool cp) {
		Constant[] constants = cp.getConstantPool();
		switch (c.getTag()) {

		case Constants.CONSTANT_String: {
			ConstantString s = (ConstantString) c;
			ConstantUtf8 u8 = (ConstantUtf8) constants[s.getStringIndex()];

			return addString(u8.getValue());
		}

		case Constants.CONSTANT_Class: {
			ConstantClass s = (ConstantClass) c;
			ConstantUtf8 u8 = (ConstantUtf8) constants[s.getNameIndex()];

			return addClass(u8.getValue());
		}

		case Constants.CONSTANT_NameAndType: {
			ConstantNameAndType n = (ConstantNameAndType) c;
			ConstantUtf8 u8 = (ConstantUtf8) constants[n.getNameIndex()];
			ConstantUtf8 u8_2 = (ConstantUtf8) constants[n.getSignatureIndex()];

			return addNameAndType(u8.getValue(), u8_2.getValue());
		}
		
		case Constants.CONSTANT_InvokeDynamic: {
			ConstantInvokeDynamic cid = (ConstantInvokeDynamic)c;
			int index1 = cid.getBootstrapMethodAttrIndex();
			ConstantNameAndType cnat = (ConstantNameAndType)constants[cid.getNameAndTypeIndex()];
			ConstantUtf8 name = (ConstantUtf8) constants[cnat.getNameIndex()];
			ConstantUtf8 signature = (ConstantUtf8) constants[cnat.getSignatureIndex()];
			int index2 = addNameAndType(name.getValue(), signature.getValue());
			return addInvokeDynamic(index1,index2);
		}
		
		case Constants.CONSTANT_MethodHandle:
			ConstantMethodHandle cmh = (ConstantMethodHandle)c;
			return addMethodHandle(cmh.getReferenceKind(),addConstant(constants[cmh.getReferenceIndex()],cp));

		case Constants.CONSTANT_Utf8:
			return addUtf8(((ConstantUtf8) c).getValue());

		case Constants.CONSTANT_Double:
			return addDouble(((ConstantDouble) c).getValue());

		case Constants.CONSTANT_Float:
			return addFloat(((ConstantFloat) c).getValue());

		case Constants.CONSTANT_Long:
			return addLong(((ConstantLong) c).getValue());

		case Constants.CONSTANT_Integer:
			return addInteger(((ConstantInteger) c).getValue());
			
		case Constants.CONSTANT_MethodType:
			ConstantMethodType cmt = (ConstantMethodType)c;
			return addMethodType(addConstant(constants[cmt.getDescriptorIndex()],cp));

		case Constants.CONSTANT_InterfaceMethodref:
		case Constants.CONSTANT_Methodref:
		case Constants.CONSTANT_Fieldref: {
			ConstantCP m = (ConstantCP) c;
			ConstantClass clazz = (ConstantClass) constants[m.getClassIndex()];
			ConstantNameAndType n = (ConstantNameAndType) constants[m.getNameAndTypeIndex()];
			ConstantUtf8 u8 = (ConstantUtf8) constants[clazz.getNameIndex()];
			String class_name = u8.getValue().replace('/', '.');

			u8 = (ConstantUtf8) constants[n.getNameIndex()];
			String name = u8.getValue();

			u8 = (ConstantUtf8) constants[n.getSignatureIndex()];
			String signature = u8.getValue();

			switch (c.getTag()) {
			case Constants.CONSTANT_InterfaceMethodref:
				return addInterfaceMethodref(class_name, name, signature);

			case Constants.CONSTANT_Methodref:
				return addMethodref(class_name, name, signature); // OPTIMIZE indicate it should be cached!

			case Constants.CONSTANT_Fieldref:
				return addFieldref(class_name, name, signature);

			default: // Never reached
				throw new RuntimeException("Unknown constant type " + c);
			}
		}

		default: // Never reached
			throw new RuntimeException("Unknown constant type " + c);
		}
	}
	
	public int addMethodHandle(byte referenceKind, int referenceIndex) {
		adjustSize();
		int ret = poolSize;
		pool[poolSize++] = new ConstantMethodHandle(referenceKind, referenceIndex);
		return ret;
	}
	
	public int addMethodType(int descriptorIndex) {
		adjustSize();
		int ret = poolSize;
		pool[poolSize++] = new ConstantMethodType(descriptorIndex);
		return ret;
	}

	// OPTIMIZE should put it in the cache now
	public int addMethodref(String class_name, String method_name, String signature) {
		int ret, class_index, name_and_type_index;
		if ((ret = lookupMethodref(class_name, method_name, signature)) != -1)
			return ret; // Already in CP

		adjustSize();

		name_and_type_index = addNameAndType(method_name, signature);
		class_index = addClass(class_name);
		ret = poolSize;
		pool[poolSize++] = new ConstantMethodref(class_index, name_and_type_index);
		return ret;
	}
	
	public int addInvokeDynamic(int bootstrapMethodIndex, int constantNameAndTypeIndex) {
		adjustSize();
		int ret = poolSize;
		pool[poolSize++] = new ConstantInvokeDynamic(bootstrapMethodIndex, constantNameAndTypeIndex);
		return ret;
	}

	public int addInterfaceMethodref(String class_name, String method_name, String signature) {
		int ret = lookupInterfaceMethodref(class_name, method_name, signature);
		int class_index, name_and_type_index;

		if (ret != -1)
			return ret;
		adjustSize();

		class_index = addClass(class_name);
		name_and_type_index = addNameAndType(method_name, signature);
		ret = poolSize;
		pool[poolSize++] = new ConstantInterfaceMethodref(class_index, name_and_type_index);
		return ret;
	}

	public int lookupInterfaceMethodref(String searchClassname, String searchMethodName, String searchSignature) {
		searchClassname = searchClassname.replace('.', '/');
		for (int i = 1; i < poolSize; i++) {
			Constant c = pool[i];
			if (c != null && c.tag == Constants.CONSTANT_InterfaceMethodref) {
				ConstantInterfaceMethodref cfr = (ConstantInterfaceMethodref) c;

				ConstantClass cc = (ConstantClass) pool[cfr.getClassIndex()];
				String cName = ((ConstantUtf8) pool[cc.getNameIndex()]).getValue();
				if (!cName.equals(searchClassname))
					continue;

				// check the name and type
				ConstantNameAndType cnat = (ConstantNameAndType) pool[cfr.getNameAndTypeIndex()];
				String name = ((ConstantUtf8) pool[cnat.getNameIndex()]).getValue();
				if (!name.equals(searchMethodName))
					continue; // not this one
				String typeSignature = ((ConstantUtf8) pool[cnat.getSignatureIndex()]).getValue();
				if (!typeSignature.equals(searchSignature))
					continue;
				return i;
			}
		}
		return -1;
	}

	public int lookupMethodref(String searchClassname, String searchMethodName, String searchSignature) {
		String key = new StringBuffer().append(searchClassname).append(searchMethodName).append(searchSignature).toString();
		Integer cached = methodCache.get(key);
		if (cached != null)
			return cached.intValue();
		searchClassname = searchClassname.replace('.', '/');
		for (int i = 1; i < poolSize; i++) {
			Constant c = pool[i];
			if (c != null && c.tag == Constants.CONSTANT_Methodref) {
				ConstantMethodref cfr = (ConstantMethodref) c;
				ConstantNameAndType cnat = (ConstantNameAndType) pool[cfr.getNameAndTypeIndex()];

				// check the class
				int cIndex = cfr.getClassIndex();
				ConstantClass cc = (ConstantClass) pool[cIndex];
				String cName = ((ConstantUtf8) pool[cc.getNameIndex()]).getValue();
				if (!cName.equals(searchClassname))
					continue;

				// check the name and type
				String name = ((ConstantUtf8) pool[cnat.getNameIndex()]).getValue();
				if (!name.equals(searchMethodName))
					continue; // not this one
				String typeSignature = ((ConstantUtf8) pool[cnat.getSignatureIndex()]).getValue();
				if (!typeSignature.equals(searchSignature))
					continue;
				methodCache.put(key, new Integer(i));
				return i;
			}
		}
		return -1;
	}

	public ConstantPool getFinalConstantPool() {
		Constant[] cs = new Constant[poolSize]; // create it the exact size we need
		System.arraycopy(pool, 0, cs, 0, poolSize);
		return new ConstantPool(cs);
	}

	public String getModuleName(int moduleIndex) {
		return getConstantModule(moduleIndex).getModuleName(this);
	}

	public String getPackageName(int packageIndex) {
		return getConstantPackage(packageIndex).getPackageName(this);
	}
}