1 package org.daisy.pipeline.nlp.calabash.impl;
2
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.List;
6 import java.util.regex.Matcher;
7 import java.util.regex.Pattern;
8
9 import org.daisy.pipeline.nlp.lexing.LexService.Sentence;
10 import org.daisy.pipeline.nlp.lexing.LexService.TextBoundaries;
11
12
13
14
15
16
17
18 public class StringComposer {
19
20 static public class TextPointer {
21
22 public int firstSegment;
23
24 public int firstIndex;
25
26 public int lastSegment;
27
28 public int lastIndex;
29
30 public boolean properNoun;
31 }
32
33 static public class SentencePointer {
34 public TextPointer boundaries;
35 public List<TextPointer> content;
36 }
37
38 private List<SentencePointer> mSentencePointers = new ArrayList<SentencePointer>();
39 private List<TextPointer> mWordPointers = new ArrayList<TextPointer>();
40 private int[] mCoordinates = new int[2];
41 private Matcher mSpaceMatcher = Pattern.compile("[\\p{Z}\\s]+").matcher("");
42 private Matcher mSpaceMatcherEnd = Pattern.compile("[\\p{Z}\\s]+$").matcher("");
43
44 public String concat(Collection<String> segments) {
45 StringBuilder sb = new StringBuilder();
46 for (String segment : segments) {
47 if (segment != null)
48 sb.append(segment);
49 }
50 return sb.toString();
51 }
52
53
54
55
56
57
58
59
60
61
62
63 public List<SentencePointer> makePointers(List<Sentence> sentences, List<String> segments,
64 boolean[] isLexMark) {
65
66
67 int maxContentSize = 0;
68 for (Sentence s : sentences)
69 if (s.words != null)
70 maxContentSize += s.words.size();
71 for (int size = mWordPointers.size(); size < maxContentSize; ++size)
72 mWordPointers.add(new TextPointer());
73
74
75 StringBuilder sb = new StringBuilder();
76 for (int i = 0; i < segments.size(); ++i) {
77 if (isLexMark[i])
78 for (int k = segments.get(i).length(); k > 0; --k)
79 sb.append(" ");
80 else if (segments.get(i) != null)
81 sb.append(segments.get(i));
82 }
83 String ref = sb.toString();
84
85
86 int contentIndex = 0;
87 int nrOfSents = 0;
88 int left, right;
89 int[] coord;
90 for (int i = 0; i < sentences.size(); ++i) {
91 if (mSentencePointers.size() == nrOfSents) {
92 SentencePointer sp = new SentencePointer();
93 sp.boundaries = new TextPointer();
94 mSentencePointers.add(sp);
95 }
96 Sentence sentence = sentences.get(i);
97 SentencePointer sp = mSentencePointers.get(nrOfSents);
98
99 left = trimLeft(sentence.boundaries.left, ref);
100 right = trimRight(sentence.boundaries.right, ref);
101 if (left >= right) {
102
103 continue;
104 }
105
106 coord = findLeft(segments, left);
107 sp.boundaries.firstSegment = coord[0];
108 sp.boundaries.firstIndex = coord[1];
109
110 coord = findRight(segments, right);
111 sp.boundaries.lastSegment = coord[0];
112 sp.boundaries.lastIndex = coord[1];
113 ++nrOfSents;
114
115 if (sentence.words == null || sentence.words.size() == 0) {
116 sp.content = null;
117 } else {
118 int contentLeft = contentIndex;
119 for (int j = 0; j < sentence.words.size(); ++j) {
120 TextBoundaries word = sentence.words.get(j);
121 TextPointer tp = mWordPointers.get(contentIndex);
122
123 left = trimLeft(word.left, ref);
124 right = trimRight(word.right, ref);
125
126 if (left >= right) {
127 continue;
128 }
129
130 coord = findLeft(segments, left);
131 tp.firstSegment = coord[0];
132 tp.firstIndex = coord[1];
133
134 coord = findRight(segments, right);
135 tp.lastSegment = coord[0];
136 tp.lastIndex = coord[1];
137
138 ++contentIndex;
139 }
140 if (contentLeft != contentIndex)
141 sp.content = mWordPointers.subList(contentLeft, contentIndex);
142 else
143 sp.content = null;
144 }
145 }
146
147 return mSentencePointers.subList(0, nrOfSents);
148 }
149
150 private int trimLeft(int left, String ref) {
151 mSpaceMatcher.reset(ref.substring(left));
152 if (mSpaceMatcher.lookingAt()) {
153 left += mSpaceMatcher.end();
154 }
155 return left;
156 }
157
158 private int trimRight(int right, String ref) {
159 mSpaceMatcherEnd.reset(ref.substring(0, right));
160 if (mSpaceMatcherEnd.find()) {
161 right = mSpaceMatcherEnd.start();
162 }
163 return right;
164 }
165
166 private int[] findLeft(List<String> segments, int index) {
167 int res[] = findInArray(segments, index);
168 if (res[1] == segments.get(res[0]).length()) {
169 res[0]++;
170 res[1] = 0;
171 }
172 return res;
173 }
174
175 private int[] findRight(List<String> segments, int index) {
176 int[] res = findInArray(segments, index - 1);
177 res[1]++;
178 if (res[1] == 0) {
179 res[0]--;
180 res[1] = segments.get(res[0]).length();
181 }
182 return res;
183 }
184
185 private int[] findInArray(List<String> segments, int index) {
186 mCoordinates[0] = 0;
187 while ((segments.get(mCoordinates[0]) == null)
188 || (index >= segments.get(mCoordinates[0]).length())) {
189 if (segments.get(mCoordinates[0]) != null)
190 index -= segments.get(mCoordinates[0]).length();
191 ++mCoordinates[0];
192 }
193 mCoordinates[1] = index;
194 return mCoordinates;
195 }
196 }