Home | History | Annotate | Download | only in cls
      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 
     32     public final Attribute_info get (final int offset)
     33     {
     34         return (Attribute_info) m_attributes.get (offset);
     35     }
     36 
     37     public final boolean hasSynthetic ()
     38     {
     39         return m_syntheticRefCount > 0;
     40     }
     41 
     42     public final boolean hasBridge ()
     43     {
     44         return m_bridgeRefCount > 0;
     45     }
     46 
     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 
     56     public final int size ()
     57     {
     58         return m_attributes.size ();
     59     }
     60 
     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      */
     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 
    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 
    116     public void accept (final IClassDefVisitor visitor, final Object ctx)
    117     {
    118         visitor.visit (this, ctx);
    119     }
    120 
    121 
    122     // MUTATORS:
    123 
    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 
    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 
    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 
    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