View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   https://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.bcel.generic;
20  
21  import java.io.DataOutputStream;
22  import java.io.IOException;
23  import java.util.ArrayList;
24  import java.util.List;
25  import java.util.stream.Collectors;
26  
27  import org.apache.bcel.classfile.ArrayElementValue;
28  import org.apache.bcel.classfile.ElementValue;
29  import org.apache.bcel.util.Args;
30  import org.apache.commons.lang3.stream.Streams;
31  
32  /**
33   * Generates array element values in annotations.
34   *
35   * @since 6.0
36   */
37  public class ArrayElementValueGen extends ElementValueGen {
38      // J5TODO: Should we make this an array or a list? A list would be easier to
39      // modify ...
40      private final List<ElementValueGen> evalues;
41  
42      /**
43       * Constructs an ArrayElementValueGen.
44       *
45       * @param value The array element value.
46       * @param cpool The constant pool generator.
47       * @param copyPoolEntries whether to copy pool entries.
48       */
49      public ArrayElementValueGen(final ArrayElementValue value, final ConstantPoolGen cpool, final boolean copyPoolEntries) {
50          super(ARRAY, cpool);
51          evalues = new ArrayList<>();
52          final ElementValue[] in = value.getElementValuesArray();
53          for (final ElementValue element : in) {
54              evalues.add(copy(element, cpool, copyPoolEntries));
55          }
56      }
57  
58      /**
59       * Constructs an ArrayElementValueGen.
60       *
61       * @param cp The constant pool generator.
62       */
63      public ArrayElementValueGen(final ConstantPoolGen cp) {
64          super(ARRAY, cp);
65          evalues = new ArrayList<>();
66      }
67  
68      /**
69       * Constructs an ArrayElementValueGen.
70       *
71       * @param type The type.
72       * @param elementValues The element values.
73       * @param cpool The constant pool generator.
74       */
75      public ArrayElementValueGen(final int type, final ElementValue[] elementValues, final ConstantPoolGen cpool) {
76          super(type, cpool);
77          if (type != ARRAY) {
78              throw new IllegalArgumentException("Only element values of type array can be built with this ctor - type specified: " + type);
79          }
80          this.evalues = Streams.of(elementValues).map(e -> copy(e, cpool, true)).collect(Collectors.toList());
81      }
82  
83      /**
84       * Adds an element.
85       *
86       * @param gen The element value generator.
87       */
88      public void addElement(final ElementValueGen gen) {
89          evalues.add(gen);
90      }
91  
92      @Override
93      public void dump(final DataOutputStream dos) throws IOException {
94          dos.writeByte(super.getElementValueType()); // u1 type of value (ARRAY == '[')
95          dos.writeShort(Args.requireU2(evalues.size(), "evalues.size()"));
96          for (final ElementValueGen element : evalues) {
97              element.dump(dos);
98          }
99      }
100 
101     /**
102      * Return immutable variant of this ArrayElementValueGen.
103      *
104      * @return immutable variant of this ArrayElementValueGen.
105      */
106     @Override
107     public ElementValue getElementValue() {
108         final ElementValue[] immutableData = new ElementValue[evalues.size()];
109         int i = 0;
110         for (final ElementValueGen element : evalues) {
111             immutableData[i++] = element.getElementValue();
112         }
113         return new ArrayElementValue(super.getElementValueType(), immutableData, getConstantPool().getConstantPool());
114     }
115 
116     /**
117      * Gets the element values.
118      *
119      * @return The element values.
120      */
121     public List<ElementValueGen> getElementValues() {
122         return evalues;
123     }
124 
125     /**
126      * Gets the element values size.
127      *
128      * @return The element values size.
129      */
130     public int getElementValuesSize() {
131         return evalues.size();
132     }
133 
134     @Override
135     public String stringifyValue() {
136         final StringBuilder sb = new StringBuilder();
137         sb.append("[");
138         String comma = "";
139         for (final ElementValueGen element : evalues) {
140             sb.append(comma);
141             comma = ",";
142             sb.append(element.stringifyValue());
143         }
144         sb.append("]");
145         return sb.toString();
146     }
147 }