001/*
002 *  Copyright 2019 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.cms.search.query;
017
018import java.util.Collection;
019import java.util.Objects;
020
021import org.apache.solr.client.solrj.util.ClientUtils;
022
023/**
024 * Same as {@link OrQuery}, but the score for each result will be the max score from the clauses (instead of the sum).
025 */
026public class MaxScoreOrQuery extends OrQuery
027{
028    private static final float __DEFAULT_TIE_BREAKER = 0.01f;
029    private float _tieBreaker;
030    
031    /**
032     * Build a MaxScoreOrQuery object with default tiebreaker.
033     * @param queries the queries.
034     */
035    public MaxScoreOrQuery(Query... queries)
036    {
037        this(__DEFAULT_TIE_BREAKER, queries);
038    }
039    
040    /**
041     * Build a MaxScoreOrQuery object with default tiebreaker.
042     * @param queries the queries as a Collection.
043     */
044    public MaxScoreOrQuery(Collection<Query> queries)
045    {
046        this(__DEFAULT_TIE_BREAKER, queries);
047    }
048    
049    /**
050     * Build a MaxScoreOrQuery object.
051     * @param tieBreaker The tiebreaker
052     * @param queries the queries.
053     */
054    public MaxScoreOrQuery(float tieBreaker, Query... queries)
055    {
056        super(queries);
057        _tieBreaker = tieBreaker;
058    }
059    
060    /**
061     * Build a MaxScoreOrQuery object.
062     * @param tieBreaker The tiebreaker
063     * @param queries the queries as a Collection.
064     */
065    public MaxScoreOrQuery(float tieBreaker, Collection<Query> queries)
066    {
067        super(queries);
068        _tieBreaker = tieBreaker;
069    }
070    
071    @Override
072    public String build() throws QuerySyntaxException
073    {
074        StringBuilder sb = new StringBuilder()
075                .append("{!maxscore tie=")
076                .append(_tieBreaker)
077                .append(" v=\"")
078                .append(ClientUtils.escapeQueryChars(super.build()))
079                .append("\"}");
080        return sb.toString();
081    }
082    
083    @Override
084    protected String _tagNameForToString()
085    {
086        return "OR(MAXSCORE)";
087    }
088
089    @Override
090    public int hashCode()
091    {
092        final int prime = 31;
093        int result = super.hashCode();
094        result = prime * result + Objects.hash(_tieBreaker);
095        return result;
096    }
097
098    @Override
099    public boolean equals(Object obj)
100    {
101        if (this == obj)
102        {
103            return true;
104        }
105        if (!super.equals(obj))
106        {
107            return false;
108        }
109        if (getClass() != obj.getClass())
110        {
111            return false;
112        }
113        MaxScoreOrQuery other = (MaxScoreOrQuery) obj;
114        return Float.floatToIntBits(_tieBreaker) == Float.floatToIntBits(other._tieBreaker);
115    }
116}
117