public static Set<PhraseMatcher.Phrase> getNonOverlappingFullPhraseMatches(PhraseMatcher phraseMatcher,
                                                                               Query query)
                                                                               throws RuntimeException {
        RewriterUtils.log(logger, query, "Retrieving longest non-overlapping full phrase matches");
        if (phraseMatcher == null)
            return null;

        Item root = query.getModel().getQueryTree().getRoot();
        List<PhraseMatcher.Phrase> matches = phraseMatcher.matchPhrases(root);
        if (matches == null || matches.isEmpty())
            return null;

        Set<PhraseMatcher.Phrase> resultMatches = new HashSet<>();
        ListIterator<Phrase> matchesIter = matches.listIterator();

        // Iterate through all matches
        while (matchesIter.hasNext()) {
            PhraseMatcher.Phrase phrase = matchesIter.next();
            RewriterUtils.log(logger, query, "Working on phrase: " + phrase);
            CompositeItem currOwner = phrase.getOwner();

            // Check if this is full phrase
            // If phrase is not an AND item, only keep those that are single word
            // in order to eliminate cases such as (new RANK york) from being treated
            // as match if only new york but not new or york is in the dictionary
            if((currOwner != null &&
                ((phrase.isComplete() && currOwner instanceof AndItem) ||
                 (phrase.getLength() == 1 && currOwner instanceof OrItem) ||
                 (phrase.getLength() == 1 && currOwner instanceof RankItem && phrase.getStartIndex() == 0))) ||
               (currOwner == null && phrase.getLength() == 1)) {
               resultMatches.add(phrase);
               RewriterUtils.log(logger, query, "Keeping phrase: " + phrase);
            }
        }

        RewriterUtils.log(logger, query, "Successfully Retrieved longest non-overlapping full phrase matches");
        return resultMatches;
    }
<p>Retrieve the longest, from left to right non overlapping full
phrase substrings in query based on FSA dictionary</p>

e.g. query: ((modern AND new AND york AND city AND travel) OR travel) AND
            ((sunny AND travel AND agency) OR nyc)<br>
     dictionary: <br>
                 mny\tmodern new york<br>
                 mo\tmodern<br>
                 modern\tn/a<br>
                 modern\tnew york\tn/a<br>
                 new york\tn/a<br>
                 new york city\tn/a<br>
                 new york city travel\tn/a<br>
                 new york company\tn/a<br>
                 ny\tnew york<br>
                 nyc\tnew york city\tnew york company<br>
                 nyct\tnew york city travel<br>
                 ta\ttravel agency<br>
                 travel agency\tn/a<br>
     return: nyc
@param phraseMatcher PhraseMatcher object loaded with FSA dict
@param query Query object from the searcher
@return Matching phrases
container-search/src/main/java/com/yahoo/search/query/rewrite/RewriterFeatures.java