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: InnerClassesAttribute_info.java,v 1.1.1.1 2004/05/09 16:57:48 vlad_r Exp $
8 */
9package com.vladium.jcd.cls.attribute;
10
11import java.io.IOException;
12import java.util.ArrayList;
13import java.util.List;
14
15import com.vladium.jcd.lib.UDataInputStream;
16import com.vladium.jcd.lib.UDataOutputStream;
17
18// ----------------------------------------------------------------------------
19/**
20 * @author Vlad Roubtsov, (C) 2003
21 */
22public
23final class InnerClassesAttribute_info extends Attribute_info
24{
25    // public: ................................................................
26
27    // ACCESSORS:
28
29    public boolean makesClassNested (final int class_index, final int [] nestedAccessFlags)
30    {
31        if (class_index > 0)
32        {
33            // TODO: avoid linear loop by keeping all class indices in a bitset
34
35            for (int i = 0, iLimit = size (); i < iLimit; ++ i)
36            {
37                final InnerClass_info info = get (i);
38
39                if (info.m_inner_class_index == class_index)
40                {
41                    nestedAccessFlags [0] = info.m_inner_access_flags;
42                    return true;
43                }
44            }
45        }
46
47        return false;
48    }
49
50    /**
51     * Returns {@link InnerClass_info} descriptor at a given offset.
52     *
53     * @param offset inner class entry offset [must be in [0, size()) range;
54     * input not checked]
55     * @return InnerClass_info descriptor [never null]
56     *
57     * @throws IndexOutOfBoundsException if 'offset' is outside of valid range
58     */
59    public final InnerClass_info get (final int offset)
60    {
61        return (InnerClass_info) m_classes.get (offset);
62    }
63
64    /**
65     * Returns the number of descriptors in this collection [can be 0].
66     */
67    public final int size ()
68    {
69        return m_classes.size ();
70    }
71
72    public final long length ()
73    {
74        return 8 + (m_classes.size () << 3); // use size() if class becomes non-final
75    }
76
77    // Visitor:
78
79    public void accept (final IAttributeVisitor visitor, final Object ctx)
80    {
81        visitor.visit (this, ctx);
82    }
83
84    public String toString ()
85    {
86        final StringBuffer s = new StringBuffer ("InnerClassesAttribute_info: [attribute_name_index = " + m_name_index + ", attribute_length = " + length () + "]\n");
87
88        for (int l = 0; l < size (); ++ l)
89        {
90            s.append ("            " + get (l));
91            s.append ("\n"); // TODO: proper EOL const
92        }
93
94        return s.toString ();
95    }
96
97    // Cloneable:
98
99    /**
100     * Performs a deep copy.
101     */
102    public Object clone ()
103    {
104        final InnerClassesAttribute_info _clone = (InnerClassesAttribute_info) super.clone ();
105
106        final List/* InnerClass_info */ classes = m_classes;
107
108        // do deep copy:
109        final int class_count = classes.size (); // use size() if class becomes non-final
110        _clone.m_classes = new ArrayList (class_count);
111        for (int e = 0; e < class_count; ++ e)
112        {
113            _clone.m_classes.add (((InnerClass_info) classes.get (e)).clone ());
114        }
115
116        return _clone;
117    }
118
119    // IClassFormatOutput:
120
121    public void writeInClassFormat (final UDataOutputStream out) throws IOException
122    {
123        super.writeInClassFormat (out);
124
125        final List/* InnerClass_info */ classes = m_classes;
126
127        final int class_count = classes.size (); // use size() if class becomes non-final
128        out.writeU2 (class_count);
129
130        for (int l = 0; l < class_count; ++ l)
131        {
132            ((InnerClass_info) classes.get (l)).writeInClassFormat (out);
133        }
134    }
135
136    // protected: .............................................................
137
138    // package: ...............................................................
139
140
141    InnerClassesAttribute_info (final int attribute_name_index, final long attribute_length,
142                                final UDataInputStream bytes)
143        throws IOException
144    {
145        super (attribute_name_index, attribute_length);
146
147        final int class_count = bytes.readU2 ();
148        final List/* InnerClass_info */ classes = new ArrayList (class_count);
149
150        for (int i = 0; i < class_count; ++ i)
151        {
152            classes.add (new InnerClass_info (bytes));
153        }
154
155        m_classes = classes;
156    }
157
158    // private: ...............................................................
159
160
161    private List/* InnerClass_info */ m_classes; // never null
162
163} // end of class
164// ----------------------------------------------------------------------------