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.server.core.partition.impl.btree; 021 022 023import java.io.IOException; 024import java.util.Iterator; 025 026import org.apache.directory.api.i18n.I18n; 027import org.apache.directory.api.ldap.model.constants.Loggers; 028import org.apache.directory.api.ldap.model.cursor.ClosureMonitor; 029import org.apache.directory.api.ldap.model.cursor.Cursor; 030import org.apache.directory.api.ldap.model.cursor.CursorException; 031import org.apache.directory.api.ldap.model.cursor.CursorIterator; 032import org.apache.directory.api.ldap.model.cursor.Tuple; 033import org.apache.directory.api.ldap.model.exception.LdapException; 034import org.apache.directory.server.core.api.partition.PartitionTxn; 035import org.apache.directory.server.xdbm.AbstractIndexCursor; 036import org.apache.directory.server.xdbm.IndexEntry; 037import org.slf4j.Logger; 038import org.slf4j.LoggerFactory; 039 040 041/** 042 * A Cursor which adapts an underlying Tuple based Cursor to one which returns 043 * IndexEntry objects rather than tuples. 044 * 045 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 046 */ 047public class IndexCursorAdaptor<K> extends AbstractIndexCursor<K> 048{ 049 /** A dedicated log for cursors */ 050 private static final Logger LOG_CURSOR = LoggerFactory.getLogger( Loggers.CURSOR_LOG.getName() ); 051 052 /** Speedup for logs */ 053 private static final boolean IS_DEBUG = LOG_CURSOR.isDebugEnabled(); 054 055 @SuppressWarnings("unchecked") 056 final Cursor<Tuple> wrappedCursor; 057 final IndexEntry<K, String> forwardEntry; 058 059 060 /** 061 * Creates an IndexCursorAdaptor which wraps and adapts a Cursor from a table to 062 * one which returns an IndexEntry. 063 * 064 * @param partitionTxn The transaction to use 065 * @param wrappedCursor the Cursor being adapted 066 * @param forwardIndex true for a cursor over a forward index, false for 067 * one over a reverse index 068 */ 069 @SuppressWarnings("unchecked") 070 public IndexCursorAdaptor( PartitionTxn partitionTxn, Cursor<Tuple> wrappedCursor, boolean forwardIndex ) 071 { 072 this.wrappedCursor = wrappedCursor; 073 074 forwardEntry = new IndexEntry<>(); 075 this.partitionTxn = partitionTxn; 076 077 if ( IS_DEBUG ) 078 { 079 LOG_CURSOR.debug( "Creating IndexCursorAdaptor {}", this ); 080 } 081 } 082 083 084 /** 085 * {@inheritDoc} 086 */ 087 public boolean available() 088 { 089 return wrappedCursor.available(); 090 } 091 092 093 /** 094 * {@inheritDoc} 095 */ 096 public void before( IndexEntry<K, String> element ) throws LdapException, CursorException 097 { 098 wrappedCursor.before( element.getTuple() ); 099 } 100 101 102 /** 103 * {@inheritDoc} 104 */ 105 public void after( IndexEntry<K, String> element ) throws LdapException, CursorException 106 { 107 wrappedCursor.after( element.getTuple() ); 108 } 109 110 111 /** 112 * {@inheritDoc} 113 */ 114 public void beforeFirst() throws LdapException, CursorException 115 { 116 wrappedCursor.beforeFirst(); 117 } 118 119 120 /** 121 * {@inheritDoc} 122 */ 123 public void afterLast() throws LdapException, CursorException 124 { 125 wrappedCursor.afterLast(); 126 } 127 128 129 /** 130 * {@inheritDoc} 131 */ 132 public boolean first() throws LdapException, CursorException 133 { 134 return wrappedCursor.first(); 135 } 136 137 138 /** 139 * {@inheritDoc} 140 */ 141 public boolean last() throws LdapException, CursorException 142 { 143 return wrappedCursor.last(); 144 } 145 146 147 /** 148 * {@inheritDoc} 149 */ 150 public boolean isClosed() 151 { 152 return wrappedCursor.isClosed(); 153 } 154 155 156 /** 157 * {@inheritDoc} 158 */ 159 public boolean previous() throws LdapException, CursorException 160 { 161 return wrappedCursor.previous(); 162 } 163 164 165 /** 166 * {@inheritDoc} 167 */ 168 public boolean next() throws LdapException, CursorException 169 { 170 return wrappedCursor.next(); 171 } 172 173 174 /** 175 * {@inheritDoc} 176 */ 177 @SuppressWarnings("unchecked") 178 public IndexEntry<K, String> get() throws CursorException 179 { 180 Tuple<K, String> tuple = wrappedCursor.get(); 181 forwardEntry.setTuple( tuple ); 182 183 return forwardEntry; 184 } 185 186 187 public final void setClosureMonitor( ClosureMonitor monitor ) 188 { 189 wrappedCursor.setClosureMonitor( monitor ); 190 } 191 192 193 /** 194 * {@inheritDoc} 195 */ 196 public void close() throws IOException 197 { 198 if ( IS_DEBUG ) 199 { 200 LOG_CURSOR.debug( "Closing IndexCursorAdaptor {}", this ); 201 } 202 203 wrappedCursor.close(); 204 } 205 206 207 /** 208 * {@inheritDoc} 209 */ 210 public void close( Exception reason ) throws IOException 211 { 212 if ( IS_DEBUG ) 213 { 214 LOG_CURSOR.debug( "Closing IndexCursorAdaptor {}", this ); 215 } 216 217 wrappedCursor.close( reason ); 218 } 219 220 221 public Iterator<IndexEntry<K, String>> iterator() 222 { 223 return new CursorIterator<IndexEntry<K, String>>( this ); 224 } 225 226 227 /** 228 * {@inheritDoc} 229 */ 230 public boolean isAfterLast() 231 { 232 throw new UnsupportedOperationException( I18n.err( I18n.ERR_13102_UNSUPPORTED_OPERATION, getClass().getName() 233 .concat( "." ).concat( "isAfterLast()" ) ) ); 234 } 235 236 237 /** 238 * {@inheritDoc} 239 */ 240 public boolean isBeforeFirst() 241 { 242 throw new UnsupportedOperationException( I18n.err( I18n.ERR_13102_UNSUPPORTED_OPERATION, getClass().getName() 243 .concat( "." ).concat( "isBeforeFirst()" ) ) ); 244 } 245 246 247 /** 248 * {@inheritDoc} 249 */ 250 public boolean isFirst() 251 { 252 throw new UnsupportedOperationException( I18n.err( I18n.ERR_13102_UNSUPPORTED_OPERATION, getClass().getName() 253 .concat( "." ).concat( "isFirst()" ) ) ); 254 } 255 256 257 /** 258 * {@inheritDoc} 259 */ 260 public boolean isLast() 261 { 262 throw new UnsupportedOperationException( I18n.err( I18n.ERR_13102_UNSUPPORTED_OPERATION, getClass().getName() 263 .concat( "." ).concat( "isLast()" ) ) ); 264 } 265 266 267 /** 268 * {@inheritDoc} 269 */ 270 protected String getUnsupportedMessage() 271 { 272 return UNSUPPORTED_MSG; 273 } 274 275 276 /** 277 * @see Object#toString() 278 */ 279 public String toString( String tabs ) 280 { 281 StringBuilder sb = new StringBuilder(); 282 283 sb.append( tabs ).append( "IndexCursorAdaptor (" ); 284 285 if ( available() ) 286 { 287 sb.append( "available)" ); 288 } 289 else 290 { 291 sb.append( "absent)" ); 292 } 293 294 sb.append( " :\n" ); 295 296 sb.append( wrappedCursor.toString( tabs + " " ) ); 297 298 return sb.toString(); 299 } 300 301 302 /** 303 * @see Object#toString() 304 */ 305 public String toString() 306 { 307 return toString( "" ); 308 } 309}