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