/** * */ package querqy.rewrite.commonrules.model; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import querqy.ComparableCharSequence; import querqy.model.BooleanQuery; import querqy.model.Clause.Occur; import querqy.model.DisjunctionMaxQuery; import querqy.model.ExpandedQuery; import querqy.model.Term; /** * @author René Kriegler, @renekrie * */ public class SynonymInstruction implements Instruction { final List<querqy.rewrite.commonrules.model.Term> synonym; /** * */ public SynonymInstruction(final List<querqy.rewrite.commonrules.model.Term> synonym) { if (synonym == null || synonym.isEmpty()) { throw new IllegalArgumentException("Synonym expansion required"); } this.synonym = synonym; } /* (non-Javadoc) * @see querqy.rewrite.commonrules.model.Instruction#apply(querqy.rewrite.commonrules.model.PositionSequence, querqy.rewrite.commonrules.model.TermMatches, int, int, querqy.model.ExpandedQuery, java.util.Map) */ @Override public void apply(final PositionSequence<Term> sequence, final TermMatches termMatches, final int startPosition, final int endPosition, final ExpandedQuery expandedQuery, final Map<String, Object> context) { switch (termMatches.size()) { case 0: throw new IllegalArgumentException("termMatches must not be empty"); case 1: { final Term match = termMatches.get(0).getQueryTerm(); final DisjunctionMaxQuery parent = match.getParent(); if (synonym.size() == 1) { addSynonymTermToDisjunctionMaxQuery(parent, synonym.get(0), termMatches); } else { final BooleanQuery bq = new BooleanQuery(match.getParent(), Occur.SHOULD, true); match.getParent().addClause(bq); for (final querqy.rewrite.commonrules.model.Term synTerm: synonym) { final DisjunctionMaxQuery dmq = new DisjunctionMaxQuery(bq, Occur.MUST, true); bq.addClause(dmq); addSynonymTermToDisjunctionMaxQuery(dmq, synTerm, termMatches); } } } break; default: for (final TermMatch match: termMatches) { final DisjunctionMaxQuery clauseDmq = match.getQueryTerm().getParent(); if (synonym.size() == 1) { addSynonymTermToDisjunctionMaxQuery(clauseDmq, synonym.get(0), termMatches); } else { final BooleanQuery bq = new BooleanQuery(clauseDmq, Occur.SHOULD, true); clauseDmq.addClause(bq); for (final querqy.rewrite.commonrules.model.Term synTerm: synonym) { final DisjunctionMaxQuery dmq = new DisjunctionMaxQuery(bq, Occur.MUST, true); bq.addClause(dmq); addSynonymTermToDisjunctionMaxQuery(dmq, synTerm, termMatches); } } } } } protected void addSynonymTermToDisjunctionMaxQuery(final DisjunctionMaxQuery dmq, final querqy.rewrite.commonrules.model.Term synTerm, final TermMatches termMatches) { final List<String> fieldNames = synTerm.getFieldNames(); final ComparableCharSequence charSequence = synTerm.fillPlaceholders(termMatches); if (fieldNames == null || fieldNames.isEmpty()) { dmq.addClause(new Term(dmq, charSequence, true)); } else { for (final String fieldName: fieldNames) { dmq.addClause(new Term(dmq, fieldName, charSequence, true)); } } } @Override public Set<Term> getGenerableTerms() { final Set<Term> result = new HashSet<>(); for (querqy.rewrite.commonrules.model.Term synTerm: synonym) { if (!synTerm.hasPlaceHolder()) { final List<String> fieldNames = synTerm.getFieldNames(); if (fieldNames == null || fieldNames.isEmpty()) { result.add(new Term(null, synTerm, true)); } else { for (final String fieldName: fieldNames) { result.add(new Term(null, fieldName, synTerm, true)); } } } } return result; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((synonym == null) ? 0 : synonym.hashCode()); return result; } @Override public boolean equals(final Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; final SynonymInstruction other = (SynonymInstruction) obj; if (synonym == null) { if (other.synonym != null) return false; } else if (!synonym.equals(other.synonym)) return false; return true; } @Override public String toString() { return "SynonymInstruction [synonym=" + synonym + "]"; } }