/** * 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; import org.orbeon.oxf.common.OXFException; import org.orbeon.oxf.pipeline.api.PipelineContext; import org.orbeon.oxf.xml.XMLReceiver; import org.orbeon.oxf.xml.NamingConvention; import org.xml.sax.ContentHandler; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; /** * This is the class that must be extended to create a custom processor. See the <a * href="http://wiki.orbeon.com/forms/doc/developer-guide/api-xpl-processor-api">Processor API section</a> for more information. */ public abstract class SimpleProcessor extends ProcessorImpl { private static final String GENERATE = "generate"; private Map<String, Method> outputToMethod = new HashMap<String, Method>(); /** * This constructor must be called by subclasses. * * Iterate through the generateXxx() methods and stores a reference to the method in outputToMethod. * * This checks for the following signatures: * * generateXxx(PipelineContext context, XMLReceiver xmlReceiver) * generateXxx(PipelineContext context, ContentHandler contentHandler) * * For a given "Xxx", only one of the two methods should be implemented. If both are present, the ContentHandler * version is ignored. */ public SimpleProcessor() { final Method[] methods = getClass().getDeclaredMethods(); for (final Method method : methods) { final Class[] parameterTypes = method.getParameterTypes(); if (method.getName().startsWith(GENERATE) && parameterTypes.length == 2 && parameterTypes[0].equals(PipelineContext.class) && (parameterTypes[1].equals(XMLReceiver.class) || parameterTypes[1].equals(ContentHandler.class))) { final String javaName = method.getName().substring(GENERATE.length()); outputToMethod.put(NamingConvention.javaToXMLName(javaName), method); } } } /** * Create an output. Delegate processing to the appropriate generateXXX() method. */ @Override public ProcessorOutput createOutput(final String name) { final ProcessorOutput output = new ProcessorOutputImpl(SimpleProcessor.this, name) { public void readImpl(PipelineContext context, XMLReceiver xmlReceiver) { try { final Method method = outputToMethod.get(name); if (method == null) throw new OXFException("Cannot find \"generate\" method for output \"" + name + "\" in class \"" + SimpleProcessor.this.getClass().getName() + "\""); method.invoke(SimpleProcessor.this, context, xmlReceiver); } catch (Exception e) { throw new OXFException(e); } } }; addOutput(name, output); return output; } }