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.ByteBuffer;
024import java.util.ArrayList;
025import java.util.List;
026
027import org.apache.directory.api.asn1.DecoderException;
028import org.apache.directory.api.asn1.EncoderException;
029import org.apache.directory.api.i18n.I18n;
030
031
032/**
033 * This Filter abstract class is used to store a set of filters used by
034 * OR/AND/NOT filters.
035 * 
036 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
037 */
038public abstract class ConnectorFilter extends Filter
039{
040    /** The set of filters used by And/Or filters */
041    protected List<Filter> filterSet;
042
043    /** The filters length */
044    protected int filtersLength;
045
046
047    /**
048     * The constructor. We wont initialize the ArrayList as it may not be used.
049     * 
050     * @param tlvId The TLV identifier
051     */
052    public ConnectorFilter( int tlvId )
053    {
054        super( tlvId );
055    }
056
057
058    /**
059     * The constructor. We wont initialize the ArrayList as it may not be used.
060     */
061    public ConnectorFilter()
062    {
063        super();
064    }
065
066
067    /**
068     * Add a new Filter to the list.
069     * 
070     * @param filter The filter to add
071     * @throws DecoderException If the decoding failed
072     */
073    public void addFilter( Filter filter ) throws DecoderException
074    {
075
076        if ( filterSet == null )
077        {
078            filterSet = new ArrayList<>();
079        }
080
081        filterSet.add( filter );
082    }
083
084
085    /**
086     * Get the list of filters stored in the composite filter
087     * 
088     * @return And array of filters
089     */
090    public List<Filter> getFilterSet()
091    {
092        return filterSet;
093    }
094
095
096    /**
097     * Compute the ConnectorFilter length Length(ConnectorFilter) =
098     * sum(filterSet.computeLength())
099     * 
100     * @return The encoded length
101     */
102    @Override
103    public int computeLength()
104    {
105        int connectorFilterLength = 0;
106
107        if ( ( filterSet != null ) && ( !filterSet.isEmpty() ) )
108        {
109            for ( Filter filter : filterSet )
110            {
111                connectorFilterLength += filter.computeLength();
112            }
113        }
114
115        return connectorFilterLength;
116    }
117
118
119    /**
120     * Encode the ConnectorFilter message to a PDU. 
121     * <pre>
122     * ConnectorFilter :
123     * filter.encode() ... filter.encode()
124     * </pre>
125     * 
126     * @param buffer The buffer where to put the PDU
127     * @return The PDU.
128     * @throws EncoderException If the encoding failed
129     */
130    @Override
131    public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
132    {
133        if ( buffer == null )
134        {
135            throw new EncoderException( I18n.err( I18n.ERR_04023 ) );
136        }
137
138        // encode each filter
139        if ( ( filterSet != null ) && ( !filterSet.isEmpty() ) )
140        {
141            for ( Filter filter : filterSet )
142            {
143                filter.encode( buffer );
144            }
145        }
146
147        return buffer;
148    }
149
150
151    /**
152     * Return a string compliant with RFC 2254 representing a composite filter,
153     * one of AND, OR and NOT
154     * 
155     * @return The composite filter string
156     */
157    @Override
158    public String toString()
159    {
160        StringBuilder sb = new StringBuilder();
161
162        if ( ( filterSet != null ) && ( !filterSet.isEmpty() ) )
163        {
164            for ( Filter filter : filterSet )
165            {
166                sb.append( '(' ).append( filter ).append( ')' );
167            }
168        }
169
170        return sb.toString();
171    }
172}