Example usage for java.util ListIterator hasPrevious

List of usage examples for java.util ListIterator hasPrevious

Introduction

In this page you can find the example usage for java.util ListIterator hasPrevious.

Prototype

boolean hasPrevious();

Source Link

Document

Returns true if this list iterator has more elements when traversing the list in the reverse direction.

Usage

From source file:org.zenoss.zep.index.impl.EventIndexDaoImplIT.java

@Test
public void testArchiveMissingInDb() throws ZepException {
    List<EventSummary> created = Lists.newArrayList();
    for (int i = 0; i < 10; i++) {
        String summary = String.format("Event Archive %03d", i);
        EventSummary event = createArchiveClosed(
                Event.newBuilder(EventTestUtils.createSampleEvent()).setSummary(summary).build());

        created.add(event);/*from   w w  w .  j a v a2  s  .c  om*/
    }
    this.eventArchiveIndexDao.indexMany(created);

    // Delete the first 3 events from the database (but don't delete from index)
    List<String> summariesToDelete = Lists.newArrayList();
    for (int i = 0; i < 3; i++) {
        summariesToDelete.add(created.get(i).getOccurrence(0).getSummary());
    }
    Map<String, List<String>> args = Collections.singletonMap("_summaries", summariesToDelete);
    this.simpleJdbcTemplate.update("DELETE FROM event_archive WHERE summary IN (:_summaries)", args);

    EventSort sort = EventSort.newBuilder().setField(Field.EVENT_SUMMARY).build();
    EventSummaryRequest req = EventSummaryRequest.newBuilder().addSort(sort).build();
    EventSummaryResult result = this.eventArchiveIndexDao.list(req);
    assertContainsEvents(result, created.subList(3, 10));

    // Test sorting descending by summary
    sort = EventSort.newBuilder().setField(Field.EVENT_SUMMARY).setDirection(Direction.DESCENDING).build();
    req = EventSummaryRequest.newBuilder().addSort(sort).build();
    result = this.eventArchiveIndexDao.list(req);
    List<EventSummary> subList = created.subList(3, 10);
    assertContainsEvents(result, subList);
    ListIterator<EventSummary> it = subList.listIterator(subList.size());
    int i = 0;
    while (it.hasPrevious()) {
        assertEquals(result.getEvents(i), it.previous());
        ++i;
    }
}

From source file:org.eclipse.jubula.rc.swt.driver.RobotSwtImpl.java

/**
 * @param options options/*from w  ww. j  a va 2  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.slc.sli.dashboard.manager.impl.PopulationManagerImpl.java

/**
 * /* w  w w .  jav  a  2s  . c o  m*/
 * Finds the chronologically (strictly) earlier date on the list as compared
 * to the anchorDate. Note that this method assumes the dates list has been
 * chronologically sorted, the anchorDate is contained on it, and it has no
 * "null" entries. The input parameters themselves can be null, in which
 * case null is returned.
 * 
 * @param dates
 * @param anchorDate
 */
@SuppressWarnings({ "unchecked", "rawtypes" })
private Date findPrevDate(List<Date> dates, Date anchorDate) {
    if (anchorDate == null || dates == null) {
        return null;
    }
    Date prevDate = null;
    ListIterator<Date> li = dates.listIterator(dates.indexOf(anchorDate));
    while (li.hasPrevious()) {
        Date d = li.previous();
        if (d.before(anchorDate)) {
            prevDate = d;
            break;
        }
    }
    return prevDate;
}

From source file:com.projity.script.object.TimeIntervals.java

