001/*
002 *  Licensed to the Apache Software Foundation (ASF) under one
003 *  or more contributor license agreements.  See the NOTICE file
004 *  distributed with this work for additional information
005 *  regarding copyright ownership.  The ASF licenses this file
006 *  to you under the Apache License, Version 2.0 (the
007 *  "License"); you may not use this file except in compliance
008 *  with the License.  You may obtain a copy of the License at
009 * 
010 *    http://www.apache.org/licenses/LICENSE-2.0
011 * 
012 *  Unless required by applicable law or agreed to in writing,
013 *  software distributed under the License is distributed on an
014 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 *  KIND, either express or implied.  See the License for the
016 *  specific language governing permissions and limitations
017 *  under the License.
018 * 
019 */
020package org.apache.directory.api.ldap.codec.search;
021
022
023import java.nio.BufferOverflowException;
024import java.nio.ByteBuffer;
025
026import org.apache.directory.api.asn1.EncoderException;
027import org.apache.directory.api.asn1.ber.tlv.BerValue;
028import org.apache.directory.api.asn1.ber.tlv.TLV;
029import org.apache.directory.api.i18n.I18n;
030import org.apache.directory.api.ldap.codec.AttributeValueAssertion;
031import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
032
033
034/**
035 * Object to store the filter. A filter is seen as a tree with a root.
036 * 
037 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
038 */
039public class AttributeValueAssertionFilter extends Filter
040{
041    // ~ Instance fields
042    // ----------------------------------------------------------------------------
043
044    /** The assertion. */
045    private AttributeValueAssertion assertion;
046
047    /** The filter type */
048    private int filterType;
049
050    /** The attributeValueAssertion length */
051    private int avaLength;
052
053
054    // ~ Constructors
055    // -------------------------------------------------------------------------------
056
057    /**
058     * The constructor.
059     * 
060     * @param filterType The filter type
061     */
062    public AttributeValueAssertionFilter( int tlvId, int filterType )
063    {
064        super( tlvId );
065        this.filterType = filterType;
066    }
067
068
069    /**
070     * The constructor.
071     * 
072     * @param filterType The filter type
073     */
074    public AttributeValueAssertionFilter( int filterType )
075    {
076        super();
077        this.filterType = filterType;
078    }
079
080
081    // ~ Methods
082    // ------------------------------------------------------------------------------------
083
084    /**
085     * Get the assertion
086     * 
087     * @return Returns the assertion.
088     */
089    public AttributeValueAssertion getAssertion()
090    {
091        return assertion;
092    }
093
094
095    /**
096     * Set the assertion
097     * 
098     * @param assertion The assertion to set.
099     */
100    public void setAssertion( AttributeValueAssertion assertion )
101    {
102        this.assertion = assertion;
103    }
104
105
106    /**
107     * Get the filter type
108     * 
109     * @return Returns the filterType.
110     */
111    public int getFilterType()
112    {
113        return filterType;
114    }
115
116
117    /**
118     * Set the filter type
119     * 
120     * @param filterType The filterType to set.
121     */
122    public void setFilterType( int filterType )
123    {
124        this.filterType = filterType;
125    }
126
127
128    /**
129     * Compute the AttributeValueFilter length
130     * 
131     * AttributeValueFilter :
132     * 
133     * 0xA(3, 5, 6, 8) L1
134     *  |
135     *  +--> 0x04 L2 attributeDesc
136     *  +--> 0x04 L3 assertionValue
137     * 
138     * 
139     * L2 = Length(attributeDesc)
140     * L3 = Length(assertionValue)
141     * L1 = 1 + Length(L2) + L2
142     *      + 1 + Length(L3) + L3
143     * 
144     * Length(AttributeValueFilter) = Length(0xA?) + Length(L1)
145     *                                + 1 + Length(L2) + L2
146     *                                + 1 + Length(L3) + L3
147     */
148    public int computeLength()
149    {
150        avaLength = 0;
151        int attributeDescLength = assertion.getAttributeDesc().length();
152
153        avaLength = 1 + TLV.getNbBytes( attributeDescLength ) + attributeDescLength;
154
155        org.apache.directory.api.ldap.model.entry.Value<?> assertionValue = assertion.getAssertionValue();
156
157        int assertionValueLength = 0;
158
159        assertionValueLength = assertionValue.getBytes().length;
160
161        avaLength += 1 + TLV.getNbBytes( assertionValueLength ) + assertionValueLength;
162
163        return 1 + TLV.getNbBytes( avaLength ) + avaLength;
164    }
165
166
167    /**
168     * Encode the AttributeValueAssertion Filters to a PDU. The
169     * following filters are to be encoded :
170     *  - equality match
171     *  - greater or equal
172     *  - less or equal
173     *  - approx match
174     * 
175     * AttributeValueAssertion filters :
176     * 
177     * 0xA[3, 5, 6, 8] LL
178     * 0x04 LL attributeDesc
179     * 0x04 LL assertionValue
180     * 
181     * @param buffer The buffer where to put the PDU
182     * @return The PDU.
183     */
184    public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
185    {
186        if ( buffer == null )
187        {
188            throw new EncoderException( I18n.err( I18n.ERR_04023 ) );
189        }
190
191        try
192        {
193            // The AttributeValueAssertion Tag
194            switch ( filterType )
195            {
196                case LdapCodecConstants.EQUALITY_MATCH_FILTER:
197                    buffer.put( ( byte ) LdapCodecConstants.EQUALITY_MATCH_FILTER_TAG );
198                    break;
199
200                case LdapCodecConstants.LESS_OR_EQUAL_FILTER:
201                    buffer.put( ( byte ) LdapCodecConstants.LESS_OR_EQUAL_FILTER_TAG );
202                    break;
203
204                case LdapCodecConstants.GREATER_OR_EQUAL_FILTER:
205                    buffer.put( ( byte ) LdapCodecConstants.GREATER_OR_EQUAL_FILTER_TAG );
206                    break;
207
208                case LdapCodecConstants.APPROX_MATCH_FILTER:
209                    buffer.put( ( byte ) LdapCodecConstants.APPROX_MATCH_FILTER_TAG );
210                    break;
211
212                default:
213                    throw new IllegalArgumentException( "Unexpected filter type: " + filterType );
214            }
215
216            buffer.put( TLV.getBytes( avaLength ) );
217        }
218        catch ( BufferOverflowException boe )
219        {
220            throw new EncoderException( I18n.err( I18n.ERR_04005 ), boe );
221        }
222
223        // The attribute desc
224        BerValue.encode( buffer, assertion.getAttributeDesc() );
225
226        // The assertion desc
227        if ( assertion.getAssertionValue().isHumanReadable() )
228        {
229            BerValue.encode( buffer, assertion.getAssertionValue().getString() );
230        }
231        else
232        {
233            BerValue.encode( buffer, assertion.getAssertionValue().getBytes() );
234        }
235
236        return buffer;
237    }
238
239
240    /**
241     * Return a string compliant with RFC 2254 representing an item filter
242     * 
243     * @return The item filter string
244     */
245    public String toString()
246    {
247        return assertion != null ? assertion.toStringRFC2254( filterType ) : "";
248    }
249}