You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by pc...@apache.org on 2006/06/28 21:46:19 UTC

svn commit: r417860 [6/12] - in /incubator/openjpa/trunk: ./ openjpa-lib/ openjpa-lib/main/ openjpa-lib/src/ openjpa-lib/src/main/ openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/ openjpa-lib/src/test/ openjpa-lib/src/test/java/ openjpa-lib/src/t...

Added: incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/ConstantInstruction.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/ConstantInstruction.java?rev=417860&view=auto
==============================================================================
--- incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/ConstantInstruction.java (added)
+++ incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/ConstantInstruction.java Wed Jun 28 12:46:13 2006
@@ -0,0 +1,531 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package serp.bytecode;
+
+import serp.bytecode.lowlevel.*;
+
+import serp.bytecode.visitor.*;
+
+import serp.util.*;
+
+import java.io.*;
+
+
+/**
+ *  <p>An instruction that that loads a constant onto the stack.
+ *  The opcode represented by this instruction may change depending on the
+ *  type and value of the constant set.  For example, if the constant value
+ *  is initially set to 5, the opcode will be <code>iconst5</code>; if later
+ *  incremented        to 6, the opcode will be changed to <code>bipush(6)</code>.</p>
+ *
+ *  @author Abe White
+ */
+public class ConstantInstruction extends TypedInstruction {
+    private int _arg = -1;
+
+    ConstantInstruction(Code owner) {
+        super(owner);
+    }
+
+    ConstantInstruction(Code owner, int opcode) {
+        super(owner, opcode);
+    }
+
+    int getLength() {
+        switch (getOpcode()) {
+        case Constants.BIPUSH:
+        case Constants.LDC:
+            return super.getLength() + 1;
+
+        case Constants.SIPUSH:
+        case Constants.LDCW:
+        case Constants.LDC2W:
+            return super.getLength() + 2;
+
+        default:
+            return super.getLength();
+        }
+    }
+
+    public int getStackChange() {
+        String type = getTypeName();
+
+        if (double.class.getName().equals(type) ||
+                long.class.getName().equals(type)) {
+            return 2;
+        }
+
+        return 1;
+    }
+
+    public int getLogicalStackChange() {
+        return 1;
+    }
+
+    public String getTypeName() {
+        int opcode = getOpcode();
+
+        switch (opcode) {
+        case Constants.NOP:
+            return null;
+
+        case Constants.ACONSTNULL:
+            return Object.class.getName();
+
+        case Constants.ICONSTM1:
+        case Constants.ICONST0:
+        case Constants.ICONST1:
+        case Constants.ICONST2:
+        case Constants.ICONST3:
+        case Constants.ICONST4:
+        case Constants.ICONST5:
+        case Constants.BIPUSH:
+        case Constants.SIPUSH:
+            return int.class.getName();
+
+        case Constants.LCONST0:
+        case Constants.LCONST1:
+            return long.class.getName();
+
+        case Constants.FCONST0:
+        case Constants.FCONST1:
+        case Constants.FCONST2:
+            return float.class.getName();
+
+        case Constants.DCONST0:
+        case Constants.DCONST1:
+            return double.class.getName();
+        }
+
+        Entry entry = getPool().getEntry(_arg);
+
+        switch (entry.getType()) {
+        case Entry.UTF8:
+        case Entry.STRING:
+            return String.class.getName();
+
+        case Entry.INT:
+            return int.class.getName();
+
+        case Entry.FLOAT:
+            return float.class.getName();
+
+        case Entry.LONG:
+            return long.class.getName();
+
+        case Entry.DOUBLE:
+            return double.class.getName();
+
+        case Entry.CLASS:
+            return Class.class.getName();
+
+        default:
+            return null;
+        }
+    }
+
+    public TypedInstruction setType(String type) {
+        throw new UnsupportedOperationException("Use setValue");
+    }
+
+    /**
+     *  Return the value of the constant as its wrapper type, or null if
+     *  not set.  Returns class values as the class name.
+     */
+    public Object getValue() {
+        int opcode = getOpcode();
+
+        switch (opcode) {
+        case Constants.NOP:
+        case Constants.ACONSTNULL:
+            return null;
+
+        case Constants.ICONSTM1:
+        case Constants.ICONST0:
+        case Constants.ICONST1:
+        case Constants.ICONST2:
+        case Constants.ICONST3:
+        case Constants.ICONST4:
+        case Constants.ICONST5:
+            return Numbers.valueOf(opcode - Constants.ICONST0);
+
+        case Constants.LCONST0:
+        case Constants.LCONST1:
+            return Numbers.valueOf((long) (opcode - Constants.LCONST0));
+
+        case Constants.FCONST0:
+        case Constants.FCONST1:
+        case Constants.FCONST2:
+            return new Float(opcode - Constants.FCONST0);
+
+        case Constants.DCONST0:
+        case Constants.DCONST1:
+            return new Double(opcode - Constants.DCONST0);
+
+        case Constants.BIPUSH:
+        case Constants.SIPUSH:
+            return Numbers.valueOf(_arg);
+
+        default:
+
+            Entry entry = getPool().getEntry(_arg);
+            Object val = ((ConstantEntry) entry).getConstant();
+
+            if (entry.getType() == Entry.CLASS) {
+                return getProject().getNameCache()
+                           .getExternalForm((String) val, false);
+            }
+
+            return val;
+        }
+    }
+
+    /**
+     *  Set the constant to the given value.  The value should be
+     *  an instance of String, Integer, Long, Double, Float, Class, BCClass, or
+     *  null depending on the constant type.  If the given value is not
+     *  supported directly, it will be converted accordingly.
+      *
+     *  @return this instruction, for method chaining
+     */
+    public ConstantInstruction setValue(Object value) {
+        if (value instanceof Boolean) {
+            value = Numbers.valueOf((((Boolean) value).booleanValue()) ? 1 : 0);
+        } else if (value instanceof Character) {
+            value = Numbers.valueOf((int) ((Character) value).charValue());
+        } else if (value instanceof Byte) {
+            value = Numbers.valueOf(((Byte) value).intValue());
+        } else if (value instanceof Short) {
+            value = Numbers.valueOf(((Short) value).intValue());
+        } else if ((value != null) && !(value instanceof Number) &&
+                !(value instanceof String) && !(value instanceof Class) &&
+                !(value instanceof BCClass)) {
+            throw new IllegalArgumentException("value = " + value);
+        }
+
+        calculateOpcode(value, false);
+
+        return this;
+    }
+
+    /**
+      *  Return the string value of this constant, or null if not set.
+     */
+    public String getStringValue() {
+        return (String) getValue();
+    }
+
+    /**
+      *  Return the int value of this constant, or 0 if not set.
+     */
+    public int getIntValue() {
+        Object value = getValue();
+
+        return (value == null) ? 0 : ((Number) value).intValue();
+    }
+
+    /**
+      *  Return the long value of this constant, or 0 if not set.
+     */
+    public long getLongValue() {
+        Object value = getValue();
+
+        return (value == null) ? 0L : ((Number) value).longValue();
+    }
+
+    /**
+      *  Return the float value of this constant, or 0 if not set.
+     */
+    public float getFloatValue() {
+        Object value = getValue();
+
+        return (value == null) ? 0F : ((Number) value).floatValue();
+    }
+
+    /**
+      *  Return the double value of this constant, or 0 if not set.
+     */
+    public double getDoubleValue() {
+        Object value = getValue();
+
+        return (value == null) ? 0D : ((Number) value).doubleValue();
+    }
+
+    /**
+      *  Return the class value of this constant, or null if not set.
+     */
+    public String getClassNameValue() {
+        return (String) getValue();
+    }
+
+    /**
+     *  Set this constant to null.
+      *
+     *  @return this instruction, for method chaining
+     */
+    public ConstantInstruction setNull() {
+        calculateOpcode(null, false);
+
+        return this;
+    }
+
+    /**
+      *  Set the value of this constant.
+      *
+     *  @return this instruction, for method chaining
+     */
+    public ConstantInstruction setValue(String value) {
+        calculateOpcode(value, false);
+
+        return this;
+    }
+
+    /**
+      *  Set the value of this constant.
+      *
+     *  @return this instruction, for method chaining
+     */
+    public ConstantInstruction setValue(Class value) {
+        calculateOpcode(value, false);
+
+        return this;
+    }
+
+    /**
+      *  Set the value of this constant.
+      *
+     *  @return this instruction, for method chaining
+     */
+    public ConstantInstruction setValue(BCClass value) {
+        calculateOpcode(value, false);
+
+        return this;
+    }
+
+    /**
+      *  Set the value of this constant.
+      *
+     *  @return this instruction, for method chaining
+     */
+    public ConstantInstruction setValue(int value) {
+        calculateOpcode(Numbers.valueOf(value), false);
+
+        return this;
+    }
+
+    /**
+      *  Set the value of this constant.
+      *
+     *  @return this instruction, for method chaining
+     */
+    public ConstantInstruction setValue(long value) {
+        calculateOpcode(Numbers.valueOf(value), false);
+
+        return this;
+    }
+
+    /**
+      *  Set the value of this constant.
+      *
+     *  @return this instruction, for method chaining
+     */
+    public ConstantInstruction setValue(float value) {
+        calculateOpcode(new Float(value), false);
+
+        return this;
+    }
+
+    /**
+      *  Set the value of this constant.
+      *
+     *  @return this instruction, for method chaining
+     */
+    public ConstantInstruction setValue(double value) {
+        calculateOpcode(new Double(value), false);
+
+        return this;
+    }
+
+    /**
+     *  Set the value of this constant; note that this type is converted
+     *  to int.
+      *
+     *  @return this instruction, for method chaining
+     */
+    public ConstantInstruction setValue(boolean value) {
+        return setValue((value) ? 1 : 0);
+    }
+
+    /**
+     *  Set the value of this constant; note that this type is converted
+     *  to int.
+      *
+     *  @return this instruction, for method chaining
+     */
+    public ConstantInstruction setValue(short value) {
+        return setValue((int) value);
+    }
+
+    /**
+     *  Set the value of this constant; note that this type is converted
+     *  to int.
+      *
+     *  @return this instruction, for method chaining
+     */
+    public ConstantInstruction setValue(char value) {
+        return setValue((int) value);
+    }
+
+    /**
+     *  ConstantInstructions are equal if the const they reference is the same,
+     *  or if the const of either is unset.
+     */
+    public boolean equalsInstruction(Instruction other) {
+        if (this == other) {
+            return true;
+        }
+
+        if (!(other instanceof ConstantInstruction)) {
+            return false;
+        }
+
+        Object value = getValue();
+        Object otherValue = ((ConstantInstruction) other).getValue();
+
+        return (value == null) || (otherValue == null) ||
+        value.equals(otherValue);
+    }
+
+    public void acceptVisit(BCVisitor visit) {
+        visit.enterConstantInstruction(this);
+        visit.exitConstantInstruction(this);
+    }
+
+    void read(Instruction orig) {
+        super.read(orig);
+
+        ConstantInstruction ci = (ConstantInstruction) orig;
+        calculateOpcode(ci.getValue(), ci.getOpcode() == Constants.LDCW);
+    }
+
+    void read(DataInput in) throws IOException {
+        super.read(in);
+
+        switch (getOpcode()) {
+        case Constants.BIPUSH:
+        case Constants.LDC:
+            _arg = in.readUnsignedByte();
+
+            break;
+
+        case Constants.SIPUSH:
+        case Constants.LDCW:
+        case Constants.LDC2W:
+            _arg = in.readUnsignedShort();
+        }
+    }
+
+    void write(DataOutput out) throws IOException {
+        super.write(out);
+
+        switch (getOpcode()) {
+        case Constants.BIPUSH:
+        case Constants.LDC:
+            out.writeByte(_arg);
+
+            break;
+
+        case Constants.SIPUSH:
+        case Constants.LDCW:
+        case Constants.LDC2W:
+            out.writeShort(_arg);
+
+            break;
+        }
+    }
+
+    private void calculateOpcode(Object value, boolean wide) {
+        _arg = -1;
+
+        if (value == null) {
+            setOpcode(Constants.ACONSTNULL);
+        } else if (value instanceof Float) {
+            float floatVal = ((Float) value).floatValue();
+
+            if ((floatVal == 0) || (floatVal == 1) || (floatVal == 2)) {
+                setOpcode(Constants.FCONST0 + (int) floatVal);
+            } else {
+                _arg = getPool().findFloatEntry((float) floatVal, true);
+                setOpcode(((_arg > 255) || wide) ? Constants.LDCW : Constants.LDC);
+            }
+        } else if (value instanceof Long) {
+            long longVal = ((Long) value).longValue();
+
+            if ((longVal == 0) || (longVal == 1)) {
+                setOpcode(Constants.LCONST0 + (int) longVal);
+            } else {
+                _arg = getPool().findLongEntry(longVal, true);
+                setOpcode(Constants.LDC2W);
+            }
+        } else if (value instanceof Double) {
+            double doubleVal = ((Double) value).doubleValue();
+
+            if ((doubleVal == 0) || (doubleVal == 1)) {
+                setOpcode(Constants.DCONST0 + (int) doubleVal);
+            } else {
+                _arg = getPool().findDoubleEntry(doubleVal, true);
+                setOpcode(Constants.LDC2W);
+            }
+        } else if (value instanceof Integer) {
+            int intVal = ((Integer) value).intValue();
+
+            if ((intVal >= -1) && (intVal <= 5)) {
+                setOpcode(Constants.ICONST0 + intVal);
+            } else if ((intVal >= -(2 << 6)) && (intVal < (2 << 6))) {
+                setOpcode(Constants.BIPUSH);
+                _arg = intVal;
+            } else if ((intVal >= -(2 << 14)) && (intVal < (2 << 14))) {
+                setOpcode(Constants.SIPUSH);
+                _arg = intVal;
+            } else {
+                _arg = getPool().findIntEntry(intVal, true);
+                setOpcode(((_arg > 255) || wide) ? Constants.LDCW : Constants.LDC);
+            }
+        } else if (value instanceof String) {
+            _arg = getPool().findStringEntry((String) value, true);
+            setOpcode(((_arg > 255) || wide) ? Constants.LDCW : Constants.LDC);
+        } else if (value instanceof Class) {
+            String name = getProject().getNameCache()
+                              .getInternalForm(((Class) value).getName(), false);
+            _arg = getPool().findClassEntry(name, true);
+            setOpcode(Constants.LDCW);
+        } else if (value instanceof BCClass) {
+            BCClass bc = (BCClass) value;
+            ClassEntry entry = (ClassEntry) bc.getPool().getEntry(bc.getIndex());
+
+            if (bc.getPool() == getPool()) {
+                _arg = getPool().indexOf(entry);
+            } else {
+                _arg = getPool()
+                           .findClassEntry((String) entry.getConstant(), true);
+            }
+
+            setOpcode(Constants.LDCW);
+        } else {
+            throw new IllegalArgumentException(String.valueOf(value));
+        }
+    }
+}

