/*
* Copyright 2008-2013 UnboundID Corp.
* All Rights Reserved.
*/
/*
* Copyright (C) 2008-2013 UnboundID Corp.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License (GPLv2 only)
* or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses>.
*/
package com.hwlcn.ldap.ldap.sdk.controls;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import com.hwlcn.ldap.asn1.ASN1Element;
import com.hwlcn.ldap.asn1.ASN1OctetString;
import com.hwlcn.ldap.asn1.ASN1Sequence;
import com.hwlcn.ldap.ldap.sdk.Filter;
import com.hwlcn.ldap.ldap.sdk.LDAPException;
import com.hwlcn.ldap.ldap.sdk.ResultCode;
import com.hwlcn.core.annotation.NotMutable;
import com.hwlcn.core.annotation.ThreadSafety;
import com.hwlcn.ldap.util.ThreadSafetyLevel;
import static com.hwlcn.ldap.ldap.sdk.controls.ControlMessages.*;
import static com.hwlcn.ldap.util.Debug.*;
import static com.hwlcn.ldap.util.StaticUtils.*;
import static com.hwlcn.ldap.util.Validator.*;
/**
* This class provides an implementation of the simple filter item for use with
* the {@link MatchedValuesRequestControl} as defined in
* <A HREF="http://www.ietf.org/rfc/rfc3876.txt">RFC 3876</A>. It is similar to
* a search filter (see the {@link com.hwlcn.ldap.ldap.sdk.Filter} class), but
* may only contain a single element (i.e., no AND, OR, or NOT components are
* allowed), and extensible matching does not allow the use of the dnAttributes
* field.
*/
@NotMutable()
@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
public final class MatchedValuesFilter
implements Serializable
{
public static final byte MATCH_TYPE_EQUALITY = (byte) 0xA3;
public static final byte MATCH_TYPE_SUBSTRINGS = (byte) 0xA4;
public static final byte MATCH_TYPE_GREATER_OR_EQUAL = (byte) 0xA5;
public static final byte MATCH_TYPE_LESS_OR_EQUAL = (byte) 0xA6;
public static final byte MATCH_TYPE_PRESENT = (byte) 0x87;
public static final byte MATCH_TYPE_APPROXIMATE = (byte) 0xA8;
public static final byte MATCH_TYPE_EXTENSIBLE = (byte) 0xA9;
private static final byte SUBSTRING_TYPE_SUBINITIAL = (byte) 0x80;
private static final byte SUBSTRING_TYPE_SUBANY = (byte) 0x81;
private static final byte SUBSTRING_TYPE_SUBFINAL = (byte) 0x82;
private static final byte EXTENSIBLE_TYPE_MATCHING_RULE_ID = (byte) 0x81;
private static final byte EXTENSIBLE_TYPE_ATTRIBUTE_NAME = (byte) 0x82;
private static final byte EXTENSIBLE_TYPE_MATCH_VALUE = (byte) 0x83;
private static final ASN1OctetString[] NO_SUB_ANY = new ASN1OctetString[0];
private static final String[] NO_SUB_ANY_STRINGS = NO_STRINGS;
private static final byte[][] NO_SUB_ANY_BYTES = new byte[0][];
private static final long serialVersionUID = 8144732301100674661L;
private final ASN1OctetString assertionValue;
private final ASN1OctetString subFinalValue;
private final ASN1OctetString subInitialValue;
private final ASN1OctetString[] subAnyValues;
private final byte matchType;
private final String attributeType;
private final String matchingRuleID;
private MatchedValuesFilter(final byte matchType, final String attributeType,
final ASN1OctetString assertionValue,
final ASN1OctetString subInitialValue,
final ASN1OctetString[] subAnyValues,
final ASN1OctetString subFinalValue,
final String matchingRuleID)
{
this.matchType = matchType;
this.attributeType = attributeType;
this.assertionValue = assertionValue;
this.subInitialValue = subInitialValue;
this.subAnyValues = subAnyValues;
this.subFinalValue = subFinalValue;
this.matchingRuleID = matchingRuleID;
}
public static MatchedValuesFilter createEqualityFilter(
final String attributeType,
final String assertionValue)
{
ensureNotNull(attributeType, assertionValue);
return new MatchedValuesFilter(MATCH_TYPE_EQUALITY, attributeType,
new ASN1OctetString(assertionValue), null,
NO_SUB_ANY, null, null);
}
public static MatchedValuesFilter createEqualityFilter(
final String attributeType,
final byte[] assertionValue)
{
ensureNotNull(attributeType, assertionValue);
return new MatchedValuesFilter(MATCH_TYPE_EQUALITY, attributeType,
new ASN1OctetString(assertionValue), null,
NO_SUB_ANY, null, null);
}
public static MatchedValuesFilter createSubstringFilter(
final String attributeType,
final String subInitialValue,
final String[] subAnyValues,
final String subFinalValue)
{
ensureNotNull(attributeType);
ensureTrue((subInitialValue != null) ||
((subAnyValues != null) && (subAnyValues.length > 0)) ||
(subFinalValue != null));
final ASN1OctetString subInitialOS;
if (subInitialValue == null)
{
subInitialOS = null;
}
else
{
subInitialOS = new ASN1OctetString(SUBSTRING_TYPE_SUBINITIAL,
subInitialValue);
}
final ASN1OctetString[] subAnyOS;
if ((subAnyValues == null) || (subAnyValues.length == 0))
{
subAnyOS = NO_SUB_ANY;
}
else
{
subAnyOS = new ASN1OctetString[subAnyValues.length];
for (int i=0; i < subAnyValues.length; i++)
{
subAnyOS[i] = new ASN1OctetString(SUBSTRING_TYPE_SUBANY,
subAnyValues[i]);
}
}
final ASN1OctetString subFinalOS;
if (subFinalValue == null)
{
subFinalOS = null;
}
else
{
subFinalOS = new ASN1OctetString(SUBSTRING_TYPE_SUBFINAL, subFinalValue);
}
return new MatchedValuesFilter(MATCH_TYPE_SUBSTRINGS, attributeType, null,
subInitialOS, subAnyOS, subFinalOS, null);
}
public static MatchedValuesFilter createSubstringFilter(
final String attributeType,
final byte[] subInitialValue,
final byte[][] subAnyValues,
final byte[] subFinalValue)
{
ensureNotNull(attributeType);
ensureTrue((subInitialValue != null) ||
((subAnyValues != null) && (subAnyValues.length > 0)) ||
(subFinalValue != null));
final ASN1OctetString subInitialOS;
if (subInitialValue == null)
{
subInitialOS = null;
}
else
{
subInitialOS = new ASN1OctetString(SUBSTRING_TYPE_SUBINITIAL,
subInitialValue);
}
final ASN1OctetString[] subAnyOS;
if ((subAnyValues == null) || (subAnyValues.length == 0))
{
subAnyOS = NO_SUB_ANY;
}
else
{
subAnyOS = new ASN1OctetString[subAnyValues.length];
for (int i=0; i < subAnyValues.length; i++)
{
subAnyOS[i] = new ASN1OctetString(SUBSTRING_TYPE_SUBANY,
subAnyValues[i]);
}
}
final ASN1OctetString subFinalOS;
if (subFinalValue == null)
{
subFinalOS = null;
}
else
{
subFinalOS = new ASN1OctetString(SUBSTRING_TYPE_SUBFINAL, subFinalValue);
}
return new MatchedValuesFilter(MATCH_TYPE_SUBSTRINGS, attributeType, null,
subInitialOS, subAnyOS, subFinalOS, null);
}
public static MatchedValuesFilter createGreaterOrEqualFilter(
final String attributeType,
final String assertionValue)
{
ensureNotNull(attributeType, assertionValue);
return new MatchedValuesFilter(MATCH_TYPE_GREATER_OR_EQUAL, attributeType,
new ASN1OctetString(assertionValue), null,
NO_SUB_ANY, null, null);
}
public static MatchedValuesFilter createGreaterOrEqualFilter(
final String attributeType,
final byte[] assertionValue)
{
ensureNotNull(attributeType, assertionValue);
return new MatchedValuesFilter(MATCH_TYPE_GREATER_OR_EQUAL, attributeType,
new ASN1OctetString(assertionValue), null,
NO_SUB_ANY, null, null);
}
public static MatchedValuesFilter createLessOrEqualFilter(
final String attributeType,
final String assertionValue)
{
ensureNotNull(attributeType, assertionValue);
return new MatchedValuesFilter(MATCH_TYPE_LESS_OR_EQUAL, attributeType,
new ASN1OctetString(assertionValue), null,
NO_SUB_ANY, null, null);
}
public static MatchedValuesFilter createLessOrEqualFilter(
final String attributeType,
final byte[] assertionValue)
{
ensureNotNull(attributeType, assertionValue);
return new MatchedValuesFilter(MATCH_TYPE_LESS_OR_EQUAL, attributeType,
new ASN1OctetString(assertionValue), null,
NO_SUB_ANY, null, null);
}
public static MatchedValuesFilter createPresentFilter(
final String attributeType)
{
ensureNotNull(attributeType);
return new MatchedValuesFilter(MATCH_TYPE_PRESENT, attributeType, null,
null, NO_SUB_ANY, null, null);
}
public static MatchedValuesFilter createApproximateFilter(
final String attributeType,
final String assertionValue)
{
ensureNotNull(attributeType, assertionValue);
return new MatchedValuesFilter(MATCH_TYPE_APPROXIMATE, attributeType,
new ASN1OctetString(assertionValue), null,
NO_SUB_ANY, null, null);
}
public static MatchedValuesFilter createApproximateFilter(
final String attributeType,
final byte[] assertionValue)
{
ensureNotNull(attributeType, assertionValue);
return new MatchedValuesFilter(MATCH_TYPE_APPROXIMATE, attributeType,
new ASN1OctetString(assertionValue), null,
NO_SUB_ANY, null, null);
}
public static MatchedValuesFilter createExtensibleMatchFilter(
final String attributeType,
final String matchingRuleID,
final String assertionValue)
{
ensureNotNull(assertionValue);
ensureTrue((attributeType != null) || (matchingRuleID != null));
final ASN1OctetString matchValue =
new ASN1OctetString(EXTENSIBLE_TYPE_MATCH_VALUE, assertionValue);
return new MatchedValuesFilter(MATCH_TYPE_EXTENSIBLE, attributeType,
matchValue, null, NO_SUB_ANY, null,
matchingRuleID);
}
public static MatchedValuesFilter createExtensibleMatchFilter(
final String attributeType,
final String matchingRuleID,
final byte[] assertionValue)
{
ensureNotNull(assertionValue);
ensureTrue((attributeType != null) || (matchingRuleID != null));
final ASN1OctetString matchValue =
new ASN1OctetString(EXTENSIBLE_TYPE_MATCH_VALUE, assertionValue);
return new MatchedValuesFilter(MATCH_TYPE_EXTENSIBLE, attributeType,
matchValue, null, NO_SUB_ANY, null,
matchingRuleID);
}
public static MatchedValuesFilter create(final Filter filter)
throws LDAPException
{
switch (filter.getFilterType())
{
case Filter.FILTER_TYPE_AND:
throw new LDAPException(ResultCode.DECODING_ERROR,
ERR_MV_FILTER_AND_NOT_SUPPORTED.get());
case Filter.FILTER_TYPE_OR:
throw new LDAPException(ResultCode.DECODING_ERROR,
ERR_MV_FILTER_OR_NOT_SUPPORTED.get());
case Filter.FILTER_TYPE_NOT:
throw new LDAPException(ResultCode.DECODING_ERROR,
ERR_MV_FILTER_NOT_NOT_SUPPORTED.get());
case Filter.FILTER_TYPE_EQUALITY:
return createEqualityFilter(filter.getAttributeName(),
filter.getAssertionValueBytes());
case Filter.FILTER_TYPE_SUBSTRING:
return createSubstringFilter(filter.getAttributeName(),
filter.getSubInitialBytes(), filter.getSubAnyBytes(),
filter.getSubFinalBytes());
case Filter.FILTER_TYPE_GREATER_OR_EQUAL:
return createGreaterOrEqualFilter(filter.getAttributeName(),
filter.getAssertionValueBytes());
case Filter.FILTER_TYPE_LESS_OR_EQUAL:
return createLessOrEqualFilter(filter.getAttributeName(),
filter.getAssertionValueBytes());
case Filter.FILTER_TYPE_PRESENCE:
return createPresentFilter(filter.getAttributeName());
case Filter.FILTER_TYPE_APPROXIMATE_MATCH:
return createApproximateFilter(filter.getAttributeName(),
filter.getAssertionValueBytes());
case Filter.FILTER_TYPE_EXTENSIBLE_MATCH:
if (filter.getDNAttributes())
{
throw new LDAPException(ResultCode.DECODING_ERROR,
ERR_MV_FILTER_DNATTRS_NOT_SUPPORTED.get());
}
return createExtensibleMatchFilter(filter.getAttributeName(),
filter.getMatchingRuleID(),
filter.getAssertionValueBytes());
default:
// This should never happen.
throw new LDAPException(ResultCode.DECODING_ERROR,
ERR_MV_FILTER_INVALID_FILTER_TYPE.get(
toHex(filter.getFilterType())));
}
}
public byte getMatchType()
{
return matchType;
}
public String getAttributeType()
{
return attributeType;
}
public String getAssertionValue()
{
if (assertionValue == null)
{
return null;
}
else
{
return assertionValue.stringValue();
}
}
public byte[] getAssertionValueBytes()
{
if (assertionValue == null)
{
return null;
}
else
{
return assertionValue.getValue();
}
}
public ASN1OctetString getRawAssertionValue()
{
return assertionValue;
}
public String getSubInitialValue()
{
if (subInitialValue == null)
{
return null;
}
else
{
return subInitialValue.stringValue();
}
}
public byte[] getSubInitialValueBytes()
{
if (subInitialValue == null)
{
return null;
}
else
{
return subInitialValue.getValue();
}
}
public ASN1OctetString getRawSubInitialValue()
{
return subInitialValue;
}
public String[] getSubAnyValues()
{
if (subAnyValues.length == 0)
{
return NO_SUB_ANY_STRINGS;
}
else
{
final String[] subAnyStrings = new String[subAnyValues.length];
for (int i=0; i < subAnyValues.length; i++)
{
subAnyStrings[i] = subAnyValues[i].stringValue();
}
return subAnyStrings;
}
}
public byte[][] getSubAnyValueBytes()
{
if (subAnyValues.length == 0)
{
return NO_SUB_ANY_BYTES;
}
else
{
final byte[][] subAnyBytes = new byte[subAnyValues.length][];
for (int i=0; i < subAnyValues.length; i++)
{
subAnyBytes[i] = subAnyValues[i].getValue();
}
return subAnyBytes;
}
}
public ASN1OctetString[] getRawSubAnyValues()
{
return subAnyValues;
}
public String getSubFinalValue()
{
if (subFinalValue == null)
{
return null;
}
else
{
return subFinalValue.stringValue();
}
}
public byte[] getSubFinalValueBytes()
{
if (subFinalValue == null)
{
return null;
}
else
{
return subFinalValue.getValue();
}
}
public ASN1OctetString getRawSubFinalValue()
{
return subFinalValue;
}
public String getMatchingRuleID()
{
return matchingRuleID;
}
public ASN1Element encode()
{
switch (matchType)
{
case MATCH_TYPE_EQUALITY:
case MATCH_TYPE_GREATER_OR_EQUAL:
case MATCH_TYPE_LESS_OR_EQUAL:
case MATCH_TYPE_APPROXIMATE:
ASN1Element[] elements =
{
new ASN1OctetString(attributeType),
assertionValue
};
return new ASN1Sequence(matchType, elements);
case MATCH_TYPE_SUBSTRINGS:
final ArrayList<ASN1Element> subElements =
new ArrayList<ASN1Element>(3);
if (subInitialValue != null)
{
subElements.add(subInitialValue);
}
if (subAnyValues.length > 0)
{
subElements.addAll(Arrays.asList(subAnyValues));
}
if (subFinalValue != null)
{
subElements.add(subFinalValue);
}
elements = new ASN1Element[]
{
new ASN1OctetString(attributeType),
new ASN1Sequence(subElements)
};
return new ASN1Sequence(matchType, elements);
case MATCH_TYPE_PRESENT:
return new ASN1OctetString(matchType, attributeType);
case MATCH_TYPE_EXTENSIBLE:
final ArrayList<ASN1Element> extElements =
new ArrayList<ASN1Element>(3);
if (attributeType != null)
{
extElements.add(new ASN1OctetString(EXTENSIBLE_TYPE_ATTRIBUTE_NAME,
attributeType));
}
if (matchingRuleID != null)
{
extElements.add(new ASN1OctetString(EXTENSIBLE_TYPE_MATCHING_RULE_ID,
matchingRuleID));
}
extElements.add(assertionValue);
return new ASN1Sequence(matchType, extElements);
default:
return null;
}
}
public static MatchedValuesFilter decode(final ASN1Element element)
throws LDAPException
{
ASN1OctetString assertionValue = null;
ASN1OctetString subInitialValue = null;
ASN1OctetString subFinalValue = null;
ASN1OctetString[] subAnyValues = NO_SUB_ANY;
final byte matchType = element.getType();
String attributeType = null;
String matchingRuleID = null;
switch (matchType)
{
case MATCH_TYPE_EQUALITY:
case MATCH_TYPE_GREATER_OR_EQUAL:
case MATCH_TYPE_LESS_OR_EQUAL:
case MATCH_TYPE_APPROXIMATE:
try
{
final ASN1Element[] elements =
ASN1Sequence.decodeAsSequence(element).elements();
attributeType =
ASN1OctetString.decodeAsOctetString(elements[0]).stringValue();
assertionValue =
ASN1OctetString.decodeAsOctetString(elements[1]);
}
catch (Exception e)
{
debugException(e);
throw new LDAPException(ResultCode.DECODING_ERROR,
ERR_MV_FILTER_NOT_AVA.get(e), e);
}
break;
case MATCH_TYPE_SUBSTRINGS:
try
{
final ASN1Element[] elements =
ASN1Sequence.decodeAsSequence(element).elements();
attributeType =
ASN1OctetString.decodeAsOctetString(elements[0]).stringValue();
ArrayList<ASN1OctetString> subAnyList = null;
final ASN1Element[] subElements =
ASN1Sequence.decodeAsSequence(elements[1]).elements();
for (final ASN1Element e : subElements)
{
switch (e.getType())
{
case SUBSTRING_TYPE_SUBINITIAL:
if (subInitialValue == null)
{
subInitialValue = ASN1OctetString.decodeAsOctetString(e);
}
else
{
throw new LDAPException(ResultCode.DECODING_ERROR,
ERR_MV_FILTER_MULTIPLE_SUBINITIAL.get());
}
break;
case SUBSTRING_TYPE_SUBANY:
if (subAnyList == null)
{
subAnyList =
new ArrayList<ASN1OctetString>(subElements.length);
}
subAnyList.add(ASN1OctetString.decodeAsOctetString(e));
break;
case SUBSTRING_TYPE_SUBFINAL:
if (subFinalValue == null)
{
subFinalValue = ASN1OctetString.decodeAsOctetString(e);
}
else
{
throw new LDAPException(ResultCode.DECODING_ERROR,
ERR_MV_FILTER_MULTIPLE_SUBFINAL.get());
}
break;
default:
throw new LDAPException(ResultCode.DECODING_ERROR,
ERR_MV_FILTER_INVALID_SUB_TYPE.get(
toHex(e.getType())));
}
}
if (subAnyList != null)
{
subAnyValues =
subAnyList.toArray(new ASN1OctetString[subAnyList.size()]);
}
}
catch (LDAPException le)
{
debugException(le);
throw le;
}
catch (Exception e)
{
debugException(e);
throw new LDAPException(ResultCode.DECODING_ERROR,
ERR_MV_FILTER_CANNOT_DECODE_SUBSTRING.get(e),
e);
}
if ((subInitialValue == null) && (subAnyValues.length == 0) &&
(subFinalValue == null))
{
throw new LDAPException(ResultCode.DECODING_ERROR,
ERR_MV_FILTER_NO_SUBSTRING_ELEMENTS.get());
}
break;
case MATCH_TYPE_PRESENT:
attributeType =
ASN1OctetString.decodeAsOctetString(element).stringValue();
break;
case MATCH_TYPE_EXTENSIBLE:
try
{
final ASN1Element[] elements =
ASN1Sequence.decodeAsSequence(element).elements();
for (final ASN1Element e : elements)
{
switch (e.getType())
{
case EXTENSIBLE_TYPE_ATTRIBUTE_NAME:
if (attributeType == null)
{
attributeType =
ASN1OctetString.decodeAsOctetString(e).stringValue();
}
else
{
throw new LDAPException(ResultCode.DECODING_ERROR,
ERR_MV_FILTER_EXT_MULTIPLE_AT.get());
}
break;
case EXTENSIBLE_TYPE_MATCHING_RULE_ID:
if (matchingRuleID == null)
{
matchingRuleID =
ASN1OctetString.decodeAsOctetString(e).stringValue();
}
else
{
throw new LDAPException(ResultCode.DECODING_ERROR,
ERR_MV_FILTER_MULTIPLE_MRID.get());
}
break;
case EXTENSIBLE_TYPE_MATCH_VALUE:
if (assertionValue == null)
{
assertionValue =
ASN1OctetString.decodeAsOctetString(e);
}
else
{
throw new LDAPException(ResultCode.DECODING_ERROR,
ERR_MV_FILTER_EXT_MULTIPLE_VALUE.get());
}
break;
default:
throw new LDAPException(ResultCode.DECODING_ERROR,
ERR_MV_FILTER_EXT_INVALID_TYPE.get(
toHex(e.getType())));
}
}
}
catch (LDAPException le)
{
debugException(le);
throw le;
}
catch (Exception e)
{
debugException(e);
throw new LDAPException(ResultCode.DECODING_ERROR,
ERR_MV_FILTER_EXT_NOT_SEQUENCE.get(e), e);
}
if ((attributeType == null) && (matchingRuleID == null))
{
throw new LDAPException(ResultCode.DECODING_ERROR,
ERR_MV_FILTER_NO_ATTR_OR_MRID.get());
}
if (assertionValue == null)
{
throw new LDAPException(ResultCode.DECODING_ERROR,
ERR_MV_FILTER_EXT_NO_VALUE.get());
}
break;
default:
throw new LDAPException(ResultCode.DECODING_ERROR,
ERR_MV_FILTER_INVALID_TYPE.get(
toHex(matchType)));
}
return new MatchedValuesFilter(matchType, attributeType, assertionValue,
subInitialValue, subAnyValues, subFinalValue,
matchingRuleID);
}
public Filter toFilter()
{
switch (matchType)
{
case MATCH_TYPE_EQUALITY:
return Filter.createEqualityFilter(attributeType,
assertionValue.getValue());
case MATCH_TYPE_SUBSTRINGS:
return Filter.createSubstringFilter(attributeType,
getSubInitialValueBytes(), getSubAnyValueBytes(),
getSubFinalValueBytes());
case MATCH_TYPE_GREATER_OR_EQUAL:
return Filter.createGreaterOrEqualFilter(attributeType,
assertionValue.getValue());
case MATCH_TYPE_LESS_OR_EQUAL:
return Filter.createLessOrEqualFilter(attributeType,
assertionValue.getValue());
case MATCH_TYPE_PRESENT:
return Filter.createPresenceFilter(attributeType);
case MATCH_TYPE_APPROXIMATE:
return Filter.createApproximateMatchFilter(attributeType,
assertionValue.getValue());
case MATCH_TYPE_EXTENSIBLE:
return Filter.createExtensibleMatchFilter(attributeType, matchingRuleID,
false, assertionValue.getValue());
default:
return null;
}
}
@Override()
public String toString()
{
final StringBuilder buffer = new StringBuilder();
toString(buffer);
return buffer.toString();
}
public void toString(final StringBuilder buffer)
{
buffer.append('(');
switch (matchType)
{
case MATCH_TYPE_EQUALITY:
buffer.append(attributeType);
buffer.append('=');
buffer.append(assertionValue.stringValue());
break;
case MATCH_TYPE_SUBSTRINGS:
buffer.append(attributeType);
buffer.append('=');
if (subInitialValue != null)
{
buffer.append(subInitialValue.stringValue());
}
for (final ASN1OctetString s : subAnyValues)
{
buffer.append('*');
buffer.append(s.stringValue());
}
buffer.append('*');
if (subFinalValue != null)
{
buffer.append(subFinalValue.stringValue());
}
break;
case MATCH_TYPE_GREATER_OR_EQUAL:
buffer.append(attributeType);
buffer.append(">=");
buffer.append(assertionValue.stringValue());
break;
case MATCH_TYPE_LESS_OR_EQUAL:
buffer.append(attributeType);
buffer.append("<=");
buffer.append(assertionValue.stringValue());
break;
case MATCH_TYPE_PRESENT:
buffer.append(attributeType);
buffer.append("=*");
break;
case MATCH_TYPE_APPROXIMATE:
buffer.append(attributeType);
buffer.append("~=");
buffer.append(assertionValue.stringValue());
break;
case MATCH_TYPE_EXTENSIBLE:
if (attributeType != null)
{
buffer.append(attributeType);
}
if (matchingRuleID != null)
{
buffer.append(':');
buffer.append(matchingRuleID);
}
buffer.append(":=");
buffer.append(assertionValue.stringValue());
break;
}
buffer.append(')');
}
}