/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
* ------------------------------------------------------------------------- *
* This software is published under the terms of the Apache Software License *
* version 1.1, a copy of which has been included with this distribution in *
* the LICENSE file. *
*****************************************************************************/
package org.apache.batik.bridge;
import java.io.InputStream;
import java.io.IOException;
import java.util.HashMap;
import org.apache.batik.dom.svg.SAXSVGDocumentFactory;
import org.apache.batik.dom.svg.SVGDocumentFactory;
import org.apache.batik.dom.util.DocumentDescriptor;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.svg.SVGDocument;
/**
* This class is responsible on loading an SVG document and
* maintaining a cache.
*
* @author <a href="mailto:Thierry.Kormann@sophia.inria.fr">Thierry Kormann</a>
* @version $Id: DocumentLoader.java,v 1.18 2003/07/10 02:01:26 deweese Exp $
*/
public class DocumentLoader {
/**
* The document factory used to create the document according a
* DOM implementation.
*/
protected SVGDocumentFactory documentFactory;
/**
* The map that contains the Document indexed by the URI.
*
* WARNING: tagged private as no element of this Map should be
* referenced outise of this class
*/
protected HashMap cacheMap = new HashMap();
/**
* The user agent.
*/
protected UserAgent userAgent;
/**
* The bridge context.
*/
protected BridgeContext bridgeContext;
/**
* Constructs a new <tt>DocumentLoader</tt>.
*/
protected DocumentLoader() { }
/**
* Constructs a new <tt>DocumentLoader</tt> with the specified XML parser.
* @param userAgent the user agent to use
*/
public DocumentLoader(UserAgent userAgent) {
this.userAgent = userAgent;
documentFactory = new SAXSVGDocumentFactory
(userAgent.getXMLParserClassName(), true);
documentFactory.setValidating(userAgent.isXMLParserValidating());
}
public Document checkCache(String uri) {
int n = uri.lastIndexOf('/');
if (n == -1)
n = 0;
n = uri.indexOf('#', n);
if (n != -1) {
uri = uri.substring(0, n);
}
DocumentState state = (DocumentState)cacheMap.get(uri);
if (state != null)
return state.document;
return null;
}
/**
* Returns a document from the specified uri.
* @param uri the uri of the document
* @exception IOException if an I/O error occured while loading
* the document
*/
public Document loadDocument(String uri) throws IOException {
Document ret = checkCache(uri);
if (ret != null)
return ret;
SVGDocument document = documentFactory.createSVGDocument(uri);
if (bridgeContext != null) {
bridgeContext.initializeDocument(document);
}
DocumentDescriptor desc = documentFactory.getDocumentDescriptor();
DocumentState state = new DocumentState(uri, document, desc);
cacheMap.put(uri, state);
return state.document;
}
/**
* Returns a document from the specified uri.
* @param uri the uri of the document
* @exception IOException if an I/O error occured while loading
* the document
*/
public Document loadDocument(String uri, InputStream is)
throws IOException {
Document ret = checkCache(uri);
if (ret != null)
return ret;
SVGDocument document = documentFactory.createSVGDocument(uri, is);
if (bridgeContext != null) {
bridgeContext.initializeDocument(document);
}
DocumentDescriptor desc = documentFactory.getDocumentDescriptor();
DocumentState state = new DocumentState(uri, document, desc);
cacheMap.put(uri, state);
return state.document;
}
/**
* Sets the bridge context.
*/
public void setBridgeContext(BridgeContext bc) {
bridgeContext = bc;
}
/**
* Returns the userAgent used by this DocumentLoader
*/
public UserAgent getUserAgent(){
return userAgent;
}
/**
* Disposes and releases all resources allocated by this document loader.
*/
public void dispose() {
//System.out.println("purge the cache");
cacheMap.clear();
}
/**
* Returns the line in the source code of the specified element or
* -1 if not found.
*
* @param e the element
* @return -1 the document has been removed from the cache or has not
* been loaded by this document loader.
*/
public int getLineNumber(Element e) {
String uri = ((SVGDocument)e.getOwnerDocument()).getURL();
DocumentState state = (DocumentState)cacheMap.get(uri);
if (state == null) {
return -1;
} else {
return state.desc.getLocationLine(e);
}
}
/**
* A simple class that contains a Document and its number of nodes.
*/
private static class DocumentState {
private String uri;
private Document document;
private DocumentDescriptor desc;
public DocumentState(String uri,
Document document,
DocumentDescriptor desc) {
this.uri = uri;
this.document = document;
this.desc = desc;
}
public DocumentDescriptor getDocumentDescriptor() {
return desc;
}
public String getURI() {
return uri;
}
public Document getDocument() {
return document;
}
}
}