/** * 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; } }