public TimeIntervals translate(int winCount) { //TODO case winCount<0

    //      for (TimeWindow w : history) System.out.println("history0: "+w);
    //      for (TimeWindow w : win) System.out.println("win0: "+w);

    //for (TimeWindow w : history) System.out.println("id="+w.getId());
    TimeIntervals t = new TimeIntervals();
    t.setScale(scale);/*from   ww w  .  j a v a  2  s .  c  om*/
    LinkedList<TimeWindow> twin = t.getWin();
    if (winCount == 0 || win.size() == 0)
        return t; //or null
    if (winCount > 0) {
        t.winId = winId + win.size();
        int lastId = t.winId - 1 + winCount;
        int maxHistoryId = Math.min(history.getLast().getId(), lastId);
        int i = t.winId;
        if (i <= maxHistoryId) {
            ListIterator<TimeWindow> it = history.listIterator();
            TimeWindow w;
            while (it.hasNext()) {
                w = it.next();
                if (w.getId() == t.winId) {
                    it.previous();
                    break;
                }
            }
            for (; i <= maxHistoryId && it.hasNext(); i++) {
                w = it.next();
                twin.add(w);
                //               System.out.println("Found in history: "+w);
            }
        }
        LinkedList<TimeWindow> newWin = new LinkedList<TimeWindow>();
        generateWindows(scale, (twin.size() > 0 ? twin : win).getLast().getE(), start, end, lastId - i + 1,
                newWin);
        t.indexWindows(t.winId + t.getWin().size(), newWin);
        //         for (TimeWindow w : newWin) System.out.println("New window: "+w);
        t.getWin().addAll(newWin);
        history.addAll(newWin);
    } else {
        t.winId = winId - 1;
        int lastId = t.winId + 1 + winCount;
        int minHistoryId = Math.max(history.getFirst().getId(), lastId);
        int i = t.winId;
        if (i >= minHistoryId) {
            ListIterator<TimeWindow> it = history.listIterator(history.size() - 1);
            TimeWindow w;
            while (it.hasPrevious()) {
                w = it.previous();
                if (w.getId() == t.winId) {
                    it.next();
                    break;
                }
            }
            for (; i >= minHistoryId; i--) {
                w = it.previous();
                twin.addFirst(w);
                //               System.out.println("Found in history: "+w);
            }
        }
        //         System.out.println("winId="+winId+", t.winId="+t.winId+", lastId="+lastId+", i="+i+" minHistoryId="+minHistoryId);
        LinkedList<TimeWindow> newWin = new LinkedList<TimeWindow>();
        generateWindows(scale, (twin.size() > 0 ? twin : win).getFirst().getS(), start, end, lastId - i - 1,
                newWin);
        t.indexWindows(lastId, newWin);
        //         for (TimeWindow w : newWin) System.out.println("New window: "+w);
        t.getWin().addAll(0, newWin);
        history.addAll(0, newWin);
    }

    int translation = 0;
    for (TimeWindow w : t.getWin()) {
        if (winCount > 0) {
            win.removeFirst();
            win.addLast(w);
            translation++;
        } else {
            win.removeLast();
            win.addFirst(w);
            translation--;
        }
    }
    winId = winId + translation;
    t.setTranslation(translation);

    //      for (TimeWindow w : history) System.out.println("history1: "+w);
    //      for (TimeWindow w : win) System.out.println("win1: "+w);
    //      for (TimeWindow w : twin) System.out.println("t.win1: "+w);

    return t;
}

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);/*from   ww w  .jav  a2 s . com*/

    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:net.sourceforge.fenixedu.domain.DegreeCurricularPlan.java

