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    /** The assertion. */
042    private AttributeValueAssertion assertion;
043
044    /** The filter type */
045    private int filterType;
046
047    /** The attributeValueAssertion length */
048    private int avaLength;
049
050
051    /**
052     * The constructor.
053     * 
054     * @param tlvId The TLV identifier
055     * @param filterType The filter type
056     */
057    public AttributeValueAssertionFilter( int tlvId, int filterType )
058    {
059        super( tlvId );
060        this.filterType = filterType;
061    }
062
063
064    /**
065     * The constructor.
066     * 
067     * @param filterType The filter type
068     */
069    public AttributeValueAssertionFilter( int filterType )
070    {
071        super();
072        this.filterType = filterType;
073    }
074
075
076    /**
077     * Get the assertion
078     * 
079     * @return Returns the assertion.
080     */
081    public AttributeValueAssertion getAssertion()
082    {
083        return assertion;
084    }
085
086
087    /**
088     * Set the assertion
089     * 
090     * @param assertion The assertion to set.
091     */
092    public void setAssertion( AttributeValueAssertion assertion )
093    {
094        this.assertion = assertion;
095    }
096
097
098    /**
099     * Get the filter type
100     * 
101     * @return Returns the filterType.
102     */
103    public int getFilterType()
104    {
105        return filterType;
106    }
107
108
109    /**
110     * Set the filter type
111     * 
112     * @param filterType The filterType to set.
113     */
114    public void setFilterType( int filterType )
115    {
116        this.filterType = filterType;
117    }
118
119
120    /**
121     * Compute the AttributeValueFilter length
122     * <br>
123     * AttributeValueFilter :
124     * <pre>
125     * 0xA(3, 5, 6, 8) L1
126     *  |
127     *  +--&gt; 0x04 L2 attributeDesc
128     *  +--&gt; 0x04 L3 assertionValue
129     * 
130     * 
131     * L2 = Length(attributeDesc)
132     * L3 = Length(assertionValue)
133     * L1 = 1 + Length(L2) + L2
134     *      + 1 + Length(L3) + L3
135     * 
136     * Length(AttributeValueFilter) = Length(0xA?) + Length(L1)
137     *                                + 1 + Length(L2) + L2
138     *                                + 1 + Length(L3) + L3
139     * </pre>
140     * 
141     * @return The encoded length
142     */
143    @Override
144    public int computeLength()
145    {
146        avaLength = 0;
147        int attributeDescLength = assertion.getAttributeDesc().length();
148
149        avaLength = 1 + TLV.getNbBytes( attributeDescLength ) + attributeDescLength;
150
151        org.apache.directory.api.ldap.model.entry.Value<?> assertionValue = assertion.getAssertionValue();
152
153        int assertionValueLength;
154
155        assertionValueLength = assertionValue.getBytes().length;
156
157        avaLength += 1 + TLV.getNbBytes( assertionValueLength ) + assertionValueLength;
158
159        return 1 + TLV.getNbBytes( avaLength ) + avaLength;
160    }
161
162
163    /**
164     * Encode the AttributeValueAssertion Filters to a PDU. The
165     * following filters are to be encoded :
166     * <ul>
167     *   <li>equality match</li>
168     *   <li>greater or equal</li>
169     *   <li>less or equal</li>
170     *   <li>approx match</li>
171     * </ul>
172     * 
173     * AttributeValueAssertion filters :
174     * <br>
175     * <pre>
176     * 0xA[3, 5, 6, 8] LL
177     *   0x04 LL attributeDesc
178     *   0x04 LL assertionValue
179     * </pre>
180     * 
181     * @param buffer The buffer where to put the PDU
182     * @return The PDU.
183     */
184    @Override
185    public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
186    {
187        if ( buffer == null )
188        {
189            throw new EncoderException( I18n.err( I18n.ERR_04023 ) );
190        }
191
192        try
193        {
194            // The AttributeValueAssertion Tag
195            switch ( filterType )
196            {
197                case LdapCodecConstants.EQUALITY_MATCH_FILTER:
198                    buffer.put( ( byte ) LdapCodecConstants.EQUALITY_MATCH_FILTER_TAG );
199                    break;
200
201                case LdapCodecConstants.LESS_OR_EQUAL_FILTER:
202                    buffer.put( ( byte ) LdapCodecConstants.LESS_OR_EQUAL_FILTER_TAG );
203                    break;
204
205                case LdapCodecConstants.GREATER_OR_EQUAL_FILTER:
206                    buffer.put( ( byte ) LdapCodecConstants.GREATER_OR_EQUAL_FILTER_TAG );
207                    break;
208
209                case LdapCodecConstants.APPROX_MATCH_FILTER:
210                    buffer.put( ( byte ) LdapCodecConstants.APPROX_MATCH_FILTER_TAG );
211                    break;
212
213                default:
214                    throw new IllegalArgumentException( "Unexpected filter type: " + filterType );
215            }
216
217            buffer.put( TLV.getBytes( avaLength ) );
218        }
219        catch ( BufferOverflowException boe )
220        {
221            throw new EncoderException( I18n.err( I18n.ERR_04005 ), boe );
222        }
223
224        // The attribute desc
225        BerValue.encode( buffer, assertion.getAttributeDesc() );
226
227        // The assertion desc
228        if ( assertion.getAssertionValue().isHumanReadable() )
229        {
230            BerValue.encode( buffer, assertion.getAssertionValue().getString() );
231        }
232        else
233        {
234            BerValue.encode( buffer, assertion.getAssertionValue().getBytes() );
235        }
236
237        return buffer;
238    }
239
240
241    /**
242     * Return a string compliant with RFC 2254 representing an item filter
243     * 
244     * @return The item filter string
245     */
246    @Override
247    public String toString()
248    {
249        return assertion != null ? assertion.toStringRFC2254( filterType ) : "";
250    }
251}