1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package net.sf.okapi.common.resource;
20
21 import java.util.Iterator;
22 import java.util.LinkedList;
23 import java.util.List;
24 import java.util.NoSuchElementException;
25
26 import net.sf.okapi.common.IResource;
27 import net.sf.okapi.common.ISegmenter;
28 import net.sf.okapi.common.LocaleId;
29 import net.sf.okapi.common.exceptions.OkapiMisAlignmentException;
30
31
32
33
34
35
36
37
38
39 public class AlignedSegments implements IAlignedSegments {
40 private ITextUnit parent;
41
42 public AlignedSegments(ITextUnit parent) {
43 this.parent = parent;
44 }
45
46 @Override
47 public void append(Segment srcSeg, Segment trgSeg, LocaleId trgLoc) {
48 if (srcSeg == null && trgSeg == null)
49 throw new IllegalArgumentException("srcSeg and trgSeg cannot both be null");
50 insertOrAppend(true, -1, srcSeg, trgSeg, trgLoc);
51 }
52
53 @Override
54 public void insert(int index, Segment srcSeg, Segment trgSeg, LocaleId trgLoc) {
55 if (srcSeg == null)
56 throw new IllegalArgumentException("srcSeg cannot be null");
57 insertOrAppend(false, index, srcSeg, trgSeg, trgLoc);
58 }
59
60 private void insertOrAppend(boolean append, int index, Segment srcSeg, Segment trgSeg,
61 LocaleId trgLoc) {
62 Segment sourceSeg = (srcSeg != null ? srcSeg : new Segment(null, new TextFragment("")));
63 Segment targetSeg = (trgSeg != null ? trgSeg : new Segment(null, new TextFragment("")));
64
65 String originalId = null;
66 String insertedId = null;
67
68 ContainerIterator ci = new ContainerIterator(trgLoc);
69
70 if (append) {
71 targetSeg.id = sourceSeg.id;
72 if (ci.hasSource())
73 ci.getSource().getSegments().append(sourceSeg);
74 if (ci.hasTarget())
75 ci.getTarget().getSegments().append(targetSeg);
76 } else {
77 originalId = getSource(trgLoc).getSegments().get(index).id;
78 if (ci.hasSource())
79 insertedId = doInsert(ci.getSource(), index, null, null, sourceSeg);
80 if (ci.hasTarget())
81 insertedId = doInsert(ci.getTarget(), index, originalId, insertedId, targetSeg);
82 }
83 }
84
85 private String doInsert(TextContainer container, int index, String originalId, String insertedId,
86 Segment seg) {
87 ISegments segs = container.getSegments();
88 Segment currentSeg;
89
90 if (originalId == null) {
91 segs.insert(index, seg);
92 return seg.id;
93 }
94 currentSeg = segs.get(originalId);
95 if (currentSeg != null) {
96 segs.insert(segs.getIndex(originalId), seg);
97 if (insertedId != null)
98 seg.id = insertedId;
99 return seg.id;
100 }
101 segs.append(seg);
102 return insertedId;
103 }
104
105 @Override
106 public void setSegment(int index, Segment seg, LocaleId trgLoc) {
107 ISegments segs = getSource(trgLoc).getSegments();
108 String oldId = segs.get(index).id;
109 String newId = seg.id;
110 boolean idChanged = !newId.equals(oldId);
111
112 Segment tempSeg;
113 ContainerIterator ci = new ContainerIterator(trgLoc);
114
115 if (ci.hasSource())
116 ci.getSource().getSegments().set(index, seg.clone());
117 if (ci.hasTarget()) {
118 segs = ci.getTarget().getSegments();
119 segs.set(segs.getIndex(oldId), seg.clone());
120 }
121
122 if (idChanged) {
123 ci = new ContainerIterator(trgLoc);
124 if (ci.hasSource()) {
125 tempSeg = ci.getSource().getSegments().get(oldId);
126 if (tempSeg != null)
127 tempSeg.id = newId;
128 }
129 if (ci.hasTarget()) {
130 tempSeg = ci.getTarget().getSegments().get(oldId);
131 if (tempSeg != null)
132 tempSeg.id = newId;
133 }
134 }
135 }
136
137 @Override
138 public boolean remove(Segment seg, LocaleId trgLoc) {
139 int count = 0;
140 ContainerIterator ci = new ContainerIterator(trgLoc);
141 if (ci.hasSource())
142 count += removeSegment(ci.getSource(), seg.id);
143 if (ci.hasTarget())
144 count += removeSegment(ci.getTarget(), seg.id);
145 return (count > 0);
146 }
147
148 private int removeSegment(TextContainer container, String segId) {
149 ISegments segs = container.getSegments();
150 int segIndex = segs.getIndex(segId);
151 if (segIndex > -1) {
152 container.remove(segs.getPartIndex(segIndex));
153 return 1;
154 }
155 return 0;
156 }
157
158 @Override
159 public Segment getSource(int index, LocaleId trgLoc) {
160 return getSource(trgLoc).getSegments().get(index);
161 }
162
163 @Override
164 public Segment getCorrespondingTarget(Segment srcSeg, LocaleId trgLoc) {
165 ISegments trgSegs = parent.getTargetSegments(trgLoc);
166 return trgSegs.get(srcSeg.id);
167 }
168
169 @Override
170 public Segment getCorrespondingSource(Segment trgSeg, LocaleId trgLoc) {
171 ISegments srcSegs = getSource(trgLoc).getSegments();
172 return srcSegs.get(trgSeg.id);
173 }
174
175 @Override
176 public void align(List<AlignedPair> alignedSegmentPairs, LocaleId trgLoc) {
177 parent.createTarget(trgLoc, false, IResource.CREATE_EMPTY);
178
179 TextContainer src = getSource(trgLoc);
180 TextContainer trg = parent.getTarget(trgLoc);
181
182
183
184
185
186 for (AlignedPair pair : alignedSegmentPairs) {
187 List<TextPart> srcParts = pair.getSourceParts();
188 List<TextPart> trgParts = pair.getTargetParts();
189
190 if (srcParts != null && !srcParts.isEmpty()) {
191 for (TextPart part : srcParts) {
192 src.append(part.clone());
193 }
194 }
195 if (trgParts != null && !trgParts.isEmpty()) {
196 for (TextPart part : trgParts) {
197 trg.append(part.clone());
198 }
199 }
200 }
201
202 src.setHasBeenSegmentedFlag(true);
203 trg.setHasBeenSegmentedFlag(true);
204 trg.getSegments().setAlignmentStatus(AlignmentStatus.ALIGNED);
205 }
206
207 @Override
208 public void align(LocaleId trgLoc) {
209 Iterator<Segment> srcSegsIt = getSource(trgLoc).getSegments().iterator();
210 Iterator<Segment> trgSegsIt = parent.createTarget(trgLoc, false, IResource.COPY_SEGMENTATION)
211 .getSegments().iterator();
212 while (srcSegsIt.hasNext()) {
213 try {
214 Segment srcSeg = srcSegsIt.next();
215 Segment trgSeg = trgSegsIt.next();
216 trgSeg.id = srcSeg.id;
217 } catch (NoSuchElementException e) {
218 throw new OkapiMisAlignmentException("Different number of source and target segments", e);
219 }
220 }
221 parent.getTargetSegments(trgLoc).setAlignmentStatus(AlignmentStatus.ALIGNED);
222 }
223
224 @Override
225 public void alignCollapseAll(LocaleId trgLoc) {
226 ContainerIterator ci = new ContainerIterator(trgLoc);
227 LinkedList<TextContainer> collapsed = new LinkedList<>();
228
229 if (ci.hasSource()) {
230 ci.getSource().joinAll();
231 ci.getSource().setHasBeenSegmentedFlag(false);
232 collapsed.add(ci.getSource());
233 }
234 if (ci.hasTarget()) {
235 ci.getTarget().joinAll();
236 ci.getTarget().setHasBeenSegmentedFlag(false);
237 collapsed.add(ci.getTarget());
238 }
239
240 for (LocaleId loc : parent.getTargetLocales()) {
241 TextContainer src = getSource(loc);
242 if (collapsed.contains(src)) {
243 TextContainer trg = parent.getTarget(loc);
244 if (collapsed.contains(trg)) {
245 trg.getSegments().setAlignmentStatus(AlignmentStatus.ALIGNED);
246 trg.getFirstSegment().id = src.getFirstSegment().getId();
247 }
248 }
249 }
250 }
251
252 @Override
253 public Segment splitSource(LocaleId trgLoc, Segment srcSeg, int splitPos) {
254 TextContainer theSource = getSource(trgLoc);
255 ISegments srcSegs = theSource.getSegments();
256 int segIndex = srcSegs.getIndex(srcSeg.id);
257 if (segIndex == -1)
258 return null;
259 int partIndex = srcSegs.getPartIndex(segIndex);
260 theSource.split(partIndex, splitPos, splitPos, false);
261 Segment newSeg = srcSegs.get(segIndex + 1);
262
263 ContainerIterator ci = new ContainerIterator(trgLoc);
264 if (ci.hasTarget()) {
265 ISegments currentSegs = ci.getTarget().getSegments();
266 Segment currentSeg = currentSegs.get(srcSeg.id);
267 if (currentSeg != null)
268 currentSegs.insert(currentSegs.getIndex(srcSeg.id) + 1,
269 new Segment(srcSeg.id, new TextFragment("")));
270 }
271 return newSeg;
272 }
273
274 @Override
275 public Segment splitTarget(LocaleId trgLoc, Segment trgSeg, int splitPos) {
276 TextContainer theTarget = parent.createTarget(trgLoc, false, IResource.COPY_SEGMENTATION);
277 ISegments trgSegs = theTarget.getSegments();
278 int segIndex = trgSegs.getIndex(trgSeg.id);
279 if (segIndex == -1)
280 return null;
281 int partIndex = trgSegs.getPartIndex(segIndex);
282 theTarget.split(partIndex, splitPos, splitPos, false);
283 Segment newSeg = trgSegs.get(segIndex + 1);
284
285 ContainerIterator ci = new ContainerIterator(trgLoc);
286 if (ci.hasSource()) {
287 ISegments currentSegs = ci.getSource().getSegments();
288 Segment currentSeg = currentSegs.get(trgSeg.id);
289 if (currentSeg != null)
290 currentSegs.insert(currentSegs.getIndex(trgSeg.id) + 1,
291 new Segment(trgSeg.id, new TextFragment("")));
292 }
293 return newSeg;
294 }
295
296 @Override
297 public void joinWithNext(Segment seg, LocaleId trgLoc) {
298 ContainerIterator ci = new ContainerIterator(trgLoc);
299 if (ci.hasSource())
300 doJoinWithNext(ci.getSource(), seg.id);
301 if (ci.hasTarget())
302 doJoinWithNext(ci.getTarget(), seg.id);
303 }
304
305 private void doJoinWithNext(TextContainer cont, String segId) {
306 int segIndex = cont.getSegments().getIndex(segId);
307 if (segIndex != -1)
308 cont.getSegments().joinWithNext(segIndex);
309 }
310
311 @Override
312 public void joinAll(LocaleId trgLoc) {
313 ContainerIterator ci = new ContainerIterator(trgLoc);
314 if (ci.hasSource())
315 ci.getSource().joinAll();
316 if (ci.hasTarget())
317 ci.getTarget().joinAll();
318 }
319
320 @Override
321 public AlignmentStatus getAlignmentStatus() {
322 for (LocaleId loc : parent.getTargetLocales()) {
323 ISegments trgSegs = parent.getTargetSegments(loc);
324 if (trgSegs.getAlignmentStatus() == AlignmentStatus.NOT_ALIGNED) {
325 return AlignmentStatus.NOT_ALIGNED;
326 }
327 }
328 return AlignmentStatus.ALIGNED;
329 }
330
331 @Override
332 public AlignmentStatus getAlignmentStatus(LocaleId trgLoc) {
333 return parent.getTargetSegments(trgLoc).getAlignmentStatus();
334 }
335
336 @Override
337 public void segmentSource(ISegmenter segmenter, LocaleId targetLocale) {
338 TextContainer theSource = getSource(targetLocale);
339 segmenter.computeSegments(theSource);
340 theSource.getSegments().create(segmenter.getRanges());
341 }
342
343 @Override
344 public void segmentTarget(ISegmenter segmenter, LocaleId targetLocale) {
345 TextContainer theTarget = parent.createTarget(targetLocale, false, IResource.COPY_SEGMENTATION);
346 segmenter.computeSegments(theTarget);
347 theTarget.getSegments().create(segmenter.getRanges());
348 }
349
350 @Override
351 public Iterator<Segment> iterator() {
352 return parent.getSource().getSegments().iterator();
353 }
354
355 @Override
356 public Iterator<Segment> iterator(LocaleId trgLoc) {
357 return getSource(trgLoc).getSegments().iterator();
358 }
359
360 private TextContainer getSource(LocaleId loc) {
361 return parent.getSource();
362 }
363
364 private class ContainerIterator {
365 private TextContainer theSource = null;
366 private TextContainer theTarget = null;
367
368 public ContainerIterator(LocaleId trgLoc) {
369 theSource = AlignedSegments.this.getSource(trgLoc);
370 theTarget = parent.getTarget(trgLoc);
371 }
372
373 public boolean hasSource() {
374 return theSource != null;
375 }
376
377 public TextContainer getSource() {
378 if (theSource == null)
379 throw new IllegalStateException(
380 "this method can only be called after hasSource() returns true");
381 return theSource;
382 }
383
384 public boolean hasTarget() {
385 return theTarget != null;
386 }
387
388 public TextContainer getTarget() {
389 if (theTarget == null)
390 throw new IllegalStateException(
391 "this method can only be called after hasTarget() returns true");
392 return theTarget;
393 }
394 }
395
396 public final ITextUnit getParent() {
397 return parent;
398 }
399 }