1 package org.daisy.pipeline.braille.common.calabash.impl;
2
3 import java.util.ArrayList;
4 import java.util.Hashtable;
5 import java.util.List;
6 import java.util.Map;
7 import java.util.NoSuchElementException;
8
9 import javax.xml.namespace.QName;
10
11 import com.google.common.collect.ImmutableMap;
12 import com.xmlcalabash.core.XProcException;
13 import com.xmlcalabash.core.XProcRuntime;
14 import com.xmlcalabash.io.ReadablePipe;
15 import com.xmlcalabash.io.WritablePipe;
16 import com.xmlcalabash.library.DefaultStep;
17 import com.xmlcalabash.model.RuntimeValue;
18 import com.xmlcalabash.runtime.XAtomicStep;
19
20 import net.sf.saxon.s9api.SaxonApiException;
21
22 import org.daisy.common.transform.TransformerException;
23 import org.daisy.common.transform.XMLTransformer;
24 import org.daisy.common.xproc.calabash.XMLCalabashInputValue;
25 import org.daisy.common.xproc.calabash.XMLCalabashOutputValue;
26 import org.daisy.common.xproc.calabash.XMLCalabashParameterInputValue;
27 import org.daisy.common.xproc.calabash.XProcStep;
28 import org.daisy.common.xproc.calabash.XProcStepProvider;
29 import org.daisy.common.xproc.XProcMonitor;
30 import org.daisy.pipeline.braille.common.Transform;
31 import org.daisy.pipeline.braille.common.TransformProvider;
32 import org.daisy.pipeline.braille.common.Query;
33 import static org.daisy.pipeline.braille.common.Query.util.query;
34 import static org.daisy.pipeline.braille.common.TransformProvider.util.dispatch;
35 import static org.daisy.pipeline.braille.common.TransformProvider.util.logSelect;
36 import org.daisy.pipeline.braille.common.XMLTransform;
37
38 import org.osgi.service.component.annotations.Component;
39 import org.osgi.service.component.annotations.Reference;
40 import org.osgi.service.component.annotations.ReferenceCardinality;
41 import org.osgi.service.component.annotations.ReferencePolicy;
42
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45
46 public class PxTransformStep extends DefaultStep implements XProcStep {
47
48 private final XProcMonitor monitor;
49 private final Map<String,String> properties;
50 private final TransformProvider<Transform> provider;
51 private ReadablePipe source = null;
52 private WritablePipe result = null;
53 private final Hashtable<net.sf.saxon.s9api.QName,RuntimeValue> params = new Hashtable<>();
54
55 private static final net.sf.saxon.s9api.QName _query = new net.sf.saxon.s9api.QName("query");
56
57 private PxTransformStep(XProcRuntime runtime,
58 XAtomicStep step,
59 XProcMonitor monitor,
60 Map<String,String> properties,
61 TransformProvider<Transform> provider) {
62 super(runtime, step);
63 this.monitor = monitor;
64 this.properties = properties;
65 this.provider = provider;
66 }
67
68 @Override
69 public void setInput(String port, ReadablePipe pipe) {
70 source = pipe;
71 }
72
73 @Override
74 public void setOutput(String port, WritablePipe pipe) {
75 result = pipe;
76 }
77
78 @Override
79 public void reset() {
80 source.resetReader();
81 result.resetWriter();
82 }
83
84 @Override
85 public void setParameter(net.sf.saxon.s9api.QName name, RuntimeValue value) {
86 params.put(name, value);
87 }
88
89 @Override
90 public void setParameter(String port, net.sf.saxon.s9api.QName name, RuntimeValue value) {
91 setParameter(name, value);
92 }
93
94 @Override
95 public void run() throws SaxonApiException {
96 try {
97 Query query = query(getOption(_query).getString());
98 XMLTransformer xmlTransformer = null;
99 try {
100 for (Transform t : logSelect(query, provider, logger))
101 if (t instanceof XProcStepProvider) {
102
103 xmlTransformer = ((XProcStepProvider)t).newStep(runtime, step, monitor, properties);
104 break; }
105 else if (t instanceof XMLTransform) {
106
107
108 xmlTransformer = ((XMLTransform)t).fromXmlToXml();
109 break; }}
110 catch (NoSuchElementException e) {}
111 if (xmlTransformer == null)
112 throw new XProcException(step, "Could not find a Transform for query: " + query);
113 xmlTransformer.transform(
114 ImmutableMap.of(
115 new QName("source"), new XMLCalabashInputValue(source),
116 new QName("parameters"), new XMLCalabashParameterInputValue(params)),
117 ImmutableMap.of(
118 new QName("result"), new XMLCalabashOutputValue(result, runtime))
119 ).run();
120 } catch (Throwable e) {
121 if (e instanceof TransformerException && e.getCause() instanceof XProcException)
122
123 throw (XProcException)e.getCause();
124 else
125 throw XProcStep.raiseError(e, step);
126 }
127 super.run();
128 }
129
130 @Component(
131 name = "px:transform",
132 service = { XProcStepProvider.class },
133 property = { "type:String={http://www.daisy.org/ns/pipeline/xproc}transform" }
134 )
135 public static class StepProvider implements XProcStepProvider {
136
137 @Override
138 public XProcStep newStep(XProcRuntime runtime, XAtomicStep step, XProcMonitor monitor, Map<String,String> properties) {
139 return new PxTransformStep(runtime, step, monitor, properties, provider);
140 }
141
142 @Reference(
143 name = "XProcTransformProvider",
144 unbind = "-",
145 service = TransformProvider.class,
146 cardinality = ReferenceCardinality.MULTIPLE,
147 policy = ReferencePolicy.STATIC
148 )
149 @SuppressWarnings(
150 "unchecked"
151 )
152 public void bindXProcTransformProvider(TransformProvider<?> provider) {
153 providers.add((TransformProvider<Transform>)provider);
154 logger.debug("Adding XProcTransform provider: {}", provider);
155 }
156
157 public void unbindXProcTransformProvider(TransformProvider<?> provider) {
158 providers.remove(provider);
159 logger.debug("Removing XProcTransform provider: {}", provider);
160 }
161
162 private List<TransformProvider<Transform>> providers = new ArrayList<>();
163 private TransformProvider<Transform> provider = dispatch(providers).withContext(logger);
164
165 }
166
167 private static final Logger logger = LoggerFactory.getLogger(PxTransformStep.class);
168
169 }