001/* 002 * Copyright (c) 2016-2017 Chris K Wensel <chris@wensel.net>. All Rights Reserved. 003 * Copyright (c) 2007-2017 Xplenty, Inc. All Rights Reserved. 004 * 005 * Project and contact information: http://www.cascading.org/ 006 * 007 * This file is part of the Cascading project. 008 * 009 * Licensed under the Apache License, Version 2.0 (the "License"); 010 * you may not use this file except in compliance with the License. 011 * You may obtain a copy of the License at 012 * 013 * http://www.apache.org/licenses/LICENSE-2.0 014 * 015 * Unless required by applicable law or agreed to in writing, software 016 * distributed under the License is distributed on an "AS IS" BASIS, 017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 018 * See the License for the specific language governing permissions and 019 * limitations under the License. 020 */ 021 022package cascading.pipe.joiner; 023 024import java.beans.ConstructorProperties; 025import java.util.Arrays; 026import java.util.Iterator; 027 028import cascading.tuple.Fields; 029import cascading.tuple.Tuple; 030 031/** 032 * Class MixedJoin will return an {@link java.util.Iterator} that will iterate over a given 033 * {@link Joiner} and return tuples that represent a join as defined by the given boolean array. 034 * <p> 035 * So if joining three streams, {@code boolean []{true,false,false}} will result in a 'inner', 'outer', 'outer' join. 036 * <p> 037 * Joins perform based on the equality of the join keys. In the case of null values, Java treats two 038 * null values as equivalent. SQL does not treat null values as equal. To produce SQL like results in a given 039 * join, a new {@link java.util.Comparator} will need to be used on the joined values to prevent null from 040 * equaling null. As a convenience, see the {@link cascading.util.NullNotEquivalentComparator} class. 041 */ 042public class MixedJoin extends BaseJoiner 043 { 044 /** Field INNER */ 045 public static boolean INNER = true; 046 /** Field OUTER */ 047 public static boolean OUTER = false; 048 049 final boolean[] asInner; 050 051 /** 052 * Constructor MixedJoin creates a new MixedJoin instance. 053 * 054 * @param asInner of type boolean[] 055 */ 056 @ConstructorProperties({"asInner"}) 057 public MixedJoin( boolean[] asInner ) 058 { 059 this.asInner = Arrays.copyOf( asInner, asInner.length ); 060 } 061 062 @ConstructorProperties({"fieldDeclaration", "asInner"}) 063 public MixedJoin( Fields fieldDeclaration, boolean[] asInner ) 064 { 065 super( fieldDeclaration ); 066 this.asInner = asInner; 067 } 068 069 /** @see Joiner#numJoins() */ 070 public int numJoins() 071 { 072 return asInner.length - 1; 073 } 074 075 public Iterator<Tuple> getIterator( JoinerClosure closure ) 076 { 077 return new JoinIterator( closure ); 078 } 079 080 public class JoinIterator extends OuterJoin.JoinIterator 081 { 082 public JoinIterator( JoinerClosure closure ) 083 { 084 super( closure ); 085 } 086 087 @Override 088 protected boolean isOuter( int i ) 089 { 090 return !asInner[ i ] && super.isOuter( i ); 091 } 092 } 093 }