001 package edu.rice.cs.cunit.classFile.attributes;
002
003 import edu.rice.cs.cunit.classFile.code.instructions.LineNumberTable;
004 import edu.rice.cs.cunit.classFile.constantPool.AUTFPoolInfo;
005 import edu.rice.cs.cunit.classFile.constantPool.ConstantPool;
006 import edu.rice.cs.cunit.util.Types;
007
008 import java.io.ByteArrayOutputStream;
009 import java.io.IOException;
010 import java.util.ArrayList;
011 import java.util.List;
012
013 /**
014 * Represents an abstract annotations attribute in a class file that can contain annotations for multiple entities,
015 * like for method parameters or local variables.
016 *
017 * @author Mathias Ricken
018 */
019 public abstract class AMultipleAnnotationsAttributeInfo extends AAnnotationsAttributeInfo {
020 /**
021 * Creates a new abstract multiple annotations attribute.
022 * @param name name of attribute
023 * @param data data array
024 * @param cp constant pool
025 */
026 public AMultipleAnnotationsAttributeInfo(AUTFPoolInfo name, byte data[], ConstantPool cp) {
027 super(name, data, cp);
028 }
029
030 /**
031 * Return the number of entities.
032 *
033 * @return number of entities
034 *
035 * @throws ClassFormatError
036 */
037 public short getEntityCount() throws ClassFormatError {
038 return _data[0];
039 }
040
041 /**
042 * Return the list of entity annotations arrays.
043 *
044 * @return list of arrays of entity annotations.
045 *
046 * @throws ClassFormatError
047 */
048 public List<Annotation[]> getEntityAnnotations() throws ClassFormatError {
049 ArrayList<Annotation[]> entityAnnots = new ArrayList<Annotation[]>();
050 int index = 1;
051 for(int entity=0; entity<getEntityCount(); ++entity) {
052 int count = Types.ushortFromBytes(_data, index);
053 assert(count <= 0xffff);
054 index += 2;
055 Annotation[] ann = new Annotation[count];
056 for(short i = 0; i < count; ++i) {
057 ann[i] = new Annotation(_constantPool,_data,index);
058 index += ann[i].getSize();
059 }
060 entityAnnots.add(ann);
061 }
062 return entityAnnots;
063 }
064
065 /**
066 * Set the entity annotations list.
067 *
068 * @param entityAnnots list of arrays of entity anotations
069 *
070 * @throws ClassFormatError
071 */
072 public void setEntityAnnotations(List<Annotation[]> entityAnnots) throws IOException {
073 ByteArrayOutputStream baos = new ByteArrayOutputStream();
074 baos.write((byte)entityAnnots.size());
075 for(Annotation[] ann: entityAnnots) {
076 baos.write(Types.bytesFromShort((short)ann.length));
077 for(int i = 0; i < ann.length; ++i) {
078 ann[i].writeToByteArrayOutputStream(_constantPool,baos);
079 }
080 }
081 setData(baos.toByteArray());
082 }
083
084 /**
085 * Return a human-readable version of this attribute.
086 *
087 * @return string
088 */
089 public String toString() {
090 StringBuilder x = new StringBuilder();
091 x.append(_name);
092 x.append(" <");
093 x.append(getEntityCount());
094 x.append(" ");
095 x.append(getEntityName());
096 x.append("(s) { ");
097 boolean first = true;
098 for(Annotation[] entityAnnot : getEntityAnnotations()) {
099 if (first) {
100 first = false;
101 }
102 else {
103 x.append(", ");
104 }
105 boolean firstAnn = true;
106 for(Annotation ann : entityAnnot) {
107 if (firstAnn) {
108 firstAnn = false;
109 }
110 else {
111 x.append(", ");
112 }
113 x.append(ann.toString());
114 }
115 x.append(" }");
116 }
117 x.append(" } >");
118 return x.toString();
119 }
120
121 /**
122 * Return the name of the entity, e.g. "parameter" or "local variable".
123 * @return name of tne entity
124 */
125 public abstract String getEntityName();
126
127 /**
128 * Adjust program counter values contained in this attribute, starting at startPC, by adding deltaPC to them.
129 *
130 * @param startPC program counter to start at
131 * @param deltaPC change in program counter values
132 */
133 public void adjustPC(int startPC, int deltaPC) {
134 // nothing to do
135 }
136
137 /**
138 * Translate the program counter values contained in this attribute from an old line number table to a new one.
139 *
140 * @param index critical point (insertion or deletion point)
141 * @param deltaIndex delta value to add to all old line numbers greater than the critical point
142 * @param oldLnt old line number table
143 * @param newLnt new line number table
144 */
145 public void translatePC(int index, int deltaIndex, LineNumberTable oldLnt, LineNumberTable newLnt) {
146 // nothing to do
147 }
148
149 /**
150 * Creates and returns a copy of this object.
151 */
152 public Object clone() throws CloneNotSupportedException {
153 return super.clone();
154 }
155 }