001/* 002 * Copyright (c) 2016-2018 Chris K Wensel <chris@wensel.net>. All Rights Reserved. 003 * 004 * Project and contact information: http://www.cascading.org/ 005 * 006 * This file is part of the Cascading project. 007 * 008 * Licensed under the Apache License, Version 2.0 (the "License"); 009 * you may not use this file except in compliance with the License. 010 * You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, software 015 * distributed under the License is distributed on an "AS IS" BASIS, 016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 017 * See the License for the specific language governing permissions and 018 * limitations under the License. 019 */ 020 021package cascading.tap; 022 023import java.beans.ConstructorProperties; 024import java.io.IOException; 025import java.util.Set; 026import java.util.function.Function; 027 028import cascading.flow.Flow; 029import cascading.flow.FlowProcess; 030import cascading.flow.planner.Scope; 031import cascading.property.ConfigDef; 032import cascading.scheme.Scheme; 033import cascading.tuple.Fields; 034import cascading.tuple.TupleEntryCollector; 035import cascading.tuple.TupleEntryIterator; 036import cascading.util.Util; 037 038/** 039 * Class AdaptorTap wraps a given {@link Tap} instance, delegating all calls to the original. In addition, AdaptorTap 040 * implementations must provide {@link Function} implementations that will adapt one Config and {@link FlowProcess} 041 * type from the current platform types to the underlying Tap platform types. 042 */ 043public class AdaptorTap<TConfig, TInput, TOutput, OConfig, OInput, OOutput> extends Tap<TConfig, TInput, TOutput> 044 { 045 protected Tap<OConfig, OInput, OOutput> original; 046 protected Function<FlowProcess<? extends TConfig>, FlowProcess<? extends OConfig>> processProvider; 047 protected Function<TConfig, OConfig> configProvider; 048 049 @ConstructorProperties({"original", "processProvider", "configProvider"}) 050 public AdaptorTap( Tap<OConfig, OInput, OOutput> original, Function<FlowProcess<? extends TConfig>, FlowProcess<? extends OConfig>> processProvider, Function<TConfig, OConfig> configProvider ) 051 { 052 setOriginal( original ); 053 054 if( processProvider == null ) 055 throw new IllegalArgumentException( "processProvider may not be null" ); 056 057 if( configProvider == null ) 058 throw new IllegalArgumentException( "confProvider may not be null" ); 059 060 this.processProvider = processProvider; 061 this.configProvider = configProvider; 062 } 063 064 public Tap<OConfig, OInput, OOutput> getOriginal() 065 { 066 return original; 067 } 068 069 protected void setOriginal( Tap<OConfig, OInput, OOutput> original ) 070 { 071 if( original == null ) 072 throw new IllegalArgumentException( "wrapped tap value may not be null" ); 073 074 this.original = original; 075 } 076 077 @Override 078 public Scheme<TConfig, TInput, TOutput, ?, ?> getScheme() 079 { 080 throw new UnsupportedOperationException( "cannot retrieve Scheme" ); 081 } 082 083 @Override 084 public String getTrace() 085 { 086 return original.getTrace(); 087 } 088 089 @Override 090 public void flowConfInit( Flow<TConfig> flow ) 091 { 092 // do nothing 093 } 094 095 @Override 096 public void sourceConfInit( FlowProcess<? extends TConfig> flowProcess, TConfig conf ) 097 { 098 original.sourceConfInit( processProvider.apply( flowProcess ), configProvider.apply( conf ) ); 099 } 100 101 @Override 102 public void sinkConfInit( FlowProcess<? extends TConfig> flowProcess, TConfig conf ) 103 { 104 original.sinkConfInit( processProvider.apply( flowProcess ), configProvider.apply( conf ) ); 105 } 106 107 @Override 108 public String getIdentifier() 109 { 110 return original.getIdentifier(); 111 } 112 113 @Override 114 public Fields getSourceFields() 115 { 116 return original.getSourceFields(); 117 } 118 119 @Override 120 public Fields getSinkFields() 121 { 122 return original.getSinkFields(); 123 } 124 125 @Override 126 public TupleEntryIterator openForRead( FlowProcess<? extends TConfig> flowProcess, TInput input ) throws IOException 127 { 128 return original.openForRead( processProvider.apply( flowProcess ), null ); 129 } 130 131 @Override 132 public TupleEntryIterator openForRead( FlowProcess<? extends TConfig> flowProcess ) throws IOException 133 { 134 return original.openForRead( processProvider.apply( flowProcess ) ); 135 } 136 137 @Override 138 public TupleEntryCollector openForWrite( FlowProcess<? extends TConfig> flowProcess, TOutput output ) throws IOException 139 { 140 return original.openForWrite( processProvider.apply( flowProcess ), null ); 141 } 142 143 @Override 144 public TupleEntryCollector openForWrite( FlowProcess<? extends TConfig> flowProcess ) throws IOException 145 { 146 return original.openForWrite( processProvider.apply( flowProcess ) ); 147 } 148 149 @Override 150 public Scope outgoingScopeFor( Set<Scope> incomingScopes ) 151 { 152 return original.outgoingScopeFor( incomingScopes ); 153 } 154 155 @Override 156 public Fields retrieveSourceFields( FlowProcess<? extends TConfig> flowProcess ) 157 { 158 return original.retrieveSourceFields( processProvider.apply( flowProcess ) ); 159 } 160 161 @Override 162 public void presentSourceFields( FlowProcess<? extends TConfig> flowProcess, Fields fields ) 163 { 164 original.presentSourceFields( processProvider.apply( flowProcess ), fields ); 165 } 166 167 @Override 168 public Fields retrieveSinkFields( FlowProcess<? extends TConfig> flowProcess ) 169 { 170 return original.retrieveSinkFields( processProvider.apply( flowProcess ) ); 171 } 172 173 @Override 174 public void presentSinkFields( FlowProcess<? extends TConfig> flowProcess, Fields fields ) 175 { 176 original.presentSinkFields( processProvider.apply( flowProcess ), fields ); 177 } 178 179 @Override 180 public Fields resolveIncomingOperationArgumentFields( Scope incomingScope ) 181 { 182 return original.resolveIncomingOperationArgumentFields( incomingScope ); 183 } 184 185 @Override 186 public Fields resolveIncomingOperationPassThroughFields( Scope incomingScope ) 187 { 188 return original.resolveIncomingOperationPassThroughFields( incomingScope ); 189 } 190 191 @Override 192 public String getFullIdentifier( FlowProcess<? extends TConfig> flowProcess ) 193 { 194 return original.getFullIdentifier( processProvider.apply( flowProcess ) ); 195 } 196 197 @Override 198 public String getFullIdentifier( TConfig conf ) 199 { 200 return original.getFullIdentifier( configProvider.apply( conf ) ); 201 } 202 203 @Override 204 public boolean createResource( FlowProcess<? extends TConfig> flowProcess ) throws IOException 205 { 206 return original.createResource( processProvider.apply( flowProcess ) ); 207 } 208 209 @Override 210 public boolean createResource( TConfig conf ) throws IOException 211 { 212 return original.createResource( configProvider.apply( conf ) ); 213 } 214 215 @Override 216 public boolean deleteResource( FlowProcess<? extends TConfig> flowProcess ) throws IOException 217 { 218 return original.deleteResource( processProvider.apply( flowProcess ) ); 219 } 220 221 @Override 222 public boolean deleteResource( TConfig conf ) throws IOException 223 { 224 return original.deleteResource( configProvider.apply( conf ) ); 225 } 226 227 @Override 228 public boolean prepareResourceForRead( TConfig conf ) throws IOException 229 { 230 return original.prepareResourceForRead( configProvider.apply( conf ) ); 231 } 232 233 @Override 234 public boolean prepareResourceForWrite( TConfig conf ) throws IOException 235 { 236 return original.prepareResourceForWrite( configProvider.apply( conf ) ); 237 } 238 239 @Override 240 public boolean commitResource( TConfig conf ) throws IOException 241 { 242 return original.commitResource( configProvider.apply( conf ) ); 243 } 244 245 @Override 246 public boolean rollbackResource( TConfig conf ) throws IOException 247 { 248 return original.rollbackResource( configProvider.apply( conf ) ); 249 } 250 251 @Override 252 public boolean resourceExists( FlowProcess<? extends TConfig> flowProcess ) throws IOException 253 { 254 return original.resourceExists( processProvider.apply( flowProcess ) ); 255 } 256 257 @Override 258 public boolean resourceExists( TConfig conf ) throws IOException 259 { 260 return original.resourceExists( configProvider.apply( conf ) ); 261 } 262 263 @Override 264 public long getModifiedTime( FlowProcess<? extends TConfig> flowProcess ) throws IOException 265 { 266 return original.getModifiedTime( processProvider.apply( flowProcess ) ); 267 } 268 269 @Override 270 public long getModifiedTime( TConfig conf ) throws IOException 271 { 272 return original.getModifiedTime( configProvider.apply( conf ) ); 273 } 274 275 @Override 276 public SinkMode getSinkMode() 277 { 278 return original.getSinkMode(); 279 } 280 281 @Override 282 public boolean isKeep() 283 { 284 return original.isKeep(); 285 } 286 287 @Override 288 public boolean isReplace() 289 { 290 return original.isReplace(); 291 } 292 293 @Override 294 public boolean isUpdate() 295 { 296 return original.isUpdate(); 297 } 298 299 @Override 300 public boolean isSink() 301 { 302 return original.isSink(); 303 } 304 305 @Override 306 public boolean isSource() 307 { 308 return original.isSource(); 309 } 310 311 @Override 312 public boolean isTemporary() 313 { 314 return original.isTemporary(); 315 } 316 317 @Override 318 public ConfigDef getConfigDef() 319 { 320 return original.getConfigDef(); 321 } 322 323 @Override 324 public boolean hasConfigDef() 325 { 326 return original.hasConfigDef(); 327 } 328 329 @Override 330 public ConfigDef getNodeConfigDef() 331 { 332 return original.getNodeConfigDef(); 333 } 334 335 @Override 336 public boolean hasNodeConfigDef() 337 { 338 return original.hasNodeConfigDef(); 339 } 340 341 @Override 342 public ConfigDef getStepConfigDef() 343 { 344 return original.getStepConfigDef(); 345 } 346 347 @Override 348 public boolean hasStepConfigDef() 349 { 350 return original.hasStepConfigDef(); 351 } 352 353 @Override 354 public boolean equals( Object object ) 355 { 356 if( this == object ) 357 return true; 358 if( object == null || getClass() != object.getClass() ) 359 return false; 360 361 Tap tap = (Tap) object; 362 363 if( tap instanceof AdaptorTap ) 364 tap = ( (AdaptorTap) tap ).getOriginal(); 365 366 if( getIdentifier() != null ? !getIdentifier().equals( tap.getIdentifier() ) : tap.getIdentifier() != null ) 367 return false; 368 369 if( original.getScheme() != null ? !original.getScheme().equals( tap.getScheme() ) : tap.getScheme() != null ) 370 return false; 371 372 return true; 373 } 374 375 @Override 376 public int hashCode() 377 { 378 int result = getIdentifier() != null ? getIdentifier().hashCode() : 0; 379 380 result = 31 * result + ( original.getScheme() != null ? original.getScheme().hashCode() : 0 ); 381 382 return result; 383 } 384 385 @Override 386 public String toString() 387 { 388 if( getIdentifier() != null ) 389 return getClass().getSimpleName() + "[\"" + original.getScheme() + "\"]" + "[\"" + Util.sanitizeUrl( getIdentifier() ) + "\"]"; // sanitize 390 else 391 return getClass().getSimpleName() + "[\"" + original.getScheme() + "\"]" + "[not initialized]"; 392 } 393 }