1 /*
2  * Copyright (c) 2005, 2012, 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 
26 package com.sun.xml.internal.stream.buffer;
27 
28 import 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"})
37 public 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 
AttributesHolder()52     public AttributesHolder() {
53         _strings = new String[DEFAULT_CAPACITY * ITEM_SIZE];
54     }
55 
getLength()56     public final int getLength() {
57         return _attributeCount;
58     }
59 
getPrefix(int index)60     public final String getPrefix(int index) {
61         return (index >= 0 && index < _attributeCount) ?
62             _strings[(index << 3) + PREFIX] : null;
63     }
64 
getLocalName(int index)65     public final String getLocalName(int index) {
66         return (index >= 0 && index < _attributeCount) ?
67             _strings[(index << 3) + LOCAL_NAME] : null;
68     }
69 
getQName(int index)70     public final String getQName(int index) {
71         return (index >= 0 && index < _attributeCount) ?
72             _strings[(index << 3) + QNAME] : null;
73     }
74 
getType(int index)75     public final String getType(int index) {
76         return (index >= 0 && index < _attributeCount) ?
77             _strings[(index << 3) + TYPE] : null;
78     }
79 
getURI(int index)80     public final String getURI(int index) {
81         return (index >= 0 && index < _attributeCount) ?
82             _strings[(index << 3) + URI] : null;
83     }
84 
getValue(int index)85     public final String getValue(int index) {
86         return (index >= 0 && index < _attributeCount) ?
87             _strings[(index << 3) + VALUE] : null;
88     }
89 
getIndex(String qName)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 
getType(String qName)99     public final String getType(String qName) {
100         final int i = (getIndex(qName) << 3) + TYPE;
101         return (i >= 0) ? _strings[i] : null;
102     }
103 
getValue(String qName)104     public final String getValue(String qName) {
105         final int i = (getIndex(qName) << 3) + VALUE;
106         return (i >= 0) ? _strings[i] : null;
107     }
108 
getIndex(String uri, String localName)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 
getType(String uri, String localName)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 
getValue(String uri, String localName)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 
clear()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      */
addAttributeWithQName(String uri, String localName, String qName, String type, String value)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      */
addAttributeWithPrefix(String prefix, String uri, String localName, String type, String value)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 
resize(int length)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