001    /* $Id: VariableAttributes.java 471661 2006-11-06 08:09:25Z skitching $
002     *
003     * Licensed to the Apache Software Foundation (ASF) under one or more
004     * contributor license agreements.  See the NOTICE file distributed with
005     * this work for additional information regarding copyright ownership.
006     * The ASF licenses this file to You under the Apache License, Version 2.0
007     * (the "License"); you may not use this file except in compliance with
008     * the License.  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    
020    package org.apache.commons.digester.substitution;
021    
022    import org.xml.sax.Attributes;
023    
024    import java.util.ArrayList;
025    
026    
027    /**
028     * <p>Wrapper for an org.xml.sax.Attributes object which expands any 
029     * "variables" referenced in the attribute value via ${foo} or similar. 
030     * This is only done when something actually asks for the attribute value, 
031     * thereby imposing no performance penalty if the attribute is not used.</p>
032     *
033     * @since 1.6
034     */
035    
036    public class VariableAttributes implements Attributes {
037    
038        // list of mapped attributes.
039        private ArrayList values = new ArrayList(10);
040    
041        private Attributes attrs;
042        private VariableExpander expander;
043        
044        // ------------------- Public Methods
045        
046        /**
047         * Specify which attributes class this object is a proxy for.
048         */
049        public void init(Attributes attrs, VariableExpander expander) {
050            this.attrs = attrs;
051            this.expander = expander;
052    
053            // I hope this doesn't release the memory for this array; for 
054            // efficiency, this should just mark the array as being size 0.
055            values.clear(); 
056        }
057    
058        public String getValue(int index) {
059            if (index >= values.size()) {
060                // Expand the values array with null elements, so the later
061                // call to set(index, s) works ok.
062                //
063                // Unfortunately, there is no easy way to set the size of
064                // an arraylist; we must repeatedly add null elements to it..
065                values.ensureCapacity(index+1);
066                for(int i = values.size(); i<= index; ++i) {
067                    values.add(null);
068                }
069            }
070            
071            String s = (String) values.get(index);
072            
073            if (s == null) {
074                // we have never been asked for this value before.
075                // get the real attribute value and perform substitution
076                // on it.
077                s = attrs.getValue(index);
078                if (s != null) {
079                    s = expander.expand(s);
080                    values.set(index, s);
081                }
082            }
083            
084            return s;
085        }
086        
087        public String getValue(String qname) {
088            int index = attrs.getIndex(qname);
089            if (index == -1) {
090                return null;
091            }
092            return getValue(index);
093        }
094        
095        public String getValue(String uri, String localname) {
096            int index = attrs.getIndex(uri, localname);
097            if (index == -1) {
098                return null;
099            }
100            return getValue(index);
101        }
102        
103        // plain proxy methods follow : nothing interesting :-)
104        public int getIndex(String qname) {
105            return attrs.getIndex(qname); 
106        }
107        
108        public int getIndex(String uri, String localpart) {
109            return attrs.getIndex(uri, localpart); 
110        }
111        
112        public int getLength() {
113            return attrs.getLength();
114        }
115        
116        public String getLocalName(int index) {
117            return attrs.getLocalName(index);
118        }
119        
120        public String getQName(int index) {
121            return attrs.getQName(index);
122        }
123        
124        public String getType(int index) {
125            return attrs.getType(index);
126        }
127    
128        public String getType(String qname) {
129            return attrs.getType(qname);
130        }
131        
132        public String getType(String uri, String localname) {
133            return attrs.getType(uri, localname);
134        }
135        
136        public String getURI(int index) {
137            return attrs.getURI(index);
138        }
139     
140    }