1 /* Copyright (C) 2003 Vladimir Roubtsov. All rights reserved. 2 * 3 * This program and the accompanying materials are made available under 4 * the terms of the Common Public License v1.0 which accompanies this distribution, 5 * and is available at http://www.eclipse.org/legal/cpl-v10.html 6 * 7 * $Id: AttributeCollection.java,v 1.1.1.1 2004/05/09 16:57:44 vlad_r Exp $ 8 */ 9 package com.vladium.jcd.cls; 10 11 import java.io.IOException; 12 import java.util.ArrayList; 13 import java.util.List; 14 15 import com.vladium.jcd.cls.attribute.*; 16 import com.vladium.jcd.lib.UDataOutputStream; 17 import com.vladium.util.asserts.$assert; 18 19 // ---------------------------------------------------------------------------- 20 /** 21 * @author (C) 2001, Vlad Roubtsov 22 */ 23 final class AttributeCollection implements IAttributeCollection 24 { 25 // public: ................................................................ 26 27 // TODO: extend ItemCollection into all XXXCollection classes ? 28 29 30 // ACCESSORS: 31 get(final int offset)32 public final Attribute_info get (final int offset) 33 { 34 return (Attribute_info) m_attributes.get (offset); 35 } 36 hasSynthetic()37 public final boolean hasSynthetic () 38 { 39 return m_syntheticRefCount > 0; 40 } 41 hasBridge()42 public final boolean hasBridge () 43 { 44 return m_bridgeRefCount > 0; 45 } 46 getInnerClassesAttribute()47 public final InnerClassesAttribute_info getInnerClassesAttribute () 48 { 49 final int innerClassesAttributeOffset = m_innerClassesAttributeOffset; 50 if (innerClassesAttributeOffset < 0) 51 return null; 52 else 53 return (InnerClassesAttribute_info) get (innerClassesAttributeOffset); 54 } 55 size()56 public final int size () 57 { 58 return m_attributes.size (); 59 } 60 length()61 public final long length () 62 { 63 // TODO: cache? 64 65 long result = 2; 66 67 int _attributes_count = m_attributes.size (); // use size() if this class becomes non-final 68 for (int i = 0; i < _attributes_count; i++) result += get (i).length (); 69 70 return result; 71 } 72 73 // Cloneable: 74 75 /** 76 * Performs a deep copy. 77 */ clone()78 public Object clone () 79 { 80 try 81 { 82 final AttributeCollection _clone = (AttributeCollection) super.clone (); 83 84 // deep clone: 85 86 final int attributes_count = m_attributes.size (); // use size() if this class becomes non-final 87 _clone.m_attributes = new ArrayList (attributes_count); 88 for (int a = 0; a < attributes_count; ++ a) 89 { 90 _clone.m_attributes.add (((Attribute_info) m_attributes.get (a)).clone ()); 91 } 92 93 return _clone; 94 } 95 catch (CloneNotSupportedException e) 96 { 97 throw new InternalError (e.toString ()); 98 } 99 } 100 101 // IClassFormatOutput: 102 writeInClassFormat(final UDataOutputStream out)103 public void writeInClassFormat (final UDataOutputStream out) throws IOException 104 { 105 int attributes_count = size (); 106 out.writeU2 (attributes_count); 107 108 for (int i = 0; i < attributes_count; i++) 109 { 110 get (i).writeInClassFormat (out); 111 } 112 } 113 114 // Visitor: 115 accept(final IClassDefVisitor visitor, final Object ctx)116 public void accept (final IClassDefVisitor visitor, final Object ctx) 117 { 118 visitor.visit (this, ctx); 119 } 120 121 122 // MUTATORS: 123 add(final Attribute_info attribute)124 public int add (final Attribute_info attribute) 125 { 126 final List/* Attribute_info */ attributes = m_attributes; 127 128 final int result = attributes.size (); 129 attributes.add (attribute); 130 131 if (attribute instanceof SyntheticAttribute_info) 132 ++ m_syntheticRefCount; 133 else if (attribute instanceof InnerClassesAttribute_info) 134 { 135 if (m_innerClassesAttributeOffset >= 0) 136 throw new IllegalArgumentException ("this attribute collection already has an InnerClasses attribute"); 137 138 m_innerClassesAttributeOffset = result; 139 } 140 else if (attribute instanceof BridgeAttribute_info) 141 ++ m_bridgeRefCount; 142 143 if (DISALLOW_MULTIPLE_SYNTHETIC_ATTRIBUTES && $assert.ENABLED) 144 $assert.ASSERT (m_syntheticRefCount >= 0 && m_syntheticRefCount <= 1, 145 "bad synthetic attribute count: " + m_syntheticRefCount); 146 147 return result; 148 } 149 set(final int offset, final Attribute_info attribute)150 public Attribute_info set (final int offset, final Attribute_info attribute) 151 { 152 final Attribute_info result = (Attribute_info) m_attributes.set (offset, attribute); 153 154 if (result instanceof SyntheticAttribute_info) 155 -- m_syntheticRefCount; 156 else if (result instanceof InnerClassesAttribute_info) 157 m_innerClassesAttributeOffset = -1; 158 else if (result instanceof BridgeAttribute_info) 159 -- m_bridgeRefCount; 160 161 if (attribute instanceof SyntheticAttribute_info) 162 ++ m_syntheticRefCount; 163 else if (attribute instanceof InnerClassesAttribute_info) 164 m_innerClassesAttributeOffset = offset; 165 else if (attribute instanceof BridgeAttribute_info) 166 ++ m_bridgeRefCount; 167 168 if (DISALLOW_MULTIPLE_SYNTHETIC_ATTRIBUTES && $assert.ENABLED) 169 $assert.ASSERT (m_syntheticRefCount >= 0 && m_syntheticRefCount <= 1, 170 "bad synthetic attribute count: " + m_syntheticRefCount); 171 172 return result; 173 } 174 remove(final int offset)175 public Attribute_info remove (final int offset) 176 { 177 final Attribute_info result = (Attribute_info) m_attributes.remove (offset); 178 179 if (result instanceof SyntheticAttribute_info) 180 -- m_syntheticRefCount; 181 else if (result instanceof InnerClassesAttribute_info) 182 m_innerClassesAttributeOffset = -1; 183 else if (result instanceof BridgeAttribute_info) 184 -- m_bridgeRefCount; 185 186 if (DISALLOW_MULTIPLE_SYNTHETIC_ATTRIBUTES && $assert.ENABLED) 187 $assert.ASSERT (m_syntheticRefCount >= 0 && m_syntheticRefCount <= 1, 188 "bad synthetic attribute count: " + m_syntheticRefCount); 189 190 return result; 191 } 192 193 // protected: ............................................................. 194 195 // package: ............................................................... 196 197 AttributeCollection(final int capacity)198 AttributeCollection (final int capacity) 199 { 200 m_attributes = capacity < 0 ? new ArrayList () : new ArrayList (capacity); 201 m_innerClassesAttributeOffset = -1; 202 } 203 204 // private: ............................................................... 205 206 207 private List/* Attribute_info */ m_attributes; // never null 208 private transient int m_syntheticRefCount, m_bridgeRefCount; 209 private transient int m_innerClassesAttributeOffset; 210 211 // note: the spec does not disallow multiple synthetic attributes 212 private static final boolean DISALLOW_MULTIPLE_SYNTHETIC_ATTRIBUTES = false; 213 214 // note: the spec disallows multiple inner classes attributes 215 216 } // end of class 217 // ---------------------------------------------------------------------------- 218