1 package org.daisy.pipeline.common.calabash.impl;
2
3 import java.util.Map;
4
5 import com.xmlcalabash.core.XProcRuntime;
6 import com.xmlcalabash.io.ReadablePipe;
7 import com.xmlcalabash.io.WritablePipe;
8 import com.xmlcalabash.library.DefaultStep;
9 import com.xmlcalabash.model.RuntimeValue;
10 import com.xmlcalabash.model.Step;
11 import com.xmlcalabash.runtime.XAtomicStep;
12
13 import net.sf.saxon.s9api.QName;
14 import net.sf.saxon.s9api.SaxonApiException;
15 import net.sf.saxon.s9api.XdmNode;
16
17 import org.daisy.common.saxon.SaxonHelper;
18 import org.daisy.common.xproc.calabash.XMLCalabashInputValue;
19 import org.daisy.common.xproc.calabash.XMLCalabashOutputValue;
20 import org.daisy.common.xproc.calabash.XProcStep;
21 import org.daisy.common.xproc.calabash.XProcStepProvider;
22 import org.daisy.common.xproc.XProcMonitor;
23
24 import org.osgi.service.component.annotations.Component;
25
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28
29 public class ChunkerStep extends DefaultStep implements XProcStep {
30
31 @Component(
32 name = "px:chunker",
33 service = { XProcStepProvider.class },
34 property = { "type:String={http://www.daisy.org/ns/pipeline/xproc}xml-chunker" }
35 )
36 public static class Provider implements XProcStepProvider {
37
38 @Override
39 public XProcStep newStep(XProcRuntime runtime, XAtomicStep step, XProcMonitor monitor, Map<String,String> properties) {
40 return new ChunkerStep(runtime, step);
41 }
42 }
43
44 private ReadablePipe sourcePipe = null;
45 private WritablePipe resultPipe = null;
46 private WritablePipe mappingPipe = null;
47
48 private static final QName ALLOW_BREAK_BEFORE = new QName("allow-break-before");
49 private static final QName ALLOW_BREAK_AFTER = new QName("allow-break-after");
50 private static final QName PREFER_BREAK_BEFORE = new QName("prefer-break-before");
51 private static final QName PREFER_BREAK_AFTER = new QName("prefer-break-after");
52 private static final QName ALWAYS_BREAK_BEFORE = new QName("always-break-before");
53 private static final QName ALWAYS_BREAK_AFTER = new QName("always-break-after");
54
55 private static final QName PART_ATTRIBUTE = new QName("part-attribute");
56 private static final QName PROPAGATE = new QName("propagate");
57 private static final QName MAX_CHUNK_SIZE = new QName("max-chunk-size");
58
59 private ChunkerStep(XProcRuntime runtime, XAtomicStep step) {
60 super(runtime, step);
61 }
62
63 @Override
64 public void setInput(String port, ReadablePipe pipe) {
65 sourcePipe = pipe;
66 }
67
68 @Override
69 public void setOutput(String port, WritablePipe pipe) {
70 if ("result".equals(port)) {
71 resultPipe = pipe;
72 } else {
73 mappingPipe = pipe;
74 }
75 }
76
77 @Override
78 public void reset() {
79 sourcePipe.resetReader();
80 resultPipe.resetWriter();
81 mappingPipe.resetWriter();
82 }
83
84 @Override
85 public void run() throws SaxonApiException {
86 super.run();
87 try {
88 RuntimeValue partAttribute = getOption(PART_ATTRIBUTE);
89 new Chunker(
90 getOption(ALLOW_BREAK_BEFORE),
91 getOption(ALLOW_BREAK_AFTER),
92 getOption(PREFER_BREAK_BEFORE),
93 getOption(PREFER_BREAK_AFTER),
94 getOption(ALWAYS_BREAK_BEFORE),
95 getOption(ALWAYS_BREAK_AFTER),
96 partAttribute != null ? SaxonHelper.jaxpQName(partAttribute.getQName()) : null,
97 getOption(PROPAGATE, true),
98 getOption(MAX_CHUNK_SIZE, -1),
99 runtime.getProcessor().getUnderlyingConfiguration())
100 .transform(
101 new XMLCalabashInputValue(sourcePipe),
102 new XMLCalabashOutputValue(
103 new WritablePipe() {
104 private int count = 0;
105 public void write(XdmNode doc) {
106 (count++ == 0 ? mappingPipe : resultPipe).write(doc);
107 }
108 public void canWriteSequence(boolean sequence) { throw new UnsupportedOperationException(); }
109 public boolean writeSequence() { throw new UnsupportedOperationException(); }
110 public void setWriter(Step step) { throw new UnsupportedOperationException(); }
111 public void resetWriter() { throw new UnsupportedOperationException(); }
112 public void close() { throw new UnsupportedOperationException(); }
113 },
114 runtime))
115 .run();
116 } catch (Throwable e) {
117 throw XProcStep.raiseError(e, step);
118 }
119 }
120
121 private static final Logger logger = LoggerFactory.getLogger(ChunkerStep.class);
122
123 }