Java tutorial
/* * Copyright (C) 2007 Herve Quiroz * * This library 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 library 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. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * $Id$ */ package org.trancecode.xproc; import com.google.common.base.Function; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.google.common.collect.Maps; import java.io.IOException; import java.net.URI; import java.net.URL; import java.util.Map; import java.util.ServiceLoader; import java.util.Set; import java.util.concurrent.ExecutorService; import javax.xml.transform.Source; import javax.xml.transform.URIResolver; import javax.xml.transform.stream.StreamSource; import net.sf.saxon.s9api.Processor; import net.sf.saxon.s9api.QName; import org.trancecode.concurrent.TaskExecutor; import org.trancecode.concurrent.TaskExecutors; import org.trancecode.event.EventDispatcher; import org.trancecode.event.EventDispatchers; import org.trancecode.io.DefaultInputResolver; import org.trancecode.io.DefaultOutputResolver; import org.trancecode.io.InputResolver; import org.trancecode.io.OutputResolver; import org.trancecode.logging.Logger; import org.trancecode.xproc.event.XProcEvent; import org.trancecode.xproc.step.CoreStepProcessor; import org.trancecode.xproc.step.Step; import org.trancecode.xproc.step.StepProcessor; import org.trancecode.xproc.step.StepProcessors; import org.trancecode.xproc.step.XProcSteps; import org.trancecode.xproc.xpath.XPathExtensionFunction; /** * @author Herve Quiroz */ public final class PipelineConfiguration extends AbstractPipelineContext { private static final String RESOURCE_PATH_XPROC_LIBRARY_1_0 = "/org/trancecode/xproc/tubular.xpl"; private static final Map<QName, StepProcessor> DEFAULT_STEP_PROCESSORS = getDefaultStepProcessors(); private static final Map<QName, Step> CORE_LIBRARY = getCoreLibrary(); private static final Iterable<XPathExtensionFunction> EXTENSION_FUNCTIONS = ImmutableList .copyOf(ServiceLoader.load(XPathExtensionFunction.class)); private static final URI DEFAULT_LIBRARY_URI = URI.create("trancecode:tubular:default-library.xpl"); private static final Set<URI> EMPTY_SET_OF_URIS = ImmutableSet.of(); private static final Logger LOG = Logger.getLogger(PipelineConfiguration.class); private static final PipelineLibrary DEFAULT_PIPELINE_LIBRARY = getDefaultPipelineLibrary(); private static PipelineLibrary getDefaultPipelineLibrary() { final Map<String, Object> properties = Maps.newHashMap(); properties.put(PROPERTY_EVENT_DISPATCHER, newEventDispatcher()); properties.put(PROPERTY_EXECUTOR, TaskExecutors.onDemandExecutor()); final Processor processor = new Processor(false); properties.put(PROPERTY_PROCESSOR, processor); properties.put(PROPERTY_URI_RESOLVER, processor.getUnderlyingConfiguration().getURIResolver()); properties.put(PROPERTY_PIPELINE_LIBRARY, new PipelineLibrary(DEFAULT_LIBRARY_URI, CORE_LIBRARY, EMPTY_SET_OF_URIS, null)); properties.put(PROPERTY_STEP_PROCESSORS, DEFAULT_STEP_PROCESSORS); final PipelineContext context = new ImmutablePipelineContext(properties); final URL xprocLibraryUrl = PipelineConfiguration.class.getResource(RESOURCE_PATH_XPROC_LIBRARY_1_0); final Source defaultLibrarySource; try { defaultLibrarySource = new StreamSource(xprocLibraryUrl.openStream(), xprocLibraryUrl.toString()); } catch (final IOException e) { throw new IllegalStateException("cannot parse default library: " + xprocLibraryUrl, e); } final PipelineLibrary library = PipelineParser.parseLibrary(context, defaultLibrarySource); LOG.trace("supported steps: {}", library.getStepTypes()); return library; } private static EventDispatcher<XProcEvent> newEventDispatcher() { return EventDispatchers.newEventDispatcher(); } private static Map<QName, StepProcessor> getDefaultStepProcessors() { final Map<QName, StepProcessor> processors = Maps.newHashMap(); final Map<QName, StepProcessor> availableProcessors = Maps .uniqueIndex(ServiceLoader.load(StepProcessor.class), stepProcessor -> stepProcessor.getStepType()); processors.putAll(availableProcessors); for (final QName stepType : Iterables.concat(XProcSteps.REQUIRED_STEPS, XProcSteps.OPTIONAL_STEPS)) { if (!processors.containsKey(stepType)) { processors.put(stepType, StepProcessors.unsupportedStepProcessor(stepType)); } } return ImmutableMap.copyOf(processors); } private static Map<QName, Step> getCoreLibrary() { final Map<QName, Step> coreSteps = Maps.newHashMap(); for (final CoreStepProcessor coreStepProcessor : ServiceLoader.load(CoreStepProcessor.class)) { coreSteps.put(coreStepProcessor.getStepType(), coreStepProcessor.getStepDeclaration()); } return ImmutableMap.copyOf(coreSteps); } public PipelineConfiguration() { this(new Processor(false)); } private static Map<String, Object> newEmptyPropertiesMap() { return Maps.newHashMap(); } public PipelineConfiguration(final Processor processor) { super(newEmptyPropertiesMap()); getProperties().put(PROPERTY_EVENT_DISPATCHER, newEventDispatcher()); getProperties().put(PROPERTY_EXECUTOR, TaskExecutors.onDemandExecutor()); getProperties().put(PROPERTY_INPUT_RESOLVER, DefaultInputResolver.INSTANCE); getProperties().put(PROPERTY_OUTPUT_RESOLVER, DefaultOutputResolver.INSTANCE); getProperties().put(PROPERTY_PIPELINE_LIBRARY, DEFAULT_PIPELINE_LIBRARY); getProperties().put(PROPERTY_PROCESSOR, Preconditions.checkNotNull(processor)); getProperties().put(PROPERTY_STEP_PROCESSORS, Maps.newHashMap(DEFAULT_STEP_PROCESSORS)); getProperties().put(PROPERTY_URI_RESOLVER, processor.getUnderlyingConfiguration().getURIResolver()); for (final XPathExtensionFunction function : EXTENSION_FUNCTIONS) { LOG.trace("register XPath extension function: {}", function); processor.registerExtensionFunction(function.getExtensionFunctionDefinition()); } } public void setExecutor(final TaskExecutor executor) { getProperties().put(PROPERTY_EXECUTOR, Preconditions.checkNotNull(executor)); } public void setExecutor(final ExecutorService executor) { setExecutor(TaskExecutors.forExecutorService(executor)); } public void setInputResolver(final InputResolver inputResolver) { getProperties().put(PROPERTY_INPUT_RESOLVER, Preconditions.checkNotNull(inputResolver)); } public void setUriResolver(final URIResolver uriResolver) { getProperties().put(PROPERTY_URI_RESOLVER, Preconditions.checkNotNull(uriResolver)); } public void setOutputResolver(final OutputResolver outputResolver) { getProperties().put(PROPERTY_OUTPUT_RESOLVER, Preconditions.checkNotNull(outputResolver)); } public void registerStepProcessor(final StepProcessor stepProcessor) { Preconditions.checkNotNull(stepProcessor); final Map<QName, StepProcessor> stepProcessors = getProperty(PROPERTY_STEP_PROCESSORS); stepProcessors.put(stepProcessor.getStepType(), stepProcessor); } public void registerPipelineLibrary(final PipelineLibrary library) { Preconditions.checkNotNull(library); getProperties().put(PROPERTY_PIPELINE_LIBRARY, library.importLibrary(getPipelineLibrary())); } public void setProperty(final String name, final Object value) { properties.put(name, value); } }