1/*
2 * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package com.sun.xml.internal.stream.buffer;
27
28import org.xml.sax.Attributes;
29
30/**
31 * Class for holding attributes.
32 *
33 * Since it implements {@link Attributes}, this class follows the SAX convention
34 * of using "" instead of null.
35 */
36@SuppressWarnings({"PointlessArithmeticExpression"})
37public final class AttributesHolder implements Attributes {
38    private static final int DEFAULT_CAPACITY = 8;
39    private static final int ITEM_SIZE = 1 << 3;
40
41    private static final int PREFIX     = 0;
42    private static final int URI        = 1;
43    private static final int LOCAL_NAME = 2;
44    private static final int QNAME      = 3;
45    private static final int TYPE       = 4;
46    private static final int VALUE      = 5;
47
48    private int _attributeCount;
49
50    private String[] _strings;
51
52    public AttributesHolder() {
53        _strings = new String[DEFAULT_CAPACITY * ITEM_SIZE];
54    }
55
56    public final int getLength() {
57        return _attributeCount;
58    }
59
60    public final String getPrefix(int index) {
61        return (index >= 0 && index < _attributeCount) ?
62            _strings[(index << 3) + PREFIX] : null;
63    }
64
65    public final String getLocalName(int index) {
66        return (index >= 0 && index < _attributeCount) ?
67            _strings[(index << 3) + LOCAL_NAME] : null;
68    }
69
70    public final String getQName(int index) {
71        return (index >= 0 && index < _attributeCount) ?
72            _strings[(index << 3) + QNAME] : null;
73    }
74
75    public final String getType(int index) {
76        return (index >= 0 && index < _attributeCount) ?
77            _strings[(index << 3) + TYPE] : null;
78    }
79
80    public final String getURI(int index) {
81        return (index >= 0 && index < _attributeCount) ?
82            _strings[(index << 3) + URI] : null;
83    }
84
85    public final String getValue(int index) {
86        return (index >= 0 && index < _attributeCount) ?
87            _strings[(index << 3) + VALUE] : null;
88    }
89
90    public final int getIndex(String qName) {
91        for (int i = 0; i < _attributeCount; i++) {
92            if (qName.equals(_strings[(i << 3) + QNAME])) {
93                return i;
94            }
95        }
96        return -1;
97    }
98
99    public final String getType(String qName) {
100        final int i = (getIndex(qName) << 3) + TYPE;
101        return (i >= 0) ? _strings[i] : null;
102    }
103
104    public final String getValue(String qName) {
105        final int i = (getIndex(qName) << 3) + VALUE;
106        return (i >= 0) ? _strings[i] : null;
107    }
108
109    public final int getIndex(String uri, String localName) {
110        for (int i = 0; i < _attributeCount; i++) {
111            if (localName.equals(_strings[(i << 3) + LOCAL_NAME]) &&
112                uri.equals(_strings[(i << 3) + URI])) {
113                return i;
114            }
115        }
116        return -1;
117    }
118
119    public final String getType(String uri, String localName) {
120        final int i = (getIndex(uri, localName) << 3) + TYPE;
121        return (i >= 0) ? _strings[i] : null;
122    }
123
124    public final String getValue(String uri, String localName) {
125        final int i = (getIndex(uri, localName) << 3) + VALUE;
126        return (i >= 0) ? _strings[i] : null;
127    }
128
129    public final void clear() {
130        if (_attributeCount > 0) {
131            for (int i = 0; i < _attributeCount; i++) {
132                _strings[(i << 3) + VALUE] = null;
133            }
134            _attributeCount = 0;
135        }
136    }
137
138
139    /**
140     * Add an attribute using a qualified name that contains the
141     * prefix and local name.
142     *
143     * @param uri
144     *      This can be empty but not null, just like everywhere else in SAX.
145     */
146    public final void addAttributeWithQName(String uri, String localName, String qName, String type, String value) {
147        final int i = _attributeCount << 3;
148        if (i == _strings.length) {
149            resize(i);
150        }
151
152        _strings[i + PREFIX] = null;
153        _strings[i + URI] = uri;
154        _strings[i + LOCAL_NAME] = localName;
155        _strings[i + QNAME] = qName;
156        _strings[i + TYPE] = type;
157        _strings[i + VALUE] = value;
158
159        _attributeCount++;
160    }
161
162    /**
163     * Add an attribute using a prefix.
164     *
165     * @param prefix
166     *      This can be empty but not null, just like everywhere else in SAX.
167     * @param uri
168     *      This can be empty but not null, just like everywhere else in SAX.
169     */
170    public final void addAttributeWithPrefix(String prefix, String uri, String localName, String type, String value) {
171        final int i = _attributeCount << 3;
172        if (i == _strings.length) {
173            resize(i);
174        }
175
176        _strings[i + PREFIX] = prefix;
177        _strings[i + URI] = uri;
178        _strings[i + LOCAL_NAME] = localName;
179        _strings[i + QNAME] = null;
180        _strings[i + TYPE] = type;
181        _strings[i + VALUE] = value;
182
183        _attributeCount++;
184    }
185
186    private void resize(int length) {
187        final int newLength = length * 2;
188        final String[] strings = new String[newLength];
189        System.arraycopy(_strings, 0, strings, 0, length);
190        _strings = strings;
191    }
192
193}
194