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 AssertMatches matches the given regular expression patternString against the whole argument
037 * {@link cascading.tuple.Tuple} by joining each individual element of the Tuple with a tab character (\t) unless
038 * otherwise specified.
039 * See {@link AssertMatchesAll} if you need to match the patternString regex against each individual tuple element.
040 * <p>
041 * This operation uses {@link java.util.regex.Matcher} internally, specifically the method {@link java.util.regex.Matcher#find()}.
042 * <p>
043 * Note a {@code null} valued argument passed to the parser will be converted to an empty string ({@code ""}) before
044 * the regex is applied.
045 * <p>
046 * Any Object value will be coerced to a String type via any provided {@link cascading.tuple.type.CoercibleType} on
047 * the argument selector or via its {@code toString()} method.
048 *
049 * @see java.util.regex.Matcher
050 * @see java.util.regex.Pattern
051 */
052public class AssertMatches extends RegexMatcher implements ValueAssertion<Matcher>
053  {
054  /** Field message */
055  private final static String message = "argument tuple: %s did not match: %s";
056
057  /**
058   * Constructor AssertMatches creates a new AssertMatches instance.
059   *
060   * @param patternString of type String
061   */
062  @ConstructorProperties({"patternString"})
063  public AssertMatches( String patternString )
064    {
065    super( patternString, false );
066    }
067
068  /**
069   * Constructor AssertMatches creates a new AssertMatches instance.
070   *
071   * @param patternString of type String
072   * @param delimiter     of type String
073   */
074  @ConstructorProperties({"patternString", "delimiter"})
075  public AssertMatches( String patternString, String delimiter )
076    {
077    super( patternString, false, delimiter );
078    }
079
080  /**
081   * Constructor AssertMatches creates a new AssertMatches instance.
082   *
083   * @param patternString of type String
084   * @param negateMatch   of type boolean
085   */
086  @ConstructorProperties({"patternString", "negateMatch"})
087  public AssertMatches( String patternString, boolean negateMatch )
088    {
089    super( patternString, negateMatch );
090    }
091
092  /**
093   * Constructor AssertMatches creates a new AssertMatches instance.
094   *
095   * @param patternString of type String
096   * @param negateMatch   of type boolean
097   * @param delimiter     of type String
098   */
099  @ConstructorProperties({"patternString", "negateMatch", "delimiter"})
100  public AssertMatches( String patternString, boolean negateMatch, String delimiter )
101    {
102    super( patternString, negateMatch, delimiter );
103    }
104
105  @Override
106  public boolean supportsPlannerLevel( PlannerLevel plannerLevel )
107    {
108    return plannerLevel instanceof AssertionLevel;
109    }
110
111  @Override
112  public void doAssert( FlowProcess flowProcess, ValueAssertionCall<Matcher> assertionCall )
113    {
114    TupleEntry tupleEntry = assertionCall.getArguments();
115
116    if( matchWholeTuple( assertionCall.getContext(), tupleEntry ) )
117      BaseAssertion.throwFail( message, tupleEntry.getTuple().print(), patternString );
118    }
119  }