git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@1087 379699f6-c40d-0410-875b-85095c16579ebranch_1_1
parent
48d5c63aec
commit
6786a3fa35
@ -1,785 +0,0 @@ |
|||||||
/* ClassInfo Copyright (C) 1998-1999 Jochen Hoenicke. |
|
||||||
* |
|
||||||
* This program is free software; you can redistribute it and/or modify |
|
||||||
* it under the terms of the GNU General Public License as published by |
|
||||||
* the Free Software Foundation; either version 2, or (at your option) |
|
||||||
* any later version. |
|
||||||
* |
|
||||||
* This program 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 for more details. |
|
||||||
* |
|
||||||
* You should have received a copy of the GNU General Public License |
|
||||||
* along with this program; see the file COPYING. If not, write to |
|
||||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. |
|
||||||
* |
|
||||||
* $Id$ |
|
||||||
*/ |
|
||||||
|
|
||||||
package jode.bytecode; |
|
||||||
import jode.GlobalOptions; |
|
||||||
import java.io.DataInputStream; |
|
||||||
import java.io.DataOutputStream; |
|
||||||
import java.io.IOException; |
|
||||||
import java.util.Enumeration; |
|
||||||
///#ifdef JDK12
|
|
||||||
///import java.util.Map;
|
|
||||||
///import java.util.HashMap;
|
|
||||||
///import java.lang.ref.WeakReference;
|
|
||||||
///import java.lang.ref.ReferenceQueue;
|
|
||||||
///#else
|
|
||||||
import java.util.Hashtable; |
|
||||||
///#endif
|
|
||||||
import java.lang.reflect.Field; |
|
||||||
import java.lang.reflect.Method; |
|
||||||
import java.lang.reflect.Modifier; |
|
||||||
|
|
||||||
/** |
|
||||||
* This class does represent a class similar to java.lang.Class. You |
|
||||||
* can get the super class and the interfaces. |
|
||||||
* |
|
||||||
* The main difference to java.lang.Class is, that the objects are builded |
|
||||||
* from a stream containing the .class file, and that it uses the |
|
||||||
* <code>Type</code> to represent types instead of Class itself. |
|
||||||
* |
|
||||||
* @author Jochen Hoenicke |
|
||||||
*/ |
|
||||||
public class ClassInfo extends BinaryInfo { |
|
||||||
|
|
||||||
private static SearchPath classpath; |
|
||||||
///#ifdef JDK12
|
|
||||||
/// private static final Map classes = new HashMap();
|
|
||||||
/// private static final ReferenceQueue queue = new ReferenceQueue();
|
|
||||||
///#else
|
|
||||||
private static final Hashtable classes = new Hashtable(); |
|
||||||
///#endif
|
|
||||||
|
|
||||||
private int status = 0; |
|
||||||
|
|
||||||
private boolean modified = false; |
|
||||||
|
|
||||||
private int modifiers = -1; |
|
||||||
private String name; |
|
||||||
private ClassInfo superclass; |
|
||||||
private ClassInfo[] interfaces; |
|
||||||
private FieldInfo[] fields; |
|
||||||
private MethodInfo[] methods; |
|
||||||
private InnerClassInfo[] outerClasses; |
|
||||||
private InnerClassInfo[] innerClasses; |
|
||||||
private InnerClassInfo[] extraClasses; |
|
||||||
private String sourceFile; |
|
||||||
|
|
||||||
public final static ClassInfo javaLangObject = forName("java.lang.Object"); |
|
||||||
|
|
||||||
public static void setClassPath(String path) { |
|
||||||
classpath = new SearchPath(path); |
|
||||||
///#ifdef JDK12
|
|
||||||
/// java.lang.ref.Reference died;
|
|
||||||
/// while ((died = queue.poll()) != null) {
|
|
||||||
/// classes.values().remove(died);
|
|
||||||
/// }
|
|
||||||
/// Iterator i = classes.values().iterator();
|
|
||||||
/// while (i.hasNext()) {
|
|
||||||
/// ClassInfo ci = (ClassInfo) ((WeakReference)i.next()).get();
|
|
||||||
/// if (ci == null) {
|
|
||||||
/// i.remove();
|
|
||||||
/// continue;
|
|
||||||
/// }
|
|
||||||
///#else
|
|
||||||
Enumeration enum = classes.elements(); |
|
||||||
while (enum.hasMoreElements()) { |
|
||||||
ClassInfo ci = (ClassInfo) enum.nextElement(); |
|
||||||
///#endif
|
|
||||||
ci.status = 0; |
|
||||||
ci.superclass = null; |
|
||||||
ci.fields = null; |
|
||||||
ci.interfaces = null; |
|
||||||
ci.methods = null; |
|
||||||
ci.removeAllAttributes(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public static boolean exists(String name) { |
|
||||||
return classpath.exists(name.replace('.', '/') + ".class"); |
|
||||||
} |
|
||||||
|
|
||||||
public static boolean isPackage(String name) { |
|
||||||
return classpath.isDirectory(name.replace('.', '/')); |
|
||||||
} |
|
||||||
|
|
||||||
public static Enumeration getClassesAndPackages(final String packageName) { |
|
||||||
final Enumeration enum = |
|
||||||
classpath.listFiles(packageName.replace('.','/')); |
|
||||||
return new Enumeration() { |
|
||||||
public boolean hasMoreElements() { |
|
||||||
return enum.hasMoreElements(); |
|
||||||
} |
|
||||||
public Object nextElement() { |
|
||||||
String name = (String) enum.nextElement(); |
|
||||||
if (!name.endsWith(".class")) |
|
||||||
// This is a package
|
|
||||||
return name; |
|
||||||
return name.substring(0, name.length()-6); |
|
||||||
|
|
||||||
} |
|
||||||
}; |
|
||||||
} |
|
||||||
|
|
||||||
public static ClassInfo forName(String name) { |
|
||||||
if (name == null |
|
||||||
|| name.indexOf(';') != -1 |
|
||||||
|| name.indexOf('[') != -1 |
|
||||||
|| name.indexOf('/') != -1) |
|
||||||
throw new IllegalArgumentException("Illegal class name: "+name); |
|
||||||
|
|
||||||
///#ifdef JDK12
|
|
||||||
/// java.lang.ref.Reference died;
|
|
||||||
/// while ((died = queue.poll()) != null) {
|
|
||||||
/// classes.values().remove(died);
|
|
||||||
/// }
|
|
||||||
/// WeakReference ref = (WeakReference) classes.get(name);
|
|
||||||
/// ClassInfo clazz = (ref == null) ? null : (ClassInfo) ref.get();
|
|
||||||
///#else
|
|
||||||
ClassInfo clazz = (ClassInfo) classes.get(name); |
|
||||||
///#endif
|
|
||||||
if (clazz == null) { |
|
||||||
clazz = new ClassInfo(name); |
|
||||||
///#ifdef JDK12
|
|
||||||
/// classes.put(name, new WeakReference(clazz, queue));
|
|
||||||
///#else
|
|
||||||
classes.put(name, clazz); |
|
||||||
///#endif
|
|
||||||
} |
|
||||||
return clazz; |
|
||||||
} |
|
||||||
|
|
||||||
private ClassInfo(String name) { |
|
||||||
this.name = name; |
|
||||||
} |
|
||||||
|
|
||||||
protected void readAttribute(String name, int length, |
|
||||||
ConstantPool cp, |
|
||||||
DataInputStream input, |
|
||||||
int howMuch) throws IOException { |
|
||||||
if ((howMuch & ALL_ATTRIBUTES) != 0 && name.equals("SourceFile")) { |
|
||||||
if (length != 2) |
|
||||||
throw new ClassFormatException("SourceFile attribute" |
|
||||||
+ " has wrong length"); |
|
||||||
sourceFile = cp.getUTF8(input.readUnsignedShort()); |
|
||||||
} else if ((howMuch & (OUTERCLASSES | INNERCLASSES)) != 0 |
|
||||||
&& name.equals("InnerClasses")) { |
|
||||||
int count = input.readUnsignedShort(); |
|
||||||
int innerCount = 0, outerCount = 0, extraCount = 0; |
|
||||||
InnerClassInfo[] innerClassInfo = new InnerClassInfo[count]; |
|
||||||
for (int i=0; i< count; i++) { |
|
||||||
int innerIndex = input.readUnsignedShort(); |
|
||||||
int outerIndex = input.readUnsignedShort(); |
|
||||||
int nameIndex = input.readUnsignedShort(); |
|
||||||
String inner = cp.getClassName(innerIndex); |
|
||||||
String outer = |
|
||||||
outerIndex != 0 ? cp.getClassName(outerIndex) : null; |
|
||||||
String innername = |
|
||||||
nameIndex != 0 ? cp.getUTF8(nameIndex) : null; |
|
||||||
int access = input.readUnsignedShort(); |
|
||||||
if (innername != null && innername.length() == 0) |
|
||||||
innername = null; |
|
||||||
InnerClassInfo ici = new InnerClassInfo |
|
||||||
(inner, outer, innername, access); |
|
||||||
|
|
||||||
if (outer != null && outer.equals(getName()) |
|
||||||
&& innername != null) |
|
||||||
innerClassInfo[innerCount++] = ici; |
|
||||||
else |
|
||||||
innerClassInfo[count - (++extraCount)] = ici; |
|
||||||
} |
|
||||||
{ |
|
||||||
String lastOuterName = getName(); |
|
||||||
for (int i = count - extraCount; i < count; i++) { |
|
||||||
InnerClassInfo ici = innerClassInfo[i]; |
|
||||||
if (ici.inner.equals(lastOuterName)) { |
|
||||||
for (int j = i; j > count - extraCount; j--) |
|
||||||
innerClassInfo[j] = innerClassInfo[j-1]; |
|
||||||
innerClassInfo[count-extraCount] = ici; |
|
||||||
extraCount--; |
|
||||||
outerCount++; |
|
||||||
lastOuterName = ici.outer; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
if (innerCount > 0) { |
|
||||||
innerClasses = new InnerClassInfo[innerCount]; |
|
||||||
System.arraycopy(innerClassInfo, 0, |
|
||||||
innerClasses, 0, innerCount); |
|
||||||
} else |
|
||||||
innerClasses = null; |
|
||||||
|
|
||||||
if (outerCount > 0) { |
|
||||||
outerClasses = new InnerClassInfo[outerCount]; |
|
||||||
System.arraycopy(innerClassInfo, innerCount, |
|
||||||
outerClasses, 0, outerCount); |
|
||||||
} else |
|
||||||
outerClasses = null; |
|
||||||
|
|
||||||
if (extraCount > 0) { |
|
||||||
extraClasses = new InnerClassInfo[extraCount]; |
|
||||||
System.arraycopy(innerClassInfo, innerCount + outerCount, |
|
||||||
extraClasses, 0, extraCount); |
|
||||||
} else |
|
||||||
extraClasses = null; |
|
||||||
|
|
||||||
if (length != 2 + 8 * count) |
|
||||||
throw new ClassFormatException |
|
||||||
("InnerClasses attribute has wrong length"); |
|
||||||
} else |
|
||||||
super.readAttribute(name, length, cp, input, howMuch); |
|
||||||
} |
|
||||||
|
|
||||||
public void read(DataInputStream input, int howMuch) throws IOException { |
|
||||||
/* Since we have to read the whole class anyway, we load all |
|
||||||
* info, that we may need later and that does not take much memory. |
|
||||||
*/ |
|
||||||
howMuch |= FIELDS | METHODS | HIERARCHY | INNERCLASSES | OUTERCLASSES; |
|
||||||
howMuch &= ~status; |
|
||||||
/* header */ |
|
||||||
if (input.readInt() != 0xcafebabe) |
|
||||||
throw new ClassFormatException("Wrong magic"); |
|
||||||
if (input.readUnsignedShort() > 3) |
|
||||||
throw new ClassFormatException("Wrong minor"); |
|
||||||
if (input.readUnsignedShort() != 45) |
|
||||||
throw new ClassFormatException("Wrong major"); |
|
||||||
|
|
||||||
/* constant pool */ |
|
||||||
ConstantPool cpool = new ConstantPool(); |
|
||||||
cpool.read(input); |
|
||||||
|
|
||||||
/* always read modifiers, name, super, ifaces */ |
|
||||||
{ |
|
||||||
modifiers = input.readUnsignedShort(); |
|
||||||
String className = cpool.getClassName(input.readUnsignedShort()); |
|
||||||
if (!name.equals(className)) |
|
||||||
throw new ClassFormatException("wrong name " + className); |
|
||||||
String superName = cpool.getClassName(input.readUnsignedShort()); |
|
||||||
superclass = superName != null ? ClassInfo.forName(superName) : null; |
|
||||||
int count = input.readUnsignedShort(); |
|
||||||
interfaces = new ClassInfo[count]; |
|
||||||
for (int i=0; i< count; i++) { |
|
||||||
interfaces[i] = ClassInfo.forName |
|
||||||
(cpool.getClassName(input.readUnsignedShort())); |
|
||||||
} |
|
||||||
status |= HIERARCHY; |
|
||||||
} |
|
||||||
|
|
||||||
/* fields */ |
|
||||||
if ((howMuch & (FIELDS | ALL_ATTRIBUTES)) != 0) { |
|
||||||
int count = input.readUnsignedShort(); |
|
||||||
if ((howMuch & FIELDS) != 0) |
|
||||||
fields = new FieldInfo[count]; |
|
||||||
for (int i=0; i< count; i++) { |
|
||||||
if ((howMuch & FIELDS) != 0) |
|
||||||
fields[i] = new FieldInfo(this); |
|
||||||
fields[i].read(cpool, input, howMuch); |
|
||||||
} |
|
||||||
} else { |
|
||||||
byte[] skipBuf = new byte[6]; |
|
||||||
int count = input.readUnsignedShort(); |
|
||||||
for (int i=0; i< count; i++) { |
|
||||||
input.readFully(skipBuf); // modifier, name, type
|
|
||||||
skipAttributes(input); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/* methods */ |
|
||||||
if ((howMuch & (METHODS | ALL_ATTRIBUTES)) != 0) { |
|
||||||
int count = input.readUnsignedShort(); |
|
||||||
if ((howMuch & METHODS) != 0) |
|
||||||
methods = new MethodInfo[count]; |
|
||||||
for (int i=0; i< count; i++) { |
|
||||||
if ((howMuch & METHODS) != 0) |
|
||||||
methods[i] = new MethodInfo(this); |
|
||||||
methods[i].read(cpool, input, howMuch); |
|
||||||
} |
|
||||||
} else { |
|
||||||
byte[] skipBuf = new byte[6]; |
|
||||||
int count = input.readUnsignedShort(); |
|
||||||
for (int i=0; i< count; i++) { |
|
||||||
input.readFully(skipBuf); // modifier, name, type
|
|
||||||
skipAttributes(input); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/* attributes */ |
|
||||||
readAttributes(cpool, input, howMuch); |
|
||||||
status |= howMuch; |
|
||||||
} |
|
||||||
|
|
||||||
public void reserveSmallConstants(GrowableConstantPool gcp) { |
|
||||||
for (int i=0; i < fields.length; i++) |
|
||||||
fields[i].reserveSmallConstants(gcp); |
|
||||||
|
|
||||||
for (int i=0; i < methods.length; i++) |
|
||||||
methods[i].reserveSmallConstants(gcp); |
|
||||||
} |
|
||||||
|
|
||||||
public void prepareWriting(GrowableConstantPool gcp) { |
|
||||||
gcp.putClassName(name); |
|
||||||
gcp.putClassName(superclass.getName()); |
|
||||||
for (int i=0; i < interfaces.length; i++) |
|
||||||
gcp.putClassName(interfaces[i].getName()); |
|
||||||
|
|
||||||
for (int i=0; i < fields.length; i++) |
|
||||||
fields[i].prepareWriting(gcp); |
|
||||||
|
|
||||||
for (int i=0; i < methods.length; i++) |
|
||||||
methods[i].prepareWriting(gcp); |
|
||||||
|
|
||||||
if (sourceFile != null) { |
|
||||||
gcp.putUTF8("SourceFile"); |
|
||||||
gcp.putUTF8(sourceFile); |
|
||||||
} |
|
||||||
if (outerClasses != null || innerClasses != null |
|
||||||
|| extraClasses != null) { |
|
||||||
gcp.putUTF8("InnerClasses"); |
|
||||||
int outerCount = outerClasses != null ? outerClasses.length : 0; |
|
||||||
for (int i=outerCount; i-- > 0;) { |
|
||||||
gcp.putClassName(outerClasses[i].inner); |
|
||||||
if (outerClasses[i].outer != null) |
|
||||||
gcp.putClassName(outerClasses[i].outer); |
|
||||||
if (outerClasses[i].name != null) |
|
||||||
gcp.putUTF8(outerClasses[i].name); |
|
||||||
} |
|
||||||
int innerCount = innerClasses != null ? innerClasses.length : 0; |
|
||||||
for (int i=0; i< innerCount; i++) { |
|
||||||
gcp.putClassName(innerClasses[i].inner); |
|
||||||
if (innerClasses[i].outer != null) |
|
||||||
gcp.putClassName(innerClasses[i].outer); |
|
||||||
if (innerClasses[i].name != null) |
|
||||||
gcp.putUTF8(innerClasses[i].name); |
|
||||||
} |
|
||||||
int extraCount = extraClasses != null ? extraClasses.length : 0; |
|
||||||
for (int i=0; i< extraCount; i++) { |
|
||||||
gcp.putClassName(extraClasses[i].inner); |
|
||||||
if (extraClasses[i].outer != null) |
|
||||||
gcp.putClassName(extraClasses[i].outer); |
|
||||||
if (extraClasses[i].name != null) |
|
||||||
gcp.putUTF8(extraClasses[i].name); |
|
||||||
} |
|
||||||
} |
|
||||||
prepareAttributes(gcp); |
|
||||||
} |
|
||||||
|
|
||||||
protected int getKnownAttributeCount() { |
|
||||||
int count = 0; |
|
||||||
if (sourceFile != null) |
|
||||||
count++; |
|
||||||
if (innerClasses != null || outerClasses != null |
|
||||||
|| extraClasses != null) |
|
||||||
count++; |
|
||||||
return count; |
|
||||||
} |
|
||||||
|
|
||||||
public void writeKnownAttributes(GrowableConstantPool gcp, |
|
||||||
DataOutputStream output) |
|
||||||
throws IOException { |
|
||||||
if (sourceFile != null) { |
|
||||||
output.writeShort(gcp.putUTF8("SourceFile")); |
|
||||||
output.writeInt(2); |
|
||||||
output.writeShort(gcp.putUTF8(sourceFile)); |
|
||||||
} |
|
||||||
if (outerClasses != null || innerClasses != null |
|
||||||
|| extraClasses != null) { |
|
||||||
output.writeShort(gcp.putUTF8("InnerClasses")); |
|
||||||
int outerCount = (outerClasses != null) ? outerClasses.length : 0; |
|
||||||
int innerCount = (innerClasses != null) ? innerClasses.length : 0; |
|
||||||
int extraCount = (extraClasses != null) ? extraClasses.length : 0; |
|
||||||
int count = outerCount + innerCount + extraCount; |
|
||||||
output.writeInt(2 + count * 8); |
|
||||||
output.writeShort(count); |
|
||||||
for (int i=outerCount; i-- > 0; ) { |
|
||||||
output.writeShort(gcp.putClassName(outerClasses[i].inner)); |
|
||||||
output.writeShort(outerClasses[i].outer != null ? |
|
||||||
gcp.putClassName(outerClasses[i].outer) : 0); |
|
||||||
output.writeShort(outerClasses[i].name != null ? |
|
||||||
gcp.putUTF8(outerClasses[i].name) : 0); |
|
||||||
output.writeShort(outerClasses[i].modifiers); |
|
||||||
} |
|
||||||
for (int i=0; i< innerCount; i++) { |
|
||||||
output.writeShort(gcp.putClassName(innerClasses[i].inner)); |
|
||||||
output.writeShort(innerClasses[i].outer != null ? |
|
||||||
gcp.putClassName(innerClasses[i].outer) : 0); |
|
||||||
output.writeShort(innerClasses[i].name != null ? |
|
||||||
gcp.putUTF8(innerClasses[i].name) : 0); |
|
||||||
output.writeShort(innerClasses[i].modifiers); |
|
||||||
} |
|
||||||
for (int i=0; i< extraCount; i++) { |
|
||||||
output.writeShort(gcp.putClassName(extraClasses[i].inner)); |
|
||||||
output.writeShort(extraClasses[i].outer != null ? |
|
||||||
gcp.putClassName(extraClasses[i].outer) : 0); |
|
||||||
output.writeShort(extraClasses[i].name != null ? |
|
||||||
gcp.putUTF8(extraClasses[i].name) : 0); |
|
||||||
output.writeShort(extraClasses[i].modifiers); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public void write(DataOutputStream out) throws IOException { |
|
||||||
GrowableConstantPool gcp = new GrowableConstantPool(); |
|
||||||
reserveSmallConstants(gcp); |
|
||||||
prepareWriting(gcp); |
|
||||||
|
|
||||||
out.writeInt(0xcafebabe); |
|
||||||
out.writeShort(3); |
|
||||||
out.writeShort(45); |
|
||||||
gcp.write(out); |
|
||||||
|
|
||||||
out.writeShort(modifiers); |
|
||||||
out.writeShort(gcp.putClassName(name)); |
|
||||||
out.writeShort(gcp.putClassName(superclass.getName())); |
|
||||||
out.writeShort(interfaces.length); |
|
||||||
for (int i=0; i < interfaces.length; i++) |
|
||||||
out.writeShort(gcp.putClassName(interfaces[i].getName())); |
|
||||||
|
|
||||||
out.writeShort(fields.length); |
|
||||||
for (int i=0; i < fields.length; i++) |
|
||||||
fields[i].write(gcp, out); |
|
||||||
|
|
||||||
out.writeShort(methods.length); |
|
||||||
for (int i=0; i < methods.length; i++) |
|
||||||
methods[i].write(gcp, out); |
|
||||||
|
|
||||||
writeAttributes(gcp, out); |
|
||||||
} |
|
||||||
|
|
||||||
public void loadInfoReflection(Class clazz, int howMuch) |
|
||||||
throws SecurityException { |
|
||||||
if ((howMuch & HIERARCHY) != 0) { |
|
||||||
modifiers = clazz.getModifiers(); |
|
||||||
if (clazz.getSuperclass() == null) |
|
||||||
superclass = null; |
|
||||||
else |
|
||||||
superclass = ClassInfo.forName |
|
||||||
(clazz.getSuperclass().getName()); |
|
||||||
Class[] ifaces = clazz.getInterfaces(); |
|
||||||
interfaces = new ClassInfo[ifaces.length]; |
|
||||||
for (int i=0; i<ifaces.length; i++) |
|
||||||
interfaces[i] = ClassInfo.forName(ifaces[i].getName()); |
|
||||||
status |= HIERARCHY; |
|
||||||
} |
|
||||||
if ((howMuch & FIELDS) != 0 && fields == null) { |
|
||||||
Field[] fs; |
|
||||||
try { |
|
||||||
fs = clazz.getDeclaredFields(); |
|
||||||
} catch (SecurityException ex) { |
|
||||||
fs = clazz.getFields(); |
|
||||||
GlobalOptions.err.println |
|
||||||
("Could only get public fields of class " |
|
||||||
+ name + "."); |
|
||||||
} |
|
||||||
fields = new FieldInfo[fs.length]; |
|
||||||
for (int i = fs.length; --i >= 0; ) { |
|
||||||
String type = TypeSignature.getSignature(fs[i].getType()); |
|
||||||
fields[i] = new FieldInfo |
|
||||||
(this, fs[i].getName(), type, fs[i].getModifiers()); |
|
||||||
} |
|
||||||
} |
|
||||||
if ((howMuch & METHODS) != 0 && methods == null) { |
|
||||||
Method[] ms; |
|
||||||
try { |
|
||||||
ms = clazz.getDeclaredMethods(); |
|
||||||
} catch (SecurityException ex) { |
|
||||||
ms = clazz.getMethods(); |
|
||||||
GlobalOptions.err.println |
|
||||||
("Could only get public methods of class " |
|
||||||
+ name + "."); |
|
||||||
} |
|
||||||
methods = new MethodInfo[ms.length]; |
|
||||||
for (int i = ms.length; --i >= 0; ) { |
|
||||||
String type = TypeSignature.getSignature |
|
||||||
(ms[i].getParameterTypes(), ms[i].getReturnType()); |
|
||||||
methods[i] = new MethodInfo |
|
||||||
(this, ms[i].getName(), type, ms[i].getModifiers()); |
|
||||||
} |
|
||||||
} |
|
||||||
if ((howMuch & INNERCLASSES) != 0 && innerClasses == null) { |
|
||||||
Class[] is; |
|
||||||
try { |
|
||||||
is = clazz.getDeclaredClasses(); |
|
||||||
} catch (SecurityException ex) { |
|
||||||
is = clazz.getClasses(); |
|
||||||
GlobalOptions.err.println |
|
||||||
("Could only get public methods of class " |
|
||||||
+ name + "."); |
|
||||||
} |
|
||||||
if (is.length > 0) { |
|
||||||
innerClasses = new InnerClassInfo[is.length]; |
|
||||||
for (int i = is.length; --i >= 0; ) { |
|
||||||
String inner = is[i].getName(); |
|
||||||
int dollar = inner.lastIndexOf('$'); |
|
||||||
String name = inner.substring(dollar+1); |
|
||||||
innerClasses[i] = new InnerClassInfo |
|
||||||
(inner, getName(), name, is[i].getModifiers()); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
if ((howMuch & OUTERCLASSES) != 0 && outerClasses == null) { |
|
||||||
int count = 0; |
|
||||||
Class declarer = clazz.getDeclaringClass(); |
|
||||||
while (declarer != null) { |
|
||||||
count++; |
|
||||||
declarer = declarer.getDeclaringClass(); |
|
||||||
} |
|
||||||
if (count > 0) { |
|
||||||
outerClasses = new InnerClassInfo[count]; |
|
||||||
Class current = clazz; |
|
||||||
for (int i = 0; i < count; i++) { |
|
||||||
declarer = current.getDeclaringClass(); |
|
||||||
String name = current.getName(); |
|
||||||
int dollar = name.lastIndexOf('$'); |
|
||||||
outerClasses[i] = new InnerClassInfo |
|
||||||
(name, declarer.getName(), |
|
||||||
name.substring(dollar+1), current.getModifiers()); |
|
||||||
current = declarer; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
status |= howMuch; |
|
||||||
} |
|
||||||
|
|
||||||
public void loadInfo(int howMuch) { |
|
||||||
if ((status & howMuch) == howMuch) |
|
||||||
return; |
|
||||||
if (modified) { |
|
||||||
System.err.println("Allocating info 0x" |
|
||||||
+ Integer.toHexString(howMuch) |
|
||||||
+ " (status 0x" + Integer.toHexString(status) |
|
||||||
+ ") in class " + this); |
|
||||||
Thread.dumpStack(); |
|
||||||
return; |
|
||||||
} |
|
||||||
try { |
|
||||||
DataInputStream input = |
|
||||||
new DataInputStream(classpath.getFile(name.replace('.', '/') |
|
||||||
+ ".class")); |
|
||||||
read(input, howMuch); |
|
||||||
|
|
||||||
} catch (IOException ex) { |
|
||||||
String message = ex.getMessage(); |
|
||||||
if ((howMuch & ~(FIELDS|METHODS|HIERARCHY |
|
||||||
|INNERCLASSES|OUTERCLASSES)) != 0) { |
|
||||||
GlobalOptions.err.println |
|
||||||
("Can't read class " + name + "."); |
|
||||||
ex.printStackTrace(GlobalOptions.err); |
|
||||||
throw new NoClassDefFoundError(name); |
|
||||||
} |
|
||||||
// Try getting the info through the reflection interface
|
|
||||||
// instead.
|
|
||||||
Class clazz = null; |
|
||||||
try { |
|
||||||
clazz = Class.forName(name); |
|
||||||
} catch (ClassNotFoundException ex2) { |
|
||||||
} catch (NoClassDefFoundError ex2) { |
|
||||||
} |
|
||||||
try { |
|
||||||
if (clazz != null) { |
|
||||||
loadInfoReflection(clazz, howMuch); |
|
||||||
return; |
|
||||||
} |
|
||||||
} catch (SecurityException ex2) { |
|
||||||
GlobalOptions.err.println |
|
||||||
(ex2+" while collecting info about class " + name + "."); |
|
||||||
} |
|
||||||
|
|
||||||
// Give a warning and ``guess'' the hierarchie, methods etc.
|
|
||||||
GlobalOptions.err.println |
|
||||||
("Can't read class " + name + ", types may be incorrect. (" |
|
||||||
+ ex.getClass().getName() |
|
||||||
+ (message != null ? ": " + message : "") + ")"); |
|
||||||
|
|
||||||
if ((howMuch & HIERARCHY) != 0) { |
|
||||||
modifiers = Modifier.PUBLIC; |
|
||||||
if (name.equals("java.lang.Object")) |
|
||||||
superclass = null; |
|
||||||
else |
|
||||||
superclass = javaLangObject; |
|
||||||
interfaces = new ClassInfo[0]; |
|
||||||
} |
|
||||||
if ((howMuch & METHODS) != 0) |
|
||||||
methods = new MethodInfo[0]; |
|
||||||
if ((howMuch & FIELDS) != 0) |
|
||||||
fields = new FieldInfo[0]; |
|
||||||
status |= howMuch; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public String getName() { |
|
||||||
return name; |
|
||||||
} |
|
||||||
|
|
||||||
public String getJavaName() { |
|
||||||
/* Don't load attributes for class names not containing a |
|
||||||
* dollar sign. |
|
||||||
*/ |
|
||||||
if (name.indexOf('$') == -1) |
|
||||||
return getName(); |
|
||||||
if (getOuterClasses() != null) { |
|
||||||
int last = outerClasses.length-1; |
|
||||||
StringBuffer sb = |
|
||||||
new StringBuffer(outerClasses[last].outer != null |
|
||||||
? outerClasses[last].outer : "METHOD"); |
|
||||||
for (int i=last; i >= 0; i--) |
|
||||||
sb.append(".").append(outerClasses[i].name != null |
|
||||||
? outerClasses[i].name : "ANONYMOUS"); |
|
||||||
return sb.toString(); |
|
||||||
} |
|
||||||
return getName(); |
|
||||||
} |
|
||||||
|
|
||||||
public ClassInfo getSuperclass() { |
|
||||||
if ((status & HIERARCHY) == 0) |
|
||||||
loadInfo(HIERARCHY); |
|
||||||
return superclass; |
|
||||||
} |
|
||||||
|
|
||||||
public ClassInfo[] getInterfaces() { |
|
||||||
if ((status & HIERARCHY) == 0) |
|
||||||
loadInfo(HIERARCHY); |
|
||||||
return interfaces; |
|
||||||
} |
|
||||||
|
|
||||||
public int getModifiers() { |
|
||||||
if ((status & HIERARCHY) == 0) |
|
||||||
loadInfo(HIERARCHY); |
|
||||||
return modifiers; |
|
||||||
} |
|
||||||
|
|
||||||
public boolean isInterface() { |
|
||||||
return Modifier.isInterface(getModifiers()); |
|
||||||
} |
|
||||||
|
|
||||||
public FieldInfo findField(String name, String typeSig) { |
|
||||||
if ((status & FIELDS) == 0) |
|
||||||
loadInfo(FIELDS); |
|
||||||
for (int i=0; i< fields.length; i++) |
|
||||||
if (fields[i].getName().equals(name) |
|
||||||
&& fields[i].getType().equals(typeSig)) |
|
||||||
return fields[i]; |
|
||||||
return null; |
|
||||||
} |
|
||||||
|
|
||||||
public MethodInfo findMethod(String name, String typeSig) { |
|
||||||
if ((status & METHODS) == 0) |
|
||||||
loadInfo(METHODS); |
|
||||||
for (int i=0; i< methods.length; i++) |
|
||||||
if (methods[i].getName().equals(name) |
|
||||||
&& methods[i].getType().equals(typeSig)) |
|
||||||
return methods[i]; |
|
||||||
return null; |
|
||||||
} |
|
||||||
|
|
||||||
public MethodInfo[] getMethods() { |
|
||||||
if ((status & METHODS) == 0) |
|
||||||
loadInfo(METHODS); |
|
||||||
return methods; |
|
||||||
} |
|
||||||
|
|
||||||
public FieldInfo[] getFields() { |
|
||||||
if ((status & FIELDS) == 0) |
|
||||||
loadInfo(FIELDS); |
|
||||||
return fields; |
|
||||||
} |
|
||||||
|
|
||||||
public InnerClassInfo[] getOuterClasses() { |
|
||||||
if ((status & OUTERCLASSES) == 0) |
|
||||||
loadInfo(OUTERCLASSES); |
|
||||||
return outerClasses; |
|
||||||
} |
|
||||||
|
|
||||||
public InnerClassInfo[] getInnerClasses() { |
|
||||||
if ((status & INNERCLASSES) == 0) |
|
||||||
loadInfo(INNERCLASSES); |
|
||||||
return innerClasses; |
|
||||||
} |
|
||||||
|
|
||||||
public InnerClassInfo[] getExtraClasses() { |
|
||||||
if ((status & INNERCLASSES) == 0) |
|
||||||
loadInfo(INNERCLASSES); |
|
||||||
return extraClasses; |
|
||||||
} |
|
||||||
|
|
||||||
public String getSourceFile() { |
|
||||||
return sourceFile; |
|
||||||
} |
|
||||||
|
|
||||||
public void setName(String newName) { |
|
||||||
name = newName; |
|
||||||
modified = true; |
|
||||||
} |
|
||||||
|
|
||||||
public void setSuperclass(ClassInfo newSuper) { |
|
||||||
superclass = newSuper; |
|
||||||
modified = true; |
|
||||||
} |
|
||||||
|
|
||||||
public void setInterfaces(ClassInfo[] newIfaces) { |
|
||||||
interfaces = newIfaces; |
|
||||||
modified = true; |
|
||||||
} |
|
||||||
|
|
||||||
public void setModifiers(int newModifiers) { |
|
||||||
modifiers = newModifiers; |
|
||||||
modified = true; |
|
||||||
} |
|
||||||
|
|
||||||
public void setMethods(MethodInfo[] mi) { |
|
||||||
methods = mi; |
|
||||||
modified = true; |
|
||||||
} |
|
||||||
|
|
||||||
public void setFields(FieldInfo[] fi) { |
|
||||||
fields = fi; |
|
||||||
modified = true; |
|
||||||
} |
|
||||||
|
|
||||||
public void setOuterClasses(InnerClassInfo[] oc) { |
|
||||||
outerClasses = oc; |
|
||||||
modified = true; |
|
||||||
} |
|
||||||
|
|
||||||
public void setInnerClasses(InnerClassInfo[] ic) { |
|
||||||
innerClasses = ic; |
|
||||||
modified = true; |
|
||||||
} |
|
||||||
|
|
||||||
public void setExtraClasses(InnerClassInfo[] ec) { |
|
||||||
extraClasses = ec; |
|
||||||
modified = true; |
|
||||||
} |
|
||||||
|
|
||||||
public void setSourceFile(String newSource) { |
|
||||||
sourceFile = newSource; |
|
||||||
modified = true; |
|
||||||
} |
|
||||||
|
|
||||||
public boolean superClassOf(ClassInfo son) { |
|
||||||
while (son != this && son != null) { |
|
||||||
son = son.getSuperclass(); |
|
||||||
} |
|
||||||
return son == this; |
|
||||||
} |
|
||||||
|
|
||||||
public boolean implementedBy(ClassInfo clazz) { |
|
||||||
while (clazz != this && clazz != null) { |
|
||||||
ClassInfo[] ifaces = clazz.getInterfaces(); |
|
||||||
for (int i=0; i< ifaces.length; i++) { |
|
||||||
if (implementedBy(ifaces[i])) |
|
||||||
return true; |
|
||||||
} |
|
||||||
clazz = clazz.getSuperclass(); |
|
||||||
} |
|
||||||
return clazz == this; |
|
||||||
} |
|
||||||
|
|
||||||
public String toString() { |
|
||||||
return name; |
|
||||||
} |
|
||||||
} |
|
@ -1,337 +0,0 @@ |
|||||||
// This interface is taken from the Classpath project.
|
|
||||||
// Please note the different copyright holder!
|
|
||||||
// The changes I did is this comment, the package line, some
|
|
||||||
// imports from java.util and some minor jdk12 -> jdk11 fixes.
|
|
||||||
// -- Jochen Hoenicke <jochen@gnu.org>
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
// AbstractCollection.java -- Abstract implementation of most of Collection
|
|
||||||
//
|
|
||||||
// Copyright (c) 1998 by Stuart Ballard (stuart.ballard@mcmail.com)
|
|
||||||
//
|
|
||||||
// This program is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Library General Public License as published
|
|
||||||
// by the Free Software Foundation, version 2. (see COPYING.LIB)
|
|
||||||
//
|
|
||||||
// This program 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 Library General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Library General Public License
|
|
||||||
// along with this program; if not, write to the Free Software Foundation
|
|
||||||
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
package jode.util; |
|
||||||
|
|
||||||
import java.lang.reflect.Array; |
|
||||||
|
|
||||||
/** |
|
||||||
* A basic implementation of most of the methods in the Collection interface to |
|
||||||
* make it easier to create a collection. To create an unmodifiable Collection, |
|
||||||
* just subclass AbstractCollection and provide implementations of the |
|
||||||
* iterator() and size() methods. The Iterator returned by iterator() need only |
|
||||||
* provide implementations of hasNext() and next() (that is, it may throw an |
|
||||||
* UnsupportedOperationException if remove() is called). To create a modifiable |
|
||||||
* Collection, you must in addition provide an implementation of the |
|
||||||
* add(Object) method and the Iterator returned by iterator() must provide an |
|
||||||
* implementation of remove(). Other methods should be overridden if the |
|
||||||
* backing data structure allows for a more efficient implementation. The |
|
||||||
* precise implementation used by AbstractCollection is documented, so that |
|
||||||
* subclasses can tell which methods could be implemented more efficiently. |
|
||||||
*/ |
|
||||||
public abstract class AbstractCollection implements Collection { |
|
||||||
|
|
||||||
/** |
|
||||||
* Return an Iterator over this collection. The iterator must provide the |
|
||||||
* hasNext and next methods and should in addition provide remove if the |
|
||||||
* collection is modifiable. |
|
||||||
*/ |
|
||||||
public abstract Iterator iterator(); |
|
||||||
|
|
||||||
/** |
|
||||||
* Return the number of elements in this collection. |
|
||||||
*/ |
|
||||||
public abstract int size(); |
|
||||||
|
|
||||||
/** |
|
||||||
* Add an object to the collection. This implementation always throws an |
|
||||||
* UnsupportedOperationException - it should be overridden if the collection |
|
||||||
* is to be modifiable. |
|
||||||
* |
|
||||||
* @param o the object to add |
|
||||||
* @return true if the add operation caused the Collection to change |
|
||||||
* @exception UnsupportedOperationException if the add operation is not |
|
||||||
* supported on this collection |
|
||||||
*/ |
|
||||||
public boolean add(Object o) { |
|
||||||
throw new UnsupportedOperationException(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Add all the elements of a given collection to this collection. This |
|
||||||
* implementation obtains an Iterator over the given collection and iterates |
|
||||||
* over it, adding each element with the add(Object) method (thus this method |
|
||||||
* will fail with an UnsupportedOperationException if the add method does). |
|
||||||
* |
|
||||||
* @param c the collection to add the elements of to this collection |
|
||||||
* @return true if the add operation caused the Collection to change |
|
||||||
* @exception UnsupportedOperationException if the add operation is not |
|
||||||
* supported on this collection |
|
||||||
*/ |
|
||||||
public boolean addAll(Collection c) { |
|
||||||
Iterator i = c.iterator(); |
|
||||||
boolean modified = false; |
|
||||||
while (i.hasNext()) { |
|
||||||
modified |= add(i.next()); |
|
||||||
} |
|
||||||
return modified; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Remove all elements from the collection. This implementation obtains an |
|
||||||
* iterator over the collection and calls next and remove on it repeatedly |
|
||||||
* (thus this method will fail with an UnsupportedOperationException if the |
|
||||||
* Iterator's remove method does) until there are no more elements to remove. |
|
||||||
* Many implementations will have a faster way of doing this. |
|
||||||
* |
|
||||||
* @exception UnsupportedOperationException if the Iterator returned by |
|
||||||
* iterator does not provide an implementation of remove |
|
||||||
*/ |
|
||||||
public void clear() { |
|
||||||
Iterator i = iterator(); |
|
||||||
while (i.hasNext()) { |
|
||||||
i.next(); |
|
||||||
i.remove(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Test whether this collection contains a given object. That is, if the |
|
||||||
* collection has an element e such that (o == null ? e == null : |
|
||||||
* o.equals(e)). This implementation obtains an iterator over the collection |
|
||||||
* and iterates over it, testing each element for equality with the given |
|
||||||
* object. If it is equal, true is returned. Otherwise false is returned when |
|
||||||
* the end of the collection is reached. |
|
||||||
* |
|
||||||
* @param o the object to remove from this collection |
|
||||||
* @return true if this collection contains an object equal to o |
|
||||||
*/ |
|
||||||
public boolean contains(Object o) { |
|
||||||
Iterator i = iterator(); |
|
||||||
|
|
||||||
// This looks crazily inefficient, but it takes the test o==null outside
|
|
||||||
// the loop, saving time, and also saves needing to store the result of
|
|
||||||
// i.next() each time.
|
|
||||||
if (o == null) { |
|
||||||
while (i.hasNext()) { |
|
||||||
if (i.next() == null) { |
|
||||||
return true; |
|
||||||
} |
|
||||||
} |
|
||||||
} else { |
|
||||||
while (i.hasNext()) { |
|
||||||
if (o.equals(i.next())) { |
|
||||||
return true; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Tests whether this collection contains all the elements in a given |
|
||||||
* collection. This implementation iterates over the given collection, |
|
||||||
* testing whether each element is contained in this collection. If any one |
|
||||||
* is not, false is returned. Otherwise true is returned. |
|
||||||
* |
|
||||||
* @param c the collection to test against |
|
||||||
* @return true if this collection contains all the elements in the given |
|
||||||
* collection |
|
||||||
*/ |
|
||||||
public boolean containsAll(Collection c) { |
|
||||||
Iterator i = c.iterator(); |
|
||||||
while (i.hasNext()) { |
|
||||||
if (!contains(i.next())) { |
|
||||||
return false; |
|
||||||
} |
|
||||||
} |
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Test whether this collection is empty. This implementation returns |
|
||||||
* size() == 0. |
|
||||||
* |
|
||||||
* @return true if this collection is empty. |
|
||||||
*/ |
|
||||||
public boolean isEmpty() { |
|
||||||
return size() == 0; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Remove a single instance of an object from this collection. That is, |
|
||||||
* remove one element e such that (o == null ? e == null : o.equals(e)), if |
|
||||||
* such an element exists. This implementation obtains an iterator over the |
|
||||||
* collection and iterates over it, testing each element for equality with |
|
||||||
* the given object. If it is equal, it is removed by the iterator's remove |
|
||||||
* method (thus this method will fail with an UnsupportedOperationException |
|
||||||
* if the Iterator's remove method does). After the first element has been |
|
||||||
* removed, true is returned; if the end of the collection is reached, false |
|
||||||
* is returned. |
|
||||||
* |
|
||||||
* @param o the object to remove from this collection |
|
||||||
* @return true if the remove operation caused the Collection to change, or |
|
||||||
* equivalently if the collection did contain o. |
|
||||||
* @exception UnsupportedOperationException if this collection's Iterator |
|
||||||
* does not support the remove method |
|
||||||
*/ |
|
||||||
public boolean remove(Object o) { |
|
||||||
Iterator i = iterator(); |
|
||||||
|
|
||||||
// This looks crazily inefficient, but it takes the test o==null outside
|
|
||||||
// the loop, saving time, and also saves needing to store the result of
|
|
||||||
// i.next() each time.
|
|
||||||
if (o == null) { |
|
||||||
while (i.hasNext()) { |
|
||||||
if (i.next() == null) { |
|
||||||
i.remove(); |
|
||||||
return true; |
|
||||||
} |
|
||||||
} |
|
||||||
} else { |
|
||||||
while (i.hasNext()) { |
|
||||||
if (o.equals(i.next())) { |
|
||||||
i.remove(); |
|
||||||
return true; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Remove from this collection all its elements that are contained in a given |
|
||||||
* collection. This implementation iterates over this collection, and for |
|
||||||
* each element tests if it is contained in the given collection. If so, it |
|
||||||
* is removed by the Iterator's remove method (thus this method will fail |
|
||||||
* with an UnsupportedOperationException if the Iterator's remove method |
|
||||||
* does). |
|
||||||
* |
|
||||||
* @param c the collection to remove the elements of |
|
||||||
* @return true if the remove operation caused the Collection to change |
|
||||||
* @exception UnsupportedOperationException if this collection's Iterator |
|
||||||
* does not support the remove method |
|
||||||
*/ |
|
||||||
public boolean removeAll(Collection c) { |
|
||||||
Iterator i = iterator(); |
|
||||||
boolean changed = false; |
|
||||||
while (i.hasNext()) { |
|
||||||
if (c.contains(i.next())) { |
|
||||||
i.remove(); |
|
||||||
changed = true; |
|
||||||
} |
|
||||||
} |
|
||||||
return changed; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Remove from this collection all its elements that are not contained in a |
|
||||||
* given collection. This implementation iterates over this collection, and |
|
||||||
* for each element tests if it is contained in the given collection. If not, |
|
||||||
* it is removed by the Iterator's remove method (thus this method will fail |
|
||||||
* with an UnsupportedOperationException if the Iterator's remove method |
|
||||||
* does). |
|
||||||
* |
|
||||||
* @param c the collection to retain the elements of |
|
||||||
* @return true if the remove operation caused the Collection to change |
|
||||||
* @exception UnsupportedOperationException if this collection's Iterator |
|
||||||
* does not support the remove method |
|
||||||
*/ |
|
||||||
public boolean retainAll(Collection c) { |
|
||||||
Iterator i = iterator(); |
|
||||||
boolean changed = false; |
|
||||||
while (i.hasNext()) { |
|
||||||
if (!c.contains(i.next())) { |
|
||||||
i.remove(); |
|
||||||
changed = true; |
|
||||||
} |
|
||||||
} |
|
||||||
return changed; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Return an array containing the elements of this collection. This |
|
||||||
* implementation creates an Object array of size size() and then iterates |
|
||||||
* over the collection, setting each element of the array from the value |
|
||||||
* returned by the iterator. |
|
||||||
* |
|
||||||
* @return an array containing the elements of this collection |
|
||||||
*/ |
|
||||||
public Object[] toArray() { |
|
||||||
Object[] a = new Object[size()]; |
|
||||||
Iterator i = iterator(); |
|
||||||
for (int pos = 0; pos < a.length; pos++) { |
|
||||||
a[pos] = i.next(); |
|
||||||
} |
|
||||||
return a; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Copy the collection into a given array if it will fit, or into a |
|
||||||
* dynamically created array of the same run-time type as the given array if |
|
||||||
* not. If there is space remaining in the array, the first element after the |
|
||||||
* end of the collection is set to null (this is only useful if the |
|
||||||
* collection is known to contain no null elements, however). This |
|
||||||
* implementation first tests whether the given array is large enough to hold |
|
||||||
* all the elements of the collection. If not, the reflection API is used to |
|
||||||
* allocate a new array of the same run-time type. Next an iterator is |
|
||||||
* obtained over the collection and the elements are placed in the array as |
|
||||||
* they are returned by the iterator. Finally the first spare element, if |
|
||||||
* any, of the array is set to null, and the created array is returned. |
|
||||||
* |
|
||||||
* @param a the array to copy into, or of the correct run-time type |
|
||||||
* @return the array that was produced |
|
||||||
* @exception ClassCastException if the type of the array precludes holding |
|
||||||
* one of the elements of the Collection |
|
||||||
*/ |
|
||||||
public Object[] toArray(Object[] a) { |
|
||||||
final int n = size(); |
|
||||||
if (a.length < n) { |
|
||||||
a = (Object[])Array.newInstance(a.getClass().getComponentType(), n); |
|
||||||
} |
|
||||||
Iterator i = iterator(); |
|
||||||
for (int pos = 0; pos < n; pos++) { |
|
||||||
a[pos] = i.next(); |
|
||||||
} |
|
||||||
if (a.length > n) { |
|
||||||
a[n] = null; |
|
||||||
} |
|
||||||
return a; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Creates a String representation of the Collection. The string returned is |
|
||||||
* of the form "[a, b, ...]" where a and b etc are the results of calling |
|
||||||
* toString on the elements of the collection. This implementation obtains an |
|
||||||
* Iterator over the Collection and adds each element to a StringBuffer as it |
|
||||||
* is returned by the iterator. |
|
||||||
* |
|
||||||
* @return a String representation of the Collection |
|
||||||
*/ |
|
||||||
public String toString() { |
|
||||||
StringBuffer s = new StringBuffer(); |
|
||||||
s.append('['); |
|
||||||
Iterator i = iterator(); |
|
||||||
boolean more = i.hasNext(); |
|
||||||
while(more) { |
|
||||||
s.append(i.next()); |
|
||||||
if (more = i.hasNext()) { |
|
||||||
s.append(", "); |
|
||||||
} |
|
||||||
} |
|
||||||
s.append(']'); |
|
||||||
return s.toString(); |
|
||||||
} |
|
||||||
} |
|
@ -1,560 +0,0 @@ |
|||||||
// This interface is taken from the Classpath project.
|
|
||||||
// Please note the different copyright holder!
|
|
||||||
// The changes I did is this comment, the package line, some
|
|
||||||
// imports from java.util and some minor jdk12 -> jdk11 fixes.
|
|
||||||
// -- Jochen Hoenicke <jochen@gnu.org>
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
// AbstractList.java -- Abstract implementation of most of List
|
|
||||||
//
|
|
||||||
// Copyright (c) 1998 by Stuart Ballard (stuart.ballard@mcmail.com)
|
|
||||||
//
|
|
||||||
// This program is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Library General Public License as published
|
|
||||||
// by the Free Software Foundation, version 2. (see COPYING.LIB)
|
|
||||||
//
|
|
||||||
// This program 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 Library General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Library General Public License
|
|
||||||
// along with this program; if not, write to the Free Software Foundation
|
|
||||||
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// TO DO:
|
|
||||||
// ~ Doc comments for almost everything.
|
|
||||||
// ~ Better general commenting
|
|
||||||
|
|
||||||
package jode.util; |
|
||||||
import java.util.NoSuchElementException; |
|
||||||
|
|
||||||
/** |
|
||||||
* A basic implementation of most of the methods in the List interface to make |
|
||||||
* it easier to create a List based on a random-access data structure. To |
|
||||||
* create an unmodifiable list, it is only necessary to override the size() and |
|
||||||
* get(int) methods (this contrasts with all other abstract collection classes |
|
||||||
* which require an iterator to be provided). To make the list modifiable, the |
|
||||||
* set(int, Object) method should also be overridden, and to make the list |
|
||||||
* resizable, the add(int, Object) and remove(int) methods should be overridden |
|
||||||
* too. Other methods should be overridden if the backing data structure allows |
|
||||||
* for a more efficient implementation. The precise implementation used by |
|
||||||
* AbstractList is documented, so that subclasses can tell which methods could |
|
||||||
* be implemented more efficiently. |
|
||||||
*/ |
|
||||||
public abstract class AbstractList extends AbstractCollection implements List { |
|
||||||
|
|
||||||
/** |
|
||||||
* A count of the number of structural modifications that have been made to |
|
||||||
* the list (that is, insertions and removals). |
|
||||||
*/ |
|
||||||
protected transient int modCount = 0; |
|
||||||
|
|
||||||
public abstract Object get(int index); |
|
||||||
|
|
||||||
public void add(int index, Object o) { |
|
||||||
throw new UnsupportedOperationException(); |
|
||||||
} |
|
||||||
|
|
||||||
public boolean add(Object o) { |
|
||||||
add(size(), o); |
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
public boolean addAll(int index, Collection c) { |
|
||||||
Iterator i = c.iterator(); |
|
||||||
if (i.hasNext()) { |
|
||||||
do { |
|
||||||
add(index++, i.next()); |
|
||||||
} while (i.hasNext()); |
|
||||||
return true; |
|
||||||
} else { |
|
||||||
return false; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public void clear() { |
|
||||||
removeRange(0, size()); |
|
||||||
} |
|
||||||
|
|
||||||
public boolean equals(Object o) { |
|
||||||
if (o == this) { |
|
||||||
return true; |
|
||||||
} else if (!(o instanceof List)) { |
|
||||||
return false; |
|
||||||
} else { |
|
||||||
Iterator i1 = iterator(); |
|
||||||
Iterator i2 = ((List)o).iterator(); |
|
||||||
while (i1.hasNext()) { |
|
||||||
if (!i2.hasNext()) { |
|
||||||
return false; |
|
||||||
} else { |
|
||||||
Object e = i1.next(); |
|
||||||
if (e == null ? i2.next() != null : !e.equals(i2.next())) { |
|
||||||
return false; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
if (i2.hasNext()) { |
|
||||||
return false; |
|
||||||
} else { |
|
||||||
return true; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public int hashCode() { |
|
||||||
int hashCode = 1; |
|
||||||
Iterator i = iterator(); |
|
||||||
while (i.hasNext()) { |
|
||||||
Object obj = i.next(); |
|
||||||
hashCode = 31 * hashCode + (obj == null ? 0 : obj.hashCode()); |
|
||||||
} |
|
||||||
return hashCode; |
|
||||||
} |
|
||||||
|
|
||||||
public int indexOf(Object o) { |
|
||||||
int index = 0; |
|
||||||
ListIterator i = listIterator(); |
|
||||||
if (o == null) { |
|
||||||
while (i.hasNext()) { |
|
||||||
if (i.next() == null) { |
|
||||||
return index; |
|
||||||
} |
|
||||||
index++; |
|
||||||
} |
|
||||||
} else { |
|
||||||
while (i.hasNext()) { |
|
||||||
if (o.equals(i.next())) { |
|
||||||
return index; |
|
||||||
} |
|
||||||
index++; |
|
||||||
} |
|
||||||
} |
|
||||||
return -1; |
|
||||||
} |
|
||||||
|
|
||||||
public Iterator iterator() { |
|
||||||
return new Iterator() { |
|
||||||
private int knownMod = modCount; |
|
||||||
private int position = 0; |
|
||||||
boolean removed = true; |
|
||||||
|
|
||||||
private void checkMod() { |
|
||||||
if (knownMod != modCount) { |
|
||||||
throw new ConcurrentModificationException(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public boolean hasNext() { |
|
||||||
checkMod(); |
|
||||||
return position < size(); |
|
||||||
} |
|
||||||
|
|
||||||
public Object next() { |
|
||||||
checkMod(); |
|
||||||
removed = false; |
|
||||||
try { |
|
||||||
return get(position++); |
|
||||||
} catch (IndexOutOfBoundsException e) { |
|
||||||
throw new NoSuchElementException(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public void remove() { |
|
||||||
checkMod(); |
|
||||||
if (removed) { |
|
||||||
throw new IllegalStateException(); |
|
||||||
} |
|
||||||
AbstractList.this.remove(--position); |
|
||||||
knownMod = modCount; |
|
||||||
removed = true; |
|
||||||
} |
|
||||||
}; |
|
||||||
} |
|
||||||
|
|
||||||
public int lastIndexOf(Object o) { |
|
||||||
int index = size(); |
|
||||||
ListIterator i = listIterator(index); |
|
||||||
if (o == null) { |
|
||||||
while (i.hasPrevious()) { |
|
||||||
if (i.previous() == null) { |
|
||||||
return index; |
|
||||||
} |
|
||||||
index--; |
|
||||||
} |
|
||||||
} else { |
|
||||||
while (i.hasPrevious()) { |
|
||||||
if (o.equals(i.previous())) { |
|
||||||
return index; |
|
||||||
} |
|
||||||
index--; |
|
||||||
} |
|
||||||
} |
|
||||||
return -1; |
|
||||||
} |
|
||||||
|
|
||||||
public ListIterator listIterator() { |
|
||||||
return listIterator(0); |
|
||||||
} |
|
||||||
|
|
||||||
public ListIterator listIterator(final int index) { |
|
||||||
|
|
||||||
if (index < 0 || index > size()) { |
|
||||||
throw new IndexOutOfBoundsException(); |
|
||||||
} |
|
||||||
|
|
||||||
return new ListIterator() { |
|
||||||
private int knownMod = modCount; |
|
||||||
private int position = index; |
|
||||||
private int lastReturned = -1; |
|
||||||
|
|
||||||
private void checkMod() { |
|
||||||
if (knownMod != modCount) { |
|
||||||
throw new ConcurrentModificationException(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public boolean hasNext() { |
|
||||||
checkMod(); |
|
||||||
return position < size(); |
|
||||||
} |
|
||||||
|
|
||||||
public boolean hasPrevious() { |
|
||||||
checkMod(); |
|
||||||
return position > 0; |
|
||||||
} |
|
||||||
|
|
||||||
public Object next() { |
|
||||||
checkMod(); |
|
||||||
if (hasNext()) { |
|
||||||
lastReturned = position++; |
|
||||||
return get(lastReturned); |
|
||||||
} else { |
|
||||||
throw new NoSuchElementException(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public Object previous() { |
|
||||||
checkMod(); |
|
||||||
if (hasPrevious()) { |
|
||||||
lastReturned = --position; |
|
||||||
return get(lastReturned); |
|
||||||
} else { |
|
||||||
throw new NoSuchElementException(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public int nextIndex() { |
|
||||||
checkMod(); |
|
||||||
return position; |
|
||||||
} |
|
||||||
|
|
||||||
public int previousIndex() { |
|
||||||
checkMod(); |
|
||||||
return position - 1; |
|
||||||
} |
|
||||||
|
|
||||||
public void remove() { |
|
||||||
checkMod(); |
|
||||||
if (lastReturned < 0) { |
|
||||||
throw new IllegalStateException(); |
|
||||||
} |
|
||||||
AbstractList.this.remove(lastReturned); |
|
||||||
knownMod = modCount; |
|
||||||
position = lastReturned; |
|
||||||
lastReturned = -1; |
|
||||||
} |
|
||||||
|
|
||||||
public void set(Object o) { |
|
||||||
checkMod(); |
|
||||||
if (lastReturned < 0) { |
|
||||||
throw new IllegalStateException(); |
|
||||||
} |
|
||||||
AbstractList.this.set(lastReturned, o); |
|
||||||
} |
|
||||||
|
|
||||||
public void add(Object o) { |
|
||||||
checkMod(); |
|
||||||
AbstractList.this.add(position++, o); |
|
||||||
lastReturned = -1; |
|
||||||
knownMod = modCount; |
|
||||||
} |
|
||||||
}; |
|
||||||
} |
|
||||||
|
|
||||||
public Object remove(int index) { |
|
||||||
throw new UnsupportedOperationException(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Remove a subsection of the list. This is called by the clear and |
|
||||||
* removeRange methods of the class which implements subList, which are |
|
||||||
* difficult for subclasses to override directly. Therefore, this method |
|
||||||
* should be overridden instead by the more efficient implementation, if one |
|
||||||
* exists. |
|
||||||
* <p> |
|
||||||
* This implementation first checks for illegal or out of range arguments. It |
|
||||||
* then obtains a ListIterator over the list using listIterator(fromIndex). |
|
||||||
* It then calls next() and remove() on this iterator repeatedly, toIndex - |
|
||||||
* fromIndex times. |
|
||||||
* |
|
||||||
* @param fromIndex the index, inclusive, to remove from. |
|
||||||
* @param toIndex the index, exclusive, to remove to. |
|
||||||
* @exception UnsupportedOperationException if this list does not support |
|
||||||
* the removeRange operation. |
|
||||||
* @exception IndexOutOfBoundsException if fromIndex > toIndex || fromIndex < |
|
||||||
* 0 || toIndex > size(). |
|
||||||
*/ |
|
||||||
protected void removeRange(int fromIndex, int toIndex) { |
|
||||||
if (fromIndex > toIndex) { |
|
||||||
throw new IllegalArgumentException(); |
|
||||||
} else if (fromIndex < 0 || toIndex > size()) { |
|
||||||
throw new IndexOutOfBoundsException(); |
|
||||||
} else { |
|
||||||
ListIterator i = listIterator(fromIndex); |
|
||||||
for (int index = fromIndex; index < toIndex; index++) { |
|
||||||
i.next(); |
|
||||||
i.remove(); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public Object set(int index, Object o) { |
|
||||||
throw new UnsupportedOperationException(); |
|
||||||
} |
|
||||||
|
|
||||||
private static class SubList extends AbstractList { |
|
||||||
|
|
||||||
// Note that within this class two fields called modCount are inherited -
|
|
||||||
// one from the superclass, and one from the backing class. These are
|
|
||||||
// explicitly disambiguated in the code by referring to "this.modCount"
|
|
||||||
// and "backing.modCount".
|
|
||||||
// The code uses both these two fields and *no other* to provide fail-fast
|
|
||||||
// behaviour. For correct operation, the two fields should contain equal
|
|
||||||
// values. Therefore, if this.modCount != backing.modCount, there
|
|
||||||
// has been a concurrent modification. This is all achieved purely by using
|
|
||||||
// the modCount field, precisely according to the docs of AbstractList.
|
|
||||||
// See the methods upMod and checkMod.
|
|
||||||
|
|
||||||
// Jikes doesn't want to access outer instance with AbstractList.this,
|
|
||||||
// since this is an AbstractList, too. I therefor changed class to static
|
|
||||||
// and do it by hand. This makes it a lot clearer by the way.
|
|
||||||
private AbstractList backing; |
|
||||||
private final int offset; |
|
||||||
private int size; |
|
||||||
|
|
||||||
SubList(AbstractList backing, int fromIndex, int toIndex) { |
|
||||||
this.backing = backing; |
|
||||||
this.offset = fromIndex; |
|
||||||
this.size = toIndex - fromIndex; |
|
||||||
|
|
||||||
upMod(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* This method checks the two modCount fields to ensure that there has |
|
||||||
* not been a concurrent modification. It throws an exception if there |
|
||||||
* has been, and otherwise returns normally. |
|
||||||
* Note that since this method is private, it will be inlined. |
|
||||||
* |
|
||||||
* @exception ConcurrentModificationException if there has been a |
|
||||||
* concurrent modification. |
|
||||||
*/ |
|
||||||
private void checkMod() { |
|
||||||
if (modCount != backing.modCount) { |
|
||||||
throw new ConcurrentModificationException(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* This method is called after every method that causes a structural |
|
||||||
* modification to the backing list. It updates the local modCount field |
|
||||||
* to match that of the backing list. |
|
||||||
* Note that since this method is private, it will be inlined. |
|
||||||
*/ |
|
||||||
private void upMod() { |
|
||||||
modCount = backing.modCount; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* This method checks that a value is between 0 and size (inclusive). If |
|
||||||
* it is not, an exception is thrown. |
|
||||||
* Note that since this method is private, it will be inlined. |
|
||||||
* |
|
||||||
* @exception IndexOutOfBoundsException if the value is out of range. |
|
||||||
*/ |
|
||||||
private void checkBoundsInclusive(int index) { |
|
||||||
if (index < 0 || index > size) { |
|
||||||
throw new IndexOutOfBoundsException(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* This method checks that a value is between 0 (inclusive) and size |
|
||||||
* (exclusive). If it is not, an exception is thrown. |
|
||||||
* Note that since this method is private, it will be inlined. |
|
||||||
* |
|
||||||
* @exception IndexOutOfBoundsException if the value is out of range. |
|
||||||
*/ |
|
||||||
private void checkBoundsExclusive(int index) { |
|
||||||
if (index < 0 || index >= size) { |
|
||||||
throw new IndexOutOfBoundsException(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public int size() { |
|
||||||
checkMod(); |
|
||||||
return size; |
|
||||||
} |
|
||||||
|
|
||||||
public Iterator iterator() { |
|
||||||
return listIterator(); |
|
||||||
} |
|
||||||
|
|
||||||
public ListIterator listIterator(final int index) { |
|
||||||
|
|
||||||
checkMod(); |
|
||||||
checkBoundsInclusive(index); |
|
||||||
|
|
||||||
return new ListIterator() { |
|
||||||
ListIterator i = backing.listIterator(index + offset); |
|
||||||
int position = index; |
|
||||||
|
|
||||||
public boolean hasNext() { |
|
||||||
checkMod(); |
|
||||||
return position < size; |
|
||||||
} |
|
||||||
|
|
||||||
public boolean hasPrevious() { |
|
||||||
checkMod(); |
|
||||||
return position > 0; |
|
||||||
} |
|
||||||
|
|
||||||
public Object next() { |
|
||||||
if (position < size) { |
|
||||||
Object o = i.next(); |
|
||||||
position++; |
|
||||||
return o; |
|
||||||
} else { |
|
||||||
throw new NoSuchElementException(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public Object previous() { |
|
||||||
if (position > 0) { |
|
||||||
Object o = i.previous(); |
|
||||||
position--; |
|
||||||
return o; |
|
||||||
} else { |
|
||||||
throw new NoSuchElementException(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public int nextIndex() { |
|
||||||
return offset + i.nextIndex(); |
|
||||||
} |
|
||||||
|
|
||||||
public int previousIndex() { |
|
||||||
return offset + i.previousIndex(); |
|
||||||
} |
|
||||||
|
|
||||||
public void remove() { |
|
||||||
i.remove(); |
|
||||||
upMod(); |
|
||||||
size--; |
|
||||||
position = nextIndex(); |
|
||||||
} |
|
||||||
|
|
||||||
public void set(Object o) { |
|
||||||
i.set(o); |
|
||||||
} |
|
||||||
|
|
||||||
public void add(Object o) { |
|
||||||
i.add(o); |
|
||||||
upMod(); |
|
||||||
size++; |
|
||||||
position++; |
|
||||||
} |
|
||||||
|
|
||||||
// Here is the reason why the various modCount fields are mostly
|
|
||||||
// ignored in this wrapper listIterator.
|
|
||||||
// IF the backing listIterator is failfast, then the following holds:
|
|
||||||
// Using any other method on this list will call a corresponding
|
|
||||||
// method on the backing list *after* the backing listIterator
|
|
||||||
// is created, which will in turn cause a ConcurrentModException
|
|
||||||
// when this listIterator comes to use the backing one. So it is
|
|
||||||
// implicitly failfast.
|
|
||||||
// If the backing listIterator is NOT failfast, then the whole of
|
|
||||||
// this list isn't failfast, because the modCount field of the
|
|
||||||
// backing list is not valid. It would still be *possible* to
|
|
||||||
// make the iterator failfast wrt modifications of the sublist
|
|
||||||
// only, but somewhat pointless when the list can be changed under
|
|
||||||
// us.
|
|
||||||
// Either way, no explicit handling of modCount is needed.
|
|
||||||
// However upMod() must be called in add and remove, and size
|
|
||||||
// must also be updated in these two methods, since they do not go
|
|
||||||
// through the corresponding methods of the subList.
|
|
||||||
|
|
||||||
}; |
|
||||||
} |
|
||||||
|
|
||||||
public Object set(int index, Object o) { |
|
||||||
checkMod(); |
|
||||||
checkBoundsExclusive(index); |
|
||||||
o = backing.set(index + offset, o); |
|
||||||
upMod(); |
|
||||||
return o; |
|
||||||
} |
|
||||||
|
|
||||||
public Object get(int index) { |
|
||||||
checkMod(); |
|
||||||
checkBoundsExclusive(index); |
|
||||||
return backing.get(index + offset); |
|
||||||
} |
|
||||||
|
|
||||||
public void add(int index, Object o) { |
|
||||||
checkMod(); |
|
||||||
checkBoundsInclusive(index); |
|
||||||
backing.add(index + offset, o); |
|
||||||
upMod(); |
|
||||||
size++; |
|
||||||
} |
|
||||||
|
|
||||||
public Object remove(int index) { |
|
||||||
checkMod(); |
|
||||||
checkBoundsExclusive(index); |
|
||||||
Object o = backing.remove(index + offset); |
|
||||||
upMod(); |
|
||||||
size--; |
|
||||||
return o; |
|
||||||
} |
|
||||||
|
|
||||||
public void removeRange(int fromIndex2, int toIndex2) { |
|
||||||
checkMod(); |
|
||||||
checkBoundsExclusive(fromIndex2); |
|
||||||
checkBoundsInclusive(toIndex2); |
|
||||||
|
|
||||||
// this call will catch the toIndex2 < fromIndex2 condition
|
|
||||||
backing.removeRange(offset + fromIndex2, offset + toIndex2); |
|
||||||
upMod(); |
|
||||||
size -= toIndex2 - fromIndex2; |
|
||||||
} |
|
||||||
|
|
||||||
public boolean addAll(int index, Collection c) { |
|
||||||
checkMod(); |
|
||||||
checkBoundsInclusive(index); |
|
||||||
int s = backing.size(); |
|
||||||
boolean result = backing.addAll(offset + index, c); |
|
||||||
upMod(); |
|
||||||
size += backing.size() - s; |
|
||||||
return result; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public List subList(final int fromIndex, final int toIndex) { |
|
||||||
return new SubList(this, fromIndex, toIndex); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,280 +0,0 @@ |
|||||||
// This interface is taken from the Classpath project.
|
|
||||||
// Please note the different copyright holder!
|
|
||||||
// The changes I did is this comment, the package line, some
|
|
||||||
// imports from java.util and some minor jdk12 -> jdk11 fixes.
|
|
||||||
// -- Jochen Hoenicke <jochen@gnu.org>
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
// AbstractMap.java -- Abstract implementation of most of Map
|
|
||||||
//
|
|
||||||
// Copyright (c) 1998 by Stuart Ballard (stuart.ballard@mcmail.com),
|
|
||||||
// Free Software Foundation, Inc.
|
|
||||||
//
|
|
||||||
// This program is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Library General Public License as published
|
|
||||||
// by the Free Software Foundation, version 2. (see COPYING.LIB)
|
|
||||||
//
|
|
||||||
// This program 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 Library General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Library General Public License
|
|
||||||
// along with this program; if not, write to the Free Software Foundation
|
|
||||||
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// TO DO:
|
|
||||||
// comments
|
|
||||||
// test suite
|
|
||||||
|
|
||||||
package jode.util; |
|
||||||
|
|
||||||
public abstract class AbstractMap implements Map { |
|
||||||
|
|
||||||
public void clear() |
|
||||||
{ |
|
||||||
entrySet().clear(); |
|
||||||
} |
|
||||||
|
|
||||||
public boolean containsKey( Object key ) |
|
||||||
{ |
|
||||||
Object k; |
|
||||||
Iterator entries = entrySet().iterator(); |
|
||||||
|
|
||||||
while( entries.hasNext() ) |
|
||||||
{ |
|
||||||
k = ((Map.Entry)entries.next()).getKey(); |
|
||||||
if( key == null ? k == null : key.equals( k ) ) |
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
public boolean containsValue( Object value ) |
|
||||||
{ |
|
||||||
Object v; |
|
||||||
Iterator entries = entrySet().iterator(); |
|
||||||
|
|
||||||
while( entries.hasNext() ) |
|
||||||
{ |
|
||||||
v = ((Map.Entry)entries.next()).getValue(); |
|
||||||
if( value == null ? v == null : value.equals( v ) ) |
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
public abstract Set entrySet(); |
|
||||||
|
|
||||||
public boolean equals( Object o ) |
|
||||||
{ |
|
||||||
if( this == o ) |
|
||||||
return true; |
|
||||||
|
|
||||||
if( o == null || !( o instanceof Map ) ) |
|
||||||
return false; |
|
||||||
|
|
||||||
Map m = (Map)o; |
|
||||||
if( m.size() != size() ) |
|
||||||
return false; |
|
||||||
|
|
||||||
Object key, value1, value2; |
|
||||||
Map.Entry entry; |
|
||||||
Iterator entries = entrySet().iterator(); |
|
||||||
while( entries.hasNext() ) |
|
||||||
{ |
|
||||||
entry = (Map.Entry)entries.next(); |
|
||||||
key = entry.getKey(); |
|
||||||
value1 = entry.getValue(); |
|
||||||
value2 = m.get( key ); |
|
||||||
|
|
||||||
if( !( ( value1 == null && value2 == null ) |
|
||||||
|| value1.equals( value2 ) ) ) |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
public Object get( Object key ) |
|
||||||
{ |
|
||||||
Object k; |
|
||||||
Map.Entry entry; |
|
||||||
Iterator entries = entrySet().iterator(); |
|
||||||
|
|
||||||
while( entries.hasNext() ) |
|
||||||
{ |
|
||||||
entry = (Map.Entry)entries.next(); |
|
||||||
k = entry.getKey(); |
|
||||||
if( key == null ? k == null : key.equals( k ) ) |
|
||||||
return entry.getValue(); |
|
||||||
} |
|
||||||
|
|
||||||
return null; |
|
||||||
} |
|
||||||
|
|
||||||
public int hashCode() |
|
||||||
{ |
|
||||||
int hashcode = 0; |
|
||||||
Iterator entries = entrySet().iterator(); |
|
||||||
|
|
||||||
while( entries.hasNext() ) |
|
||||||
hashcode += entries.next().hashCode(); |
|
||||||
|
|
||||||
return hashcode; |
|
||||||
} |
|
||||||
|
|
||||||
public boolean isEmpty() |
|
||||||
{ |
|
||||||
return size() == 0; |
|
||||||
} |
|
||||||
|
|
||||||
public Set keySet() |
|
||||||
{ |
|
||||||
if( this.keySet == null ) |
|
||||||
{ |
|
||||||
this.keySet = |
|
||||||
new AbstractSet() |
|
||||||
{ |
|
||||||
public int size() |
|
||||||
{ |
|
||||||
return AbstractMap.this.size(); |
|
||||||
} |
|
||||||
|
|
||||||
public boolean contains(Object key) |
|
||||||
{ |
|
||||||
return AbstractMap.this.containsKey(key); |
|
||||||
} |
|
||||||
|
|
||||||
public Iterator iterator() |
|
||||||
{ |
|
||||||
return new Iterator() |
|
||||||
{ |
|
||||||
Iterator map_iterator = AbstractMap.this.entrySet().iterator(); |
|
||||||
|
|
||||||
public boolean hasNext() |
|
||||||
{ |
|
||||||
return map_iterator.hasNext(); |
|
||||||
} |
|
||||||
|
|
||||||
public Object next() |
|
||||||
{ |
|
||||||
return ((Map.Entry)map_iterator.next()).getKey(); |
|
||||||
} |
|
||||||
|
|
||||||
public void remove() |
|
||||||
{ |
|
||||||
map_iterator.remove(); |
|
||||||
} |
|
||||||
}; |
|
||||||
} |
|
||||||
}; |
|
||||||
} |
|
||||||
|
|
||||||
return this.keySet; |
|
||||||
} |
|
||||||
|
|
||||||
public Object put( Object key, Object value ) |
|
||||||
{ |
|
||||||
throw new UnsupportedOperationException(); |
|
||||||
} |
|
||||||
|
|
||||||
public void putAll( Map m ) |
|
||||||
{ |
|
||||||
Map.Entry entry; |
|
||||||
Iterator entries = m.entrySet().iterator(); |
|
||||||
while( entries.hasNext() ) |
|
||||||
{ |
|
||||||
entry = (Map.Entry)entries.next(); |
|
||||||
put( entry.getKey(), entry.getValue() ); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public Object remove( Object key ) |
|
||||||
{ |
|
||||||
Object k, value; |
|
||||||
Map.Entry entry; |
|
||||||
Iterator entries = entrySet().iterator(); |
|
||||||
|
|
||||||
while( entries.hasNext() ) |
|
||||||
{ |
|
||||||
entry = (Map.Entry)entries.next(); |
|
||||||
k = entry.getKey(); |
|
||||||
if( key == null ? k == null : key.equals( k ) ) |
|
||||||
{ |
|
||||||
value = entry.getValue(); |
|
||||||
entries.remove(); |
|
||||||
return value; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
return null; |
|
||||||
} |
|
||||||
|
|
||||||
public int size() |
|
||||||
{ |
|
||||||
return entrySet().size(); |
|
||||||
} |
|
||||||
|
|
||||||
public String toString() |
|
||||||
{ |
|
||||||
Map.Entry entry; |
|
||||||
String rep = "AbstractMap< "; |
|
||||||
Iterator entries = entrySet().iterator(); |
|
||||||
|
|
||||||
while( entries.hasNext() ) |
|
||||||
{ |
|
||||||
entry = (Map.Entry)entries.next(); |
|
||||||
rep += entry.getKey() + " -> " + entry.getValue() + ", "; |
|
||||||
} |
|
||||||
|
|
||||||
return rep.substring( 0, rep.length() - 2 ) + " >"; |
|
||||||
} |
|
||||||
|
|
||||||
public Collection values() |
|
||||||
{ |
|
||||||
if( this.valueCollection == null ) |
|
||||||
{ |
|
||||||
this.valueCollection = |
|
||||||
new AbstractCollection() |
|
||||||
{ |
|
||||||
public int size() |
|
||||||
{ |
|
||||||
return AbstractMap.this.size(); |
|
||||||
} |
|
||||||
|
|
||||||
public Iterator iterator() |
|
||||||
{ |
|
||||||
return new Iterator() |
|
||||||
{ |
|
||||||
Iterator map_iterator = AbstractMap.this.entrySet().iterator(); |
|
||||||
|
|
||||||
public boolean hasNext() |
|
||||||
{ |
|
||||||
return map_iterator.hasNext(); |
|
||||||
} |
|
||||||
|
|
||||||
public Object next() |
|
||||||
{ |
|
||||||
return ((Map.Entry)map_iterator.next()).getValue(); |
|
||||||
} |
|
||||||
|
|
||||||
public void remove() |
|
||||||
{ |
|
||||||
map_iterator.remove(); |
|
||||||
} |
|
||||||
}; |
|
||||||
} |
|
||||||
}; |
|
||||||
} |
|
||||||
|
|
||||||
return this.valueCollection; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
private Collection valueCollection = null; |
|
||||||
private Set keySet = null; |
|
||||||
} |
|
@ -1,111 +0,0 @@ |
|||||||
// This interface is taken from the Classpath project.
|
|
||||||
// Please note the different copyright holder!
|
|
||||||
// The changes I did is this comment, the package line, some
|
|
||||||
// imports from java.util and some minor jdk12 -> jdk11 fixes.
|
|
||||||
// -- Jochen Hoenicke <jochen@gnu.org>
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
// AbstractSequentialList.java -- List implementation for sequential access
|
|
||||||
//
|
|
||||||
// Copyright (c) 1998 by Stuart Ballard (stuart.ballard@mcmail.com)
|
|
||||||
//
|
|
||||||
// This program is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Library General Public License as published
|
|
||||||
// by the Free Software Foundation, version 2. (see COPYING.LIB)
|
|
||||||
//
|
|
||||||
// This program 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 Library General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Library General Public License
|
|
||||||
// along with this program; if not, write to the Free Software Foundation
|
|
||||||
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// TO DO:
|
|
||||||
// ~ Lots of doc comments still missing.
|
|
||||||
// ~ The class comment should include a description of what should be overridden
|
|
||||||
// to provide what features, as should the listIterator comment.
|
|
||||||
|
|
||||||
package jode.util; |
|
||||||
|
|
||||||
/** |
|
||||||
* Abstract superclass to make it easier to implement the List interface when |
|
||||||
* backed by a sequential-access store, such as a linked list. |
|
||||||
*/ |
|
||||||
public abstract class AbstractSequentialList extends AbstractList { |
|
||||||
|
|
||||||
/** |
|
||||||
* Returns a ListIterator over the list, starting from position index. |
|
||||||
* Subclasses must provide an implementation of this method. |
|
||||||
* |
|
||||||
* @exception IndexOutOfBoundsException if index < 0 || index > size() |
|
||||||
*/ |
|
||||||
public abstract ListIterator listIterator(int index); |
|
||||||
|
|
||||||
/** |
|
||||||
* Add an element to the list at a given index. This implementation obtains a |
|
||||||
* ListIterator positioned at the specified index, and then adds the element |
|
||||||
* using the ListIterator's add method. |
|
||||||
* |
|
||||||
* @param index the position to add the element |
|
||||||
* @param o the element to insert |
|
||||||
* @exception IndexOutOfBoundsException if index < 0 || index > size() |
|
||||||
* @exception UnsupportedOperationException if the iterator returned by |
|
||||||
* listIterator(index) does not support the add method. |
|
||||||
*/ |
|
||||||
public void add(int index, Object o) { |
|
||||||
ListIterator i = listIterator(index); |
|
||||||
i.add(o); |
|
||||||
} |
|
||||||
|
|
||||||
public boolean addAll(int index, Collection c) { |
|
||||||
boolean changed = false; |
|
||||||
Iterator ci = c.iterator(); |
|
||||||
ListIterator i = listIterator(index); |
|
||||||
while (ci.hasNext()) { |
|
||||||
i.add(ci.next()); |
|
||||||
changed = true; |
|
||||||
} |
|
||||||
return changed; |
|
||||||
} |
|
||||||
|
|
||||||
public Object get(int index) { |
|
||||||
ListIterator i = listIterator(index); |
|
||||||
if (!i.hasNext()) { |
|
||||||
throw new IndexOutOfBoundsException(); |
|
||||||
} |
|
||||||
return i.next(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Return an Iterator over this List. This implementation returns |
|
||||||
* listIterator(). |
|
||||||
* |
|
||||||
* @return an Iterator over this List |
|
||||||
*/ |
|
||||||
public Iterator iterator() { |
|
||||||
return listIterator(); |
|
||||||
} |
|
||||||
|
|
||||||
public Object remove(int index) { |
|
||||||
ListIterator i = listIterator(index); |
|
||||||
if (!i.hasNext()) { |
|
||||||
throw new IndexOutOfBoundsException(); |
|
||||||
} |
|
||||||
Object removed = i.next(); |
|
||||||
i.remove(); |
|
||||||
return removed; |
|
||||||
} |
|
||||||
|
|
||||||
public Object set(int index, Object o) { |
|
||||||
ListIterator i = listIterator(index); |
|
||||||
if (!i.hasNext()) { |
|
||||||
throw new IndexOutOfBoundsException(); |
|
||||||
} |
|
||||||
Object old = i.next(); |
|
||||||
i.set(o); |
|
||||||
return old; |
|
||||||
} |
|
||||||
} |
|
@ -1,78 +0,0 @@ |
|||||||
// This interface is taken from the Classpath project.
|
|
||||||
// Please note the different copyright holder!
|
|
||||||
// The changes I did is this comment, the package line, some
|
|
||||||
// imports from java.util and some minor jdk12 -> jdk11 fixes.
|
|
||||||
// -- Jochen Hoenicke <jochen@gnu.org>
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
// AbstractSet.java -- Abstract implementation of most of Set
|
|
||||||
//
|
|
||||||
// Copyright (c) 1998 by Stuart Ballard (stuart.ballard@mcmail.com)
|
|
||||||
//
|
|
||||||
// This program is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Library General Public License as published
|
|
||||||
// by the Free Software Foundation, version 2. (see COPYING.LIB)
|
|
||||||
//
|
|
||||||
// This program 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 Library General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Library General Public License
|
|
||||||
// along with this program; if not, write to the Free Software Foundation
|
|
||||||
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
package jode.util; |
|
||||||
|
|
||||||
/** |
|
||||||
* An abstract implementation of Set to make it easier to create your own |
|
||||||
* implementations. In order to create a Set, subclass AbstractSet and |
|
||||||
* implement the same methods that are required for AbstractCollection |
|
||||||
* (although these methods must of course meet the requirements that Set puts |
|
||||||
* on them - specifically, no element may be in the set more than once). This |
|
||||||
* class simply provides implementations of equals() and hashCode() to fulfil |
|
||||||
* the requirements placed on them by the Set interface. |
|
||||||
*/ |
|
||||||
public abstract class AbstractSet extends AbstractCollection implements Set { |
|
||||||
|
|
||||||
/** |
|
||||||
* Tests whether the given object is equal to this Set. This implementation |
|
||||||
* first checks whether this set <em>is</em> the given object, and returns |
|
||||||
* true if so. Otherwise, if o is a Set and is the same size as this one, it |
|
||||||
* returns the result of calling containsAll on the given Set. Otherwise, it |
|
||||||
* returns false. |
|
||||||
* |
|
||||||
* @param o the Object to be tested for equality with this Set |
|
||||||
* @return true if the given object is equal to this Set |
|
||||||
*/ |
|
||||||
public boolean equals(Object o) { |
|
||||||
if (o == this) { |
|
||||||
return true; |
|
||||||
} else if (o instanceof Set && ((Set)o).size() == size()) { |
|
||||||
return containsAll((Collection)o); |
|
||||||
} else { |
|
||||||
return false; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Returns a hash code for this Set. The hash code of a Set is the sum of the |
|
||||||
* hash codes of all its elements, except that the hash code of null is |
|
||||||
* defined to be zero. This implementation obtains an Iterator over the Set, |
|
||||||
* and sums the results. |
|
||||||
* |
|
||||||
* @return a hash code for this Set |
|
||||||
*/ |
|
||||||
public int hashCode() { |
|
||||||
int hash = 0; |
|
||||||
Iterator i = iterator(); |
|
||||||
while (i.hasNext()) { |
|
||||||
try { |
|
||||||
hash += i.next().hashCode(); |
|
||||||
} catch (NullPointerException e) { |
|
||||||
} |
|
||||||
} |
|
||||||
return hash; |
|
||||||
} |
|
||||||
} |
|
@ -1,489 +0,0 @@ |
|||||||
// This class is taken from the Classpath project.
|
|
||||||
// Please note the different copyright holder!
|
|
||||||
// The changes I did is this comment, the package line, some
|
|
||||||
// imports from java.util and some minor jdk12 -> jdk11 fixes.
|
|
||||||
// -- Jochen Hoenicke <jochen@gnu.org>
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
// ArrayList.java -- JDK1.2's answer to Vector; this is an array-backed
|
|
||||||
// implementation of the List interface
|
|
||||||
//
|
|
||||||
// This is a JDK 1.2 compliant version of ArrayList.java
|
|
||||||
//
|
|
||||||
// Copyright (c) 1998 by Jon A. Zeppieri (jon@eease.com),
|
|
||||||
// Free Software Foundation, Inc.
|
|
||||||
//
|
|
||||||
// This program is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Library General Public License as published
|
|
||||||
// by the Free Software Foundation, version 2. (see COPYING.LIB)
|
|
||||||
//
|
|
||||||
// This program 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 Library General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Library General Public License
|
|
||||||
// along with this program; if not, write to the Free Software Foundation
|
|
||||||
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
package jode.util; |
|
||||||
|
|
||||||
import java.lang.reflect.Array; |
|
||||||
import java.io.Serializable; |
|
||||||
import java.io.IOException; |
|
||||||
import java.io.ObjectInputStream; |
|
||||||
import java.io.ObjectOutputStream; |
|
||||||
|
|
||||||
/** |
|
||||||
* An array-backed implementation of the List interface. ArrayList |
|
||||||
* performs well on simple tasks: random access into a list, appending |
|
||||||
* to or removing from the end of a list, checking the size, &c. |
|
||||||
* |
|
||||||
* @author Jon A. Zeppieri |
|
||||||
* @version $Id$ |
|
||||||
* @see java.util.AbstractList |
|
||||||
* @see java.util.List |
|
||||||
*/ |
|
||||||
public class ArrayList extends AbstractList |
|
||||||
implements List, Cloneable, Serializable |
|
||||||
{ |
|
||||||
/** the default capacity for new ArrayLists */ |
|
||||||
private static final int DEFAULT_CAPACITY = 16; |
|
||||||
|
|
||||||
/** the number of elements in this list */ |
|
||||||
int size; |
|
||||||
|
|
||||||
/** where the data is stored */ |
|
||||||
transient Object[] _arData; |
|
||||||
|
|
||||||
/** |
|
||||||
* Construct a new ArrayList with the supplied initial capacity. |
|
||||||
* |
|
||||||
* @param iCapacity |
|
||||||
*/ |
|
||||||
public ArrayList(int iCapacity) |
|
||||||
{ |
|
||||||
_arData = new Object[iCapacity]; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Construct a new ArrayList with the default capcity |
|
||||||
*/ |
|
||||||
public ArrayList() |
|
||||||
{ |
|
||||||
this(DEFAULT_CAPACITY); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Construct a new ArrayList, and initialize it with the elements |
|
||||||
* in the supplied Collection; Sun specs say that the initial |
|
||||||
* capacity is 110% of the Collection's size. |
|
||||||
* |
|
||||||
* @param oCollection the collection whose elements will |
|
||||||
* initialize this list |
|
||||||
*/ |
|
||||||
public ArrayList(Collection oCollection) |
|
||||||
{ |
|
||||||
this((int) (oCollection.size() * 1.1)); |
|
||||||
addAll(oCollection); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Guarantees that this list will have at least enough capacity to |
|
||||||
* hold iMinCapacity elements. |
|
||||||
* |
|
||||||
* @param iMinCapacity the minimum guaranteed capacity |
|
||||||
*/ |
|
||||||
public void ensureCapacity(int iMinCapacity) |
|
||||||
{ |
|
||||||
Object[] arNewData; |
|
||||||
int iCapacity = _arData.length; |
|
||||||
|
|
||||||
if (iMinCapacity > iCapacity) |
|
||||||
{ |
|
||||||
arNewData = new Object[Math.max((iCapacity * 2), iMinCapacity)]; |
|
||||||
System.arraycopy(_arData, 0, arNewData, 0, iCapacity); |
|
||||||
_arData = arNewData; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Appends the supplied element to the end of this list. |
|
||||||
* |
|
||||||
* @param oElement the element to be appended to this list |
|
||||||
*/ |
|
||||||
public boolean add(Object oElement) |
|
||||||
{ |
|
||||||
ensureCapacity(size + 1); |
|
||||||
_arData[size++] = oElement; |
|
||||||
modCount++; |
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Retrieves the element at the user-supplied index. |
|
||||||
* |
|
||||||
* @param iIndex the index of the element we are fetching |
|
||||||
* @throws IndexOutOfBoundsException (iIndex < 0) || (iIndex >= size()) |
|
||||||
*/ |
|
||||||
public Object get(int iIndex) |
|
||||||
{ |
|
||||||
if (iIndex >= size) |
|
||||||
throw new IndexOutOfBoundsException("ArrayList size=" + |
|
||||||
String.valueOf(size) + "; " + |
|
||||||
"index=" + String.valueOf(iIndex)); |
|
||||||
return _arData[iIndex]; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Returns the number of elements in this list |
|
||||||
*/ |
|
||||||
public int size() |
|
||||||
{ |
|
||||||
return size; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Removes the element at the user-supplied index |
|
||||||
* |
|
||||||
* @param iIndex the index of the element to be removed |
|
||||||
* @return the removed Object |
|
||||||
* @throws IndexOutOfBoundsException (iIndex < 0) || (iIndex >= size()) |
|
||||||
*/ |
|
||||||
public Object remove(int iIndex) |
|
||||||
{ |
|
||||||
Object oResult; |
|
||||||
|
|
||||||
if (iIndex >= size) |
|
||||||
throw new IndexOutOfBoundsException("ArrayList size=" + |
|
||||||
String.valueOf(size) + "; " + |
|
||||||
"index=" + String.valueOf(iIndex)); |
|
||||||
|
|
||||||
oResult = _arData[iIndex]; |
|
||||||
|
|
||||||
if (iIndex != --size) |
|
||||||
System.arraycopy(_arData, (iIndex + 1), _arData, iIndex, |
|
||||||
(size - iIndex)); |
|
||||||
|
|
||||||
modCount++; |
|
||||||
_arData[size] = null; |
|
||||||
|
|
||||||
return oResult; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Removes all elements in the half-open interval [iFromIndex, iToIndex). |
|
||||||
* |
|
||||||
* @param iFromIndex the first index which will be removed |
|
||||||
* @param iToIndex one greater than the last index which will be |
|
||||||
* removed |
|
||||||
*/ |
|
||||||
public void removeRange(int iFromIndex, int iToIndex) |
|
||||||
{ |
|
||||||
int iReduction; |
|
||||||
int i; |
|
||||||
|
|
||||||
if ((iFromIndex >= size) || (iToIndex >= size)) |
|
||||||
{ |
|
||||||
throw new IndexOutOfBoundsException("ArrayList size=" + |
|
||||||
String.valueOf(size) + "; " + |
|
||||||
"indices=" + |
|
||||||
String.valueOf(iFromIndex) + "," + |
|
||||||
String.valueOf(iToIndex)); |
|
||||||
} |
|
||||||
else if (iFromIndex > iToIndex) |
|
||||||
{ |
|
||||||
throw new IllegalArgumentException("fromIndex(" + |
|
||||||
String.valueOf(iFromIndex) + |
|
||||||
") > toIndex(" + |
|
||||||
String.valueOf(iToIndex) + ")"); |
|
||||||
} |
|
||||||
else if (iFromIndex != iToIndex) |
|
||||||
{ |
|
||||||
iReduction = iToIndex - iFromIndex; |
|
||||||
System.arraycopy(_arData, (iFromIndex + iReduction), _arData, |
|
||||||
iFromIndex, (size - iFromIndex - iReduction)); |
|
||||||
modCount++; |
|
||||||
|
|
||||||
for (i = (iFromIndex + iReduction); i < size; i++) |
|
||||||
_arData[i] = null; |
|
||||||
|
|
||||||
size -= iReduction; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Adds the supplied element at the specified index, shifting all |
|
||||||
* elements currently at that index or higher one to the right. |
|
||||||
* |
|
||||||
* @param iIndex the index at which the element is being added |
|
||||||
* @param oElement the element being added |
|
||||||
*/ |
|
||||||
public void add(int iIndex, Object oElement) |
|
||||||
{ |
|
||||||
if (iIndex > size) |
|
||||||
throw new IndexOutOfBoundsException("ArrayList size=" + |
|
||||||
String.valueOf(size) + "; " + |
|
||||||
"index=" + String.valueOf(iIndex)); |
|
||||||
|
|
||||||
ensureCapacity(size + 1); |
|
||||||
System.arraycopy(_arData, iIndex, _arData, |
|
||||||
(iIndex + 1), (size - iIndex)); |
|
||||||
_arData[iIndex] = oElement; |
|
||||||
size++; |
|
||||||
modCount++; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Add each element in the supplied Collection to this List. |
|
||||||
* |
|
||||||
* @param oCollection a Collection containing elements to be |
|
||||||
* added to this List |
|
||||||
*/ |
|
||||||
public boolean addAll(Collection oCollection) |
|
||||||
{ |
|
||||||
Iterator itElements; |
|
||||||
int iLen = oCollection.size(); |
|
||||||
|
|
||||||
if (iLen > 0) |
|
||||||
{ |
|
||||||
ensureCapacity(size + iLen); |
|
||||||
modCount++; |
|
||||||
|
|
||||||
itElements = oCollection.iterator(); |
|
||||||
|
|
||||||
while (itElements.hasNext()) |
|
||||||
_arData[size++] = itElements.next(); |
|
||||||
|
|
||||||
return true; |
|
||||||
} |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Add all elements in the supplied collection, inserting them beginning |
|
||||||
* at the specified index. |
|
||||||
* |
|
||||||
* @param iIndex the index at which the elements will be inserted |
|
||||||
* @param oCollection the Collection containing the elements to be |
|
||||||
* inserted |
|
||||||
*/ |
|
||||||
public boolean addAll(int iIndex, Collection oCollection) |
|
||||||
{ |
|
||||||
Iterator itElements; |
|
||||||
int iLen; |
|
||||||
|
|
||||||
if (iIndex > size) |
|
||||||
throw new IndexOutOfBoundsException("ArrayList size=" + |
|
||||||
String.valueOf(size) + "; " + |
|
||||||
"index=" + String.valueOf(iIndex)); |
|
||||||
|
|
||||||
iLen = oCollection.size(); |
|
||||||
|
|
||||||
if (iLen > 0) |
|
||||||
{ |
|
||||||
ensureCapacity(size + iLen); |
|
||||||
|
|
||||||
System.arraycopy(_arData, iIndex, _arData, |
|
||||||
(iIndex + iLen), (size - iIndex)); |
|
||||||
modCount++; |
|
||||||
size += iLen; |
|
||||||
|
|
||||||
itElements = oCollection.iterator(); |
|
||||||
while (itElements.hasNext()) |
|
||||||
_arData[iIndex++] = itElements.next(); |
|
||||||
|
|
||||||
return true; |
|
||||||
} |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Creates a shallow copy of this ArrayList |
|
||||||
*/ |
|
||||||
public Object clone() |
|
||||||
{ |
|
||||||
ArrayList oClone; |
|
||||||
|
|
||||||
try |
|
||||||
{ |
|
||||||
oClone = (ArrayList) super.clone(); |
|
||||||
oClone._arData = _arData; |
|
||||||
oClone.size = size; |
|
||||||
} |
|
||||||
catch(CloneNotSupportedException e) |
|
||||||
{ |
|
||||||
oClone = null; |
|
||||||
} |
|
||||||
return oClone; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Returns true iff oElement is in this ArrayList. |
|
||||||
* |
|
||||||
* @param oElement the element whose inclusion in the List is being |
|
||||||
* tested |
|
||||||
*/ |
|
||||||
public boolean contains(Object oElement) |
|
||||||
{ |
|
||||||
return (indexOf(oElement) != -1); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Returns the lowest index at which oElement appears in this List, or |
|
||||||
* -1 if it does not appear. |
|
||||||
* |
|
||||||
* @param oElement the element whose inclusion in the List is being |
|
||||||
* tested |
|
||||||
*/ |
|
||||||
public int indexOf(Object oElement) |
|
||||||
{ |
|
||||||
int i; |
|
||||||
|
|
||||||
for (i = 0; i < size; i++) |
|
||||||
{ |
|
||||||
if (doesEqual(oElement, _arData[i])) |
|
||||||
return i; |
|
||||||
} |
|
||||||
return -1; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Returns the highest index at which oElement appears in this List, or |
|
||||||
* -1 if it does not appear. |
|
||||||
* |
|
||||||
* @param oElement the element whose inclusion in the List is being |
|
||||||
* tested |
|
||||||
*/ |
|
||||||
public int lastIndexOf(Object oElement) |
|
||||||
{ |
|
||||||
int i; |
|
||||||
|
|
||||||
for (i = size - 1; i >= 0; i--) |
|
||||||
{ |
|
||||||
if (doesEqual(oElement, _arData[i])) |
|
||||||
return i; |
|
||||||
} |
|
||||||
return -1; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Removes all elements from this List |
|
||||||
*/ |
|
||||||
public void clear() |
|
||||||
{ |
|
||||||
int i; |
|
||||||
|
|
||||||
if (size > 0) |
|
||||||
{ |
|
||||||
modCount++; |
|
||||||
size = 0; |
|
||||||
|
|
||||||
for (i = 0; i < size; i++) |
|
||||||
_arData[i] = null; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Sets the element at the specified index. |
|
||||||
* |
|
||||||
* @param iIndex the index at which the element is being set |
|
||||||
* @param oElement the element to be set |
|
||||||
* @return the element previously at the specified index, or null if |
|
||||||
* none was there |
|
||||||
*/ |
|
||||||
public Object set(int iIndex, Object oElement) |
|
||||||
{ |
|
||||||
Object oResult; |
|
||||||
|
|
||||||
if (iIndex >= size) |
|
||||||
throw new IndexOutOfBoundsException("ArrayList size=" + |
|
||||||
String.valueOf(size) + "; " + |
|
||||||
"index=" + String.valueOf(iIndex)); |
|
||||||
oResult = _arData[iIndex]; |
|
||||||
modCount++; |
|
||||||
_arData[iIndex] = oElement; |
|
||||||
|
|
||||||
return oResult; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Returns an Object Array containing all of the elements in this ArrayList |
|
||||||
*/ |
|
||||||
public Object[] toArray() |
|
||||||
{ |
|
||||||
Object[] arObjects = new Object[size]; |
|
||||||
System.arraycopy(_arData, 0, arObjects, 0, size); |
|
||||||
return arObjects; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Returns an Array whse component type is the runtime component type of |
|
||||||
* the passes-in Array. The returned Array is populated with all of the |
|
||||||
* elements in this ArrayList. If the passed-in Array is not large enough |
|
||||||
* to store all of the elements in this List, a new Array will be created |
|
||||||
* and returned; if the passed-in Array is <i>larger</i> than the size |
|
||||||
* of this List, then size() + 1 index will be set to null. |
|
||||||
* |
|
||||||
* @param arObjects the passed-in Array |
|
||||||
*/ |
|
||||||
public Object[] toArray(Object[] arObjects) |
|
||||||
{ |
|
||||||
Object[] arReturn = (arObjects.length >= size) |
|
||||||
? arObjects |
|
||||||
: (Object[]) |
|
||||||
Array.newInstance(arObjects.getClass().getComponentType(), size); |
|
||||||
|
|
||||||
System.arraycopy(_arData, 0, arReturn, 0, size); |
|
||||||
|
|
||||||
if (arReturn.length > size) |
|
||||||
arReturn[size] = null; |
|
||||||
|
|
||||||
return arReturn; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Trims the capacity of tjis List to be equal to its size; |
|
||||||
* a memory saver. |
|
||||||
*/ |
|
||||||
public void trimToSize() |
|
||||||
{ |
|
||||||
Object[] arNewData = new Object[size]; |
|
||||||
System.arraycopy(_arData, 0, arNewData, 0, size); |
|
||||||
modCount++; |
|
||||||
_arData = arNewData; |
|
||||||
} |
|
||||||
|
|
||||||
private void writeObject(ObjectOutputStream oOut) |
|
||||||
throws IOException |
|
||||||
{ |
|
||||||
int i; |
|
||||||
|
|
||||||
oOut.defaultWriteObject(); |
|
||||||
|
|
||||||
oOut.writeInt(_arData.length); |
|
||||||
for (i = 0; i < _arData.length; i++) |
|
||||||
oOut.writeObject(_arData[i]); |
|
||||||
} |
|
||||||
|
|
||||||
private void readObject(ObjectInputStream oIn) |
|
||||||
throws IOException, ClassNotFoundException |
|
||||||
{ |
|
||||||
int i; |
|
||||||
int iCapacity; |
|
||||||
oIn.defaultReadObject(); |
|
||||||
|
|
||||||
iCapacity = oIn.readInt(); |
|
||||||
_arData = new Object[iCapacity]; |
|
||||||
|
|
||||||
for (i = 0; i < iCapacity; i++) |
|
||||||
_arData[i] = oIn.readObject(); |
|
||||||
} |
|
||||||
|
|
||||||
private static final boolean doesEqual(Object oOne, Object oTwo) |
|
||||||
{ |
|
||||||
return ((oOne == null) ? (oTwo == null) : oOne.equals(oTwo)); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -1,138 +0,0 @@ |
|||||||
// This class is taken from the Classpath project.
|
|
||||||
// Please note the different copyright holder!
|
|
||||||
// The changes I did is this comment, the package line, some
|
|
||||||
// imports from java.util and some minor jdk12 -> jdk11 fixes.
|
|
||||||
// -- Jochen Hoenicke <jochen@gnu.org>
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
// BasicMapEntry.java -- a class providing a plain-vanilla implementation of
|
|
||||||
// the Map.Entry interface; could be used anywhere in
|
|
||||||
// java.util
|
|
||||||
//
|
|
||||||
// Copyright (c) 1998 by Jon A. Zeppieri (jon@eease.com)
|
|
||||||
//
|
|
||||||
// This program is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Library General Public License as published
|
|
||||||
// by the Free Software Foundation, version 2. (see COPYING.LIB)
|
|
||||||
//
|
|
||||||
// This program 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 Library General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Library General Public License
|
|
||||||
// along with this program; if not, write to the Free Software Foundation
|
|
||||||
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
package jode.util; |
|
||||||
///#ifdef JDK12
|
|
||||||
///import java.lang.UnsupportedOperationException;
|
|
||||||
///import java.util.Map;
|
|
||||||
///#endif
|
|
||||||
|
|
||||||
/** |
|
||||||
* a class which implements Map.Entry |
|
||||||
* |
|
||||||
* @author Jon Zeppieri |
|
||||||
* @version $Revision$ |
|
||||||
* @modified $Id$ |
|
||||||
*/ |
|
||||||
class BasicMapEntry implements Map.Entry |
|
||||||
{ |
|
||||||
/** the key */ |
|
||||||
Object key; |
|
||||||
/** the value */ |
|
||||||
Object value; |
|
||||||
|
|
||||||
/** |
|
||||||
* construct a new BasicMapEntry with the given key and value |
|
||||||
* |
|
||||||
* @param newKey the key of this Entry |
|
||||||
* @param newValue the value of this Entry |
|
||||||
*/ |
|
||||||
BasicMapEntry(Object newKey, Object newValue) |
|
||||||
{ |
|
||||||
key = newKey; |
|
||||||
value = newValue; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* returns true if <pre>o</pre> is a Map.Entry and |
|
||||||
* <pre> |
|
||||||
* (((o.getKey == null) ? (key == null) : |
|
||||||
* o.getKey().equals(key)) && |
|
||||||
* ((o.getValue() == null) ? (value == null) : |
|
||||||
* o.getValue().equals(value))) |
|
||||||
* </pre> |
|
||||||
* |
|
||||||
* NOTE: the calls to getKey() and getValue() in this implementation |
|
||||||
* are <i>NOT</i> superfluous and should not be removed. They insure |
|
||||||
* that subclasses such as HashMapEntry work correctly |
|
||||||
* |
|
||||||
* @param o the Object being tested for equality |
|
||||||
*/ |
|
||||||
public boolean equals(Object o) |
|
||||||
{ |
|
||||||
Map.Entry tester; |
|
||||||
Object oTestingKey, oTestingValue; |
|
||||||
Object oKey, oValue; |
|
||||||
if (o instanceof Map.Entry) |
|
||||||
{ |
|
||||||
tester = (Map.Entry) o; |
|
||||||
oKey = getKey(); |
|
||||||
oValue = getValue(); |
|
||||||
oTestingKey = tester.getKey(); |
|
||||||
oTestingValue = tester.getValue(); |
|
||||||
return (((oTestingKey == null) ? (oKey == null) : |
|
||||||
oTestingKey.equals(oKey)) && |
|
||||||
((oTestingValue == null) ? (oValue == null) : |
|
||||||
oTestingValue.equals(oValue))); |
|
||||||
} |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
/** returns the key */ |
|
||||||
public Object getKey() |
|
||||||
{ |
|
||||||
return key; |
|
||||||
} |
|
||||||
|
|
||||||
/** returns the value */ |
|
||||||
public Object getValue() |
|
||||||
{ |
|
||||||
return value; |
|
||||||
} |
|
||||||
|
|
||||||
/** the hashCode() for a Map.Entry is |
|
||||||
* <pre> |
|
||||||
* ((getKey() == null) ? 0 : getKey().hashCode()) ^ |
|
||||||
* ((getValue() == null) ? 0 : getValue().hashCode()); |
|
||||||
* </pre> |
|
||||||
* |
|
||||||
* NOTE: the calls to getKey() and getValue() in this implementation |
|
||||||
* are <i>NOT</i> superfluous and should not be removed. They insure |
|
||||||
* that subclasses such as HashMapEntry work correctly |
|
||||||
*/ |
|
||||||
public int hashCode() |
|
||||||
{ |
|
||||||
Object oKey = getKey(); |
|
||||||
Object oValue = getValue(); |
|
||||||
return ((oKey == null) ? 0 : oKey.hashCode()) ^ |
|
||||||
((oValue == null) ? 0 : oValue.hashCode()); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* sets the value of this Map.Entry |
|
||||||
* |
|
||||||
* @param newValue the new value of this Map.Entry |
|
||||||
*/ |
|
||||||
public Object setValue(Object newValue) |
|
||||||
throws UnsupportedOperationException, ClassCastException, |
|
||||||
IllegalArgumentException, NullPointerException |
|
||||||
{ |
|
||||||
Object oVal = value; |
|
||||||
value = newValue; |
|
||||||
return oVal; |
|
||||||
} |
|
||||||
} |
|
@ -1,198 +0,0 @@ |
|||||||
// This class is taken from the Classpath project.
|
|
||||||
// Please note the different copyright holder!
|
|
||||||
// The changes I did is this comment, the package line, some
|
|
||||||
// imports from java.util and some minor jdk12 -> jdk11 fixes.
|
|
||||||
// -- Jochen Hoenicke <jochen@gnu.org>
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Bucket.java -- a class providing a hash-bucket data structure (a lightweight
|
|
||||||
// linked list)
|
|
||||||
//
|
|
||||||
// Copyright (c) 1998 by Jon A. Zeppieri (jon@eease.com)
|
|
||||||
//
|
|
||||||
// This program is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Library General Public License as published
|
|
||||||
// by the Free Software Foundation, version 2. (see COPYING.LIB)
|
|
||||||
//
|
|
||||||
// This program 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 Library General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Library General Public License
|
|
||||||
// along with this program; if not, write to the Free Software Foundation
|
|
||||||
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
package jode.util; |
|
||||||
|
|
||||||
/** |
|
||||||
* a class representing a simple, lightweight linked-list, using Node |
|
||||||
* objects as its linked nodes; this is used by Hashtable and HashMap |
|
||||||
* |
|
||||||
* @author Jon Zeppieri |
|
||||||
* @version $Revision$ |
|
||||||
* @modified $Id$ |
|
||||||
*/ |
|
||||||
class Bucket |
|
||||||
{ |
|
||||||
/** the first node of the lined list, originally null */ |
|
||||||
Node first; |
|
||||||
|
|
||||||
/** trivial constructor for a Bucket */ |
|
||||||
Bucket() |
|
||||||
{ |
|
||||||
} |
|
||||||
|
|
||||||
/** add this key / value pair to the list |
|
||||||
* |
|
||||||
* @param entry a Map.Entry object to be added to this list |
|
||||||
*/ |
|
||||||
Map.Entry add(Node newNode) |
|
||||||
{ |
|
||||||
Object oKey; |
|
||||||
Object oTestKey = newNode.getKey(); |
|
||||||
Node it = first; |
|
||||||
Node prev = null; |
|
||||||
if (it == null) // if the list is empty (the ideal case), we make a new single-node list
|
|
||||||
{ |
|
||||||
first = newNode; |
|
||||||
return null; |
|
||||||
} |
|
||||||
else // otherwise try to find where this key already exists in the list,
|
|
||||||
{// and if it does, replace the value with the new one (and return the old one)
|
|
||||||
while (it != null) |
|
||||||
{ |
|
||||||
oKey = it.getKey(); |
|
||||||
if ((oKey == null) ? (oTestKey == null) : |
|
||||||
oKey.equals(oTestKey)) |
|
||||||
{ |
|
||||||
if (prev != null) |
|
||||||
prev.next = newNode; |
|
||||||
else |
|
||||||
first = newNode; |
|
||||||
newNode.next = it.next; |
|
||||||
return it; |
|
||||||
} |
|
||||||
prev = it; |
|
||||||
it = it.next; |
|
||||||
} |
|
||||||
prev.next = newNode; // otherwise, just stick this at the
|
|
||||||
return null; // end of the list
|
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* remove a Map.Entry in this list with the supplied key and return its value, |
|
||||||
* if it exists, else return null |
|
||||||
* |
|
||||||
* @param key the key we are looking for in this list |
|
||||||
*/ |
|
||||||
Object removeByKey(Object key) |
|
||||||
{ |
|
||||||
Object oEntryKey; |
|
||||||
Node prev = null; |
|
||||||
Node it = first; |
|
||||||
while (it != null) |
|
||||||
{ |
|
||||||
oEntryKey = it.getKey(); |
|
||||||
if ((oEntryKey == null) ? (key == null) : oEntryKey.equals(key)) |
|
||||||
{ |
|
||||||
if (prev == null) // we are removing the first element
|
|
||||||
first = it.next; |
|
||||||
else |
|
||||||
prev.next = it.next; |
|
||||||
return it.getValue(); |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
prev = it; |
|
||||||
it = it.next; |
|
||||||
} |
|
||||||
} |
|
||||||
return null; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* return the value which the supplied key maps to, if it maps to anything in this list, |
|
||||||
* otherwise, return null |
|
||||||
* |
|
||||||
* @param key the key mapping to a value that we are looking for |
|
||||||
*/ |
|
||||||
Object getValueByKey(Object key) |
|
||||||
{ |
|
||||||
Node entry = getEntryByKey(key); |
|
||||||
return (entry == null) ? null : entry.getValue(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* return the Map.Entry which the supplied key is a part of, if such a Map.Entry exists, |
|
||||||
* null otherwise |
|
||||||
* |
|
||||||
* this method is important for HashMap, which can hold null values and the null key |
|
||||||
* |
|
||||||
* @param key the key for which we are finding the corresponding Map.Entry |
|
||||||
*/ |
|
||||||
Node getEntryByKey(Object key) |
|
||||||
{ |
|
||||||
Object oEntryKey; |
|
||||||
Node it = first; |
|
||||||
while (it != null) |
|
||||||
{ |
|
||||||
oEntryKey = it.getKey(); |
|
||||||
if ((oEntryKey == null) ? (key == null) : oEntryKey.equals(key)) |
|
||||||
return it; |
|
||||||
it = it.next; |
|
||||||
} |
|
||||||
return null; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* return true if this list has a Map.Entry whose value equals() the supplied value |
|
||||||
* |
|
||||||
* @param value the value we are looking to match in this list |
|
||||||
*/ |
|
||||||
boolean containsValue(Object value) |
|
||||||
{ |
|
||||||
Object oEntryValue; |
|
||||||
Node it = first; |
|
||||||
while (it != null) |
|
||||||
{ |
|
||||||
oEntryValue = it.getValue(); |
|
||||||
if ((oEntryValue == null) ? (value == null) : oEntryValue.equals(value)) |
|
||||||
return true; |
|
||||||
it = it.next; |
|
||||||
} |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
// INNSER CLASSES ----------------------------------------------------------
|
|
||||||
|
|
||||||
/** |
|
||||||
* a class represnting a node in our lightweight linked-list |
|
||||||
* that we use for hash buckets; a Node object contains a Map.Entry as its |
|
||||||
* <pre>value</pre> property and a reference (possibly, even hopefully, null) |
|
||||||
* to another Node as its <pre>next</pre> property. |
|
||||||
* |
|
||||||
* There <i>is</i> a reason for not using a highly generic "LinkedNode" type |
|
||||||
* class: we want to eliminate runtime typechecks. |
|
||||||
* |
|
||||||
* @author Jon Zeppieri |
|
||||||
* @version $Revision$ |
|
||||||
* @modified $Id$ |
|
||||||
*/ |
|
||||||
static class Node extends BasicMapEntry implements Map.Entry |
|
||||||
{ |
|
||||||
/** a reference to the next node in the linked list */ |
|
||||||
Node next; |
|
||||||
|
|
||||||
/** non-trivial contructor -- sets the <pre>value</pre> of the Bucket upon instantiation */ |
|
||||||
Node(Object key, Object value) |
|
||||||
{ |
|
||||||
super(key, value); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
} |
|
||||||
// EOF ------------------------------------------------------------------------
|
|
||||||
} |
|
@ -1,234 +0,0 @@ |
|||||||
// This interface is taken from the Classpath project.
|
|
||||||
// Please note the different copyright holder!
|
|
||||||
// The changes I did is this comment, the package line, some
|
|
||||||
// imports from java.util and some minor jdk12 -> jdk11 fixes.
|
|
||||||
// -- Jochen Hoenicke <jochen@gnu.org>
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Collection.java -- Interface that represents a collection of objects
|
|
||||||
//
|
|
||||||
// Copyright (c) 1998 by Stuart Ballard (stuart.ballard@mcmail.com)
|
|
||||||
//
|
|
||||||
// This program is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Library General Public License as published
|
|
||||||
// by the Free Software Foundation, version 2. (see COPYING.LIB)
|
|
||||||
//
|
|
||||||
// This program 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 Library General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Library General Public License
|
|
||||||
// along with this program; if not, write to the Free Software Foundation
|
|
||||||
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// TO DO:
|
|
||||||
// ~ Maybe some more @see clauses would be helpful.
|
|
||||||
|
|
||||||
package jode.util; |
|
||||||
|
|
||||||
/** |
|
||||||
* Interface that represents a collection of objects. This interface is the |
|
||||||
* root of the collection hierarchy, and does not provide any guarantees about |
|
||||||
* the order of its elements or whether or not duplicate elements are |
|
||||||
* permitted. |
|
||||||
* <p> |
|
||||||
* All methods of this interface that are defined to modify the collection are |
|
||||||
* defined as <dfn>optional</dfn>. An optional operation may throw an |
|
||||||
* UnsupportedOperationException if the data backing this collection does not |
|
||||||
* support such a modification. This may mean that the data structure is |
|
||||||
* immutable, or that it is read-only but may change ("unmodifiable"), or |
|
||||||
* that it is modifiable but of fixed size (such as an array), or any number |
|
||||||
* of other combinations. |
|
||||||
* <p> |
|
||||||
* A class that wishes to implement this interface should consider subclassing |
|
||||||
* AbstractCollection, which provides basic implementations of most of the |
|
||||||
* methods of this interface. Classes that are prepared to make guarantees |
|
||||||
* about ordering or about absence of duplicate elements should consider |
|
||||||
* implementing List or Set respectively, both of which are subinterfaces of |
|
||||||
* Collection. |
|
||||||
* <p> |
|
||||||
* A general-purpose implementation of the Collection interface should in most |
|
||||||
* cases provide at least two constructors: One which takes no arguments and |
|
||||||
* creates an empty collection, and one which takes a Collection as an argument |
|
||||||
* and returns a collection containing the same elements (that is, creates a |
|
||||||
* copy of the argument using its own implementation). |
|
||||||
* |
|
||||||
* @see java.util.List |
|
||||||
* @see java.util.Set |
|
||||||
* @see java.util.AbstractCollection |
|
||||||
*/ |
|
||||||
public interface Collection { |
|
||||||
|
|
||||||
/** |
|
||||||
* Add an element to this collection. |
|
||||||
* |
|
||||||
* @param o the object to add. |
|
||||||
* @returns true if the collection was modified as a result of this action. |
|
||||||
* @exception UnsupportedOperationException if this collection does not |
|
||||||
* support the add operation. |
|
||||||
* @exception ClassCastException if o cannot be added to this collection due |
|
||||||
* to its type. |
|
||||||
* @exception IllegalArgumentException if o cannot be added to this |
|
||||||
* collection for some other reason. |
|
||||||
*/ |
|
||||||
boolean add(Object o); |
|
||||||
|
|
||||||
/** |
|
||||||
* Add the contents of a given collection to this collection. |
|
||||||
* |
|
||||||
* @param c the collection to add. |
|
||||||
* @returns true if the collection was modified as a result of this action. |
|
||||||
* @exception UnsupportedOperationException if this collection does not |
|
||||||
* support the addAll operation. |
|
||||||
* @exception ClassCastException if some element of c cannot be added to this |
|
||||||
* collection due to its type. |
|
||||||
* @exception IllegalArgumentException if some element of c cannot be added |
|
||||||
* to this collection for some other reason. |
|
||||||
*/ |
|
||||||
boolean addAll(Collection c); |
|
||||||
|
|
||||||
/** |
|
||||||
* Clear the collection, such that a subsequent call to isEmpty() would |
|
||||||
* return true. |
|
||||||
* |
|
||||||
* @exception UnsupportedOperationException if this collection does not |
|
||||||
* support the clear operation. |
|
||||||
*/ |
|
||||||
void clear(); |
|
||||||
|
|
||||||
/** |
|
||||||
* Test whether this collection contains a given object as one of its |
|
||||||
* elements. |
|
||||||
* |
|
||||||
* @param o the element to look for. |
|
||||||
* @returns true if this collection contains at least one element e such that |
|
||||||
* <code>o == null ? e == null : o.equals(e)</code>. |
|
||||||
*/ |
|
||||||
boolean contains(Object o); |
|
||||||
|
|
||||||
/** |
|
||||||
* Test whether this collection contains every element in a given collection. |
|
||||||
* |
|
||||||
* @param c the collection to test for. |
|
||||||
* @returns true if for every element o in c, contains(o) would return true. |
|
||||||
*/ |
|
||||||
boolean containsAll(Collection c); |
|
||||||
|
|
||||||
/** |
|
||||||
* Test whether this collection is equal to some object. The Collection |
|
||||||
* interface does not explicitly require any behaviour from this method, and |
|
||||||
* it may be left to the default implementation provided by Object. The Set |
|
||||||
* and List interfaces do, however, require specific behaviour from this |
|
||||||
* method. |
|
||||||
* <p> |
|
||||||
* If an implementation of Collection, which is not also an implementation of |
|
||||||
* Set or List, should choose to implement this method, it should take care |
|
||||||
* to obey the contract of the equals method of Object. In particular, care |
|
||||||
* should be taken to return false when o is a Set or a List, in order to |
|
||||||
* preserve the symmetry of the relation. |
|
||||||
* |
|
||||||
* @param o the object to compare to this collection. |
|
||||||
* @returns true if the o is equal to this collection. |
|
||||||
*/ |
|
||||||
boolean equals(Object o); |
|
||||||
|
|
||||||
/** |
|
||||||
* Obtain a hash code for this collection. The Collection interface does not |
|
||||||
* explicitly require any behaviour from this method, and it may be left to |
|
||||||
* the default implementation provided by Object. The Set and List interfaces |
|
||||||
* do, however, require specific behaviour from this method. |
|
||||||
* <p> |
|
||||||
* If an implementation of Collection, which is not also an implementation of |
|
||||||
* Set or List, should choose to implement this method, it should take care |
|
||||||
* to obey the contract of the hashCode method of Object. Note that this |
|
||||||
* method renders it impossible to correctly implement both Set and List, as |
|
||||||
* the required implementations are mutually exclusive. |
|
||||||
* |
|
||||||
* @returns a hash code for this collection. |
|
||||||
*/ |
|
||||||
int hashCode(); |
|
||||||
|
|
||||||
/** |
|
||||||
* Test whether this collection is empty, that is, if size() == 0. |
|
||||||
* |
|
||||||
* @returns true if this collection contains no elements. |
|
||||||
*/ |
|
||||||
boolean isEmpty(); |
|
||||||
|
|
||||||
/** |
|
||||||
* Obtain an Iterator over this collection. |
|
||||||
* |
|
||||||
* @returns an Iterator over the elements of this collection, in any order. |
|
||||||
*/ |
|
||||||
Iterator iterator(); |
|
||||||
|
|
||||||
/** |
|
||||||
* Remove a single occurrence of an object from this collection. That is, |
|
||||||
* remove an element e, if one exists, such that <code>o == null ? e == null |
|
||||||
* : o.equals(e)</code>. |
|
||||||
* |
|
||||||
* @param o the object to remove. |
|
||||||
* @returns true if the collection changed as a result of this call, that is, |
|
||||||
* if the collection contained at least one occurrence of o. |
|
||||||
* @exception UnsupportedOperationException if this collection does not |
|
||||||
* support the remove operation. |
|
||||||
*/ |
|
||||||
boolean remove(Object o); |
|
||||||
|
|
||||||
/** |
|
||||||
* Remove all elements of a given collection from this collection. That is, |
|
||||||
* remove every element e such that c.contains(e). |
|
||||||
* |
|
||||||
* @returns true if this collection was modified as a result of this call. |
|
||||||
* @exception UnsupportedOperationException if this collection does not |
|
||||||
* support the removeAll operation. |
|
||||||
*/ |
|
||||||
boolean removeAll(Collection c); |
|
||||||
|
|
||||||
/** |
|
||||||
* Remove all elements of this collection that are not contained in a given |
|
||||||
* collection. That is, remove every element e such that !c.contains(e). |
|
||||||
* |
|
||||||
* @returns true if this collection was modified as a result of this call. |
|
||||||
* @exception UnsupportedOperationException if this collection does not |
|
||||||
* support the retainAll operation. |
|
||||||
*/ |
|
||||||
boolean retainAll(Collection c); |
|
||||||
|
|
||||||
/** |
|
||||||
* Get the number of elements in this collection. |
|
||||||
* |
|
||||||
* @returns the number of elements in the collection. |
|
||||||
*/ |
|
||||||
int size(); |
|
||||||
|
|
||||||
/** |
|
||||||
* Copy the current contents of this collection into an array. |
|
||||||
* |
|
||||||
* @returns an array of type Object[] and length equal to the size of this |
|
||||||
* collection, containing the elements currently in this collection, in |
|
||||||
* any order. |
|
||||||
*/ |
|
||||||
Object[] toArray(); |
|
||||||
|
|
||||||
/** |
|
||||||
* Copy the current contents of this collection into an array. If the array |
|
||||||
* passed as an argument has length less than the size of this collection, an |
|
||||||
* array of the same run-time type as a, and length equal to the size of this |
|
||||||
* collection, is allocated using Reflection. Otherwise, a itself is used. |
|
||||||
* The elements of this collection are copied into it, and if there is space |
|
||||||
* in the array, the following element is set to null. The resultant array is |
|
||||||
* returned. |
|
||||||
* Note: The fact that the following element is set to null is only useful |
|
||||||
* if it is known that this collection does not contain any null elements. |
|
||||||
* |
|
||||||
* @param a the array to copy this collection into. |
|
||||||
* @returns an array containing the elements currently in this collection, in |
|
||||||
* any order. |
|
||||||
* @exception ArrayStoreException if the type of any element of the |
|
||||||
* collection is not a subtype of the element type of a. |
|
||||||
*/ |
|
||||||
Object[] toArray(Object[] a); |
|
||||||
} |
|
File diff suppressed because it is too large
Load Diff
@ -1,51 +0,0 @@ |
|||||||
// This interface is taken from the Classpath project.
|
|
||||||
// Please note the different copyright holder!
|
|
||||||
// The changes I did is this comment, the package line, some
|
|
||||||
// imports from java.util and some minor jdk12 -> jdk11 fixes.
|
|
||||||
// -- Jochen Hoenicke <jochen@gnu.org>
|
|
||||||
|
|
||||||
/************************************************************************* |
|
||||||
/* Comparable.java -- Interface for comparaing objects to obtain an ordering |
|
||||||
/* |
|
||||||
/* Copyright (c) 1998 by Free Software Foundation, Inc. |
|
||||||
/* |
|
||||||
/* This program is free software; you can redistribute it and/or modify |
|
||||||
/* it under the terms of the GNU Library General Public License as published |
|
||||||
/* by the Free Software Foundation, version 2. (see COPYING.LIB) |
|
||||||
/* |
|
||||||
/* This program 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 for more details. |
|
||||||
/* |
|
||||||
/* You should have received a copy of the GNU General Public License |
|
||||||
/* along with this program; if not, write to the Free Software Foundation |
|
||||||
/* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA |
|
||||||
/*************************************************************************/ |
|
||||||
|
|
||||||
package jode.util; |
|
||||||
|
|
||||||
/** |
|
||||||
** Interface for objects that can be ordering among other |
|
||||||
** objects. The ordering can be <EM>total</EM>, such that two objects |
|
||||||
** only compare equal if they are equal by the equals method, or |
|
||||||
** <EM>partial</EM> such that this is not necessarily true. For |
|
||||||
** example, a case-sensitive dictionary order comparison of Strings |
|
||||||
** is total, but if it is case-insensitive it is partial, because |
|
||||||
** "abc" and "ABC" compare as equal even though "abc".equals("ABC") |
|
||||||
** returns false. |
|
||||||
** |
|
||||||
** @author Geoff Berry |
|
||||||
** |
|
||||||
** @since JDK1.2 |
|
||||||
** @see java.util.Comparator |
|
||||||
**/ |
|
||||||
public interface Comparable |
|
||||||
{ |
|
||||||
/** |
|
||||||
** @return a negative integer if this object is less than |
|
||||||
** <code>o<code>, zero if this object is equal to <code>o</code>, or |
|
||||||
** a positive integer if this object is greater than <code>o</code> |
|
||||||
**/ |
|
||||||
public int compareTo( Object o ); |
|
||||||
} |
|
@ -1,62 +0,0 @@ |
|||||||
// This interface is taken from the Classpath project.
|
|
||||||
// Please note the different copyright holder!
|
|
||||||
// The changes I did is this comment, the package line, some
|
|
||||||
// imports from java.util and some minor jdk12 -> jdk11 fixes.
|
|
||||||
// -- Jochen Hoenicke <jochen@gnu.org>
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Comparator.java -- Interface for objects that specify an ordering
|
|
||||||
//
|
|
||||||
// Copyright (c) 1998 by Stuart Ballard (stuart.ballard@mcmail.com)
|
|
||||||
//
|
|
||||||
// This program is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Library General Public License as published
|
|
||||||
// by the Free Software Foundation, version 2. (see COPYING.LIB)
|
|
||||||
//
|
|
||||||
// This program 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 Library General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Library General Public License
|
|
||||||
// along with this program; if not, write to the Free Software Foundation
|
|
||||||
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
package jode.util; |
|
||||||
|
|
||||||
/** |
|
||||||
* Interface for objects that specify an ordering between objects. The ordering |
|
||||||
* can be <EM>total</EM>, such that two objects only compare equal if they are |
|
||||||
* equal by the equals method, or <EM>partial</EM> such that this is not |
|
||||||
* necessarily true. For example, a case-sensitive dictionary order comparison |
|
||||||
* of Strings is total, but if it is case-insensitive it is partial, because |
|
||||||
* "abc" and "ABC" compare as equal even though "abc".equals("ABC") returns |
|
||||||
* false. |
|
||||||
* <P> |
|
||||||
* In general, Comparators should be Serializable, because when they are passed |
|
||||||
* to Serializable data structures such as SortedMap or SortedSet, the entire |
|
||||||
* data structure will only serialize correctly if the comparator is |
|
||||||
* Serializable. |
|
||||||
*/ |
|
||||||
public interface Comparator { |
|
||||||
|
|
||||||
/** |
|
||||||
* Return an integer that is negative, zero or positive depending on whether |
|
||||||
* the first argument is less than, equal to or greater than the second |
|
||||||
* according to this ordering. This method should obey the following contract: |
|
||||||
* <UL> |
|
||||||
* <LI>if compare(a, b) < 0 then compare(b, a) > 0</LI> |
|
||||||
* <LI>if compare(a, b) throws an exception, so does compare(b, a)</LI> |
|
||||||
* <LI>if compare(a, b) < 0 and compare(b, c) < 0 then compare(a, c) |
|
||||||
* < 0</LI> |
|
||||||
* <LI>if a.equals(b) or both a and b are null, then compare(a, b) == 0. |
|
||||||
* The converse need not be true, but if it is, this Comparator |
|
||||||
* specifies a <EM>total</EM> ordering.</LI> |
|
||||||
* </UL> |
|
||||||
* |
|
||||||
* @throws ClassCastException if the elements are not of types that can be |
|
||||||
* compared by this ordering. |
|
||||||
*/ |
|
||||||
int compare(Object o1, Object o2); |
|
||||||
} |
|
@ -1,53 +0,0 @@ |
|||||||
// This interface is taken from the Classpath project.
|
|
||||||
// Please note the different copyright holder!
|
|
||||||
// The changes I did is this comment, the package line, some
|
|
||||||
// imports from java.util and some minor jdk12 -> jdk11 fixes.
|
|
||||||
// -- Jochen Hoenicke <jochen@gnu.org>
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
// ConcurrentModificationException.java -- Data structure concurrently modified
|
|
||||||
//
|
|
||||||
// Copyright (c) 1998 by Stuart Ballard (stuart.ballard@mcmail.com)
|
|
||||||
//
|
|
||||||
// This program is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Library General Public License as published
|
|
||||||
// by the Free Software Foundation, version 2. (see COPYING.LIB)
|
|
||||||
//
|
|
||||||
// This program 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 Library General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Library General Public License
|
|
||||||
// along with this program; if not, write to the Free Software Foundation
|
|
||||||
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
package jode.util; |
|
||||||
|
|
||||||
/** |
|
||||||
* Exception that is thrown by the collections classes when it is detected that |
|
||||||
* a modification has been made to a data structure when this is not allowed, |
|
||||||
* such as when a collection is structurally modified while an Iterator is |
|
||||||
* operating over it. In cases where this can be detected, a |
|
||||||
* ConcurrentModificationException will be thrown. An Iterator that detects this |
|
||||||
* condition is referred to as fail-fast. |
|
||||||
*/ |
|
||||||
public class ConcurrentModificationException extends RuntimeException { |
|
||||||
|
|
||||||
/** |
|
||||||
* Constructs a ConcurrentModificationException with no detail message. |
|
||||||
*/ |
|
||||||
public ConcurrentModificationException() { |
|
||||||
super(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Constructs a ConcurrentModificationException with a detail message. |
|
||||||
* |
|
||||||
* @param detail the detail message for the exception |
|
||||||
*/ |
|
||||||
public ConcurrentModificationException(String detail) { |
|
||||||
super(detail); |
|
||||||
} |
|
||||||
} |
|
@ -1,876 +0,0 @@ |
|||||||
// This class is taken from the Classpath project.
|
|
||||||
// Please note the different copyright holder!
|
|
||||||
// The changes I did is this comment, the package line, some
|
|
||||||
// imports from java.util and some minor jdk12 -> jdk11 fixes.
|
|
||||||
// -- Jochen Hoenicke <jochen@gnu.org>
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
// HashMap.java -- a class providing a basic hashtable data structure,
|
|
||||||
// mapping Object --> Object; part of the JDK1.2 collections
|
|
||||||
// API
|
|
||||||
//
|
|
||||||
// This is a JDK 1.2 compliant version of HashMap.java
|
|
||||||
//
|
|
||||||
// Copyright (c) 1998 by Jon A. Zeppieri (jon@eease.com),
|
|
||||||
// Free Software Foundation, Inc.
|
|
||||||
//
|
|
||||||
// This program is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Library General Public License as published
|
|
||||||
// by the Free Software Foundation, version 2. (see COPYING.LIB)
|
|
||||||
//
|
|
||||||
// This program 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 Library General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Library General Public License
|
|
||||||
// along with this program; if not, write to the Free Software Foundation
|
|
||||||
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
package jode.util; |
|
||||||
import java.util.NoSuchElementException; |
|
||||||
|
|
||||||
import java.io.IOException; |
|
||||||
import java.io.Serializable; |
|
||||||
import java.io.ObjectInputStream; |
|
||||||
import java.io.ObjectOutputStream; |
|
||||||
|
|
||||||
/** |
|
||||||
* This class provides a hashtable-backed implementation of the |
|
||||||
* Map interface. |
|
||||||
* |
|
||||||
* It uses a hash-bucket approach; that is, hash |
|
||||||
* collisions are handled by linking the new node off of the |
|
||||||
* pre-existing node (or list of nodes). In this manner, techniques |
|
||||||
* such as linear probing (which can casue primary clustering) and |
|
||||||
* rehashing (which does not fit very well with Java's method of |
|
||||||
* precomputing hash codes) are avoided. |
|
||||||
* |
|
||||||
* Under ideal circumstances (no collisions, HashMap offers O(1) |
|
||||||
* performance on most operations (<pre>containsValue()</pre> is, |
|
||||||
* of course, O(n)). In the worst case (all keys map to the same |
|
||||||
* hash code -- very unlikely), most operations are O(n). |
|
||||||
* |
|
||||||
* HashMap is part of the JDK1.2 Collections API. It differs from |
|
||||||
* Hashtable in that it accepts the null key and null values, and it |
|
||||||
* does not support "Enumeration views." |
|
||||||
* |
|
||||||
* @author Jon Zeppieri |
|
||||||
* @version $Revision$ |
|
||||||
* @modified $Id$ |
|
||||||
*/ |
|
||||||
public class HashMap extends AbstractMap |
|
||||||
implements Map, Cloneable, Serializable |
|
||||||
{ |
|
||||||
// STATIC (CLASS) VARIABLES ------------------------------------------
|
|
||||||
|
|
||||||
/** |
|
||||||
* the default capacity for an instance of HashMap -- I think this |
|
||||||
* is low, and perhaps it shoudl be raised; Sun's documentation mildly |
|
||||||
* suggests that this (11) is the correct value, though |
|
||||||
*/ |
|
||||||
private static final int DEFAULT_CAPACITY = 11; |
|
||||||
|
|
||||||
/** the default load factor of a HashMap */ |
|
||||||
private static final float DEFAULT_LOAD_FACTOR = 0.75F; |
|
||||||
|
|
||||||
/** used internally to represent the null key */ |
|
||||||
private static final HashMap.Null NULL_KEY = new HashMap.Null(); |
|
||||||
|
|
||||||
/** used internally to parameterize the creation of set/collection views */ |
|
||||||
private static final int KEYS = 0; |
|
||||||
|
|
||||||
/** used internally to parameterize the creation of set/collection views */ |
|
||||||
private static final int VALUES = 1; |
|
||||||
|
|
||||||
/** used internally to parameterize the creation of set/collection views */ |
|
||||||
private static final int ENTRIES = 2; |
|
||||||
|
|
||||||
private static final long serialVersionUID = 362498820763181265L; |
|
||||||
|
|
||||||
// INSTANCE VARIABLES -------------------------------------------------
|
|
||||||
|
|
||||||
/** the capacity of this HashMap: denotes the size of the bucket array */ |
|
||||||
transient int capacity; |
|
||||||
|
|
||||||
/** the size of this HashMap: denotes the number of key-value pairs */ |
|
||||||
private transient int size; |
|
||||||
|
|
||||||
/** the load factor of this HashMap: used in computing the threshold |
|
||||||
* @serial |
|
||||||
*/ |
|
||||||
float loadFactor; |
|
||||||
|
|
||||||
/* the rounded product of the capacity and the load factor; when the number of |
|
||||||
* elements exceeds the threshold, the HashMap calls <pre>rehash()</pre> |
|
||||||
* @serial |
|
||||||
*/ |
|
||||||
private int threshold; |
|
||||||
|
|
||||||
/** |
|
||||||
* this data structure contains the actual key-value mappings; a |
|
||||||
* <pre>BucketList</pre> is a lightweight linked list of "Buckets", |
|
||||||
* which, in turn, are linked nodes containing a key-value mapping |
|
||||||
* and a reference to the "next" Bucket in the list |
|
||||||
*/ |
|
||||||
private transient Bucket[] buckets; |
|
||||||
|
|
||||||
/** |
|
||||||
* counts the number of modifications this HashMap has undergone; used by Iterators |
|
||||||
* to know when to throw ConcurrentModificationExceptions (idea ripped-off from |
|
||||||
* Stuart Ballard's AbstractList implementation) |
|
||||||
*/ |
|
||||||
private transient int modCount; |
|
||||||
|
|
||||||
|
|
||||||
// CONSTRUCTORS ---------------------------------------------------------
|
|
||||||
|
|
||||||
/** |
|
||||||
* construct a new HashMap with the default capacity and the default |
|
||||||
* load factor |
|
||||||
*/ |
|
||||||
public HashMap() |
|
||||||
{ |
|
||||||
init(DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* construct a new HashMap with a specific inital capacity and load factor |
|
||||||
* |
|
||||||
* @param initialCapacity the initial capacity of this HashMap (>=0) |
|
||||||
* @param initialLoadFactor the load factor of this HashMap |
|
||||||
* (a misnomer, really, since the load factor of |
|
||||||
* a HashMap does not change) |
|
||||||
* |
|
||||||
* @throws IllegalArgumentException if (initialCapacity < 0) || |
|
||||||
* (initialLoadFactor > 1.0) || |
|
||||||
* (initialLoadFactor <= 0.0) |
|
||||||
*/ |
|
||||||
public HashMap(int initialCapacity, float initialLoadFactor) |
|
||||||
throws IllegalArgumentException |
|
||||||
{ |
|
||||||
if (initialCapacity < 0 || initialLoadFactor <= 0 || initialLoadFactor > 1) |
|
||||||
throw new IllegalArgumentException(); |
|
||||||
else |
|
||||||
init(initialCapacity, initialLoadFactor); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* construct a new HashMap with a specific inital capacity |
|
||||||
* |
|
||||||
* @param initialCapacity the initial capacity of this HashMap (>=0) |
|
||||||
* |
|
||||||
* @throws IllegalArgumentException if (initialCapacity < 0) |
|
||||||
*/ |
|
||||||
public HashMap(int initialCapacity) |
|
||||||
throws IllegalArgumentException |
|
||||||
{ |
|
||||||
if (initialCapacity < 0) |
|
||||||
throw new IllegalArgumentException(); |
|
||||||
else |
|
||||||
init(initialCapacity, DEFAULT_LOAD_FACTOR); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* construct a new HashMap from the given Map |
|
||||||
* |
|
||||||
* every element in Map t will be put into this new HashMap |
|
||||||
* |
|
||||||
* @param t a Map whose key / value pairs will be put into |
|
||||||
* the new HashMap. <b>NOTE: key / value pairs |
|
||||||
* are not cloned in this constructor</b> |
|
||||||
*/ |
|
||||||
public HashMap(Map t) |
|
||||||
{ |
|
||||||
int mapSize = t.size() * 2; |
|
||||||
init(((mapSize > DEFAULT_CAPACITY) ? mapSize : DEFAULT_CAPACITY), DEFAULT_LOAD_FACTOR); |
|
||||||
putAll(t); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
// PUBLIC METHODS ---------------------------------------------------------
|
|
||||||
|
|
||||||
/** returns the number of kay-value mappings currently in this Map */ |
|
||||||
public int size() |
|
||||||
{ |
|
||||||
return size; |
|
||||||
} |
|
||||||
|
|
||||||
/** returns true if there are no key-value mappings currently in this Map */ |
|
||||||
public boolean isEmpty() |
|
||||||
{ |
|
||||||
return size == 0; |
|
||||||
} |
|
||||||
|
|
||||||
/** empties this HashMap of all elements */ |
|
||||||
public void clear() |
|
||||||
{ |
|
||||||
size = 0; |
|
||||||
modCount++; |
|
||||||
buckets = new Bucket[capacity]; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* returns a shallow clone of this HashMap (i.e. the Map itself is cloned, but |
|
||||||
* its contents are not) |
|
||||||
*/ |
|
||||||
public Object clone() |
|
||||||
{ |
|
||||||
Map.Entry entry; |
|
||||||
Iterator it = entrySet().iterator(); |
|
||||||
HashMap clone = new HashMap(capacity, loadFactor); |
|
||||||
while (it.hasNext()) |
|
||||||
{ |
|
||||||
entry = (Map.Entry) it.next(); |
|
||||||
clone.internalPut(entry.getKey(), entry.getValue()); |
|
||||||
} |
|
||||||
return clone; |
|
||||||
} |
|
||||||
|
|
||||||
/** returns a "set view" of this HashMap's keys */ |
|
||||||
public Set keySet() |
|
||||||
{ |
|
||||||
return new HashMapSet(KEYS); |
|
||||||
} |
|
||||||
|
|
||||||
/** returns a "set view" of this HashMap's entries */ |
|
||||||
public Set entrySet() |
|
||||||
{ |
|
||||||
return new HashMapSet(ENTRIES); |
|
||||||
} |
|
||||||
|
|
||||||
/** returns a "collection view" (or "bag view") of this HashMap's values */ |
|
||||||
public Collection values() |
|
||||||
{ |
|
||||||
return new HashMapCollection(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* returns true if the supplied object equals (<pre>equals()</pre>) a key |
|
||||||
* in this HashMap |
|
||||||
* |
|
||||||
* @param key the key to search for in this HashMap |
|
||||||
*/ |
|
||||||
public boolean containsKey(Object key) |
|
||||||
{ |
|
||||||
return (internalGet(key) != null); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* returns true if this HashMap contains a value <pre>o</pre>, such that |
|
||||||
* <pre>o.equals(value)</pre>. |
|
||||||
* |
|
||||||
* @param value the value to search for in this Hashtable |
|
||||||
*/ |
|
||||||
public boolean containsValue(Object value) |
|
||||||
{ |
|
||||||
int i; |
|
||||||
Bucket list; |
|
||||||
|
|
||||||
for (i = 0; i < capacity; i++) |
|
||||||
{ |
|
||||||
list = buckets[i]; |
|
||||||
if (list != null && list.containsValue(value)) |
|
||||||
return true; |
|
||||||
} |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
/* |
|
||||||
* return the value in this Hashtable associated with the supplied key, or <pre>null</pre> |
|
||||||
* if the key maps to nothing |
|
||||||
* |
|
||||||
* @param key the key for which to fetch an associated value |
|
||||||
*/ |
|
||||||
public Object get(Object key) |
|
||||||
{ |
|
||||||
Map.Entry oResult = internalGet(key); |
|
||||||
return (oResult == null) ? null : oResult.getValue(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* puts the supplied value into the Map, mapped by the supplied key |
|
||||||
* |
|
||||||
* @param key the HashMap key used to locate the value |
|
||||||
* @param value the value to be stored in the HashMap |
|
||||||
*/ |
|
||||||
public Object put(Object key, Object value) |
|
||||||
{ |
|
||||||
return internalPut(key, value); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* part of the Map interface; for each Map.Entry in t, the key / value pair is |
|
||||||
* added to this Map, <b>using the <pre>put()</pre> method -- this may not be |
|
||||||
* you want, so be warned (if you override the put() method, this could lead to |
|
||||||
* off behavior)</b> |
|
||||||
* |
|
||||||
* @param t a Map whose key / value pairs will be added to this Hashtable |
|
||||||
*/ |
|
||||||
public void putAll(Map t) |
|
||||||
{ |
|
||||||
Map.Entry entry; |
|
||||||
Iterator it = t.entrySet().iterator(); |
|
||||||
while (it.hasNext()) |
|
||||||
{ |
|
||||||
entry = (Map.Entry) it.next(); |
|
||||||
put(entry.getKey(), entry.getValue()); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* removes from the HashMap and returns the value which is mapped by the |
|
||||||
* supplied key; if the key maps to nothing, then the HashMap remains unchanged, |
|
||||||
* and <pre>null</pre> is returned |
|
||||||
* |
|
||||||
* @param key the key used to locate the value to remove from the HashMap |
|
||||||
*/ |
|
||||||
public Object remove(Object key) |
|
||||||
{ |
|
||||||
Bucket list; |
|
||||||
int index; |
|
||||||
Object result = null; |
|
||||||
if (size > 0) |
|
||||||
{ |
|
||||||
index = hash(((key == null) ? NULL_KEY : key)); |
|
||||||
list = buckets[index]; |
|
||||||
if (list != null) |
|
||||||
{ |
|
||||||
result = list.removeByKey(key); |
|
||||||
if (result != null) |
|
||||||
{ |
|
||||||
size--; |
|
||||||
modCount++; |
|
||||||
if (list.first == null) |
|
||||||
buckets[index] = null; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
return result; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
// PRIVATE METHODS -----------------------------------------------------------
|
|
||||||
|
|
||||||
/** |
|
||||||
* puts the given key-value pair into this HashMap; a private method is used |
|
||||||
* because it is called by the rehash() method as well as the put() method, |
|
||||||
* and if a subclass overrides put(), then rehash would do funky things |
|
||||||
* if it called put() |
|
||||||
* |
|
||||||
* @param key the HashMap key used to locate the value |
|
||||||
* @param value the value to be stored in the HashMap |
|
||||||
*/ |
|
||||||
private Object internalPut(Object key, Object value) |
|
||||||
{ |
|
||||||
HashMapEntry entry; |
|
||||||
Bucket list; |
|
||||||
int hashIndex; |
|
||||||
Object oResult; |
|
||||||
Object oRealKey = ((key == null) ? NULL_KEY : key); |
|
||||||
|
|
||||||
modCount++; |
|
||||||
if (size == threshold) |
|
||||||
rehash(); |
|
||||||
entry = new HashMapEntry(oRealKey, value); |
|
||||||
hashIndex = hash(oRealKey); |
|
||||||
list = buckets[hashIndex]; |
|
||||||
if (list == null) |
|
||||||
{ |
|
||||||
list = new Bucket(); |
|
||||||
buckets[hashIndex] = list; |
|
||||||
} |
|
||||||
oResult = list.add(entry); |
|
||||||
if (oResult == null) |
|
||||||
{ |
|
||||||
size++; |
|
||||||
return null; |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
return ((Map.Entry) oResult).getValue(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* a private method, called by all of the constructors to initialize a new HashMap |
|
||||||
* |
|
||||||
* @param initialCapacity the initial capacity of this HashMap (>=0) |
|
||||||
* @param initialLoadFactor the load factor of this HashMap |
|
||||||
* (a misnomer, really, since the load factor of |
|
||||||
* a HashMap does not change) |
|
||||||
*/ |
|
||||||
private void init(int initialCapacity, float initialLoadFactor) |
|
||||||
{ |
|
||||||
size = 0; |
|
||||||
modCount = 0; |
|
||||||
capacity = initialCapacity; |
|
||||||
loadFactor = initialLoadFactor; |
|
||||||
threshold = (int) ((float) capacity * loadFactor); |
|
||||||
buckets = new Bucket[capacity]; |
|
||||||
} |
|
||||||
|
|
||||||
/** private -- simply hashes a non-null Object to its array index */ |
|
||||||
private int hash(Object key) |
|
||||||
{ |
|
||||||
return Math.abs(key.hashCode() % capacity); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* increases the size of the HashMap and rehashes all keys to new array indices; |
|
||||||
* this is called when the addition of a new value would cause size() > threshold |
|
||||||
*/ |
|
||||||
private void rehash() |
|
||||||
{ |
|
||||||
int i; |
|
||||||
Bucket[] data = buckets; |
|
||||||
Bucket.Node node; |
|
||||||
|
|
||||||
modCount++; |
|
||||||
capacity = (capacity * 2) + 1; |
|
||||||
size = 0; |
|
||||||
threshold = (int) ((float) capacity * loadFactor); |
|
||||||
buckets = new Bucket[capacity]; |
|
||||||
for (i = 0; i < data.length; i++) |
|
||||||
{ |
|
||||||
if (data[i] != null) |
|
||||||
{ |
|
||||||
node = data[i].first; |
|
||||||
while (node != null) |
|
||||||
{ |
|
||||||
internalPut(node.getKey(), node.getValue()); |
|
||||||
node = node.next; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* a private method which does the "dirty work" (or some of it anyway) of fetching a value |
|
||||||
* with a key |
|
||||||
* |
|
||||||
* @param key the key for which to fetch an associated value |
|
||||||
*/ |
|
||||||
private Map.Entry internalGet(Object key) |
|
||||||
{ |
|
||||||
Bucket list; |
|
||||||
if (size == 0) |
|
||||||
{ |
|
||||||
return null; |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
list = buckets[hash(((key == null) ? NULL_KEY : key))]; |
|
||||||
return (list == null) ? null : list.getEntryByKey(key); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* a private method used by inner class HashMapSet to implement its own |
|
||||||
* <pre>contains(Map.Entry)</pre> method; returns true if the supplied |
|
||||||
* key / value pair is found in this HashMap (again, using <pre>equals()</pre>, |
|
||||||
* rather than <pre>==</pre>) |
|
||||||
* |
|
||||||
* @param entry a Map.Entry to match against key / value pairs in |
|
||||||
* this HashMap |
|
||||||
*/ |
|
||||||
private boolean containsEntry(Map.Entry entry) |
|
||||||
{ |
|
||||||
Map.Entry oInternalEntry; |
|
||||||
if (entry == null) |
|
||||||
{ |
|
||||||
return false; |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
oInternalEntry = internalGet(entry.getKey()); |
|
||||||
return (oInternalEntry != null && oInternalEntry.equals(entry)); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Serializes this object to the given stream. |
|
||||||
* @serialdata the <i>capacity</i>(int) that is the length of the |
|
||||||
* bucket array, the <i>size</i>(int) of the hash map are emitted |
|
||||||
* first. They are followed by size entries, each consisting of |
|
||||||
* a key (Object) and a value (Object). |
|
||||||
*/ |
|
||||||
private void writeObject(ObjectOutputStream s) |
|
||||||
throws IOException |
|
||||||
{ |
|
||||||
// the fields
|
|
||||||
s.defaultWriteObject(); |
|
||||||
|
|
||||||
s.writeInt(capacity); |
|
||||||
s.writeInt(size); |
|
||||||
Iterator it = entrySet().iterator(); |
|
||||||
while (it.hasNext()) |
|
||||||
{ |
|
||||||
Map.Entry oEntry = (Map.Entry) it.next(); |
|
||||||
s.writeObject(oEntry.getKey()); |
|
||||||
s.writeObject(oEntry.getValue()); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Deserializes this object from the given stream. |
|
||||||
* @serialdata the <i>capacity</i>(int) that is the length of the |
|
||||||
* bucket array, the <i>size</i>(int) of the hash map are emitted |
|
||||||
* first. They are followed by size entries, each consisting of |
|
||||||
* a key (Object) and a value (Object). |
|
||||||
*/ |
|
||||||
private void readObject(ObjectInputStream s) |
|
||||||
throws IOException, ClassNotFoundException |
|
||||||
{ |
|
||||||
// the fields
|
|
||||||
s.defaultReadObject(); |
|
||||||
|
|
||||||
capacity = s.readInt(); |
|
||||||
int iLen = s.readInt(); |
|
||||||
size = 0; |
|
||||||
modCount = 0; |
|
||||||
buckets = new Bucket[capacity]; |
|
||||||
|
|
||||||
for (int i = 0; i < iLen; i++) |
|
||||||
{ |
|
||||||
Object oKey = s.readObject(); |
|
||||||
Object oValue = s.readObject(); |
|
||||||
internalPut(oKey, oValue); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// INNER CLASSES -------------------------------------------------------------
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/** |
|
||||||
* an inner class providing a Set view of a HashMap; this implementation is |
|
||||||
* parameterized to view either a Set of keys or a Set of Map.Entry objects |
|
||||||
* |
|
||||||
* Note: a lot of these methods are implemented by AbstractSet, and would work |
|
||||||
* just fine without any meddling, but far greater efficiency can be gained by |
|
||||||
* overriding a number of them. And so I did. |
|
||||||
* |
|
||||||
* @author Jon Zeppieri |
|
||||||
* @version $Revision$ |
|
||||||
* @modified $Id$ |
|
||||||
*/ |
|
||||||
private class HashMapSet extends AbstractSet |
|
||||||
implements Set |
|
||||||
{ |
|
||||||
/** the type of this Set view: KEYS or ENTRIES */ |
|
||||||
private int setType; |
|
||||||
|
|
||||||
/** construct a new HashtableSet with the supplied view type */ |
|
||||||
HashMapSet(int type) |
|
||||||
{ |
|
||||||
setType = type; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* adding an element is unsupported; this method simply throws an exception |
|
||||||
* |
|
||||||
* @throws UnsupportedOperationException |
|
||||||
*/ |
|
||||||
public boolean add(Object o) throws UnsupportedOperationException |
|
||||||
{ |
|
||||||
throw new UnsupportedOperationException(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* adding an element is unsupported; this method simply throws an exception |
|
||||||
* |
|
||||||
* @throws UnsupportedOperationException |
|
||||||
*/ |
|
||||||
public boolean addAll(Collection c) throws UnsupportedOperationException |
|
||||||
{ |
|
||||||
throw new UnsupportedOperationException(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* clears the backing HashMap; this is a prime example of an overridden implementation |
|
||||||
* which is far more efficient than its superclass implementation (which uses an iterator |
|
||||||
* and is O(n) -- this is an O(1) call) |
|
||||||
*/ |
|
||||||
public void clear() |
|
||||||
{ |
|
||||||
HashMap.this.clear(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* returns true if the supplied object is contained by this Set |
|
||||||
* |
|
||||||
* @param o an Object being testing to see if it is in this Set |
|
||||||
*/ |
|
||||||
public boolean contains(Object o) |
|
||||||
{ |
|
||||||
if (setType == KEYS) |
|
||||||
return HashMap.this.containsKey(o); |
|
||||||
else |
|
||||||
return (o instanceof Map.Entry) ? HashMap.this.containsEntry((Map.Entry) o) : false; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* returns true if the backing HashMap is empty (which is the only case either a KEYS |
|
||||||
* Set or an ENTRIES Set would be empty) |
|
||||||
*/ |
|
||||||
public boolean isEmpty() |
|
||||||
{ |
|
||||||
return HashMap.this.isEmpty(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* removes the supplied Object from the Set |
|
||||||
* |
|
||||||
* @param o the Object to be removed |
|
||||||
*/ |
|
||||||
public boolean remove(Object o) |
|
||||||
{ |
|
||||||
if (setType == KEYS) |
|
||||||
return (HashMap.this.remove(o) != null); |
|
||||||
else |
|
||||||
return (o instanceof Map.Entry) ? |
|
||||||
(HashMap.this.remove(((Map.Entry) o).getKey()) != null) : false; |
|
||||||
} |
|
||||||
|
|
||||||
/** returns the size of this Set (always equal to the size of the backing Hashtable) */ |
|
||||||
public int size() |
|
||||||
{ |
|
||||||
return HashMap.this.size(); |
|
||||||
} |
|
||||||
|
|
||||||
/** returns an Iterator over the elements of this Set */ |
|
||||||
public Iterator iterator() |
|
||||||
{ |
|
||||||
return new HashMapIterator(setType); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Like the above Set view, except this one if for values, which are not |
|
||||||
* guaranteed to be unique in a Map; this prvides a Bag of values |
|
||||||
* in the HashMap |
|
||||||
* |
|
||||||
* @author Jon Zeppieri |
|
||||||
* @version $Revision$ |
|
||||||
* @modified $Id$ |
|
||||||
*/ |
|
||||||
private class HashMapCollection extends AbstractCollection |
|
||||||
implements Collection |
|
||||||
{ |
|
||||||
/** a trivial contructor for HashMapCollection */ |
|
||||||
HashMapCollection() |
|
||||||
{ |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* adding elements is not supported by this Collection; |
|
||||||
* this method merely throws an exception |
|
||||||
* |
|
||||||
* @throws UnsupportedOperationException |
|
||||||
*/ |
|
||||||
public boolean add(Object o) throws UnsupportedOperationException |
|
||||||
{ |
|
||||||
throw new UnsupportedOperationException(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* adding elements is not supported by this Collection; |
|
||||||
* this method merely throws an exception |
|
||||||
* |
|
||||||
* @throws UnsupportedOperationException |
|
||||||
*/ |
|
||||||
public boolean addAll(Collection c) throws UnsupportedOperationException |
|
||||||
{ |
|
||||||
throw new UnsupportedOperationException(); |
|
||||||
} |
|
||||||
|
|
||||||
/** removes all elements from this Collection (and from the backing HashMap) */ |
|
||||||
public void clear() |
|
||||||
{ |
|
||||||
HashMap.this.clear(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* returns true if this Collection contains at least one Object which equals() the |
|
||||||
* supplied Object |
|
||||||
* |
|
||||||
* @param o the Object to compare against those in the Set |
|
||||||
*/ |
|
||||||
public boolean contains(Object o) |
|
||||||
{ |
|
||||||
return HashMap.this.containsValue(o); |
|
||||||
} |
|
||||||
|
|
||||||
/** returns true IFF the Collection has no elements */ |
|
||||||
public boolean isEmpty() |
|
||||||
{ |
|
||||||
return HashMap.this.isEmpty(); |
|
||||||
} |
|
||||||
|
|
||||||
/** returns the size of this Collection */ |
|
||||||
public int size() |
|
||||||
{ |
|
||||||
return HashMap.this.size(); |
|
||||||
} |
|
||||||
|
|
||||||
/** returns an Iterator over the elements in this Collection */ |
|
||||||
public Iterator iterator() |
|
||||||
{ |
|
||||||
return new HashMapIterator(VALUES); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* a class which implements the Iterator interface and is used for |
|
||||||
* iterating over HashMaps; |
|
||||||
* this implementation is parameterized to give a sequential view of |
|
||||||
* keys, values, or entries; it also allows the removal of elements, |
|
||||||
* as per the Javasoft spec. |
|
||||||
* |
|
||||||
* @author Jon Zeppieri |
|
||||||
* @version $Revision$ |
|
||||||
* @modified $Id$ |
|
||||||
*/ |
|
||||||
class HashMapIterator implements Iterator |
|
||||||
{ |
|
||||||
/** the type of this Iterator: KEYS, VALUES, or ENTRIES */ |
|
||||||
private int myType; |
|
||||||
/** |
|
||||||
* the number of modifications to the backing Hashtable for which |
|
||||||
* this Iterator can account (idea ripped off from Stuart Ballard) |
|
||||||
*/ |
|
||||||
private int knownMods; |
|
||||||
/** the location of our sequential "cursor" */ |
|
||||||
private int position; |
|
||||||
/** the current index of the BucketList array */ |
|
||||||
private int bucketIndex; |
|
||||||
/** a reference, originally null, to the specific Bucket our "cursor" is pointing to */ |
|
||||||
private Bucket.Node currentNode; |
|
||||||
/** a reference to the current key -- used fro removing elements via the Iterator */ |
|
||||||
private Object currentKey; |
|
||||||
|
|
||||||
/** construct a new HashtableIterator with the supllied type: KEYS, VALUES, or ENTRIES */ |
|
||||||
HashMapIterator(int type) |
|
||||||
{ |
|
||||||
myType = type; |
|
||||||
knownMods = HashMap.this.modCount; |
|
||||||
position = 0; |
|
||||||
bucketIndex = -1; |
|
||||||
currentNode = null; |
|
||||||
currentKey = null; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Stuart Ballard's code: if the backing HashMap has been altered through anything |
|
||||||
* but <i>this</i> Iterator's <pre>remove()</pre> method, we will give up right here, |
|
||||||
* rather than risking undefined behavior |
|
||||||
* |
|
||||||
* @throws ConcurrentModificationException |
|
||||||
*/ |
|
||||||
private void checkMod() |
|
||||||
{ |
|
||||||
if (knownMods != HashMap.this.modCount) |
|
||||||
throw new ConcurrentModificationException(); |
|
||||||
} |
|
||||||
|
|
||||||
/** returns true if the Iterator has more elements */ |
|
||||||
public boolean hasNext() |
|
||||||
{ |
|
||||||
checkMod(); |
|
||||||
return position < HashMap.this.size(); |
|
||||||
} |
|
||||||
|
|
||||||
/** returns the next element in the Iterator's sequential view */ |
|
||||||
public Object next() |
|
||||||
{ |
|
||||||
Bucket list = null; |
|
||||||
Object result; |
|
||||||
checkMod(); |
|
||||||
try |
|
||||||
{ |
|
||||||
while (currentNode == null) |
|
||||||
{ |
|
||||||
while (list == null) |
|
||||||
list = HashMap.this.buckets[++bucketIndex]; |
|
||||||
currentNode = list.first; |
|
||||||
} |
|
||||||
currentKey = currentNode.getKey(); |
|
||||||
result = (myType == KEYS) ? currentKey : |
|
||||||
((myType == VALUES) ? currentNode.getValue() : currentNode); |
|
||||||
currentNode = currentNode.next; |
|
||||||
} |
|
||||||
catch(Exception e) |
|
||||||
{ |
|
||||||
throw new NoSuchElementException(); |
|
||||||
} |
|
||||||
position++; |
|
||||||
return result; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* removes from the backing HashMap the last element which was fetched with the |
|
||||||
* <pre>next()</pre> method |
|
||||||
*/ |
|
||||||
public void remove() |
|
||||||
{ |
|
||||||
checkMod(); |
|
||||||
if (currentKey == null) |
|
||||||
{ |
|
||||||
throw new IllegalStateException(); |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
HashMap.this.remove(currentKey); |
|
||||||
knownMods++; |
|
||||||
currentKey = null; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* a singleton instance of this class (HashMap.NULL_KEY) |
|
||||||
* is used to represent the null key in HashMap objects |
|
||||||
* |
|
||||||
* @author Jon Zeppieri |
|
||||||
* @version $Revision$ |
|
||||||
* @modified $Id$ |
|
||||||
*/ |
|
||||||
private static class Null |
|
||||||
{ |
|
||||||
/** trivial constructor */ |
|
||||||
Null() |
|
||||||
{ |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* a HashMap version of Map.Entry -- one thing in this implementation is |
|
||||||
* HashMap-specific: if the key is HashMap.NULL_KEY, getKey() will return |
|
||||||
* null |
|
||||||
* |
|
||||||
* Simply, a key / value pair |
|
||||||
* |
|
||||||
* @author Jon Zeppieri |
|
||||||
* @version $Revision$ |
|
||||||
* @modified $Id$ |
|
||||||
*/ |
|
||||||
private static class HashMapEntry extends Bucket.Node implements Map.Entry |
|
||||||
{ |
|
||||||
/** construct a new HashMapEntry with the given key and value */ |
|
||||||
public HashMapEntry(Object key, Object value) |
|
||||||
{ |
|
||||||
super(key, value); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* if the key == HashMap.NULL_KEY, null is returned, otherwise the actual |
|
||||||
* key is returned |
|
||||||
*/ |
|
||||||
public Object getKey() |
|
||||||
{ |
|
||||||
Object oResult = super.getKey(); |
|
||||||
return (oResult == HashMap.NULL_KEY) ? null : oResult; |
|
||||||
} |
|
||||||
} |
|
||||||
// EOF -----------------------------------------------------------------------
|
|
||||||
} |
|
@ -1,238 +0,0 @@ |
|||||||
// This class is taken from the Classpath project.
|
|
||||||
// Please note the different copyright holder!
|
|
||||||
// The changes I did is this comment, the package line, some
|
|
||||||
// imports from java.util and some minor jdk12 -> jdk11 fixes.
|
|
||||||
// -- Jochen Hoenicke <jochen@gnu.org>
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
// HashSet.java -- a class providing a HashMap-backet Set
|
|
||||||
//
|
|
||||||
// Copyright (c) 1998 by Jon A. Zeppieri (jon@eease.com)
|
|
||||||
//
|
|
||||||
// This program is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Library General Public License as published
|
|
||||||
// by the Free Software Foundation, version 2. (see COPYING.LIB)
|
|
||||||
//
|
|
||||||
// This program 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 Library General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Library General Public License
|
|
||||||
// along with this program; if not, write to the Free Software Foundation
|
|
||||||
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
package jode.util; |
|
||||||
|
|
||||||
import java.io.IOException; |
|
||||||
import java.io.Serializable; |
|
||||||
import java.io.ObjectInputStream; |
|
||||||
import java.io.ObjectOutputStream; |
|
||||||
|
|
||||||
/** |
|
||||||
* This class provides a HashMap-backed implementation of the |
|
||||||
* Set interface. |
|
||||||
* |
|
||||||
* Each element in the Set is a key in the backing HashMap; each key |
|
||||||
* maps to a static token, denoting that the key does, in fact, exist. |
|
||||||
* |
|
||||||
* Most operations are O(1), assuming no hash collisions. In the worst |
|
||||||
* case (where all hases collide), operations are O(n). |
|
||||||
* |
|
||||||
* HashSet is a part of the JDK1.2 Collections API. |
|
||||||
* |
|
||||||
* @author Jon Zeppieri |
|
||||||
* @version $Revision$ |
|
||||||
* @modified $Id$ |
|
||||||
*/ |
|
||||||
public class HashSet extends AbstractSet |
|
||||||
implements Set, Cloneable, Serializable |
|
||||||
{ |
|
||||||
// INSTANCE VARIABLES -------------------------------------------------
|
|
||||||
/** the HashMap which backs this Set */ |
|
||||||
private transient HashMap map; |
|
||||||
static final long serialVersionUID = -5024744406713321676L; |
|
||||||
|
|
||||||
// CONSTRUCTORS ---------------------------------------------------------
|
|
||||||
|
|
||||||
/** |
|
||||||
* construct a new, empty HashSet whose backing HashMap has the default |
|
||||||
* capacity and loadFacor |
|
||||||
*/ |
|
||||||
public HashSet() |
|
||||||
{ |
|
||||||
map = new HashMap(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* construct a new, empty HashSet whose backing HashMap has the supplied |
|
||||||
* capacity and the default load factor |
|
||||||
* |
|
||||||
* @param initialCapacity the initial capacity of the backing |
|
||||||
* HashMap |
|
||||||
*/ |
|
||||||
public HashSet(int initialCapacity) |
|
||||||
{ |
|
||||||
map = new HashMap(initialCapacity); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* construct a new, empty HashSet whose backing HashMap has the supplied |
|
||||||
* capacity and load factor |
|
||||||
* |
|
||||||
* @param initialCapacity the initial capacity of the backing |
|
||||||
* HashMap |
|
||||||
* @param loadFactor the load factor of the backing HashMap |
|
||||||
*/ |
|
||||||
public HashSet(int initialCapacity, float loadFactor) |
|
||||||
{ |
|
||||||
map = new HashMap(initialCapacity, loadFactor); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* construct a new HashSet with the same elements as are in the supplied |
|
||||||
* collection (eliminating any duplicates, of course; the backing HashMap |
|
||||||
* will have the default capacity and load factor |
|
||||||
* |
|
||||||
* @param c a collection containing the elements with |
|
||||||
* which this set will be initialized |
|
||||||
*/ |
|
||||||
public HashSet(Collection c) |
|
||||||
{ |
|
||||||
map = new HashMap(); |
|
||||||
addAll(c); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
// PUBLIC METHODS ---------------------------------------------------------
|
|
||||||
|
|
||||||
/** |
|
||||||
* adds the given Object to the set if it is not already in the Set, |
|
||||||
* returns true if teh element was added, false otherwise |
|
||||||
* |
|
||||||
* @param o the Object to add to this Set |
|
||||||
*/ |
|
||||||
public boolean add(Object o) |
|
||||||
{ |
|
||||||
if (map.containsKey(o)) |
|
||||||
{ |
|
||||||
return false; |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
internalAdd(o); |
|
||||||
return true; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* empties this Set of all elements; this is a fast operation [O(1)] |
|
||||||
*/ |
|
||||||
public void clear() |
|
||||||
{ |
|
||||||
map.clear(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* returns a shallow copy of this Set (the Set itself is cloned; its |
|
||||||
* elements are not) |
|
||||||
*/ |
|
||||||
public Object clone() |
|
||||||
{ |
|
||||||
Iterator it = iterator(); |
|
||||||
HashSet clone = new HashSet(map.capacity, map.loadFactor); |
|
||||||
while (it.hasNext()) |
|
||||||
clone.internalAdd(it.next()); |
|
||||||
return clone; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* returns true if the supplied element is in this Set, false otherwise |
|
||||||
* |
|
||||||
* @param o the Object whose presence in this Set we are testing for |
|
||||||
*/ |
|
||||||
public boolean contains(Object o) |
|
||||||
{ |
|
||||||
return map.containsKey(o); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* returns true if this set has no elements in it (size() == 0) |
|
||||||
*/ |
|
||||||
public boolean isEmpty() |
|
||||||
{ |
|
||||||
return map.isEmpty(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* returns an Iterator over the elements of this Set; the Iterator allows |
|
||||||
* removal of elements |
|
||||||
*/ |
|
||||||
public Iterator iterator() |
|
||||||
{ |
|
||||||
return map.keySet().iterator(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* removes the supplied Object from this Set if it is in the Set; returns |
|
||||||
* true if an element was removed, false otherwise |
|
||||||
*/ |
|
||||||
public boolean remove(Object o) |
|
||||||
{ |
|
||||||
return (map.remove(o) != null); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* returns the number of elements in this Set |
|
||||||
*/ |
|
||||||
public int size() |
|
||||||
{ |
|
||||||
return map.size(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
// PRIVATE METHODS -----------------------------------------------------------
|
|
||||||
|
|
||||||
/** |
|
||||||
* adds the supplied element to this Set; this private method is used |
|
||||||
* internally [clone()] instead of add(), because add() can be overridden |
|
||||||
* to do unexpected things |
|
||||||
* |
|
||||||
* @param o the Object to add to this Set |
|
||||||
*/ |
|
||||||
private void internalAdd(Object o) |
|
||||||
{ |
|
||||||
map.put(o, Boolean.TRUE); |
|
||||||
} |
|
||||||
|
|
||||||
/** Serialize this Object in a manner which is binary-compatible with the JDK */ |
|
||||||
private void writeObject(ObjectOutputStream s) throws IOException |
|
||||||
{ |
|
||||||
Iterator it = iterator(); |
|
||||||
s.writeInt(map.capacity); |
|
||||||
s.writeFloat(map.loadFactor); |
|
||||||
s.writeInt(size()); |
|
||||||
while (it.hasNext()) |
|
||||||
s.writeObject(it.next()); |
|
||||||
} |
|
||||||
|
|
||||||
/** Deserialize this Object in a manner which is binary-compatible with the JDK */ |
|
||||||
private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException |
|
||||||
{ |
|
||||||
int i, iSize, iCapacity; |
|
||||||
float fLoadFactor; |
|
||||||
Object oElement; |
|
||||||
|
|
||||||
iCapacity = s.readInt(); |
|
||||||
fLoadFactor = s.readFloat(); |
|
||||||
iSize = s.readInt(); |
|
||||||
|
|
||||||
map = new HashMap(iCapacity, fLoadFactor); |
|
||||||
|
|
||||||
for (i = 0; i < iSize; i++) |
|
||||||
{ |
|
||||||
oElement = s.readObject(); |
|
||||||
internalAdd(oElement); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,66 +0,0 @@ |
|||||||
// This interface is taken from the Classpath project.
|
|
||||||
// Please note the different copyright holder!
|
|
||||||
// The changes I did is this comment, the package line, some
|
|
||||||
// imports from java.util and some minor jdk12 -> jdk11 fixes.
|
|
||||||
// -- Jochen Hoenicke <jochen@gnu.org>
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Iterator.java -- Interface for iterating over collections
|
|
||||||
//
|
|
||||||
// Copyright (c) 1998 by Stuart Ballard (stuart.ballard@mcmail.com)
|
|
||||||
//
|
|
||||||
// This program is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Library General Public License as published
|
|
||||||
// by the Free Software Foundation, version 2. (see COPYING.LIB)
|
|
||||||
//
|
|
||||||
// This program 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 Library General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Library General Public License
|
|
||||||
// along with this program; if not, write to the Free Software Foundation
|
|
||||||
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
package jode.util; |
|
||||||
|
|
||||||
/** |
|
||||||
* An object which iterates over a collection. An Iterator is used to return the |
|
||||||
* items once only, in sequence, by successive calls to the next method. It is |
|
||||||
* also possible to remove elements from the underlying collection by using the |
|
||||||
* optional remove method. Iterator is intended as a replacement for the |
|
||||||
* Enumeration interface of previous versions of Java, which did not have the |
|
||||||
* remove method and had less conveniently named methods. |
|
||||||
*/ |
|
||||||
public interface Iterator { |
|
||||||
|
|
||||||
/** |
|
||||||
* Tests whether there are elements remaining in the collection. |
|
||||||
* |
|
||||||
* @return true if there is at least one more element in the collection, |
|
||||||
* that is, if the next call to next will not throw NoSuchElementException. |
|
||||||
*/ |
|
||||||
boolean hasNext(); |
|
||||||
|
|
||||||
/** |
|
||||||
* Obtain the next element in the collection. |
|
||||||
* |
|
||||||
* @return the next element in the collection |
|
||||||
* @exception NoSuchElementException if there are no more elements |
|
||||||
*/ |
|
||||||
Object next(); |
|
||||||
|
|
||||||
/** |
|
||||||
* Remove from the underlying collection the last element returned by next. |
|
||||||
* This method can be called only once after each call to next. It does not |
|
||||||
* affect what will be returned by subsequent calls to next. This operation is |
|
||||||
* optional, it may throw an UnsupportedOperationException. |
|
||||||
* |
|
||||||
* @exception IllegalStateException if next has not yet been called or remove |
|
||||||
* has already been called since the last call to next. |
|
||||||
* @exception UnsupportedOperationException if this Iterator does not support |
|
||||||
* the remove operation. |
|
||||||
*/ |
|
||||||
void remove(); |
|
||||||
} |
|
@ -1,581 +0,0 @@ |
|||||||
// This class is taken from the Classpath project.
|
|
||||||
// Please note the different copyright holder!
|
|
||||||
// The changes I did is this comment, the package line, some
|
|
||||||
// imports from java.util and some minor jdk12 -> jdk11 fixes.
|
|
||||||
// -- Jochen Hoenicke <jochen@gnu.org>
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
// LinkedList.java -- Linked list implementation of the List interface
|
|
||||||
//
|
|
||||||
// Copyright (c) 1998 by Stuart Ballard (stuart.ballard@mcmail.com)
|
|
||||||
//
|
|
||||||
// This program is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Library General Public License as published
|
|
||||||
// by the Free Software Foundation, version 2. (see COPYING.LIB)
|
|
||||||
//
|
|
||||||
// This program 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 Library General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Library General Public License
|
|
||||||
// along with this program; if not, write to the Free Software Foundation
|
|
||||||
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
package jode.util; |
|
||||||
import java.util.NoSuchElementException; |
|
||||||
import java.io.Serializable; |
|
||||||
import java.io.ObjectOutputStream; |
|
||||||
import java.io.ObjectInputStream; |
|
||||||
import java.io.IOException; |
|
||||||
|
|
||||||
// TO DO:
|
|
||||||
// ~ Doc comment for the class.
|
|
||||||
// ~ Doc comments for the non-list methods.
|
|
||||||
// ~ Some commenting on the Backing API and other general implementation notes.
|
|
||||||
|
|
||||||
/** |
|
||||||
* Linked list implementation of the List interface. |
|
||||||
*/ |
|
||||||
public class LinkedList extends AbstractSequentialList |
|
||||||
implements Serializable, Cloneable |
|
||||||
{ |
|
||||||
static final long serialVersionUID = 876323262645176354L; |
|
||||||
|
|
||||||
/** |
|
||||||
* An Entry containing the head (in the next field) and the tail (in the |
|
||||||
* previous field) of the list. The data field is null. If the list is empty, |
|
||||||
* both the head and the tail point to ends itself. |
|
||||||
*/ |
|
||||||
transient Entry ends = new Entry(); |
|
||||||
|
|
||||||
/** |
|
||||||
* The current length of the list. |
|
||||||
*/ |
|
||||||
transient int size = 0; |
|
||||||
|
|
||||||
/** |
|
||||||
* Class to represent an entry in the list. Holds a single element. |
|
||||||
*/ |
|
||||||
private static class Entry { |
|
||||||
|
|
||||||
/** |
|
||||||
* The list element. |
|
||||||
*/ |
|
||||||
Object data = null; |
|
||||||
|
|
||||||
/** |
|
||||||
* The next entry in the list. If this is the last entry in the list, the |
|
||||||
* ends field of the list is held here. |
|
||||||
*/ |
|
||||||
Entry next; |
|
||||||
|
|
||||||
/** |
|
||||||
* The previous entry in the list. If this is the first entry in the list, |
|
||||||
* the ends field of the list is held here. |
|
||||||
*/ |
|
||||||
Entry previous; |
|
||||||
|
|
||||||
/** |
|
||||||
* Create an entry with given data and linkage. |
|
||||||
*/ |
|
||||||
Entry(Object d, Entry n, Entry p) { |
|
||||||
data = d; |
|
||||||
next = n; |
|
||||||
previous = p; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Create an entry with no data and linking to itself, for use as the ends |
|
||||||
* field of the list. |
|
||||||
*/ |
|
||||||
Entry() { |
|
||||||
next = previous = this; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Remove this entry. |
|
||||||
*/ |
|
||||||
Object remove() { |
|
||||||
previous.next = next; |
|
||||||
next.previous = previous; |
|
||||||
return data; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private static interface Backing { |
|
||||||
void checkMod(int known); |
|
||||||
void upMod(); |
|
||||||
void incSize(int by); |
|
||||||
void decSize(int by); |
|
||||||
} |
|
||||||
|
|
||||||
private final Backing back = new Backing() { |
|
||||||
public void checkMod(int known) { |
|
||||||
if (known != modCount) { |
|
||||||
throw new ConcurrentModificationException(); |
|
||||||
} |
|
||||||
} |
|
||||||
public void upMod() { |
|
||||||
modCount++; |
|
||||||
} |
|
||||||
public void incSize(int by) { |
|
||||||
size += by; |
|
||||||
} |
|
||||||
public void decSize(int by) { |
|
||||||
size -= by; |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
/** A ListIterator over the list. This class keeps track of its |
|
||||||
* position in the list, the size of the list, and the two list |
|
||||||
* entries it is between. This enables it to be used identically |
|
||||||
* for both the list itself and a sublist of the list. |
|
||||||
*/ |
|
||||||
private static class Iter implements ListIterator { |
|
||||||
|
|
||||||
/** |
|
||||||
* The index of the element that will be returned by next(). |
|
||||||
*/ |
|
||||||
int pos; |
|
||||||
|
|
||||||
/** |
|
||||||
* The size of the backing list. |
|
||||||
*/ |
|
||||||
int size; |
|
||||||
|
|
||||||
/** |
|
||||||
* The entry containing the element that will be returned by next(). |
|
||||||
*/ |
|
||||||
Entry next; |
|
||||||
|
|
||||||
/** |
|
||||||
* The entry containing the element that will be returned by previous(). |
|
||||||
*/ |
|
||||||
Entry previous; |
|
||||||
|
|
||||||
/** |
|
||||||
* The entry that will be affected by remove() or set(). |
|
||||||
*/ |
|
||||||
Entry recent; |
|
||||||
|
|
||||||
/** |
|
||||||
* The known value of the modCount of the backing list. |
|
||||||
*/ |
|
||||||
int knownMod; |
|
||||||
|
|
||||||
private final Backing b; |
|
||||||
|
|
||||||
/** |
|
||||||
* Create a new Iter starting at a given Entry within the list, at a given |
|
||||||
* position, in a list of given size. |
|
||||||
* |
|
||||||
* @param index the index to begin iteration. |
|
||||||
* @exception IndexOutOfBoundsException if index < 0 || index > size. |
|
||||||
*/ |
|
||||||
Iter(Backing backing, Entry n, int index, int s, int mc) { |
|
||||||
b = backing; |
|
||||||
pos = index; |
|
||||||
size = s; |
|
||||||
next = n; |
|
||||||
previous = n.previous; |
|
||||||
knownMod = mc; |
|
||||||
} |
|
||||||
|
|
||||||
public int nextIndex() { |
|
||||||
b.checkMod(knownMod); |
|
||||||
return pos; |
|
||||||
} |
|
||||||
|
|
||||||
public int previousIndex() { |
|
||||||
b.checkMod(knownMod); |
|
||||||
return pos - 1; |
|
||||||
} |
|
||||||
|
|
||||||
public boolean hasNext() { |
|
||||||
b.checkMod(knownMod); |
|
||||||
return pos < size; |
|
||||||
} |
|
||||||
|
|
||||||
public boolean hasPrevious() { |
|
||||||
b.checkMod(knownMod); |
|
||||||
return pos > 0; |
|
||||||
} |
|
||||||
|
|
||||||
public Object next() { |
|
||||||
b.checkMod(knownMod); |
|
||||||
if (pos >= size) { |
|
||||||
throw new NoSuchElementException(); |
|
||||||
} else { |
|
||||||
pos++; |
|
||||||
recent = previous = next; |
|
||||||
next = recent.next; |
|
||||||
return recent.data; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public Object previous() { |
|
||||||
b.checkMod(knownMod); |
|
||||||
if (pos <= 0) { |
|
||||||
throw new NoSuchElementException(); |
|
||||||
} else { |
|
||||||
pos--; |
|
||||||
recent = next = previous; |
|
||||||
previous = recent.previous; |
|
||||||
return recent.data; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public void remove() { |
|
||||||
b.checkMod(knownMod); |
|
||||||
if (recent == null) { |
|
||||||
throw new IllegalStateException(); |
|
||||||
} |
|
||||||
|
|
||||||
// Adjust the position to before the removed element
|
|
||||||
if (recent == previous) pos--; |
|
||||||
|
|
||||||
// Could use recent.remove() but this way is quicker, and also correctly
|
|
||||||
// fixes next and previous.
|
|
||||||
next = recent.previous.next = recent.next; |
|
||||||
previous = recent.next.previous = recent.previous; |
|
||||||
size--; |
|
||||||
b.decSize(1); |
|
||||||
knownMod++; |
|
||||||
b.upMod(); |
|
||||||
recent = null; |
|
||||||
} |
|
||||||
|
|
||||||
public void add(Object o) { |
|
||||||
b.checkMod(knownMod); |
|
||||||
previous.next = next.previous = new Entry(o, next, previous); |
|
||||||
|
|
||||||
// New for 1.2RC1 - the semantics changed so that the iterator is
|
|
||||||
// positioned *after* the new element.
|
|
||||||
previous = next; |
|
||||||
next = previous.next; |
|
||||||
pos++; |
|
||||||
|
|
||||||
size++; |
|
||||||
b.incSize(1); |
|
||||||
knownMod++; |
|
||||||
b.upMod(); |
|
||||||
recent = null; |
|
||||||
} |
|
||||||
|
|
||||||
public void set(Object o) { |
|
||||||
b.checkMod(knownMod); |
|
||||||
if (recent == null) { |
|
||||||
throw new IllegalStateException(); |
|
||||||
} |
|
||||||
recent.data = o; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Obtain the Entry at a given position in a list. This method of course |
|
||||||
* takes linear time, but it is intelligent enough to take the shorter of the |
|
||||||
* paths to get to the Entry required. This implies that the first or last |
|
||||||
* entry in the list is obtained in constant time, which is a very desirable |
|
||||||
* property. |
|
||||||
* For speed and flexibility in which ranges are valid, range checking is not |
|
||||||
* done in this method, and if n is outside the range -1 <= n <= size, the |
|
||||||
* result will be wrong (but no exception will be thrown). |
|
||||||
* Note that you *can* obtain entries at position -1 and size, which are |
|
||||||
* equal to prehead and posttail respectively. |
|
||||||
* This method is static so that it can also be used in subList. |
|
||||||
* |
|
||||||
* @param n the number of the entry to get. |
|
||||||
* @param size the size of the list to get the entry in. |
|
||||||
* @param head the entry before the first element of the list (usually ends). |
|
||||||
* @param tail the entry after the last element of the list (usually ends). |
|
||||||
*/ |
|
||||||
static Entry getEntry(int n, int size, Entry head, Entry tail) { |
|
||||||
|
|
||||||
// n less than size/2, iterate from start
|
|
||||||
if (n < size >> 1) { |
|
||||||
while (n-- >= 0) { |
|
||||||
head = head.next; |
|
||||||
} |
|
||||||
return head; |
|
||||||
|
|
||||||
// n greater than size/2, iterate from end
|
|
||||||
} else { |
|
||||||
while (++n <= size) { |
|
||||||
tail = tail.previous; |
|
||||||
} |
|
||||||
return tail; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Create an empty linked list. |
|
||||||
*/ |
|
||||||
public LinkedList() { |
|
||||||
super(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Create a linked list containing the elements, in order, of a given |
|
||||||
* collection. |
|
||||||
* |
|
||||||
* @param c the collection to populate this list from. |
|
||||||
*/ |
|
||||||
public LinkedList(Collection c) { |
|
||||||
super(); |
|
||||||
// Note: addAll could be made slightly faster, but not enough so to justify
|
|
||||||
// re-implementing it from scratch. It is just a matter of a relatively
|
|
||||||
// small constant factor.
|
|
||||||
addAll(c); |
|
||||||
} |
|
||||||
|
|
||||||
public Object getFirst() { |
|
||||||
if (size == 0) { |
|
||||||
throw new NoSuchElementException(); |
|
||||||
} |
|
||||||
return ends.next.data; |
|
||||||
} |
|
||||||
|
|
||||||
public Object getLast() { |
|
||||||
if (size == 0) { |
|
||||||
throw new NoSuchElementException(); |
|
||||||
} |
|
||||||
return ends.previous.data; |
|
||||||
} |
|
||||||
|
|
||||||
public Object removeFirst() { |
|
||||||
if (size == 0) { |
|
||||||
throw new NoSuchElementException(); |
|
||||||
} |
|
||||||
size--; |
|
||||||
modCount++; |
|
||||||
return ends.next.remove(); |
|
||||||
} |
|
||||||
|
|
||||||
public Object removeLast() { |
|
||||||
if (size == 0) { |
|
||||||
throw new NoSuchElementException(); |
|
||||||
} |
|
||||||
size--; |
|
||||||
modCount++; |
|
||||||
return ends.previous.remove(); |
|
||||||
} |
|
||||||
|
|
||||||
public void addFirst(Object o) { |
|
||||||
ends.next.previous = ends.next = new Entry(o, ends.next, ends); |
|
||||||
size++; |
|
||||||
modCount++; |
|
||||||
} |
|
||||||
|
|
||||||
public void addLast(Object o) { |
|
||||||
ends.previous.next = ends.previous = new Entry(o, ends, ends.previous); |
|
||||||
size++; |
|
||||||
modCount++; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Obtain the number of elements currently in this list. |
|
||||||
* |
|
||||||
* @returns the number of elements currently in this list. |
|
||||||
*/ |
|
||||||
public int size() { |
|
||||||
return size; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Remove a range of elements from this list. |
|
||||||
* |
|
||||||
* @param fromIndex the index, inclusive, to remove from. |
|
||||||
* @param toIndex the index, exclusive, to remove to. |
|
||||||
* @exception IndexOutOfBoundsException if fromIndex > toIndex || fromIndex < |
|
||||||
* 0 || toIndex > size(). |
|
||||||
*/ |
|
||||||
// Note: normally removeRange is provided to allow efficient ways to
|
|
||||||
// implement clear() on subLists. However, in this case clear on subLists
|
|
||||||
// works anyway, so this implementation is included just for completeness
|
|
||||||
// and because subclasses might try to use it.
|
|
||||||
protected void removeRange(int fromIndex, int toIndex) { |
|
||||||
subList(fromIndex, toIndex).clear(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Clear the list. |
|
||||||
*/ |
|
||||||
public void clear() { |
|
||||||
ends.next = ends.previous = ends; |
|
||||||
modCount++; |
|
||||||
size = 0; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Obtain a ListIterator over this list, starting at a given index. The |
|
||||||
* ListIterator returned by this method supports the add, remove and set |
|
||||||
* methods. |
|
||||||
* |
|
||||||
* @param index the index of the element to be returned by the first call to |
|
||||||
* next(), or size() to be initially positioned at the end of the list. |
|
||||||
* @exception IndexOutOfBoundsException if index < 0 || index > size(). |
|
||||||
*/ |
|
||||||
public ListIterator listIterator(int index) { |
|
||||||
|
|
||||||
// Check bounds
|
|
||||||
if (index < 0 || index > size) { |
|
||||||
throw new IndexOutOfBoundsException(); |
|
||||||
} |
|
||||||
|
|
||||||
return new Iter(back, getEntry(index, size, ends, ends), |
|
||||||
index, size, modCount); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Obtain a List view of a subsection of this list, from fromIndex |
|
||||||
* (inclusive) to toIndex (exclusive). The returned list is modifiable in |
|
||||||
* every respect. Changes to the returned list are reflected in this list. If |
|
||||||
* this list is structurally modified is any way other than through the |
|
||||||
* returned list, any subsequent operations on the returned list will result |
|
||||||
* in a ConcurrentModificationException (that is, the returned list is |
|
||||||
* fail-fast). |
|
||||||
* |
|
||||||
* @param fromIndex the index that the returned list should start from |
|
||||||
* (inclusive). |
|
||||||
* @param toIndex the index that the returned list should go to (exclusive). |
|
||||||
* @returns a List backed by a subsection of this list. |
|
||||||
* @exception IndexOutOfBoundsException if fromIndex < 0 || toIndex > size() |
|
||||||
* || fromIndex > toIndex. |
|
||||||
*/ |
|
||||||
public List subList(int fromIndex, int toIndex) { |
|
||||||
|
|
||||||
// Check bounds
|
|
||||||
if (fromIndex > toIndex || fromIndex < 0 || toIndex > size) { |
|
||||||
throw new IndexOutOfBoundsException(); |
|
||||||
} |
|
||||||
|
|
||||||
return new SubLinkedList(back, getEntry(fromIndex - 1, size, ends, ends), |
|
||||||
getEntry(toIndex, size, ends, ends), |
|
||||||
toIndex - fromIndex); |
|
||||||
} |
|
||||||
|
|
||||||
private static class SubLinkedList extends AbstractSequentialList { |
|
||||||
|
|
||||||
Entry head; // entry before the beginning
|
|
||||||
Entry tail; // entry after the end
|
|
||||||
int size; |
|
||||||
private final Backing b; |
|
||||||
|
|
||||||
private final Backing back = new Backing() { |
|
||||||
public void checkMod(int known) { |
|
||||||
if (known != modCount) { |
|
||||||
throw new ConcurrentModificationException(); |
|
||||||
} |
|
||||||
} |
|
||||||
public void upMod() { |
|
||||||
modCount++; |
|
||||||
} |
|
||||||
public void incSize(int by) { |
|
||||||
size += by; |
|
||||||
} |
|
||||||
public void decSize(int by) { |
|
||||||
size -= by; |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
SubLinkedList(Backing backing, Entry h, Entry t, int s) { |
|
||||||
b = backing; |
|
||||||
head = h; |
|
||||||
tail = t; |
|
||||||
size = s; |
|
||||||
} |
|
||||||
|
|
||||||
public int size() { |
|
||||||
b.checkMod(this.modCount); |
|
||||||
return size; |
|
||||||
} |
|
||||||
|
|
||||||
public ListIterator listIterator(int index) { |
|
||||||
b.checkMod(this.modCount); |
|
||||||
|
|
||||||
// Check bounds
|
|
||||||
if (index < 0 || index > size) { |
|
||||||
throw new IndexOutOfBoundsException(); |
|
||||||
} |
|
||||||
|
|
||||||
return new Iter(back, getEntry(index, size, head, tail), |
|
||||||
index, size, modCount); |
|
||||||
} |
|
||||||
|
|
||||||
public void clear() { |
|
||||||
b.checkMod(this.modCount); |
|
||||||
head.next = tail; |
|
||||||
tail.previous = head; |
|
||||||
size = 0; |
|
||||||
b.decSize(size); |
|
||||||
modCount++; |
|
||||||
b.upMod(); |
|
||||||
} |
|
||||||
|
|
||||||
// No removeRange because this class cannot be publically subclassed.
|
|
||||||
|
|
||||||
public List subList(int fromIndex, int toIndex) { |
|
||||||
b.checkMod(this.modCount); |
|
||||||
|
|
||||||
// Check bounds
|
|
||||||
if (fromIndex > toIndex || fromIndex < 0 || toIndex > size) { |
|
||||||
throw new IndexOutOfBoundsException(); |
|
||||||
} |
|
||||||
|
|
||||||
return new SubLinkedList(back, getEntry(fromIndex - 1, size, head, tail), |
|
||||||
getEntry(toIndex, size, head, tail), |
|
||||||
toIndex - fromIndex); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Create a shallow copy of this LinkedList. |
|
||||||
* @return an object of the same class as this object, containing the |
|
||||||
* same elements in the same order. |
|
||||||
*/ |
|
||||||
public Object clone() |
|
||||||
{ |
|
||||||
LinkedList copy; |
|
||||||
try |
|
||||||
{ |
|
||||||
copy = (LinkedList) super.clone(); |
|
||||||
} |
|
||||||
catch (CloneNotSupportedException ex) |
|
||||||
{ |
|
||||||
throw new InternalError(ex.getMessage()); |
|
||||||
} |
|
||||||
copy.size = 0; |
|
||||||
copy.ends = new Entry(); |
|
||||||
copy.addAll(this); |
|
||||||
return copy; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Serialize an object to a stream. |
|
||||||
* @serialdata the size of the list (int), followed by all the elements |
|
||||||
* (Object) in proper order. |
|
||||||
*/ |
|
||||||
private void writeObject(ObjectOutputStream s) |
|
||||||
throws IOException |
|
||||||
{ |
|
||||||
s.writeInt(size); |
|
||||||
for (Iterator i = iterator(); i.hasNext(); ) |
|
||||||
s.writeObject(i.next()); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Deserialize an object from a stream. |
|
||||||
* @serialdata the size of the list (int), followed by all the elements |
|
||||||
* (Object) in proper order. |
|
||||||
*/ |
|
||||||
private void readObject(ObjectInputStream s) |
|
||||||
throws IOException, ClassNotFoundException |
|
||||||
{ |
|
||||||
int serialSize = s.readInt(); |
|
||||||
ends = new Entry(); |
|
||||||
for (int i=0; i< serialSize; i++) |
|
||||||
addLast(s.readObject()); |
|
||||||
} |
|
||||||
} |
|
@ -1,331 +0,0 @@ |
|||||||
// This interface is taken from the Classpath project.
|
|
||||||
// Please note the different copyright holder!
|
|
||||||
// The changes I did is this comment, the package line, some
|
|
||||||
// imports from java.util and some minor jdk12 -> jdk11 fixes.
|
|
||||||
// -- Jochen Hoenicke <jochen@gnu.org>
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
// List.java -- An ordered collection which allows indexed access
|
|
||||||
//
|
|
||||||
// Copyright (c) 1998 by Stuart Ballard (stuart.ballard@mcmail.com)
|
|
||||||
//
|
|
||||||
// This program is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Library General Public License as published
|
|
||||||
// by the Free Software Foundation, version 2. (see COPYING.LIB)
|
|
||||||
//
|
|
||||||
// This program 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 Library General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Library General Public License
|
|
||||||
// along with this program; if not, write to the Free Software Foundation
|
|
||||||
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// TO DO:
|
|
||||||
// ~ Doc comment for the interface itself needs to be put into english.
|
|
||||||
// ~ Some more @see clauses might be nice.
|
|
||||||
|
|
||||||
package jode.util; |
|
||||||
|
|
||||||
/** |
|
||||||
* [This is what this doc comment will mention: |
|
||||||
* ~ Additional restrictions on some methods. Others included for completeness. |
|
||||||
* ~ ListIterator and what it can do |
|
||||||
* ~ Positional and iterated access |
|
||||||
* ~ search (but linear time) |
|
||||||
* ~ be careful when containing self as an element, because equals and hashCode |
|
||||||
* loop.] |
|
||||||
*/ |
|
||||||
public interface List extends Collection { |
|
||||||
|
|
||||||
/** |
|
||||||
* Insert an element into the list at a given position. |
|
||||||
* |
|
||||||
* @param index the location to insert the item. |
|
||||||
* @param o the object to insert. |
|
||||||
* @exception UnsupportedOperationException if this list does not support the |
|
||||||
* add operation. |
|
||||||
* @exception IndexOutOfBoundsException if index < 0 || index > size() |
|
||||||
* @exception ClassCastException if o cannot be added to this list due to its |
|
||||||
* type. |
|
||||||
* @exception IllegalArgumentException if o cannot be added to this list for |
|
||||||
* some other reason. |
|
||||||
*/ |
|
||||||
void add(int index, Object o); |
|
||||||
|
|
||||||
/** |
|
||||||
* Add an element to the end of the list. |
|
||||||
* |
|
||||||
* @param o the object to add. |
|
||||||
* @returns true, as Collection defines this method as returning true if the |
|
||||||
* list was modified as a result of this action, and it always is for a |
|
||||||
* list. |
|
||||||
* @exception UnsupportedOperationException if this list does not support the |
|
||||||
* add operation. |
|
||||||
* @exception ClassCastException if o cannot be added to this list due to its |
|
||||||
* type. |
|
||||||
* @exception IllegalArgumentException if o cannot be added to this list for |
|
||||||
* some other reason. |
|
||||||
*/ |
|
||||||
boolean add(Object o); |
|
||||||
|
|
||||||
/** |
|
||||||
* Insert the contents of a collection into the list at a given position. |
|
||||||
* |
|
||||||
* @param index the location to insert the collection. |
|
||||||
* @param c the collection to insert. |
|
||||||
* @returns true if the list was modified by this action, that is, if c is |
|
||||||
* non-empty. |
|
||||||
* @exception UnsupportedOperationException if this list does not support the |
|
||||||
* addAll operation. |
|
||||||
* @exception IndexOutOfBoundsException if index < 0 || index > size() |
|
||||||
* @exception ClassCastException if some element of c cannot be added to this |
|
||||||
* list due to its type. |
|
||||||
* @exception IllegalArgumentException if some element of c cannot be added |
|
||||||
* to this list for some other reason. |
|
||||||
*/ |
|
||||||
boolean addAll(int index, Collection c); |
|
||||||
|
|
||||||
/** |
|
||||||
* Add the contents of a collection to the end of the list. |
|
||||||
* |
|
||||||
* @param c the collection to add. |
|
||||||
* @returns true if the list was modified by this action, that is, if c is |
|
||||||
* non-empty. |
|
||||||
* @exception UnsupportedOperationException if this list does not support the |
|
||||||
* addAll operation. |
|
||||||
* @exception ClassCastException if some element of c cannot be added to this |
|
||||||
* list due to its type. |
|
||||||
* @exception IllegalArgumentException if some element of c cannot be added |
|
||||||
* to this list for some other reason. |
|
||||||
*/ |
|
||||||
boolean addAll(Collection c); |
|
||||||
|
|
||||||
/** |
|
||||||
* Clear the list, such that a subsequent call to isEmpty() would return |
|
||||||
* true. |
|
||||||
* |
|
||||||
* @exception UnsupportedOperationException if this list does not support the |
|
||||||
* clear operation. |
|
||||||
*/ |
|
||||||
void clear(); |
|
||||||
|
|
||||||
/** |
|
||||||
* Test whether this list contains a given object as one of its elements. |
|
||||||
* |
|
||||||
* @param o the element to look for. |
|
||||||
* @returns true if this list contains an element e such that <code>o == |
|
||||||
* null ? e == null : o.equals(e)</code>. |
|
||||||
*/ |
|
||||||
boolean contains(Object o); |
|
||||||
|
|
||||||
/** |
|
||||||
* Test whether this list contains every element in a given collection. |
|
||||||
* |
|
||||||
* @param c the collection to test for. |
|
||||||
* @returns true if for every element o in c, contains(o) would return true. |
|
||||||
*/ |
|
||||||
boolean containsAll(Collection c); |
|
||||||
|
|
||||||
/** |
|
||||||
* Test whether this list is equal to another object. A List is defined to be |
|
||||||
* equal to an object if and only if that object is also a List, and the two |
|
||||||
* lists are equal. Two lists l1 and l2 are defined to be equal if and only |
|
||||||
* if <code>l1.size() == l2.size()</code>, and for every integer n between 0 |
|
||||||
* and <code>l1.size() - 1</code> inclusive, <code>l1.get(n) == null ? |
|
||||||
* l2.get(n) == null : l1.get(n).equals(l2.get(n))</code>. |
|
||||||
* |
|
||||||
* @param o the object to test for equality with this list. |
|
||||||
* @returns true if o is equal to this list. |
|
||||||
*/ |
|
||||||
boolean equals(Object o); |
|
||||||
|
|
||||||
/** |
|
||||||
* Get the element at a given index in this list. |
|
||||||
* |
|
||||||
* @param index the index of the element to be returned. |
|
||||||
* @returns the element at index index in this list. |
|
||||||
* @exception IndexOutOfBoundsException if index < 0 || index >= size() |
|
||||||
*/ |
|
||||||
Object get(int index); |
|
||||||
|
|
||||||
/** |
|
||||||
* Obtain a hash code for this list. In order to obey the general contract of |
|
||||||
* the hashCode method of class Object, this value is calculated as follows: |
|
||||||
* <pre> |
|
||||||
* hashCode = 1; |
|
||||||
* Iterator i = list.iterator(); |
|
||||||
* while (i.hasNext()) { |
|
||||||
* Object obj = i.next(); |
|
||||||
* hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode()); |
|
||||||
* } |
|
||||||
* </pre> |
|
||||||
* This ensures that the general contract of Object.hashCode() is adhered to. |
|
||||||
* |
|
||||||
* @returns the hash code of this list. |
|
||||||
*/ |
|
||||||
int hashCode(); |
|
||||||
|
|
||||||
/** |
|
||||||
* Obtain the first index at which a given object is to be found in this |
|
||||||
* list. |
|
||||||
* |
|
||||||
* @returns the least integer n such that <code>o == null ? get(n) == null : |
|
||||||
* o.equals(get(n))</code>, or -1 if there is no such index. |
|
||||||
*/ |
|
||||||
int indexOf(Object o); |
|
||||||
|
|
||||||
/** |
|
||||||
* Test whether this list is empty, that is, if size() == 0. |
|
||||||
* |
|
||||||
* @returns true if this list contains no elements. |
|
||||||
*/ |
|
||||||
boolean isEmpty(); |
|
||||||
|
|
||||||
/** |
|
||||||
* Obtain an Iterator over this list. |
|
||||||
* |
|
||||||
* @returns an Iterator over the elements of this list, in order. |
|
||||||
*/ |
|
||||||
Iterator iterator(); |
|
||||||
|
|
||||||
/** |
|
||||||
* Obtain the last index at which a given object is to be found in this |
|
||||||
* list. |
|
||||||
* |
|
||||||
* @returns the greatest integer n such that <code>o == null ? get(n) == null |
|
||||||
* : o.equals(get(n))</code>. |
|
||||||
*/ |
|
||||||
int lastIndexOf(Object o); |
|
||||||
|
|
||||||
/** |
|
||||||
* Obtain a ListIterator over this list, starting at the beginning. |
|
||||||
* |
|
||||||
* @returns a ListIterator over the elements of this list, in order, starting |
|
||||||
* at the beginning. |
|
||||||
*/ |
|
||||||
ListIterator listIterator(); |
|
||||||
|
|
||||||
/** |
|
||||||
* Obtain a ListIterator over this list, starting at a given position. |
|
||||||
* |
|
||||||
* @param index the position, between 0 and size() inclusive, to begin the |
|
||||||
* iteration from. |
|
||||||
* @returns a ListIterator over the elements of this list, in order, starting |
|
||||||
* at index. |
|
||||||
* @exception IndexOutOfBoundsException if index < 0 || index > size() |
|
||||||
*/ |
|
||||||
ListIterator listIterator(int index); |
|
||||||
|
|
||||||
/** |
|
||||||
* Remove the element at a given position in this list. |
|
||||||
* |
|
||||||
* @param index the position within the list of the object to remove. |
|
||||||
* @returns the object that was removed. |
|
||||||
* @exception UnsupportedOperationException if this list does not support the |
|
||||||
* remove operation. |
|
||||||
* @exception IndexOutOfBoundsException if index < 0 || index > size() |
|
||||||
*/ |
|
||||||
Object remove(int index); |
|
||||||
|
|
||||||
/** |
|
||||||
* Remove the first occurence of an object from this list. That is, remove |
|
||||||
* the first element e such that <code>o == null ? e == null : |
|
||||||
* o.equals(e)</code>. |
|
||||||
* |
|
||||||
* @param o the object to remove. |
|
||||||
* @returns true if the list changed as a result of this call, that is, if |
|
||||||
* the list contained at least one occurrence of o. |
|
||||||
* @exception UnsupportedOperationException if this list does not support the |
|
||||||
* remove operation. |
|
||||||
*/ |
|
||||||
boolean remove(Object o); |
|
||||||
|
|
||||||
/** |
|
||||||
* Remove all elements of a given collection from this list. That is, remove |
|
||||||
* every element e such that c.contains(e). |
|
||||||
* |
|
||||||
* @returns true if this list was modified as a result of this call. |
|
||||||
* @exception UnsupportedOperationException if this list does not support the |
|
||||||
* removeAll operation. |
|
||||||
*/ |
|
||||||
boolean removeAll(Collection c); |
|
||||||
|
|
||||||
/** |
|
||||||
* Remove all elements of this list that are not contained in a given |
|
||||||
* collection. That is, remove every element e such that !c.contains(e). |
|
||||||
* |
|
||||||
* @returns true if this list was modified as a result of this call. |
|
||||||
* @exception UnsupportedOperationException if this list does not support the |
|
||||||
* retainAll operation. |
|
||||||
*/ |
|
||||||
boolean retainAll(Collection c); |
|
||||||
|
|
||||||
/** |
|
||||||
* Replace an element of this list with another object. |
|
||||||
* |
|
||||||
* @param index the position within this list of the element to be replaced. |
|
||||||
* @param o the object to replace it with. |
|
||||||
* @returns the object that was replaced. |
|
||||||
* @exception UnsupportedOperationException if this list does not support the |
|
||||||
* set operation. |
|
||||||
* @exception IndexOutOfBoundsException if index < 0 || index >= size() |
|
||||||
* @exception ClassCastException if o cannot be added to this list due to its |
|
||||||
* type. |
|
||||||
* @exception IllegalArgumentException if o cannot be added to this list for |
|
||||||
* some other reason. |
|
||||||
*/ |
|
||||||
Object set(int index, Object o); |
|
||||||
|
|
||||||
/** |
|
||||||
* Get the number of elements in this list. |
|
||||||
* |
|
||||||
* @returns the number of elements in the list. |
|
||||||
*/ |
|
||||||
int size(); |
|
||||||
|
|
||||||
/** |
|
||||||
* Obtain a List view of a subsection of this list, from fromIndex |
|
||||||
* (inclusive) to toIndex (exclusive). The returned list should be modifiable |
|
||||||
* if and only if this list is modifiable. Changes to the returned list |
|
||||||
* should be reflected in this list. If this list is structurally modified in |
|
||||||
* any way other than through the returned list, the result of any subsequent |
|
||||||
* operations on the returned list is undefined. |
|
||||||
* |
|
||||||
* @param fromIndex the index that the returned list should start from |
|
||||||
* (inclusive). |
|
||||||
* @param toIndex the index that the returned list should go to (exclusive). |
|
||||||
* @returns a List backed by a subsection of this list. |
|
||||||
* @exception IndexOutOfBoundsException if fromIndex < 0 || toIndex > size() |
|
||||||
* || fromIndex > toIndex. |
|
||||||
*/ |
|
||||||
List subList(int fromIndex, int toIndex); |
|
||||||
|
|
||||||
/** |
|
||||||
* Copy the current contents of this list into an array. |
|
||||||
* |
|
||||||
* @returns an array of type Object[] and length equal to the length of this |
|
||||||
* list, containing the elements currently in this list, in order. |
|
||||||
*/ |
|
||||||
Object[] toArray(); |
|
||||||
|
|
||||||
/** |
|
||||||
* Copy the current contents of this list into an array. If the array passed |
|
||||||
* as an argument has length less than that of this list, an array of the |
|
||||||
* same run-time type as a, and length equal to the length of this list, is |
|
||||||
* allocated using Reflection. Otherwise, a itself is used. The elements of |
|
||||||
* this list are copied into it, and if there is space in the array, the |
|
||||||
* following element is set to null. The resultant array is returned. |
|
||||||
* Note: The fact that the following element is set to null is only useful |
|
||||||
* if it is known that this list does not contain any null elements. |
|
||||||
* |
|
||||||
* @param a the array to copy this list into. |
|
||||||
* @returns an array containing the elements currently in this list, in |
|
||||||
* order. |
|
||||||
* @exception ArrayStoreException if the type of any element of the |
|
||||||
* collection is not a subtype of the element type of a. |
|
||||||
*/ |
|
||||||
Object[] toArray(Object[] a); |
|
||||||
} |
|
@ -1,145 +0,0 @@ |
|||||||
// This interface is taken from the Classpath project.
|
|
||||||
// Please note the different copyright holder!
|
|
||||||
// The changes I did is this comment, the package line, some
|
|
||||||
// imports from java.util and some minor jdk12 -> jdk11 fixes.
|
|
||||||
// -- Jochen Hoenicke <jochen@gnu.org>
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
// ListIterator.java -- Extended Iterator for iterating over ordered lists
|
|
||||||
//
|
|
||||||
// Copyright (c) 1998 by Stuart Ballard (stuart.ballard@mcmail.com)
|
|
||||||
//
|
|
||||||
// This program is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Library General Public License as published
|
|
||||||
// by the Free Software Foundation, version 2. (see COPYING.LIB)
|
|
||||||
//
|
|
||||||
// This program 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 Library General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Library General Public License
|
|
||||||
// along with this program; if not, write to the Free Software Foundation
|
|
||||||
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
package jode.util; |
|
||||||
|
|
||||||
/** |
|
||||||
* An extended version of Iterator to support the extra features of Lists. The |
|
||||||
* elements may be accessed in forward or reverse order, elements may be |
|
||||||
* replaced as well as removed, and new elements may be inserted, during the |
|
||||||
* traversal of the list. |
|
||||||
*/ |
|
||||||
public interface ListIterator extends Iterator { |
|
||||||
|
|
||||||
/** |
|
||||||
* Tests whether there are elements remaining in the list in the forward |
|
||||||
* direction. |
|
||||||
* |
|
||||||
* @return true if there is at least one more element in the list in the |
|
||||||
* forward direction, that is, if the next call to next will not throw |
|
||||||
* NoSuchElementException. |
|
||||||
*/ |
|
||||||
boolean hasNext(); |
|
||||||
|
|
||||||
/** |
|
||||||
* Tests whether there are elements remaining in the list in the reverse |
|
||||||
* direction. |
|
||||||
* |
|
||||||
* @return true if there is at least one more element in the list in the |
|
||||||
* reverse direction, that is, if the next call to previous will not throw |
|
||||||
* NoSuchElementException. |
|
||||||
*/ |
|
||||||
boolean hasPrevious(); |
|
||||||
|
|
||||||
/** |
|
||||||
* Obtain the next element in the list in the forward direction. Repeated |
|
||||||
* calls to next may be used to iterate over the entire list, or calls to next |
|
||||||
* and previous may be used together to go forwards and backwards. Alternating |
|
||||||
* calls to next and previous will return the same element. |
|
||||||
* |
|
||||||
* @return the next element in the list in the forward direction |
|
||||||
* @exception NoSuchElementException if there are no more elements |
|
||||||
*/ |
|
||||||
Object next(); |
|
||||||
|
|
||||||
/** |
|
||||||
* Obtain the next element in the list in the reverse direction. Repeated |
|
||||||
* calls to previous may be used to iterate backwards over the entire list, or |
|
||||||
* calls to next and previous may be used together to go forwards and |
|
||||||
* backwards. Alternating calls to next and previous will return the same |
|
||||||
* element. |
|
||||||
* |
|
||||||
* @return the next element in the list in the reverse direction |
|
||||||
* @exception NoSuchElementException if there are no more elements |
|
||||||
*/ |
|
||||||
Object previous(); |
|
||||||
|
|
||||||
/** |
|
||||||
* Find the index of the element that would be returned by a call to next. |
|
||||||
* |
|
||||||
* @return the index of the element that would be returned by a call to next, |
|
||||||
* or list.size() if the iterator is at the end of the list. |
|
||||||
*/ |
|
||||||
int nextIndex(); |
|
||||||
|
|
||||||
/** |
|
||||||
* Find the index of the element that would be returned by a call to previous. |
|
||||||
* |
|
||||||
* @return the index of the element that would be returned by a call to |
|
||||||
* previous, or -1 if the iterator is at the beginning of the list. |
|
||||||
*/ |
|
||||||
int previousIndex(); |
|
||||||
|
|
||||||
/** |
|
||||||
* Insert an element into the list at the current position of the iterator. |
|
||||||
* The element is inserted in between the element that would be returned by |
|
||||||
* previous and the element that would be returned by next. After the |
|
||||||
* insertion, a subsequent call to next is unaffected, but a call to |
|
||||||
* previous returns the item that was added. This operation is optional, it |
|
||||||
* may throw an UnsupportedOperationException. |
|
||||||
* |
|
||||||
* @param o the object to insert into the list |
|
||||||
* @exception ClassCastException the object is of a type which cannot be added |
|
||||||
* to this list |
|
||||||
* @exception IllegalArgumentException some other aspect of the object stops |
|
||||||
* it being added to this list |
|
||||||
* @exception UnsupportedOperationException if this ListIterator does not |
|
||||||
* support the add operation |
|
||||||
*/ |
|
||||||
void add(Object o); |
|
||||||
|
|
||||||
/** |
|
||||||
* Remove from the list the element last returned by a call to next or |
|
||||||
* previous. This method may only be called if neither add nor remove have |
|
||||||
* been called since the last call to next or previous. This operation is |
|
||||||
* optional, it may throw an UnsupportedOperationException. |
|
||||||
* |
|
||||||
* @exception IllegalStateException if neither next or previous have been |
|
||||||
* called, or if add or remove has been called since the last call to next |
|
||||||
* or previous. |
|
||||||
* @exception UnsupportedOperationException if this ListIterator does not |
|
||||||
* support the remove operation. |
|
||||||
*/ |
|
||||||
void remove(); |
|
||||||
|
|
||||||
/** |
|
||||||
* Replace the element last returned by a call to next or previous with a |
|
||||||
* given object. This method may only be called if neither add nor remove have |
|
||||||
* been called since the last call to next or previous. This operation is |
|
||||||
* optional, it may throw an UnsupportedOperationException. |
|
||||||
* |
|
||||||
* @param o the object to replace the element with |
|
||||||
* @exception ClassCastException the object is of a type which cannot be added |
|
||||||
* to this list |
|
||||||
* @exception IllegalArgumentException some other aspect of the object stops |
|
||||||
* it being added to this list |
|
||||||
* @exception IllegalStateException if neither next or previous have been |
|
||||||
* called, or if add or remove has been called since the last call to next |
|
||||||
* or previous. |
|
||||||
* @exception UnsupportedOperationException if this ListIterator does not |
|
||||||
* support the set operation. |
|
||||||
*/ |
|
||||||
void set(Object o); |
|
||||||
} |
|
@ -1,55 +0,0 @@ |
|||||||
// This interface is taken from the Classpath project.
|
|
||||||
// Please note the different copyright holder!
|
|
||||||
// The changes I did is this comment, the package line, some
|
|
||||||
// imports from java.util and some minor jdk12 -> jdk11 fixes.
|
|
||||||
// -- Jochen Hoenicke <jochen@gnu.org>
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Map.java -- An object that maps keys to values
|
|
||||||
//
|
|
||||||
// Copyright (c) 1998 by Stuart Ballard (stuart.ballard@mcmail.com)
|
|
||||||
//
|
|
||||||
// This program is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Library General Public License as published
|
|
||||||
// by the Free Software Foundation, version 2. (see COPYING.LIB)
|
|
||||||
//
|
|
||||||
// This program 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 Library General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Library General Public License
|
|
||||||
// along with this program; if not, write to the Free Software Foundation
|
|
||||||
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// TO DO:
|
|
||||||
// ~ Doc comments for everything.
|
|
||||||
|
|
||||||
package jode.util; |
|
||||||
|
|
||||||
public interface Map |
|
||||||
{ |
|
||||||
public void clear(); |
|
||||||
public boolean containsKey(Object key); |
|
||||||
public boolean containsValue(Object value); |
|
||||||
public Set entrySet(); |
|
||||||
public boolean equals(Object o); |
|
||||||
public Object get(Object key); |
|
||||||
public Object put(Object key, Object value); |
|
||||||
public int hashCode(); |
|
||||||
public boolean isEmpty(); |
|
||||||
public Set keySet(); |
|
||||||
public void putAll(Map m); |
|
||||||
public Object remove(Object o); |
|
||||||
public int size(); |
|
||||||
public Collection values(); |
|
||||||
|
|
||||||
public static interface Entry { |
|
||||||
public Object getKey(); |
|
||||||
public Object getValue(); |
|
||||||
public Object setValue(Object value); |
|
||||||
public int hashCode(); |
|
||||||
public boolean equals(Object o); |
|
||||||
} |
|
||||||
} |
|
@ -1,46 +0,0 @@ |
|||||||
// This interface is taken from the Classpath project.
|
|
||||||
// Please note the different copyright holder!
|
|
||||||
// The changes I did is this comment, the package line, some
|
|
||||||
// imports from java.util and some minor jdk12 -> jdk11 fixes.
|
|
||||||
// -- Jochen Hoenicke <jochen@gnu.org>
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Set.java -- A collection that prohibits duplicates
|
|
||||||
//
|
|
||||||
// Copyright (c) 1998 by Stuart Ballard (stuart.ballard@mcmail.com)
|
|
||||||
//
|
|
||||||
// This program is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Library General Public License as published
|
|
||||||
// by the Free Software Foundation, version 2. (see COPYING.LIB)
|
|
||||||
//
|
|
||||||
// This program 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 Library General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Library General Public License
|
|
||||||
// along with this program; if not, write to the Free Software Foundation
|
|
||||||
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// TO DO:
|
|
||||||
// ~ Doc comments for everything.
|
|
||||||
|
|
||||||
package jode.util; |
|
||||||
|
|
||||||
public interface Set extends Collection { |
|
||||||
boolean add(Object o); |
|
||||||
boolean addAll(Collection c); |
|
||||||
void clear(); |
|
||||||
boolean contains(Object o); |
|
||||||
boolean containsAll(Collection c); |
|
||||||
boolean equals(Object o); |
|
||||||
int hashCode(); |
|
||||||
boolean isEmpty(); |
|
||||||
Iterator iterator(); |
|
||||||
boolean remove(Object o); |
|
||||||
boolean removeAll(Collection c); |
|
||||||
boolean retainAll(Collection c); |
|
||||||
int size(); |
|
||||||
Object[] toArray(); |
|
||||||
} |
|
@ -1,38 +0,0 @@ |
|||||||
// This interface is taken from the Classpath project.
|
|
||||||
// Please note the different copyright holder!
|
|
||||||
// The changes I did is this comment, the package line, some
|
|
||||||
// imports from java.util and some minor jdk12 -> jdk11 fixes.
|
|
||||||
// -- Jochen Hoenicke <jochen@gnu.org>
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
// SortedMap.java -- A map that makes guarantees about the order of its keys
|
|
||||||
//
|
|
||||||
// Copyright (c) 1998 by Stuart Ballard (stuart.ballard@mcmail.com)
|
|
||||||
//
|
|
||||||
// This program is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Library General Public License as published
|
|
||||||
// by the Free Software Foundation, version 2. (see COPYING.LIB)
|
|
||||||
//
|
|
||||||
// This program 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 Library General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Library General Public License
|
|
||||||
// along with this program; if not, write to the Free Software Foundation
|
|
||||||
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// TO DO:
|
|
||||||
// ~ Doc comments for everything.
|
|
||||||
|
|
||||||
package jode.util; |
|
||||||
|
|
||||||
public interface SortedMap extends Map { |
|
||||||
Comparator comparator(); |
|
||||||
Object firstKey(); |
|
||||||
SortedMap headMap(Object toKey); |
|
||||||
Object lastKey(); |
|
||||||
SortedMap subMap(Object fromKey, Object toKey); |
|
||||||
SortedMap tailMap(Object fromKey); |
|
||||||
} |
|
@ -1,38 +0,0 @@ |
|||||||
// This interface is taken from the Classpath project.
|
|
||||||
// Please note the different copyright holder!
|
|
||||||
// The changes I did is this comment, the package line, some
|
|
||||||
// imports from java.util and some minor jdk12 -> jdk11 fixes.
|
|
||||||
// -- Jochen Hoenicke <jochen@gnu.org>
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
// SortedSet.java -- A set that makes guarantees about the order of its elements
|
|
||||||
//
|
|
||||||
// Copyright (c) 1998 by Stuart Ballard (stuart.ballard@mcmail.com)
|
|
||||||
//
|
|
||||||
// This program is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Library General Public License as published
|
|
||||||
// by the Free Software Foundation, version 2. (see COPYING.LIB)
|
|
||||||
//
|
|
||||||
// This program 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 Library General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Library General Public License
|
|
||||||
// along with this program; if not, write to the Free Software Foundation
|
|
||||||
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// TO DO:
|
|
||||||
// ~ Doc comments for everything.
|
|
||||||
|
|
||||||
package jode.util; |
|
||||||
|
|
||||||
public interface SortedSet extends Set { |
|
||||||
Comparator comparator(); |
|
||||||
Object first(); |
|
||||||
SortedSet headSet(Object toElement); |
|
||||||
Object last(); |
|
||||||
SortedSet subSet(Object fromElement, Object toElement); |
|
||||||
SortedSet tailSet(Object fromElement); |
|
||||||
} |
|
File diff suppressed because it is too large
Load Diff
@ -1,331 +0,0 @@ |
|||||||
// This class is taken from the Classpath project.
|
|
||||||
// Please note the different copyright holder!
|
|
||||||
// The changes I did is this comment, the package line, some
|
|
||||||
// imports from java.util and some minor jdk12 -> jdk11 fixes.
|
|
||||||
// -- Jochen Hoenicke <jochen@gnu.org>
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
// TreeSet.java -- a class providing a TreeMap-backet SortedSet
|
|
||||||
//
|
|
||||||
// Copyright (c) 1999 by Jon A. Zeppieri (jon@eease.com)
|
|
||||||
//
|
|
||||||
// This program is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Library General Public License as published
|
|
||||||
// by the Free Software Foundation, version 2. (see COPYING.LIB)
|
|
||||||
//
|
|
||||||
// This program 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 Library General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Library General Public License
|
|
||||||
// along with this program; if not, write to the Free Software Foundation
|
|
||||||
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
package jode.util; |
|
||||||
|
|
||||||
import java.io.IOException; |
|
||||||
import java.io.Serializable; |
|
||||||
import java.io.ObjectInputStream; |
|
||||||
import java.io.ObjectOutputStream; |
|
||||||
|
|
||||||
/** |
|
||||||
* This class provides a TreeMap-backed implementation of the |
|
||||||
* SortedSet interface. |
|
||||||
* |
|
||||||
* Each element in the Set is a key in the backing TreeMap; each key |
|
||||||
* maps to a static token, denoting that the key does, in fact, exist. |
|
||||||
* |
|
||||||
* Most operations are O(log n). |
|
||||||
* |
|
||||||
* TreeSet is a part of the JDK1.2 Collections API. |
|
||||||
* |
|
||||||
* @author Jon Zeppieri |
|
||||||
* @version $Revision$ |
|
||||||
* @modified $Id$ |
|
||||||
*/ |
|
||||||
|
|
||||||
public class TreeSet extends AbstractSet |
|
||||||
implements SortedSet, Cloneable, Serializable |
|
||||||
{ |
|
||||||
// INSTANCE VARIABLES -------------------------------------------------
|
|
||||||
|
|
||||||
/** The TreeMap which backs this Set */ |
|
||||||
transient SortedMap _oMap; |
|
||||||
static final long serialVersionUID = -2479143000061671589L; |
|
||||||
|
|
||||||
|
|
||||||
// CONSTRUCTORS -------------------------------------------------------
|
|
||||||
|
|
||||||
/** |
|
||||||
* Construct a new TreeSet whose backing TreeMap using the "natural" ordering |
|
||||||
* of keys. |
|
||||||
*/ |
|
||||||
public TreeSet() |
|
||||||
{ |
|
||||||
this((Comparator) null); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Construct a new TreeSet whose backing TreeMap uses the supplied |
|
||||||
* Comparator. |
|
||||||
* |
|
||||||
* @param oComparator the Comparator this Set will use |
|
||||||
*/ |
|
||||||
public TreeSet(Comparator oComparator) |
|
||||||
{ |
|
||||||
_oMap = new TreeMap(oComparator); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Construct a new TreeSet whose backing TreeMap uses the "natural" |
|
||||||
* orering of the keys and which contains all of the elements in the |
|
||||||
* supplied Collection. |
|
||||||
* |
|
||||||
* @param oCollection the new Set will be initialized with all |
|
||||||
* of the elements in this Collection |
|
||||||
*/ |
|
||||||
public TreeSet(Collection oCollection) |
|
||||||
{ |
|
||||||
this((Comparator) null); |
|
||||||
addAll(oCollection); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Construct a new TreeSet, using the same key ordering as the supplied |
|
||||||
* SortedSet and containing all of the elements in the supplied SortedSet. |
|
||||||
* This constructor runs in linear time. |
|
||||||
* |
|
||||||
* @param oSortedSet the new TreeSet will use this SortedSet's |
|
||||||
* comparator and will initialize itself |
|
||||||
* with all of the elements in this SortedSet |
|
||||||
*/ |
|
||||||
public TreeSet(SortedSet oSortedSet) |
|
||||||
{ |
|
||||||
this(oSortedSet.comparator()); |
|
||||||
|
|
||||||
TreeMap oMap = (TreeMap) _oMap; |
|
||||||
int i = 0; |
|
||||||
Map.Entry[] arEntries = new Map.Entry[oSortedSet.size()]; |
|
||||||
Iterator itEntries = oSortedSet.iterator(); |
|
||||||
|
|
||||||
while (itEntries.hasNext()) |
|
||||||
arEntries[i++] = new BasicMapEntry(itEntries.next(), Boolean.TRUE); |
|
||||||
|
|
||||||
oMap._iSize = i; |
|
||||||
oMap.putAllLinear(arEntries); |
|
||||||
} |
|
||||||
|
|
||||||
TreeSet(SortedMap oMap) |
|
||||||
{ |
|
||||||
_oMap = oMap; |
|
||||||
} |
|
||||||
|
|
||||||
// METHODS -----------------------------------------------------------
|
|
||||||
|
|
||||||
/** |
|
||||||
* Adds the spplied Object to the Set if it is not already in the Set; |
|
||||||
* returns true if the element is added, false otherwise |
|
||||||
* |
|
||||||
* @param oObject the Object to be added to this Set |
|
||||||
*/ |
|
||||||
public boolean add(Object oObject) |
|
||||||
{ |
|
||||||
if (_oMap.containsKey(oObject)) |
|
||||||
{ |
|
||||||
return false; |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
internalAdd(_oMap, oObject); |
|
||||||
return true; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Adds all of the elements in the supplied Collection to this TreeSet. |
|
||||||
* |
|
||||||
* @param oCollection All of the elements in this Collection |
|
||||||
* will be added to the Set. |
|
||||||
* |
|
||||||
* @return true if the Set is altered, false otherwise |
|
||||||
*/ |
|
||||||
public boolean addAll(Collection oCollection) |
|
||||||
{ |
|
||||||
boolean boResult = false; |
|
||||||
Iterator itElements = oCollection.iterator(); |
|
||||||
|
|
||||||
while (itElements.hasNext()) |
|
||||||
boResult = (boResult || add(itElements.next())); |
|
||||||
|
|
||||||
return boResult; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Removes all elements in this Set. |
|
||||||
*/ |
|
||||||
public void clear() |
|
||||||
{ |
|
||||||
_oMap.clear(); |
|
||||||
} |
|
||||||
|
|
||||||
/** Returns a shallow copy of this Set. */ |
|
||||||
public Object clone() |
|
||||||
{ |
|
||||||
TreeSet oClone; |
|
||||||
|
|
||||||
try |
|
||||||
{ |
|
||||||
oClone = (TreeSet) super.clone(); |
|
||||||
oClone._oMap = _oMap; |
|
||||||
} |
|
||||||
catch(CloneNotSupportedException e) |
|
||||||
{ |
|
||||||
oClone = null; |
|
||||||
} |
|
||||||
return oClone; |
|
||||||
} |
|
||||||
|
|
||||||
/** Returns this Set's comparator */ |
|
||||||
public Comparator comparator() |
|
||||||
{ |
|
||||||
return _oMap.comparator(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Returns true if this Set contains the supplied Object, |
|
||||||
* false otherwise |
|
||||||
* |
|
||||||
* @param oObject the Object whose existence in the Set is |
|
||||||
* being tested |
|
||||||
*/ |
|
||||||
public boolean contains(Object oObject) |
|
||||||
{ |
|
||||||
return _oMap.containsKey(oObject); |
|
||||||
} |
|
||||||
|
|
||||||
/** Returns true if this Set has size 0, false otherwise */ |
|
||||||
public boolean isEmpty() |
|
||||||
{ |
|
||||||
return _oMap.isEmpty(); |
|
||||||
} |
|
||||||
|
|
||||||
/** Returns the number of elements in this Set */ |
|
||||||
public int size() |
|
||||||
{ |
|
||||||
return _oMap.size(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* If the supplied Object is in this Set, it is removed, and true is |
|
||||||
* returned; otherwise, false is returned. |
|
||||||
* |
|
||||||
* @param oObject the Object we are attempting to remove |
|
||||||
* from this Set |
|
||||||
*/ |
|
||||||
public boolean remove(Object oObject) |
|
||||||
{ |
|
||||||
return (_oMap.remove(oObject) != null); |
|
||||||
} |
|
||||||
|
|
||||||
/** Returns the first (by order) element in this Set */ |
|
||||||
public Object first() |
|
||||||
{ |
|
||||||
return _oMap.firstKey(); |
|
||||||
} |
|
||||||
|
|
||||||
/** Returns the last (by order) element in this Set */ |
|
||||||
public Object last() |
|
||||||
{ |
|
||||||
return _oMap.lastKey(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Returns a view of this Set including all elements in the interval |
|
||||||
* [oFromElement, oToElement). |
|
||||||
* |
|
||||||
* @param oFromElement the resultant view will contain all |
|
||||||
* elements greater than or equal to this |
|
||||||
* element |
|
||||||
* @param oToElement the resultant view will contain all |
|
||||||
* elements less than this element |
|
||||||
*/ |
|
||||||
public SortedSet subSet(Object oFromElement, Object oToElement) |
|
||||||
{ |
|
||||||
return new TreeSet(_oMap.subMap(oFromElement, oToElement)); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Returns a view of this Set including all elements less than oToElement |
|
||||||
* |
|
||||||
* @param oToElement the resultant view will contain all |
|
||||||
* elements less than this element |
|
||||||
*/ |
|
||||||
public SortedSet headSet(Object oToElement) |
|
||||||
{ |
|
||||||
return new TreeSet(_oMap.headMap(oToElement)); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Returns a view of this Set including all elements greater than or |
|
||||||
* equal to oFromElement. |
|
||||||
* |
|
||||||
* @param oFromElement the resultant view will contain all |
|
||||||
* elements greater than or equal to this |
|
||||||
* element |
|
||||||
*/ |
|
||||||
public SortedSet tailSet(Object oFromElement) |
|
||||||
{ |
|
||||||
return new TreeSet(_oMap.tailMap(oFromElement)); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** Returns in Iterator over the elements in this TreeSet */ |
|
||||||
public Iterator iterator() |
|
||||||
{ |
|
||||||
return _oMap.keySet().iterator(); |
|
||||||
} |
|
||||||
|
|
||||||
private void writeObject(ObjectOutputStream oOut) throws IOException |
|
||||||
{ |
|
||||||
Iterator itElements = iterator(); |
|
||||||
|
|
||||||
oOut.writeObject(comparator()); |
|
||||||
oOut.writeInt(size()); |
|
||||||
|
|
||||||
while (itElements.hasNext()) |
|
||||||
oOut.writeObject(itElements.next()); |
|
||||||
} |
|
||||||
|
|
||||||
private void readObject(ObjectInputStream oIn) |
|
||||||
throws IOException, ClassNotFoundException |
|
||||||
{ |
|
||||||
int i; |
|
||||||
Map.Entry[] arEntries; |
|
||||||
TreeMap oMap; |
|
||||||
Comparator oComparator = (Comparator) oIn.readObject(); |
|
||||||
int iSize = oIn.readInt(); |
|
||||||
|
|
||||||
arEntries = new Map.Entry[iSize]; |
|
||||||
|
|
||||||
for (i = 0; i < iSize; i++) |
|
||||||
arEntries[iSize] = new BasicMapEntry(oIn.readObject(), Boolean.TRUE); |
|
||||||
|
|
||||||
oMap = new TreeMap(oComparator); |
|
||||||
oMap._iSize = iSize; |
|
||||||
oMap.putAllLinear(arEntries); |
|
||||||
_oMap = oMap; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* adds the supplied element to this Set; this private method is used |
|
||||||
* internally instead of add(), because add() can be overridden |
|
||||||
* to do unexpected things |
|
||||||
* |
|
||||||
* @param o the Object to add to this Set |
|
||||||
*/ |
|
||||||
private static final void internalAdd(Map oMap, Object oObject) |
|
||||||
{ |
|
||||||
oMap.put(oObject, Boolean.TRUE); |
|
||||||
} |
|
||||||
} |
|
@ -1,54 +0,0 @@ |
|||||||
// This interface is taken from the Classpath project.
|
|
||||||
// Please note the different copyright holder!
|
|
||||||
// The changes I did is this comment, the package line, some
|
|
||||||
// imports from java.util and some minor jdk12 -> jdk11 fixes.
|
|
||||||
// -- Jochen Hoenicke <jochen@gnu.org>
|
|
||||||
|
|
||||||
/************************************************************************* |
|
||||||
/* UnsupportedOperationException.java -- Exception thrown when an |
|
||||||
/* unsupported operation is attempted on an object |
|
||||||
/* |
|
||||||
/* Copyright (c) 1998 by Free Software Foundation, Inc. |
|
||||||
/* |
|
||||||
/* This program is free software; you can redistribute it and/or modify |
|
||||||
/* it under the terms of the GNU Library General Public License as published |
|
||||||
/* by the Free Software Foundation, version 2. (see COPYING.LIB) |
|
||||||
/* |
|
||||||
/* This program 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 for more details. |
|
||||||
/* |
|
||||||
/* You should have received a copy of the GNU General Public License |
|
||||||
/* along with this program; if not, write to the Free Software Foundation |
|
||||||
/* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA |
|
||||||
/*************************************************************************/ |
|
||||||
|
|
||||||
package jode.util; |
|
||||||
|
|
||||||
/** |
|
||||||
* This exception is thrown by an object when an operation is |
|
||||||
* requested of it that it does not support. |
|
||||||
* |
|
||||||
* @since JDK 1.2 |
|
||||||
*/ |
|
||||||
public class UnsupportedOperationException extends RuntimeException |
|
||||||
{ |
|
||||||
static final long serialVersionUID = -1242599979055084673L; |
|
||||||
|
|
||||||
/** |
|
||||||
* Create an exception without a message. |
|
||||||
*/ |
|
||||||
public UnsupportedOperationException() |
|
||||||
{ |
|
||||||
super(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Create an exception with a message. |
|
||||||
*/ |
|
||||||
public UnsupportedOperationException( String s ) |
|
||||||
{ |
|
||||||
super(s); |
|
||||||
} |
|
||||||
} |
|
Loading…
Reference in new issue