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        // ...existing code...
112        return ((ConstantUtf8) getConstantPool().getConstant(typeIdx)).getBytes();
113        // ...existing code...
114    }
115
116    /**
117     * Gets the enum value string.
118     *
119     * @return the enum value string.
120     */
121    public String getEnumValueString() {
122        return ((ConstantUtf8) getConstantPool().getConstant(valueIdx)).getBytes();
123        // ...existing code...
124    }
125
126    /**
127     * Gets the type index.
128     *
129     * @return the type index.
130     */
131    public int getTypeIndex() {
132        return typeIdx;
133    }
134
135    /**
136     * Gets the value index.
137     *
138     * @return the value index.
139     */
140    public int getValueIndex() {
141        return valueIdx;
142    }
143
144    @Override
145    public String stringifyValue() {
146        final ConstantUtf8 cu8 = (ConstantUtf8) getConstantPool().getConstant(valueIdx);
147        return cu8.getBytes();
148        // ConstantString cu8 =
149        // (ConstantString) getConstantPool().getConstant(valueIdx);
150        // return
151        // ((ConstantUtf8) getConstantPool().getConstant(cu8.getStringIndex())).getBytes();
152    }
153}