Propchange: incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/ConstantInstruction.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/ConstantValue.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/ConstantValue.java?rev=417860&view=auto
==============================================================================
--- incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/ConstantValue.java (added)
+++ incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/ConstantValue.java Wed Jun 28 12:46:13 2006
@@ -0,0 +1,263 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package serp.bytecode;
+
+import serp.bytecode.lowlevel.*;
+
+import serp.bytecode.visitor.*;
+
+import java.io.*;
+
+
+/**
+ *  <p>A constant value for a member field.</p>
+ *
+ *  @author Abe White
+ */
+public class ConstantValue extends Attribute {
+    int _valueIndex = 0;
+
+    ConstantValue(int nameIndex, Attributes owner) {
+        super(nameIndex, owner);
+    }
+
+    int getLength() {
+        return 2;
+    }
+
+    /**
+     *  Return the owning field.
+      */
+    public BCField getField() {
+        return (BCField) getOwner();
+    }
+
+    /**
+     *  Return the {@link ConstantPool} index of the {@link ConstantEntry}
+     *  holding the value of this constant.  Defaults to 0.
+     */
+    public int getValueIndex() {
+        return _valueIndex;
+    }
+
+    /**
+     *  Set the {@link ConstantPool} of the {@link ConstantEntry}
+     *  holding the value of this constant.
+     */
+    public void setValueIndex(int valueIndex) {
+        _valueIndex = valueIndex;
+    }
+
+    /**
+     *  Return the type of constant this attribute represents, or null if
+     *  not set.
+     */
+    public String getTypeName() {
+        Class type = getType();
+
+        if (type == null) {
+            return null;
+        }
+
+        return type.getName();
+    }
+
+    /**
+     *  Return the type of constant this attribute represents (String.class,
+     *  int.class, etc), or null if not set.
+     */
+    public Class getType() {
+        Object value = getValue();
+
+        if (value == null) {
+            return null;
+        }
+
+        Class type = value.getClass();
+
+        if (type == Integer.class) {
+            return int.class;
+        }
+
+        if (type == Float.class) {
+            return float.class;
+        }
+
+        if (type == Double.class) {
+            return double.class;
+        }
+
+        if (type == Long.class) {
+            return long.class;
+        }
+
+        return String.class;
+    }
+
+    /**
+     *  Return the bytecode for the type of constant this attribute
+     *  represents.
+     */
+    public BCClass getTypeBC() {
+        return getProject().loadClass(getType());
+    }
+
+    /**
+     *  Return the value of this constant as an Object of the appropriate
+     *  type (String, Integer, Double, etc), or null if not set.
+     */
+    public Object getValue() {
+        if (_valueIndex <= 0) {
+            return null;
+        }
+
+        return ((ConstantEntry) getPool().getEntry(_valueIndex)).getConstant();
+    }
+
+    /**
+     *  Set the value of this constant using the appropriate wrapper Object
+     *  type (String, Integer, Double, etc).  Types that are not directly
+     *  supported will be converted accordingly if possible.
+     */
+    public void setValue(Object value) {
+        Class type = value.getClass();
+
+        if (type == Boolean.class) {
+            setIntValue((((Boolean) value).booleanValue()) ? 1 : 0);
+        } else if (type == Character.class) {
+            setIntValue((int) ((Character) value).charValue());
+        } else if ((type == Byte.class) || (type == Integer.class) ||
+                (type == Short.class)) {
+            setIntValue(((Number) value).intValue());
+        } else if (type == Float.class) {
+            setFloatValue(((Number) value).floatValue());
+        } else if (type == Double.class) {
+            setDoubleValue(((Number) value).doubleValue());
+        } else if (type == Long.class) {
+            setLongValue(((Number) value).longValue());
+        } else {
+            setStringValue(value.toString());
+        }
+    }
+
+    /**
+     *  Get the value of this int constant, or 0 if not set.
+     */
+    public int getIntValue() {
+        if (getValueIndex() <= 0) {
+            return 0;
+        }
+
+        return ((IntEntry) getPool().getEntry(getValueIndex())).getValue();
+    }
+
+    /**
+     *  Set the value of this int constant.
+     */
+    public void setIntValue(int value) {
+        setValueIndex(getPool().findIntEntry(value, true));
+    }
+
+    /**
+     *  Get the value of this float constant.
+     */
+    public float getFloatValue() {
+        if (getValueIndex() <= 0) {
+            return 0F;
+        }
+
+        return ((FloatEntry) getPool().getEntry(getValueIndex())).getValue();
+    }
+
+    /**
+     *  Set the value of this float constant.
+     */
+    public void setFloatValue(float value) {
+        setValueIndex(getPool().findFloatEntry(value, true));
+    }
+
+    /**
+     *  Get the value of this double constant.
+     */
+    public double getDoubleValue() {
+        if (getValueIndex() <= 0) {
+            return 0D;
+        }
+
+        return ((DoubleEntry) getPool().getEntry(getValueIndex())).getValue();
+    }
+
+    /**
+     *  Set the value of this double constant.
+     */
+    public void setDoubleValue(double value) {
+        setValueIndex(getPool().findDoubleEntry(value, true));
+    }
+
+    /**
+     *  Get the value of this long constant.
+     */
+    public long getLongValue() {
+        if (getValueIndex() <= 0) {
+            return 0L;
+        }
+
+        return ((LongEntry) getPool().getEntry(getValueIndex())).getValue();
+    }
+
+    /**
+     *  Set the value of this long constant.
+     */
+    public void setLongValue(long value) {
+        setValueIndex(getPool().findLongEntry(value, true));
+    }
+
+    /**
+     *  Get the value of this string constant.
+     */
+    public String getStringValue() {
+        if (getValueIndex() <= 0) {
+            return null;
+        }
+
+        return ((StringEntry) getPool().getEntry(getValueIndex())).getStringEntry()
+                .getValue();
+    }
+
+    /**
+     *  Set the value of this string constant.
+     */
+    public void setStringValue(String value) {
+        setValueIndex(getPool().findStringEntry(value, true));
+    }
+
+    public void acceptVisit(BCVisitor visit) {
+        visit.enterConstantValue(this);
+        visit.exitConstantValue(this);
+    }
+
+    void read(Attribute other) {
+        setValue(((ConstantValue) other).getValue());
+    }
+
+    void read(DataInput in, int length) throws IOException {
+        setValueIndex(in.readUnsignedShort());
+    }
+
+    void write(DataOutput out, int length) throws IOException {
+        out.writeShort(getValueIndex());
+    }
+}

