/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
* or http://forgerock.org/license/CDDLv1.0.html.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at legal-notices/CDDLv1_0.txt.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information:
* Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
*
* Copyright 2006-2010 Sun Microsystems, Inc.
* Portions Copyright 2013-2014 Manuel Gaupp
*/
package org.opends.server.controls;
import org.opends.messages.Message;
import java.util.ArrayList;
import java.util.List;
import java.io.IOException;
import org.opends.server.api.ApproximateMatchingRule;
import org.opends.server.api.EqualityMatchingRule;
import org.opends.server.api.MatchingRule;
import org.opends.server.api.OrderingMatchingRule;
import org.opends.server.api.SubstringMatchingRule;
import org.opends.server.core.DirectoryServer;
import org.opends.server.protocols.asn1.*;
import org.opends.server.protocols.ldap.LDAPResultCode;
import org.opends.server.util.Validator;
import static org.opends.server.loggers.debug.DebugLogger.*;
import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.types.*;
import static org.opends.messages.ProtocolMessages.*;
import static org.opends.server.protocols.ldap.LDAPConstants.*;
import static org.opends.server.util.StaticUtils.*;
/**
* This class defines a filter that may be used in conjunction with the matched
* values control to indicate which particular values of a multivalued attribute
* should be returned. The matched values filter is essentially a subset of an
* LDAP search filter, lacking support for AND, OR, and NOT components, and
* lacking support for the dnAttributes component of extensible matching
* filters.
*/
public class MatchedValuesFilter
{
/**
* The tracer object for the debug logger.
*/
private static final DebugTracer TRACER = getTracer();
/**
* The BER type associated with the equalityMatch filter type.
*/
public static final byte EQUALITY_MATCH_TYPE = (byte) 0xA3;
/**
* The BER type associated with the substrings filter type.
*/
public static final byte SUBSTRINGS_TYPE = (byte) 0xA4;
/**
* The BER type associated with the greaterOrEqual filter type.
*/
public static final byte GREATER_OR_EQUAL_TYPE = (byte) 0xA5;
/**
* The BER type associated with the lessOrEqual filter type.
*/
public static final byte LESS_OR_EQUAL_TYPE = (byte) 0xA6;
/**
* The BER type associated with the present filter type.
*/
public static final byte PRESENT_TYPE = (byte) 0x87;
/**
* The BER type associated with the approxMatch filter type.
*/
public static final byte APPROXIMATE_MATCH_TYPE = (byte) 0xA8;
/**
* The BER type associated with the extensibleMatch filter type.
*/
public static final byte EXTENSIBLE_MATCH_TYPE = (byte) 0xA9;
// The approximate matching rule for this matched values filter.
private ApproximateMatchingRule approximateMatchingRule;
// The normalized subFinal value for this matched values filter.
private ByteString normalizedSubFinal;
// The normalized subInitial value for this matched values filter.
private ByteString normalizedSubInitial;
// The raw, unprocessed assertion value for this matched values filter.
private final ByteString rawAssertionValue;
// The subFinal value for this matched values filter.
private final ByteString subFinal;
// The subInitial value for this matched values filter.
private final ByteString subInitial;
// The processed attribute type for this matched values filter.
private AttributeType attributeType;
// The processed assertion value for this matched values filter.
private AttributeValue assertionValue;
// Indicates whether the elements of this matched values filter have been
// fully decoded.
private boolean decoded;
// The match type for this matched values filter.
private final byte matchType;
// The equality matching rule for this matched values filter.
private EqualityMatchingRule equalityMatchingRule;
// The set of normalized subAny values for this matched values filter.
private List<ByteString> normalizedSubAny;
// The set of subAny values for this matched values filter.
private final List<ByteString> subAny;
// The matching rule for this matched values filter.
private MatchingRule matchingRule;
// The ordering matching rule for this matched values filter.
private OrderingMatchingRule orderingMatchingRule;
// The matching rule ID for this matched values filter.
private final String matchingRuleID;
// The raw, unprocessed attribute type for this matched values filter.
private final String rawAttributeType;
// The substring matching rule for this matched values filter.
private SubstringMatchingRule substringMatchingRule;
/**
* Creates a new matched values filter with the provided information.
*
* @param matchType The match type for this matched values filter.
* @param rawAttributeType The raw, unprocessed attribute type.
* @param rawAssertionValue The raw, unprocessed assertion value.
* @param subInitial The subInitial element.
* @param subAny The set of subAny elements.
* @param subFinal The subFinal element.
* @param matchingRuleID The matching rule ID.
*/
private MatchedValuesFilter(byte matchType, String rawAttributeType,
ByteString rawAssertionValue,
ByteString subInitial, List<ByteString> subAny,
ByteString subFinal, String matchingRuleID)
{
this.matchType = matchType;
this.rawAttributeType = rawAttributeType;
this.rawAssertionValue = rawAssertionValue;
this.subInitial = subInitial;
this.subAny = subAny;
this.subFinal = subFinal;
this.matchingRuleID = matchingRuleID;
decoded = false;
attributeType = null;
assertionValue = null;
matchingRule = null;
normalizedSubInitial = null;
normalizedSubAny = null;
normalizedSubFinal = null;
approximateMatchingRule = null;
equalityMatchingRule = null;
orderingMatchingRule = null;
substringMatchingRule = null;
}
/**
* Creates a new equalityMatch filter with the provided information.
*
* @param rawAttributeType The raw, unprocessed attribute type.
* @param rawAssertionValue The raw, unprocessed assertion value.
*
* @return The created equalityMatch filter.
*/
public static MatchedValuesFilter createEqualityFilter(
String rawAttributeType,
ByteString rawAssertionValue)
{
Validator.ensureNotNull(rawAttributeType,rawAssertionValue);
return new MatchedValuesFilter(EQUALITY_MATCH_TYPE, rawAttributeType,
rawAssertionValue, null, null, null, null);
}
/**
* Creates a new equalityMatch filter with the provided information.
*
* @param attributeType The attribute type.
* @param assertionValue The assertion value.
*
* @return The created equalityMatch filter.
*/
public static MatchedValuesFilter createEqualityFilter(
AttributeType attributeType,
AttributeValue assertionValue)
{
Validator.ensureNotNull(attributeType, assertionValue);
String rawAttributeType = attributeType.getNameOrOID();
ByteString rawAssertionValue = assertionValue.getValue();
MatchedValuesFilter filter =
new MatchedValuesFilter(EQUALITY_MATCH_TYPE, rawAttributeType,
rawAssertionValue, null, null, null, null);
filter.attributeType = attributeType;
filter.assertionValue = assertionValue;
return filter;
}
/**
* Creates a new substrings filter with the provided information.
*
* @param rawAttributeType The raw, unprocessed attribute type.
* @param subInitial The subInitial element.
* @param subAny The set of subAny elements.
* @param subFinal The subFinal element.
*
* @return The created substrings filter.
*/
public static MatchedValuesFilter createSubstringsFilter(
String rawAttributeType,
ByteString subInitial,
List<ByteString> subAny,
ByteString subFinal)
{
Validator.ensureNotNull(rawAttributeType);
return new MatchedValuesFilter(SUBSTRINGS_TYPE, rawAttributeType, null,
subInitial, subAny, subFinal, null);
}
/**
* Creates a new substrings filter with the provided information.
*
* @param attributeType The raw, unprocessed attribute type.
* @param subInitial The subInitial element.
* @param subAny The set of subAny elements.
* @param subFinal The subFinal element.
*
* @return The created substrings filter.
*/
public static MatchedValuesFilter createSubstringsFilter(
AttributeType attributeType,
ByteString subInitial,
List<ByteString> subAny,
ByteString subFinal)
{
Validator.ensureNotNull(attributeType);
String rawAttributeType = attributeType.getNameOrOID();
MatchedValuesFilter filter =
new MatchedValuesFilter(SUBSTRINGS_TYPE, rawAttributeType, null,
subInitial, subAny, subFinal, null);
filter.attributeType = attributeType;
return filter;
}
/**
* Creates a new greaterOrEqual filter with the provided information.
*
* @param rawAttributeType The raw, unprocessed attribute type.
* @param rawAssertionValue The raw, unprocessed assertion value.
*
* @return The created greaterOrEqual filter.
*/
public static MatchedValuesFilter createGreaterOrEqualFilter(
String rawAttributeType,
ByteString rawAssertionValue)
{
Validator.ensureNotNull(rawAttributeType, rawAssertionValue);
return new MatchedValuesFilter(GREATER_OR_EQUAL_TYPE, rawAttributeType,
rawAssertionValue, null, null, null, null);
}
/**
* Creates a new greaterOrEqual filter with the provided information.
*
* @param attributeType The attribute type.
* @param assertionValue The assertion value.
*
* @return The created greaterOrEqual filter.
*/
public static MatchedValuesFilter createGreaterOrEqualFilter(
AttributeType attributeType,
AttributeValue assertionValue)
{
Validator.ensureNotNull(attributeType, assertionValue);
String rawAttributeType = attributeType.getNameOrOID();
ByteString rawAssertionValue = assertionValue.getValue();
MatchedValuesFilter filter =
new MatchedValuesFilter(GREATER_OR_EQUAL_TYPE, rawAttributeType,
rawAssertionValue, null, null, null, null);
filter.attributeType = attributeType;
filter.assertionValue = assertionValue;
return filter;
}
/**
* Creates a new lessOrEqual filter with the provided information.
*
* @param rawAttributeType The raw, unprocessed attribute type.
* @param rawAssertionValue The raw, unprocessed assertion value.
*
* @return The created lessOrEqual filter.
*/
public static MatchedValuesFilter createLessOrEqualFilter(
String rawAttributeType,
ByteString rawAssertionValue)
{
Validator.ensureNotNull(rawAttributeType, rawAssertionValue);
return new MatchedValuesFilter(LESS_OR_EQUAL_TYPE, rawAttributeType,
rawAssertionValue, null, null, null, null);
}
/**
* Creates a new lessOrEqual filter with the provided information.
*
* @param attributeType The attribute type.
* @param assertionValue The assertion value.
*
* @return The created lessOrEqual filter.
*/
public static MatchedValuesFilter createLessOrEqualFilter(
AttributeType attributeType,
AttributeValue assertionValue)
{
Validator.ensureNotNull(attributeType, assertionValue);
String rawAttributeType = attributeType.getNameOrOID();
ByteString rawAssertionValue = assertionValue.getValue();
MatchedValuesFilter filter =
new MatchedValuesFilter(LESS_OR_EQUAL_TYPE, rawAttributeType,
rawAssertionValue, null, null, null, null);
filter.attributeType = attributeType;
filter.assertionValue = assertionValue;
return filter;
}
/**
* Creates a new present filter with the provided information.
*
* @param rawAttributeType The raw, unprocessed attribute type.
*
* @return The created present filter.
*/
public static MatchedValuesFilter createPresentFilter(String rawAttributeType)
{
Validator.ensureNotNull(rawAttributeType) ;
return new MatchedValuesFilter(PRESENT_TYPE, rawAttributeType, null, null,
null, null, null);
}
/**
* Creates a new present filter with the provided information.
*
* @param attributeType The attribute type.
*
* @return The created present filter.
*/
public static MatchedValuesFilter createPresentFilter(
AttributeType attributeType)
{
Validator.ensureNotNull(attributeType);
String rawAttributeType = attributeType.getNameOrOID();
MatchedValuesFilter filter =
new MatchedValuesFilter(PRESENT_TYPE, rawAttributeType, null, null,
null, null, null);
filter.attributeType = attributeType;
return filter;
}
/**
* Creates a new approxMatch filter with the provided information.
*
* @param rawAttributeType The raw, unprocessed attribute type.
* @param rawAssertionValue The raw, unprocessed assertion value.
*
* @return The created approxMatch filter.
*/
public static MatchedValuesFilter createApproximateFilter(
String rawAttributeType,
ByteString rawAssertionValue)
{
Validator.ensureNotNull(rawAttributeType,rawAssertionValue);
return new MatchedValuesFilter(APPROXIMATE_MATCH_TYPE, rawAttributeType,
rawAssertionValue, null, null, null, null);
}
/**
* Creates a new approxMatch filter with the provided information.
*
* @param attributeType The attribute type.
* @param assertionValue The assertion value.
*
* @return The created approxMatch filter.
*/
public static MatchedValuesFilter createApproximateFilter(
AttributeType attributeType,
AttributeValue assertionValue)
{
Validator.ensureNotNull(attributeType,assertionValue);
String rawAttributeType = attributeType.getNameOrOID();
ByteString rawAssertionValue = assertionValue.getValue();
MatchedValuesFilter filter =
new MatchedValuesFilter(APPROXIMATE_MATCH_TYPE, rawAttributeType,
rawAssertionValue, null, null, null, null);
filter.attributeType = attributeType;
filter.assertionValue = assertionValue;
return filter;
}
/**
* Creates a new extensibleMatch filter with the provided information.
*
* @param rawAttributeType The raw, unprocessed attribute type.
* @param matchingRuleID The matching rule ID.
* @param rawAssertionValue The raw, unprocessed assertion value.
*
* @return The created extensibleMatch filter.
*/
public static MatchedValuesFilter createExtensibleMatchFilter(
String rawAttributeType,
String matchingRuleID,
ByteString rawAssertionValue)
{
Validator
.ensureNotNull(rawAttributeType, matchingRuleID, rawAssertionValue);
return new MatchedValuesFilter(EXTENSIBLE_MATCH_TYPE, rawAttributeType,
rawAssertionValue, null, null, null,
matchingRuleID);
}
/**
* Creates a new extensibleMatch filter with the provided information.
*
* @param attributeType The attribute type.
* @param matchingRule The matching rule.
* @param assertionValue The assertion value.
*
* @return The created extensibleMatch filter.
*/
public static MatchedValuesFilter createExtensibleMatchFilter(
AttributeType attributeType,
MatchingRule matchingRule,
AttributeValue assertionValue)
{
Validator.ensureNotNull(attributeType, matchingRule, assertionValue);
String rawAttributeType = attributeType.getNameOrOID();
String matchingRuleID = matchingRule.getOID();
ByteString rawAssertionValue = assertionValue.getValue();
MatchedValuesFilter filter =
new MatchedValuesFilter(EXTENSIBLE_MATCH_TYPE, rawAttributeType,
rawAssertionValue, null, null, null,
matchingRuleID);
filter.attributeType = attributeType;
filter.assertionValue = assertionValue;
filter.matchingRule = matchingRule;
return filter;
}
/**
* Creates a new matched values filter from the provided LDAP filter.
*
* @param filter The LDAP filter to use for this matched values filter.
*
* @return The corresponding matched values filter.
*
* @throws LDAPException If the provided LDAP filter cannot be treated as a
* matched values filter.
*/
public static MatchedValuesFilter createFromLDAPFilter(RawFilter filter)
throws LDAPException
{
switch (filter.getFilterType())
{
case AND:
case OR:
case NOT:
// These filter types cannot be used in a matched values filter.
Message message = ERR_MVFILTER_INVALID_LDAP_FILTER_TYPE.get(
String.valueOf(filter), String.valueOf(filter.getFilterType()));
throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message);
case EQUALITY:
return new MatchedValuesFilter(EQUALITY_MATCH_TYPE,
filter.getAttributeType(),
filter.getAssertionValue(), null, null,
null, null);
case SUBSTRING:
return new MatchedValuesFilter(SUBSTRINGS_TYPE,
filter.getAttributeType(), null,
filter.getSubInitialElement(),
filter.getSubAnyElements(),
filter.getSubFinalElement(), null);
case GREATER_OR_EQUAL:
return new MatchedValuesFilter(GREATER_OR_EQUAL_TYPE,
filter.getAttributeType(),
filter.getAssertionValue(), null, null,
null, null);
case LESS_OR_EQUAL:
return new MatchedValuesFilter(LESS_OR_EQUAL_TYPE,
filter.getAttributeType(),
filter.getAssertionValue(), null, null,
null, null);
case PRESENT:
return new MatchedValuesFilter(PRESENT_TYPE, filter.getAttributeType(),
null, null, null, null, null);
case APPROXIMATE_MATCH:
return new MatchedValuesFilter(APPROXIMATE_MATCH_TYPE,
filter.getAttributeType(),
filter.getAssertionValue(), null, null,
null, null);
case EXTENSIBLE_MATCH:
if (filter.getDNAttributes())
{
// This cannot be represented in a matched values filter.
message = ERR_MVFILTER_INVALID_DN_ATTRIBUTES_FLAG.get(
String.valueOf(filter));
throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message);
}
else
{
return new MatchedValuesFilter(EXTENSIBLE_MATCH_TYPE,
filter.getAttributeType(),
filter.getAssertionValue(), null, null,
null, filter.getMatchingRuleID());
}
default:
message = ERR_MVFILTER_INVALID_LDAP_FILTER_TYPE.get(
String.valueOf(filter), String.valueOf(filter.getFilterType()));
throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message);
}
}
/**
* Encodes this matched values filter as an ASN.1 element.
*
* @param writer The ASN1Writer to use to encode this matched values filter.
* @throws IOException if an error occurs while encoding.
*/
public void encode(ASN1Writer writer) throws IOException
{
switch (matchType)
{
case EQUALITY_MATCH_TYPE:
case GREATER_OR_EQUAL_TYPE:
case LESS_OR_EQUAL_TYPE:
case APPROXIMATE_MATCH_TYPE:
// These will all be encoded in the same way.
writer.writeStartSequence(matchType);
writer.writeOctetString(rawAttributeType);
writer.writeOctetString(rawAssertionValue);
writer.writeEndSequence();
return;
case SUBSTRINGS_TYPE:
writer.writeStartSequence(matchType);
writer.writeOctetString(rawAttributeType);
writer.writeStartSequence();
if (subInitial != null)
{
writer.writeOctetString(TYPE_SUBINITIAL, subInitial);
}
if (subAny != null)
{
for (ByteString s : subAny)
{
writer.writeOctetString(TYPE_SUBANY, s);
}
}
if (subFinal != null)
{
writer.writeOctetString(TYPE_SUBFINAL, subFinal);
}
writer.writeEndSequence();
writer.writeEndSequence();
return;
case PRESENT_TYPE:
writer.writeOctetString(matchType, rawAttributeType);
return;
case EXTENSIBLE_MATCH_TYPE:
writer.writeStartSequence(matchType);
if (matchingRuleID != null)
{
writer.writeOctetString(TYPE_MATCHING_RULE_ID, matchingRuleID);
}
if (rawAttributeType != null)
{
writer.writeOctetString(TYPE_MATCHING_RULE_TYPE, rawAttributeType);
}
writer.writeOctetString(TYPE_MATCHING_RULE_VALUE, rawAssertionValue);
writer.writeEndSequence();
return;
default:
}
}
/**
* Decodes the provided ASN.1 element as a matched values filter item.
*
* @param reader The ASN.1 reader.
*
* @return The decoded matched values filter.
*
* @throws LDAPException If a problem occurs while attempting to decode the
* filter item.
*/
public static MatchedValuesFilter decode(ASN1Reader reader)
throws LDAPException
{
byte type;
try
{
type = reader.peekType();
}
catch(Exception e)
{
// TODO: Need a better message.
Message message =
ERR_MVFILTER_INVALID_ELEMENT_TYPE.get(e.toString());
throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message);
}
switch (type)
{
case EQUALITY_MATCH_TYPE:
case GREATER_OR_EQUAL_TYPE:
case LESS_OR_EQUAL_TYPE:
case APPROXIMATE_MATCH_TYPE:
// These will all be decoded in the same manner. The element must be a
// sequence consisting of the attribute type and assertion value.
try
{
reader.readStartSequence();
String rawAttributeType = reader.readOctetStringAsString();
ByteString rawAssertionValue = reader.readOctetString();
reader.readEndSequence();
return new MatchedValuesFilter(type, rawAttributeType,
rawAssertionValue, null, null, null, null);
}
catch (Exception e)
{
if (debugEnabled())
{
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
Message message =
ERR_MVFILTER_CANNOT_DECODE_AVA.get(getExceptionMessage(e));
throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message,
e);
}
case SUBSTRINGS_TYPE:
// This must be a sequence of two elements, where the second is a
// sequence of substring types.
try
{
reader.readStartSequence();
String rawAttributeType = reader.readOctetStringAsString();
reader.readStartSequence();
if(!reader.hasNextElement())
{
Message message = ERR_MVFILTER_NO_SUBSTRING_ELEMENTS.get();
throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message);
}
ByteString subInitial = null;
ArrayList<ByteString> subAny = null;
ByteString subFinal = null;
if(reader.hasNextElement() &&
reader.peekType() == TYPE_SUBINITIAL)
{
subInitial = reader.readOctetString();
}
while(reader.hasNextElement() &&
reader.peekType() == TYPE_SUBANY)
{
if(subAny == null)
{
subAny = new ArrayList<ByteString>();
}
subAny.add(reader.readOctetString());
}
if(reader.hasNextElement() &&
reader.peekType() == TYPE_SUBFINAL)
{
subFinal = reader.readOctetString();
}
reader.readEndSequence();
reader.readEndSequence();
return new MatchedValuesFilter(type, rawAttributeType,
null, subInitial, subAny, subFinal,
null);
}
catch (LDAPException le)
{
throw le;
}
catch (Exception e)
{
if (debugEnabled())
{
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
Message message =
ERR_MVFILTER_CANNOT_DECODE_SUBSTRINGS.get(getExceptionMessage(e));
throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message,
e);
}
case PRESENT_TYPE:
// The element must be an ASN.1 octet string holding the attribute type.
try
{
String rawAttributeType = reader.readOctetStringAsString();
return new MatchedValuesFilter(type, rawAttributeType,
null, null, null, null, null);
}
catch (Exception e)
{
if (debugEnabled())
{
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
Message message = ERR_MVFILTER_CANNOT_DECODE_PRESENT_TYPE.get(
getExceptionMessage(e));
throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message,
e);
}
case EXTENSIBLE_MATCH_TYPE:
// This must be a two or three element sequence with an assertion value
// as the last element and an attribute type and/or matching rule ID as
// the first element(s).
try
{
reader.readStartSequence();
String rawAttributeType = null;
String matchingRuleID = null;
ByteString rawAssertionValue;
if(reader.peekType() == TYPE_MATCHING_RULE_ID)
{
matchingRuleID = reader.readOctetStringAsString();
}
if(matchingRuleID == null ||
reader.peekType() == TYPE_MATCHING_RULE_TYPE)
{
rawAttributeType = reader.readOctetStringAsString();
}
rawAssertionValue = reader.readOctetString();
reader.readEndSequence();
return new MatchedValuesFilter(type, rawAttributeType,
rawAssertionValue, null, null, null,
matchingRuleID);
}
catch (Exception e)
{
if (debugEnabled())
{
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
Message message = ERR_MVFILTER_CANNOT_DECODE_EXTENSIBLE_MATCH.get(
getExceptionMessage(e));
throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message,
e);
}
default:
Message message =
ERR_MVFILTER_INVALID_ELEMENT_TYPE.get(byteToHex(type));
throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message);
}
}
/**
* Retrieves the match type for this matched values filter.
*
* @return The match type for this matched values filter.
*/
public byte getMatchType()
{
return matchType;
}
/**
* Retrieves the raw, unprocessed attribute type for this matched values
* filter.
*
* @return The raw, unprocessed attribute type for this matched values
* filter, or <CODE>null</CODE> if there is none.
*/
public String getRawAttributeType()
{
return rawAttributeType;
}
/**
* Retrieves the attribute type for this matched values filter.
*
* @return The attribute type for this matched values filter, or
* <CODE>null</CODE> if there is none.
*/
public AttributeType getAttributeType()
{
if (attributeType == null)
{
if (rawAttributeType != null)
{
attributeType =
DirectoryServer.getAttributeType(toLowerCase(rawAttributeType));
if (attributeType == null)
{
attributeType =
DirectoryServer.getDefaultAttributeType(rawAttributeType);
}
}
}
return attributeType;
}
/**
* Retrieves the raw, unprocessed assertion value for this matched values
* filter.
*
* @return The raw, unprocessed assertion value for this matched values
* filter, or <CODE>null</CODE> if there is none.
*/
public ByteString getRawAssertionValue()
{
return rawAssertionValue;
}
/**
* Retrieves the assertion value for this matched values filter.
*
* @return The assertion value for this matched values filter, or
* <CODE>null</CODE> if there is none.
*/
public AttributeValue getAssertionValue()
{
if (assertionValue == null)
{
if (rawAssertionValue != null)
{
assertionValue = AttributeValues.create(
getAttributeType(), rawAssertionValue);
}
}
return assertionValue;
}
/**
* Retrieves the subInitial element for this matched values filter.
*
* @return The subInitial element for this matched values filter, or
* <CODE>null</CODE> if there is none.
*/
public ByteString getSubInitialElement()
{
return subInitial;
}
/**
* Retrieves the normalized form of the subInitial element.
*
* @return The normalized form of the subInitial element, or
* <CODE>null</CODE> if there is none.
*/
public ByteString getNormalizedSubInitialElement()
{
if (normalizedSubInitial == null)
{
if ((subInitial != null) && (getSubstringMatchingRule() != null))
{
try
{
normalizedSubInitial =
getSubstringMatchingRule().normalizeSubstring(subInitial);
}
catch (Exception e)
{
if (debugEnabled())
{
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
}
}
}
return normalizedSubInitial;
}
/**
* Retrieves the set of subAny elements for this matched values filter.
*
* @return The set of subAny elements for this matched values filter. If
* there are none, then the return value may be either
* <CODE>null</CODE> or an empty list.
*/
public List<ByteString> getSubAnyElements()
{
return subAny;
}
/**
* Retrieves the set of normalized subAny elements for this matched values
* filter.
*
* @return The set of subAny elements for this matched values filter. If
* there are none, then an empty list will be returned. If a
* problem occurs while attempting to perform the normalization, then
* <CODE>null</CODE> will be returned.
*/
public List<ByteString> getNormalizedSubAnyElements()
{
if (normalizedSubAny == null)
{
if ((subAny == null) || (subAny.isEmpty()))
{
normalizedSubAny = new ArrayList<ByteString>(0);
}
else
{
if (getSubstringMatchingRule() == null)
{
return null;
}
normalizedSubAny = new ArrayList<ByteString>();
try
{
for (ByteString s : subAny)
{
normalizedSubAny.add(
substringMatchingRule.normalizeSubstring(s));
}
}
catch (Exception e)
{
if (debugEnabled())
{
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
normalizedSubAny = null;
}
}
}
return normalizedSubAny;
}
/**
* Retrieves the subFinal element for this matched values filter.
*
* @return The subFinal element for this matched values filter, or
* <CODE>null</CODE> if there is none.
*/
public ByteString getSubFinalElement()
{
return subFinal;
}
/**
* Retrieves the normalized form of the subFinal element.
*
* @return The normalized form of the subFinal element, or <CODE>null</CODE>
* if there is none.
*/
public ByteString getNormalizedSubFinalElement()
{
if (normalizedSubFinal == null)
{
if ((subFinal != null) && (getSubstringMatchingRule() != null))
{
try
{
normalizedSubFinal =
getSubstringMatchingRule().normalizeSubstring(subFinal);
}
catch (Exception e)
{
if (debugEnabled())
{
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
}
}
}
return normalizedSubFinal;
}
/**
* Retrieves the matching rule ID for this matched values filter.
*
* @return The matching rule ID for this matched values filter, or
* <CODE>null</CODE> if there is none.
*/
public String getMatchingRuleID()
{
return matchingRuleID;
}
/**
* Retrieves the matching rule for this matched values filter.
*
* @return The matching rule for this matched values filter, or
* <CODE>null</CODE> if there is none.
*/
public MatchingRule getMatchingRule()
{
if (matchingRule == null)
{
if (matchingRuleID != null)
{
matchingRule =
DirectoryServer.getMatchingRule(toLowerCase(matchingRuleID));
}
}
return matchingRule;
}
/**
* Retrieves the approximate matching rule that should be used for this
* matched values filter.
*
* @return The approximate matching rule that should be used for this matched
* values filter, or <CODE>null</CODE> if there is none.
*/
public ApproximateMatchingRule getApproximateMatchingRule()
{
if (approximateMatchingRule == null)
{
AttributeType attrType = getAttributeType();
if (attrType != null)
{
approximateMatchingRule = attrType.getApproximateMatchingRule();
}
}
return approximateMatchingRule;
}
/**
* Retrieves the equality matching rule that should be used for this matched
* values filter.
*
* @return The equality matching rule that should be used for this matched
* values filter, or <CODE>null</CODE> if there is none.
*/
public EqualityMatchingRule getEqualityMatchingRule()
{
if (equalityMatchingRule == null)
{
AttributeType attrType = getAttributeType();
if (attrType != null)
{
equalityMatchingRule = attrType.getEqualityMatchingRule();
}
}
return equalityMatchingRule;
}
/**
* Retrieves the ordering matching rule that should be used for this matched
* values filter.
*
* @return The ordering matching rule that should be used for this matched
* values filter, or <CODE>null</CODE> if there is none.
*/
public OrderingMatchingRule getOrderingMatchingRule()
{
if (orderingMatchingRule == null)
{
AttributeType attrType = getAttributeType();
if (attrType != null)
{
orderingMatchingRule = attrType.getOrderingMatchingRule();
}
}
return orderingMatchingRule;
}
/**
* Retrieves the substring matching rule that should be used for this matched
* values filter.
*
* @return The substring matching rule that should be used for this matched
* values filter, or <CODE>null</CODE> if there is none.
*/
public SubstringMatchingRule getSubstringMatchingRule()
{
if (substringMatchingRule == null)
{
AttributeType attrType = getAttributeType();
if (attrType != null)
{
substringMatchingRule = attrType.getSubstringMatchingRule();
}
}
return substringMatchingRule;
}
/**
* Decodes all components of the matched values filter so that they can be
* referenced as member variables.
*/
private void fullyDecode()
{
if (! decoded)
{
getAttributeType();
getAssertionValue();
getNormalizedSubInitialElement();
getNormalizedSubAnyElements();
getNormalizedSubFinalElement();
getMatchingRule();
getApproximateMatchingRule();
getEqualityMatchingRule();
getOrderingMatchingRule();
getSubstringMatchingRule();
decoded = true;
}
}
/**
* Indicates whether the specified attribute value matches the criteria
* defined in this matched values filter.
*
* @param type The attribute type with which the provided value is
* associated.
* @param value The attribute value for which to make the determination.
*
* @return <CODE>true</CODE> if the specified attribute value matches the
* criteria defined in this matched values filter, or
* <CODE>false</CODE> if not.
*/
public boolean valueMatches(AttributeType type, AttributeValue value)
{
fullyDecode();
switch (matchType)
{
case EQUALITY_MATCH_TYPE:
if ((attributeType != null) && (type != null) &&
attributeType.equals(type) && (rawAssertionValue != null) &&
(value != null) && (equalityMatchingRule != null))
{
try
{
return equalityMatchingRule.areEqual(
equalityMatchingRule.normalizeAssertionValue(rawAssertionValue),
value.getNormalizedValue());
}
catch (Exception e)
{
if (debugEnabled())
{
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
return false;
}
}
else
{
return false;
}
case SUBSTRINGS_TYPE:
if ((attributeType != null) && (type != null) &&
attributeType.equals(type) && (substringMatchingRule != null))
{
try
{
ArrayList<ByteSequence> normalizedSubAnyBS =
new ArrayList<ByteSequence>(normalizedSubAny);
return substringMatchingRule.valueMatchesSubstring(
substringMatchingRule.normalizeValue(value.getValue()),
normalizedSubInitial,
normalizedSubAnyBS, normalizedSubFinal);
}
catch (Exception e)
{
if (debugEnabled())
{
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
return false;
}
}
else
{
return false;
}
case GREATER_OR_EQUAL_TYPE:
if ((attributeType != null) && (type != null) &&
attributeType.equals(type) && (assertionValue != null) &&
(value != null) && (orderingMatchingRule != null))
{
try
{
return (orderingMatchingRule.compareValues(
assertionValue.getNormalizedValue(),
orderingMatchingRule.normalizeValue(
value.getValue())) >= 0);
}
catch (Exception e)
{
if (debugEnabled())
{
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
return false;
}
}
else
{
return false;
}
case LESS_OR_EQUAL_TYPE:
if ((attributeType != null) && (type != null) &&
attributeType.equals(type) && (assertionValue != null) &&
(value != null) && (orderingMatchingRule != null))
{
try
{
return (orderingMatchingRule.compareValues(
assertionValue.getNormalizedValue(),
orderingMatchingRule.normalizeValue(
value.getValue())) <= 0);
}
catch (Exception e)
{
if (debugEnabled())
{
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
return false;
}
}
else
{
return false;
}
case PRESENT_TYPE:
return ((attributeType != null) && (type != null) &&
attributeType.equals(type));
case APPROXIMATE_MATCH_TYPE:
if ((attributeType != null) && (type != null) &&
attributeType.equals(type) && (assertionValue != null) &&
(value != null) && (approximateMatchingRule != null))
{
try
{
ByteString nv1 = approximateMatchingRule.normalizeValue(
assertionValue.getNormalizedValue());
ByteString nv2 = approximateMatchingRule.normalizeValue(
approximateMatchingRule.normalizeValue(value.getValue()));
return approximateMatchingRule.approximatelyMatch(nv1, nv2);
}
catch (Exception e)
{
if (debugEnabled())
{
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
return false;
}
}
else
{
return false;
}
case EXTENSIBLE_MATCH_TYPE:
if ((assertionValue == null) || (value == null))
{
return false;
}
if (attributeType == null)
{
if (matchingRule == null)
{
return false;
}
try
{
ByteString nv1 =
matchingRule.normalizeValue(value.getValue());
ByteString nv2 =
matchingRule.normalizeValue(assertionValue.getValue());
return (matchingRule.valuesMatch(nv1, nv2) == ConditionResult.TRUE);
}
catch (Exception e)
{
if (debugEnabled())
{
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
return false;
}
}
else
{
if ((! attributeType.equals(type)) || (equalityMatchingRule == null))
{
return false;
}
try
{
return equalityMatchingRule.areEqual(
equalityMatchingRule.normalizeAssertionValue(rawAssertionValue),
value.getNormalizedValue());
}
catch (Exception e)
{
if (debugEnabled())
{
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
return false;
}
}
default:
return false;
}
}
/**
* Retrieves a string representation of this matched values filter, as an RFC
* 2254-compliant filter string.
*
* @return A string representation of this matched values filter.
*/
@Override
public String toString()
{
StringBuilder buffer = new StringBuilder();
toString(buffer);
return buffer.toString();
}
/**
* Appends a string representation of this matched values filter, as an RFC
* 2254-compliant filter string, to the provided buffer.
*
* @param buffer The buffer to which the filter string should be appended.
*/
public void toString(StringBuilder buffer)
{
switch (matchType)
{
case EQUALITY_MATCH_TYPE:
buffer.append("(");
buffer.append(rawAttributeType);
buffer.append("=");
RawFilter.valueToFilterString(buffer, rawAssertionValue);
buffer.append(")");
break;
case SUBSTRINGS_TYPE:
buffer.append("(");
buffer.append(rawAttributeType);
buffer.append("=");
if (subInitial != null)
{
RawFilter.valueToFilterString(buffer, subInitial);
}
if (subAny != null)
{
for (ByteString s : subAny)
{
buffer.append("*");
RawFilter.valueToFilterString(buffer, s);
}
}
buffer.append("*");
if (subFinal != null)
{
RawFilter.valueToFilterString(buffer, subFinal);
}
buffer.append(")");
break;
case GREATER_OR_EQUAL_TYPE:
buffer.append("(");
buffer.append(rawAttributeType);
buffer.append(">=");
RawFilter.valueToFilterString(buffer, rawAssertionValue);
buffer.append(")");
break;
case LESS_OR_EQUAL_TYPE:
buffer.append("(");
buffer.append(rawAttributeType);
buffer.append("<=");
RawFilter.valueToFilterString(buffer, rawAssertionValue);
buffer.append(")");
break;
case PRESENT_TYPE:
buffer.append("(");
buffer.append(rawAttributeType);
buffer.append("=*)");
break;
case APPROXIMATE_MATCH_TYPE:
buffer.append("(");
buffer.append(rawAttributeType);
buffer.append("~=");
RawFilter.valueToFilterString(buffer, rawAssertionValue);
buffer.append(")");
break;
case EXTENSIBLE_MATCH_TYPE:
buffer.append("(");
if (rawAttributeType != null)
{
buffer.append(rawAttributeType);
}
if (matchingRuleID != null)
{
buffer.append(":");
buffer.append(matchingRuleID);
}
buffer.append(":=");
RawFilter.valueToFilterString(buffer, rawAssertionValue);
buffer.append(")");
break;
}
}
}