001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *   https://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.apache.bcel.generic;
020
021import java.io.DataOutputStream;
022import java.io.IOException;
023
024import org.apache.bcel.classfile.ConstantUtf8;
025import org.apache.bcel.classfile.ElementValue;
026import org.apache.bcel.classfile.EnumElementValue;
027
028/**
029 * Generates enum element values in annotations.
030 *
031 * @since 6.0
032 */
033public class EnumElementValueGen extends ElementValueGen {
034    // For enum types, these two indices point to the type and value
035    private final int typeIdx;
036
037    private final int valueIdx;
038
039    /**
040     * Constructs an EnumElementValueGen from an EnumElementValue.
041     *
042     * @param value The enum element value.
043     * @param cpool The constant pool.
044     * @param copyPoolEntries whether to copy pool entries.
045     */
046    public EnumElementValueGen(final EnumElementValue value, final ConstantPoolGen cpool, final boolean copyPoolEntries) {
047        super(ENUM_CONSTANT, cpool);
048        if (copyPoolEntries) {
049            typeIdx = cpool.addUtf8(value.getEnumTypeString()); // was addClass(value.getEnumTypeString());
050            valueIdx = cpool.addUtf8(value.getEnumValueString()); // was addString(value.getEnumValueString());
051        } else {
052            typeIdx = value.getTypeIndex();
053            valueIdx = value.getValueIndex();
054        }
055    }
056
057    /**
058     * This constructor assumes the constant pool already contains the right type and value - as indicated by typeIdx and valueIdx.
059     * This constructor is used for deserialization.
060     *
061     * @param typeIdx The type index.
062     * @param valueIdx The value index.
063     * @param cpool The constant pool.
064     */
065    protected EnumElementValueGen(final int typeIdx, final int valueIdx, final ConstantPoolGen cpool) {
066        super(ENUM_CONSTANT, cpool);
067        if (super.getElementValueType() != ENUM_CONSTANT) {
068            throw new IllegalArgumentException("Only element values of type enum can be built with this ctor - type specified: " + super.getElementValueType());
069        }
070        this.typeIdx = typeIdx;
071        this.valueIdx = valueIdx;
072    }
073
074    /**
075     * Constructs an EnumElementValueGen.
076     *
077     * @param t The object type.
078     * @param value The value.
079     * @param cpool The constant pool.
080     */
081    public EnumElementValueGen(final ObjectType t, final String value, final ConstantPoolGen cpool) {
082        super(ENUM_CONSTANT, cpool);
083        typeIdx = cpool.addUtf8(t.getSignature()); // was addClass(t);
084        valueIdx = cpool.addUtf8(value); // was addString(value);
085    }
086
087    @Override
088    public void dump(final DataOutputStream dos) throws IOException {
089        dos.writeByte(super.getElementValueType()); // u1 type of value (ENUM_CONSTANT == 'e')
090        dos.writeShort(typeIdx); // u2
091        dos.writeShort(valueIdx); // u2
092    }
093
094    /**
095     * Returns immutable variant of this EnumElementValueGen.
096     *
097     * @return immutable variant.
098     */
099    @Override
100    public ElementValue getElementValue() {
101        System.err.println("Duplicating value: " + getEnumTypeString() + ":" + getEnumValueString());
102        return new EnumElementValue(super.getElementValueType(), typeIdx, valueIdx, getConstantPool().getConstantPool());
103    }
104
105    /**
106     * Gets the enum type string.
107     *
108     * @return The enum type string.
109     */
110    public String getEnumTypeString() {
111        // Constant cc = getConstantPool().getConstant(typeIdx);
112        // ConstantClass cu8 =
113        // (ConstantClass) getConstantPool().getConstant(typeIdx);
114        // return
115        // ((ConstantUtf8) getConstantPool().getConstant(cu8.getNameIndex())).getBytes();
116        return ((ConstantUtf8) getConstantPool().getConstant(typeIdx)).getBytes();
117        // return Utility.signatureToString(cu8.getBytes());
118    }
119
120    /**
121     * Gets the enum value string.
122     *
123     * @return The enum value string.
124     */
125    public String getEnumValueString() {
126        return ((ConstantUtf8) getConstantPool().getConstant(valueIdx)).getBytes();
127        // ConstantString cu8 =
128        // (ConstantString) getConstantPool().getConstant(valueIdx);
129        // return
130        // ((ConstantUtf8) getConstantPool().getConstant(cu8.getStringIndex())).getBytes();
131    }
132
133    /**
134     * Gets the type index.
135     *
136     * @return The type index.
137     */
138    public int getTypeIndex() {
139        return typeIdx;
140    }
141
142    /**
143     * Gets the value index.
144     *
145     * @return The value index.
146     */
147    public int getValueIndex() {
148        return valueIdx;
149    }
150
151    @Override
152    public String stringifyValue() {
153        final ConstantUtf8 cu8 = (ConstantUtf8) getConstantPool().getConstant(valueIdx);
154        return cu8.getBytes();
155        // ConstantString cu8 =
156        // (ConstantString) getConstantPool().getConstant(valueIdx);
157        // return
158        // ((ConstantUtf8) getConstantPool().getConstant(cu8.getStringIndex())).getBytes();
159    }
160}