001/*
002 * Copyright (c) 2007-2017 Xplenty, Inc. 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.operation.assertion;
022
023import java.beans.ConstructorProperties;
024import java.util.regex.Matcher;
025
026import cascading.flow.FlowProcess;
027import cascading.operation.AssertionLevel;
028import cascading.operation.PlannerLevel;
029import cascading.operation.ValueAssertion;
030import cascading.operation.ValueAssertionCall;
031import cascading.operation.regex.RegexMatcher;
032import cascading.tuple.TupleEntry;
033
034/**
035 * Class AssertMatchesAll matches the given regular expression patternString against each argument
036 * {@link cascading.tuple.Tuple} element individually. See {@link AssertMatches} if you need to match the patternString regex against
037 * the tuple as a whole.
038 * <p/>
039 * This operation uses {@link java.util.regex.Matcher} internally, specifically the method {@link java.util.regex.Matcher#find()}.
040 * <p/>
041 * Note a {@code null} valued argument passed to the parser will be converted to an empty string ({@code ""}) before
042 * the regex is applied.
043 * <p/>
044 * Any Object value will be coerced to a String type via any provided {@link cascading.tuple.type.CoercibleType} on
045 * the argument selector or via its {@code toString()} method.
046 *
047 * @see java.util.regex.Matcher
048 * @see java.util.regex.Pattern
049 */
050public class AssertMatchesAll extends RegexMatcher implements ValueAssertion<Matcher>
051  {
052  /** Field message */
053  private final static String message = "argument '%s' value was: %s, did not match: %s, in tuple: %s";
054
055  /**
056   * Constructor AssertMatchesAll creates a new AssertMatchesAll instance.
057   *
058   * @param patternString of type String
059   */
060  @ConstructorProperties({"patternString"})
061  public AssertMatchesAll( String patternString )
062    {
063    super( patternString, false );
064    }
065
066  /**
067   * Constructor AssertMatchesAll creates a new AssertMatchesAll instance.
068   *
069   * @param patternString of type String
070   * @param negateMatch   of type boolean
071   */
072  @ConstructorProperties({"patternString", "negateMatch"})
073  public AssertMatchesAll( String patternString, boolean negateMatch )
074    {
075    super( patternString, negateMatch );
076    }
077
078  @Override
079  public boolean supportsPlannerLevel( PlannerLevel plannerLevel )
080    {
081    return plannerLevel instanceof AssertionLevel;
082    }
083
084  @Override
085  public void doAssert( FlowProcess flowProcess, ValueAssertionCall<Matcher> assertionCall )
086    {
087    TupleEntry input = assertionCall.getArguments();
088
089    int pos = matchEachElementPos( assertionCall.getContext(), input );
090
091    if( pos != -1 )
092      BaseAssertion.throwFail( message, input.getFields().get( pos ), input.getObject( pos ), patternString, input.getTuple().print() );
093    }
094  }