Propchange: incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/ConstantValue.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/Constants.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/Constants.java?rev=417860&view=auto
==============================================================================
--- incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/Constants.java (added)
+++ incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/Constants.java Wed Jun 28 12:46:13 2006
@@ -0,0 +1,324 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package serp.bytecode;
+
+
+/**
+ *  <p>Interface to track constants used in bytecode.  Entities can access these
+ *  constants using the static <code>Constants.</code> field prefix,
+ *  or implement this interface themselves to conveniently import the
+ *  constants into their own namespace.</p>
+ *
+ *  @author Abe White
+ */
+public interface Constants {
+    // class magic number
+    public static final int VALID_MAGIC = 0xcafebabe;
+
+    // standard major, minor versions
+    public static final int MAJOR_VERSION = 45;
+    public static final int MINOR_VERSION = 3;
+
+    // access constants for classes, fields, methods
+    public static final int ACCESS_PUBLIC = 0x0001;
+    public static final int ACCESS_PRIVATE = 0x0002;
+    public static final int ACCESS_PROTECTED = 0x0004;
+    public static final int ACCESS_STATIC = 0x0008;
+    public static final int ACCESS_FINAL = 0x0010;
+    public static final int ACCESS_SUPER = 0x0020;
+    public static final int ACCESS_SYNCHRONIZED = 0x0020;
+    public static final int ACCESS_VOLATILE = 0x0040;
+    public static final int ACCESS_TRANSIENT = 0x0080;
+    public static final int ACCESS_NATIVE = 0x0100;
+    public static final int ACCESS_INTERFACE = 0x0200;
+    public static final int ACCESS_ABSTRACT = 0x0400;
+    public static final int ACCESS_STRICT = 0x0800;
+
+    // attribute types the compiler must support
+    public static final String ATTR_CODE = "Code";
+    public static final String ATTR_CONST = "ConstantValue";
+    public static final String ATTR_DEPRECATED = "Deprecated";
+    public static final String ATTR_EXCEPTIONS = "Exceptions";
+    public static final String ATTR_INNERCLASS = "InnerClasses";
+    public static final String ATTR_LINENUMBERS = "LineNumberTable";
+    public static final String ATTR_LOCALS = "LocalVariableTable";
+    public static final String ATTR_LOCAL_TYPES = "LocalVariableTypeTable";
+    public static final String ATTR_SOURCE = "SourceFile";
+    public static final String ATTR_SYNTHETIC = "Synthetic";
+    public static final String ATTR_UNKNOWN = "Unknown";
+
+    // opcodes
+    public static final int NOP = 0;
+    public static final int ACONSTNULL = 1;
+    public static final int ICONSTM1 = 2;
+    public static final int ICONST0 = 3;
+    public static final int ICONST1 = 4;
+    public static final int ICONST2 = 5;
+    public static final int ICONST3 = 6;
+    public static final int ICONST4 = 7;
+    public static final int ICONST5 = 8;
+    public static final int LCONST0 = 9;
+    public static final int LCONST1 = 10;
+    public static final int FCONST0 = 11;
+    public static final int FCONST1 = 12;
+    public static final int FCONST2 = 13;
+    public static final int DCONST0 = 14;
+    public static final int DCONST1 = 15;
+    public static final int BIPUSH = 16;
+    public static final int SIPUSH = 17;
+    public static final int LDC = 18;
+    public static final int LDCW = 19;
+    public static final int LDC2W = 20;
+    public static final int ILOAD = 21;
+    public static final int LLOAD = 22;
+    public static final int FLOAD = 23;
+    public static final int DLOAD = 24;
+    public static final int ALOAD = 25;
+    public static final int ILOAD0 = 26;
+    public static final int ILOAD1 = 27;
+    public static final int ILOAD2 = 28;
+    public static final int ILOAD3 = 29;
+    public static final int LLOAD0 = 30;
+    public static final int LLOAD1 = 31;
+    public static final int LLOAD2 = 32;
+    public static final int LLOAD3 = 33;
+    public static final int FLOAD0 = 34;
+    public static final int FLOAD1 = 35;
+    public static final int FLOAD2 = 36;
+    public static final int FLOAD3 = 37;
+    public static final int DLOAD0 = 38;
+    public static final int DLOAD1 = 39;
+    public static final int DLOAD2 = 40;
+    public static final int DLOAD3 = 41;
+    public static final int ALOAD0 = 42;
+    public static final int ALOAD1 = 43;
+    public static final int ALOAD2 = 44;
+    public static final int ALOAD3 = 45;
+    public static final int IALOAD = 46;
+    public static final int LALOAD = 47;
+    public static final int FALOAD = 48;
+    public static final int DALOAD = 49;
+    public static final int AALOAD = 50;
+    public static final int BALOAD = 51;
+    public static final int CALOAD = 52;
+    public static final int SALOAD = 53;
+    public static final int ISTORE = 54;
+    public static final int LSTORE = 55;
+    public static final int FSTORE = 56;
+    public static final int DSTORE = 57;
+    public static final int ASTORE = 58;
+    public static final int ISTORE0 = 59;
+    public static final int ISTORE1 = 60;
+    public static final int ISTORE2 = 61;
+    public static final int ISTORE3 = 62;
+    public static final int LSTORE0 = 63;
+    public static final int LSTORE1 = 64;
+    public static final int LSTORE2 = 65;
+    public static final int LSTORE3 = 66;
+    public static final int FSTORE0 = 67;
+    public static final int FSTORE1 = 68;
+    public static final int FSTORE2 = 69;
+    public static final int FSTORE3 = 70;
+    public static final int DSTORE0 = 71;
+    public static final int DSTORE1 = 72;
+    public static final int DSTORE2 = 73;
+    public static final int DSTORE3 = 74;
+    public static final int ASTORE0 = 75;
+    public static final int ASTORE1 = 76;
+    public static final int ASTORE2 = 77;
+    public static final int ASTORE3 = 78;
+    public static final int IASTORE = 79;
+    public static final int LASTORE = 80;
+    public static final int FASTORE = 81;
+    public static final int DASTORE = 82;
+    public static final int AASTORE = 83;
+    public static final int BASTORE = 84;
+    public static final int CASTORE = 85;
+    public static final int SASTORE = 86;
+    public static final int POP = 87;
+    public static final int POP2 = 88;
+    public static final int DUP = 89;
+    public static final int DUPX1 = 90;
+    public static final int DUPX2 = 91;
+    public static final int DUP2 = 92;
+    public static final int DUP2X1 = 93;
+    public static final int DUP2X2 = 94;
+    public static final int SWAP = 95;
+    public static final int IADD = 96;
+    public static final int LADD = 97;
+    public static final int FADD = 98;
+    public static final int DADD = 99;
+    public static final int ISUB = 100;
+    public static final int LSUB = 101;
+    public static final int FSUB = 102;
+    public static final int DSUB = 103;
+    public static final int IMUL = 104;
+    public static final int LMUL = 105;
+    public static final int FMUL = 106;
+    public static final int DMUL = 107;
+    public static final int IDIV = 108;
+    public static final int LDIV = 109;
+    public static final int FDIV = 110;
+    public static final int DDIV = 111;
+    public static final int IREM = 112;
+    public static final int LREM = 113;
+    public static final int FREM = 114;
+    public static final int DREM = 115;
+    public static final int INEG = 116;
+    public static final int LNEG = 117;
+    public static final int FNEG = 118;
+    public static final int DNEG = 119;
+    public static final int ISHL = 120;
+    public static final int LSHL = 121;
+    public static final int ISHR = 122;
+    public static final int LSHR = 123;
+    public static final int IUSHR = 124;
+    public static final int LUSHR = 125;
+    public static final int IAND = 126;
+    public static final int LAND = 127;
+    public static final int IOR = 128;
+    public static final int LOR = 129;
+    public static final int IXOR = 130;
+    public static final int LXOR = 131;
+    public static final int IINC = 132;
+    public static final int I2L = 133;
+    public static final int I2F = 134;
+    public static final int I2D = 135;
+    public static final int L2I = 136;
+    public static final int L2F = 137;
+    public static final int L2D = 138;
+    public static final int F2I = 139;
+    public static final int F2L = 140;
+    public static final int F2D = 141;
+    public static final int D2I = 142;
+    public static final int D2L = 143;
+    public static final int D2F = 144;
+    public static final int I2B = 145;
+    public static final int I2C = 146;
+    public static final int I2S = 147;
+    public static final int LCMP = 148;
+    public static final int FCMPL = 149;
+    public static final int FCMPG = 150;
+    public static final int DCMPL = 151;
+    public static final int DCMPG = 152;
+    public static final int IFEQ = 153;
+    public static final int IFNE = 154;
+    public static final int IFLT = 155;
+    public static final int IFGE = 156;
+    public static final int IFGT = 157;
+    public static final int IFLE = 158;
+    public static final int IFICMPEQ = 159;
+    public static final int IFICMPNE = 160;
+    public static final int IFICMPLT = 161;
+    public static final int IFICMPGE = 162;
+    public static final int IFICMPGT = 163;
+    public static final int IFICMPLE = 164;
+    public static final int IFACMPEQ = 165;
+    public static final int IFACMPNE = 166;
+    public static final int GOTO = 167;
+    public static final int JSR = 168;
+    public static final int RET = 169;
+    public static final int TABLESWITCH = 170;
+    public static final int LOOKUPSWITCH = 171;
+    public static final int IRETURN = 172;
+    public static final int LRETURN = 173;
+    public static final int FRETURN = 174;
+    public static final int DRETURN = 175;
+    public static final int ARETURN = 176;
+    public static final int RETURN = 177;
+    public static final int GETSTATIC = 178;
+    public static final int PUTSTATIC = 179;
+    public static final int GETFIELD = 180;
+    public static final int PUTFIELD = 181;
+    public static final int INVOKEVIRTUAL = 182;
+    public static final int INVOKESPECIAL = 183;
+    public static final int INVOKESTATIC = 184;
+    public static final int INVOKEINTERFACE = 185;
+    public static final int NEW = 187;
+    public static final int NEWARRAY = 188;
+    public static final int ANEWARRAY = 189;
+    public static final int ARRAYLENGTH = 190;
+    public static final int ATHROW = 191;
+    public static final int CHECKCAST = 192;
+    public static final int INSTANCEOF = 193;
+    public static final int MONITORENTER = 194;
+    public static final int MONITOREXIT = 195;
+    public static final int WIDE = 196;
+    public static final int MULTIANEWARRAY = 197;
+    public static final int IFNULL = 198;
+    public static final int IFNONNULL = 199;
+    public static final int GOTOW = 200;
+    public static final int JSRW = 201;
+
+    // array types
+    public static final int ARRAY_BOOLEAN = 4;
+    public static final int ARRAY_CHAR = 5;
+    public static final int ARRAY_FLOAT = 6;
+    public static final int ARRAY_DOUBLE = 7;
+    public static final int ARRAY_BYTE = 8;
+    public static final int ARRAY_SHORT = 9;
+    public static final int ARRAY_INT = 10;
+    public static final int ARRAY_LONG = 11;
+
+    // math operations
+    public static final int MATH_ADD = IADD;
+    public static final int MATH_SUB = ISUB;
+    public static final int MATH_MUL = IMUL;
+    public static final int MATH_DIV = IDIV;
+    public static final int MATH_REM = IREM;
+    public static final int MATH_NEG = INEG;
+    public static final int MATH_SHL = ISHL;
+    public static final int MATH_SHR = ISHR;
+    public static final int MATH_USHR = IUSHR;
+    public static final int MATH_AND = IAND;
+    public static final int MATH_OR = IOR;
+    public static final int MATH_XOR = IXOR;
+
+    // human-readable opcode names
+    public static final String[] OPCODE_NAMES = new String[] {
+            "nop", "aconstnull", "iconstm1", "iconst0", "iconst1", "iconst2",
+            "iconst3", "iconst4", "iconst5", "lconst0", "lconst1", "fconst0",
+            "fconst1", "fconst2", "dconst0", "dconst1", "bipush", "sipush",
+            "ldc", "ldcw", "ldc2w", "iload", "lload", "fload", "dload", "aload",
+            "iload0", "iload1", "iload2", "iload3", "lload0", "lload1", "lload2",
+            "lload3", "fload0", "fload1", "fload2", "fload3", "dload0", "dload1",
+            "dload2", "dload3", "aload0", "aload1", "aload2", "aload3", "iaload",
+            "laload", "faload", "daload", "aaload", "baload", "caload", "saload",
+            "istore", "lstore", "fstore", "dstore", "astore", "istore0",
+            "istore1", "istore2", "istore3", "lstore0", "lstore1", "lstore2",
+            "lstore3", "fstore0", "fstore1", "fstore2", "fstore3", "dstore0",
+            "dstore1", "dstore2", "dstore3", "astore0", "astore1", "astore2",
+            "astore3", "iastore", "lastore", "fastore", "dastore", "aastore",
+            "bastore", "castore", "sastore", "pop", "pop2", "dup", "dupx1",
+            "dupx2", "dup2", "dup2x1", "dup2x2", "swap", "iadd", "ladd", "fadd",
+            "dadd", "isub", "lsub", "fsub", "dsub", "imul", "lmul", "fmul",
+            "dmul", "idiv", "ldiv", "fdiv", "ddiv", "irem", "lrem", "frem",
+            "drem", "ineg", "lneg", "fneg", "dneg", "ishl", "lshl", "ishr",
+            "lshr", "iushr", "lushr", "iand", "land", "ior", "lor", "ixor",
+            "lxor", "iinc", "i2l", "i2f", "i2d", "l2i", "l2f", "l2d", "f2i",
+            "f2l", "f2d", "d2i", "d2l", "d2f", "i2b", "i2c", "i2s", "lcmp",
+            "fcmpl", "fcmpg", "dcmpl", "dcmpg", "ifeq", "ifne", "iflt", "ifge",
+            "ifgt", "ifle", "ificmpeq", "ificmpne", "ificmplt", "ificmpge",
+            "ificmpgt", "ificmple", "ifacmpeq", "ifacmpne", "goto", "jsr", "ret",
+            "tableswitch", "lookupswitch", "ireturn", "lreturn", "freturn",
+            "dreturn", "areturn", "return", "getstatic", "putstatic", "getfield",
+            "putfield", "invokevirtual", "invokespecial", "invokestatic",
+            "invokeinterface", "??", "new", "newarray", "anewarray",
+            "arraylength", "athrow", "checkcast", "instanceof", "monitorenter",
+            "monitorexit", "wide", "multianewarray", "ifnull", "ifnonnull",
+            "gotow", "jsrw",
+        };
+}