public ExecutionDegree getMostRecentExecutionDegree() {
    if (getExecutionDegreesSet().isEmpty()) {
        return null;
    }//from  ww  w . j a v  a 2 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.apache.fop.layoutmgr.inline.LineLayoutManager.java

/**
 * Add a line with inline content/*from   www .  j av  a2 s  .c o 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:com.android.systemui.qs.QSDragPanel.java

public void setTiles(final Collection<QSTile<?>> tilesCollection) {
    // we try to be as efficient as possible here because this can happen while the user
    // is in edit mode, or maybe even while tiles are animating
    // step 1: stop all animations
    // step 2: remove tiles no longer to be used, cache ones that are still valid
    // step 3: remove empty viewpager pages
    // step 4: generate new tiles, re-add cached ones

    if (DEBUG_TILES) {
        Log.i(TAG, "setTiles() called with tiles = [" + tilesCollection + "]");
    }/*from  w w w. j a  va 2s.com*/
    if (mLastDragRecord != null && mRecords.indexOf(mLastDragRecord) == -1) {
        // the last removed record might be stored in mLastDragRecord if we just shifted
        // re-add it to the list so we'll clean it up below
        mRecords.add(mLastDragRecord);
        mLastDragRecord = null;
    }

    // step kinda-1
    if (mDraggingRecord != null) {
        // dragging record might be animating back, force it to finished position
        mDraggingRecord.tileView.animate().cancel();
    }

    int currentViewPagerPage = mViewPager.getCurrentItem();
    int removedPages = 0;

    Map<QSTile<?>, DragTileRecord> cachedRecords = new ArrayMap<>();
    ListIterator<TileRecord> iterator = mRecords.listIterator(mRecords.size());

    int recordsRemoved = 0;
    // cleanup current records
    while (iterator.hasPrevious()) { // mRecords
        DragTileRecord dr = (DragTileRecord) iterator.previous();

        // step 1
        dr.tileView.animate().cancel();

        // step 2
        if (tilesCollection.contains(dr.tile)) {
            if (DEBUG_TILES) {
                Log.i(TAG, "caching tile: " + dr.tile);
            }
            cachedRecords.put(dr.tile, dr);
        } else {
            if (dr.page >= 0) {
                if (DEBUG_TILES) {
                    Log.w(TAG, "removed dr.tileView: " + dr.tileView + " from page: " + dr.page
                            + " (dest page: " + dr.destinationPage + ")");
                }

                removeTileView(dr.tileView);
            }
            if (DEBUG_TILES) {
                Log.i(TAG, "removing tile: " + dr.tile);
            }

            // remove record
            iterator.remove();
            recordsRemoved++;

            dr.page = -1;
            dr.destinationPage = -1;
        }
    }

    // at this point cachedRecords should have all retained tiles, no new or old tiles
    int delta = tilesCollection.size() - cachedRecords.size() - recordsRemoved;
    if (DEBUG_TILES) {
        Log.i(TAG, "record map delta: " + delta);
    }

    // step 3
    final Iterator<QSPage> pageIterator = mPages.iterator();
    while (pageIterator.hasNext()) {
        final QSPage page = pageIterator.next();
        final int viewpagerIndex = page.getPageIndex() + (mEditing ? 1 : 0);
        final int childCount = page.getChildCount();

        if (DEBUG_TILES) {
            Log.d(TAG, "page " + viewpagerIndex + " has " + childCount);
        }
        if (page.getPageIndex() >= getCurrentMaxPageCount() - 1) {
            if (DEBUG_TILES) {
                Log.d(TAG, "page : " + page + " has " + childCount + " children");
            }
            if (childCount == 0) {
                removedPages++;

                page.removeAllViews();
                mPagerAdapter.startUpdate(mViewPager);
                mPagerAdapter.destroyItem(mViewPager, viewpagerIndex, page);
                mPagerAdapter.finishUpdate(mViewPager);
                mPagerAdapter.notifyDataSetChanged();
            }
        }
    }

    if (removedPages > 0) {
        // even though we explicitly destroy old pages, without this call,
        // the viewpager doesn't seem to want to pick up the fact that we have less pages
        // and allows "empty" scrolls to the right where there is no page.
        if (DEBUG_TILES) {
            Log.d(TAG, "re-setting adapter, page: " + currentViewPagerPage);
        }
        mViewPager.setAdapter(mPagerAdapter);
        mViewPager.setCurrentItem(Math.min(currentViewPagerPage, mPagerAdapter.getCount()), false);
        mPagerAdapter.notifyDataSetChanged();
    }

    // step 4
    mRecords.ensureCapacity(tilesCollection.size());
    int runningCount = 0;

    final Iterator<QSTile<?>> newTileIterator = tilesCollection.iterator();
    while (newTileIterator.hasNext()) {
        QSTile<?> tile = newTileIterator.next();
        if (tile instanceof CustomQSTile) {
            if (((CustomQSTile) tile).isUserRemoved() || ((CustomQSTile) tile).getTile() == null) {
                // tile not published yet
                continue;
            }
        }
        final int tileDestPage = getPagesForCount(runningCount + 1) - 1;

        if (DEBUG_TILES) {
            Log.d(TAG, "tile at : " + runningCount + ": " + tile + " to dest page: " + tileDestPage);
        }
        DragTileRecord record;
        if (!cachedRecords.containsKey(tile)) {
            if (DEBUG_TILES) {
                Log.d(TAG, "tile at: " + runningCount + " not cached, adding it to records");
            }
            record = makeRecord(tile);
            record.destinationPage = tileDestPage;
            mRecords.add(runningCount, record);
            mPagerAdapter.notifyDataSetChanged();
        } else {
            record = cachedRecords.get(tile);
            if (DEBUG_TILES) {
                Log.d(TAG, "tile at : " + runningCount + ": cached, restoring: " + record);
            }

            mPages.get(record.page).removeView(record.tileView);

            record.page = -1;
            record.destinationPage = tileDestPage;

            mRecords.remove(record);
            mRecords.add(runningCount, record);
            mPagerAdapter.notifyDataSetChanged();
        }
        if (record.page == -1) {
            // add the view
            mPages.get(record.destinationPage).addView(record.tileView);
            record.page = record.destinationPage;
            if (DEBUG_TILES) {
                Log.d(TAG, "added view " + record);
            }
        }
        runningCount++;
    }

    if (isShowingDetail()) {
        mDetail.bringToFront();
    }
    mPagerAdapter.notifyDataSetChanged();

    refreshAllTiles();
    requestLayout();
}

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.
 *//*  w w  w  .j  av  a 2  s.  com*/
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);
    }
}

