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  }