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: 917231 $
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        public IndexEnumeration( NamingEnumeration<Tuple> list ) throws NamingException
065        {
066            this( list, false, null );
067        }
068    
069    
070        public IndexEnumeration( NamingEnumeration<Tuple> list, boolean swapKeyVal ) throws NamingException
071        {
072            this( list, swapKeyVal, null );
073        }
074    
075    
076        public IndexEnumeration( NamingEnumeration<Tuple> list, boolean swapKeyVal, Pattern regex ) throws NamingException
077        {
078            re = regex;
079            underlying = list;
080            this.swapKeyVal = swapKeyVal;
081    
082            if ( !underlying.hasMore() )
083            {
084                hasMore = false;
085                return;
086            }
087    
088            prefetch();
089        }
090    
091    
092        // ------------------------------------------------------------------------
093        // NamingEnumeration Interface Methods 
094        // ------------------------------------------------------------------------
095    
096        /**
097         * @see javax.naming.NamingEnumeration#next()
098         */
099        public IndexEntry next() throws NamingException
100        {
101            returned.copy( prefetched );
102            prefetch();
103            return returned;
104        }
105    
106    
107        /**
108         * @see java.util.Enumeration#nextElement()
109         */
110        public IndexEntry nextElement()
111        {
112            try
113            {
114                return next();
115            }
116            catch ( NamingException ne )
117            {
118                throw new NoSuchElementException();
119            }
120        }
121    
122    
123        /**
124         * @see javax.naming.NamingEnumeration#hasMore()
125         */
126        public boolean hasMore()
127        {
128            return hasMore;
129        }
130    
131    
132        /**
133         * @see javax.naming.NamingEnumeration#hasMoreElements()
134         */
135        public boolean hasMoreElements()
136        {
137            return hasMore;
138        }
139    
140    
141        /**
142         * @see javax.naming.NamingEnumeration#close()
143         */
144        public void close() throws NamingException
145        {
146            hasMore = false;
147            underlying.close();
148        }
149    
150    
151        // ------------------------------------------------------------------------
152        // Private Methods 
153        // ------------------------------------------------------------------------
154    
155        private void prefetch() throws NamingException
156        {
157            while ( underlying.hasMore() )
158            {
159                Tuple tuple = underlying.next();
160    
161                if ( swapKeyVal )
162                {
163                    throw new NotImplementedException();
164                    // tmp.setSwapped( tuple, null );
165                }
166                else
167                {
168                    tmp.setTuple( tuple, null );
169                }
170    
171                // If regex is null just transfer into prefetched from tmp record
172                // but if it is not then use it to match.  Successful match shorts
173                // while loop.
174                if ( null == re || re.matcher( ( String ) tmp.getValue() ).matches() )
175                {
176                    prefetched.copy( tmp );
177                    return;
178                }
179            }
180    
181            // If we got down here then cursor has been consumed without a match!
182            hasMore = false;
183        }
184    }