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.server.core.partition.impl.btree;
021    
022    
023    import org.apache.directory.shared.ldap.NotImplementedException;
024    import org.apache.directory.server.xdbm.ForwardIndexEntry;
025    import org.apache.directory.server.xdbm.IndexEntry;
026    import org.apache.directory.server.xdbm.Tuple;
027    
028    import java.util.NoSuchElementException;
029    import java.util.regex.Pattern;
030    
031    import javax.naming.NamingEnumeration;
032    import javax.naming.NamingException;
033    
034    
035    /**
036     * A NamingEnumeration over an Index which returns IndexRecords.
037     * 
038     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
039     * @version $Rev: 640657 $
040     */
041    public class IndexEnumeration<T> implements NamingEnumeration<IndexEntry>
042    {
043        /** */
044        private final Pattern re;
045        /** */
046        private final ForwardIndexEntry tmp = new ForwardIndexEntry();
047        /** */
048        private final ForwardIndexEntry returned = new ForwardIndexEntry();
049        /** */
050        private final ForwardIndexEntry prefetched = new ForwardIndexEntry();
051        /** */
052        private final boolean swapKeyVal;
053        /** */
054        private final NamingEnumeration<Tuple> underlying;
055    
056        /** */
057        private boolean hasMore = true;
058    
059    
060        // ------------------------------------------------------------------------
061        // C O N S T R U C T O R S
062        // ------------------------------------------------------------------------
063    
064        
065        public IndexEnumeration( NamingEnumeration<Tuple> list ) throws NamingException
066        {
067            this( list, false, null );
068        }
069    
070    
071        public IndexEnumeration( NamingEnumeration<Tuple> list, boolean swapKeyVal ) throws NamingException
072        {
073            this( list, swapKeyVal, null );
074        }
075    
076    
077        public IndexEnumeration( NamingEnumeration<Tuple> list, boolean swapKeyVal, Pattern regex ) 
078            throws NamingException
079        {
080            re = regex;
081            underlying = list;
082            this.swapKeyVal = swapKeyVal;
083    
084            if ( !underlying.hasMore() )
085            {
086                hasMore = false;
087                return;
088            }
089    
090            prefetch();
091        }
092    
093    
094        // ------------------------------------------------------------------------
095        // NamingEnumeration Interface Methods 
096        // ------------------------------------------------------------------------
097    
098        /**
099         * @see javax.naming.NamingEnumeration#next()
100         */
101        public IndexEntry next() throws NamingException
102        {
103            returned.copy( prefetched );
104            prefetch();
105            return returned;
106        }
107    
108    
109        /**
110         * @see java.util.Enumeration#nextElement()
111         */
112        public IndexEntry nextElement()
113        {
114            try
115            {
116                return next();
117            }
118            catch ( NamingException ne )
119            {
120                throw new NoSuchElementException();
121            }
122        }
123    
124    
125        /**
126         * @see javax.naming.NamingEnumeration#hasMore()
127         */
128        public boolean hasMore()
129        {
130            return hasMore;
131        }
132    
133    
134        /**
135         * @see javax.naming.NamingEnumeration#hasMoreElements()
136         */
137        public boolean hasMoreElements()
138        {
139            return hasMore;
140        }
141    
142    
143        /**
144         * @see javax.naming.NamingEnumeration#close()
145         */
146        public void close() throws NamingException
147        {
148            hasMore = false;
149            underlying.close();
150        }
151    
152    
153        // ------------------------------------------------------------------------
154        // Private Methods 
155        // ------------------------------------------------------------------------
156    
157    
158        private void prefetch() throws NamingException
159        {
160            while ( underlying.hasMore() )
161            {
162                Tuple tuple = underlying.next();
163    
164                if ( swapKeyVal )
165                {
166                    throw new NotImplementedException();
167                    // tmp.setSwapped( tuple, null );
168                }
169                else
170                {
171                    tmp.setTuple( tuple, null );
172                }
173    
174                // If regex is null just transfer into prefetched from tmp record
175                // but if it is not then use it to match.  Successful match shorts
176                // while loop.
177                if ( null == re || re.matcher( ( String ) tmp.getValue() ).matches() )
178                {
179                    prefetched.copy( tmp );
180                    return;
181                }
182            }
183    
184            // If we got down here then cursor has been consumed without a match!
185            hasMore = false;
186        }
187    }