001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements. See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership. The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the  "License");
007     * you may not use this file except in compliance with the License.
008     * You may obtain a copy of the License at
009     *
010     *     http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing, software
013     * distributed under the License is distributed on an "AS IS" BASIS,
014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    /*
019     * $Id: AttributeList.java 468652 2006-10-28 07:05:17Z minchau $
020     */
021    
022    package org.apache.xalan.xsltc.runtime;
023    
024    import java.util.Vector;
025    
026    /**
027     * @author Morten Jorgensen
028     */
029    public class AttributeList implements org.xml.sax.Attributes {
030    
031        private final static String EMPTYSTRING = "";
032        private final static String CDATASTRING = "CDATA";
033    
034        private Hashtable _attributes;
035        private Vector    _names;
036        private Vector    _qnames;
037        private Vector    _values;
038        private Vector    _uris;
039        private int       _length;
040    
041        /**
042         * AttributeList constructor
043         */
044        public AttributeList() {
045            /*
046            _attributes = new Hashtable();
047            _names  = new Vector();
048            _values = new Vector();
049            _qnames = new Vector();
050            _uris   = new Vector();
051            */
052            _length = 0;
053        }
054    
055        /**
056         * Attributes clone constructor
057         */
058        public AttributeList(org.xml.sax.Attributes attributes) {
059            this();
060            if (attributes != null) {
061                final int count = attributes.getLength();
062                for (int i = 0; i < count; i++) {
063                    add(attributes.getQName(i),attributes.getValue(i));
064                }
065            }
066        }
067        
068        /**
069         * Allocate memory for the AttributeList
070         * %OPT% Use on-demand allocation for the internal vectors. The memory
071         * is only allocated when there is an attribute. This reduces the cost 
072         * of creating many small RTFs.
073         */
074        private void alloc() {
075            _attributes = new Hashtable();
076            _names  = new Vector();
077            _values = new Vector();
078            _qnames = new Vector();
079            _uris   = new Vector();        
080        }
081    
082        /**
083         * SAX2: Return the number of attributes in the list. 
084         */
085        public int getLength() {
086            return(_length);
087        }
088    
089        /**
090         * SAX2: Look up an attribute's Namespace URI by index.
091         */
092        public String getURI(int index) {
093            if (index < _length)
094                return((String)_uris.elementAt(index));
095            else
096                return(null);
097        }
098    
099        /**
100         * SAX2: Look up an attribute's local name by index.
101         */
102        public String getLocalName(int index) {
103            if (index < _length)
104                return((String)_names.elementAt(index));
105            else
106                return(null);
107        }
108    
109        /**
110         * Return the name of an attribute in this list (by position).
111         */
112        public String getQName(int pos) {
113            if (pos < _length)
114                return((String)_qnames.elementAt(pos));
115            else
116                return(null);
117        }
118    
119        /**
120         * SAX2: Look up an attribute's type by index.
121         */
122        public String getType(int index) {
123            return(CDATASTRING);
124        }
125    
126        /**
127         * SAX2: Look up the index of an attribute by Namespace name.
128         */
129        public int getIndex(String namespaceURI, String localPart) {
130            return(-1);
131        }
132    
133        /**
134         * SAX2: Look up the index of an attribute by XML 1.0 qualified name.
135         */
136        public int getIndex(String qname) {
137            return(-1);
138        }
139    
140        /**
141         * SAX2: Look up an attribute's type by Namespace name.
142         */
143        public String getType(String uri, String localName) {
144            return(CDATASTRING);
145        }
146    
147        /**
148         * SAX2: Look up an attribute's type by qname.
149         */
150        public String getType(String qname) {
151            return(CDATASTRING);
152        }
153    
154        /**
155         * SAX2: Look up an attribute's value by index.
156         */
157        public String getValue(int pos) {
158            if (pos < _length)
159                return((String)_values.elementAt(pos));
160            else
161                return(null);
162        }
163    
164        /**
165         * SAX2: Look up an attribute's value by qname.
166         */
167        public String getValue(String qname) {
168            if (_attributes != null) {
169                final Integer obj = (Integer)_attributes.get(qname);
170                if (obj == null) return null;
171                return(getValue(obj.intValue()));
172            }
173            else
174                return null;
175        }
176    
177        /**
178         * SAX2: Look up an attribute's value by Namespace name - SLOW!
179         */
180        public String getValue(String uri, String localName) {
181            return(getValue(uri+':'+localName));
182        }
183    
184        /**
185         * Adds an attribute to the list
186         */
187        public void add(String qname, String value) {
188            // Initialize the internal vectors at the first usage.
189            if (_attributes == null)
190                alloc();
191            
192            // Stuff the QName into the names vector & hashtable
193            Integer obj = (Integer)_attributes.get(qname);
194            if (obj == null) {
195                _attributes.put(qname, obj = new Integer(_length++));
196                _qnames.addElement(qname);
197                _values.addElement(value);
198                int col = qname.lastIndexOf(':');
199                if (col > -1) {
200                    _uris.addElement(qname.substring(0,col));
201                    _names.addElement(qname.substring(col+1));
202                }
203                else {
204                    _uris.addElement(EMPTYSTRING);
205                    _names.addElement(qname);
206                }
207            }
208            else {
209                final int index = obj.intValue();
210                _values.set(index, value);
211            }
212        }
213    
214        /**
215         * Clears the attribute list
216         */
217        public void clear() {
218            _length = 0;
219            if (_attributes != null) {
220                _attributes.clear();
221                _names.removeAllElements();
222                _values.removeAllElements();
223                _qnames.removeAllElements();
224                _uris.removeAllElements();
225            }
226        }
227        
228    }