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     */
020    package org.apache.directory.shared.ldap.codec.search.controls.pSearch;
021    
022    
023    import java.nio.ByteBuffer;
024    
025    import org.apache.directory.shared.asn1.AbstractAsn1Object;
026    import org.apache.directory.shared.asn1.ber.tlv.TLV;
027    import org.apache.directory.shared.asn1.ber.tlv.UniversalTag;
028    import org.apache.directory.shared.asn1.ber.tlv.Value;
029    import org.apache.directory.shared.asn1.codec.EncoderException;
030    
031    
032    /**
033     * A persistence search object
034     * 
035     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
036     * @version $Rev: 764131 $, $Date: 2009-04-11 03:03:00 +0200 (Sam, 11 avr 2009) $, 
037     */
038    public class PSearchControlCodec extends AbstractAsn1Object
039    {
040        /**
041         * If changesOnly is TRUE, the server MUST NOT return any existing entries
042         * that match the search criteria. Entries are only returned when they are
043         * changed (added, modified, deleted, or subject to a modifyDN operation).
044         */
045        private boolean changesOnly;
046    
047        /**
048         * If returnECs is TRUE, the server MUST return an Entry Change Notification
049         * control with each entry returned as the result of changes.
050         */
051        private boolean returnECs;
052    
053        /**
054         * As changes are made to the server, the effected entries MUST be returned
055         * to the client if they match the standard search criteria and if the
056         * operation that caused the change is included in the changeTypes field.
057         * The changeTypes field is the logical OR of one or more of these values:
058         * add    (1), 
059         * delete (2), 
060         * modify (4), 
061         * modDN  (8).
062         */
063        private int changeTypes;
064        
065        /** Definition of the change types */
066        public static final int CHANGE_TYPE_ADD     = 1;
067        public static final int CHANGE_TYPE_DELETE  = 2;
068        public static final int CHANGE_TYPE_MODIFY  = 4;
069        public static final int CHANGE_TYPE_MODDN   = 8;
070        
071        /** Min and Max values for the possible combined change types */
072        public static final int CHANGE_TYPES_MIN = CHANGE_TYPE_ADD;
073        public static final int CHANGE_TYPES_MAX = CHANGE_TYPE_ADD | CHANGE_TYPE_DELETE | CHANGE_TYPE_MODIFY | CHANGE_TYPE_MODDN;
074    
075        /** A temporary storage for a psearch length */
076        private int psearchSeqLength;
077    
078        /**
079         * Default constructor
080         *
081         */
082        public PSearchControlCodec()
083        {
084            super();
085        }
086    
087        public void setChangesOnly( boolean changesOnly )
088        {
089            this.changesOnly = changesOnly;
090        }
091    
092    
093        public boolean isChangesOnly()
094        {
095            return changesOnly;
096        }
097    
098    
099        public void setReturnECs( boolean returnECs )
100        {
101            this.returnECs = returnECs;
102        }
103    
104    
105        public boolean isReturnECs()
106        {
107            return returnECs;
108        }
109    
110    
111        public void setChangeTypes( int changeTypes )
112        {
113            this.changeTypes = changeTypes;
114        }
115    
116    
117        public int getChangeTypes()
118        {
119            return changeTypes;
120        }
121    
122        /**
123         * Compute the PSearchControl length 
124         * 0x30 L1 
125         *   | 
126         *   +--> 0x02 0x0(1-4) [0..2^31-1] (changeTypes) 
127         *   +--> 0x01 0x01 [0x00 | 0xFF] (changeOnly) 
128         *   +--> 0x01 0x01 [0x00 | 0xFF] (returnRCs)
129         */
130        public int computeLength()
131        {
132            int changeTypesLength = 1 + 1 + Value.getNbBytes( changeTypes );
133            int changesOnlyLength = 1 + 1 + 1;
134            int returnRCsLength = 1 + 1 + 1;
135    
136            psearchSeqLength = changeTypesLength + changesOnlyLength + returnRCsLength;
137    
138            return 1 + TLV.getNbBytes( psearchSeqLength ) + psearchSeqLength;
139        }
140    
141    
142        /**
143         * Encodes the persistent search control.
144         * 
145         * @param buffer The encoded sink
146         * @return A ByteBuffer that contains the encoded PDU
147         * @throws EncoderException If anything goes wrong.
148         */
149        public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
150        {
151            // Allocate the bytes buffer.
152            ByteBuffer bb = ByteBuffer.allocate( computeLength() );
153            bb.put( UniversalTag.SEQUENCE_TAG );
154            bb.put( TLV.getBytes( psearchSeqLength ) );
155    
156            Value.encode( bb, changeTypes );
157            Value.encode( bb, changesOnly );
158            Value.encode( bb, returnECs );
159            return bb;
160        }
161    
162    
163        /**
164         * Return a String representing this PSearchControl.
165         */
166        public String toString()
167        {
168            StringBuffer sb = new StringBuffer();
169    
170            sb.append( "    Persistant Search Control\n" );
171            sb.append( "        changeTypes : '" ).append( changeTypes ).append( "'\n" );
172            sb.append( "        changesOnly : '" ).append( changesOnly ).append( "'\n" );
173            sb.append( "        returnECs   : '" ).append( returnECs ).append( "'\n" );
174    
175            return sb.toString();
176        }
177    }