Propchange: incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/Constants.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/ConvertInstruction.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/ConvertInstruction.java?rev=417860&view=auto
==============================================================================
--- incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/ConvertInstruction.java (added)
+++ incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/ConvertInstruction.java Wed Jun 28 12:46:13 2006
@@ -0,0 +1,440 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package serp.bytecode;
+
+import serp.bytecode.visitor.*;
+
+import serp.util.*;
+
+import java.util.*;
+
+
+/**
+ *  <p>A conversion opcode such as <code>i2l, f2i</code>, etc.
+ *  Changing the types of the instruction will automatically
+ *  update the underlying opcode.  Converting from one type to the same
+ *  type will result in a <code>nop</code>.</p>
+ *
+ *  @author Abe White
+ */
+public class ConvertInstruction extends TypedInstruction {
+    private static final Class[][] _mappings = new Class[][] {
+            { boolean.class, int.class },
+            { void.class, int.class },
+            { Object.class, int.class },
+        };
+    private static final Class[][] _fromMappings = new Class[][] {
+            { boolean.class, int.class },
+            { void.class, int.class },
+            { Object.class, int.class },
+            { byte.class, int.class },
+            { char.class, int.class },
+            { short.class, int.class },
+        };
+    String _toType = null;
+    String _fromType = null;
+
+    ConvertInstruction(Code owner) {
+        super(owner);
+    }
+
+    ConvertInstruction(Code owner, int opcode) {
+        super(owner, opcode);
+    }
+
+    public int getLogicalStackChange() {
+        return 0;
+    }
+
+    public int getStackChange() {
+        switch (getOpcode()) {
+        case Constants.I2L:
+        case Constants.I2D:
+        case Constants.F2L:
+        case Constants.F2D:
+            return 1;
+
+        case Constants.L2I:
+        case Constants.L2F:
+        case Constants.D2I:
+        case Constants.D2F:
+            return -1;
+
+        default:
+            return 0;
+        }
+    }
+
+    public String getTypeName() {
+        switch (getOpcode()) {
+        case Constants.L2I:
+        case Constants.F2I:
+        case Constants.D2I:
+            return int.class.getName();
+
+        case Constants.I2L:
+        case Constants.F2L:
+        case Constants.D2L:
+            return long.class.getName();
+
+        case Constants.I2F:
+        case Constants.L2F:
+        case Constants.D2F:
+            return float.class.getName();
+
+        case Constants.I2D:
+        case Constants.L2D:
+        case Constants.F2D:
+            return double.class.getName();
+
+        case Constants.I2B:
+            return byte.class.getName();
+
+        case Constants.I2C:
+            return char.class.getName();
+
+        case Constants.I2S:
+            return short.class.getName();
+
+        default:
+            return _toType;
+        }
+    }
+
+    public TypedInstruction setType(String type) {
+        String toType = mapType(type, _mappings, true);
+        String fromType = getFromTypeName();
+
+        // if no valid opcode, remember current types in case they reset one
+        // to create a valid opcode
+        if ((toType == null) || (fromType == null) || toType.equals(fromType)) {
+            _toType = toType;
+            _fromType = fromType;
+
+            return (TypedInstruction) setOpcode(Constants.NOP);
+        }
+
+        // ok, valid conversion possible, forget saved types
+        _toType = null;
+        _fromType = null;
+
+        char to = toType.charAt(0);
+        char from = fromType.charAt(0);
+
+        switch (to) {
+        case 'i':
+
+            switch (from) {
+            case 'l':
+                return (TypedInstruction) setOpcode(Constants.L2I);
+
+            case 'f':
+                return (TypedInstruction) setOpcode(Constants.F2I);
+
+            case 'd':
+                return (TypedInstruction) setOpcode(Constants.D2I);
+            }
+
+        case 'l':
+
+            switch (from) {
+            case 'i':
+                return (TypedInstruction) setOpcode(Constants.I2L);
+
+            case 'f':
+                return (TypedInstruction) setOpcode(Constants.F2L);
+
+            case 'd':
+                return (TypedInstruction) setOpcode(Constants.D2L);
+            }
+
+        case 'f':
+
+            switch (from) {
+            case 'i':
+                return (TypedInstruction) setOpcode(Constants.I2F);
+
+            case 'l':
+                return (TypedInstruction) setOpcode(Constants.L2F);
+
+            case 'd':
+                return (TypedInstruction) setOpcode(Constants.D2F);
+            }
+
+        case 'd':
+
+            switch (from) {
+            case 'i':
+                return (TypedInstruction) setOpcode(Constants.I2D);
+
+            case 'l':
+                return (TypedInstruction) setOpcode(Constants.L2D);
+
+            case 'f':
+                return (TypedInstruction) setOpcode(Constants.F2D);
+            }
+
+        case 'b':
+
+            if (from == 'i') {
+                return (TypedInstruction) setOpcode(Constants.I2B);
+            }
+
+        case 'C':
+
+            if (from == 'i') {
+                return (TypedInstruction) setOpcode(Constants.I2C);
+            }
+
+        case 'S':
+
+            if (from == 'i') {
+                return (TypedInstruction) setOpcode(Constants.I2S);
+            }
+
+        default:
+            throw new IllegalStateException();
+        }
+    }
+
+    /**
+     *  Return the name of the type being converted from.
+     *  If neither type has been set, this method will return null.
+     */
+    public String getFromTypeName() {
+        switch (getOpcode()) {
+        case Constants.I2L:
+        case Constants.I2F:
+        case Constants.I2D:
+        case Constants.I2B:
+        case Constants.I2S:
+        case Constants.I2C:
+            return int.class.getName();
+
+        case Constants.L2I:
+        case Constants.L2F:
+        case Constants.L2D:
+            return long.class.getName();
+
+        case Constants.F2I:
+        case Constants.F2L:
+        case Constants.F2D:
+            return float.class.getName();
+
+        case Constants.D2I:
+        case Constants.D2L:
+        case Constants.D2F:
+            return double.class.getName();
+
+        default:
+            return _fromType;
+        }
+    }
+
+    /**
+     *  Return the {@link Class} of the type being converted from.
+     *  If neither type has been set, this method will return null.
+     */
+    public Class getFromType() {
+        String type = getFromTypeName();
+
+        if (type == null) {
+            return null;
+        }
+
+        return Strings.toClass(type, getClassLoader());
+    }
+
+    /**
+     *  Return the bytecode of the type being converted from.
+     *  If neither type has been set, this method will return null.
+     */
+    public BCClass getFromTypeBC() {
+        String type = getFromTypeName();
+
+        if (type == null) {
+            return null;
+        }
+
+        return getProject().loadClass(type, getClassLoader());
+    }
+
+    /**
+     *  Set the type being converted from.  Types that have no direct
+     *  support will be converted accordingly.
+     *
+     *  @return this instruction, for method chaining
+     */
+    public ConvertInstruction setFromType(String type) {
+        String fromType = mapType(type, _fromMappings, true);
+        String toType = getTypeName();
+
+        // if no valid opcode, remember current types in case they reset one
+        // to create a valid opcode
+        if ((toType == null) || (fromType == null) || toType.equals(fromType)) {
+            _toType = toType;
+            _fromType = fromType;
+
+            return (ConvertInstruction) setOpcode(Constants.NOP);
+        }
+
+        // ok, valid conversion possible, forget saved types
+        _toType = null;
+        _fromType = null;
+
+        char to = toType.charAt(0);
+        char from = fromType.charAt(0);
+
+        switch (from) {
+        case 'i':
+
+            switch (to) {
+            case 'l':
+                return (ConvertInstruction) setOpcode(Constants.I2L);
+
+            case 'f':
+                return (ConvertInstruction) setOpcode(Constants.I2F);
+
+            case 'd':
+                return (ConvertInstruction) setOpcode(Constants.I2D);
+
+            case 'b':
+                return (ConvertInstruction) setOpcode(Constants.I2B);
+
+            case 'c':
+                return (ConvertInstruction) setOpcode(Constants.I2C);
+
+            case 's':
+                return (ConvertInstruction) setOpcode(Constants.I2S);
+            }
+
+        case 'l':
+
+            switch (to) {
+            case 'i':
+                return (ConvertInstruction) setOpcode(Constants.L2I);
+
+            case 'f':
+                return (ConvertInstruction) setOpcode(Constants.L2F);
+
+            case 'd':
+                return (ConvertInstruction) setOpcode(Constants.L2D);
+            }
+
+        case 'f':
+
+            switch (to) {
+            case 'i':
+                return (ConvertInstruction) setOpcode(Constants.F2I);
+
+            case 'l':
+                return (ConvertInstruction) setOpcode(Constants.F2L);
+
+            case 'd':
+                return (ConvertInstruction) setOpcode(Constants.F2D);
+            }
+
+        case 'd':
+
+            switch (to) {
+            case 'i':
+                return (ConvertInstruction) setOpcode(Constants.D2I);
+
+            case 'l':
+                return (ConvertInstruction) setOpcode(Constants.D2L);
+
+            case 'f':
+                return (ConvertInstruction) setOpcode(Constants.D2F);
+            }
+
+        default:
+            throw new IllegalStateException();
+        }
+    }
+
+    /**
+     *  Set the type being converted from.  Types that have no direct
+     *  support will be converted accordingly.
+     *
+     *  @return this instruction, for method chaining
+     */
+    public ConvertInstruction setFromType(Class type) {
+        if (type == null) {
+            return setFromType((String) null);
+        }
+
+        return setFromType(type.getName());
+    }
+
+    /**
+     *  Set the type being converted from.  Types that have no direct
+     *  support will be converted accordingly.
+     *
+     *  @return this instruction, for method chaining
+     */
+    public ConvertInstruction setFromType(BCClass type) {
+        if (type == null) {
+            return setFromType((String) null);
+        }
+
+        return setFromType(type.getName());
+    }
+
+    /**
+     *  ConvertInstructions are equal if the types they convert between are
+     *  either equal or unset.
+     */
+    public boolean equalsInstruction(Instruction other) {
+        if (other == this) {
+            return true;
+        }
+
+        if (!(other instanceof ConvertInstruction)) {
+            return false;
+        }
+
+        ConvertInstruction ins = (ConvertInstruction) other;
+
+        if ((getOpcode() != Constants.NOP) && (getOpcode() == ins.getOpcode())) {
+            return true;
+        }
+
+        String type = getTypeName();
+        String otherType = ins.getTypeName();
+
+        if (!((type == null) || (otherType == null) || type.equals(otherType))) {
+            return false;
+        }
+
+        type = getFromTypeName();
+        otherType = ins.getFromTypeName();
+
+        return (type == null) || (otherType == null) || type.equals(otherType);
+    }
+
+    public void acceptVisit(BCVisitor visit) {
+        visit.enterConvertInstruction(this);
+        visit.exitConvertInstruction(this);
+    }
+
+    void read(Instruction orig) {
+        super.read(orig);
+
+        ConvertInstruction ins = (ConvertInstruction) orig;
+        _toType = ins._toType;
+        _fromType = ins._fromType;
+    }
+}

