List of usage examples for java.util ListIterator previous
E previous();
From source file:org.matonto.catalog.impl.SimpleCatalogManager.java
@Override public Set<Conflict> getConflicts(Resource leftId, Resource rightId) throws MatOntoException { if (resourceExists(leftId, Commit.TYPE) && resourceExists(rightId, Commit.TYPE)) { try (RepositoryConnection conn = repository.getConnection()) { LinkedList<Value> leftList = new LinkedList<>(); LinkedList<Value> rightList = new LinkedList<>(); getCommitChainIterator(leftId, conn).forEachRemaining(leftList::add); getCommitChainIterator(rightId, conn).forEachRemaining(rightList::add); ListIterator<Value> leftIterator = leftList.listIterator(); ListIterator<Value> rightIterator = rightList.listIterator(); Value originalEnd = null;//from ww w .j a v a2 s.co m while (leftIterator.hasNext() && rightIterator.hasNext()) { Value currentId = leftIterator.next(); if (!currentId.equals(rightIterator.next())) { leftIterator.previous(); rightIterator.previous(); break; } else { originalEnd = currentId; } } if (originalEnd == null) { throw new MatOntoException("There is no common parent between the provided Commits."); } Model left = createModelFromIterator(leftIterator, conn); Model right = createModelFromIterator(rightIterator, conn); Model duplicates = mf.createModel(left); duplicates.retainAll(right); left.removeAll(duplicates); right.removeAll(duplicates); Resource deletionContext = vf.createIRI(DELETION_CONTEXT); Model leftDeletions = mf.createModel(left.filter(null, null, null, deletionContext)); Model rightDeletions = mf.createModel(right.filter(null, null, null, deletionContext)); left.removeAll(leftDeletions); right.removeAll(rightDeletions); Set<Conflict> result = new HashSet<>(); Model original = getCompiledResource((Resource) originalEnd).get(); IRI rdfType = vf.createIRI(RDF.TYPE.stringValue()); leftDeletions.forEach(statement -> { Resource subject = statement.getSubject(); IRI predicate = statement.getPredicate(); if (predicate.equals(rdfType) || right.contains(subject, predicate, null)) { result.add(createConflict(subject, predicate, original, left, leftDeletions, right, rightDeletions)); Stream.of(left, right, rightDeletions) .forEach(item -> item.remove(subject, predicate, null)); } }); rightDeletions.forEach(statement -> { Resource subject = statement.getSubject(); IRI predicate = statement.getPredicate(); if (predicate.equals(rdfType) || left.contains(subject, predicate, null)) { result.add(createConflict(subject, predicate, original, left, leftDeletions, right, rightDeletions)); Stream.of(left, leftDeletions, right) .forEach(item -> item.remove(subject, predicate, null)); } }); left.forEach(statement -> { Resource subject = statement.getSubject(); IRI predicate = statement.getPredicate(); if (right.contains(subject, predicate, null)) { result.add(createConflict(subject, predicate, original, left, leftDeletions, right, rightDeletions)); Stream.of(leftDeletions, right, rightDeletions) .forEach(item -> item.remove(subject, predicate, null)); } }); return result; } catch (RepositoryException e) { throw new MatOntoException("Error in repository connection.", e); } } throw new MatOntoException("One or both of the commit IRIs could not be found in the Repository."); }
From source file:org.eclipse.jubula.rc.swt.driver.RobotSwtImpl.java
/** * @param options options//w ww.j av a2 s. co m * @param alreadyDown set of pressed keys * @param i ListIterator */ private void releaseKeys(final InterceptorOptions options, final Set alreadyDown, final ListIterator i) { // Release all keys in reverse order. final Set alreadyUp = new HashSet(); try { while (i.hasPrevious()) { IRobotEventConfirmer confirmer = m_interceptor.intercept(options); m_queuer.invokeAndWait(this.getClass().getName() + ".type", //$NON-NLS-1$ new IRunnable() { public Object run() { // SYNCH THREAD START AbstractKeyTyper keyTyper = (AbstractKeyTyper) i.previous(); if (log.isDebugEnabled()) { log.debug("trying to release: " + keyTyper); //$NON-NLS-1$ } if (alreadyDown.contains(keyTyper) && !alreadyUp.contains(keyTyper)) { if (log.isDebugEnabled()) { log.debug("releasing: " + keyTyper); //$NON-NLS-1$ } post(keyTyper.createKeyUpEvent()); alreadyUp.add(keyTyper); } return null; } }); confirmer.waitToConfirm(null, new KeySwtEventMatcher(SWT.KeyUp)); } } catch (RobotException e) { log.error("error releasing keys", e); //$NON-NLS-1$ if (!i.hasPrevious()) { throw e; } } }
From source file:org.apache.fop.layoutmgr.inline.TextLayoutManager.java
/** {@inheritDoc} */ public boolean applyChanges(final List oldList, int depth) { // make sure the LM appears unfinished in between this call // and the next call to getChangedKnuthElements() setFinished(false);// w w w . jav a 2 s . c om if (oldList.isEmpty()) { return false; } // Find the first and last positions in oldList that point to an AreaInfo // (i.e. getLeafPos() != -1) LeafPosition startPos = null; LeafPosition endPos = null; ListIterator oldListIter; for (oldListIter = oldList.listIterator(); oldListIter.hasNext();) { Position pos = ((KnuthElement) oldListIter.next()).getPosition(); startPos = (LeafPosition) pos.getPosition(depth); if (startPos != null && startPos.getLeafPos() != -1) { break; } } for (oldListIter = oldList.listIterator(oldList.size()); oldListIter.hasPrevious();) { Position pos = ((KnuthElement) oldListIter.previous()).getPosition(); endPos = (LeafPosition) pos.getPosition(depth); if (endPos != null && endPos.getLeafPos() != -1) { break; } } // set start/end index, taking into account any offset due to // changes applied to previous paragraphs returnedIndices[0] = (startPos != null ? startPos.getLeafPos() : -1) + changeOffset; returnedIndices[1] = (endPos != null ? endPos.getLeafPos() : -1) + changeOffset; int areaInfosAdded = 0; int areaInfosRemoved = 0; if (!changeList.isEmpty()) { int oldIndex = -1; int changeIndex; PendingChange currChange; ListIterator changeListIterator = changeList.listIterator(); while (changeListIterator.hasNext()) { currChange = (PendingChange) changeListIterator.next(); if (currChange.index == oldIndex) { areaInfosAdded++; changeIndex = currChange.index + areaInfosAdded - areaInfosRemoved; } else { areaInfosRemoved++; areaInfosAdded++; oldIndex = currChange.index; changeIndex = currChange.index + areaInfosAdded - areaInfosRemoved; removeAreaInfo(changeIndex); } addAreaInfo(changeIndex, currChange.areaInfo); } changeList.clear(); } // increase the end index for getChangedKnuthElements() returnedIndices[1] += (areaInfosAdded - areaInfosRemoved); // increase offset to use for subsequent paragraphs changeOffset += (areaInfosAdded - areaInfosRemoved); return hasChanged; }
From source file:org.apache.fop.layoutmgr.inline.LineLayoutManager.java
private void processUpdates(Paragraph par, List updateList) { // create iterator for the updateList ListIterator updateListIterator = updateList.listIterator(); Update currUpdate;/* ww w. j a v a 2 s .co m*/ int elementsAdded = 0; while (updateListIterator.hasNext()) { // ask the LMs to apply the changes and return // the new KnuthElements to replace the old ones currUpdate = (Update) updateListIterator.next(); int fromIndex = currUpdate.firstIndex; int toIndex; if (updateListIterator.hasNext()) { Update nextUpdate = (Update) updateListIterator.next(); toIndex = nextUpdate.firstIndex; updateListIterator.previous(); } else { // maybe this is not always correct! toIndex = par.size() - par.ignoreAtEnd - elementsAdded; } // applyChanges() returns true if the LM modifies its data, // so it must return new KnuthElements to replace the old ones if (currUpdate.inlineLM.applyChanges(par.subList(fromIndex + elementsAdded, toIndex + elementsAdded))) { // insert the new KnuthElements List newElements = currUpdate.inlineLM.getChangedKnuthElements( par.subList(fromIndex + elementsAdded, toIndex + elementsAdded), /*flaggedPenalty,*/ effectiveAlignment); // remove the old elements par.subList(fromIndex + elementsAdded, toIndex + elementsAdded).clear(); // insert the new elements par.addAll(fromIndex + elementsAdded, newElements); elementsAdded += newElements.size() - (toIndex - fromIndex); } } updateList.clear(); }
From source file:com.edgenius.wiki.render.macro.AlignMacro.java
@Override protected void replaceHTML(HTMLNode node, ListIterator<HTMLNode> iter, RenderContext context) { if (node.getPair() == null) { log.warn("Unexpect case: No close tag for " + this.getClass().getName()); return;//w w w.ja v a 2 s. co m } if (node.getStyle() != null && node.getStyle().get(NameConstants.TEXT_ALIGN) != null && (node.getAttributes() == null || StringUtils.isBlank(node.getAttributes().get(NameConstants.AID)))) { String align = node.getStyle().get(NameConstants.TEXT_ALIGN); HTMLNode alignNode = null; //what ever the NODE is, such as <td style="align:center;colspan=4"> etc, the align attribute need be remove node.removeStyle("text-align", null); if ("div".equalsIgnoreCase(node.getTagName()) || "span".equalsIgnoreCase(node.getTagName()) || "p".equalsIgnoreCase(node.getTagName())) { alignNode = node; } else { //maybe <td> tag, it can not be simply reset -- otherwise, table will lost one cell.So here will add a paired <span> node //!!! don't insert <div> pair as it may broken TableMacro.isSimpleTableSupport() //enclose by current node //?? need handle default left? if ("center".equalsIgnoreCase(align) || "right".equalsIgnoreCase(align)) { //build a proxy tag, their tagname does not matter as it will reset following code alignNode = new HTMLNode("<span>", false); HTMLNode closeAlignNode = new HTMLNode("</span>", false); alignNode.setPair(closeAlignNode); iter.add(alignNode); //example, go to </td> tag moveIteratorCursorTo(node.getPair(), iter, true); //this is that node before </td>, need confirm it is not <td> (basically, it is impossible a <div> insert after <td>) HTMLNode nd = iter.previous(); if (nd != node) { iter.add(closeAlignNode); //move iterator back to node moveIteratorCursorTo(node, iter, false); } } } if (alignNode != null) { if ("center".equalsIgnoreCase(align)) { alignNode.reset("{align:align=center}", true); alignNode.getPair().reset("{align}", true); } else if ("right".equalsIgnoreCase(align)) { alignNode.reset("{align:align=right}", true); alignNode.getPair().reset("{align}", true); } } } }
From source file:org.apache.fop.layoutmgr.inline.LineLayoutManager.java
/** * Add a line with inline content/* w w w . j a v a 2 s .co m*/ * @param context the context for adding areas * @param lbp the position for which the line is generated * @param isLastPosition true if this is the last position of this LM */ private void addInlineArea(LayoutContext context, LineBreakPosition lbp, boolean isLastPosition) { KnuthSequence seq = knuthParagraphs.get(lbp.parIndex); int startElementIndex = lbp.startIndex; int endElementIndex = lbp.getLeafPos(); LineArea lineArea = new LineArea((lbp.getLeafPos() < seq.size() - 1 ? textAlignment : textAlignmentLast), lbp.difference, lbp.availableStretch, lbp.availableShrink); if (lbp.startIndent != 0) { lineArea.addTrait(Trait.START_INDENT, lbp.startIndent); } if (lbp.endIndent != 0) { lineArea.addTrait(Trait.END_INDENT, new Integer(lbp.endIndent)); } lineArea.setBPD(lbp.lineHeight); lineArea.setIPD(lbp.lineWidth); lineArea.setBidiLevel(bidiLevel); lineArea.addTrait(Trait.SPACE_BEFORE, lbp.spaceBefore); lineArea.addTrait(Trait.SPACE_AFTER, lbp.spaceAfter); alignmentContext.resizeLine(lbp.lineHeight, lbp.baseline); if (seq instanceof Paragraph) { Paragraph currPar = (Paragraph) seq; // ignore the first elements added by the LineLayoutManager startElementIndex += (startElementIndex == 0) ? currPar.ignoreAtStart : 0; // if this is the last line area that for this paragraph, // ignore the last elements added by the LineLayoutManager and // subtract the last-line-end-indent from the area ipd if (endElementIndex == (currPar.size() - 1)) { endElementIndex -= currPar.ignoreAtEnd; lineArea.setIPD(lineArea.getIPD() - lastLineEndIndent.getValue(this)); } } // ignore the last element in the line if it is a KnuthGlue object ListIterator seqIterator = seq.listIterator(endElementIndex); KnuthElement lastElement = (KnuthElement) seqIterator.next(); // the TLM which created the last KnuthElement in this line LayoutManager lastLM = lastElement.getLayoutManager(); if (lastElement.isGlue()) { // Remove trailing spaces if allowed so if (whiteSpaceTreament == EN_IGNORE_IF_SURROUNDING_LINEFEED || whiteSpaceTreament == EN_IGNORE || whiteSpaceTreament == EN_IGNORE_IF_BEFORE_LINEFEED) { endElementIndex--; // this returns the same KnuthElement seqIterator.previous(); if (seqIterator.hasPrevious()) { lastLM = ((KnuthElement) seqIterator.previous()).getLayoutManager(); } } } // Remove leading spaces if allowed so if (whiteSpaceTreament == EN_IGNORE_IF_SURROUNDING_LINEFEED || whiteSpaceTreament == EN_IGNORE || whiteSpaceTreament == EN_IGNORE_IF_AFTER_LINEFEED) { // ignore KnuthGlue and KnuthPenalty objects // at the beginning of the line seqIterator = seq.listIterator(startElementIndex); while (seqIterator.hasNext() && !((KnuthElement) seqIterator.next()).isBox()) { startElementIndex++; } } // Add the inline areas to lineArea PositionIterator inlinePosIter = new KnuthPossPosIter(seq, startElementIndex, endElementIndex + 1); LayoutContext lc = new LayoutContext(0); lc.setAlignmentContext(alignmentContext); lc.setSpaceAdjust(lbp.dAdjust); lc.setIPDAdjust(lbp.ipdAdjust); lc.setLeadingSpace(new SpaceSpecifier(true)); lc.setTrailingSpace(new SpaceSpecifier(false)); lc.setFlags(LayoutContext.RESOLVE_LEADING_SPACE, true); setCurrentArea(lineArea); setChildContext(lc); LayoutManager childLM; while ((childLM = inlinePosIter.getNextChildLM()) != null) { lc.setFlags(LayoutContext.LAST_AREA, (childLM == lastLM)); childLM.addAreas(inlinePosIter, lc); lc.setLeadingSpace(lc.getTrailingSpace()); lc.setTrailingSpace(new SpaceSpecifier(false)); } // if display-align is distribute, add space after if (context.getSpaceAfter() > 0 && (!context.isLastArea() || !isLastPosition)) { lineArea.setBPD(lineArea.getBPD() + context.getSpaceAfter()); } lineArea.finish(); if (lineArea.getBidiLevel() >= 0) { BidiResolver.reorder(lineArea); } parentLayoutManager.addChildArea(lineArea); }
From source file:org.apache.fop.layoutmgr.SpaceResolver.java
/** * Resolves unresolved elements applying the space resolution rules defined in 4.3.1. * @param elems the element list/*from ww w . j a v a 2 s .c o m*/ */ public static void resolveElementList(List elems) { if (LOG.isTraceEnabled()) { LOG.trace(elems); } boolean first = true; boolean last = false; boolean skipNextElement = false; List unresolvedFirst = new java.util.ArrayList(); List unresolvedSecond = new java.util.ArrayList(); List currentGroup; ListIterator iter = elems.listIterator(); while (iter.hasNext()) { ListElement el = (ListElement) iter.next(); if (el.isUnresolvedElement()) { if (LOG.isTraceEnabled()) { LOG.trace("unresolved found: " + el + " " + first + "/" + last); } BreakElement breakPoss = null; //Clear temp lists unresolvedFirst.clear(); unresolvedSecond.clear(); //Collect groups if (el instanceof BreakElement) { breakPoss = (BreakElement) el; currentGroup = unresolvedSecond; } else { currentGroup = unresolvedFirst; currentGroup.add(el); } iter.remove(); last = true; skipNextElement = true; while (iter.hasNext()) { el = (ListElement) iter.next(); if (el instanceof BreakElement && breakPoss != null) { skipNextElement = false; last = false; break; } else if (currentGroup == unresolvedFirst && (el instanceof BreakElement)) { breakPoss = (BreakElement) el; iter.remove(); currentGroup = unresolvedSecond; } else if (el.isUnresolvedElement()) { currentGroup.add(el); iter.remove(); } else { last = false; break; } } //last = !iter.hasNext(); if (breakPoss == null && unresolvedSecond.isEmpty() && !last) { LOG.trace("Swap first and second parts in no-break condition," + " second part is empty."); //The first list is reversed, so swap if this shouldn't happen List swapList = unresolvedSecond; unresolvedSecond = unresolvedFirst; unresolvedFirst = swapList; } LOG.debug("----start space resolution (first=" + first + ", last=" + last + ")..."); SpaceResolver resolver = new SpaceResolver(unresolvedFirst, breakPoss, unresolvedSecond, first, last); if (!last) { iter.previous(); } resolver.generate(iter); if (!last && skipNextElement) { iter.next(); } LOG.debug("----end space resolution."); } first = false; } }
From source file:org.rifidi.emulator.reader.thingmagic.commandobjects.SetCommand.java
private void setUpStart(ListIterator<String> tokenIterator) throws CommandCreationException { /*/*from w ww .j a v a 2s . c o m*/ * we are expecting a "turn on" command */ String token; do { token = tokenIterator.next(); if (!token.matches(WHITE_SPACE)) { throw new CommandCreationException("Error 0100: syntax error at '" + token + "'"); } if (!tmsr.getCursorCommandRegistry().containsKey(token)) { throw new CommandCreationException("Error 0100: Cursor does not exist"); } cursorList.add(tmsr.getCursorCommandRegistry().get(token)); token = tokenIterator.next(); } while (token.matches(COMMA_WITH_WS)); if (!token.matches(EQUALS_WITH_WS)) { throw new CommandCreationException("Error 0100: syntax error at '" + token + "'"); } token = tokenIterator.next(); if (!token.equalsIgnoreCase("ON")) { throw new CommandCreationException("Error 0100: syntax error at '" + token + "'"); } token = tokenIterator.next(); if (token.matches(COMMA_WITH_WS)) { token = tokenIterator.next(); if (!token.equals("repeat")) { throw new CommandCreationException("Error 0100: syntax error at '" + token + "'"); } token = tokenIterator.next(); if (token.matches(EQUALS_WITH_WS)) { throw new CommandCreationException("Error 0100: syntax error at '" + token + "'"); } token = tokenIterator.next(); try { repeat = Long.parseLong(token); } catch (NumberFormatException e) { throw new CommandCreationException("Error 0100: syntax error at '" + token + "'"); } } else { /* * rewind one token. */ tokenIterator.previous(); } commandSwitch = ESetSubCommand.START; }
From source file:net.sourceforge.fenixedu.domain.DegreeCurricularPlan.java
public ExecutionDegree getMostRecentExecutionDegree() { if (getExecutionDegreesSet().isEmpty()) { return null; }//from w ww . ja v a2 s.c o m final ExecutionYear currentYear = ExecutionYear.readCurrentExecutionYear(); ExecutionDegree result = getExecutionDegreeByYear(currentYear); if (result != null) { return result; } final List<ExecutionDegree> sorted = new ArrayList<ExecutionDegree>(getExecutionDegreesSet()); Collections.sort(sorted, ExecutionDegree.EXECUTION_DEGREE_COMPARATORY_BY_YEAR); final ExecutionDegree first = sorted.iterator().next(); if (sorted.size() == 1) { return first; } if (first.getExecutionYear().isAfter(currentYear)) { return first; } else { final ListIterator<ExecutionDegree> iter = sorted.listIterator(sorted.size()); while (iter.hasPrevious()) { final ExecutionDegree executionDegree = iter.previous(); if (executionDegree.getExecutionYear().isBeforeOrEquals(currentYear)) { return executionDegree; } } } return null; }
From source file:org.trnltk.experiment.morphology.ambiguity.DataDiffUtil.java
/** * Reorder and merge like edit sections. Merge equalities. * Any edit section can move as long as it doesn't cross an equality. * * @param diffs LinkedList of Diff objects. *//*from w w w . j a va 2 s .c om*/ public void diff_cleanupMerge(LinkedList<Diff<T>> diffs) { diffs.add(new Diff<T>(Operation.EQUAL, new ArrayList<T>())); // Add a dummy entry at the end. ListIterator<Diff<T>> pointer = diffs.listIterator(); int count_delete = 0; int count_insert = 0; List<T> text_delete = new ArrayList<T>(); List<T> text_insert = new ArrayList<T>(); Diff thisDiff = pointer.next(); Diff prevEqual = null; int commonlength; while (thisDiff != null) { switch (thisDiff.operation) { case INSERT: count_insert++; text_insert = ListUtils.union(text_insert, thisDiff.text); prevEqual = null; break; case DELETE: count_delete++; text_delete = ListUtils.union(text_delete, thisDiff.text); prevEqual = null; break; case EQUAL: if (count_delete + count_insert > 1) { boolean both_types = count_delete != 0 && count_insert != 0; // Delete the offending records. pointer.previous(); // Reverse direction. while (count_delete-- > 0) { pointer.previous(); pointer.remove(); } while (count_insert-- > 0) { pointer.previous(); pointer.remove(); } if (both_types) { // Factor out any common prefixies. commonlength = diff_commonPrefix(text_insert, text_delete); if (commonlength != 0) { if (pointer.hasPrevious()) { thisDiff = pointer.previous(); assert thisDiff.operation == Operation.EQUAL : "Previous diff should have been an equality."; thisDiff.text = ListUtils.union(thisDiff.text, text_insert.subList(0, commonlength)); pointer.next(); } else { pointer.add(new Diff(Operation.EQUAL, text_insert.subList(0, commonlength))); } text_insert = text_insert.subList(commonlength, text_insert.size()); text_delete = text_delete.subList(commonlength, text_delete.size()); } // Factor out any common suffixies. commonlength = diff_commonSuffix(text_insert, text_delete); if (commonlength != 0) { thisDiff = pointer.next(); thisDiff.text = ListUtils.union( text_insert.subList(text_insert.size() - commonlength, text_insert.size()), thisDiff.text); text_insert = text_insert.subList(0, text_insert.size() - commonlength); text_delete = text_delete.subList(0, text_delete.size() - commonlength); pointer.previous(); } } // Insert the merged records. if (text_delete.size() != 0) { pointer.add(new Diff(Operation.DELETE, text_delete)); } if (text_insert.size() != 0) { pointer.add(new Diff(Operation.INSERT, text_insert)); } // Step forward to the equality. thisDiff = pointer.hasNext() ? pointer.next() : null; } else if (prevEqual != null) { // Merge this equality with the previous one. prevEqual.text = ListUtils.union(prevEqual.text, thisDiff.text); pointer.remove(); thisDiff = pointer.previous(); pointer.next(); // Forward direction } count_insert = 0; count_delete = 0; text_delete = new ArrayList<T>(); text_insert = new ArrayList<T>(); prevEqual = thisDiff; break; } thisDiff = pointer.hasNext() ? pointer.next() : null; } if (diffs.getLast().text.size() == 0) { diffs.removeLast(); // Remove the dummy entry at the end. } /* * Second pass: look for single edits surrounded on both sides by equalities * which can be shifted sideways to eliminate an equality. * e.g: A<ins>BA</ins>C -> <ins>AB</ins>AC */ boolean changes = false; // Create a new iterator at the start. // (As opposed to walking the current one back.) pointer = diffs.listIterator(); Diff<T> prevDiff = pointer.hasNext() ? pointer.next() : null; thisDiff = pointer.hasNext() ? pointer.next() : null; Diff nextDiff = pointer.hasNext() ? pointer.next() : null; // Intentionally ignore the first and last element (don't need checking). while (nextDiff != null) { if (prevDiff.operation == Operation.EQUAL && nextDiff.operation == Operation.EQUAL) { // This is a single edit surrounded by equalities. if (endsWith(thisDiff.text, prevDiff.text)) { // Shift the edit over the previous equality. thisDiff.text = ListUtils.union(prevDiff.text, thisDiff.text.subList(0, thisDiff.text.size() - prevDiff.text.size())); nextDiff.text = ListUtils.union(prevDiff.text, nextDiff.text); pointer.previous(); // Walk past nextDiff. pointer.previous(); // Walk past thisDiff. pointer.previous(); // Walk past prevDiff. pointer.remove(); // Delete prevDiff. pointer.next(); // Walk past thisDiff. thisDiff = pointer.next(); // Walk past nextDiff. nextDiff = pointer.hasNext() ? pointer.next() : null; changes = true; } else if (startsWith(thisDiff.text, nextDiff.text)) { // Shift the edit over the next equality. prevDiff.text = ListUtils.union(prevDiff.text, nextDiff.text); thisDiff.text = ListUtils.union( thisDiff.text.subList(nextDiff.text.size(), thisDiff.text.size()), nextDiff.text); pointer.remove(); // Delete nextDiff. nextDiff = pointer.hasNext() ? pointer.next() : null; changes = true; } } prevDiff = thisDiff; thisDiff = nextDiff; nextDiff = pointer.hasNext() ? pointer.next() : null; } // If shifts were made, the diff needs reordering and another shift sweep. if (changes) { diff_cleanupMerge(diffs); } }