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 @Override 088 public boolean available() 089 { 090 return wrappedCursor.available(); 091 } 092 093 094 /** 095 * {@inheritDoc} 096 */ 097 @Override 098 public void before( IndexEntry<K, String> element ) throws LdapException, CursorException 099 { 100 wrappedCursor.before( element.getTuple() ); 101 } 102 103 104 /** 105 * {@inheritDoc} 106 */ 107 @Override 108 public void after( IndexEntry<K, String> element ) throws LdapException, CursorException 109 { 110 wrappedCursor.after( element.getTuple() ); 111 } 112 113 114 /** 115 * {@inheritDoc} 116 */ 117 public void beforeFirst() throws LdapException, CursorException 118 { 119 wrappedCursor.beforeFirst(); 120 } 121 122 123 /** 124 * {@inheritDoc} 125 */ 126 public void afterLast() throws LdapException, CursorException 127 { 128 wrappedCursor.afterLast(); 129 } 130 131 132 /** 133 * {@inheritDoc} 134 */ 135 public boolean first() throws LdapException, CursorException 136 { 137 return wrappedCursor.first(); 138 } 139 140 141 /** 142 * {@inheritDoc} 143 */ 144 public boolean last() throws LdapException, CursorException 145 { 146 return wrappedCursor.last(); 147 } 148 149 150 /** 151 * {@inheritDoc} 152 */ 153 @Override 154 public boolean isClosed() 155 { 156 return wrappedCursor.isClosed(); 157 } 158 159 160 /** 161 * {@inheritDoc} 162 */ 163 @Override 164 public boolean previous() throws LdapException, CursorException 165 { 166 return wrappedCursor.previous(); 167 } 168 169 170 /** 171 * {@inheritDoc} 172 */ 173 @Override 174 public boolean next() throws LdapException, CursorException 175 { 176 return wrappedCursor.next(); 177 } 178 179 180 /** 181 * {@inheritDoc} 182 */ 183 @SuppressWarnings("unchecked") 184 public IndexEntry<K, String> get() throws CursorException 185 { 186 Tuple<K, String> tuple = wrappedCursor.get(); 187 forwardEntry.setTuple( tuple ); 188 189 return forwardEntry; 190 } 191 192 193 @Override 194 public final void setClosureMonitor( ClosureMonitor monitor ) 195 { 196 wrappedCursor.setClosureMonitor( monitor ); 197 } 198 199 200 /** 201 * {@inheritDoc} 202 */ 203 @Override 204 public void close() throws IOException 205 { 206 if ( IS_DEBUG ) 207 { 208 LOG_CURSOR.debug( "Closing IndexCursorAdaptor {}", this ); 209 } 210 211 wrappedCursor.close(); 212 } 213 214 215 /** 216 * {@inheritDoc} 217 */ 218 @Override 219 public void close( Exception reason ) throws IOException 220 { 221 if ( IS_DEBUG ) 222 { 223 LOG_CURSOR.debug( "Closing IndexCursorAdaptor {}", this ); 224 } 225 226 wrappedCursor.close( reason ); 227 } 228 229 230 @Override 231 public Iterator<IndexEntry<K, String>> iterator() 232 { 233 return new CursorIterator<>( this ); 234 } 235 236 237 /** 238 * {@inheritDoc} 239 */ 240 @Override 241 public boolean isAfterLast() 242 { 243 throw new UnsupportedOperationException( I18n.err( I18n.ERR_13102_UNSUPPORTED_OPERATION, getClass().getName() 244 .concat( "." ).concat( "isAfterLast()" ) ) ); 245 } 246 247 248 /** 249 * {@inheritDoc} 250 */ 251 @Override 252 public boolean isBeforeFirst() 253 { 254 throw new UnsupportedOperationException( I18n.err( I18n.ERR_13102_UNSUPPORTED_OPERATION, getClass().getName() 255 .concat( "." ).concat( "isBeforeFirst()" ) ) ); 256 } 257 258 259 /** 260 * {@inheritDoc} 261 */ 262 @Override 263 public boolean isFirst() 264 { 265 throw new UnsupportedOperationException( I18n.err( I18n.ERR_13102_UNSUPPORTED_OPERATION, getClass().getName() 266 .concat( "." ).concat( "isFirst()" ) ) ); 267 } 268 269 270 /** 271 * {@inheritDoc} 272 */ 273 @Override 274 public boolean isLast() 275 { 276 throw new UnsupportedOperationException( I18n.err( I18n.ERR_13102_UNSUPPORTED_OPERATION, getClass().getName() 277 .concat( "." ).concat( "isLast()" ) ) ); 278 } 279 280 281 /** 282 * {@inheritDoc} 283 */ 284 protected String getUnsupportedMessage() 285 { 286 return UNSUPPORTED_MSG; 287 } 288 289 290 /** 291 * @see Object#toString() 292 */ 293 @Override 294 public String toString( String tabs ) 295 { 296 StringBuilder sb = new StringBuilder(); 297 298 sb.append( tabs ).append( "IndexCursorAdaptor (" ); 299 300 if ( available() ) 301 { 302 sb.append( "available)" ); 303 } 304 else 305 { 306 sb.append( "absent)" ); 307 } 308 309 sb.append( " :\n" ); 310 311 sb.append( wrappedCursor.toString( tabs + " " ) ); 312 313 return sb.toString(); 314 } 315 316 317 /** 318 * @see Object#toString() 319 */ 320 public String toString() 321 { 322 return toString( "" ); 323 } 324}