Skip to content

Commit

Permalink
Issue #89: regression - NumberFormatException: For input string: '$' …
Browse files Browse the repository at this point in the history
…not matching original message.
  • Loading branch information
jmrozanec committed May 27, 2016
1 parent bb90e76 commit 11ea8be
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 62 deletions.
77 changes: 77 additions & 0 deletions src/main/java/com/cronutils/StringValidations.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* Copyright 2014 jmrozanec
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.cronutils;

import com.cronutils.model.field.constraint.FieldConstraints;
import com.cronutils.model.field.value.SpecialChar;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Sets;

import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class StringValidations {
private FieldConstraints constraints;
private Pattern stringToIntKeysPattern;
private Pattern numsAndCharsPattern;
private Pattern lwPattern;
private boolean strictRanges;

public StringValidations(FieldConstraints constraints){
this.lwPattern = buildLWPattern(constraints.getSpecialChars());
this.stringToIntKeysPattern = buildStringToIntPattern(constraints.getStringMapping().keySet());
this.numsAndCharsPattern = Pattern.compile("[#\\?/\\*0-9]");
}

@VisibleForTesting
Pattern buildStringToIntPattern(Set<String> strings){
return buildWordsPattern(strings);
}

@VisibleForTesting
public String removeValidChars(String exp){
exp = exp.toUpperCase();
Matcher numsAndCharsMatcher = numsAndCharsPattern.matcher(exp);
Matcher stringToIntKeysMatcher = stringToIntKeysPattern.matcher(numsAndCharsMatcher.replaceAll(""));
Matcher specialWordsMatcher = lwPattern.matcher(stringToIntKeysMatcher.replaceAll(""));
return specialWordsMatcher.replaceAll("").replaceAll("\\s+", "").replaceAll(",", "").replaceAll("-", "");
}

@VisibleForTesting
Pattern buildLWPattern(Set<SpecialChar> specialChars){
Set<String> scs = Sets.newHashSet();
for(SpecialChar sc : new SpecialChar[]{SpecialChar.L, SpecialChar.LW, SpecialChar.W}){
if(specialChars.contains(sc)){
scs.add(sc.name());
}
}
return buildWordsPattern(scs);
}

@VisibleForTesting
Pattern buildWordsPattern(Set<String> words){
StringBuilder builder = new StringBuilder("\\b(");
boolean first = true;
for(String word : words){
if(!first){
builder.append("|");
}else{
first=false;
}
builder.append(word);
}
builder.append(")\\b");
return Pattern.compile(builder.toString());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,38 +12,30 @@
*/
package com.cronutils.model.field.expression.visitor;

import com.cronutils.StringValidations;
import com.cronutils.model.field.value.FieldValue;
import com.cronutils.model.field.value.IntegerFieldValue;
import com.cronutils.model.field.value.SpecialChar;
import com.cronutils.model.field.constraint.FieldConstraints;
import com.cronutils.model.field.expression.*;
import com.cronutils.model.field.value.SpecialCharFieldValue;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Sets;

import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ValidationFieldExpressionVisitor implements FieldExpressionVisitor {
private static final String OORANGE = "Value %s not in range [%s, %s]";
private FieldConstraints constraints;
private Pattern stringToIntKeysPattern;
private Pattern numsAndCharsPattern;
private Pattern lwPattern;
private StringValidations stringValidations;
private boolean strictRanges;

public ValidationFieldExpressionVisitor(FieldConstraints constraints, boolean strictRanges){
this.constraints = constraints;
this.lwPattern = buildLWPattern(constraints.getSpecialChars());
this.stringToIntKeysPattern = buildStringToIntPattern(constraints.getStringMapping().keySet());
this.numsAndCharsPattern = Pattern.compile("[#\\?/\\*0-9]");
this.stringValidations = new StringValidations(constraints);
this.strictRanges = strictRanges;
}

@Override
public FieldExpression visit(FieldExpression expression) {
String unsupportedChars = removeValidChars(expression.asString()).toUpperCase();
String unsupportedChars = stringValidations.removeValidChars(expression.asString());
if("".equals(unsupportedChars)){
if(expression instanceof Always){
return visit((Always)expression);
Expand All @@ -64,7 +56,7 @@ public FieldExpression visit(FieldExpression expression) {
return visit((QuestionMark)expression);
}
}
throw new RuntimeException(String.format("Expression contains unsupported chars: %s", unsupportedChars));
throw new IllegalArgumentException(String.format("Invalid chars in expression! Expression: %s Invalid chars: %s", expression.asString(), unsupportedChars));
}

@Override
Expand Down Expand Up @@ -124,50 +116,12 @@ public QuestionMark visit(QuestionMark questionMark) {
return questionMark;
}

@VisibleForTesting
Pattern buildStringToIntPattern(Set<String> strings){
return buildWordsPattern(strings);
}

@VisibleForTesting
String removeValidChars(String exp){
Matcher numsAndCharsMatcher = numsAndCharsPattern.matcher(exp);
Matcher stringToIntKeysMatcher = stringToIntKeysPattern.matcher(numsAndCharsMatcher.replaceAll(""));
Matcher specialWordsMatcher = lwPattern.matcher(stringToIntKeysMatcher.replaceAll(""));
return specialWordsMatcher.replaceAll("").replaceAll("\\s+", "").replaceAll(",", "").replaceAll("-", "");
}

@VisibleForTesting
Pattern buildLWPattern(Set<SpecialChar> specialChars){
Set<String> scs = Sets.newHashSet();
for(SpecialChar sc : new SpecialChar[]{SpecialChar.L, SpecialChar.LW, SpecialChar.W}){
if(specialChars.contains(sc)){
scs.add(sc.name());
}
}
return buildWordsPattern(scs);
}

@VisibleForTesting
Pattern buildWordsPattern(Set<String> words){
StringBuilder builder = new StringBuilder("\\b(");
boolean first = true;
for(String word : words){
if(!first){
builder.append("|");
}else{
first=false;
}
builder.append(word);
}
builder.append(")\\b");
return Pattern.compile(builder.toString());
}

/**
* Check if given number is greater or equal to start range and minor or equal to end range
* @param fieldValue - to be validated
* @throws - RuntimeException if not in range
* @throws IllegalArgumentException - if not in range
*/
@VisibleForTesting
void isInRange(FieldValue fieldValue) {
Expand All @@ -181,16 +135,10 @@ void isInRange(FieldValue fieldValue) {

@VisibleForTesting
boolean isDefault(FieldValue fieldValue) {
if(fieldValue instanceof IntegerFieldValue){
return ((IntegerFieldValue)fieldValue).getValue()==-1;
}
return false;
return fieldValue instanceof IntegerFieldValue && ((IntegerFieldValue) fieldValue).getValue() == -1;
}

boolean isSpecialCharNotL(FieldValue fieldValue){
if(fieldValue instanceof SpecialCharFieldValue){
return !SpecialChar.L.equals(fieldValue.getValue());
}
return false;
boolean isSpecialCharNotL(FieldValue fieldValue) {
return fieldValue instanceof SpecialCharFieldValue && !SpecialChar.L.equals(fieldValue.getValue());
}
}
4 changes: 3 additions & 1 deletion src/main/java/com/cronutils/parser/FieldParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
*/
package com.cronutils.parser;

import com.cronutils.StringValidations;
import com.cronutils.model.field.constraint.FieldConstraints;
import com.cronutils.model.field.expression.*;
import com.cronutils.model.field.value.FieldValue;
Expand Down Expand Up @@ -206,7 +207,8 @@ int stringToInt(String exp) {
try{
return Integer.parseInt(exp);
}catch (NumberFormatException e){
throw new IllegalArgumentException(e);
String invalidChars = new StringValidations(fieldConstraints).removeValidChars(exp);
throw new IllegalArgumentException(String.format("Invalid chars in expression! Expression: %s Invalid chars: %s", exp, invalidChars));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,21 @@ public void testIntervalMinutes() {
Assert.assertEquals(assertDate, lastExecution);
}

/**
* Issue #89: regression - NumberFormatException: For input string: "$"
*/
@Test
public void testRegressionDifferentMessageForException(){
boolean asserted = false;
try{
ExecutionTime.forCron(parser.parse("* * * * $ ?"));
}catch (IllegalArgumentException e){
assertEquals("Invalid chars in expression! Expression: $ Invalid chars: $", e.getMessage());
asserted = true;
}
assertTrue(asserted);
}

/**
* Issue #90: Reported error contains other expression than the one provided
*/
Expand Down

0 comments on commit 11ea8be

Please sign in to comment.