// Path: src/main/java/com/cronutils/model/field/constraint/FieldConstraints.java
// public class FieldConstraints implements Serializable {
// 
//     private static final long serialVersionUID = -9112124669329704710L;
//     private final Map<String, Integer> stringMapping;
//     private final Map<Integer, Integer> intMapping;
//     private final Set<SpecialChar> specialChars;
//     private final Integer startRange;
//     private final Integer endRange;
//     private final boolean strictRange;
// 
//     /**
//      * Constructor.
//      *
//      * @param specialChars - allowed special chars.
//      * @param startRange   - lowest possible value
//      * @param endRange     - highest possible value
//      * @param strictRange  - if we shall consider strict ranges for this field - regardless global strict ranges criteria
//      */
//     public FieldConstraints(final Map<String, Integer> stringMapping, final Map<Integer, Integer> intMapping, final Set<SpecialChar> specialChars, final int startRange,
//             final int endRange, final boolean strictRange) {
//         this.stringMapping = Collections.unmodifiableMap(Preconditions.checkNotNull(stringMapping, "String mapping must not be null"));
//         this.intMapping = Collections.unmodifiableMap(Preconditions.checkNotNull(intMapping, "Integer mapping must not be null"));
//         this.specialChars = Collections.unmodifiableSet(Preconditions.checkNotNull(specialChars, "Special (non-standard) chars set must not be null"));
//         this.startRange = startRange;
//         this.endRange = endRange;
//         this.strictRange = strictRange;
//     }
// 
//     public int getStartRange() {
//         return startRange;
//     }
// 
//     public int getEndRange() {
//         return endRange;
//     }
// 
//     public Set<SpecialChar> getSpecialChars() {
//         return specialChars;
//     }
// 
//     /**
//      * Check if given number is greater or equal to start range and minor or equal to end range.
//      *
//      * @param value - to be checked
//      */
//     public boolean isInRange(final int value) {
//         return value >= getStartRange() && value <= getEndRange();
//     }
// 
//     /**
//      * Check if given period is compatible with the given range.
//      *
//      * @param period - to be checked
//      * @return {@code true} if period is compatible, {@code false} otherwise.
//      */
//     public boolean isPeriodInRange(final int period) {
//         return period > 0 && period <= (getEndRange() - getStartRange() +1) && period <= getEndRange();
//     }
// 
//     public Set<String> getStringMappingKeySet() {
//         return stringMapping.keySet();
//     }
// 
//     public Integer getStringMappingValue(final String exp) {
//         return stringMapping.get(exp);
//     }
// 
//     public Integer getIntMappingValue(final Integer exp) {
//         return intMapping.get(exp);
//     }
// 
//     public boolean isStrictRange() {
//         return strictRange;
//     }
// }


