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 AssertMatches matches the given regular expression patternString against the whole argument
036 * {@link cascading.tuple.Tuple} by joining each individual element of the Tuple with a tab character (\t) unless
037 * otherwise specified.
038 * See {@link AssertMatchesAll} if you need to match the patternString regex against each individual tuple element.
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 AssertMatches extends RegexMatcher implements ValueAssertion<Matcher>
052  {
053  /** Field message */
054  private final static String message = "argument tuple: %s did not match: %s";
055
056  /**
057   * Constructor AssertMatches creates a new AssertMatches instance.
058   *
059   * @param patternString of type String
060   */
061  @ConstructorProperties({"patternString"})
062  public AssertMatches( String patternString )
063    {
064    super( patternString, false );
065    }
066
067  /**
068   * Constructor AssertMatches creates a new AssertMatches instance.
069   *
070   * @param patternString of type String
071   * @param delimiter     of type String
072   */
073  @ConstructorProperties({"patternString", "delimiter"})
074  public AssertMatches( String patternString, String delimiter )
075    {
076    super( patternString, false, delimiter );
077    }
078
079  /**
080   * Constructor AssertMatches creates a new AssertMatches instance.
081   *
082   * @param patternString of type String
083   * @param negateMatch   of type boolean
084   */
085  @ConstructorProperties({"patternString", "negateMatch"})
086  public AssertMatches( String patternString, boolean negateMatch )
087    {
088    super( patternString, negateMatch );
089    }
090
091  /**
092   * Constructor AssertMatches creates a new AssertMatches instance.
093   *
094   * @param patternString of type String
095   * @param negateMatch   of type boolean
096   * @param delimiter     of type String
097   */
098  @ConstructorProperties({"patternString", "negateMatch", "delimiter"})
099  public AssertMatches( String patternString, boolean negateMatch, String delimiter )
100    {
101    super( patternString, negateMatch, delimiter );
102    }
103
104  @Override
105  public boolean supportsPlannerLevel( PlannerLevel plannerLevel )
106    {
107    return plannerLevel instanceof AssertionLevel;
108    }
109
110  @Override
111  public void doAssert( FlowProcess flowProcess, ValueAssertionCall<Matcher> assertionCall )
112    {
113    TupleEntry tupleEntry = assertionCall.getArguments();
114
115    if( matchWholeTuple( assertionCall.getContext(), tupleEntry ) )
116      BaseAssertion.throwFail( message, tupleEntry.getTuple().print(), patternString );
117    }
118  }