001    package edu.rice.cs.cunit.classFile.attributes;
002    
003    import edu.rice.cs.cunit.classFile.attributes.visitors.IAttributeVisitor;
004    import edu.rice.cs.cunit.classFile.code.instructions.LineNumberTable;
005    import edu.rice.cs.cunit.classFile.constantPool.AUTFPoolInfo;
006    import edu.rice.cs.cunit.classFile.constantPool.ConstantPool;
007    import edu.rice.cs.cunit.classFile.constantPool.ClassPoolInfo;
008    import edu.rice.cs.cunit.classFile.constantPool.NameAndTypePoolInfo;
009    import edu.rice.cs.cunit.classFile.constantPool.visitors.CheckClassVisitor;
010    import edu.rice.cs.cunit.classFile.constantPool.visitors.CheckNameAndTypeVisitor;
011    import edu.rice.cs.cunit.util.Types;
012    
013    /**
014     * Represents the EnclosingMethod attribute in a class file.
015     *
016     * @author Mathias Ricken
017     */
018    public class EnclosingMethodAttributeInfo extends AAttributeInfo {
019        /**
020         * Constructor.
021         *
022         * @param name attribute name
023         * @param data attribute data
024         * @param cp   constant pool
025         *
026         * @throws ClassFormatError
027         */
028        public EnclosingMethodAttributeInfo(AUTFPoolInfo name, byte[] data, ConstantPool cp) throws ClassFormatError {
029            super(name, data, cp);
030        }
031    
032        /**
033         * Return the enclosing class information.
034         *
035         * @return class information
036         *
037         * @throws ClassFormatError
038         */
039        public ClassPoolInfo getEnclosingClass() throws ClassFormatError {
040            return _constantPool.get(Types.ushortFromBytes(_data, 0)).execute(CheckClassVisitor.singleton(), null);
041        }
042    
043        /**
044         * Set the enclosing class information.
045         *
046         * @param newClass enclosing class
047         */
048        public void setSourceFileName(ClassPoolInfo newClass) {
049            Types.bytesFromShort(_constantPool.indexOf(newClass), _data, 0);
050        }
051    
052        /**
053         * Return the enclosing method information.
054         *
055         * @return method information
056         *
057         * @throws ClassFormatError
058         */
059        public NameAndTypePoolInfo getEnclosingMethod() throws ClassFormatError {
060            return _constantPool.get(Types.ushortFromBytes(_data, 2)).execute(CheckNameAndTypeVisitor.singleton(), null);
061        }
062    
063        /**
064         * Set the enclosing method information.
065         *
066         * @param newMethod enclosing method
067         */
068        public void setEnclosinMethod(ClassPoolInfo newMethod) {
069            Types.bytesFromShort(_constantPool.indexOf(newMethod), _data, 2);
070        }
071    
072        /**
073         * Execute a visitor on this attribute.
074         *
075         * @param visitor visitor
076         * @param param   visitor-specific parameter
077         *
078         * @return visitor-specific return value
079         */
080        public <R, D> R execute(IAttributeVisitor<R, D> visitor, D param) {
081            return visitor.enclosingMethodCase(this, param);
082        }
083    
084        /**
085         * Adjust program counter values contained in this attribute, starting at startPC, by adding deltaPC to them.
086         *
087         * @param startPC program counter to start at
088         * @param deltaPC change in program counter values
089         */
090        public void adjustPC(int startPC, int deltaPC) {
091            // nothing to do
092        }
093    
094        /**
095         * Translate the program counter values contained in this attribute from an old line number table to a new one.
096         *
097         * @param index      critical point (insertion or deletion point)
098         * @param deltaIndex delta value to add to all old line numbers greater than the critical point
099         * @param oldLnt     old line number table
100         * @param newLnt     new line number table
101         */
102        public void translatePC(int index, int deltaIndex, LineNumberTable oldLnt, LineNumberTable newLnt) {
103            // nothing to do
104        }
105    
106        /**
107         * Creates and returns a copy of this object.
108         */
109        public Object clone() throws CloneNotSupportedException {
110            return super.clone();
111        }
112    
113        /**
114         * Return a human-readable version of this attribute.
115         *
116         * @return string
117         */
118        public String toString() {
119            try {
120                return "EnclosingMethod <Class = "+getEnclosingClass().toString()+", Method = "+getEnclosingMethod().toStringVerbose()+" >";
121            }
122            catch(ClassFormatError cfe) {
123                if ((cfe.getMessage().startsWith("Info is of type ") && cfe.getMessage().endsWith(", needs to be NameAndType"))) {
124                    return "EnclosingMethod: <unknown; encountered EmptyPoolInfo>";
125                }
126                throw cfe;
127            }
128        }
129    
130        /**
131         * Returns the name of the attribute as it appears in the class file.
132         *
133         * @return name of the attribute.
134         */
135        public static String getAttributeName() {
136            return "EnclosingMethod";
137        }
138    }