@Override public Highlight clone() { try { Highlight clone = (Highlight) super.clone(); clone.highlightItems = new LinkedHashMap<>(); for (Map.Entry<String,AndItem> entry: highlightItems.entrySet()) { clone.highlightItems.put(entry.getKey(),(AndItem)entry.getValue().clone()); } clone.highlightTerms = new LinkedHashMap<>(); for (Map.Entry<String, List<String>> entry : highlightTerms.entrySet()) clone.highlightTerms.put(entry.getKey(), new ArrayList<>(entry.getValue())); return clone; } catch (CloneNotSupportedException e) { throw new RuntimeException(e); } }
@NonNull private CompositeItem buildAnd(OperatorNode<ExpressionOperator> ast) { AndItem andItem = new AndItem(); NotItem notItem = new NotItem(); convertVarArgsAnd(ast, 0, andItem, notItem); Preconditions .checkArgument(andItem.getItemCount() > 0, "Vespa does not support AND with no logically positive branches."); if (notItem.getItemCount() == 0) { return andItem; } if (andItem.getItemCount() == 1) { notItem.setPositiveItem(andItem.getItem(0)); } else { notItem.setPositiveItem(andItem); } return notItem; }
/** * Creates the root of the query subtree which will contain the grams to match, * called by {@link #splitToGrams}. This hook is provided to make it easy to create a subclass which * matches grams using a different composite item, e.g an OrItem. * <p> * This default implementation return new AndItem(); * * @param query the input query, to make it possible to return a different composite item type * depending on the query content * @return the composite item to add the gram items to in {@link #splitToGrams} */ protected CompositeItem createGramRoot(Query query) { return new AndItem(); }
private static CompositeItem extractAndNot(AndItem parent) { NotItem theOnlyNot = null; for (int i = 0; i < parent.getItemCount(); i++) { Item child = parent.getItem(i); if (child instanceof NotItem) { NotItem thisNot = (NotItem) child; parent.setItem(i, thisNot.getPositiveItem()); if (theOnlyNot == null) { theOnlyNot = thisNot; theOnlyNot.setPositiveItem(parent); } else { for (int j=1; j < thisNot.getItemCount(); j++) { theOnlyNot.addNegativeItem(thisNot.getItem(j)); } } } } return (theOnlyNot != null) ? theOnlyNot : parent; }
private boolean optimizeAnd(AndItem and, IndexFacts.Session indexFacts) { // Find consolidated ranges by collecting a list of compatible ranges List<FieldRange> fieldRanges = null; for (Iterator<Item> i = and.getItemIterator(); i.hasNext(); ) { Item item = i.next(); if ( ! (item instanceof IntItem)) continue; IntItem intItem = (IntItem)item; if (intItem.getHitLimit() != 0) continue; // each such op gets a different partial set: Cannot be optimized if (intItem.getFromLimit().equals(intItem.getToLimit())) continue; // don't optimize searches for single numbers if (indexFacts.getIndex(intItem.getIndexName()).isMultivalue()) continue; // May match different values in each range if (fieldRanges == null) fieldRanges = new ArrayList<>(); Optional<FieldRange> compatibleRange = findCompatibleRange(intItem, fieldRanges); if (compatibleRange.isPresent()) compatibleRange.get().addRange(intItem); else fieldRanges.add(new FieldRange(intItem)); i.remove(); } // Add consolidated ranges if (fieldRanges == null) return false; boolean optimized = false; for (FieldRange fieldRange : fieldRanges) { and.addItem(fieldRange.toItem()); optimized |= fieldRange.isOptimization(); } return optimized; }
List<WordItem> words = new ArrayList<>(); List<CompositeItem> phrases = new ArrayList<>(); for (Iterator<Item> i = root.getItemIterator(); i.hasNext(); ) { Item item = i.next(); if (item instanceof WordItem) {
private void convertVarArgsAnd(OperatorNode<ExpressionOperator> ast, int argIdx, AndItem outAnd, NotItem outNot) { Iterable<OperatorNode<ExpressionOperator>> args = ast.getArgument(argIdx); for (OperatorNode<ExpressionOperator> arg : args) { assertHasOperator(arg, ExpressionOperator.class); if (arg.getOperator() == ExpressionOperator.NOT) { OperatorNode<ExpressionOperator> exp = arg.getArgument(0); assertHasOperator(exp, ExpressionOperator.class); outNot.addNegativeItem(convertExpression(exp)); } else { outAnd.addItem(convertExpression(arg)); } } }
@NonNull private CompositeItem buildAnd(String key, Inspector value) { AndItem andItem = new AndItem(); addItemsFromInspector(andItem, value); return andItem; }
/** * Convert AndItem to PhraseItem<br> * * e.g. (AND a b) to "a b" * @param andItem query tree to be converted * @return converted PhraseItem */ private static PhraseItem convertAndToPhrase(AndItem andItem) { PhraseItem result = new PhraseItem(); Iterator<Item> subItems = andItem.getItemIterator(); while(subItems.hasNext()) { Item curr = (subItems.next()); if(curr instanceof IntItem) { WordItem numItem = new WordItem(((IntItem)curr).stringValue()); result.addItem(numItem); } else { result.addItem(curr); } } return result; }
private void addHighlightItem(String key, Item value) { /*List<IndexedItem> l = highlightItems.get(key); if (l == null) { l = new ArrayList<IndexedItem>(); highlightItems.put(key, l); } l.addField(value);*/ AndItem item = highlightItems.get(key); if (item == null) { item = new AndItem(); highlightItems.put(key, item); } item.addItem(value); }
private CompositeItem createType(TermType termType) { if (termType==TermType.DEFAULT) { if (query.getModel().getType().equals(Query.Type.ANY)) return new OrItem(); else return new AndItem(); } else if (termType==TermType.AND) { return new AndItem(); } else if (termType==TermType.OR) { return new OrItem(); } else if (termType==TermType.RANK) { return new RankItem(); } else if (termType==TermType.NOT) { return new NotItem(); } throw new IllegalArgumentException("Programing error, this method should be updated with add in RankType"); }
private Item addAndFilter(Item root, Item item) { if (item == null) { return root; } if (root instanceof AndItem) { ((AndItem) root).addItem(item); return root; } if (root instanceof RankItem) { Item firstChild = ((RankItem) root).getItem(0); if (firstChild instanceof AndItem) { ((AndItem) firstChild).addItem(item); return root; } else if (firstChild instanceof NotItem) { ((NotItem) firstChild).addPositiveItem(item); return root; } } AndItem and = new AndItem(); and.addItem(root); and.addItem(item); return and; }
/** * Convert segment items into their mutable counterpart, do not update query tree. * Non-segment items are returned directly. * * @return a mutable CompositeItem instance */ private CompositeItem convertSegmentItem(CompositeItem item) { if (!(item instanceof SegmentItem)) { return item; } CompositeItem converted = null; if (item instanceof AndSegmentItem) { converted = new AndItem(); } else if (item instanceof PhraseSegmentItem) { PhraseItem p = new PhraseItem(); PhraseSegmentItem old = (PhraseSegmentItem) item; p.setIndexName(old.getIndexName()); converted = p; } else { // TODO: Do something else than nothing for unknowns? return item; } for (Iterator<Item> i = item.getItemIterator(); i.hasNext();) { converted.addItem(i.next()); } return converted; }
static public void andQueryItemWithRoot(QueryTree tree, Item item) { if (tree.isEmpty()) { tree.setRoot(item); } else { Item oldRoot = tree.getRoot(); if (oldRoot.getClass() == AndItem.class) { ((AndItem) oldRoot).addItem(item); } else { AndItem newRoot = new AndItem(); newRoot.addItem(oldRoot); newRoot.addItem(item); tree.setRoot(newRoot); } } }
private void addAndItem(QueryTree q, String term) { Item root = q.getRoot(); CompositeItem compositeRoot; if (root instanceof AndItem) { compositeRoot = (CompositeItem) root; } else { compositeRoot = new AndItem(); compositeRoot.addItem(root); q.setRoot(compositeRoot); } compositeRoot.addItem(new WordItem(term)); }
/** * Convenience method for adding a positive item. * If a positive item is already present * the positive item becomes an AndItem with the items added */ public void addPositiveItem(Item item) { if (getPositiveItem() == null) { setPositiveItem(item); } else if (getPositiveItem() instanceof AndItem) { ((AndItem) getPositiveItem()).addItem(item); } else { AndItem positives = new AndItem(); positives.addItem(getPositiveItem()); positives.addItem(item); setPositiveItem(positives); } }
private void insertIncompatibleItem(Item item,CompositeItem parent,Query query,TermType desiredParentType) { // Create new parent CompositeItem newParent; if (desiredParentType==TermType.DEFAULT) newParent=new AndItem(); else newParent=(CompositeItem)desiredParentType.createItemClass(); // Save previous parent parent CompositeItem parentsParent=parent.getParent(); // Add items to new parent newParent.addItem(parent); newParent.addItem(item); // Insert new parent as root or child of old parents parent if (parentsParent==null) { query.getModel().getQueryTree().setRoot(newParent); } else { int parentIndex=0; if (parentsParent!=null) { parentIndex=parentsParent.getItemIndex(parent); } parentsParent.setItem(parentIndex,newParent); } }
if (asPhrase.isExplicit() || hasOverlappingTokens(asPhrase)) return root; AndItem replacement = new AndItem(); for (ListIterator<Item> i = ((CompositeItem) root).getItemIterator(); i.hasNext();) { Item item = i.next(); if (item instanceof WordItem) replacement.addItem(item); else if (item instanceof PhraseSegmentItem) { replacement.addItem(new AndSegmentItem((PhraseSegmentItem) item)); else replacement.addItem(item); // should never run, but hey... just convert and hope it's OK :)
if (or==null) or=addOr(and,or); and=new AndItem(); or.addItem(and);