public boolean isComplete() { return startIndex==0 && length==owner.getItemCount(); }
public int getBackedLength() { return owner.getItemCount()-startIndex; }
public MatchedComposite(CompositeItem owner,List<String> replace,int startIndex,int length) { this.owner=owner; this.initialOwnerLength=owner.getItemCount(); this.replace = replace; this.startIndex=startIndex; this.startItem=owner.getItem(startIndex); this.length=length; }
public boolean hasItemAt(int index) { adjustIfBackingChanged(); if (startIndex<0) return false; // Invalid state because of backing changes if ( index >= length ) return false; if ( index+startIndex >= owner.getItemCount() ) return false; return true; }
/** * Detects and attemts to compensate for a changed backing. Stop-gap measure until we get a through * design for this */ private void adjustIfBackingChanged() { if (owner.getItemCount()==initialOwnerLength) return; startIndex=owner.getItemIndex(startItem); }
private TaggableItem lastWord(CompositeItem composite) { // yes, this assumes only WordItem instances in the CompositeItem int l = composite.getItemCount(); if (l == 0) { return null; } else { return (TaggableItem) composite.getItem(l - 1); } }
private TaggableItem firstWord(CompositeItem composite) { // yes, this assumes only WordItem instances in the CompositeItem int l = composite.getItemCount(); if (l == 0) { return null; } else { return (TaggableItem) composite.getItem(0); } }
@Override public boolean visit(Item item) { if (item instanceof NullItem) { throw new IllegalArgumentException("Got NullItem inside nonEmpty()."); } else if (item instanceof WordItem) { if (((WordItem) item).getIndexedString().isEmpty()) { throw new IllegalArgumentException("Searching for empty string inside nonEmpty()"); } } else if (item instanceof CompositeItem) { if (((CompositeItem) item).getItemCount() == 0) { throw new IllegalArgumentException("Empty composite operator (" + item.getName() + ") inside nonEmpty()"); } } return true; }
/** * Removes and returns the first <i>not</i> found in the composite, * or returns null if there's none */ private NotItem removeNot(CompositeItem composite) { for (int i = 0; i < composite.getItemCount(); i++) { if (composite.getItem(i) instanceof NotItem) { return (NotItem) composite.removeItem(i); } } return null; }
private void remove(List<PhraseMatcher.Phrase> phrases) { // Removing the leaf replace phrases first to preserve // the start index of each replace phrase until removing for (int i = phrases.size()-1; i >= 0; i-- ) { PhraseMatcher.Phrase phrase = phrases.get(i); if (phrase.getLength() < phrase.getOwner().getItemCount()) // Don't removeField all phrase.remove(); } }
private static CompositeItem extractAndNotRecursively(CompositeItem parent) { for (int i = 0; i < parent.getItemCount(); i++) { Item child = parent.getItem(i); Item possibleNewChild = optimizeAndNot(child); if (child != possibleNewChild) { parent.setItem(i, possibleNewChild); } } if (parent instanceof AndItem) { return extractAndNot((AndItem) parent); } return parent; }
/** Find matches within a composite */ private void recursivelyMatchPhrases(Item item, MatchedPhrases phrases) { if (item == null) return; if ( ! (item instanceof CompositeItem) ) return; if ( ! matchPhraseItems && item instanceof PhraseItem ) return; CompositeItem owner=(CompositeItem)item; int i=0; int checkItemCount=owner.getItemCount(); if (owner instanceof NotItem) checkItemCount=1; // Skip negatives while (i<checkItemCount) { int largestFoundLength=findPhrasesAtStartpoint(i,owner,phrases); if (largestFoundLength==0 || matchAll) { recursivelyMatchPhrases(owner.getItem(i),phrases); i=i+1; } else { i=i+largestFoundLength; } } }
private static Item collapseSingleComposites(Item item) { if (!(item instanceof CompositeItem)) { return item; } CompositeItem parent = (CompositeItem)item; int numChildren = parent.getItemCount(); for (int i = 0; i < numChildren; ++i) { Item oldChild = parent.getItem(i); Item newChild = collapseSingleComposites(oldChild); if (oldChild != newChild) { parent.setItem(i, newChild); } } return ((numChildren == 1) && !(parent instanceof NonReducibleCompositeItem)) ? parent.getItem(0) : item; }
private static void removeOtherNonrankedChildren(CompositeItem parent, int indexOfChildToKeep) { Item childToKeep = parent.getItem(indexOfChildToKeep); for (int i = parent.getItemCount(); --i >= 0; ) { Item child = parent.getItem(i); if ( child != childToKeep && ! parent.getItem(i).isRanked()) parent.removeItem(i); } }
public static void visit(QueryVisitor visitor, Item item) { if (item instanceof CompositeItem) { if (visitor.visit(item)) { CompositeItem composite = (CompositeItem) item; for (int i = 0; i < composite.getItemCount(); ++i) { visit(visitor, composite.getItem(i)); } } } else { visitor.visit(item); } visitor.onExit(); }
/** * Inserts an item to the query being evaluated in a way consistent with the query type * * @param item the item to insert * @param parent the parent of this item, or null to set the root * @param index the index at which to insert this into the parent * @param desiredParentType the desired type of the composite which contains item when this returns */ public void insertItem(Item item, CompositeItem parent, int index, TermType desiredParentType) { if (parent==null) { // TODO: Accommodate for termtype in this case too query.getModel().getQueryTree().setRoot(item); return; } if (parent.getItemCount()>0 && parent instanceof QueryTree && parent.getItem(0) instanceof CompositeItem) { // combine with the existing root instead parent=(CompositeItem)parent.getItem(0); if (index==1) { // that means adding it after the existing root index=parent.getItemCount(); } } if (( desiredParentType==TermType.DEFAULT || desiredParentType.hasItemClass(parent.getClass()) ) && equalIndexNameIfParentIsPhrase(item,parent)) { addItem(parent,index,item,desiredParentType); } else { insertIncompatibleItem(item,parent,query,desiredParentType); } }
private static CanonicalizationResult canonicalizeThis(Item item, ListIterator<Item> parentIterator) { if (item instanceof NullItem) parentIterator.remove(); if ( ! (item instanceof CompositeItem)) return CanonicalizationResult.success(); CompositeItem composite = (CompositeItem)item; boolean replacedByFalse = collapseFalse(composite, parentIterator); if (replacedByFalse) return CanonicalizationResult.success(); collapseLevels(composite); if (composite instanceof EquivItem) { removeDuplicates((EquivItem) composite); } else if (composite instanceof RankItem) { makeDuplicatesCheap((RankItem)composite); } else if (composite instanceof NotItem) { if (((NotItem) composite).getPositiveItem() == null) return CanonicalizationResult.error("Can not search for only negative items"); } if (composite.getItemCount() == 0) parentIterator.remove(); if (composite.getItemCount() == 1 && ! (composite instanceof NonReducibleCompositeItem)) { if (composite instanceof PhraseItem || composite instanceof PhraseSegmentItem) composite.getItem(0).setWeight(composite.getWeight()); parentIterator.set(composite.getItem(0)); } return CanonicalizationResult.success(); }
private static Item rewriteSddocname(Item item) { if (item instanceof CompositeItem) { CompositeItem parent = (CompositeItem)item; for (int i = 0, len = parent.getItemCount(); i < len; ++i) { Item oldChild = parent.getItem(i); Item newChild = rewriteSddocname(oldChild); if (oldChild != newChild) { parent.setItem(i, newChild); } } } else if (item instanceof SimpleIndexedItem) { SimpleIndexedItem oldItem = (SimpleIndexedItem)item; if (Hit.SDDOCNAME_FIELD.equals(oldItem.getIndexName())) { SubstringItem newItem = new SubstringItem(oldItem.getIndexedString()); newItem.setIndexName("[documentmetastore]"); return newItem; } } return item; }
/** * Inserts newItem at the position of this match * TODO: Move to ruleevaluation */ protected void insertMatch(RuleEvaluation e,Match matched, Item newItem,int offset) { newItem.setWeight(getWeight()); int insertPosition=matched.getPosition()+offset; // This check is necessary (?) because earlier items may have been removed // after we recorded the match position. It is sort of hackish. A cleaner // solution would be to update the match position on changes if (insertPosition>matched.getParent().getItemCount()) { insertPosition=matched.getParent().getItemCount(); } e.insertItem(newItem,matched.getParent(),insertPosition,getTermType()); if (e.getTraceLevel()>=6) e.trace(6,"Inserted item '" + newItem + "' at position " + insertPosition + " producing " + e.getEvaluation().getQuery().getModel().getQueryTree()); }
/** * Splits the given item into n-grams and adds them as a CompositeItem containing WordItems searching the * index of the input term. If the result is a single gram, that single WordItem is returned rather than the AndItem * * @param term the term to split, must be an item which implement the IndexedItem and BlockItem "mixins" * @param text the text of the item, just stringValue() if the item is a TermItem * @param gramSize the gram size to split to * @param query the query in which this rewriting is done * @return the root of the query subtree produced by this, containing the split items */ protected Item splitToGrams(Item term, String text, int gramSize, Query query) { String index = ((HasIndexItem)term).getIndexName(); CompositeItem gramsItem = createGramRoot(query); gramsItem.setIndexName(index); Substring origin = ((BlockItem)term).getOrigin(); for (Iterator<GramSplitter.Gram> i = getGramSplitter().split(text,gramSize); i.hasNext(); ) { GramSplitter.Gram gram = i.next(); WordItem gramWord = new WordItem(gram.extractFrom(text), index, false, origin); gramWord.setWeight(term.getWeight()); gramWord.setProtected(true); gramsItem.addItem(gramWord); } return gramsItem.getItemCount()==1 ? gramsItem.getItem(0) : gramsItem; // return the AndItem, or just the single gram if not multiple }