From source file:marytts.modules.phonemiser.AllophoneSet.java

/**
 * Syllabify a string of allophones. If stress markers are provided, they are preserved; otherwise, primary stress will be
 * assigned to the initial syllable.// w w  w  .j a v a2s  . c om
 * <p>
 * The syllabification algorithm itself follows the <i>Core Syllabification Principle (CSP)</i> from <blockquote>G.N. Clements
 * (1990) "The role of the sonority cycle in core syllabification." In: J. Kingston &amp; M.E. Beckman (Eds.),
 * <em>Papers in Laboratory Phonology I: Between the Grammar and Physics of Speech</em>, Ch. 17, pp. 283-333, Cambridge
 * University Press.</blockquote>
 *
 * @param phoneString
 *            phoneString
 * @return a syllabified string; individual allophones are separated by spaces, and syllables, by dashes.
 * @throws IllegalArgumentException
 *             if the <b>phoneString</b> is empty or contains a symbol that satisfies none of the following conditions:
 *             <ol>
 *             <li>the symbol corresponds to an Allophone, or</li> <li>the symbol is a stress symbol (cf. {@link Stress}), or
 *             </li> <li>the symbol is a syllable boundary (<code>-</code>)</li>
 *             </ol>
 * 
 */
public String syllabify(String phoneString) throws IllegalArgumentException {
    // Before we process, a sanity check:
    if (phoneString.trim().isEmpty()) {
        throw new IllegalArgumentException("Cannot syllabify empty phone string");
    }

    // First, split phoneString into a List of allophone Strings...
    List<String> allophoneStrings = splitIntoAllophoneList(phoneString, true);
    // ...and create from it a List of generic Objects
    List<Object> phonesAndSyllables = new ArrayList<Object>(allophoneStrings);

    // Create an iterator
    ListIterator<Object> iterator = phonesAndSyllables.listIterator();

    // First iteration (left-to-right):
    // CSP (a): Associate each [+syllabic] segment to a syllable node.
    Syllable currentSyllable = null;
    while (iterator.hasNext()) {
        String phone = (String) iterator.next();
        try {
            // either it's an Allophone
            Allophone allophone = getAllophone(phone);
            if (allophone.isSyllabic()) {
                // if /6/ immediately follows a non-diphthong vowel, it should be appended instead of forming its own syllable
                boolean appendR = false;
                if (allophone.getFeature("ctype").equals("r")) {
                    // it's an /6/
                    if (iterator.previousIndex() > 1) {
                        Object previousPhoneOrSyllable = phonesAndSyllables.get(iterator.previousIndex() - 1);
                        if (previousPhoneOrSyllable == currentSyllable) {
                            // the /6/ immediately follows the current syllable
                            if (!currentSyllable.getLastAllophone().isDiphthong()) {
                                // the vowel immediately preceding the /6/ is not a diphthong
                                appendR = true;
                            }
                        }
                    }
                }
                if (appendR) {
                    iterator.remove();
                    currentSyllable.appendAllophone(allophone);
                } else {
                    currentSyllable = new Syllable(allophone);
                    iterator.set(currentSyllable);
                }
            }
        } catch (IllegalArgumentException e) {
            // or a stress or boundary marker
            if (!getIgnoreChars().contains(phone)) {
                throw e;
            }
        }
    }

    // Second iteration (right-to-left):
    // CSP (b): Given P (an unsyllabified segment) preceding Q (a syllabified segment), adjoin P to the syllable containing Q
    // iff P has lower sonority rank than Q (iterative).
    currentSyllable = null;
    boolean foundPrimaryStress = false;
    iterator = phonesAndSyllables.listIterator(phonesAndSyllables.size());
    while (iterator.hasPrevious()) {
        Object phoneOrSyllable = iterator.previous();
        if (phoneOrSyllable instanceof Syllable) {
            currentSyllable = (Syllable) phoneOrSyllable;
        } else if (currentSyllable == null) {
            // haven't seen a Syllable yet in this iteration
            continue;
        } else {
            String phone = (String) phoneOrSyllable;
            try {
                // it's an Allophone -- prepend to the Syllable
                Allophone allophone = getAllophone(phone);
                if (allophone.sonority() < currentSyllable.getFirstAllophone().sonority()) {
                    iterator.remove();
                    currentSyllable.prependAllophone(allophone);
                }
            } catch (IllegalArgumentException e) {
                // it's a provided stress marker -- assign it to the Syllable
                switch (phone) {
                case Stress.PRIMARY:
                    iterator.remove();
                    currentSyllable.setStress(Stress.PRIMARY);
                    foundPrimaryStress = true;
                    break;
                case Stress.SECONDARY:
                    iterator.remove();
                    currentSyllable.setStress(Stress.SECONDARY);
                    break;
                case "-":
                    iterator.remove();
                    // TODO handle syllable boundaries
                    break;
                default:
                    throw e;
                }
            }
        }
    }

    // Third iteration (left-to-right):
    // CSP (c): Given Q (a syllabified segment) followed by R (an unsyllabified segment), adjoin R to the syllable containing
    // Q iff has a lower sonority rank than Q (iterative).
    Syllable initialSyllable = currentSyllable;
    currentSyllable = null;
    iterator = phonesAndSyllables.listIterator();
    while (iterator.hasNext()) {
        Object phoneOrSyllable = iterator.next();
        if (phoneOrSyllable instanceof Syllable) {
            currentSyllable = (Syllable) phoneOrSyllable;
        } else {
            String phone = (String) phoneOrSyllable;
            try {
                // it's an Allophone -- append to the Syllable
                Allophone allophone;
                try {
                    allophone = getAllophone(phone);
                } catch (IllegalArgumentException e) {
                    // or a stress or boundary marker -- remove
                    if (getIgnoreChars().contains(phone)) {
                        iterator.remove();
                        continue;
                    } else {
                        throw e;
                    }
                }
                if (currentSyllable == null) {
                    // haven't seen a Syllable yet in this iteration
                    iterator.remove();
                    if (initialSyllable == null) {
                        // haven't seen any syllable at all
                        initialSyllable = new Syllable(allophone);
                        iterator.add(initialSyllable);
                    } else {
                        initialSyllable.prependAllophone(allophone);
                    }
                } else {
                    // append it to the last seen Syllable
                    iterator.remove();
                    currentSyllable.appendAllophone(allophone);
                }
            } catch (IllegalArgumentException e) {
                throw e;
            }
        }
    }

    // if primary stress was not provided, assign it to initial syllable
    if (!foundPrimaryStress) {
        initialSyllable.setStress(Stress.PRIMARY);
    }

    // join Syllables with dashes and return the String
    return StringUtils.join(phonesAndSyllables, " - ");
}