/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.stanbol.entityhub.yard.solr.impl.queryencoders;
import static org.apache.stanbol.entityhub.yard.solr.query.QueryUtils.encodePhraseQuery;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.apache.stanbol.entityhub.servicesapi.query.ValueConstraint.MODE;
import org.apache.stanbol.entityhub.yard.solr.defaults.QueryConst;
import org.apache.stanbol.entityhub.yard.solr.impl.SolrQueryFactory.ConstraintValue;
import org.apache.stanbol.entityhub.yard.solr.model.IndexValue;
import org.apache.stanbol.entityhub.yard.solr.model.IndexValueFactory;
import org.apache.stanbol.entityhub.yard.solr.query.ConstraintTypePosition;
import org.apache.stanbol.entityhub.yard.solr.query.ConstraintTypePosition.PositionType;
import org.apache.stanbol.entityhub.yard.solr.query.EncodedConstraintParts;
import org.apache.stanbol.entityhub.yard.solr.query.IndexConstraintTypeEncoder;
import org.apache.stanbol.entityhub.yard.solr.query.IndexConstraintTypeEnum;
import org.apache.stanbol.entityhub.yard.solr.query.QueryUtils;
import org.apache.stanbol.entityhub.yard.solr.query.QueryUtils.QueryTerm;
/**
* Encodes the Assignment of the field to an value. If a value is parsed, than it encodes that the field must
* be equals to this value.
*
* @author Rupert Westenthaler
*/
public class AssignmentEncoder implements IndexConstraintTypeEncoder<ConstraintValue> {
public static final ConstraintTypePosition POS = new ConstraintTypePosition(PositionType.assignment);
public static final String EQ = ":";
// private final IndexValueFactory indexValueFactory;
public AssignmentEncoder(IndexValueFactory indexValueFactory) {
// if (indexValueFactory == null) {
// throw new IllegalArgumentException("The indexValueFactory MUST NOT be NULL");
// }
// this.indexValueFactory = indexValueFactory;
}
@Override
public void encode(EncodedConstraintParts constraint, ConstraintValue value) {
if(value == null){ //if no value is parsed
constraint.addEncoded(POS,EQ); // add the default
return; //and return
} //else encode the values and add them depending on the MODE
Set<String> queryConstraints = new HashSet<String>();
Collection<String> phraseTerms = new ArrayList<String>();
for(IndexValue indexValue : value){
QueryTerm[] qts = QueryUtils.encodeQueryValue(indexValue, true);
if (qts != null) {
for (QueryTerm qt : qts) {
StringBuilder sb = new StringBuilder(qt.term.length() +
(qt.needsQuotes ? 3 : 1));
sb.append(EQ);
if(qt.needsQuotes){
sb.append('"').append(qt.term).append('"');
} else {
sb.append(qt.term);
}
if(value.getBoost() != null){
sb.append("^").append(value.getBoost());
}
queryConstraints.add(sb.toString());
if(!qt.hasWildcard && qt.isText) {
phraseTerms.add(qt.term);
}
}
} else {
queryConstraints.add(EQ);
}
if(value.getMode() == MODE.any){
//in any mode we need to add values separately
constraint.addEncoded(POS, queryConstraints);
//addEncoded copies the added values so we can clear and reuse
queryConstraints.clear();
}
}
if(value.getMode() == MODE.all){
//in all mode we need to add all values in a single call
constraint.addEncoded(POS, queryConstraints);
//NOTE also that for ALL mode Phrase queries do not make sense, as
// they would weaken the selection criteria
} else {
if(phraseTerms.size() > 1){
Boolean state = (Boolean) value.getProperty(QueryConst.PHRASE_QUERY_STATE);
if(state != null && state.booleanValue()){
StringBuilder sb = encodePhraseQuery(phraseTerms);
sb.insert(0, EQ);
if(value.getBoost() != null){
sb.append("^").append(value.getBoost());
}
constraint.addEncoded(POS, sb.toString());
}//phrase query deactivated
} //else for less than two terms we can not build a phrase query
}
}
@Override
public boolean supportsDefault() {
return true;
}
@Override
public Collection<IndexConstraintTypeEnum> dependsOn() {
return Arrays.asList(IndexConstraintTypeEnum.FIELD);
}
@Override
public IndexConstraintTypeEnum encodes() {
return IndexConstraintTypeEnum.EQ;
}
@Override
public Class<ConstraintValue> acceptsValueType() {
return ConstraintValue.class;
}
}