import com.cronutils.mapper.ConstantsMapper;
import com.cronutils.mapper.WeekDay;
import com.cronutils.model.field.CronField;
import com.cronutils.model.field.CronFieldName;
import com.cronutils.model.field.constraint.FieldConstraints;
import com.cronutils.model.field.constraint.FieldConstraintsBuilder;
import com.cronutils.model.field.expression.On;
import com.cronutils.model.field.value.IntegerFieldValue;
import com.cronutils.model.field.value.SpecialChar;
import com.cronutils.model.field.value.SpecialCharFieldValue;
import org.junit.Test;
import java.util.List;
import static org.junit.Assert.*;
    @Test(expected = NoSuchValueException.class)
    public void testGenerateNextValueLastDayDoWEqualToRequestedDoW() throws NoSuchValueException {
        fieldValueGenerator = createFieldValueGeneratorInstanceLastDayDoWEqualToRequestedDoW();
        assertEquals(FIRST_DAY_DOW_EQUALTO_REQUESTED_DOW_DAY, fieldValueGenerator.generateNextValue(1));
        fieldValueGenerator.generateNextValue(FIRST_DAY_DOW_EQUALTO_REQUESTED_DOW_DAY);
    }

    @Test(expected = NoSuchValueException.class)
    public void testGeneratePreviousValueLastDayDoWGreaterThanRequestedDoW() throws NoSuchValueException {
        fieldValueGenerator = createFieldValueGeneratorInstanceFirstDayDoWGreaterThanRequestedDoW();
        assertEquals(FIRST_DAY_DOW_GREATER_THAN_REQUESTED_DOW_DAY, fieldValueGenerator.generatePreviousValue(FIRST_DAY_DOW_GREATER_THAN_REQUESTED_DOW_DAY + 1));
        fieldValueGenerator.generatePreviousValue(FIRST_DAY_DOW_GREATER_THAN_REQUESTED_DOW_DAY);
    }

    @Test(expected = NoSuchValueException.class)
    public void testGeneratePreviousValueLastDayDoWLessThanRequestedDoW() throws NoSuchValueException {
        fieldValueGenerator = createFieldValueGeneratorInstanceLastDayDoWLessThanRequestedDoW();
        assertEquals(FIRST_DAY_DOW_LESS_THAN_REQUESTED_DOW_DAY, fieldValueGenerator.generatePreviousValue(FIRST_DAY_DOW_LESS_THAN_REQUESTED_DOW_DAY + 1));
        fieldValueGenerator.generatePreviousValue(FIRST_DAY_DOW_LESS_THAN_REQUESTED_DOW_DAY);
    }

    @Test(expected = NoSuchValueException.class)
    public void testGeneratePreviousValueLastDayDoWEqualToRequestedDoW() throws NoSuchValueException {
        fieldValueGenerator = createFieldValueGeneratorInstanceLastDayDoWEqualToRequestedDoW();
        assertEquals(FIRST_DAY_DOW_EQUALTO_REQUESTED_DOW_DAY, fieldValueGenerator.generatePreviousValue(FIRST_DAY_DOW_EQUALTO_REQUESTED_DOW_DAY + 1));
        fieldValueGenerator.generatePreviousValue(FIRST_DAY_DOW_EQUALTO_REQUESTED_DOW_DAY);
    }

    @Test
    public void testGenerateCandidatesNotIncludingIntervalExtremesLastDayDoWGreaterThanRequestedDoW() {
// Path: src/main/java/com/cronutils/model/field/constraint/FieldConstraints.java
// public class FieldConstraints implements Serializable {
// 
//     private static final long serialVersionUID = -9112124669329704710L;
//     private final Map<String, Integer> stringMapping;
//     private final Map<Integer, Integer> intMapping;
//     private final Set<SpecialChar> specialChars;
//     private final Integer startRange;
//     private final Integer endRange;
//     private final boolean strictRange;
// 
//     /**
//      * Constructor.
//      *
//      * @param specialChars - allowed special chars.
//      * @param startRange   - lowest possible value
//      * @param endRange     - highest possible value
//      * @param strictRange  - if we shall consider strict ranges for this field - regardless global strict ranges criteria
//      */
//     public FieldConstraints(final Map<String, Integer> stringMapping, final Map<Integer, Integer> intMapping, final Set<SpecialChar> specialChars, final int startRange,
//             final int endRange, final boolean strictRange) {
//         this.stringMapping = Collections.unmodifiableMap(Preconditions.checkNotNull(stringMapping, "String mapping must not be null"));
//         this.intMapping = Collections.unmodifiableMap(Preconditions.checkNotNull(intMapping, "Integer mapping must not be null"));
//         this.specialChars = Collections.unmodifiableSet(Preconditions.checkNotNull(specialChars, "Special (non-standard) chars set must not be null"));
//         this.startRange = startRange;
//         this.endRange = endRange;
//         this.strictRange = strictRange;
//     }
// 
//     public int getStartRange() {
//         return startRange;
//     }
// 
//     public int getEndRange() {
//         return endRange;
//     }
// 
//     public Set<SpecialChar> getSpecialChars() {
//         return specialChars;
//     }
// 
//     /**
//      * Check if given number is greater or equal to start range and minor or equal to end range.
//      *
//      * @param value - to be checked
//      */
//     public boolean isInRange(final int value) {
//         return value >= getStartRange() && value <= getEndRange();
//     }
// 
//     /**
//      * Check if given period is compatible with the given range.
//      *
//      * @param period - to be checked
//      * @return {@code true} if period is compatible, {@code false} otherwise.
//      */
//     public boolean isPeriodInRange(final int period) {
//         return period > 0 && period <= (getEndRange() - getStartRange() +1) && period <= getEndRange();
//     }
// 
//     public Set<String> getStringMappingKeySet() {
//         return stringMapping.keySet();
//     }
// 
//     public Integer getStringMappingValue(final String exp) {
//         return stringMapping.get(exp);
//     }
// 
//     public Integer getIntMappingValue(final Integer exp) {
//         return intMapping.get(exp);
//     }
// 
//     public boolean isStrictRange() {
//         return strictRange;
//     }
// }


// Path: src/test/java/com/cronutils/model/time/generator/OnDayOfWeekValueGeneratorHashTest.java
import com.cronutils.mapper.ConstantsMapper;
import com.cronutils.mapper.WeekDay;
import com.cronutils.model.field.CronField;
import com.cronutils.model.field.CronFieldName;
import com.cronutils.model.field.constraint.FieldConstraints;
import com.cronutils.model.field.constraint.FieldConstraintsBuilder;
import com.cronutils.model.field.expression.On;
import com.cronutils.model.field.value.IntegerFieldValue;
import com.cronutils.model.field.value.SpecialChar;
import com.cronutils.model.field.value.SpecialCharFieldValue;
import org.junit.Test;
import java.util.List;
import static org.junit.Assert.*;

    @Test(expected = NoSuchValueException.class)
    public void testGenerateNextValueLastDayDoWEqualToRequestedDoW() throws NoSuchValueException {
        fieldValueGenerator = createFieldValueGeneratorInstanceLastDayDoWEqualToRequestedDoW();
        assertEquals(FIRST_DAY_DOW_EQUALTO_REQUESTED_DOW_DAY, fieldValueGenerator.generateNextValue(1));
        fieldValueGenerator.generateNextValue(FIRST_DAY_DOW_EQUALTO_REQUESTED_DOW_DAY);
    }

    @Test(expected = NoSuchValueException.class)
    public void testGeneratePreviousValueLastDayDoWGreaterThanRequestedDoW() throws NoSuchValueException {
        fieldValueGenerator = createFieldValueGeneratorInstanceFirstDayDoWGreaterThanRequestedDoW();
        assertEquals(FIRST_DAY_DOW_GREATER_THAN_REQUESTED_DOW_DAY, fieldValueGenerator.generatePreviousValue(FIRST_DAY_DOW_GREATER_THAN_REQUESTED_DOW_DAY + 1));
        fieldValueGenerator.generatePreviousValue(FIRST_DAY_DOW_GREATER_THAN_REQUESTED_DOW_DAY);
    }

    @Test(expected = NoSuchValueException.class)
    public void testGeneratePreviousValueLastDayDoWLessThanRequestedDoW() throws NoSuchValueException {
        fieldValueGenerator = createFieldValueGeneratorInstanceLastDayDoWLessThanRequestedDoW();
        assertEquals(FIRST_DAY_DOW_LESS_THAN_REQUESTED_DOW_DAY, fieldValueGenerator.generatePreviousValue(FIRST_DAY_DOW_LESS_THAN_REQUESTED_DOW_DAY + 1));
        fieldValueGenerator.generatePreviousValue(FIRST_DAY_DOW_LESS_THAN_REQUESTED_DOW_DAY);
    }

    @Test(expected = NoSuchValueException.class)
    public void testGeneratePreviousValueLastDayDoWEqualToRequestedDoW() throws NoSuchValueException {
        fieldValueGenerator = createFieldValueGeneratorInstanceLastDayDoWEqualToRequestedDoW();
        assertEquals(FIRST_DAY_DOW_EQUALTO_REQUESTED_DOW_DAY, fieldValueGenerator.generatePreviousValue(FIRST_DAY_DOW_EQUALTO_REQUESTED_DOW_DAY + 1));
        fieldValueGenerator.generatePreviousValue(FIRST_DAY_DOW_EQUALTO_REQUESTED_DOW_DAY);
    }

    @Test
    public void testGenerateCandidatesNotIncludingIntervalExtremesLastDayDoWGreaterThanRequestedDoW() {
        fieldValueGenerator = createFieldValueGeneratorInstanceFirstDayDoWGreaterThanRequestedDoW();