Propchange: incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/ConvertInstruction.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/Deprecated.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/Deprecated.java?rev=417860&view=auto
==============================================================================
--- incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/Deprecated.java (added)
+++ incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/Deprecated.java Wed Jun 28 12:46:13 2006
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package serp.bytecode;
+
+import serp.bytecode.visitor.*;
+
+
+/**
+ *  <p>Attribute signifying that a method or class is deprecated.</p>
+ *
+ *  @author Abe White
+ */
+public class Deprecated extends Attribute {
+    Deprecated(int nameIndex, Attributes owner) {
+        super(nameIndex, owner);
+    }
+
+    public void acceptVisit(BCVisitor visit) {
+        visit.enterDeprecated(this);
+        visit.exitDeprecated(this);
+    }
+}

Propchange: incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/Deprecated.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/ExceptionHandler.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/ExceptionHandler.java?rev=417860&view=auto
==============================================================================
--- incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/ExceptionHandler.java (added)
+++ incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/ExceptionHandler.java Wed Jun 28 12:46:13 2006
@@ -0,0 +1,310 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package serp.bytecode;
+
+import serp.bytecode.lowlevel.*;
+
+import serp.bytecode.visitor.*;
+
+import serp.util.*;
+
+import java.io.*;
+
+import java.util.*;
+
+
+/**
+ *  <p>Represents a <code>try {} catch() {}</code> statement in bytecode.</p>
+ *
+ *  @author Abe White
+ */
+public class ExceptionHandler implements InstructionPtr, BCEntity,
+    VisitAcceptor {
+    private int _catchIndex = 0;
+    private Code _owner = null;
+    private InstructionPtrStrategy _tryStart = new InstructionPtrStrategy(this);
+    private InstructionPtrStrategy _tryEnd = new InstructionPtrStrategy(this);
+    private InstructionPtrStrategy _tryHandler = new InstructionPtrStrategy(this);
+
+    ExceptionHandler(Code owner) {
+        _owner = owner;
+    }
+
+    /**
+     *  Return the owning code block.
+     */
+    public Code getCode() {
+        return _owner;
+    }
+
+    ///////////////////
+    // Body operations
+    ///////////////////
+
+    /**
+      *  Return the instruction marking the beginning of the try {} block.
+     */
+    public Instruction getTryStart() {
+        return _tryStart.getTargetInstruction();
+    }
+
+    /**
+     *  Set the {@link Instruction} marking the beginning of the try block.
+     *  The instruction must already be a part of the method.
+     */
+    public void setTryStart(Instruction instruction) {
+        _tryStart.setTargetInstruction(instruction);
+    }
+
+    /**
+      *  Return the instruction at the end of the try {} block.
+     */
+    public Instruction getTryEnd() {
+        return _tryEnd.getTargetInstruction();
+    }
+
+    /**
+     *  Set the Instruction at the end of the try block.  The
+     *  Instruction must already be a part of the method.
+     */
+    public void setTryEnd(Instruction instruction) {
+        _tryEnd.setTargetInstruction(instruction);
+    }
+
+    //////////////////////
+    // Handler operations
+    //////////////////////
+
+    /**
+      *  Return the instruction marking the beginning of the catch {} block.
+     */
+    public Instruction getHandlerStart() {
+        return _tryHandler.getTargetInstruction();
+    }
+
+    /**
+     *  Set the {@link Instruction} marking the beginning of the catch block.
+     *  The instruction must already be a part of the method.
+     *  WARNING: if this instruction is deleted, the results are undefined.
+     */
+    public void setHandlerStart(Instruction instruction) {
+        _tryHandler.setTargetInstruction(instruction);
+    }
+
+    ////////////////////
+    // Catch operations
+    ////////////////////
+
+    /**
+     *  Return the index into the class {@link ConstantPool} of the
+     *  {@link ClassEntry} describing the exception type this handler catches.
+     */
+    public int getCatchIndex() {
+        return _catchIndex;
+    }
+
+    /**
+     *  Set the index into the class {@link ConstantPool} of the
+     *  {@link ClassEntry} describing the exception type this handler catches.
+     */
+    public void setCatchIndex(int catchTypeIndex) {
+        _catchIndex = catchTypeIndex;
+    }
+
+    /**
+     *  Return the name of the exception type; returns null for catch-all
+     *  clauses used to implement finally blocks.  The name will be returned
+     *  in a forum suitable for a {@link Class#forName} call.
+     */
+    public String getCatchName() {
+        if (_catchIndex == 0) {
+            return null;
+        }
+
+        ClassEntry entry = (ClassEntry) getPool().getEntry(_catchIndex);
+
+        return getProject().getNameCache()
+                   .getExternalForm(entry.getNameEntry().getValue(), false);
+    }
+
+    /**
+     *  Return the {@link Class} of the exception type; returns null for
+     *  catch-all clauses used to implement finally blocks.
+     */
+    public Class getCatchType() {
+        String name = getCatchName();
+
+        if (name == null) {
+            return null;
+        }
+
+        return Strings.toClass(name, getClassLoader());
+    }
+
+    /**
+     *  Return the bytecode of the exception type; returns null for
+     *  catch-all clauses used to implement finally blocks.
+     */
+    public BCClass getCatchBC() {
+        String name = getCatchName();
+
+        if (name == null) {
+            return null;
+        }
+
+        return getProject().loadClass(name, getClassLoader());
+    }
+
+    /**
+     *  Set the class of the exception type, or null for catch-all clauses used
+     *  with finally blocks.
+     */
+    public void setCatch(String name) {
+        if (name == null) {
+            _catchIndex = 0;
+        } else {
+            _catchIndex = getPool()
+                              .findClassEntry(getProject().getNameCache()
+                                                  .getInternalForm(name, false),
+                    true);
+        }
+    }
+
+    /**
+     *  Set the class of the exception type, or null for catch-all clauses used
+     *  for finally blocks.
+     */
+    public void setCatch(Class type) {
+        if (type == null) {
+            setCatch((String) null);
+        } else {
+            setCatch(type.getName());
+        }
+    }
+
+    /**
+     *  Set the class of the exception type, or null for catch-all clauses used
+     *  for finally blocks.
+     */
+    public void setCatch(BCClass type) {
+        if (type == null) {
+            setCatch((String) null);
+        } else {
+            setCatch(type.getName());
+        }
+    }
+
+    /////////////////////////////////
+    // InstructionPtr implementation
+    /////////////////////////////////
+    public void updateTargets() {
+        _tryStart.updateTargets();
+        _tryEnd.updateTargets();
+        _tryHandler.updateTargets();
+    }
+
+    public void replaceTarget(Instruction oldTarget, Instruction newTarget) {
+        _tryStart.replaceTarget(oldTarget, newTarget);
+        _tryEnd.replaceTarget(oldTarget, newTarget);
+        _tryHandler.replaceTarget(oldTarget, newTarget);
+    }
+
+    ///////////////////////////
+    // BCEntity implementation
+    ///////////////////////////
+    public Project getProject() {
+        return _owner.getProject();
+    }
+
+    public ConstantPool getPool() {
+        return _owner.getPool();
+    }
+
+    public ClassLoader getClassLoader() {
+        return _owner.getClassLoader();
+    }
+
+    public boolean isValid() {
+        return _owner != null;
+    }
+
+    ////////////////////////////////
+    // VisitAcceptor implementation
+    ////////////////////////////////
+    public void acceptVisit(BCVisitor visit) {
+        visit.enterExceptionHandler(this);
+        visit.exitExceptionHandler(this);
+    }
+
+    //////////////////
+    // I/O operations
+    //////////////////
+    void read(ExceptionHandler orig) {
+        _tryStart.setByteIndex(orig._tryStart.getByteIndex());
+        _tryEnd.setByteIndex(orig._tryEnd.getByteIndex());
+        _tryHandler.setByteIndex(orig._tryHandler.getByteIndex());
+
+        // done at a high level so that if the name isn't in our constant pool,
+        // it will be added
+        setCatch(orig.getCatchName());
+    }
+
+    void read(DataInput in) throws IOException {
+        setTryStart(in.readUnsignedShort());
+        setTryEnd(in.readUnsignedShort());
+        setHandlerStart(in.readUnsignedShort());
+        setCatchIndex(in.readUnsignedShort());
+    }
+
+    void write(DataOutput out) throws IOException {
+        out.writeShort(getTryStartPc());
+        out.writeShort(getTryEndPc());
+        out.writeShort(getHandlerStartPc());
+        out.writeShort(getCatchIndex());
+    }
+
+    public void setTryStart(int start) {
+        _tryStart.setByteIndex(start);
+    }
+
+    public int getTryStartPc() {
+        return _tryStart.getByteIndex();
+    }
+
+    public void setTryEnd(int end) {
+        setTryEnd((Instruction) _owner.getInstruction(end).prev);
+    }
+
+    /**
+     *  Return the program counter end position for this exception handler.
+     *  This represents an index into the code byte array.
+     */
+    public int getTryEndPc() {
+        return _tryEnd.getByteIndex() + getTryEnd().getLength();
+    }
+
+    public void setHandlerStart(int handler) {
+        _tryHandler.setByteIndex(handler);
+    }
+
+    public int getHandlerStartPc() {
+        return _tryHandler.getByteIndex();
+    }
+
+    void invalidate() {
+        _owner = null;
+    }
+}

