blob: 455d541bafa2dc877edd95785cb7a594f7e6b342 [file] [log] [blame]
/*
* 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
*
* https://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.directory.api.ldap.codec.search;
import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import org.apache.directory.api.asn1.EncoderException;
import org.apache.directory.api.asn1.ber.tlv.BerValue;
import org.apache.directory.api.asn1.ber.tlv.TLV;
import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
import org.apache.directory.api.i18n.I18n;
import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
import org.apache.directory.api.util.Strings;
/**
* A Object that stores the substring filter.
*
* A substring filter follow this
* grammar :
*
* substring = attr "=" ( ([initial] any [final] |
* (initial [any] [final) |
* ([initial] [any] final) )
*
* initial = value
* any = "*" *(value "*")
* final = value
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
public class SubstringFilter extends Filter
{
/** The substring filter type (an attributeDescription) */
private String type;
/**
* This member is used to control the length of the three parts of the
* substring filter
*/
private int substringsLength;
/** The initial filter */
private String initialSubstrings;
/** The any filter. It's a list of LdapString */
private List<String> anySubstrings = new ArrayList<>( 1 );
/** The final filter */
private String finalSubstrings;
/** Temporary storage for substringsFilter length */
private int substringsFilterLength;
/** Temporary storage for substringsFilter sequence length */
private int substringsFilterSequenceLength;
/**
* The constructor. We will create the 'any' subsring arraylist with only
* one element.
*
* @param tlvId The TLV identifier
*/
public SubstringFilter( int tlvId )
{
super( tlvId );
}
/**
* The constructor. We will create the 'any' subsring arraylist with only
* one element.
*/
public SubstringFilter()
{
super();
}
/**
* Get the internal substrings
*
* @return Returns the anySubstrings.
*/
public List<String> getAnySubstrings()
{
return anySubstrings;
}
/**
* Add a internal substring
*
* @param any The anySubstrings to set.
*/
public void addAnySubstrings( String any )
{
this.anySubstrings.add( any );
}
/**
* Get the final substring
*
* @return Returns the finalSubstrings.
*/
public String getFinalSubstrings()
{
return finalSubstrings;
}
/**
* Set the final substring
*
* @param finalSubstrings The finalSubstrings to set.
*/
public void setFinalSubstrings( String finalSubstrings )
{
this.finalSubstrings = finalSubstrings;
}
/**
* Get the initial substring
*
* @return Returns the initialSubstrings.
*/
public String getInitialSubstrings()
{
return initialSubstrings;
}
/**
* Set the initial substring
*
* @param initialSubstrings The initialSubstrings to set.
*/
public void setInitialSubstrings( String initialSubstrings )
{
this.initialSubstrings = initialSubstrings;
}
/**
* Get the attribute
*
* @return Returns the type.
*/
public String getType()
{
return type;
}
/**
* Set the attribute to match
*
* @param type The type to set.
*/
public void setType( String type )
{
this.type = type;
}
/**
* @return Returns the substringsLength.
*/
public int getSubstringsLength()
{
return substringsLength;
}
/**
* @param substringsLength The substringsLength to set.
*/
public void setSubstringsLength( int substringsLength )
{
this.substringsLength = substringsLength;
}
/**
* Compute the SubstringFilter length
* <br>
* SubstringFilter :
* <pre>
* 0xA4 L1
* |
* +--&gt; 0x04 L2 type
* +--&gt; 0x30 L3
* |
* [+--&gt; 0x80 L4 initial]
* [+--&gt; 0x81 L5-1 any]
* [+--&gt; 0x81 L5-2 any]
* [+--&gt; ...
* [+--&gt; 0x81 L5-i any]
* [+--&gt; ...
* [+--&gt; 0x81 L5-n any]
* [+--&gt; 0x82 L6 final]
* </pre>
*
* @return The encoded length
*/
@Override
public int computeLength()
{
// The type
int typeLength = Strings.getBytesUtf8( type ).length;
substringsFilterLength = 1 + TLV.getNbBytes( typeLength ) + typeLength;
substringsFilterSequenceLength = 0;
if ( initialSubstrings != null )
{
int initialLength = Strings.getBytesUtf8( initialSubstrings ).length;
substringsFilterSequenceLength += 1 + TLV.getNbBytes( initialLength )
+ initialLength;
}
if ( anySubstrings != null )
{
for ( String any : anySubstrings )
{
int anyLength = Strings.getBytesUtf8( any ).length;
substringsFilterSequenceLength += 1 + TLV.getNbBytes( anyLength ) + anyLength;
}
}
if ( finalSubstrings != null )
{
int finalLength = Strings.getBytesUtf8( finalSubstrings ).length;
substringsFilterSequenceLength += 1 + TLV.getNbBytes( finalLength )
+ finalLength;
}
substringsFilterLength += 1 + TLV.getNbBytes( substringsFilterSequenceLength )
+ substringsFilterSequenceLength;
return 1 + TLV.getNbBytes( substringsFilterLength ) + substringsFilterLength;
}
/**
* Encode the Substrings Filter to a PDU.
* <br>
* Substrings Filter :
* <pre>
* 0xA4 LL
* 0x30 LL substringsFilter
* 0x04 LL type
* 0x30 LL substrings sequence
* | 0x80 LL initial
* | / [0x81 LL any]*
* |/ [0x82 LL final]
* +--[0x81 LL any]+
* \ [0x82 LL final]
* \
* 0x82 LL final
* </pre>
*
* @param buffer The buffer where to put the PDU
* @return The PDU.
*/
@Override
public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
{
if ( buffer == null )
{
throw new EncoderException( I18n.err( I18n.ERR_08000_CANNOT_PUT_A_PDU_IN_NULL_BUFFER ) );
}
try
{
// The SubstringFilter Tag
buffer.put( ( byte ) LdapCodecConstants.SUBSTRINGS_FILTER_TAG );
buffer.put( TLV.getBytes( substringsFilterLength ) );
// The type
BerValue.encode( buffer, Strings.getBytesUtf8( type ) );
// The SubstringSequenceFilter Tag
buffer.put( UniversalTag.SEQUENCE.getValue() );
buffer.put( TLV.getBytes( substringsFilterSequenceLength ) );
if ( ( initialSubstrings == null ) && ( ( anySubstrings == null ) || anySubstrings.isEmpty() )
&& ( finalSubstrings == null ) )
{
throw new EncoderException( I18n.err( I18n.ERR_05502_NULL_INITIAL_ANY_OR_FINAL_SUBSTRING ) );
}
// The initial substring
if ( initialSubstrings != null )
{
byte[] initialBytes = Strings.getBytesUtf8( initialSubstrings );
buffer.put( ( byte ) LdapCodecConstants.SUBSTRINGS_FILTER_INITIAL_TAG );
buffer.put( TLV.getBytes( initialBytes.length ) );
buffer.put( initialBytes );
}
// The any substrings
if ( anySubstrings != null )
{
for ( String any : anySubstrings )
{
byte[] anyBytes = Strings.getBytesUtf8( any );
buffer.put( ( byte ) LdapCodecConstants.SUBSTRINGS_FILTER_ANY_TAG );
buffer.put( TLV.getBytes( anyBytes.length ) );
buffer.put( anyBytes );
}
}
// The final substring
if ( finalSubstrings != null )
{
byte[] finalBytes = Strings.getBytesUtf8( finalSubstrings );
buffer.put( ( byte ) LdapCodecConstants.SUBSTRINGS_FILTER_FINAL_TAG );
buffer.put( TLV.getBytes( finalBytes.length ) );
buffer.put( finalBytes );
}
}
catch ( BufferOverflowException boe )
{
throw new EncoderException( I18n.err( I18n.ERR_08212_PDU_BUFFER_TOO_SMALL ), boe );
}
return buffer;
}
/**
* Return a string compliant with RFC 2254 representing a Substring filter
*
* @return The substring filter string
*/
@Override
public String toString()
{
StringBuilder sb = new StringBuilder();
if ( initialSubstrings != null )
{
sb.append( initialSubstrings );
}
sb.append( '*' );
if ( anySubstrings != null )
{
for ( String any : anySubstrings )
{
sb.append( any ).append( '*' );
}
}
if ( finalSubstrings != null )
{
sb.append( finalSubstrings );
}
return sb.toString();
}
}