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; }
@Override public TermItem getItem(int index) { adjustIfBackingChanged(); return (TermItem)owner.getItem(startIndex+index); }
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 Substring getOffsets(BlockItem b) { if (b instanceof TermItem) { return b.getOrigin(); } else if (b instanceof CompositeItem) { Item i = ((CompositeItem) b).getItem(0); if (i instanceof TermItem) { return ((TermItem) i).getOrigin(); // this should always be the case } else { getLogger().log(LogLevel.WARNING, "Weird, BlockItem '" + b + "' was a composite containing " + i.getClass().getName() + ", expected TermItem."); } } return null; }
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); } }
public Item next() { if (!hasNext()) throw new NoSuchElementException(this + " has no more elements"); currentIndex++; if ((phrase.matched instanceof MatchedWord)) return ((MatchedWord)phrase.matched).getItem(); else return phrase.getOwner().getItem(phrase.getStartIndex()+currentIndex-1); }
/** * 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; }
/** Removes an item, prefers the one at/close to the given position if there are multiple ones */ public void removeItem(int position,Item item) { Item removeCandidate=item.getParent().getItem(position); if (removeCandidate.equals(item)) // Remove based on position item.getParent().removeItem(position); else item.getParent().removeItem(item); // Otherwise, just removeField any such 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); } }
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; }
/** 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 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; }
private void addItem(CompositeItem parent,int index,Item item,TermType desiredParentType) { if (parent instanceof NotItem) { if (index==0 && parent.getItem(0)==null) { // Case 1: The current positive is null and we are adding a positive parent.setItem(0,item); } else if (index<=1 && !(parent.getItem(0) instanceof CompositeItem)) { // Case 2: The positive must become a composite CompositeItem positiveComposite=(CompositeItem)desiredParentType.createItemClass(); positiveComposite.addItem(parent.getItem(0)); positiveComposite.addItem(index,item); parent.setItem(0,positiveComposite); } else if (parent.getItem(0)!=null && parent.getItem(0) instanceof CompositeItem // Case 3: Add to the positive composite && index<=((CompositeItem)parent.getItem(0)).getItemCount()) { ((CompositeItem)parent.getItem(0)).addItem(index,item); } else { // Case 4: Add negative parent.addItem(index,item); } } else if (parent.getItemCount()>0 && parent instanceof QueryTree) { CompositeItem composite=(CompositeItem)desiredParentType.createItemClass(); composite.addItem(parent.getItem(0)); composite.addItem(index,item); parent.setItem(0,composite); } else { parent.addItem(index,item); } }
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 Recall optimizeCompositeItemByRestrict(CompositeItem item, String restrictParam) { Recall recall = Recall.UNKNOWN_RECALL; for (int i = item.getItemCount(); --i >= 0; ) { switch (optimizeByRestrict(item.getItem(i), restrictParam)) { case RECALLS_EVERYTHING: if ((item instanceof OrItem) || (item instanceof EquivItem)) {
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; }
/** * 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 }
private boolean rewriteToNGramMatching(Item item, int indexInParent, IndexFacts.Session indexFacts, Query query) { boolean rewritten = false; if (item instanceof SegmentItem) { // handle CJK segmented terms which should be grams instead SegmentItem segments = (SegmentItem)item; Index index = indexFacts.getIndex(segments.getIndexName()); if (index.isNGram()) { Item grams = splitToGrams(segments, toLowerCase(segments.getRawWord()), index.getGramSize(), query); replaceItemByGrams(item, grams, indexInParent); rewritten = true; } } else if (item instanceof CompositeItem) { CompositeItem composite = (CompositeItem)item; for (int i=0; i<composite.getItemCount(); i++) rewritten = rewriteToNGramMatching(composite.getItem(i), i, indexFacts, query) || rewritten; } else if (item instanceof TermItem) { TermItem term = (TermItem)item; Index index = indexFacts.getIndex(term.getIndexName()); if (index.isNGram()) { Item grams = splitToGrams(term,term.stringValue(), index.getGramSize(), query); replaceItemByGrams(item, grams, indexInParent); rewritten = true; } } return rewritten; }