Propchange: incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/ExceptionHandler.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/Exceptions.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/Exceptions.java?rev=417860&view=auto
==============================================================================
--- incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/Exceptions.java (added)
+++ incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/Exceptions.java Wed Jun 28 12:46:13 2006
@@ -0,0 +1,330 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package serp.bytecode;
+
+import serp.bytecode.lowlevel.*;
+
+import serp.bytecode.visitor.*;
+
+import serp.util.*;
+
+import java.io.*;
+
+import java.util.*;
+
+
+/**
+ *  <p>Attribute declaring the checked exceptions a method can throw.</p>
+ *
+ *  @author Abe White
+ */
+public class Exceptions extends Attribute {
+    private List _indexes = new LinkedList();
+
+    Exceptions(int nameIndex, Attributes owner) {
+        super(nameIndex, owner);
+    }
+
+    int getLength() {
+        return 2 + (2 * _indexes.size());
+    }
+
+    /**
+     *  Return the owning method.
+     */
+    public BCMethod getMethod() {
+        return (BCMethod) getOwner();
+    }
+
+    /**
+      *  Return the indexes in the class {@link ConstantPool} of the
+     *  {@link ClassEntry}s        for the exception types thrown by this method, or
+     *  an empty array if none.
+     */
+    public int[] getExceptionIndexes() {
+        int[] indexes = new int[_indexes.size()];
+        Iterator itr = _indexes.iterator();
+
+        for (int i = 0; i < indexes.length; i++)
+            indexes[i] = ((Integer) itr.next()).intValue();
+
+        return indexes;
+    }
+
+    /**
+      *  Set the indexes in the class {@link ConstantPool} of the
+     *  {@link ClassEntry}s        for the exception types thrown by this method.  Use
+     *  null or an empty array for none.
+     */
+    public void setExceptionIndexes(int[] exceptionIndexes) {
+        _indexes.clear();
+
+        if (exceptionIndexes != null) {
+            for (int i = 0; i < exceptionIndexes.length; i++)
+                _indexes.add(Numbers.valueOf(exceptionIndexes[i]));
+        }
+    }
+
+    /**
+     *  Return the names of the exception types for this method, or an empty
+     *  array if none.  The names will be in a form suitable for a
+     *  {@link Class#forName} call.
+     */
+    public String[] getExceptionNames() {
+        String[] names = new String[_indexes.size()];
+        Iterator itr = _indexes.iterator();
+        int index;
+        ClassEntry entry;
+
+        for (int i = 0; i < names.length; i++) {
+            index = ((Number) itr.next()).intValue();
+            entry = (ClassEntry) getPool().getEntry(index);
+            names[i] = getProject().getNameCache()
+                           .getExternalForm(entry.getNameEntry().getValue(),
+                    false);
+        }
+
+        return names;
+    }
+
+    /**
+     *  Return the {@link Class} objects for the exception types for this
+     *  method, or an empty        array if none.
+     */
+    public Class[] getExceptionTypes() {
+        String[] names = getExceptionNames();
+        Class[] types = new Class[names.length];
+
+        for (int i = 0; i < names.length; i++)
+            types[i] = Strings.toClass(names[i], getClassLoader());
+
+        return types;
+    }
+
+    /**
+     *  Return bytecode for the exception types of this
+     *  method, or an empty        array if none.
+     */
+    public BCClass[] getExceptionBCs() {
+        String[] names = getExceptionNames();
+        BCClass[] types = new BCClass[names.length];
+
+        for (int i = 0; i < names.length; i++)
+            types[i] = getProject().loadClass(names[i], getClassLoader());
+
+        return types;
+    }
+
+    /**
+     *  Set the checked exceptions thrown by this method.  Use null or an
+     *  empty array for none.
+     */
+    public void setExceptions(String[] exceptions) {
+        if (exceptions != null) {
+            for (int i = 0; i < exceptions.length; i++)
+                if (exceptions[i] == null) {
+                    throw new NullPointerException("exceptions[" + i +
+                        "] = null");
+                }
+        }
+
+        clear();
+
+        if (exceptions != null) {
+            for (int i = 0; i < exceptions.length; i++)
+                addException(exceptions[i]);
+        }
+    }
+
+    /**
+     *  Set the checked exceptions thrown by this method.  Use null or an
+     *  empty array for none.
+     */
+    public void setExceptions(Class[] exceptions) {
+        String[] names = null;
+
+        if (exceptions != null) {
+            names = new String[exceptions.length];
+
+            for (int i = 0; i < exceptions.length; i++)
+                names[i] = exceptions[i].getName();
+        }
+
+        setExceptions(names);
+    }
+
+    /**
+     *  Set the checked exceptions thrown by this method.  Use null or an
+     *  empty array for none.
+     */
+    public void setExceptions(BCClass[] exceptions) {
+        String[] names = null;
+
+        if (exceptions != null) {
+            names = new String[exceptions.length];
+
+            for (int i = 0; i < exceptions.length; i++)
+                names[i] = exceptions[i].getName();
+        }
+
+        setExceptions(names);
+    }
+
+    /**
+     *  Clear this method of all exception declarations.
+     */
+    public void clear() {
+        _indexes.clear();
+    }
+
+    /**
+     *  Remove an exception type thrown by this method.
+     *
+     *  @return true if the method had the exception type, false otherwise
+     */
+    public boolean removeException(String type) {
+        String internalForm = getProject().getNameCache()
+                                  .getInternalForm(type, false);
+        ClassEntry entry;
+
+        for (Iterator itr = _indexes.iterator(); itr.hasNext();) {
+            entry = (ClassEntry) getPool()
+                                     .getEntry(((Integer) itr.next()).intValue());
+
+            if (entry.getNameEntry().getValue().equals(internalForm)) {
+                itr.remove();
+
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     *  Remove an exception thrown by this method.
+     *
+     *  @return true if the method had the exception type, false otherwise
+     */
+    public boolean removeException(Class type) {
+        if (type == null) {
+            return false;
+        }
+
+        return removeException(type.getName());
+    }
+
+    /**
+     *  Remove an exception thrown by this method.
+     *
+     *  @return true if the method had the exception type, false otherwise
+     */
+    public boolean removeException(BCClass type) {
+        if (type == null) {
+            return false;
+        }
+
+        return removeException(type.getName());
+    }
+
+    /**
+      *  Add an exception type to those thrown by this method.
+     */
+    public void addException(String type) {
+        int index = getPool()
+                        .findClassEntry(getProject().getNameCache()
+                                            .getInternalForm(type, false), true);
+        _indexes.add(Numbers.valueOf(index));
+    }
+
+    /**
+      *  Add an exception to those thrown by this method.
+     */
+    public void addException(Class type) {
+        addException(type.getName());
+    }
+
+    /**
+      *  Add an exception to those thrown by this method.
+     */
+    public void addException(BCClass type) {
+        addException(type.getName());
+    }
+
+    /**
+     *  Return true if the method declares that it throws the given
+     *  exception type.
+     */
+    public boolean throwsException(String type) {
+        String[] exceptions = getExceptionNames();
+
+        for (int i = 0; i < exceptions.length; i++)
+            if (exceptions[i].equals(type)) {
+                return true;
+            }
+
+        return false;
+    }
+
+    /**
+     *  Return true if the method declares that it throws the given
+     *  exception type.
+     */
+    public boolean throwsException(Class type) {
+        if (type == null) {
+            return false;
+        }
+
+        return throwsException(type.getName());
+    }
+
+    /**
+     *  Return true if the method declares that it throws the given
+     *  exception type.
+     */
+    public boolean throwsException(BCClass type) {
+        if (type == null) {
+            return false;
+        }
+
+        return throwsException(type.getName());
+    }
+
+    public void acceptVisit(BCVisitor visit) {
+        visit.enterExceptions(this);
+        visit.exitExceptions(this);
+    }
+
+    void read(Attribute other) {
+        setExceptions(((Exceptions) other).getExceptionNames());
+    }
+
+    void read(DataInput in, int length) throws IOException {
+        _indexes.clear();
+
+        int exceptionCount = in.readUnsignedShort();
+
+        for (int i = 0; i < exceptionCount; i++)
+            _indexes.add(Numbers.valueOf((int) in.readUnsignedShort()));
+    }
+
+    void write(DataOutput out, int length) throws IOException {
+        out.writeShort(_indexes.size());
+
+        for (Iterator itr = _indexes.iterator(); itr.hasNext();)
+            out.writeShort(((Number) itr.next()).shortValue());
+    }
+}

Propchange: incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/Exceptions.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/FieldInstruction.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/FieldInstruction.java?rev=417860&view=auto
==============================================================================
--- incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/FieldInstruction.java (added)
+++ incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/FieldInstruction.java Wed Jun 28 12:46:13 2006
@@ -0,0 +1,499 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package serp.bytecode;
+
+import serp.bytecode.lowlevel.*;
+
+import serp.bytecode.visitor.*;
+
+import serp.util.*;
+
+import java.io.*;
+
+import java.lang.reflect.*;
+
+
+/**
+ *  <p>Instruction that takes as an argument a field to operate
+ *  on. Examples include <code>getfield, getstatic, setfield,
+ *  setstatic</code>.</p>
+ *
+ *  @author Abe White
+ */
+public abstract class FieldInstruction extends Instruction {
+    private int _index = 0;
+
+    FieldInstruction(Code owner, int opcode) {
+        super(owner, opcode);
+    }
+
+    int getLength() {
+        return super.getLength() + 2;
+    }
+
+    ////////////////////
+    // Field operations
+    ////////////////////
+
+    /**
+     *  Return the index in the class {@link ConstantPool} of the
+     *  {@link ComplexEntry} describing the field to operate on.
+     */
+    public int getFieldIndex() {
+        return _index;
+    }
+
+    /**
+     *  Set the index in the class {@link ConstantPool} of the
+     *  {@link ComplexEntry} describing the field to operate on.
+     *
+     *  @return this instruction, for method chaining
+     */
+    public FieldInstruction setFieldIndex(int index) {
+        _index = index;
+
+        return this;
+    }
+
+    /**
+     *  Return the field this instruction operates on, or null if not set.
+     */
+    public BCField getField() {
+        String dec = getFieldDeclarerName();
+
+        if (dec == null) {
+            return null;
+        }
+
+        BCClass bc = getProject().loadClass(dec, getClassLoader());
+        BCField[] fields = bc.getFields(getFieldName());
+
+        if (fields.length == 0) {
+            return null;
+        }
+
+        return fields[0];
+    }
+
+    /**
+     *  Set the field this instruction operates on.
+     *
+     *  @return this instruction, for method chaining
+     */
+    public FieldInstruction setField(BCField field) {
+        if (field == null) {
+            return setFieldIndex(0);
+        }
+
+        return setField(field.getDeclarer().getName(), field.getName(),
+            field.getTypeName());
+    }
+
+    /**
+     *  Set the field this instruction operates on.
+     *
+     *  @return this instruction, for method chaining
+     */
+    public FieldInstruction setField(Field field) {
+        if (field == null) {
+            return setFieldIndex(0);
+        }
+
+        return setField(field.getDeclaringClass(), field.getName(),
+            field.getType());
+    }
+
+    /**
+     *  Set the field this instruction operates on.
+     *
+     *  @param dec                the full class name of the field's declaring class
+     *  @param name        the field name
+     *  @param type        the full class name of the field type
+     *  @return this instruction, for method chaining
+     */
+    public FieldInstruction setField(String dec, String name, String type) {
+        if ((dec == null) && (name == null) && (type == null)) {
+            return setFieldIndex(0);
+        }
+
+        if (dec == null) {
+            dec = "";
+        }
+
+        if (name == null) {
+            name = "";
+        }
+
+        if (type == null) {
+            type = "";
+        }
+
+        dec = getProject().getNameCache().getInternalForm(dec, false);
+        type = getProject().getNameCache().getInternalForm(type, true);
+
+        return setFieldIndex(getPool().findFieldEntry(dec, name, type, true));
+    }
+
+    /**
+     *  Set the field this instruction operates on, for fields that are
+     *  declared by the current class.
+     *
+     *  @param name        the field name
+     *  @param type        the full class name of the field type
+     *  @return this instruction, for method chaining
+     */
+    public FieldInstruction setField(String name, String type) {
+        BCClass owner = getCode().getMethod().getDeclarer();
+
+        return setField(owner.getName(), name, type);
+    }
+
+    /**
+     *  Set the field this instruction operates on.
+     *
+     *  @param dec                the field's declaring class
+     *  @param name        the field name
+     *  @param type        the class of the field type
+     *  @return this instruction, for method chaining
+     */
+    public FieldInstruction setField(Class dec, String name, Class type) {
+        String decName = (dec == null) ? null : dec.getName();
+        String typeName = (type == null) ? null : type.getName();
+
+        return setField(decName, name, typeName);
+    }
+
+    /**
+     *  Set the field this instruction operates on, for fields that are
+     *  declared by the current class.
+     *
+     *  @param name        the field name
+     *  @param type        the class of the field type
+     *  @return this instruction, for method chaining
+     */
+    public FieldInstruction setField(String name, Class type) {
+        BCClass owner = getCode().getMethod().getDeclarer();
+        String typeName = (type == null) ? null : type.getName();
+
+        return setField(owner.getName(), name, typeName);
+    }
+
+    /**
+     *  Set the field this instruction operates on.
+     *
+     *  @param dec                the field's declaring class
+     *  @param name        the field name
+     *  @param type        the class of the field type
+     *  @return this instruction, for method chaining
+     */
+    public FieldInstruction setField(BCClass dec, String name, BCClass type) {
+        String decName = (dec == null) ? null : dec.getName();
+        String typeName = (type == null) ? null : type.getName();
+
+        return setField(decName, name, typeName);
+    }
+
+    /**
+     *  Set the field this instruction operates on, for fields that are
+     *  declared by the current class.
+     *
+     *  @param name        the field name
+     *  @param type        the class of the field type
+     *  @return this instruction, for method chaining
+     */
+    public FieldInstruction setField(String name, BCClass type) {
+        BCClass owner = getCode().getMethod().getDeclarer();
+        String typeName = (type == null) ? null : type.getName();
+
+        return setField(owner.getName(), name, typeName);
+    }
+
+    ////////////////////////////////
+    // Name, Type, Owner operations
+    ////////////////////////////////
+
+    /**
+      *  Return the name of the field this instruction operates on, or null
+     *  if not set.
+     */
+    public String getFieldName() {
+        int index = getFieldIndex();
+
+        if (index == 0) {
+            return null;
+        }
+
+        ComplexEntry entry = (ComplexEntry) getPool().getEntry(index);
+        String name = entry.getNameAndTypeEntry().getNameEntry().getValue();
+
+        if (name.length() == 0) {
+            return null;
+        }
+
+        return name;
+    }
+
+    /**
+     *  Set the name of the field this instruction operates on.
+     *
+     *  @return this instruction, for method chaining
+     */
+    public FieldInstruction setFieldName(String name) {
+        return setField(getFieldDeclarerName(), name, getFieldTypeName());
+    }
+
+    /**
+     *  Return the type of the field this instruction operates on, or null
+     *  if not set.
+     */
+    public String getFieldTypeName() {
+        int index = getFieldIndex();
+
+        if (index == 0) {
+            return null;
+        }
+
+        ComplexEntry entry = (ComplexEntry) getPool().getEntry(index);
+        String name = getProject().getNameCache()
+                          .getExternalForm(entry.getNameAndTypeEntry()
+                                                .getDescriptorEntry().getValue(),
+                false);
+
+        if (name.length() == 0) {
+            return null;
+        }
+
+        return name;
+    }
+
+    /**
+     *  Return the type of the field this instruction operates on, or null
+     *  if not set.
+     */
+    public Class getFieldType() {
+        String type = getFieldTypeName();
+
+        if (type == null) {
+            return null;
+        }
+
+        return Strings.toClass(type, getClassLoader());
+    }
+
+    /**
+     *  Return the type of the field this instruction operates on, or null
+     *  if not set.
+     */
+    public BCClass getFieldTypeBC() {
+        String type = getFieldTypeName();
+
+        if (type == null) {
+            return null;
+        }
+
+        return getProject().loadClass(type, getClassLoader());
+    }
+
+    /**
+     *  Set the type of the field this instruction operates on.
+     *
+     *  @return this instruction, for method chaining
+     */
+    public FieldInstruction setFieldType(String type) {
+        return setField(getFieldDeclarerName(), getFieldName(), type);
+    }
+
+    /**
+     *  Set the type of the field this instruction operates on.
+     *
+     *  @return this instruction, for method chaining
+     */
+    public FieldInstruction setFieldType(Class type) {
+        String name = null;
+
+        if (type != null) {
+            name = type.getName();
+        }
+
+        return setFieldType(name);
+    }
+
+    /**
+     *  Set the type of the field this instruction operates on.
+     *
+     *  @return this instruction, for method chaining
+     */
+    public FieldInstruction setFieldType(BCClass type) {
+        String name = null;
+
+        if (type != null) {
+            name = type.getName();
+        }
+
+        return setFieldType(name);
+    }
+
+    /**
+     *  Return the declaring class of the field this instruction operates on,
+     *  or null if not set.
+     */
+    public String getFieldDeclarerName() {
+        int index = getFieldIndex();
+
+        if (index == 0) {
+            return null;
+        }
+
+        ComplexEntry entry = (ComplexEntry) getPool().getEntry(index);
+        String name = getProject().getNameCache()
+                          .getExternalForm(entry.getClassEntry().getNameEntry()
+                                                .getValue(), false);
+
+        if (name.length() == 0) {
+            return null;
+        }
+
+        return name;
+    }
+
+    /**
+     *  Return the declaring class of the field this instruction operates on,
+     *  or null if not set.
+     */
+    public Class getFieldDeclarerType() {
+        String type = getFieldDeclarerName();
+
+        if (type == null) {
+            return null;
+        }
+
+        return Strings.toClass(type, getClassLoader());
+    }
+
+    /**
+     *  Return the declaring class of the field this instruction operates on,
+     *  or null        if not set.
+     */
+    public BCClass getFieldDeclarerBC() {
+        String type = getFieldDeclarerName();
+
+        if (type == null) {
+            return null;
+        }
+
+        return getProject().loadClass(type, getClassLoader());
+    }
+
+    /**
+     *  Set the declaring class of the field this instruction operates on.
+     *
+     *  @return this instruction, for method chaining
+     */
+    public FieldInstruction setFieldDeclarer(String type) {
+        return setField(type, getFieldName(), getFieldTypeName());
+    }
+
+    /**
+     *  Set the declaring class of the field this instruction operates on.
+     *
+     *  @return this instruction, for method chaining
+     */
+    public FieldInstruction setFieldDeclarer(Class type) {
+        String name = null;
+
+        if (type != null) {
+            name = type.getName();
+        }
+
+        return setFieldDeclarer(name);
+    }
+
+    /**
+     *  Set the declaring class of the field this instruction operates on.
+     *
+     *  @return this instruction, for method chaining
+     */
+    public FieldInstruction setFieldDeclarer(BCClass type) {
+        String name = null;
+
+        if (type != null) {
+            name = type.getName();
+        }
+
+        return setFieldDeclarer(name);
+    }
+
+    /**
+     *  FieldInstructions are equal if the field they reference is the same,
+     *  or if the field of either is unset.
+     */
+    public boolean equalsInstruction(Instruction other) {
+        if (other == this) {
+            return true;
+        }
+
+        if (!(other instanceof FieldInstruction)) {
+            return false;
+        }
+
+        if (!super.equalsInstruction(other)) {
+            return false;
+        }
+
+        FieldInstruction ins = (FieldInstruction) other;
+
+        String s1 = getFieldName();
+        String s2 = ins.getFieldName();
+
+        if (!((s1 == null) || (s2 == null) || s1.equals(s2))) {
+            return false;
+        }
+
+        s1 = getFieldTypeName();
+        s2 = ins.getFieldTypeName();
+
+        if (!((s1 == null) || (s2 == null) || s1.equals(s2))) {
+            return false;
+        }
+
+        s1 = getFieldDeclarerName();
+        s2 = ins.getFieldDeclarerName();
+
+        if (!((s1 == null) || (s2 == null) || s1.equals(s2))) {
+            return false;
+        }
+
+        return true;
+    }
+
+    void read(Instruction orig) {
+        super.read(orig);
+
+        FieldInstruction ins = (FieldInstruction) orig;
+        setField(ins.getFieldDeclarerName(), ins.getFieldName(),
+            ins.getFieldTypeName());
+    }
+
+    void read(DataInput in) throws IOException {
+        super.read(in);
+        setFieldIndex(in.readUnsignedShort());
+    }
+
+    void write(DataOutput out) throws IOException {
+        super.write(out);
+        out.writeShort(getFieldIndex());
+    }
+}

Propchange: incubator/openjpa/trunk/serp/src/main/java/serp/bytecode/FieldInstruction.java
------------------------------------------------------------------------------
    svn:executable = *