001/*
002 * Copyright 2001 (C) MetaStuff, Ltd. All Rights Reserved.
003 * 
004 * This software is open source. 
005 * See the bottom of this file for the licence.
006 * 
007 * $Id: QNameCache.java,v 1.6 2001/08/28 06:43:18 jstrachan Exp $
008 */
009
010package org.dom4j.tree;
011
012import java.util.ArrayList;
013import java.util.HashMap;
014import java.util.Iterator;
015import java.util.List;
016import java.util.Map;
017
018import org.dom4j.DocumentFactory;
019import org.dom4j.QName;
020import org.dom4j.Namespace;
021
022/** <p><code>QNameCache</code> caches instances of <code>QName</code> 
023  * for reuse both across documents and within documents.</p>
024  *
025  * @author <a href="mailto:james.strachan@metastuff.com">James Strachan</a>
026  * @version $Revision: 1.6 $
027  */
028public class QNameCache {
029
030    /** Cache of {@link QName} instances with no namespace */ 
031    protected Map noNamespaceCache = new HashMap();
032    
033    /** Cache of {@link Map} instances indexed by namespace which contain 
034      * caches of {@link QName} for each name
035      */ 
036    protected Map namespaceCache = new HashMap();
037
038    /** The document factory associated with new QNames instances in this cache
039      * or null if no instances should be associated by default 
040      */
041    private DocumentFactory documentFactory;
042    
043    
044    public QNameCache() {
045    }
046
047    public QNameCache(DocumentFactory documentFactory) {
048        this.documentFactory = documentFactory;
049    }
050
051    /** Returns a list of all the QName instances currently used
052     */
053    public List getQNames() {
054        List answer = new ArrayList();
055        answer.addAll( noNamespaceCache.values() );
056        for ( Iterator iter = namespaceCache.values().iterator(); iter.hasNext(); ) {
057            Map map = (Map) iter.next();
058            answer.addAll( map.values() );
059        }
060        return answer;
061    }
062    
063    /** @return the QName for the given name and no namepsace 
064      */
065    public QName get(String name) {
066        QName answer = (QName) noNamespaceCache.get(name);
067        if (answer == null) {
068            answer = createQName(name);
069            answer.setDocumentFactory( documentFactory );
070            noNamespaceCache.put(name, answer);
071        }
072        return answer;
073    }
074    
075    /** @return the QName for the given local name and namepsace 
076      */
077    public QName get(String name, Namespace namespace) {
078        Map cache = getNamespaceCache(namespace);
079        QName answer = (QName) cache.get(name);
080        if (answer == null) {
081            answer = createQName(name, namespace);
082            answer.setDocumentFactory( documentFactory );
083            cache.put(name, answer);
084        }
085        return answer;
086    }
087    
088
089    /** @return the QName for the given local name, qualified name and namepsace 
090      */
091    public QName get(String localName, Namespace namespace, String qualifiedName) {
092        Map cache = getNamespaceCache(namespace);
093        QName answer = (QName) cache.get(localName);
094        if (answer == null) {
095            answer = createQName(localName, namespace, qualifiedName);
096            answer.setDocumentFactory( documentFactory );
097            cache.put(localName, answer);
098        }
099        return answer;
100    }
101
102    
103    public QName get(String qualifiedName, String uri) {
104        int index = qualifiedName.indexOf( ':' );
105        if ( index < 0 ) {
106            return get( qualifiedName, Namespace.get( uri ) );
107        }
108        else {
109            String name = qualifiedName.substring( index + 1 );
110            String prefix = qualifiedName.substring( 0, index );
111            return get(name, Namespace.get( prefix, uri ));
112        }
113    }
114    
115    
116    /** @return the cached QName instance if there is one or adds the given
117      * qname to the cache if not 
118       */
119    public QName intern(QName qname) {
120        return get(qname.getName(), qname.getNamespace(), qname.getQualifiedName());
121    }
122
123    /** @return the cache for the given namespace. If one does not
124      * currently exist it is created.
125      */
126    protected Map getNamespaceCache(Namespace namespace) {
127        if (namespace == Namespace.NO_NAMESPACE) {
128            return noNamespaceCache;
129        }
130        Map answer = (Map) namespaceCache.get(namespace);
131        if (answer == null) {
132            answer = createMap();
133            namespaceCache.put(namespace, answer);
134        }
135        return answer;
136    }
137    
138    /** A factory method
139      * @return a newly created {@link Map} instance.
140      */
141    protected Map createMap() {
142        return new HashMap();
143    }
144    
145    /** Factory method to create a new QName object
146      * which can be overloaded to create derived QName instances
147      */
148    protected QName createQName(String name) {
149        return new QName(name);
150    }
151    
152    /** Factory method to create a new QName object
153      * which can be overloaded to create derived QName instances
154      */
155    protected QName createQName(String name, Namespace namespace) {
156        return new QName(name, namespace);
157    }
158    
159    /** Factory method to create a new QName object
160      * which can be overloaded to create derived QName instances
161      */
162    protected QName createQName(String name, Namespace namespace, String qualifiedName) {
163        return new QName(name, namespace, qualifiedName);
164    }
165}
166
167
168
169
170/*
171 * Redistribution and use of this software and associated documentation
172 * ("Software"), with or without modification, are permitted provided
173 * that the following conditions are met:
174 *
175 * 1. Redistributions of source code must retain copyright
176 *    statements and notices.  Redistributions must also contain a
177 *    copy of this document.
178 *
179 * 2. Redistributions in binary form must reproduce the
180 *    above copyright notice, this list of conditions and the
181 *    following disclaimer in the documentation and/or other
182 *    materials provided with the distribution.
183 *
184 * 3. The name "DOM4J" must not be used to endorse or promote
185 *    products derived from this Software without prior written
186 *    permission of MetaStuff, Ltd.  For written permission,
187 *    please contact dom4j-info@metastuff.com.
188 *
189 * 4. Products derived from this Software may not be called "DOM4J"
190 *    nor may "DOM4J" appear in their names without prior written
191 *    permission of MetaStuff, Ltd. DOM4J is a registered
192 *    trademark of MetaStuff, Ltd.
193 *
194 * 5. Due credit should be given to the DOM4J Project
195 *    (http://dom4j.org/).
196 *
197 * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS
198 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
199 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
200 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
201 * METASTUFF, LTD. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
202 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
203 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
204 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
205 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
206 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
207 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
208 * OF THE POSSIBILITY OF SUCH DAMAGE.
209 *
210 * Copyright 2001 (C) MetaStuff, Ltd. All Rights Reserved.
211 *
212 * $Id: QNameCache.java,v 1.6 2001/08/28 06:43:18 jstrachan Exp $
213 */