1 package org.daisy.pipeline.tts;
2
3 import java.net.URI;
4 import java.net.URISyntaxException;
5 import java.util.ArrayList;
6 import java.util.Collection;
7 import java.util.List;
8
9 import net.sf.saxon.om.NodeInfo;
10 import net.sf.saxon.s9api.Axis;
11 import net.sf.saxon.s9api.Processor;
12 import net.sf.saxon.s9api.QName;
13 import net.sf.saxon.s9api.XdmNode;
14 import net.sf.saxon.s9api.XdmNodeKind;
15 import net.sf.saxon.s9api.XdmSequenceIterator;
16
17 import org.slf4j.Logger;
18 import org.slf4j.LoggerFactory;
19
20 import com.google.common.collect.HashMultimap;
21 import com.google.common.collect.Multimap;
22 import com.xmlcalabash.util.TreeWriter;
23
24 public class DefaultSSMLMarkSplitter implements SSMLMarkSplitter {
25
26 private static Logger ServerLogger = LoggerFactory
27 .getLogger(DefaultSSMLMarkSplitter.class);
28
29 private Processor mProc;
30
31 public DefaultSSMLMarkSplitter(Processor proc) {
32 mProc = proc;
33 }
34
35 @Override
36 public Collection<Chunk> split(XdmNode ssml) {
37 List<String> sortedMarkNames = new ArrayList<String>();
38 Multimap<NodeInfo, String> marksScope = HashMultimap.create();
39 sortedMarkNames.add(null);
40 findMarks(ssml, marksScope, sortedMarkNames);
41
42 Collection<Chunk> chunks = new ArrayList<Chunk>();
43
44 if (ssml.getNodeKind() == XdmNodeKind.DOCUMENT) {
45 XdmSequenceIterator iter = ssml.axisIterator(Axis.CHILD);
46 while (ssml.getNodeKind() != XdmNodeKind.ELEMENT && iter.hasNext()) {
47 ssml = (XdmNode) iter.next();
48 }
49 }
50 URI docURI = null;
51 try {
52 docURI = new URI("http://tmp");
53 } catch (URISyntaxException e) {
54 }
55
56 for (String markName : sortedMarkNames) {
57 TreeWriter tw = new TreeWriter(mProc);
58 tw.startDocument(docURI);
59 tw.startContent();
60 toXML(ssml, tw, markName, marksScope);
61 tw.endDocument();
62 chunks.add(new Chunk(tw.getResult(), markName));
63 }
64
65 return chunks;
66 }
67
68 private static void findMarks(XdmNode ssml, Multimap<NodeInfo, String> marksScope,
69 List<String> sortedMarkNames) {
70 String markName = sortedMarkNames.get(sortedMarkNames.size() - 1);
71 marksScope.put(ssml.getUnderlyingNode(), markName);
72 XdmSequenceIterator iter = ssml.axisIterator(Axis.ANCESTOR);
73 while (iter.hasNext()) {
74 XdmNode parent = (XdmNode) iter.next();
75 marksScope.put(parent.getUnderlyingNode(), markName);
76 }
77 if (ssml.getNodeName() != null
78 && markNode.getLocalName().equals(ssml.getNodeName().getLocalName())) {
79 sortedMarkNames.add(ssml.getAttributeValue(markNameAttr));
80 }
81 iter = ssml.axisIterator(Axis.CHILD);
82 while (iter.hasNext()) {
83 findMarks((XdmNode) iter.next(), marksScope, sortedMarkNames);
84 }
85 }
86
87 private static void toXML(XdmNode ssml, TreeWriter tw, String markName,
88 Multimap<NodeInfo, String> marksScope) {
89 if (!marksScope.containsEntry(ssml.getUnderlyingNode(), markName)) {
90 return;
91 }
92 if (ssml.getNodeKind() == XdmNodeKind.TEXT) {
93 tw.addText(ssml.getStringValue());
94 } else if (ssml.getNodeKind() == XdmNodeKind.ELEMENT
95 && !markNode.getLocalName().equals(ssml.getNodeName().getLocalName())) {
96 QName elementName = ssml.getNodeName();
97 if (elementName != null) {
98 tw.addStartElement(ssml);
99 tw.addAttributes(ssml);
100 }
101
102 XdmSequenceIterator iter = ssml.axisIterator(Axis.CHILD);
103 while (iter.hasNext()) {
104 toXML((XdmNode) iter.next(), tw, markName, marksScope);
105 }
106
107 if (elementName != null) {
108 tw.addEndElement();
109 }
110 }
111 }
112
113 private static final QName markNode = new QName("mark");
114 private static final QName markNameAttr = new QName("name");
115 }