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.operation; 023 024import java.beans.ConstructorProperties; 025import java.io.PrintStream; 026 027import cascading.flow.FlowProcess; 028 029/** 030 * Class Debug is a {@link Filter} that will never remove an item from a stream, but will print the Tuple to either 031 * stdout or stderr. 032 * <p> 033 * Currently, if printFields is true, they will print every 10 Tuples. 034 * <p> 035 * The frequency that fields and tuples are printed can be set via {@link #setPrintFieldsEvery(int)} and 036 * {@link #setPrintTupleEvery(int)} methods, respectively. 037 */ 038@SuppressWarnings({"UseOfSystemOutOrSystemErr"}) 039public class Debug extends BaseOperation<Long> implements Filter<Long>, PlannedOperation<Long> 040 { 041 static public enum Output 042 { 043 STDOUT, STDERR 044 } 045 046 /** Field output */ 047 private Output output = Output.STDERR; 048 /** Field prefix */ 049 private String prefix = null; 050 /** Field printFields */ 051 private boolean printFields = false; 052 053 /** Field printFieldsEvery */ 054 private int printFieldsEvery = 10; 055 /** Field printTupleEvery */ 056 private int printTupleEvery = 1; 057 058 /** 059 * Constructor Debug creates a new Debug instance that prints to stderr by default, and does not print 060 * the Tuple instance field names. 061 */ 062 public Debug() 063 { 064 } 065 066 /** 067 * Constructor Debug creates a new Debug instance that prints to stderr by default, and does not print 068 * the Tuple instance field names. 069 * 070 * @param prefix of type String 071 */ 072 @ConstructorProperties({"prefix"}) 073 public Debug( String prefix ) 074 { 075 this.prefix = prefix; 076 } 077 078 /** 079 * Constructor Debug creates a new Debug instance that prints to stderr and will print the current 080 * Tuple instance field names if printFields is true. 081 * 082 * @param prefix of type String 083 * @param printFields of type boolean 084 */ 085 @ConstructorProperties({"prefix", "printFields"}) 086 public Debug( String prefix, boolean printFields ) 087 { 088 this.prefix = prefix; 089 this.printFields = printFields; 090 } 091 092 /** 093 * Constructor Debug creates a new Debug instance that prints to stderr and will print the current 094 * Tuple instance field names if printFields is true. 095 * 096 * @param printFields of type boolean 097 */ 098 @ConstructorProperties({"printFields"}) 099 public Debug( boolean printFields ) 100 { 101 this.printFields = printFields; 102 } 103 104 /** 105 * Constructor Debug creates a new Debug instance that prints to the declared stream and does not print the Tuple 106 * field names. 107 * 108 * @param output of type Output 109 */ 110 @ConstructorProperties({"output"}) 111 public Debug( Output output ) 112 { 113 this.output = output; 114 } 115 116 /** 117 * Constructor Debug creates a new Debug instance that prints to the declared stream and does not print the Tuple 118 * field names. 119 * 120 * @param output of type Output 121 * @param prefix of type String 122 */ 123 @ConstructorProperties({"output", "prefix"}) 124 public Debug( Output output, String prefix ) 125 { 126 this.output = output; 127 this.prefix = prefix; 128 } 129 130 /** 131 * Constructor Debug creates a new Debug instance that prints to the declared stream and will print the Tuple instances 132 * field names if printFields is true. 133 * 134 * @param output of type Output 135 * @param prefix of type String 136 * @param printFields of type boolean 137 */ 138 @ConstructorProperties({"output", "prefix", "printFields"}) 139 public Debug( Output output, String prefix, boolean printFields ) 140 { 141 this.output = output; 142 this.prefix = prefix; 143 this.printFields = printFields; 144 } 145 146 /** 147 * Constructor Debug creates a new Debug instance that prints to the declared stream and will print the Tuple instances 148 * field names if printFields is true. 149 * 150 * @param output of type Output 151 * @param printFields of type boolean 152 */ 153 @ConstructorProperties({"output", "printFields"}) 154 public Debug( Output output, boolean printFields ) 155 { 156 this.output = output; 157 this.printFields = printFields; 158 } 159 160 public Output getOutput() 161 { 162 return output; 163 } 164 165 public String getPrefix() 166 { 167 return prefix; 168 } 169 170 public boolean isPrintFields() 171 { 172 return printFields; 173 } 174 175 /** 176 * Method getPrintFieldsEvery returns the printFieldsEvery interval value of this Debug object. 177 * 178 * @return the printFieldsEvery (type int) of this Debug object. 179 */ 180 public int getPrintFieldsEvery() 181 { 182 return printFieldsEvery; 183 } 184 185 /** 186 * Method setPrintFieldsEvery sets the printFieldsEvery interval value of this Debug object. 187 * 188 * @param printFieldsEvery the printFieldsEvery of this Debug object. 189 */ 190 public void setPrintFieldsEvery( int printFieldsEvery ) 191 { 192 this.printFieldsEvery = printFieldsEvery; 193 } 194 195 /** 196 * Method getPrintTupleEvery returns the printTupleEvery interval value of this Debug object. 197 * 198 * @return the printTupleEvery (type int) of this Debug object. 199 */ 200 public int getPrintTupleEvery() 201 { 202 return printTupleEvery; 203 } 204 205 /** 206 * Method setPrintTupleEvery sets the printTupleEvery interval value of this Debug object. 207 * 208 * @param printTupleEvery the printTupleEvery of this Debug object. 209 */ 210 public void setPrintTupleEvery( int printTupleEvery ) 211 { 212 this.printTupleEvery = printTupleEvery; 213 } 214 215 @Override 216 public boolean supportsPlannerLevel( PlannerLevel plannerLevel ) 217 { 218 return plannerLevel instanceof DebugLevel; 219 } 220 221 @Override 222 public void prepare( FlowProcess flowProcess, OperationCall<Long> operationCall ) 223 { 224 super.prepare( flowProcess, operationCall ); 225 226 operationCall.setContext( 0L ); 227 } 228 229 /** @see Filter#isRemove(cascading.flow.FlowProcess, FilterCall) */ 230 public boolean isRemove( FlowProcess flowProcess, FilterCall<Long> filterCall ) 231 { 232 PrintStream stream = output == Output.STDOUT ? System.out : System.err; 233 234 if( printFields && filterCall.getContext() % printFieldsEvery == 0 ) 235 print( stream, filterCall.getArguments().getFields().print() ); 236 237 if( filterCall.getContext() % printTupleEvery == 0 ) 238 print( stream, filterCall.getArguments().getTuple().print() ); 239 240 filterCall.setContext( filterCall.getContext() + 1 ); 241 242 return false; 243 } 244 245 @Override 246 public void cleanup( FlowProcess flowProcess, OperationCall<Long> longOperationCall ) 247 { 248 if( longOperationCall.getContext() == null ) 249 return; 250 251 PrintStream stream = output == Output.STDOUT ? System.out : System.err; 252 253 print( stream, "tuples count: " + longOperationCall.getContext().toString() ); 254 } 255 256 private void print( PrintStream stream, String message ) 257 { 258 if( prefix != null ) 259 { 260 stream.print( prefix ); 261 stream.print( ": " ); 262 } 263 264 stream.println( message ); 265 } 266 267 @Override 268 public boolean equals( Object object ) 269 { 270 if( this == object ) 271 return true; 272 if( !( object instanceof Debug ) ) 273 return false; 274 if( !super.equals( object ) ) 275 return false; 276 277 Debug debug = (Debug) object; 278 279 if( printFields != debug.printFields ) 280 return false; 281 if( printFieldsEvery != debug.printFieldsEvery ) 282 return false; 283 if( printTupleEvery != debug.printTupleEvery ) 284 return false; 285 if( output != debug.output ) 286 return false; 287 if( prefix != null ? !prefix.equals( debug.prefix ) : debug.prefix != null ) 288 return false; 289 290 return true; 291 } 292 293 @Override 294 public int hashCode() 295 { 296 int result = super.hashCode(); 297 result = 31 * result + ( output != null ? output.hashCode() : 0 ); 298 result = 31 * result + ( prefix != null ? prefix.hashCode() : 0 ); 299 result = 31 * result + ( printFields ? 1 : 0 ); 300 result = 31 * result + printFieldsEvery; 301 result = 31 * result + printTupleEvery; 302 return result; 303 } 304 }