/*
* Copyright 2013 Websquared, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.fastcatsearch.ir.search.clause;
import java.io.IOException;
import java.io.PrintStream;
import java.io.Writer;
import org.fastcatsearch.ir.query.RankInfo;
/**
* 왼쪽 op에서 일치한 단어(matchFlag기반) 가 우측 op에서 출현시는 문서를 포함하지 않는다.
* 우측 op가 우선적인 선택적 OR이다.
* */
public class LOrOperatedClause extends OperatedClause {
private OperatedClause clause1;
private OperatedClause clause2;
private boolean hasNext1 = true;
private boolean hasNext2 = true;
private RankInfo docInfo1;
private RankInfo docInfo2;
public LOrOperatedClause(OperatedClause clause1, OperatedClause clause2) {
super("LOR");
if(clause1 == null) {
clause1 = NullClause.getOperatedClause();
}
if(clause2 == null) {
clause2 = NullClause.getOperatedClause();
}
this.clause1 = clause1;
this.clause2 = clause2;
}
protected boolean nextDoc(RankInfo rankInfo) {
if(hasNext1 || hasNext2){
int doc1 = docInfo1.docNo();
int doc2 = docInfo2.docNo();
if(hasNext1 && hasNext2){
if(doc1 < doc2){
rankInfo.init(doc1, docInfo1.score(), docInfo1.hit());
rankInfo.addMatchFlag(docInfo1.matchFlag());
rankInfo.explain(docInfo1);
hasNext1 = clause1.next(docInfo1);
}else if(doc1 > doc2){
rankInfo.init(doc2, docInfo2.score(), docInfo2.hit());
rankInfo.addMatchFlag(docInfo2.matchFlag());
rankInfo.explain(docInfo2);
hasNext2 = clause2.next(docInfo2);
}else{
//우측 단어가 왼쪽에 모두 포함이면 버린다.
if(docInfo1.isMatchContains(docInfo2.matchFlag())){
rankInfo.init(doc1, docInfo1.score(), docInfo1.hit());
rankInfo.addMatchFlag(docInfo1.matchFlag());
rankInfo.explain(docInfo1);
} else {
rankInfo.init(doc1, docInfo1.score() + docInfo2.score(), docInfo1.hit() + docInfo2.hit());
rankInfo.addMatchFlag(docInfo1.matchFlag());
rankInfo.addMatchFlag(docInfo2.matchFlag());
rankInfo.explain(docInfo1);
rankInfo.explain(docInfo2);
}
hasNext1 = clause1.next(docInfo1);
hasNext2 = clause2.next(docInfo2);
}
return true;
}
if(hasNext1){
rankInfo.init(doc1, docInfo1.score(), docInfo1.hit());
rankInfo.addMatchFlag(docInfo1.matchFlag());
rankInfo.explain(docInfo1);
hasNext1 = clause1.next(docInfo1);
return true;
}
if(hasNext2){
rankInfo.init(doc2, docInfo2.score(), docInfo2.hit());
rankInfo.addMatchFlag(docInfo2.matchFlag());
rankInfo.explain(docInfo2);
hasNext2 = clause2.next(docInfo2);
return true;
}
}
return false;
}
@Override
public void close() {
if(clause1 != null){
clause1.close();
}
if(clause2 != null){
clause2.close();
}
}
@Override
protected void initClause(boolean explain) {
docInfo1 = new RankInfo(explain);
docInfo2 = new RankInfo(explain);
clause1.init(explanation != null ? explanation.createSubExplanation() : null);
clause2.init(explanation != null ? explanation.createSubExplanation() : null);
hasNext1 = clause1.next(docInfo1);
hasNext2 = clause2.next(docInfo2);
}
@Override
public void printTrace(Writer writer, int indent, int depth) throws IOException {
String indentSpace = "";
if(depth > 0){
for (int i = 0; i < (depth - 1) * indent; i++) {
indentSpace += " ";
}
for (int i = (depth - 1) * indent, p = 0; i < depth * indent; i++, p++) {
if(p == 0){
indentSpace += "|";
}else{
indentSpace += "-";
}
}
}
writer.append(indentSpace).append("[LOR]\n");
if(clause1 != null){
clause1.printTrace(writer, indent, depth + 1);
}
if(clause2 != null){
clause2.printTrace(writer, indent, depth + 1);
}
}
@Override
public OperatedClause[] children() {
return new OperatedClause[] {
clause1,
clause2
};
}
}