/**
* Copyright (C) 2010 Orbeon, Inc.
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU Lesser General Public License as published by the Free Software Foundation; either version
* 2.1 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* The full text of the license is available at http://www.gnu.org/copyleft/lesser.html
*/
package org.orbeon.oxf.processor.pipeline;
import org.orbeon.dom.Element;
import org.orbeon.oxf.cache.*;
import org.orbeon.oxf.common.OXFException;
import org.orbeon.oxf.common.ValidationException;
import org.orbeon.oxf.pipeline.api.PipelineContext;
import org.orbeon.oxf.xml.SAXUtils;
import org.orbeon.oxf.xml.XMLReceiver;
import org.orbeon.oxf.processor.*;
import org.orbeon.oxf.processor.impl.CacheableTransformerOutputImpl;
import org.orbeon.oxf.xml.EmbeddedDocumentXMLReceiver;
import org.orbeon.oxf.xml.dom4j.LocationData;
import org.xml.sax.SAXException;
import java.util.*;
public class AggregatorProcessor extends ProcessorImpl {
public static final String AGGREGATOR_NAMESPACE_URI = "http://www.orbeon.com/oxf/pipeline/aggregator";
public AggregatorProcessor() {
addInputInfo(new ProcessorInputOutputInfo(INPUT_CONFIG, AGGREGATOR_NAMESPACE_URI));
addInputInfo(new ProcessorInputOutputInfo(INPUT_DATA));
addOutputInfo(new ProcessorInputOutputInfo(OUTPUT_DATA));
}
@Override
public ProcessorOutput createOutput(String name) {
final ProcessorOutput output = new CacheableTransformerOutputImpl(AggregatorProcessor.this, name) {
public void readImpl(PipelineContext context, XMLReceiver xmlReceiver) {
try {
// Read config
final Element config = readCacheInputAsDOM4J(context, INPUT_CONFIG).getRootElement();
final String rootQName = config.element("root").getText();
final String rootPrefix;
final String rootLocalName;
final String rootNamespaceURI;
// Get declared namespaces
int columnPosition = rootQName.indexOf(':');
if (columnPosition == -1) {
rootPrefix = "";
rootLocalName = rootQName;
rootNamespaceURI = "";
} else {
rootPrefix = rootQName.substring(0, columnPosition);
rootLocalName = rootQName.substring(columnPosition + 1);
String tempNamespaceURI = null;
for (Iterator i = config.elements("namespace").iterator(); i.hasNext();) {
Element namespaceElement = (Element) i.next();
if (namespaceElement.attributeValue("prefix").equals(rootPrefix)) {
tempNamespaceURI = namespaceElement.attributeValue("uri");
break;
}
}
if (tempNamespaceURI == null)
throw new ValidationException("Undeclared namespace prefix '" + rootPrefix + "'",
(LocationData) config.getData());
rootNamespaceURI = tempNamespaceURI;
}
// Start document
xmlReceiver.startDocument();
if (!rootNamespaceURI.equals(""))
xmlReceiver.startPrefixMapping(rootPrefix, rootNamespaceURI);
xmlReceiver.startElement(rootNamespaceURI, rootLocalName, rootQName, SAXUtils.EMPTY_ATTRIBUTES);
// Processor input processors
for (Iterator i = getInputsByName(INPUT_DATA).iterator(); i.hasNext();) {
ProcessorInput input = (ProcessorInput) i.next();
readInputAsSAX(context, input, new EmbeddedDocumentXMLReceiver(xmlReceiver));
}
// End document
xmlReceiver.endElement(rootNamespaceURI, rootLocalName, rootQName);
if (!rootNamespaceURI.equals(""))
xmlReceiver.endPrefixMapping(rootPrefix);
xmlReceiver.endDocument();
} catch (SAXException e) {
throw new OXFException(e);
}
}
@Override
public OutputCacheKey getKeyImpl(PipelineContext pipelineContext) {
// Create input information
final List<CacheKey> keys = new ArrayList<CacheKey>();
for (final List<ProcessorInput> inputs : getConnectedInputs().values()) {
for (final ProcessorInput input : inputs) {
final OutputCacheKey outputKey = getInputKey(pipelineContext, input);
if (outputKey == null) {
return null;
}
keys.add(outputKey);
}
}
// Add local key if needed
if (supportsLocalKeyValidity()) {
final CacheKey localKey = getLocalKey(pipelineContext);
if (localKey == null) {
return null;
}
keys.add(localKey);
}
// Concatenate current processor info and input info
final CacheKey[] outputKeys = new CacheKey[ keys.size() ];
keys.toArray(outputKeys);
final Class processorClass = getProcessorClass();
final String outputName = getName();
return new CompoundOutputCacheKey(processorClass, outputName, outputKeys);
}
};
addOutput(name, output);
return output;
}
}