001/** 002 * Powerunit - A JDK1.8 test framework 003 * Copyright (C) 2014 Mathieu Boretti. 004 * 005 * This file is part of Powerunit 006 * 007 * Powerunit is free software: you can redistribute it and/or modify 008 * it under the terms of the GNU General Public License as published by 009 * the Free Software Foundation, either version 3 of the License, or 010 * (at your option) any later version. 011 * 012 * Powerunit is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 015 * GNU General Public License for more details. 016 * 017 * You should have received a copy of the GNU General Public License 018 * along with Powerunit. If not, see <http://www.gnu.org/licenses/>. 019 */ 020package ch.powerunit.pattern; 021 022import java.util.ArrayList; 023import java.util.Collections; 024import java.util.List; 025import java.util.Objects; 026import java.util.regex.Pattern; 027 028import org.hamcrest.Matcher; 029 030import ch.powerunit.TestInterface; 031import ch.powerunit.TestSuite; 032import ch.powerunit.pattern.impl.PatternTesterImpl; 033import ch.powerunit.pattern.lang.PatternTester0; 034import ch.powerunit.pattern.lang.PatternTester1; 035import ch.powerunit.pattern.lang.PatternTester2; 036import ch.powerunit.pattern.lang.PatternTester3; 037import ch.powerunit.pattern.lang.PatternTester4; 038 039/** 040 * This is a tester to validate {@link Pattern}. 041 * <p> 042 * This tester will validate that a Pattern accept ( 043 * {@link Pattern#matcher(CharSequence)}) or not a specified string ; In the 044 * first case (accepted), it also provide a way to validate the groups ( 045 * {@link java.util.regex.Matcher#group(int)}). 046 * 047 * @author borettim 048 * @since 0.4.0 049 */ 050@TestInterface(PatternTesterImpl.class) 051public final class PatternTester { 052 private final Pattern underTest; 053 054 private final List<String> inputs; 055 056 private final List<Boolean> expectedResult; 057 058 private final List<List<Integer>> havingGroup; 059 060 private final List<List<Matcher<String>>> expectedGroup; 061 062 private PatternTester(Pattern underTest, List<String> inputs, 063 List<Boolean> expectedResult, List<List<Integer>> havingGroup, 064 List<List<Matcher<String>>> expectedGroup) { 065 this.underTest = underTest; 066 this.inputs = inputs; 067 this.expectedResult = expectedResult; 068 this.havingGroup = havingGroup; 069 this.expectedGroup = expectedGroup; 070 } 071 072 /** 073 * Start the DSL to create a tester of Pattern, based on a String. 074 * <p> 075 * The passed String will be compiled as a Pattern. <br> 076 * For instance : 077 * 078 * <pre> 079 * @TestDelegate 080 * public final PatternTester sample1 = PatternTester.of("a+").receiving("b") 081 * .thenNoMatching().receiving("aa").thenMatching().build(); 082 * </pre> 083 * 084 * @param pattern 085 * the pattern, as a String 086 * @return {@link PatternTester0#receiving(String) The next step of the 087 * DSL.} 088 * @see #of(Pattern) 089 */ 090 public static PatternTester0 of(String pattern) { 091 return of(Pattern.compile(pattern)); 092 } 093 094 /** 095 * Start the DSL to create a tester of Pattern, based on a String. 096 * <p> 097 * For instance : 098 * 099 * <pre> 100 * @TestDelegate 101 * public final PatternTester sample1 = PatternTester.of(Pattern.compile("a+")) 102 * .receiving("b").thenNoMatching().receiving("aa").thenMatching().build(); 103 * </pre> 104 * 105 * @param pattern 106 * the pattern. 107 * @return {@link PatternTester0#receiving(String) The next step of the 108 * DSL.} 109 */ 110 public static PatternTester0 of(Pattern pattern) { 111 return new PatternTesterDSL(pattern); 112 } 113 114 private static class PatternTesterDSL implements PatternTester0, 115 PatternTester1, PatternTester2, PatternTester3, PatternTester4 { 116 117 private final Pattern underTest; 118 119 private final List<String> inputs = new ArrayList<>(); 120 121 private final List<Boolean> expectedResult = new ArrayList<>(); 122 123 private final List<List<Integer>> havingGroup = new ArrayList<>(); 124 125 private final List<List<Matcher<String>>> expectedGroup = new ArrayList<>(); 126 127 private List<Integer> currentGroup = null; 128 129 private List<Matcher<String>> currentExpected = null; 130 131 private PatternTesterDSL initMatching(boolean expected) { 132 expectedResult.add(expected); 133 currentGroup = new ArrayList<>(); 134 currentExpected = new ArrayList<>(); 135 havingGroup.add(Collections.unmodifiableList(currentGroup)); 136 expectedGroup.add(Collections.unmodifiableList(currentExpected)); 137 return this; 138 } 139 140 /** 141 * @param underTest 142 */ 143 private PatternTesterDSL(Pattern underTest) { 144 this.underTest = underTest; 145 } 146 147 @Override 148 public PatternTester2 receiving(String input) { 149 inputs.add(Objects.requireNonNull(input, "input can't be null")); 150 return this; 151 } 152 153 @Override 154 public PatternTester1 thenNoMatching() { 155 return initMatching(false); 156 } 157 158 @Override 159 public PatternTester3 thenMatching() { 160 return initMatching(true); 161 } 162 163 @Override 164 public PatternTester4 havingGroup(int number) { 165 if (number < 0) { 166 throw new IllegalArgumentException("Number can't be <0"); 167 } 168 currentGroup.add(number); 169 return this; 170 } 171 172 @Override 173 public PatternTester3 matching(Matcher<String> matching) { 174 currentExpected.add(Objects.requireNonNull(matching, 175 "matching can't be null")); 176 return this; 177 } 178 179 @Override 180 public PatternTester3 equalTo(String equalTo) { 181 return matching(TestSuite.DSL.equalTo(Objects.requireNonNull( 182 equalTo, "equalTo can't be null"))); 183 } 184 185 @Override 186 public PatternTester build() { 187 return new PatternTester(underTest, inputs, expectedResult, 188 havingGroup, expectedGroup); 189 } 190 191 } 192 193 /** 194 * Used by the framework. 195 * 196 * @return the underTest 197 */ 198 public Pattern getUnderTest() { 199 return underTest; 200 } 201 202 /** 203 * Used by the framework. 204 * 205 * @return the inputs 206 */ 207 public List<String> getInputs() { 208 return Collections.unmodifiableList(inputs); 209 } 210 211 /** 212 * Used by the framework. 213 * 214 * @return the expectedResult 215 */ 216 public List<Boolean> getExpectedResult() { 217 return Collections.unmodifiableList(expectedResult); 218 } 219 220 /** 221 * Used by the framework. 222 * 223 * @return the havingGroup 224 */ 225 public List<List<Integer>> getHavingGroup() { 226 return Collections.unmodifiableList(havingGroup); 227 } 228 229 /** 230 * Used by the framework. 231 * 232 * @return the expectedGroup 233 */ 234 public List<List<Matcher<String>>> getExpectedGroup() { 235 return Collections.unmodifiableList(expectedGroup); 236 } 237 238}