001/* $Id: VariableAttributes.java 992060 2010-09-02 19:09:47Z simonetripodi $
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
020package org.apache.commons.digester.substitution;
021
022import org.xml.sax.Attributes;
023
024import 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
036public class VariableAttributes implements Attributes {
037
038    // list of mapped attributes.
039    private ArrayList<String> values = new ArrayList<String>(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 = 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}