blob: 13087b5df22028fb066442f7688d55fa08537d72 [file] [log] [blame]
using Lucene.Net.Support;
using System.Collections;
using System.Collections.Generic;
using System.Text;
namespace Lucene.Net.Search.Spans
{
/*
* 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.
*/
using ToStringUtils = Lucene.Net.Util.ToStringUtils;
/// <summary>
/// Only return those matches that have a specific payload at
/// the given position.
/// </summary>
public class SpanNearPayloadCheckQuery : SpanPositionCheckQuery
{
protected readonly ICollection<byte[]> m_payloadToMatch;
private readonly IEqualityComparer payloadEqualityComparer;
/// <param name="match"> The underlying <see cref="SpanQuery"/> to check.</param>
/// <param name="payloadToMatch"> The <see cref="T:ICollection{byte[]}"/> of payloads to match.
/// IMPORTANT: If the type provided does not implement <see cref="IList{T}"/> (including arrays) or
/// <see cref="ISet{T}"/>, it should either implement <see cref="IStructuralEquatable"/> or override
/// <see cref="object.Equals(object)"/> and <see cref="object.GetHashCode()"/> with implementations
/// that compare the values of the byte arrays to ensure they are the same.</param>
public SpanNearPayloadCheckQuery(SpanNearQuery match, ICollection<byte[]> payloadToMatch)
: base(match)
{
this.m_payloadToMatch = payloadToMatch;
// LUCENENET specific: Need to use a structural equality comparer based on the type that is passed in.
if (payloadToMatch is ISet<byte[]>)
payloadEqualityComparer = J2N.Collections.Generic.SetEqualityComparer<byte[]>.Default;
else if (payloadToMatch is IList<byte[]>)
payloadEqualityComparer = J2N.Collections.Generic.ListEqualityComparer<byte[]>.Default;
else
payloadEqualityComparer = J2N.Collections.StructuralEqualityComparer.Default;
}
protected override AcceptStatus AcceptPosition(Spans spans)
{
bool result = spans.IsPayloadAvailable;
if (result == true)
{
var candidate = spans.GetPayload();
if (candidate.Count == m_payloadToMatch.Count)
{
//TODO: check the byte arrays are the same
//hmm, can't rely on order here
int matches = 0;
foreach (var candBytes in candidate)
{
//Unfortunately, we can't rely on order, so we need to compare all
foreach (var payBytes in m_payloadToMatch)
{
if (Arrays.Equals(candBytes, payBytes) == true)
{
matches++;
break;
}
}
}
if (matches == m_payloadToMatch.Count)
{
//we've verified all the bytes
return AcceptStatus.YES;
}
else
{
return AcceptStatus.NO;
}
}
else
{
return AcceptStatus.NO;
}
}
return AcceptStatus.NO;
}
public override string ToString(string field)
{
StringBuilder buffer = new StringBuilder();
buffer.Append("spanPayCheck(");
buffer.Append(m_match.ToString(field));
buffer.Append(", payloadRef: ");
foreach (var bytes in m_payloadToMatch)
{
ToStringUtils.ByteArray(buffer, bytes);
buffer.Append(';');
}
buffer.Append(")");
buffer.Append(ToStringUtils.Boost(Boost));
return buffer.ToString();
}
public override object Clone()
{
SpanNearPayloadCheckQuery result = new SpanNearPayloadCheckQuery((SpanNearQuery)m_match.Clone(), m_payloadToMatch);
result.Boost = Boost;
return result;
}
public override bool Equals(object o)
{
if (this == o)
{
return true;
}
if (!(o is SpanNearPayloadCheckQuery other))
{
return false;
}
// LUCENENET NOTE: Need to use the structural equality comparer to compare equality of all contained values
return payloadEqualityComparer.Equals(this.m_payloadToMatch, other.m_payloadToMatch)
&& this.m_match.Equals(other.m_match)
&& this.Boost == other.Boost;
}
public override int GetHashCode()
{
int h = m_match.GetHashCode();
h ^= (h << 8) | ((int)((uint)h >> 25)); // reversible
//TODO: is this right?
h ^= payloadEqualityComparer.GetHashCode(m_payloadToMatch); // LUCENENET NOTE: Need to use the structural equality comparer to compare equality of all contained values
h ^= J2N.BitConversion.SingleToRawInt32Bits(Boost);
return h;
}
}
}