/* * Copyright (c) 2007-2010 Concurrent, Inc. All Rights Reserved. * * Project and contact information: http://www.cascading.org/ * * This file is part of the Cascading project. * * Cascading is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Cascading is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Cascading. If not, see <http://www.gnu.org/licenses/>. */ package cascading.operation.assertion; import java.beans.ConstructorProperties; import java.util.regex.Matcher; import java.util.regex.Pattern; import cascading.flow.FlowProcess; import cascading.operation.GroupAssertion; import cascading.operation.GroupAssertionCall; import cascading.operation.OperationCall; import cascading.tuple.Tuple; import cascading.tuple.TupleEntry; import org.apache.log4j.Logger; /** * */ public abstract class AssertGroupBase extends BaseAssertion<AssertGroupBase.Context> implements GroupAssertion<AssertGroupBase.Context> { /** Field LOG */ private static final Logger LOG = Logger.getLogger( AssertGroupBase.class ); /** Field patternString */ protected String patternString; /** Field size */ protected long size; public static class Context { Pattern pattern; Long count; String fields; String group; public Context set( long count, String fields, String group ) { this.count = count; this.fields = fields; this.group = group; return this; } public Context reset() { count = null; fields = null; group = null; return this; } } @ConstructorProperties({"message", "size"}) public AssertGroupBase( String message, long size ) { super( message ); this.size = size; } @ConstructorProperties({"message", "patternString", "size"}) protected AssertGroupBase( String message, String patternString, long size ) { super( message ); this.patternString = patternString; this.size = size; } private Pattern getPattern() { Pattern pattern = null; if( patternString == null ) pattern = Pattern.compile( ".*" ); else pattern = Pattern.compile( patternString ); return pattern; } private boolean matchWholeTuple( Tuple input, Pattern pattern ) { if( patternString == null ) return true; Matcher matcher = pattern.matcher( input.toString( "\t" ) ); if( LOG.isDebugEnabled() ) LOG.debug( "pattern: " + pattern + ", matches: " + matcher.matches() ); return matcher.matches(); } @Override public void prepare( FlowProcess flowProcess, OperationCall<Context> operationCall ) { operationCall.setContext( new Context() ); operationCall.getContext().pattern = getPattern(); } public void start( FlowProcess flowProcess, GroupAssertionCall<Context> assertionCall ) { TupleEntry groupEntry = assertionCall.getGroup(); Context context = assertionCall.getContext(); // didn't match, so skip if( !matchWholeTuple( groupEntry.getTuple(), context.pattern ) ) context.reset(); else context.set( 0L, groupEntry.getFields().print(), groupEntry.getTuple().print() ); } public void aggregate( FlowProcess flowProcess, GroupAssertionCall<Context> assertionCall ) { Long groupSize = (Long) assertionCall.getContext().count; // didn't match, so skip if( groupSize != null ) assertionCall.getContext().count += 1L; } public void doAssert( FlowProcess flowProcess, GroupAssertionCall<Context> assertionCall ) { Context context = assertionCall.getContext(); Long groupSize = context.count; if( groupSize == null ) // didn't match, so skip return; if( assertFails( groupSize ) ) { if( patternString == null ) fail( groupSize, size, context.fields, context.group ); else fail( patternString, groupSize, size, context.fields, context.group ); } } protected abstract boolean assertFails( Long groupSize ); @Override public boolean equals( Object object ) { if( this == object ) return true; if( !( object instanceof AssertGroupBase ) ) return false; if( !super.equals( object ) ) return false; AssertGroupBase that = (AssertGroupBase) object; if( size != that.size ) return false; if( patternString != null ? !patternString.equals( that.patternString ) : that.patternString != null ) return false; return true; } @Override public int hashCode() { int result = super.hashCode(); result = 31 * result + ( patternString != null ? patternString.hashCode() : 0 ); result = 31 * result + (int) ( size ^ ( size >>> 32 ) ); return result; } }