blob: 4a6904f7306c65351757ec563786dccb0ea1fb94 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* $Id$ */
package org.apache.fop.fo;
import java.util.Iterator;
import java.util.Map;
import org.w3c.dom.DOMImplementation;
import org.xml.sax.Locator;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xmlgraphics.util.Service;
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FopFactory;
import org.apache.fop.fo.ElementMapping.Maker;
/**
* This class keeps track of all configured ElementMapping implementations which are responsible
* for properly handling all kinds of different XML namespaces.
*/
public class ElementMappingRegistry {
/** logging instance */
protected Log log = LogFactory.getLog(ElementMappingRegistry.class);
/**
* Table mapping element names to the makers of objects
* representing formatting objects.
*/
protected Map fobjTable = new java.util.HashMap();
/**
* Map of mapped namespaces and their associated ElementMapping instances.
*/
protected Map namespaces = new java.util.HashMap();
/**
* Main constructor. Adds all default element mapping as well as detects ElementMapping
* through the Service discovery.
* @param factory the Fop Factory
*/
public ElementMappingRegistry(FopFactory factory) {
// Add standard element mappings
setupDefaultMappings();
}
/**
* Sets all the element and property list mappings to their default values.
*/
private void setupDefaultMappings() {
// add mappings from available services
Iterator providers = Service.providers(ElementMapping.class, false);
if (providers != null) {
while (providers.hasNext()) {
String mapping = (String)providers.next();
try {
addElementMapping(mapping);
} catch (IllegalArgumentException e) {
log.warn("Error while adding element mapping", e);
}
}
}
}
/**
* Add the element mapping with the given class name.
* @param mappingClassName the class name representing the element mapping.
* @throws IllegalArgumentException if there was not such element mapping.
*/
public void addElementMapping(String mappingClassName)
throws IllegalArgumentException {
try {
ElementMapping mapping
= (ElementMapping)Class.forName(mappingClassName).newInstance();
addElementMapping(mapping);
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("Could not find "
+ mappingClassName);
} catch (InstantiationException e) {
throw new IllegalArgumentException("Could not instantiate "
+ mappingClassName);
} catch (IllegalAccessException e) {
throw new IllegalArgumentException("Could not access "
+ mappingClassName);
} catch (ClassCastException e) {
throw new IllegalArgumentException(mappingClassName
+ " is not an ElementMapping");
}
}
/**
* Add the element mapping.
* @param mapping the element mapping instance
*/
public void addElementMapping(ElementMapping mapping) {
this.fobjTable.put(mapping.getNamespaceURI(), mapping.getTable());
this.namespaces.put(mapping.getNamespaceURI().intern(), mapping);
}
/**
* Finds the Maker used to create node objects of a particular type
* @param namespaceURI URI for the namespace of the element
* @param localName name of the Element
* @param locator the Locator instance for context information
* @return the ElementMapping.Maker that can create an FO object for this element
* @throws FOPException if a Maker could not be found for a bound namespace.
*/
public Maker findFOMaker(String namespaceURI, String localName, Locator locator)
throws FOPException {
Map table = (Map)fobjTable.get(namespaceURI);
Maker fobjMaker = null;
if (table != null) {
fobjMaker = (Maker)table.get(localName);
// try default
if (fobjMaker == null) {
fobjMaker = (Maker)table.get(ElementMapping.DEFAULT);
}
}
if (fobjMaker == null) {
if (namespaces.containsKey(namespaceURI.intern())) {
throw new FOPException(FONode.errorText(locator)
+ "No element mapping definition found for "
+ FONode.getNodeString(namespaceURI, localName), locator);
} else {
fobjMaker = new UnknownXMLObj.Maker(namespaceURI);
}
}
return fobjMaker;
}
/**
* Tries to determine the DOMImplementation that is used to handled a particular namespace.
* The method may return null for namespaces that don't result in a DOM. It is mostly used
* in namespaces occurring in foreign objects.
* @param namespaceURI the namespace URI
* @return the handling DOMImplementation, or null if not applicable
*/
public DOMImplementation getDOMImplementationForNamespace(String namespaceURI) {
ElementMapping mapping = (ElementMapping)this.namespaces.get(namespaceURI);
if (mapping == null) {
return null;
} else {
return mapping.getDOMImplementation();
}
}
/**
* Returns an ElementMapping class for a namespace URI if there is one.
* @param namespaceURI the namespace URI
* @return the requested ElementMapping or null, if no ElementMapping for the namespace is
* available.
*/
public ElementMapping getElementMapping(String namespaceURI) {
return (ElementMapping)this.namespaces.get(namespaceURI);
}
/**
* Indicates whether a namespace is known to FOP.
* @param namespaceURI the namespace URI
* @return true if the namespace is known.
*/
public boolean isKnownNamespace(String namespaceURI) {
return this.namespaces.containsKey(namespaceURI);
}
}