1 package org.daisy.pipeline.nlp.calabash.impl;
2
3 import java.util.ArrayList;
4 import java.util.List;
5 import java.util.Locale;
6 import java.util.Set;
7
8 import net.sf.saxon.om.NodeInfo;
9 import net.sf.saxon.s9api.Axis;
10 import net.sf.saxon.s9api.XdmNode;
11 import net.sf.saxon.s9api.XdmNodeKind;
12 import net.sf.saxon.s9api.XdmSequenceIterator;
13
14 import org.daisy.pipeline.nlp.LanguageUtils;
15 import org.daisy.pipeline.nlp.calabash.impl.InlineSectionProcessor.Leaf;
16 import org.daisy.pipeline.nlp.lexing.LexService.LexerInitException;
17
18
19
20
21
22
23
24
25
26
27
28
29
30 public class InlineSectionFinder {
31 private FormatSpecifications mSpecs;
32 private InlineSectionProcessor mProc;
33 private List<Leaf> mCurrentSection;
34 private List<String> mCurrentText;
35 private int mCurrentSectionSize;
36 private Locale mCurrentLang;
37 private Set<NodeInfo> mUnsplittable;
38
39 public void find(XdmNode root, int rootLevel, FormatSpecifications specs,
40 InlineSectionProcessor processor, Set<NodeInfo> unsplittable)
41 throws LexerInitException {
42
43 mCurrentSection = new ArrayList<Leaf>();
44 mCurrentText = new ArrayList<String>();
45 mCurrentSectionSize = 0;
46 mSpecs = specs;
47 mProc = processor;
48 mCurrentLang = null;
49 mUnsplittable = unsplittable;
50
51 findRec(root, rootLevel, null);
52 mProc = null;
53 mSpecs = null;
54 mCurrentSection = null;
55 mUnsplittable = null;
56 }
57
58 private void addToSection(XdmNode node, int level, String text) {
59 if (mCurrentSectionSize == mCurrentSection.size()) {
60 mCurrentSection.add(new Leaf());
61 mCurrentText.add(null);
62 }
63
64 Leaf l = mCurrentSection.get(mCurrentSectionSize);
65 l.formatting = node;
66 l.level = level;
67
68 mCurrentText.set(mCurrentSectionSize++, text);
69 }
70
71 private void notifyNewSection() throws LexerInitException {
72 if (mCurrentSectionSize > 0) {
73 int k = 0;
74 for (k = 0; k < mCurrentSectionSize
75 && (mCurrentText.get(k) == null || mCurrentSection.get(k).formatting == null); ++k);
76 if (k == mCurrentSectionSize) {
77 mProc.onEmptySectionFound(mCurrentSection.subList(0, mCurrentSectionSize));
78 } else {
79 mProc.onInlineSectionFound(mCurrentSection.subList(0, mCurrentSectionSize),
80 mCurrentText.subList(0, mCurrentSectionSize), mCurrentLang);
81 }
82 mCurrentSectionSize = 0;
83 }
84 }
85
86 private void findRec(XdmNode node, int level, Locale lang) throws LexerInitException {
87 if (node.getNodeKind() == XdmNodeKind.TEXT) {
88 addToSection(node.getParent(), level - 1, node.getStringValue());
89 } else {
90
91 String langstr = node.getAttributeValue(mSpecs.langAttr);
92 if (langstr != null) {
93 Locale x = LanguageUtils.stringToLanguage(langstr);
94 if (x != null) {
95 lang = x;
96 }
97 }
98
99 if (lang != mCurrentLang) {
100 notifyNewSection();
101 mCurrentLang = lang;
102 }
103
104 XdmSequenceIterator iter = node.axisIterator(Axis.CHILD);
105 if (node.getNodeName() != null
106 && mSpecs.inlineElements.test(node)
107 && (!mUnsplittable.contains(node.getUnderlyingNode()))) {
108
109
110 if (mSpecs.ensureSentenceBefore.test(node)) {
111 addToSection(null, level, LanguageUtils.getFullStopSymbol(lang));
112 }
113 if (mSpecs.ensureWordBefore.test(node)) {
114 addToSection(null, level, LanguageUtils.getCommaSymbol(lang));
115 }
116
117 if (!iter.hasNext()) {
118
119 addToSection(node, level, null);
120 } else {
121 while (iter.hasNext()) {
122 XdmNode child = (XdmNode) iter.next();
123 findRec(child, level + 1, lang);
124 }
125 }
126
127 if (mSpecs.ensureWordAfter.test(node)) {
128 addToSection(null, level, LanguageUtils.getCommaSymbol(lang));
129 }
130 if (mSpecs.ensureSentenceAfter.test(node)) {
131 addToSection(null, level, LanguageUtils.getFullStopSymbol(lang));
132 }
133 } else {
134 notifyNewSection();
135 if (!iter.hasNext()) {
136
137 addToSection(node, level, null);
138
139 } else {
140
141 while (iter.hasNext()) {
142 XdmNode child = (XdmNode) iter.next();
143 findRec(child, level + 1, lang);
144 }
145 }
146 notifyNewSection();
147 }
148 }
149 }
150 }