001    package sysModel.classFile.constantPool;
002    
003    import sysModel.classFile.constantPool.visitors.ADefaultPoolInfoVisitor;
004    import sysModel.classFile.constantPool.visitors.CheckClassVisitor;
005    
006    import java.io.DataInputStream;
007    import java.io.DataOutputStream;
008    import java.io.IOException;
009    
010    /**
011     * Represents an object in the constant pool described by class and name-and-type.
012     *
013     * @author Mathias Ricken
014     */
015    public abstract class AClassNameTypePoolInfo extends APoolInfo {
016        /**
017         * Class information.
018         */
019        protected ClassPoolInfo _classInfo;
020    
021        /**
022         * NameAndType information.
023         */
024        protected NameAndTypePoolInfo _nameAndType;
025    
026        /**
027         * Class index.
028         */
029        protected short _classInfoIndex;
030    
031        /**
032         * NameAndType index.
033         */
034        protected short _nameAndTypeIndex;
035    
036        /**
037         * Create a new object.
038         *
039         * @param type        type, either FIELD, METHOD or CONSTANT_InterfaceMethodref
040         * @param clas        class information
041         * @param nameAndType NameAndType information
042         * @param cp          constant pool
043         */
044        public AClassNameTypePoolInfo(int type,
045                                      ClassPoolInfo clas,
046                                      NameAndTypePoolInfo nameAndType,
047                                      ConstantPool cp) {
048            super(type, cp);
049            _classInfo = clas;
050            _nameAndType = nameAndType;
051            reindex();
052        }
053    
054        /**
055         * Constructor reading from a stream.
056         *
057         * @param type type, either FIELD, METHOD or CONSTANT_InterfaceMethodref
058         * @param dis  input stream
059         * @param cp   constant pool
060         *
061         * @throws IOException
062         */
063        public AClassNameTypePoolInfo(int type, DataInputStream dis, ConstantPool cp) throws IOException {
064            super(type, cp);
065            _classInfoIndex = dis.readShort();
066            _nameAndTypeIndex = dis.readShort();
067        }
068    
069        /**
070         * Accessor for the class information.
071         *
072         * @return class information
073         */
074        public ClassPoolInfo getClassInfo() {
075            return _classInfo;
076        }
077    
078        /**
079         * Mutator for the class information.
080         *
081         * @param classInfo new class information
082         */
083        public void setClassInfo(ClassPoolInfo classInfo) {
084            _classInfo = classInfo;
085        }
086    
087        /**
088         * Accessor for the NameAndType information.
089         *
090         * @return NameAndType information
091         */
092        public NameAndTypePoolInfo getNameAndType() {
093            return _nameAndType;
094        }
095    
096        /**
097         * Mutator for the NameAndType information.
098         *
099         * @param nameAndType new NameAndTypeInformation
100         */
101        public void setNameAndType(NameAndTypePoolInfo nameAndType) {
102            _nameAndType = nameAndType;
103        }
104    
105        /**
106         * Write this constant pool object into the stream, including the type byte.
107         *
108         * @param dos stream
109         *
110         * @throws IOException
111         */
112        public void write(DataOutputStream dos) throws IOException {
113            reindex();
114            dos.writeByte(_type);
115            dos.writeShort(_classInfoIndex);
116            dos.writeShort(_nameAndTypeIndex);
117        }
118    
119        /**
120         * Resolve constant pool objects. This makes sure that the object links match the index links.
121         */
122        public void resolve() {
123            _classInfo = _constantPool.get(_classInfoIndex).execute(CheckClassVisitor.singleton(), null);
124            _nameAndType = _constantPool.get(_nameAndTypeIndex).execute(new ADefaultPoolInfoVisitor<NameAndTypePoolInfo, Object>() {
125                public NameAndTypePoolInfo defaultCase(APoolInfo host, Object o) {
126                    throw new ClassFormatError(
127                        "Info is of type " + host.getClass().getName() + ", needs to be NameAndTypePoolInfo");
128                }
129    
130                public NameAndTypePoolInfo nameAndTypeCase(NameAndTypePoolInfo host, Object o) {
131                    return host;
132                }
133            }, null);
134        }
135    
136        /**
137         * Reindex constant pool indices. This makes sure the index links match the object links.
138         */
139        public void reindex() {
140            _classInfoIndex = _constantPool.indexOf(_classInfo);
141            _nameAndTypeIndex = _constantPool.indexOf(_nameAndType);
142        }
143    
144        /**
145         * Return a human-readable version of this constant pool object.
146         *
147         * @return string
148         */
149        public String toStringVerbose() {
150            return toString();
151        }
152    
153        /**
154         * Return a human-readable version of this constant pool object.
155         *
156         * @return string
157         */
158        public String toString() {
159            StringBuffer s;
160    
161            s = new StringBuffer();
162            s.append("FIELD: Class = #");
163            s.append(_classInfoIndex);
164            s.append(", Name and type = #");
165            s.append(_nameAndTypeIndex);
166    
167            return s.toString();
168        }
169    
170        /**
171         * Return a hash code.
172         *
173         * @return hash code
174         */
175        public int hashCode() {
176            return _classInfoIndex + 6101 * _nameAndTypeIndex;
177        }
178    }