From 2b4705912ce9d774378603bb1a472a88ebdfc0eb Mon Sep 17 00:00:00 2001 From: Matthew Date: Thu, 15 Aug 2019 12:14:26 +0100 Subject: [PATCH 01/20] Add streaming string generation for regexes and checksums --- .../string/streamy/ChecksumMaker.java | 21 +++++++ .../ChecksumStreamStringGenerator.java | 49 ++++++++++++++++ .../ChecksumStringGeneratorFactory.java | 39 +++++++++++++ .../streamy/ChecksumlessIsinGenerator.java | 56 +++++++++++++++++++ .../string/streamy/IsinCountryCode.java | 46 +++++++++++++++ .../PrefixingStreamStringGenerator.java | 49 ++++++++++++++++ .../streamy/RegexStreamStringGenerator.java | 45 +++++++++++++++ .../string/streamy/StreamStringGenerator.java | 28 ++++++++++ 8 files changed, 333 insertions(+) create mode 100644 generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumMaker.java create mode 100644 generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumStreamStringGenerator.java create mode 100644 generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumStringGeneratorFactory.java create mode 100644 generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumlessIsinGenerator.java create mode 100644 generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/IsinCountryCode.java create mode 100644 generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/PrefixingStreamStringGenerator.java create mode 100644 generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/RegexStreamStringGenerator.java create mode 100644 generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/StreamStringGenerator.java diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumMaker.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumMaker.java new file mode 100644 index 000000000..adaf253a6 --- /dev/null +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumMaker.java @@ -0,0 +1,21 @@ +/* + * Copyright 2019 Scott Logic Ltd + * + * 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.scottlogic.deg.generator.generation.string.streamy; + +@FunctionalInterface +public interface ChecksumMaker { + Character makeChecksum(String input); +} diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumStreamStringGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumStreamStringGenerator.java new file mode 100644 index 000000000..5d05640f0 --- /dev/null +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumStreamStringGenerator.java @@ -0,0 +1,49 @@ +/* + * Copyright 2019 Scott Logic Ltd + * + * 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.scottlogic.deg.generator.generation.string.streamy; + +import com.scottlogic.deg.generator.utils.RandomNumberGenerator; + +import java.util.stream.Stream; + +public class ChecksumStreamStringGenerator implements StreamStringGenerator { + + private final StreamStringGenerator checksumlessGenerator; + private final ChecksumMaker checksumMaker; + + public ChecksumStreamStringGenerator(StreamStringGenerator checksumlessGenerator, ChecksumMaker checksumMaker) { + this.checksumlessGenerator = checksumlessGenerator; + this.checksumMaker = checksumMaker; + } + + @Override + public Stream generateAllValues() { + return checksumlessGenerator.generateAllValues() + .map(string -> string + checksumMaker.makeChecksum(string)); + } + + @Override + public Stream generateRandomValues(RandomNumberGenerator randomNumberGenerator) { + return checksumlessGenerator.generateRandomValues(randomNumberGenerator) + .map(string -> string + checksumMaker.makeChecksum(string)); + } + + @Override + public Stream generateInterestingValues() { + return checksumlessGenerator.generateInterestingValues() + .map(string -> string + checksumMaker.makeChecksum(string)); + } +} diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumStringGeneratorFactory.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumStringGeneratorFactory.java new file mode 100644 index 000000000..2cf4ea496 --- /dev/null +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumStringGeneratorFactory.java @@ -0,0 +1,39 @@ +/* + * Copyright 2019 Scott Logic Ltd + * + * 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.scottlogic.deg.generator.generation.string.streamy; + +import com.scottlogic.deg.generator.utils.FinancialCodeUtils; + +public class ChecksumStringGeneratorFactory { + + public static StreamStringGenerator createSedolGenerator() { + return new ChecksumStreamStringGenerator( + new RegexStreamStringGenerator("[B-DF-HJ-NP-TV-Z0-9]{6}"), + FinancialCodeUtils::calculateSedolCheckDigit); + } + + public static StreamStringGenerator createCusipGenerator() { + return new ChecksumStreamStringGenerator( + new RegexStreamStringGenerator("[0-9]{3}[0-9A-Z]{5}"), + FinancialCodeUtils::calculateCusipCheckDigit); + } + + public static StreamStringGenerator createIsinGenerator() { + return new ChecksumStreamStringGenerator( + new ChecksumlessIsinGenerator(), + FinancialCodeUtils::calculateIsinCheckDigit); + } +} diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumlessIsinGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumlessIsinGenerator.java new file mode 100644 index 000000000..4b18ca36c --- /dev/null +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumlessIsinGenerator.java @@ -0,0 +1,56 @@ +/* + * Copyright 2019 Scott Logic Ltd + * + * 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.scottlogic.deg.generator.generation.string.streamy; + +import com.scottlogic.deg.generator.utils.RandomNumberGenerator; + +import java.util.Arrays; +import java.util.stream.Stream; + +import static com.scottlogic.deg.common.util.FlatMappingSpliterator.flatMap; + +public class ChecksumlessIsinGenerator implements StreamStringGenerator { + + @Override + public Stream generateAllValues() { + Stream isinStringGenerators = + Arrays.stream(IsinCountryCode.values()) + .map(IsinCountryCode::getChecksumlessStringGenerator); + + return flatMap( + isinStringGenerators, + StreamStringGenerator::generateAllValues); + } + + @Override + public Stream generateRandomValues(RandomNumberGenerator randomNumberGenerator) { + return Stream.generate(() -> + getRandomCountryCode(randomNumberGenerator) + .getChecksumlessStringGenerator() + .generateRandomValues(randomNumberGenerator) + .findFirst().get()); + } + + private IsinCountryCode getRandomCountryCode(RandomNumberGenerator randomNumberGenerator) { + int random = randomNumberGenerator.nextInt(IsinCountryCode.values().length); + return IsinCountryCode.values()[random]; + } + + @Override + public Stream generateInterestingValues() { + return generateAllValues().limit(2); + } +} diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/IsinCountryCode.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/IsinCountryCode.java new file mode 100644 index 000000000..1b79d4f59 --- /dev/null +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/IsinCountryCode.java @@ -0,0 +1,46 @@ +/* + * Copyright 2019 Scott Logic Ltd + * + * 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.scottlogic.deg.generator.generation.string.streamy; + + +import static com.scottlogic.deg.generator.generation.string.streamy.ChecksumStringGeneratorFactory.createCusipGenerator; +import static com.scottlogic.deg.generator.generation.string.streamy.ChecksumStringGeneratorFactory.createSedolGenerator; + +public enum IsinCountryCode { + GB(prefix("GB00", createSedolGenerator())), + US(prefix("US", createCusipGenerator())), + DN; + + String GENERIC_NSIN_REGEX = "[A-Z0-9]{9}"; + private final StreamStringGenerator checksumlessStringGenerator; + + IsinCountryCode(){ + checksumlessStringGenerator = prefix(this.name(), + new RegexStreamStringGenerator(GENERIC_NSIN_REGEX)); + } + + IsinCountryCode(StreamStringGenerator streamStringGenerator){ + this.checksumlessStringGenerator = streamStringGenerator; + } + + static StreamStringGenerator prefix(String prefix, StreamStringGenerator inner){ + return new PrefixingStreamStringGenerator(prefix, inner); + } + + public StreamStringGenerator getChecksumlessStringGenerator() { + return checksumlessStringGenerator; + } +} diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/PrefixingStreamStringGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/PrefixingStreamStringGenerator.java new file mode 100644 index 000000000..f84e91dc7 --- /dev/null +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/PrefixingStreamStringGenerator.java @@ -0,0 +1,49 @@ +/* + * Copyright 2019 Scott Logic Ltd + * + * 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.scottlogic.deg.generator.generation.string.streamy; + +import com.scottlogic.deg.generator.utils.RandomNumberGenerator; + +import java.util.stream.Stream; + +public class PrefixingStreamStringGenerator implements StreamStringGenerator { + + private final String prefix; + private final StreamStringGenerator innerGenerator; + + public PrefixingStreamStringGenerator(String prefix, StreamStringGenerator innerGenerator) { + this.prefix = prefix; + this.innerGenerator = innerGenerator; + } + + @Override + public Stream generateAllValues() { + return innerGenerator.generateAllValues() + .map(string -> prefix + string); + } + + @Override + public Stream generateRandomValues(RandomNumberGenerator randomNumberGenerator) { + return innerGenerator.generateRandomValues(randomNumberGenerator) + .map(string -> prefix + string); + } + + @Override + public Stream generateInterestingValues() { + return innerGenerator.generateInterestingValues() + .map(string -> prefix + string); + } +} diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/RegexStreamStringGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/RegexStreamStringGenerator.java new file mode 100644 index 000000000..129a68eb9 --- /dev/null +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/RegexStreamStringGenerator.java @@ -0,0 +1,45 @@ +/* + * Copyright 2019 Scott Logic Ltd + * + * 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.scottlogic.deg.generator.generation.string.streamy; + +import com.scottlogic.deg.generator.generation.string.RegexStringGenerator; +import com.scottlogic.deg.generator.utils.RandomNumberGenerator; + +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +public class RegexStreamStringGenerator implements StreamStringGenerator{ + private final RegexStringGenerator regexStringGenerator; + + public RegexStreamStringGenerator(String regex) { + this.regexStringGenerator = new RegexStringGenerator(regex, true); + } + + @Override + public Stream generateAllValues() { + return StreamSupport.stream(regexStringGenerator.generateAllValues().spliterator(), false); + } + + @Override + public Stream generateRandomValues(RandomNumberGenerator randomNumberGenerator) { + return StreamSupport.stream(regexStringGenerator.generateRandomValues(randomNumberGenerator).spliterator(), false); + } + + @Override + public Stream generateInterestingValues() { + return StreamSupport.stream(regexStringGenerator.generateInterestingValues().spliterator(), false); + } +} diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/StreamStringGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/StreamStringGenerator.java new file mode 100644 index 000000000..b491d0186 --- /dev/null +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/StreamStringGenerator.java @@ -0,0 +1,28 @@ +/* + * Copyright 2019 Scott Logic Ltd + * + * 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.scottlogic.deg.generator.generation.string.streamy; + +import com.scottlogic.deg.generator.utils.RandomNumberGenerator; + +import java.util.stream.Stream; + +public interface StreamStringGenerator { + Stream generateAllValues(); + + Stream generateRandomValues(RandomNumberGenerator randomNumberGenerator); + + Stream generateInterestingValues(); +} From 3c94651ee7e3230ad71452334c9582b45bae7a82 Mon Sep 17 00:00:00 2001 From: Matthew Date: Thu, 15 Aug 2019 12:28:41 +0100 Subject: [PATCH 02/20] Hook up new ISIN, CUSIP and SEDOL generation to existing code. Combining with regexes not yet implemented. Interesting mode not yet implemented --- .../string/CusipStringGenerator.java | 8 +++++ .../string/IsinStringGenerator.java | 8 +++++ .../string/SedolStringGenerator.java | 8 +++++ .../generation/string/StringGenerator.java | 30 +++++++++++++++++++ 4 files changed, 54 insertions(+) diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/CusipStringGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/CusipStringGenerator.java index c2a16f923..8b0aae6f5 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/CusipStringGenerator.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/CusipStringGenerator.java @@ -16,8 +16,11 @@ package com.scottlogic.deg.generator.generation.string; +import com.scottlogic.deg.generator.generation.fieldvaluesources.FieldValueSource; import com.scottlogic.deg.generator.utils.*; +import static com.scottlogic.deg.generator.generation.string.streamy.ChecksumStringGeneratorFactory.createCusipGenerator; + public class CusipStringGenerator extends ChecksummedCodeStringGenerator { public final static int CUSIP_LENGTH = 9; public final static String STANDARD_REGEX_REPRESENTATION = "[0-9]{3}[0-9A-Z]{5}[0-9]"; @@ -70,4 +73,9 @@ public boolean match(String subject) { ChecksummedCodeStringGenerator instantiate(RegexStringGenerator generator) { return new CusipStringGenerator(generator); } + + @Override + public FieldValueSource asFieldValueSource(){ + return new StreamStringGeneratorAsFieldValueSource(createCusipGenerator()); + } } diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/IsinStringGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/IsinStringGenerator.java index 1296b0e24..c57f9aaca 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/IsinStringGenerator.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/IsinStringGenerator.java @@ -16,6 +16,7 @@ package com.scottlogic.deg.generator.generation.string; +import com.scottlogic.deg.generator.generation.fieldvaluesources.FieldValueSource; import com.scottlogic.deg.generator.utils.*; import java.util.List; @@ -23,6 +24,8 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import static com.scottlogic.deg.generator.generation.string.streamy.ChecksumStringGeneratorFactory.createIsinGenerator; + public class IsinStringGenerator implements StringGenerator { public static final int ISIN_LENGTH = 12; private static final String GENERIC_NSIN_REGEX = "[A-Z0-9]{9}"; @@ -187,4 +190,9 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(isinRegexGenerator); } + + @Override + public FieldValueSource asFieldValueSource(){ + return new StreamStringGeneratorAsFieldValueSource(createIsinGenerator()); + } } diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/SedolStringGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/SedolStringGenerator.java index aaf93646c..8831faeba 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/SedolStringGenerator.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/SedolStringGenerator.java @@ -16,8 +16,11 @@ package com.scottlogic.deg.generator.generation.string; +import com.scottlogic.deg.generator.generation.fieldvaluesources.FieldValueSource; import com.scottlogic.deg.generator.utils.*; +import static com.scottlogic.deg.generator.generation.string.streamy.ChecksumStringGeneratorFactory.createSedolGenerator; + public class SedolStringGenerator extends ChecksummedCodeStringGenerator { public final static int SEDOL_LENGTH = 7; public final static String STANDARD_REGEX_REPRESENTATION = "[B-DF-HJ-NP-TV-Z0-9]{6}[0-9]"; @@ -71,4 +74,9 @@ public boolean match(String subject) { ChecksummedCodeStringGenerator instantiate(RegexStringGenerator generator) { return new SedolStringGenerator(generator); } + + @Override + public FieldValueSource asFieldValueSource(){ + return new StreamStringGeneratorAsFieldValueSource(createSedolGenerator()); + } } diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/StringGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/StringGenerator.java index 545e29a5e..1c7b3123b 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/StringGenerator.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/StringGenerator.java @@ -17,9 +17,12 @@ package com.scottlogic.deg.generator.generation.string; import com.scottlogic.deg.generator.generation.fieldvaluesources.FieldValueSource; +import com.scottlogic.deg.generator.generation.string.streamy.StreamStringGenerator; import com.scottlogic.deg.generator.utils.RandomNumberGenerator; import com.scottlogic.deg.generator.utils.UpCastingIterator; +import java.util.stream.StreamSupport; + public interface StringGenerator { StringGenerator intersect(StringGenerator stringGenerator); StringGenerator complement(); @@ -62,4 +65,31 @@ public Iterable generateRandomValues(RandomNumberGenerator randomNumberG underlyingGenerator.generateRandomValues(randomNumberGenerator).iterator()); } } + + class StreamStringGeneratorAsFieldValueSource implements FieldValueSource { + + private final StreamStringGenerator underlyingGenerator; + + public StreamStringGeneratorAsFieldValueSource(StreamStringGenerator underlyingGenerator) { + this.underlyingGenerator = underlyingGenerator; + } + + @Override + public Iterable generateInterestingValues() { + return () -> new UpCastingIterator<>( + underlyingGenerator.generateInterestingValues().iterator()); + } + + @Override + public Iterable generateAllValues() { + return () -> new UpCastingIterator<>( + underlyingGenerator.generateAllValues().iterator()); + } + + @Override + public Iterable generateRandomValues(RandomNumberGenerator randomNumberGenerator) { + return () -> new UpCastingIterator<>( + underlyingGenerator.generateRandomValues(randomNumberGenerator).iterator()); + } + } } From b3b2b86d2cbf5ba530eac3786d1cafbf40ffe40a Mon Sep 17 00:00:00 2001 From: Matthew Date: Tue, 20 Aug 2019 11:10:15 +0100 Subject: [PATCH 03/20] Delete old ISIN, CUSIP and SEDOL classes. Replace StringGenerator interface with new StreamStringGenerator interface. Removed code for negation of these special types. Intersection of constraints now only possible for regexes. Put regex for ISIN, CUSIP, SEDOL and RIC types into StandardConstraintTypes class. Throw exception by default if negation of constraint is not supported. Add matches methods --- .../atomic/StandardConstraintTypes.java | 19 +- .../fieldspecs/FieldSpecFactory.java | 13 +- .../StandardFieldValueSourceEvaluator.java | 4 +- .../ChecksummedCodeStringGenerator.java | 211 --------------- .../string/CusipStringGenerator.java | 81 ------ .../string/IsinStringGenerator.java | 198 -------------- .../string/NegatedIsinGenerator.java | 248 ------------------ .../string/NoStringsStringGenerator.java | 30 +-- .../string/RegexStringGenerator.java | 30 ++- .../string/SedolStringGenerator.java | 82 ------ .../generation/string/StringGenerator.java | 95 ------- .../ChecksumStreamStringGenerator.java | 12 + .../ChecksumStringGeneratorFactory.java | 5 +- .../streamy/ChecksumlessIsinGenerator.java | 9 + .../string/streamy/IsinCountryCode.java | 4 +- .../PrefixingStreamStringGenerator.java | 12 + .../streamy/RegexStreamStringGenerator.java | 45 ---- .../string/streamy/StreamStringGenerator.java | 47 ++++ .../MatchesStandardStringRestrictions.java | 116 ++------ .../restrictions/StringRestrictions.java | 4 +- .../restrictions/TextualRestrictions.java | 20 +- 21 files changed, 175 insertions(+), 1110 deletions(-) delete mode 100644 generator/src/main/java/com/scottlogic/deg/generator/generation/string/ChecksummedCodeStringGenerator.java delete mode 100644 generator/src/main/java/com/scottlogic/deg/generator/generation/string/CusipStringGenerator.java delete mode 100644 generator/src/main/java/com/scottlogic/deg/generator/generation/string/IsinStringGenerator.java delete mode 100644 generator/src/main/java/com/scottlogic/deg/generator/generation/string/NegatedIsinGenerator.java delete mode 100644 generator/src/main/java/com/scottlogic/deg/generator/generation/string/SedolStringGenerator.java delete mode 100644 generator/src/main/java/com/scottlogic/deg/generator/generation/string/StringGenerator.java delete mode 100644 generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/RegexStreamStringGenerator.java diff --git a/common/src/main/java/com/scottlogic/deg/common/profile/constraints/atomic/StandardConstraintTypes.java b/common/src/main/java/com/scottlogic/deg/common/profile/constraints/atomic/StandardConstraintTypes.java index e56c50b23..3014c3b78 100644 --- a/common/src/main/java/com/scottlogic/deg/common/profile/constraints/atomic/StandardConstraintTypes.java +++ b/common/src/main/java/com/scottlogic/deg/common/profile/constraints/atomic/StandardConstraintTypes.java @@ -17,8 +17,19 @@ package com.scottlogic.deg.common.profile.constraints.atomic; public enum StandardConstraintTypes{ - SEDOL, - ISIN, - CUSIP, - RIC + SEDOL("[B-DF-HJ-NP-TV-Z0-9]{6}[0-9]"), + ISIN("[A-Z]{2}[A-Z0-9]{10}"), + CUSIP("[0-9]{3}[0-9A-Z]{5}[0-9]"), + RIC("[A-Z]{1,4}\\.[A-Z]{1,2}"); + + private final String regex; + + StandardConstraintTypes(String regex) { + + this.regex = regex; + } + + public String getRegex() { + return regex; + } } diff --git a/generator/src/main/java/com/scottlogic/deg/generator/fieldspecs/FieldSpecFactory.java b/generator/src/main/java/com/scottlogic/deg/generator/fieldspecs/FieldSpecFactory.java index 0b2805196..ccc63a025 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/fieldspecs/FieldSpecFactory.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/fieldspecs/FieldSpecFactory.java @@ -30,8 +30,9 @@ import java.util.List; import java.util.regex.Pattern; +import static com.scottlogic.deg.common.profile.constraints.atomic.StandardConstraintTypes.RIC; + public class FieldSpecFactory { - public static final String RIC_REGEX = "[A-Z]{1,4}\\.[A-Z]{1,2}"; private final StringRestrictionsFactory stringRestrictionsFactory; @Inject @@ -256,12 +257,16 @@ private FieldSpec construct(ContainsRegexConstraint constraint, boolean negate) } private FieldSpec construct(MatchesStandardConstraint constraint, boolean negate) { - if (constraint.standard.equals(StandardConstraintTypes.RIC)) { - return construct(new MatchesRegexConstraint(constraint.field, Pattern.compile(RIC_REGEX)), negate); + if (constraint.standard.equals(RIC)) { + return construct(new MatchesRegexConstraint(constraint.field, Pattern.compile(RIC.getRegex())), negate); + } + + if (negate){ + return construct(new MatchesRegexConstraint(constraint.field, Pattern.compile(constraint.standard.getRegex())), negate); } return FieldSpec.Empty - .withStringRestrictions(new MatchesStandardStringRestrictions(constraint.standard, negate)); + .withStringRestrictions(new MatchesStandardStringRestrictions(constraint.standard)); } private FieldSpec construct(FormatConstraint constraint, boolean negate) { diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/StandardFieldValueSourceEvaluator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/StandardFieldValueSourceEvaluator.java index 7f003b58d..a324fc5aa 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/StandardFieldValueSourceEvaluator.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/StandardFieldValueSourceEvaluator.java @@ -25,7 +25,7 @@ import com.scottlogic.deg.generator.generation.fieldvaluesources.RealNumberFieldValueSource; import com.scottlogic.deg.generator.generation.fieldvaluesources.datetime.DateTimeFieldValueSource; import com.scottlogic.deg.generator.generation.string.RegexStringGenerator; -import com.scottlogic.deg.generator.generation.string.StringGenerator; +import com.scottlogic.deg.generator.generation.string.streamy.StreamStringGenerator; import com.scottlogic.deg.generator.restrictions.*; import java.util.*; @@ -115,7 +115,7 @@ private FieldValueSource getStringSource(FieldSpec fieldSpec) { Set blacklist = getBlacklist(fieldSpec); - StringGenerator generator = stringRestrictions.createGenerator(); + StreamStringGenerator generator = stringRestrictions.createGenerator(); if (!blacklist.isEmpty()) { RegexStringGenerator blacklistGenerator = RegexStringGenerator.createFromBlacklist(blacklist); diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/ChecksummedCodeStringGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/ChecksummedCodeStringGenerator.java deleted file mode 100644 index ff9962490..000000000 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/ChecksummedCodeStringGenerator.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright 2019 Scott Logic Ltd - * - * 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.scottlogic.deg.generator.generation.string; - -import com.scottlogic.deg.generator.utils.*; - -import java.util.Arrays; -import java.util.Objects; -import java.util.function.Supplier; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -public abstract class ChecksummedCodeStringGenerator implements StringGenerator { - protected final StringGenerator regexGenerator; - protected final boolean negate; - protected final int prefixLength; - protected final int codeLength; - - public ChecksummedCodeStringGenerator( - String generationPattern, - int codeLength, - int prefixLength - ) { - this( - new RegexStringGenerator(generationPattern, true), - false, - codeLength, - prefixLength - ); - } - - public ChecksummedCodeStringGenerator( - String generationPattern, - RegexStringGenerator intersectingGenerator, - int codeLength, - int prefixLength - ) { - this( - new RegexStringGenerator(generationPattern, true) - .intersect(intersectingGenerator), - false, - codeLength, - prefixLength - ); - } - - public ChecksummedCodeStringGenerator( - StringGenerator generator, - boolean negate, - int codeLength, - int prefixLength - ) { - this.negate = negate; - regexGenerator = generator; - this.codeLength = codeLength; - this.prefixLength = prefixLength; - } - - public abstract char calculateCheckDigit(String str); - - public abstract int getLength(); - - public String fixCheckDigit(String str) { - char checkDigit = calculateCheckDigit(str); - int codeLength = getLength(); - if (str.length() > prefixLength + codeLength) { - return str.substring(0, prefixLength + codeLength - 1) + - checkDigit + str.substring(prefixLength + codeLength); - } - return str.substring(0, str.length() - 1) + checkDigit; - } - - @Override - public StringGenerator intersect(StringGenerator stringGenerator) { - if (stringGenerator instanceof ChecksummedCodeStringGenerator) { - ChecksummedCodeStringGenerator otherGenerator = - (ChecksummedCodeStringGenerator)stringGenerator; - return intersect(otherGenerator.negate ? - otherGenerator.regexGenerator.complement() : - otherGenerator.regexGenerator); - } - if (stringGenerator instanceof RegexStringGenerator) { - return intersect((RegexStringGenerator)stringGenerator); - } - return new NoStringsStringGenerator( - RegexStringGenerator.intersectRepresentation(stringGenerator.toString(), "") - ); - } - - private StringGenerator intersect(RegexStringGenerator other) { - StringGenerator intersection = other.intersect(negate ? regexGenerator.complement() : regexGenerator); - if (!intersection.generateAllValues().iterator().hasNext() || !(intersection instanceof RegexStringGenerator)) { - return new NoStringsStringGenerator( - RegexStringGenerator.intersectRepresentation(other.toString(), regexGenerator.toString()) - ); - } - return instantiate((RegexStringGenerator)intersection); - } - - abstract ChecksummedCodeStringGenerator instantiate(RegexStringGenerator generator); - - @Override - public Iterable generateInterestingValues() { - if (negate) { - return new ConcatenatingIterable<>( - regexGenerator.complement().generateInterestingValues(), - generateInvalidCheckDigitStrings(regexGenerator::generateInterestingValues)); - } - return wrapIterableWithProjectionAndFilter(regexGenerator.generateInterestingValues()); - } - - @Override - public Iterable generateAllValues() { - if (negate) { - return new ConcatenatingIterable<>( - generateAllInvalidRegexStrings(), - generateAllInvalidCheckDigitStrings()); - } - return new FilteringIterable<>( - regexGenerator.generateAllValues(), - (x) -> x.equals(fixCheckDigit(x))); - } - - @Override - public Iterable generateRandomValues(RandomNumberGenerator randomNumberGenerator) { - if (negate) { - return new RandomMergingIterable<>( - Arrays.asList( - generateRandomInvalidRegexStrings(randomNumberGenerator), - generateRandomInvalidCheckDigitStrings(randomNumberGenerator)), - randomNumberGenerator); - } - return wrapIterableWithProjectionAndFilter( - regexGenerator.generateRandomValues(randomNumberGenerator) - ); - } - - private Iterable wrapIterableWithProjectionAndFilter(Iterable iterable) { - return IterableUtils.wrapIterableWithProjectionAndFilter( - iterable, - this::fixCheckDigit, - regexGenerator::match - ); - } - - private Iterable generateAllInvalidRegexStrings() { - return IterableUtils.wrapIterableWithNonEmptyStringCheck( - regexGenerator.complement().generateAllValues() - ); - } - - private Iterable generateRandomInvalidRegexStrings(RandomNumberGenerator randomNumberGenerator) { - return IterableUtils.wrapIterableWithNonEmptyStringCheck( - regexGenerator.complement().generateRandomValues(randomNumberGenerator) - ); - } - - private Iterable generateAllInvalidCheckDigitStrings() { - return generateInvalidCheckDigitStrings(regexGenerator::generateAllValues); - } - - private Iterable generateRandomInvalidCheckDigitStrings(RandomNumberGenerator randomNumberGenerator) { - return generateInvalidCheckDigitStrings( - () -> regexGenerator.generateRandomValues(randomNumberGenerator)); - } - - private Iterable generateInvalidCheckDigitStrings(Supplier> valueSupplier) { - return new FlatteningIterable<>( - valueSupplier.get(), - initialValue -> { - String sansCheckDigit = initialValue.substring( - prefixLength, - prefixLength + codeLength - 1 - ); - final char checkDigit = calculateCheckDigit(sansCheckDigit); - return IntStream.range(0, 10).boxed() - .map(digit -> Character.forDigit(digit, 10)) - .filter(digit -> digit != checkDigit) - .map(digit -> sansCheckDigit + digit) - .collect(Collectors.toList()); - }); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - ChecksummedCodeStringGenerator that = (ChecksummedCodeStringGenerator) o; - return negate == that.negate; - } - - @Override - public int hashCode() { - return Objects.hash(negate, getClass()); - } -} diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/CusipStringGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/CusipStringGenerator.java deleted file mode 100644 index 8b0aae6f5..000000000 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/CusipStringGenerator.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2019 Scott Logic Ltd - * - * 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.scottlogic.deg.generator.generation.string; - -import com.scottlogic.deg.generator.generation.fieldvaluesources.FieldValueSource; -import com.scottlogic.deg.generator.utils.*; - -import static com.scottlogic.deg.generator.generation.string.streamy.ChecksumStringGeneratorFactory.createCusipGenerator; - -public class CusipStringGenerator extends ChecksummedCodeStringGenerator { - public final static int CUSIP_LENGTH = 9; - public final static String STANDARD_REGEX_REPRESENTATION = "[0-9]{3}[0-9A-Z]{5}[0-9]"; - - public CusipStringGenerator() { - super(STANDARD_REGEX_REPRESENTATION, CUSIP_LENGTH, 0); - } - - public CusipStringGenerator(String prefix, String suffix, RegexStringGenerator additionalRestrictions) { - super( - prefix + STANDARD_REGEX_REPRESENTATION + suffix, - additionalRestrictions, - CUSIP_LENGTH, - prefix.length() - ); - } - - private CusipStringGenerator(RegexStringGenerator generator) { - super(generator, false, CUSIP_LENGTH, 0); - } - - private CusipStringGenerator(StringGenerator cusipGenerator, boolean negate) { - super(cusipGenerator, negate, CUSIP_LENGTH, 0); - } - - @Override - public char calculateCheckDigit(String str) { - return FinancialCodeUtils.calculateCusipCheckDigit( - str.substring(prefixLength, CUSIP_LENGTH + prefixLength - 1) - ); - } - - @Override - public int getLength() { - return CUSIP_LENGTH; - } - - @Override - public StringGenerator complement() { - return new CusipStringGenerator(regexGenerator, !negate); - } - - @Override - public boolean match(String subject) { - boolean matches = FinancialCodeUtils.isValidCusipNsin(subject); - return matches != negate; - } - - @Override - ChecksummedCodeStringGenerator instantiate(RegexStringGenerator generator) { - return new CusipStringGenerator(generator); - } - - @Override - public FieldValueSource asFieldValueSource(){ - return new StreamStringGeneratorAsFieldValueSource(createCusipGenerator()); - } -} diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/IsinStringGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/IsinStringGenerator.java deleted file mode 100644 index c57f9aaca..000000000 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/IsinStringGenerator.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright 2019 Scott Logic Ltd - * - * 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.scottlogic.deg.generator.generation.string; - -import com.scottlogic.deg.generator.generation.fieldvaluesources.FieldValueSource; -import com.scottlogic.deg.generator.utils.*; - -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static com.scottlogic.deg.generator.generation.string.streamy.ChecksumStringGeneratorFactory.createIsinGenerator; - -public class IsinStringGenerator implements StringGenerator { - public static final int ISIN_LENGTH = 12; - private static final String GENERIC_NSIN_REGEX = "[A-Z0-9]{9}"; - - // This generator is not used in generation itself, but is used to describe the possible - // range of output values when combining with other string generators. - private RegexStringGenerator isinRegexGenerator; - - public IsinStringGenerator() { - this(getRegexGeneratorForAllLegalIsinFormats()); - } - - IsinStringGenerator(RegexStringGenerator regexGenerator) { - isinRegexGenerator = regexGenerator; - } - - @Override - public StringGenerator intersect(StringGenerator stringGenerator) { - if (stringGenerator instanceof IsinStringGenerator) { - return - new IsinStringGenerator((RegexStringGenerator)isinRegexGenerator - .intersect(((IsinStringGenerator) stringGenerator).isinRegexGenerator)); - } - if (stringGenerator instanceof NegatedIsinGenerator) { - return new NoStringsStringGenerator( - RegexStringGenerator.intersectRepresentation(stringGenerator.toString(), "") - ); - } - if (stringGenerator instanceof ChecksummedCodeStringGenerator) { - // Assume that no other checksummed string format we know about is going to be - // compatible with the ISIN format. This is true at the time of writing. - return new NoStringsStringGenerator( - RegexStringGenerator.intersectRepresentation(stringGenerator.toString(), "") - ); - } - if (stringGenerator instanceof RegexStringGenerator) { - return intersect((RegexStringGenerator)stringGenerator); - } - return new NoStringsStringGenerator( - RegexStringGenerator.intersectRepresentation(stringGenerator.toString(), "") - ); - } - - private StringGenerator intersect(RegexStringGenerator other) { - StringGenerator intersection = - other.intersect(isinRegexGenerator); - if (!(intersection instanceof RegexStringGenerator)) { - return new NoStringsStringGenerator( - RegexStringGenerator.intersectRepresentation( - other.toString(), - isinRegexGenerator.toString() - ) - ); - } - return new IsinStringGenerator((RegexStringGenerator)intersection); - } - - @Override - public StringGenerator complement() { - return new NegatedIsinGenerator(isinRegexGenerator); - } - - @Override - public boolean match(String subject) { - return FinancialCodeUtils.isValidIsin(subject); - } - - @Override - public Iterable generateInterestingValues() { - final List> countryCodeIterables = getAllCountryIsinGeneratorsAsStream() - .limit(2) - .map(generator -> IterableUtils.wrapIterableWithProjectionAndFilter( - generator.generateInterestingValues(), - this::replaceCheckDigit, - isinRegexGenerator::match)) - .collect(Collectors.toList()); - return new ConcatenatingIterable<>(countryCodeIterables); - } - - @Override - public Iterable generateAllValues() { - final List> countryCodeIterables = getAllCountryIsinGeneratorsAsStream() - .map(generator -> new FilteringIterable<>( - generator.generateAllValues(), - (x) -> x.equals(replaceCheckDigit(x)))) - .collect(Collectors.toList()); - return new ConcatenatingIterable<>(countryCodeIterables); - } - - @Override - public Iterable generateRandomValues(RandomNumberGenerator randomNumberGenerator) { - final List> countryCodeIterables = getAllCountryIsinGeneratorsAsStream() - .map(generator -> IterableUtils.wrapIterableWithProjectionAndFilter( - generator.generateRandomValues(randomNumberGenerator), - this::replaceCheckDigit, - isinRegexGenerator::match - )) - .collect(Collectors.toList()); - return new RandomMergingIterable<>(countryCodeIterables, randomNumberGenerator); - } - - private String replaceCheckDigit(String isin) { - String isinWithoutCheckDigit = isin.substring(0, isin.length() - 1); - return isinWithoutCheckDigit + FinancialCodeUtils.calculateIsinCheckDigit(isinWithoutCheckDigit); - } - - private Stream getAllCountryIsinGeneratorsAsStream() { - return FinancialCodeUtils.VALID_COUNTRY_CODES.stream() - .map(this::getIsinGeneratorForCountry); - } - - private StringGenerator getIsinGeneratorForCountry(String countryCode) { - if (countryCode.equals("GB")) { - return new SedolStringGenerator("GB00", "[0-9]", isinRegexGenerator); - } - if (countryCode.equals("US")) { - return new CusipStringGenerator("US", "[0-9]", isinRegexGenerator); - } - return new RegexStringGenerator(countryCode + GENERIC_NSIN_REGEX + "[0-9]", true); - } - - private static RegexStringGenerator getRegexGeneratorForAllLegalIsinFormats() { - Stream countryGenerators = FinancialCodeUtils.VALID_COUNTRY_CODES - .stream() - .map( - country -> new RegexStringGenerator(getIsinRegexRepresentationForCountry(country), true) - ); - RegexStringGenerator.UnionCollector collector = countryGenerators.collect( - RegexStringGenerator.UnionCollector::new, - RegexStringGenerator.UnionCollector::accumulate, - RegexStringGenerator.UnionCollector::combine - ); - return collector.getUnionGenerator(); - } - - private static String getIsinRegexRepresentationForCountrySansCheckDigit(String countryCode) { - if (countryCode.equals("GB")) { - return "GB00" + SedolStringGenerator.STANDARD_REGEX_REPRESENTATION; - } - else if (countryCode.equals("US")) { - return "US" + CusipStringGenerator.STANDARD_REGEX_REPRESENTATION; - } - else { - return countryCode + GENERIC_NSIN_REGEX; - } - } - - private static String getIsinRegexRepresentationForCountry(String countryCode) { - return getIsinRegexRepresentationForCountrySansCheckDigit(countryCode) + "[0-9]"; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - IsinStringGenerator that = (IsinStringGenerator) o; - return Objects.equals(this.isinRegexGenerator, that.isinRegexGenerator); - } - - @Override - public int hashCode() { - return Objects.hash(isinRegexGenerator); - } - - @Override - public FieldValueSource asFieldValueSource(){ - return new StreamStringGeneratorAsFieldValueSource(createIsinGenerator()); - } -} diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/NegatedIsinGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/NegatedIsinGenerator.java deleted file mode 100644 index 0cc57534c..000000000 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/NegatedIsinGenerator.java +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Copyright 2019 Scott Logic Ltd - * - * 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.scottlogic.deg.generator.generation.string; - -import com.scottlogic.deg.generator.utils.*; - -import java.util.Arrays; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import java.util.stream.Stream; - -public class NegatedIsinGenerator implements StringGenerator { - private static final String GENERIC_NSIN_REGEX = "[A-Z0-9]{9}"; - - // This generator is not used in generation itself, but is used to describe the possible - // range of output values when combining with other string generators. - private RegexStringGenerator isinRegexGenerator; - private StringGenerator notIsinRegexGenerator; - - - public NegatedIsinGenerator(RegexStringGenerator isinRegexGenerator) { - this.isinRegexGenerator = isinRegexGenerator; - notIsinRegexGenerator = isinRegexGenerator.complement(); - } - - @Override - public StringGenerator intersect(StringGenerator stringGenerator) { - if (stringGenerator instanceof NegatedIsinGenerator) { - RegexStringGenerator otherRegexGenerator = - ((NegatedIsinGenerator) stringGenerator).isinRegexGenerator; - return new NegatedIsinGenerator(isinRegexGenerator.union(otherRegexGenerator)); - } - if (stringGenerator instanceof IsinStringGenerator) { - return new NoStringsStringGenerator( - RegexStringGenerator.intersectRepresentation(stringGenerator.toString(), "") - ); - } - if (stringGenerator instanceof ChecksummedCodeStringGenerator) { - return stringGenerator; - } - if (stringGenerator instanceof RegexStringGenerator) { - return stringGenerator.intersect(notIsinRegexGenerator); - } - return new NoStringsStringGenerator( - RegexStringGenerator.intersectRepresentation(stringGenerator.toString(), "") - ); - } - - @Override - public StringGenerator complement() { - return new IsinStringGenerator(isinRegexGenerator); - } - - @Override - public boolean match(String subject) { - return !FinancialCodeUtils.isValidIsin(subject); - } - - @Override - public Iterable generateInterestingValues() { - return new ConcatenatingIterable<>( - Arrays.asList( - generateInterestingInvalidCountryStrings(), - generateInterestingCountriesWithInvalidNsins(), - generateInterestingInvalidCheckDigitIsins())); - } - - @Override - public Iterable generateAllValues() { - return new ConcatenatingIterable<>( - Arrays.asList( - generateAllInvalidCountryStrings(), - generateAllCountriesWithInvalidNsins(), - generateAllInvalidCheckDigitIsins())); - } - - @Override - public Iterable generateRandomValues(RandomNumberGenerator randomNumberGenerator) { - return new RandomMergingIterable<>( - Arrays.asList( - generateRandomInvalidCountryStrings(randomNumberGenerator), - generateRandomCountriesWithInvalidNsins(randomNumberGenerator), - generateRandomInvalidCheckDigitIsins(randomNumberGenerator)), - randomNumberGenerator); - } - - private Iterable generateInterestingInvalidCountryStrings() { - final String invalidCountryCodeRegex = FinancialCodeUtils.VALID_COUNTRY_CODES.stream() - .limit(2) - .collect(Collectors.joining("|", "((?!", ")).*")); - return new RegexStringGenerator(invalidCountryCodeRegex, true).generateInterestingValues(); - } - - private Iterable generateAllInvalidCountryStrings() { - final String invalidCountryCodeRegex = FinancialCodeUtils.VALID_COUNTRY_CODES.stream() - .collect(Collectors.joining("|", "((?!", ")).*")); - return new RegexStringGenerator(invalidCountryCodeRegex, true).generateAllValues(); - } - - private Iterable generateRandomInvalidCountryStrings(RandomNumberGenerator randomNumberGenerator) { - final String invalidCountryCodeRegex = FinancialCodeUtils.VALID_COUNTRY_CODES.stream() - .collect(Collectors.joining("|", "((?!", ")).*")); - return new RegexStringGenerator(invalidCountryCodeRegex, true).generateRandomValues(randomNumberGenerator); - } - - private static Iterable generateInterestingCountriesWithInvalidNsins() { - final List> countryWithInvalidNsinIterables = FinancialCodeUtils.VALID_COUNTRY_CODES.stream() - .limit(2) - .map(countryCode -> { - final StringGenerator nsinGeneratorForCountry = getNsinGeneratorForCountry(countryCode); - final Iterable invalidNsinIterators = nsinGeneratorForCountry.complement().generateInterestingValues(); - return new ProjectingIterable<>(invalidNsinIterators, invalidNsin -> countryCode + invalidNsin); - }) - .collect(Collectors.toList()); - return new FilteringIterable<>(new ConcatenatingIterable<>(countryWithInvalidNsinIterables), - isin -> !FinancialCodeUtils.isValidIsin(isin)); - } - - private static Iterable generateAllCountriesWithInvalidNsins() { - final List> countryWithInvalidNsinIterables = FinancialCodeUtils.VALID_COUNTRY_CODES.stream() - .map(countryCode -> { - final StringGenerator nsinGeneratorForCountry = getNsinGeneratorForCountry(countryCode); - final Iterable invalidNsinIterators = nsinGeneratorForCountry.complement().generateAllValues(); - return new ProjectingIterable<>(invalidNsinIterators, invalidNsin -> countryCode + invalidNsin); - }) - .collect(Collectors.toList()); - return new FilteringIterable<>(new ConcatenatingIterable<>(countryWithInvalidNsinIterables), - isin -> !FinancialCodeUtils.isValidIsin(isin)); - } - - private static Iterable generateRandomCountriesWithInvalidNsins(RandomNumberGenerator randomNumberGenerator) { - final List> countryWithInvalidNsinIterables = FinancialCodeUtils.VALID_COUNTRY_CODES.stream() - .map(countryCode -> { - final StringGenerator nsinGeneratorForCountry = getNsinGeneratorForCountry(countryCode); - final Iterable invalidNsinIterators = nsinGeneratorForCountry.complement().generateRandomValues(randomNumberGenerator); - return new ProjectingIterable<>(invalidNsinIterators, invalidNsin -> countryCode + invalidNsin); - }) - .collect(Collectors.toList()); - return new FilteringIterable<>(new RandomMergingIterable<>(countryWithInvalidNsinIterables, randomNumberGenerator), - isin -> !FinancialCodeUtils.isValidIsin(isin)); - } - - private Iterable generateInterestingInvalidCheckDigitIsins() { - final List> countryCodeIterables = getAllCountryIsinGeneratorsAsStream() - .limit(2) - .map(isinSansCheckDigitGenerator -> - new FlatteningIterable<>( - isinSansCheckDigitGenerator.generateInterestingValues(), - isinSansCheckDigit -> { - final char checkDigit = FinancialCodeUtils.calculateIsinCheckDigit(isinSansCheckDigit); - return IntStream.range(0, 10).boxed() - .map(digit -> Character.forDigit(digit, 10)) - .filter(digit -> digit != checkDigit) - .map(digit -> isinSansCheckDigit + digit) - .collect(Collectors.toList()); - })) - .collect(Collectors.toList()); - return new ConcatenatingIterable<>(countryCodeIterables); - } - - private Iterable generateAllInvalidCheckDigitIsins() { - final List> countryCodeIterables = getAllCountryIsinGeneratorsAsStream() - .map(isinSansCheckDigitGenerator -> - new FlatteningIterable<>( - isinSansCheckDigitGenerator.generateAllValues(), - isinSansCheckDigit -> { - final char checkDigit = FinancialCodeUtils.calculateIsinCheckDigit(isinSansCheckDigit); - return IntStream.range(0, 10).boxed() - .map(digit -> Character.forDigit(digit, 10)) - .filter(digit -> digit != checkDigit) - .map(digit -> isinSansCheckDigit + digit) - .collect(Collectors.toList()); - })) - .collect(Collectors.toList()); - return new ConcatenatingIterable<>(countryCodeIterables); - } - - private Iterable generateRandomInvalidCheckDigitIsins(RandomNumberGenerator randomNumberGenerator) { - final List> countryCodeIterables = getAllCountryIsinGeneratorsAsStream() - .map(isinSansCheckDigitGenerator -> - new FlatteningIterable<>( - isinSansCheckDigitGenerator.generateRandomValues(randomNumberGenerator), - isinSansCheckDigit -> { - final char checkDigit = FinancialCodeUtils.calculateIsinCheckDigit(isinSansCheckDigit); - return IntStream.range(0, 10).boxed() - .map(digit -> Character.forDigit(digit, 10)) - .filter(digit -> digit != checkDigit) - .map(digit -> isinSansCheckDigit + digit) - .collect(Collectors.toList()); - })) - .collect(Collectors.toList()); - return new RandomMergingIterable<>(countryCodeIterables, randomNumberGenerator); - } - - private Stream getAllCountryIsinGeneratorsAsStream() { - return FinancialCodeUtils.VALID_COUNTRY_CODES.stream() - .map(this::getIsinGeneratorForCountry); - } - - private StringGenerator getIsinGeneratorForCountry(String countryCode) { - if (countryCode.equals("GB")) { - return new SedolStringGenerator("GB00", "[0-9]", isinRegexGenerator); - } - if (countryCode.equals("US")) { - return new CusipStringGenerator("US", "[0-9]", isinRegexGenerator); - } - return new RegexStringGenerator(countryCode + GENERIC_NSIN_REGEX + "[0-9]", true); - } - - private static StringGenerator getNsinGeneratorForCountry(String countryCode) { - if (countryCode.equals("GB")) { - return new SedolStringGenerator("00"); - } - if (countryCode.equals("US")) { - return new CusipStringGenerator(); - } - return new RegexStringGenerator(GENERIC_NSIN_REGEX, true); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - NegatedIsinGenerator that = (NegatedIsinGenerator) o; - return Objects.equals(this.isinRegexGenerator, that.isinRegexGenerator); - } - - @Override - public int hashCode() { - return Objects.hash(isinRegexGenerator); - } -} diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/NoStringsStringGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/NoStringsStringGenerator.java index 635821317..59b98bd80 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/NoStringsStringGenerator.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/NoStringsStringGenerator.java @@ -16,12 +16,14 @@ package com.scottlogic.deg.generator.generation.string; +import com.scottlogic.deg.generator.generation.string.streamy.StreamStringGenerator; import com.scottlogic.deg.generator.utils.RandomNumberGenerator; import java.util.Arrays; import java.util.Collections; +import java.util.stream.Stream; -public class NoStringsStringGenerator implements StringGenerator { +public class NoStringsStringGenerator implements StreamStringGenerator { private final String stringRepresentation; public NoStringsStringGenerator(String stringRepresentation) { @@ -33,34 +35,22 @@ public String toString() { return String.format("No strings: %s", this.stringRepresentation); } - @Override - public StringGenerator intersect(StringGenerator stringGenerator) { - return new NoStringsStringGenerator( - RegexStringGenerator.intersectRepresentation(this.stringRepresentation, stringGenerator.toString())); - } - - @Override - public StringGenerator complement() { - throw new RuntimeException("Not implemented: Return a string generator able to emit ALL strings"); - } - - @Override - public boolean match(String subject) { + public boolean matches(String subject) { return false; } @Override - public Iterable generateInterestingValues() { - return Collections.emptySet(); + public Stream generateInterestingValues() { + return Stream.empty(); } @Override - public Iterable generateAllValues() { - return Collections.emptySet(); + public Stream generateAllValues() { + return Stream.empty(); } @Override - public Iterable generateRandomValues(RandomNumberGenerator randomNumberGenerator) { - return Collections.emptySet(); + public Stream generateRandomValues(RandomNumberGenerator randomNumberGenerator) { + return Stream.empty(); } } diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/RegexStringGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/RegexStringGenerator.java index faa179c26..2ca7fe0c8 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/RegexStringGenerator.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/RegexStringGenerator.java @@ -19,6 +19,7 @@ import com.scottlogic.deg.generator.generation.string.factorys.FiniteStringAutomatonIterator; import com.scottlogic.deg.generator.generation.string.factorys.InterestingStringFactory; import com.scottlogic.deg.generator.generation.string.factorys.RandomStringFactory; +import com.scottlogic.deg.generator.generation.string.streamy.StreamStringGenerator; import com.scottlogic.deg.generator.utils.RandomNumberGenerator; import com.scottlogic.deg.generator.utils.SupplierBasedIterator; import dk.brics.automaton.Automaton; @@ -26,10 +27,12 @@ import dk.brics.automaton.Transition; import java.util.*; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; import static com.scottlogic.deg.common.util.NumberUtils.*; -public class RegexStringGenerator implements StringGenerator { +public class RegexStringGenerator implements StreamStringGenerator { /** * Cache of all matching regex automatons, keyed on their regex @@ -85,7 +88,7 @@ public static RegexStringGenerator createFromBlacklist(Set blacklist) { } @Override - public StringGenerator intersect(StringGenerator otherGenerator) { + public StreamStringGenerator intersect(StreamStringGenerator otherGenerator) { if (otherGenerator instanceof NoStringsStringGenerator) { return otherGenerator.intersect(this); } @@ -103,7 +106,7 @@ public StringGenerator intersect(StringGenerator otherGenerator) { String mergedRepresentation = intersectRepresentation( this.regexRepresentation, - otherRegexGenerator.regexRepresentation); + ((RegexStringGenerator)otherGenerator).regexRepresentation); return new RegexStringGenerator(merged, mergedRepresentation); } @@ -119,7 +122,7 @@ RegexStringGenerator union(RegexStringGenerator otherGenerator) { } @Override - public StringGenerator complement() { + public StreamStringGenerator complement() { return new RegexStringGenerator( this.automaton.clone().complement(), complementaryRepresentation(this.regexRepresentation)); @@ -138,31 +141,30 @@ static String unionRepresentation(String left, String right) { } @Override - public Iterable generateInterestingValues() { - return interestingStringFactory.generateInterestingValues(automaton); + public Stream generateInterestingValues() { + return StreamSupport.stream(interestingStringFactory.generateInterestingValues(automaton).spliterator(), false); } @Override - public Iterable generateAllValues() { - return () -> new FiniteStringAutomatonIterator(automaton); + public Stream generateAllValues() { + Iterator iterator = new FiniteStringAutomatonIterator(automaton); + return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.SORTED), false); } @Override - public Iterable generateRandomValues(RandomNumberGenerator randomNumberGenerator) { - return () -> new SupplierBasedIterator<>( + public Stream generateRandomValues(RandomNumberGenerator randomNumberGenerator) { + final Iterable iterable = () -> new SupplierBasedIterator<>( () -> randomStringFactory.createRandomString( "", automaton.getInitialState(), 1, Integer.MAX_VALUE, randomNumberGenerator)); + return StreamSupport.stream(iterable.spliterator(), false); } - @Override - public boolean match(String subject) { - + public boolean matches(String subject) { return automaton.run(subject); - } public boolean equals(Object o) { diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/SedolStringGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/SedolStringGenerator.java deleted file mode 100644 index 8831faeba..000000000 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/SedolStringGenerator.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2019 Scott Logic Ltd - * - * 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.scottlogic.deg.generator.generation.string; - -import com.scottlogic.deg.generator.generation.fieldvaluesources.FieldValueSource; -import com.scottlogic.deg.generator.utils.*; - -import static com.scottlogic.deg.generator.generation.string.streamy.ChecksumStringGeneratorFactory.createSedolGenerator; - -public class SedolStringGenerator extends ChecksummedCodeStringGenerator { - public final static int SEDOL_LENGTH = 7; - public final static String STANDARD_REGEX_REPRESENTATION = "[B-DF-HJ-NP-TV-Z0-9]{6}[0-9]"; - - public SedolStringGenerator() { - super(STANDARD_REGEX_REPRESENTATION, SEDOL_LENGTH, 0); - } - - public SedolStringGenerator(String prefix) { this(prefix, ""); } - - public SedolStringGenerator(String prefix, String suffix) { - super(prefix + STANDARD_REGEX_REPRESENTATION + suffix, SEDOL_LENGTH, 0); - } - - public SedolStringGenerator(String prefix, String suffix, RegexStringGenerator additionalRestrictions) { - super(prefix + STANDARD_REGEX_REPRESENTATION + suffix, additionalRestrictions, SEDOL_LENGTH, prefix.length()); - } - - private SedolStringGenerator(RegexStringGenerator sedolGenerator) { - super(sedolGenerator, false, SEDOL_LENGTH, 0); - } - - private SedolStringGenerator(StringGenerator sedolGenerator, boolean negate) { - super(sedolGenerator, negate, SEDOL_LENGTH, 0); - } - - @Override - public char calculateCheckDigit(String str) { - return FinancialCodeUtils.calculateSedolCheckDigit( - str.substring(prefixLength, SEDOL_LENGTH + prefixLength - 1) - ); - } - - @Override - public int getLength() { - return SEDOL_LENGTH; - } - - @Override - public StringGenerator complement() { - return new SedolStringGenerator(regexGenerator, !negate); - } - - @Override - public boolean match(String subject) { - boolean matches = FinancialCodeUtils.isValidSedolNsin(subject, prefixLength); - return matches != negate; - } - - @Override - ChecksummedCodeStringGenerator instantiate(RegexStringGenerator generator) { - return new SedolStringGenerator(generator); - } - - @Override - public FieldValueSource asFieldValueSource(){ - return new StreamStringGeneratorAsFieldValueSource(createSedolGenerator()); - } -} diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/StringGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/StringGenerator.java deleted file mode 100644 index 1c7b3123b..000000000 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/StringGenerator.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2019 Scott Logic Ltd - * - * 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.scottlogic.deg.generator.generation.string; - -import com.scottlogic.deg.generator.generation.fieldvaluesources.FieldValueSource; -import com.scottlogic.deg.generator.generation.string.streamy.StreamStringGenerator; -import com.scottlogic.deg.generator.utils.RandomNumberGenerator; -import com.scottlogic.deg.generator.utils.UpCastingIterator; - -import java.util.stream.StreamSupport; - -public interface StringGenerator { - StringGenerator intersect(StringGenerator stringGenerator); - StringGenerator complement(); - - boolean match(String subject); - - Iterable generateInterestingValues(); - - Iterable generateAllValues(); - - Iterable generateRandomValues(RandomNumberGenerator randomNumberGenerator); - - default FieldValueSource asFieldValueSource() { - return new StringGeneratorAsFieldValueSource(this); - } - - // Adapter - class StringGeneratorAsFieldValueSource implements FieldValueSource { - private final StringGenerator underlyingGenerator; - - StringGeneratorAsFieldValueSource(StringGenerator underlyingGenerator) { - this.underlyingGenerator = underlyingGenerator; - } - - @Override - public Iterable generateInterestingValues() { - return () -> new UpCastingIterator<>( - underlyingGenerator.generateInterestingValues().iterator()); - } - - @Override - public Iterable generateAllValues() { - return () -> new UpCastingIterator<>( - underlyingGenerator.generateAllValues().iterator()); - } - - @Override - public Iterable generateRandomValues(RandomNumberGenerator randomNumberGenerator) { - return () -> new UpCastingIterator<>( - underlyingGenerator.generateRandomValues(randomNumberGenerator).iterator()); - } - } - - class StreamStringGeneratorAsFieldValueSource implements FieldValueSource { - - private final StreamStringGenerator underlyingGenerator; - - public StreamStringGeneratorAsFieldValueSource(StreamStringGenerator underlyingGenerator) { - this.underlyingGenerator = underlyingGenerator; - } - - @Override - public Iterable generateInterestingValues() { - return () -> new UpCastingIterator<>( - underlyingGenerator.generateInterestingValues().iterator()); - } - - @Override - public Iterable generateAllValues() { - return () -> new UpCastingIterator<>( - underlyingGenerator.generateAllValues().iterator()); - } - - @Override - public Iterable generateRandomValues(RandomNumberGenerator randomNumberGenerator) { - return () -> new UpCastingIterator<>( - underlyingGenerator.generateRandomValues(randomNumberGenerator).iterator()); - } - } -} diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumStreamStringGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumStreamStringGenerator.java index 5d05640f0..77aab0100 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumStreamStringGenerator.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumStreamStringGenerator.java @@ -46,4 +46,16 @@ public Stream generateInterestingValues() { return checksumlessGenerator.generateInterestingValues() .map(string -> string + checksumMaker.makeChecksum(string)); } + + @Override + public boolean matches(String string) { + if (string.length() < 1) { + return false; + } + String preChecksumComponent = string.substring(0, string.length() - 1); + Character checksumComponent = string.charAt(string.length() - 1); + return + checksumlessGenerator.matches(preChecksumComponent) && + checksumMaker.makeChecksum(preChecksumComponent).equals(checksumComponent); + } } diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumStringGeneratorFactory.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumStringGeneratorFactory.java index 2cf4ea496..3cb76e557 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumStringGeneratorFactory.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumStringGeneratorFactory.java @@ -15,19 +15,20 @@ */ package com.scottlogic.deg.generator.generation.string.streamy; +import com.scottlogic.deg.generator.generation.string.RegexStringGenerator; import com.scottlogic.deg.generator.utils.FinancialCodeUtils; public class ChecksumStringGeneratorFactory { public static StreamStringGenerator createSedolGenerator() { return new ChecksumStreamStringGenerator( - new RegexStreamStringGenerator("[B-DF-HJ-NP-TV-Z0-9]{6}"), + new RegexStringGenerator("[B-DF-HJ-NP-TV-Z0-9]{6}", true), FinancialCodeUtils::calculateSedolCheckDigit); } public static StreamStringGenerator createCusipGenerator() { return new ChecksumStreamStringGenerator( - new RegexStreamStringGenerator("[0-9]{3}[0-9A-Z]{5}"), + new RegexStringGenerator("[0-9]{3}[0-9A-Z]{5}", true), FinancialCodeUtils::calculateCusipCheckDigit); } diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumlessIsinGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumlessIsinGenerator.java index 4b18ca36c..5cda3ea9c 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumlessIsinGenerator.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumlessIsinGenerator.java @@ -53,4 +53,13 @@ private IsinCountryCode getRandomCountryCode(RandomNumberGenerator randomNumberG public Stream generateInterestingValues() { return generateAllValues().limit(2); } + + @Override + public boolean matches(String string) { + Stream isinStringGenerators = + Arrays.stream(IsinCountryCode.values()) + .map(IsinCountryCode::getChecksumlessStringGenerator); + + return isinStringGenerators.anyMatch(generator -> generator.matches(string)); + } } diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/IsinCountryCode.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/IsinCountryCode.java index 1b79d4f59..3aeb21fde 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/IsinCountryCode.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/IsinCountryCode.java @@ -16,6 +16,8 @@ package com.scottlogic.deg.generator.generation.string.streamy; +import com.scottlogic.deg.generator.generation.string.RegexStringGenerator; + import static com.scottlogic.deg.generator.generation.string.streamy.ChecksumStringGeneratorFactory.createCusipGenerator; import static com.scottlogic.deg.generator.generation.string.streamy.ChecksumStringGeneratorFactory.createSedolGenerator; @@ -29,7 +31,7 @@ public enum IsinCountryCode { IsinCountryCode(){ checksumlessStringGenerator = prefix(this.name(), - new RegexStreamStringGenerator(GENERIC_NSIN_REGEX)); + new RegexStringGenerator(GENERIC_NSIN_REGEX, true)); } IsinCountryCode(StreamStringGenerator streamStringGenerator){ diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/PrefixingStreamStringGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/PrefixingStreamStringGenerator.java index f84e91dc7..09c57caba 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/PrefixingStreamStringGenerator.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/PrefixingStreamStringGenerator.java @@ -46,4 +46,16 @@ public Stream generateInterestingValues() { return innerGenerator.generateInterestingValues() .map(string -> prefix + string); } + + @Override + public boolean matches(String string) { + if (string.length() < prefix.length()) { + return false; + } + String candidatePrefix = string.substring(0, prefix.length()); + if (!candidatePrefix.equals(prefix)) { + return false; + } + return innerGenerator.matches(string.substring(prefix.length())); + } } diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/RegexStreamStringGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/RegexStreamStringGenerator.java deleted file mode 100644 index 129a68eb9..000000000 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/RegexStreamStringGenerator.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2019 Scott Logic Ltd - * - * 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.scottlogic.deg.generator.generation.string.streamy; - -import com.scottlogic.deg.generator.generation.string.RegexStringGenerator; -import com.scottlogic.deg.generator.utils.RandomNumberGenerator; - -import java.util.stream.Stream; -import java.util.stream.StreamSupport; - -public class RegexStreamStringGenerator implements StreamStringGenerator{ - private final RegexStringGenerator regexStringGenerator; - - public RegexStreamStringGenerator(String regex) { - this.regexStringGenerator = new RegexStringGenerator(regex, true); - } - - @Override - public Stream generateAllValues() { - return StreamSupport.stream(regexStringGenerator.generateAllValues().spliterator(), false); - } - - @Override - public Stream generateRandomValues(RandomNumberGenerator randomNumberGenerator) { - return StreamSupport.stream(regexStringGenerator.generateRandomValues(randomNumberGenerator).spliterator(), false); - } - - @Override - public Stream generateInterestingValues() { - return StreamSupport.stream(regexStringGenerator.generateInterestingValues().spliterator(), false); - } -} diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/StreamStringGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/StreamStringGenerator.java index b491d0186..37b3dbb6c 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/StreamStringGenerator.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/StreamStringGenerator.java @@ -15,7 +15,10 @@ */ package com.scottlogic.deg.generator.generation.string.streamy; +import com.scottlogic.deg.generator.generation.fieldvaluesources.FieldValueSource; +import com.scottlogic.deg.generator.generation.string.NoStringsStringGenerator; import com.scottlogic.deg.generator.utils.RandomNumberGenerator; +import com.scottlogic.deg.generator.utils.UpCastingIterator; import java.util.stream.Stream; @@ -25,4 +28,48 @@ public interface StreamStringGenerator { Stream generateRandomValues(RandomNumberGenerator randomNumberGenerator); Stream generateInterestingValues(); + + boolean matches(String string); + + default StreamStringGenerator intersect(StreamStringGenerator stringGenerator){ + if (this.getClass().equals(stringGenerator.getClass())){ + return this; + } + return new NoStringsStringGenerator("can't merge non standard strings"); + } + + default StreamStringGenerator complement() { + throw new UnsupportedOperationException(); + } + + default FieldValueSource asFieldValueSource() { + return new StringGeneratorAsFieldValueSource(this); + } + + // Adapter + class StringGeneratorAsFieldValueSource implements FieldValueSource { + private final StreamStringGenerator underlyingGenerator; + + StringGeneratorAsFieldValueSource(StreamStringGenerator underlyingGenerator) { + this.underlyingGenerator = underlyingGenerator; + } + + @Override + public Iterable generateInterestingValues() { + return () -> new UpCastingIterator<>( + underlyingGenerator.generateInterestingValues().iterator()); + } + + @Override + public Iterable generateAllValues() { + return () -> new UpCastingIterator<>( + underlyingGenerator.generateAllValues().iterator()); + } + + @Override + public Iterable generateRandomValues(RandomNumberGenerator randomNumberGenerator) { + return () -> new UpCastingIterator<>( + underlyingGenerator.generateRandomValues(randomNumberGenerator).iterator()); + } + } } diff --git a/generator/src/main/java/com/scottlogic/deg/generator/restrictions/MatchesStandardStringRestrictions.java b/generator/src/main/java/com/scottlogic/deg/generator/restrictions/MatchesStandardStringRestrictions.java index 6f9bd2414..271259d6e 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/restrictions/MatchesStandardStringRestrictions.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/restrictions/MatchesStandardStringRestrictions.java @@ -17,10 +17,10 @@ package com.scottlogic.deg.generator.restrictions; import com.scottlogic.deg.common.profile.constraints.atomic.StandardConstraintTypes; -import com.scottlogic.deg.generator.generation.string.CusipStringGenerator; -import com.scottlogic.deg.generator.generation.string.IsinStringGenerator; -import com.scottlogic.deg.generator.generation.string.SedolStringGenerator; -import com.scottlogic.deg.generator.generation.string.StringGenerator; +import com.scottlogic.deg.generator.generation.string.*; +import com.scottlogic.deg.generator.generation.string.streamy.StreamStringGenerator; + +import static com.scottlogic.deg.generator.generation.string.streamy.ChecksumStringGeneratorFactory.*; /** * Represents the restriction of a field to an `aValid` operator @@ -28,38 +28,28 @@ */ public class MatchesStandardStringRestrictions implements StringRestrictions{ private final StandardConstraintTypes type; - private final boolean negated; - private StringGenerator generator; + private StreamStringGenerator generator; - public MatchesStandardStringRestrictions(StandardConstraintTypes type, boolean negated) { + public MatchesStandardStringRestrictions(StandardConstraintTypes type) { this.type = type; - this.negated = negated; } @Override public boolean match(String x) { - return createGenerator().match(x); + return createGenerator().matches(x); } - public StringGenerator createGenerator() { - StringGenerator generator = getStringGenerator(); - - return negated - ? generator.complement() - : generator; - } - - private StringGenerator getStringGenerator() { + public StreamStringGenerator createGenerator() { if (generator == null) { switch (type) { case ISIN: - generator = new IsinStringGenerator(); + generator = createIsinGenerator(); break; case SEDOL: - generator = new SedolStringGenerator(); + generator = createSedolGenerator(); break; case CUSIP: - generator = new CusipStringGenerator(); + generator = createCusipGenerator(); break; default: throw new UnsupportedOperationException(String.format("Unable to create string generator for: %s", type)); @@ -68,34 +58,10 @@ private StringGenerator getStringGenerator() { return generator; } - /** - * Will combine/intersect another StringRestrictions within this instance - * - * Rules are: - * Return this instance within modification if the other restrictions matches the following: - * 1. It is an equivalent MatchesStandardStringRestrictions instance (all properties match) - * 2. It is a TextualRestrictions that has: - * 2.1. no regex restrictions of any kind - * 2.2. any present length restrictions do not impact the ability to create any value - * - * @param other The other restrictions to combine/intersect - * @return Either this instance (success) or a NoStringsPossibleStringRestrictions if the other restrictions could not be merged or intersected - */ @Override public MergeResult intersect(StringRestrictions other) { if (other instanceof TextualRestrictions){ - TextualRestrictions textualRestrictions = (TextualRestrictions) other; - StringGenerator combinedGenerator = getCombinedGenerator(textualRestrictions); - - if (!combinedGenerator.generateAllValues().iterator().hasNext()){ - return MergeResult.unsuccessful(); - } - - return new MergeResult<>(copyWithGenerator(combinedGenerator)); - } - - if (!(other instanceof MatchesStandardStringRestrictions)){ - return MergeResult.unsuccessful(); + return isLengthAcceptable((TextualRestrictions) other); } MatchesStandardStringRestrictions that = (MatchesStandardStringRestrictions) other; @@ -103,61 +69,29 @@ public MergeResult intersect(StringRestrictions other) { return MergeResult.unsuccessful(); } - return that.negated == negated - ? new MergeResult<>(this) - : MergeResult.unsuccessful(); + return new MergeResult<>(this); } - private StringGenerator getCombinedGenerator(TextualRestrictions textualRestrictions) { - StringGenerator ourGenerator = getStringGenerator(); - return ourGenerator.intersect(textualRestrictions.createGenerator()); - } + private MergeResult isLengthAcceptable(TextualRestrictions other) { + if (anyRegexes(other)){ + return MergeResult.unsuccessful(); + } - private MatchesStandardStringRestrictions copyWithGenerator(StringGenerator generator) { - MatchesStandardStringRestrictions newRestrictions = - new MatchesStandardStringRestrictions(type, negated); - newRestrictions.generator = generator; - return newRestrictions; - } + StreamStringGenerator intersect = other.createGenerator().intersect(new RegexStringGenerator(type.getRegex(), true)); - private enum Impact - { - /** - * There is definitely a partial impact on value production, but its level is - * currently unknown. - */ - PARTIAL, - - /** - * There is potentially no impact on the production of values - */ - NONE, - - /** - * The impact is such that values definitely cannot be produced. - */ - FULL + if (intersect instanceof NoStringsStringGenerator){ + return MergeResult.unsuccessful(); + } + + return new MergeResult<>(this); } - private int getCodeLength(StandardConstraintTypes type) { - switch (type) - { - case ISIN: - return IsinStringGenerator.ISIN_LENGTH; - case SEDOL: - return SedolStringGenerator.SEDOL_LENGTH; - case CUSIP: - return CusipStringGenerator.CUSIP_LENGTH; - default: - throw new UnsupportedOperationException(String.format("Unable to check string restrictions for: %s", type)); - } + private boolean anyRegexes(TextualRestrictions other) { + return !other.containingRegex.isEmpty() || !other.matchingRegex.isEmpty() || !other.notContainingRegex.isEmpty() || !other.notMatchingRegex.isEmpty(); } @Override public String toString() { - if (negated){ - return "not " + type.name(); - } return type.name(); } } diff --git a/generator/src/main/java/com/scottlogic/deg/generator/restrictions/StringRestrictions.java b/generator/src/main/java/com/scottlogic/deg/generator/restrictions/StringRestrictions.java index 8a330f4d8..cc3fbf162 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/restrictions/StringRestrictions.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/restrictions/StringRestrictions.java @@ -17,7 +17,7 @@ package com.scottlogic.deg.generator.restrictions; import com.scottlogic.deg.common.profile.constraints.atomic.IsOfTypeConstraint; -import com.scottlogic.deg.generator.generation.string.StringGenerator; +import com.scottlogic.deg.generator.generation.string.streamy.StreamStringGenerator; public interface StringRestrictions extends TypedRestrictions { MergeResult intersect(StringRestrictions other); @@ -34,7 +34,7 @@ default boolean match(Object x) { return isInstanceOf(x) && match((String) x); } - StringGenerator createGenerator(); + StreamStringGenerator createGenerator(); } diff --git a/generator/src/main/java/com/scottlogic/deg/generator/restrictions/TextualRestrictions.java b/generator/src/main/java/com/scottlogic/deg/generator/restrictions/TextualRestrictions.java index 4c74e6aeb..b260645aa 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/restrictions/TextualRestrictions.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/restrictions/TextualRestrictions.java @@ -18,7 +18,7 @@ import com.scottlogic.deg.generator.generation.string.NoStringsStringGenerator; import com.scottlogic.deg.generator.generation.string.RegexStringGenerator; -import com.scottlogic.deg.generator.generation.string.StringGenerator; +import com.scottlogic.deg.generator.generation.string.streamy.StreamStringGenerator; import com.scottlogic.deg.generator.utils.SetUtils; import java.util.*; @@ -36,7 +36,7 @@ public class TextualRestrictions implements StringRestrictions { final Set containingRegex; final Set notMatchingRegex; final Set notContainingRegex; - private StringGenerator generator; + private StreamStringGenerator generator; TextualRestrictions( Integer minLength, @@ -57,7 +57,7 @@ public class TextualRestrictions implements StringRestrictions { @Override public boolean match(String x) { - return createGenerator().match(x); + return createGenerator().matches(x); } /** @@ -104,7 +104,7 @@ private boolean isContradictory() { return false; //no regular expressions exist that can contradict } - StringGenerator generator = createGenerator(); + StreamStringGenerator generator = createGenerator(); return generator instanceof NoStringsStringGenerator; } @@ -148,8 +148,8 @@ public boolean match(Object o) { } String s = (String) o; - StringGenerator generator = createGenerator(); - return generator == null || generator.match(s); + StreamStringGenerator generator = createGenerator(); + return generator == null || generator.matches(s); } /** @@ -158,7 +158,7 @@ public boolean match(Object o) { * Create a StringGenerator that will produce strings that match all of the given constraints * Yield NoStringsGenerator if no strings could be produced for the given restrictions */ - public StringGenerator createGenerator() { + public StreamStringGenerator createGenerator() { if (generator != null){ return generator; } @@ -174,7 +174,7 @@ public StringGenerator createGenerator() { //produce a regex, and a generator for it, that can produce ANY string within the given bounds //emits /.{<shortest>,<longest>}/ //can also emit /.{<0>,<5>}|.{<7>,<255>}/ if 6 is an excluded length - StringGenerator lengthConstrainingGenerator = minLength == 0 && maxLength == null && excludedLengths.isEmpty() + StreamStringGenerator lengthConstrainingGenerator = minLength == 0 && maxLength == null && excludedLengths.isEmpty() ? null : new RegexStringGenerator( createStringLengthRestrictionRegex(minLength, maxLength), @@ -223,7 +223,7 @@ private static boolean allLengthsAreExcluded(int minLength, Integer maxLength, S /** * Get a stream of StringGenerators that represent each regex restriction in this type */ - private Stream getPatternConstraints() { + private Stream getPatternConstraints() { return concatStreams( getStringGenerators(matchingRegex, regex -> new RegexStringGenerator(regex, true)), getStringGenerators(containingRegex, regex -> new RegexStringGenerator(regex, false)), @@ -240,7 +240,7 @@ private static Stream concatStreams(Stream... streams){ .orElse(Stream.empty()); } - private static Stream getStringGenerators(Set patterns, Function getGenerator) { + private static Stream getStringGenerators(Set patterns, Function getGenerator) { if (patterns.isEmpty()){ return Stream.empty(); } From 972c57301f65bd243044b11e8975169b790bc113 Mon Sep 17 00:00:00 2001 From: Matthew Date: Tue, 20 Aug 2019 11:16:13 +0100 Subject: [PATCH 04/20] Rename StreamStringGenerator to StringGenerator --- .../StandardFieldValueSourceEvaluator.java | 4 ++-- .../string/NoStringsStringGenerator.java | 6 ++---- .../generation/string/RegexStringGenerator.java | 12 ++++-------- ...nerator.java => ChecksumStringGenerator.java} | 6 +++--- .../streamy/ChecksumStringGeneratorFactory.java | 12 ++++++------ .../streamy/ChecksumlessIsinGenerator.java | 8 ++++---- .../string/streamy/IsinCountryCode.java | 12 ++++++------ ...erator.java => PrefixingStringGenerator.java} | 6 +++--- ...StringGenerator.java => StringGenerator.java} | 10 +++++----- .../MatchesStandardStringRestrictions.java | 8 ++++---- .../restrictions/StringRestrictions.java | 4 ++-- .../restrictions/TextualRestrictions.java | 16 ++++++++-------- 12 files changed, 49 insertions(+), 55 deletions(-) rename generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/{ChecksumStreamStringGenerator.java => ChecksumStringGenerator.java} (88%) rename generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/{PrefixingStreamStringGenerator.java => PrefixingStringGenerator.java} (88%) rename generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/{StreamStringGenerator.java => StringGenerator.java} (88%) diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/StandardFieldValueSourceEvaluator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/StandardFieldValueSourceEvaluator.java index a324fc5aa..27d485cc3 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/StandardFieldValueSourceEvaluator.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/StandardFieldValueSourceEvaluator.java @@ -25,7 +25,7 @@ import com.scottlogic.deg.generator.generation.fieldvaluesources.RealNumberFieldValueSource; import com.scottlogic.deg.generator.generation.fieldvaluesources.datetime.DateTimeFieldValueSource; import com.scottlogic.deg.generator.generation.string.RegexStringGenerator; -import com.scottlogic.deg.generator.generation.string.streamy.StreamStringGenerator; +import com.scottlogic.deg.generator.generation.string.streamy.StringGenerator; import com.scottlogic.deg.generator.restrictions.*; import java.util.*; @@ -115,7 +115,7 @@ private FieldValueSource getStringSource(FieldSpec fieldSpec) { Set blacklist = getBlacklist(fieldSpec); - StreamStringGenerator generator = stringRestrictions.createGenerator(); + StringGenerator generator = stringRestrictions.createGenerator(); if (!blacklist.isEmpty()) { RegexStringGenerator blacklistGenerator = RegexStringGenerator.createFromBlacklist(blacklist); diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/NoStringsStringGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/NoStringsStringGenerator.java index 59b98bd80..c524335a5 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/NoStringsStringGenerator.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/NoStringsStringGenerator.java @@ -16,14 +16,12 @@ package com.scottlogic.deg.generator.generation.string; -import com.scottlogic.deg.generator.generation.string.streamy.StreamStringGenerator; +import com.scottlogic.deg.generator.generation.string.streamy.StringGenerator; import com.scottlogic.deg.generator.utils.RandomNumberGenerator; -import java.util.Arrays; -import java.util.Collections; import java.util.stream.Stream; -public class NoStringsStringGenerator implements StreamStringGenerator { +public class NoStringsStringGenerator implements StringGenerator { private final String stringRepresentation; public NoStringsStringGenerator(String stringRepresentation) { diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/RegexStringGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/RegexStringGenerator.java index 2ca7fe0c8..d8d8bf03b 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/RegexStringGenerator.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/RegexStringGenerator.java @@ -19,20 +19,16 @@ import com.scottlogic.deg.generator.generation.string.factorys.FiniteStringAutomatonIterator; import com.scottlogic.deg.generator.generation.string.factorys.InterestingStringFactory; import com.scottlogic.deg.generator.generation.string.factorys.RandomStringFactory; -import com.scottlogic.deg.generator.generation.string.streamy.StreamStringGenerator; +import com.scottlogic.deg.generator.generation.string.streamy.StringGenerator; import com.scottlogic.deg.generator.utils.RandomNumberGenerator; import com.scottlogic.deg.generator.utils.SupplierBasedIterator; import dk.brics.automaton.Automaton; -import dk.brics.automaton.State; -import dk.brics.automaton.Transition; import java.util.*; import java.util.stream.Stream; import java.util.stream.StreamSupport; -import static com.scottlogic.deg.common.util.NumberUtils.*; - -public class RegexStringGenerator implements StreamStringGenerator { +public class RegexStringGenerator implements StringGenerator { /** * Cache of all matching regex automatons, keyed on their regex @@ -88,7 +84,7 @@ public static RegexStringGenerator createFromBlacklist(Set blacklist) { } @Override - public StreamStringGenerator intersect(StreamStringGenerator otherGenerator) { + public StringGenerator intersect(StringGenerator otherGenerator) { if (otherGenerator instanceof NoStringsStringGenerator) { return otherGenerator.intersect(this); } @@ -122,7 +118,7 @@ RegexStringGenerator union(RegexStringGenerator otherGenerator) { } @Override - public StreamStringGenerator complement() { + public StringGenerator complement() { return new RegexStringGenerator( this.automaton.clone().complement(), complementaryRepresentation(this.regexRepresentation)); diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumStreamStringGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumStringGenerator.java similarity index 88% rename from generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumStreamStringGenerator.java rename to generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumStringGenerator.java index 77aab0100..bbdc9f361 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumStreamStringGenerator.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumStringGenerator.java @@ -19,12 +19,12 @@ import java.util.stream.Stream; -public class ChecksumStreamStringGenerator implements StreamStringGenerator { +public class ChecksumStringGenerator implements StringGenerator { - private final StreamStringGenerator checksumlessGenerator; + private final StringGenerator checksumlessGenerator; private final ChecksumMaker checksumMaker; - public ChecksumStreamStringGenerator(StreamStringGenerator checksumlessGenerator, ChecksumMaker checksumMaker) { + public ChecksumStringGenerator(StringGenerator checksumlessGenerator, ChecksumMaker checksumMaker) { this.checksumlessGenerator = checksumlessGenerator; this.checksumMaker = checksumMaker; } diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumStringGeneratorFactory.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumStringGeneratorFactory.java index 3cb76e557..a90aed4a8 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumStringGeneratorFactory.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumStringGeneratorFactory.java @@ -20,20 +20,20 @@ public class ChecksumStringGeneratorFactory { - public static StreamStringGenerator createSedolGenerator() { - return new ChecksumStreamStringGenerator( + public static StringGenerator createSedolGenerator() { + return new ChecksumStringGenerator( new RegexStringGenerator("[B-DF-HJ-NP-TV-Z0-9]{6}", true), FinancialCodeUtils::calculateSedolCheckDigit); } - public static StreamStringGenerator createCusipGenerator() { - return new ChecksumStreamStringGenerator( + public static StringGenerator createCusipGenerator() { + return new ChecksumStringGenerator( new RegexStringGenerator("[0-9]{3}[0-9A-Z]{5}", true), FinancialCodeUtils::calculateCusipCheckDigit); } - public static StreamStringGenerator createIsinGenerator() { - return new ChecksumStreamStringGenerator( + public static StringGenerator createIsinGenerator() { + return new ChecksumStringGenerator( new ChecksumlessIsinGenerator(), FinancialCodeUtils::calculateIsinCheckDigit); } diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumlessIsinGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumlessIsinGenerator.java index 5cda3ea9c..1cb10a3a4 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumlessIsinGenerator.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumlessIsinGenerator.java @@ -22,17 +22,17 @@ import static com.scottlogic.deg.common.util.FlatMappingSpliterator.flatMap; -public class ChecksumlessIsinGenerator implements StreamStringGenerator { +public class ChecksumlessIsinGenerator implements StringGenerator { @Override public Stream generateAllValues() { - Stream isinStringGenerators = + Stream isinStringGenerators = Arrays.stream(IsinCountryCode.values()) .map(IsinCountryCode::getChecksumlessStringGenerator); return flatMap( isinStringGenerators, - StreamStringGenerator::generateAllValues); + StringGenerator::generateAllValues); } @Override @@ -56,7 +56,7 @@ public Stream generateInterestingValues() { @Override public boolean matches(String string) { - Stream isinStringGenerators = + Stream isinStringGenerators = Arrays.stream(IsinCountryCode.values()) .map(IsinCountryCode::getChecksumlessStringGenerator); diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/IsinCountryCode.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/IsinCountryCode.java index 3aeb21fde..11a09b7b4 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/IsinCountryCode.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/IsinCountryCode.java @@ -27,22 +27,22 @@ public enum IsinCountryCode { DN; String GENERIC_NSIN_REGEX = "[A-Z0-9]{9}"; - private final StreamStringGenerator checksumlessStringGenerator; + private final StringGenerator checksumlessStringGenerator; IsinCountryCode(){ checksumlessStringGenerator = prefix(this.name(), new RegexStringGenerator(GENERIC_NSIN_REGEX, true)); } - IsinCountryCode(StreamStringGenerator streamStringGenerator){ - this.checksumlessStringGenerator = streamStringGenerator; + IsinCountryCode(StringGenerator stringGenerator){ + this.checksumlessStringGenerator = stringGenerator; } - static StreamStringGenerator prefix(String prefix, StreamStringGenerator inner){ - return new PrefixingStreamStringGenerator(prefix, inner); + static StringGenerator prefix(String prefix, StringGenerator inner){ + return new PrefixingStringGenerator(prefix, inner); } - public StreamStringGenerator getChecksumlessStringGenerator() { + public StringGenerator getChecksumlessStringGenerator() { return checksumlessStringGenerator; } } diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/PrefixingStreamStringGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/PrefixingStringGenerator.java similarity index 88% rename from generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/PrefixingStreamStringGenerator.java rename to generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/PrefixingStringGenerator.java index 09c57caba..3529fb2eb 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/PrefixingStreamStringGenerator.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/PrefixingStringGenerator.java @@ -19,12 +19,12 @@ import java.util.stream.Stream; -public class PrefixingStreamStringGenerator implements StreamStringGenerator { +public class PrefixingStringGenerator implements StringGenerator { private final String prefix; - private final StreamStringGenerator innerGenerator; + private final StringGenerator innerGenerator; - public PrefixingStreamStringGenerator(String prefix, StreamStringGenerator innerGenerator) { + public PrefixingStringGenerator(String prefix, StringGenerator innerGenerator) { this.prefix = prefix; this.innerGenerator = innerGenerator; } diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/StreamStringGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/StringGenerator.java similarity index 88% rename from generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/StreamStringGenerator.java rename to generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/StringGenerator.java index 37b3dbb6c..ad3de4cf1 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/StreamStringGenerator.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/StringGenerator.java @@ -22,7 +22,7 @@ import java.util.stream.Stream; -public interface StreamStringGenerator { +public interface StringGenerator { Stream generateAllValues(); Stream generateRandomValues(RandomNumberGenerator randomNumberGenerator); @@ -31,14 +31,14 @@ public interface StreamStringGenerator { boolean matches(String string); - default StreamStringGenerator intersect(StreamStringGenerator stringGenerator){ + default StringGenerator intersect(StringGenerator stringGenerator){ if (this.getClass().equals(stringGenerator.getClass())){ return this; } return new NoStringsStringGenerator("can't merge non standard strings"); } - default StreamStringGenerator complement() { + default StringGenerator complement() { throw new UnsupportedOperationException(); } @@ -48,9 +48,9 @@ default FieldValueSource asFieldValueSource() { // Adapter class StringGeneratorAsFieldValueSource implements FieldValueSource { - private final StreamStringGenerator underlyingGenerator; + private final StringGenerator underlyingGenerator; - StringGeneratorAsFieldValueSource(StreamStringGenerator underlyingGenerator) { + StringGeneratorAsFieldValueSource(StringGenerator underlyingGenerator) { this.underlyingGenerator = underlyingGenerator; } diff --git a/generator/src/main/java/com/scottlogic/deg/generator/restrictions/MatchesStandardStringRestrictions.java b/generator/src/main/java/com/scottlogic/deg/generator/restrictions/MatchesStandardStringRestrictions.java index 271259d6e..623ecdd97 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/restrictions/MatchesStandardStringRestrictions.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/restrictions/MatchesStandardStringRestrictions.java @@ -18,7 +18,7 @@ import com.scottlogic.deg.common.profile.constraints.atomic.StandardConstraintTypes; import com.scottlogic.deg.generator.generation.string.*; -import com.scottlogic.deg.generator.generation.string.streamy.StreamStringGenerator; +import com.scottlogic.deg.generator.generation.string.streamy.StringGenerator; import static com.scottlogic.deg.generator.generation.string.streamy.ChecksumStringGeneratorFactory.*; @@ -28,7 +28,7 @@ */ public class MatchesStandardStringRestrictions implements StringRestrictions{ private final StandardConstraintTypes type; - private StreamStringGenerator generator; + private StringGenerator generator; public MatchesStandardStringRestrictions(StandardConstraintTypes type) { this.type = type; @@ -39,7 +39,7 @@ public boolean match(String x) { return createGenerator().matches(x); } - public StreamStringGenerator createGenerator() { + public StringGenerator createGenerator() { if (generator == null) { switch (type) { case ISIN: @@ -77,7 +77,7 @@ private MergeResult isLengthAcceptable(TextualRestrictions o return MergeResult.unsuccessful(); } - StreamStringGenerator intersect = other.createGenerator().intersect(new RegexStringGenerator(type.getRegex(), true)); + StringGenerator intersect = other.createGenerator().intersect(new RegexStringGenerator(type.getRegex(), true)); if (intersect instanceof NoStringsStringGenerator){ return MergeResult.unsuccessful(); diff --git a/generator/src/main/java/com/scottlogic/deg/generator/restrictions/StringRestrictions.java b/generator/src/main/java/com/scottlogic/deg/generator/restrictions/StringRestrictions.java index cc3fbf162..1908b1449 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/restrictions/StringRestrictions.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/restrictions/StringRestrictions.java @@ -17,7 +17,7 @@ package com.scottlogic.deg.generator.restrictions; import com.scottlogic.deg.common.profile.constraints.atomic.IsOfTypeConstraint; -import com.scottlogic.deg.generator.generation.string.streamy.StreamStringGenerator; +import com.scottlogic.deg.generator.generation.string.streamy.StringGenerator; public interface StringRestrictions extends TypedRestrictions { MergeResult intersect(StringRestrictions other); @@ -34,7 +34,7 @@ default boolean match(Object x) { return isInstanceOf(x) && match((String) x); } - StreamStringGenerator createGenerator(); + StringGenerator createGenerator(); } diff --git a/generator/src/main/java/com/scottlogic/deg/generator/restrictions/TextualRestrictions.java b/generator/src/main/java/com/scottlogic/deg/generator/restrictions/TextualRestrictions.java index b260645aa..c04be316a 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/restrictions/TextualRestrictions.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/restrictions/TextualRestrictions.java @@ -18,7 +18,7 @@ import com.scottlogic.deg.generator.generation.string.NoStringsStringGenerator; import com.scottlogic.deg.generator.generation.string.RegexStringGenerator; -import com.scottlogic.deg.generator.generation.string.streamy.StreamStringGenerator; +import com.scottlogic.deg.generator.generation.string.streamy.StringGenerator; import com.scottlogic.deg.generator.utils.SetUtils; import java.util.*; @@ -36,7 +36,7 @@ public class TextualRestrictions implements StringRestrictions { final Set containingRegex; final Set notMatchingRegex; final Set notContainingRegex; - private StreamStringGenerator generator; + private StringGenerator generator; TextualRestrictions( Integer minLength, @@ -104,7 +104,7 @@ private boolean isContradictory() { return false; //no regular expressions exist that can contradict } - StreamStringGenerator generator = createGenerator(); + StringGenerator generator = createGenerator(); return generator instanceof NoStringsStringGenerator; } @@ -148,7 +148,7 @@ public boolean match(Object o) { } String s = (String) o; - StreamStringGenerator generator = createGenerator(); + StringGenerator generator = createGenerator(); return generator == null || generator.matches(s); } @@ -158,7 +158,7 @@ public boolean match(Object o) { * Create a StringGenerator that will produce strings that match all of the given constraints * Yield NoStringsGenerator if no strings could be produced for the given restrictions */ - public StreamStringGenerator createGenerator() { + public StringGenerator createGenerator() { if (generator != null){ return generator; } @@ -174,7 +174,7 @@ public StreamStringGenerator createGenerator() { //produce a regex, and a generator for it, that can produce ANY string within the given bounds //emits /.{<shortest>,<longest>}/ //can also emit /.{<0>,<5>}|.{<7>,<255>}/ if 6 is an excluded length - StreamStringGenerator lengthConstrainingGenerator = minLength == 0 && maxLength == null && excludedLengths.isEmpty() + StringGenerator lengthConstrainingGenerator = minLength == 0 && maxLength == null && excludedLengths.isEmpty() ? null : new RegexStringGenerator( createStringLengthRestrictionRegex(minLength, maxLength), @@ -223,7 +223,7 @@ private static boolean allLengthsAreExcluded(int minLength, Integer maxLength, S /** * Get a stream of StringGenerators that represent each regex restriction in this type */ - private Stream getPatternConstraints() { + private Stream getPatternConstraints() { return concatStreams( getStringGenerators(matchingRegex, regex -> new RegexStringGenerator(regex, true)), getStringGenerators(containingRegex, regex -> new RegexStringGenerator(regex, false)), @@ -240,7 +240,7 @@ private static Stream concatStreams(Stream... streams){ .orElse(Stream.empty()); } - private static Stream getStringGenerators(Set patterns, Function getGenerator) { + private static Stream getStringGenerators(Set patterns, Function getGenerator) { if (patterns.isEmpty()){ return Stream.empty(); } From 432a15b675de3570083c397f410e9806f6919142 Mon Sep 17 00:00:00 2001 From: Matthew Date: Tue, 20 Aug 2019 11:22:07 +0100 Subject: [PATCH 05/20] Explicitly throwing UnsupportedOperationException by default for intersection of string constraints. A class can choose to implement them or not. --- .../generator/generation/string/streamy/StringGenerator.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/StringGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/StringGenerator.java index ad3de4cf1..a29c7d42a 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/StringGenerator.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/StringGenerator.java @@ -32,10 +32,7 @@ public interface StringGenerator { boolean matches(String string); default StringGenerator intersect(StringGenerator stringGenerator){ - if (this.getClass().equals(stringGenerator.getClass())){ - return this; - } - return new NoStringsStringGenerator("can't merge non standard strings"); + throw new UnsupportedOperationException(); } default StringGenerator complement() { From ca748f1043fd266a6b4d1c9985949bb299550d40 Mon Sep 17 00:00:00 2001 From: Matthew Date: Tue, 20 Aug 2019 12:48:05 +0100 Subject: [PATCH 06/20] Change where intersection errors are handled so that UnsupportedOperationExceptions are caught by the UpfrontTreePruner and printed --- .../generation/UpfrontTreePruner.java | 18 ++++++++++++++---- .../MatchesStandardStringRestrictions.java | 3 ++- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/UpfrontTreePruner.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/UpfrontTreePruner.java index e39240713..f2dd4a45a 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/UpfrontTreePruner.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/UpfrontTreePruner.java @@ -47,16 +47,16 @@ public DecisionTree runUpfrontPrune(DecisionTree tree, DataGeneratorMonitor moni Function.identity(), f -> FieldSpec.Empty)); - Merged prunedNode = treePruner.pruneConstraintNode(tree.getRootNode(), fieldSpecs); - DecisionTree markedTree = validator.markContradictions(tree); - + Merged prunedNode = getPrunedNode(tree, fieldSpecs, monitor); if (prunedNode.isContradictory()) { monitor.addLineToPrintAtEndOfGeneration(""); monitor.addLineToPrintAtEndOfGeneration("The provided profile is wholly contradictory!"); monitor.addLineToPrintAtEndOfGeneration("No data can be generated!"); return new DecisionTree(null, tree.getFields()); + } - } else if (isPartiallyContradictory(markedTree.getRootNode())) { + DecisionTree markedTree = validator.markContradictions(tree); + if (isPartiallyContradictory(markedTree.getRootNode())) { monitor.addLineToPrintAtEndOfGeneration(""); monitor.addLineToPrintAtEndOfGeneration("The provided profile is partially contradictory!"); monitor.addLineToPrintAtEndOfGeneration("Run the visualise command for more information."); @@ -66,6 +66,16 @@ public DecisionTree runUpfrontPrune(DecisionTree tree, DataGeneratorMonitor moni return new DecisionTree(prunedNode.get(), tree.getFields()); } + private Merged getPrunedNode(DecisionTree tree, Map fieldSpecs, DataGeneratorMonitor monitor) { + try { + return treePruner.pruneConstraintNode(tree.getRootNode(), fieldSpecs); + } catch (UnsupportedOperationException ex) { + monitor.addLineToPrintAtEndOfGeneration(""); + monitor.addLineToPrintAtEndOfGeneration(ex.getMessage()); + return Merged.contradictory(); + } + } + private boolean isPartiallyContradictory(ConstraintNode root) { return root.hasMarking(NodeMarking.CONTRADICTORY) || diff --git a/generator/src/main/java/com/scottlogic/deg/generator/restrictions/MatchesStandardStringRestrictions.java b/generator/src/main/java/com/scottlogic/deg/generator/restrictions/MatchesStandardStringRestrictions.java index 623ecdd97..9e7b0f50b 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/restrictions/MatchesStandardStringRestrictions.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/restrictions/MatchesStandardStringRestrictions.java @@ -60,6 +60,7 @@ public StringGenerator createGenerator() { @Override public MergeResult intersect(StringRestrictions other) { + if (other instanceof TextualRestrictions){ return isLengthAcceptable((TextualRestrictions) other); } @@ -74,7 +75,7 @@ public MergeResult intersect(StringRestrictions other) { private MergeResult isLengthAcceptable(TextualRestrictions other) { if (anyRegexes(other)){ - return MergeResult.unsuccessful(); + throw new UnsupportedOperationException("Combining a regex constraint with an " + this.toString() + " constraint is not supported."); } StringGenerator intersect = other.createGenerator().intersect(new RegexStringGenerator(type.getRegex(), true)); From a724403c9adb3d4bdbf2639e74e37da8d3712ca5 Mon Sep 17 00:00:00 2001 From: Matthew Date: Wed, 21 Aug 2019 14:01:49 +0100 Subject: [PATCH 07/20] Move UnsupportedOperationExceptions to catch more cases. Add intersect method to all StringGenerators to improve the error messages when they don't support a constraint combination. --- .../generation/DecisionTreeDataGenerator.java | 22 ++++++++++++------- .../generation/UpfrontTreePruner.java | 19 ++++------------ .../string/NoStringsStringGenerator.java | 5 +++++ .../streamy/ChecksumStringGenerator.java | 5 +++++ .../streamy/ChecksumlessIsinGenerator.java | 5 +++++ .../streamy/PrefixingStringGenerator.java | 5 +++++ .../string/streamy/StringGenerator.java | 4 +--- 7 files changed, 39 insertions(+), 26 deletions(-) diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/DecisionTreeDataGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/DecisionTreeDataGenerator.java index bc1f0bc1c..048653664 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/DecisionTreeDataGenerator.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/DecisionTreeDataGenerator.java @@ -70,14 +70,20 @@ public Stream generateData(Profile profile) { return Stream.empty(); } - Stream> partitionedDataBags = treePartitioner - .splitTreeIntoPartitions(decisionTree) - .map(treeOptimiser::optimiseTree) - .map(treeWalker::walk); + try { + Stream> partitionedDataBags = treePartitioner + .splitTreeIntoPartitions(decisionTree) + .map(treeOptimiser::optimiseTree) + .map(treeWalker::walk); - return partitionCombiner.permute(partitionedDataBags) - .map(d->(GeneratedObject)d) - .limit(maxRows) - .peek(monitor::rowEmitted); + return partitionCombiner.permute(partitionedDataBags) + .map(d->(GeneratedObject)d) + .limit(maxRows) + .peek(monitor::rowEmitted); + } catch (UnsupportedOperationException ex) { + monitor.addLineToPrintAtEndOfGeneration(""); + monitor.addLineToPrintAtEndOfGeneration(ex.getMessage()); + return Stream.empty(); + } } } diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/UpfrontTreePruner.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/UpfrontTreePruner.java index f2dd4a45a..b242ca7cf 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/UpfrontTreePruner.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/UpfrontTreePruner.java @@ -47,16 +47,15 @@ public DecisionTree runUpfrontPrune(DecisionTree tree, DataGeneratorMonitor moni Function.identity(), f -> FieldSpec.Empty)); - Merged prunedNode = getPrunedNode(tree, fieldSpecs, monitor); + Merged prunedNode = treePruner.pruneConstraintNode(tree.getRootNode(), fieldSpecs); + DecisionTree markedTree = validator.markContradictions(tree); + if (prunedNode.isContradictory()) { monitor.addLineToPrintAtEndOfGeneration(""); monitor.addLineToPrintAtEndOfGeneration("The provided profile is wholly contradictory!"); monitor.addLineToPrintAtEndOfGeneration("No data can be generated!"); return new DecisionTree(null, tree.getFields()); - } - - DecisionTree markedTree = validator.markContradictions(tree); - if (isPartiallyContradictory(markedTree.getRootNode())) { + } else if (isPartiallyContradictory(markedTree.getRootNode())) { monitor.addLineToPrintAtEndOfGeneration(""); monitor.addLineToPrintAtEndOfGeneration("The provided profile is partially contradictory!"); monitor.addLineToPrintAtEndOfGeneration("Run the visualise command for more information."); @@ -66,16 +65,6 @@ public DecisionTree runUpfrontPrune(DecisionTree tree, DataGeneratorMonitor moni return new DecisionTree(prunedNode.get(), tree.getFields()); } - private Merged getPrunedNode(DecisionTree tree, Map fieldSpecs, DataGeneratorMonitor monitor) { - try { - return treePruner.pruneConstraintNode(tree.getRootNode(), fieldSpecs); - } catch (UnsupportedOperationException ex) { - monitor.addLineToPrintAtEndOfGeneration(""); - monitor.addLineToPrintAtEndOfGeneration(ex.getMessage()); - return Merged.contradictory(); - } - } - private boolean isPartiallyContradictory(ConstraintNode root) { return root.hasMarking(NodeMarking.CONTRADICTORY) || diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/NoStringsStringGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/NoStringsStringGenerator.java index c524335a5..30c617637 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/NoStringsStringGenerator.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/NoStringsStringGenerator.java @@ -37,6 +37,11 @@ public boolean matches(String subject) { return false; } + @Override + public StringGenerator intersect(StringGenerator stringGenerator) { + return this; + } + @Override public Stream generateInterestingValues() { return Stream.empty(); diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumStringGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumStringGenerator.java index bbdc9f361..3a4c6527d 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumStringGenerator.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumStringGenerator.java @@ -58,4 +58,9 @@ public boolean matches(String string) { checksumlessGenerator.matches(preChecksumComponent) && checksumMaker.makeChecksum(preChecksumComponent).equals(checksumComponent); } + + @Override + public StringGenerator intersect(StringGenerator stringGenerator) { + throw new UnsupportedOperationException("Checksum constraints can only be used with length and equalTo constraints."); + } } diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumlessIsinGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumlessIsinGenerator.java index 1cb10a3a4..a3eb8ba6e 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumlessIsinGenerator.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumlessIsinGenerator.java @@ -62,4 +62,9 @@ public boolean matches(String string) { return isinStringGenerators.anyMatch(generator -> generator.matches(string)); } + + @Override + public StringGenerator intersect(StringGenerator stringGenerator) { + throw new UnsupportedOperationException("Constraints with ISINs can only be used with length and equalTo constraints."); + } } diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/PrefixingStringGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/PrefixingStringGenerator.java index 3529fb2eb..642d96525 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/PrefixingStringGenerator.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/PrefixingStringGenerator.java @@ -58,4 +58,9 @@ public boolean matches(String string) { } return innerGenerator.matches(string.substring(prefix.length())); } + + @Override + public StringGenerator intersect(StringGenerator stringGenerator) { + throw new UnsupportedOperationException(); + } } diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/StringGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/StringGenerator.java index a29c7d42a..dd70e9e5a 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/StringGenerator.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/StringGenerator.java @@ -31,9 +31,7 @@ public interface StringGenerator { boolean matches(String string); - default StringGenerator intersect(StringGenerator stringGenerator){ - throw new UnsupportedOperationException(); - } + StringGenerator intersect(StringGenerator stringGenerator); default StringGenerator complement() { throw new UnsupportedOperationException(); From 65b27a02519e5eb618d9c3892e8de51e4d746bff Mon Sep 17 00:00:00 2001 From: Matthew Date: Wed, 21 Aug 2019 15:18:07 +0100 Subject: [PATCH 08/20] Rename package. Move files --- .../generation/StandardFieldValueSourceEvaluator.java | 4 ++-- .../string/{streamy => generators}/ChecksumMaker.java | 2 +- .../{streamy => generators}/ChecksumStringGenerator.java | 2 +- .../ChecksumStringGeneratorFactory.java | 3 +-- .../ChecksumlessIsinGenerator.java | 2 +- .../string/{streamy => generators}/IsinCountryCode.java | 8 +++----- .../string/{ => generators}/NoStringsStringGenerator.java | 3 +-- .../{streamy => generators}/PrefixingStringGenerator.java | 2 +- .../string/{ => generators}/RegexStringGenerator.java | 4 ++-- .../string/{streamy => generators}/StringGenerator.java | 3 +-- .../restrictions/MatchesStandardStringRestrictions.java | 7 ++++--- .../deg/generator/restrictions/StringRestrictions.java | 2 +- .../deg/generator/restrictions/TextualRestrictions.java | 6 +++--- 13 files changed, 22 insertions(+), 26 deletions(-) rename generator/src/main/java/com/scottlogic/deg/generator/generation/string/{streamy => generators}/ChecksumMaker.java (91%) rename generator/src/main/java/com/scottlogic/deg/generator/generation/string/{streamy => generators}/ChecksumStringGenerator.java (97%) rename generator/src/main/java/com/scottlogic/deg/generator/generation/string/{streamy => generators}/ChecksumStringGeneratorFactory.java (90%) rename generator/src/main/java/com/scottlogic/deg/generator/generation/string/{streamy => generators}/ChecksumlessIsinGenerator.java (97%) rename generator/src/main/java/com/scottlogic/deg/generator/generation/string/{streamy => generators}/IsinCountryCode.java (78%) rename generator/src/main/java/com/scottlogic/deg/generator/generation/string/{ => generators}/NoStringsStringGenerator.java (92%) rename generator/src/main/java/com/scottlogic/deg/generator/generation/string/{streamy => generators}/PrefixingStringGenerator.java (96%) rename generator/src/main/java/com/scottlogic/deg/generator/generation/string/{ => generators}/RegexStringGenerator.java (98%) rename generator/src/main/java/com/scottlogic/deg/generator/generation/string/{streamy => generators}/StringGenerator.java (94%) diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/StandardFieldValueSourceEvaluator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/StandardFieldValueSourceEvaluator.java index 27d485cc3..d669dc71a 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/StandardFieldValueSourceEvaluator.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/StandardFieldValueSourceEvaluator.java @@ -24,8 +24,8 @@ import com.scottlogic.deg.generator.generation.fieldvaluesources.FieldValueSource; import com.scottlogic.deg.generator.generation.fieldvaluesources.RealNumberFieldValueSource; import com.scottlogic.deg.generator.generation.fieldvaluesources.datetime.DateTimeFieldValueSource; -import com.scottlogic.deg.generator.generation.string.RegexStringGenerator; -import com.scottlogic.deg.generator.generation.string.streamy.StringGenerator; +import com.scottlogic.deg.generator.generation.string.generators.RegexStringGenerator; +import com.scottlogic.deg.generator.generation.string.generators.StringGenerator; import com.scottlogic.deg.generator.restrictions.*; import java.util.*; diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumMaker.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/ChecksumMaker.java similarity index 91% rename from generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumMaker.java rename to generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/ChecksumMaker.java index adaf253a6..6e5954de5 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumMaker.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/ChecksumMaker.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.scottlogic.deg.generator.generation.string.streamy; +package com.scottlogic.deg.generator.generation.string.generators; @FunctionalInterface public interface ChecksumMaker { diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumStringGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/ChecksumStringGenerator.java similarity index 97% rename from generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumStringGenerator.java rename to generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/ChecksumStringGenerator.java index 3a4c6527d..f96c09cdc 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumStringGenerator.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/ChecksumStringGenerator.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.scottlogic.deg.generator.generation.string.streamy; +package com.scottlogic.deg.generator.generation.string.generators; import com.scottlogic.deg.generator.utils.RandomNumberGenerator; diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumStringGeneratorFactory.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/ChecksumStringGeneratorFactory.java similarity index 90% rename from generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumStringGeneratorFactory.java rename to generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/ChecksumStringGeneratorFactory.java index a90aed4a8..b96e8eb2b 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumStringGeneratorFactory.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/ChecksumStringGeneratorFactory.java @@ -13,9 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.scottlogic.deg.generator.generation.string.streamy; +package com.scottlogic.deg.generator.generation.string.generators; -import com.scottlogic.deg.generator.generation.string.RegexStringGenerator; import com.scottlogic.deg.generator.utils.FinancialCodeUtils; public class ChecksumStringGeneratorFactory { diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumlessIsinGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/ChecksumlessIsinGenerator.java similarity index 97% rename from generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumlessIsinGenerator.java rename to generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/ChecksumlessIsinGenerator.java index a3eb8ba6e..5e8244464 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/ChecksumlessIsinGenerator.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/ChecksumlessIsinGenerator.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.scottlogic.deg.generator.generation.string.streamy; +package com.scottlogic.deg.generator.generation.string.generators; import com.scottlogic.deg.generator.utils.RandomNumberGenerator; diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/IsinCountryCode.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/IsinCountryCode.java similarity index 78% rename from generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/IsinCountryCode.java rename to generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/IsinCountryCode.java index 11a09b7b4..becab1a8e 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/IsinCountryCode.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/IsinCountryCode.java @@ -13,13 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.scottlogic.deg.generator.generation.string.streamy; +package com.scottlogic.deg.generator.generation.string.generators; -import com.scottlogic.deg.generator.generation.string.RegexStringGenerator; - -import static com.scottlogic.deg.generator.generation.string.streamy.ChecksumStringGeneratorFactory.createCusipGenerator; -import static com.scottlogic.deg.generator.generation.string.streamy.ChecksumStringGeneratorFactory.createSedolGenerator; +import static com.scottlogic.deg.generator.generation.string.generators.ChecksumStringGeneratorFactory.createCusipGenerator; +import static com.scottlogic.deg.generator.generation.string.generators.ChecksumStringGeneratorFactory.createSedolGenerator; public enum IsinCountryCode { GB(prefix("GB00", createSedolGenerator())), diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/NoStringsStringGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/NoStringsStringGenerator.java similarity index 92% rename from generator/src/main/java/com/scottlogic/deg/generator/generation/string/NoStringsStringGenerator.java rename to generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/NoStringsStringGenerator.java index 30c617637..9e34011e0 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/NoStringsStringGenerator.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/NoStringsStringGenerator.java @@ -14,9 +14,8 @@ * limitations under the License. */ -package com.scottlogic.deg.generator.generation.string; +package com.scottlogic.deg.generator.generation.string.generators; -import com.scottlogic.deg.generator.generation.string.streamy.StringGenerator; import com.scottlogic.deg.generator.utils.RandomNumberGenerator; import java.util.stream.Stream; diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/PrefixingStringGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/PrefixingStringGenerator.java similarity index 96% rename from generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/PrefixingStringGenerator.java rename to generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/PrefixingStringGenerator.java index 642d96525..4064888b3 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/PrefixingStringGenerator.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/PrefixingStringGenerator.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.scottlogic.deg.generator.generation.string.streamy; +package com.scottlogic.deg.generator.generation.string.generators; import com.scottlogic.deg.generator.utils.RandomNumberGenerator; diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/RegexStringGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/RegexStringGenerator.java similarity index 98% rename from generator/src/main/java/com/scottlogic/deg/generator/generation/string/RegexStringGenerator.java rename to generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/RegexStringGenerator.java index d8d8bf03b..00c733c4e 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/RegexStringGenerator.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/RegexStringGenerator.java @@ -14,12 +14,12 @@ * limitations under the License. */ -package com.scottlogic.deg.generator.generation.string; +package com.scottlogic.deg.generator.generation.string.generators; +import com.scottlogic.deg.generator.generation.string.AutomatonUtils; import com.scottlogic.deg.generator.generation.string.factorys.FiniteStringAutomatonIterator; import com.scottlogic.deg.generator.generation.string.factorys.InterestingStringFactory; import com.scottlogic.deg.generator.generation.string.factorys.RandomStringFactory; -import com.scottlogic.deg.generator.generation.string.streamy.StringGenerator; import com.scottlogic.deg.generator.utils.RandomNumberGenerator; import com.scottlogic.deg.generator.utils.SupplierBasedIterator; import dk.brics.automaton.Automaton; diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/StringGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/StringGenerator.java similarity index 94% rename from generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/StringGenerator.java rename to generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/StringGenerator.java index dd70e9e5a..4072087e2 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/streamy/StringGenerator.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/StringGenerator.java @@ -13,10 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.scottlogic.deg.generator.generation.string.streamy; +package com.scottlogic.deg.generator.generation.string.generators; import com.scottlogic.deg.generator.generation.fieldvaluesources.FieldValueSource; -import com.scottlogic.deg.generator.generation.string.NoStringsStringGenerator; import com.scottlogic.deg.generator.utils.RandomNumberGenerator; import com.scottlogic.deg.generator.utils.UpCastingIterator; diff --git a/generator/src/main/java/com/scottlogic/deg/generator/restrictions/MatchesStandardStringRestrictions.java b/generator/src/main/java/com/scottlogic/deg/generator/restrictions/MatchesStandardStringRestrictions.java index 9e7b0f50b..8f2ec4114 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/restrictions/MatchesStandardStringRestrictions.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/restrictions/MatchesStandardStringRestrictions.java @@ -17,10 +17,11 @@ package com.scottlogic.deg.generator.restrictions; import com.scottlogic.deg.common.profile.constraints.atomic.StandardConstraintTypes; -import com.scottlogic.deg.generator.generation.string.*; -import com.scottlogic.deg.generator.generation.string.streamy.StringGenerator; +import com.scottlogic.deg.generator.generation.string.generators.NoStringsStringGenerator; +import com.scottlogic.deg.generator.generation.string.generators.RegexStringGenerator; +import com.scottlogic.deg.generator.generation.string.generators.StringGenerator; -import static com.scottlogic.deg.generator.generation.string.streamy.ChecksumStringGeneratorFactory.*; +import static com.scottlogic.deg.generator.generation.string.generators.ChecksumStringGeneratorFactory.*; /** * Represents the restriction of a field to an `aValid` operator diff --git a/generator/src/main/java/com/scottlogic/deg/generator/restrictions/StringRestrictions.java b/generator/src/main/java/com/scottlogic/deg/generator/restrictions/StringRestrictions.java index 1908b1449..ed293b3eb 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/restrictions/StringRestrictions.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/restrictions/StringRestrictions.java @@ -17,7 +17,7 @@ package com.scottlogic.deg.generator.restrictions; import com.scottlogic.deg.common.profile.constraints.atomic.IsOfTypeConstraint; -import com.scottlogic.deg.generator.generation.string.streamy.StringGenerator; +import com.scottlogic.deg.generator.generation.string.generators.StringGenerator; public interface StringRestrictions extends TypedRestrictions { MergeResult intersect(StringRestrictions other); diff --git a/generator/src/main/java/com/scottlogic/deg/generator/restrictions/TextualRestrictions.java b/generator/src/main/java/com/scottlogic/deg/generator/restrictions/TextualRestrictions.java index c04be316a..10c5f0be1 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/restrictions/TextualRestrictions.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/restrictions/TextualRestrictions.java @@ -16,9 +16,9 @@ package com.scottlogic.deg.generator.restrictions; -import com.scottlogic.deg.generator.generation.string.NoStringsStringGenerator; -import com.scottlogic.deg.generator.generation.string.RegexStringGenerator; -import com.scottlogic.deg.generator.generation.string.streamy.StringGenerator; +import com.scottlogic.deg.generator.generation.string.generators.NoStringsStringGenerator; +import com.scottlogic.deg.generator.generation.string.generators.RegexStringGenerator; +import com.scottlogic.deg.generator.generation.string.generators.StringGenerator; import com.scottlogic.deg.generator.utils.SetUtils; import java.util.*; From 900160cb321ef5b2a68402cea2e1ceaed498e310 Mon Sep 17 00:00:00 2001 From: Matthew Date: Wed, 21 Aug 2019 15:50:03 +0100 Subject: [PATCH 09/20] Change tests to use the new checksum code and ignored tests that use functionality that has been removed --- .../generator/fieldspecs/FieldSpecTests.java | 7 +- .../string/CusipStringGeneratorTests.java | 22 +++--- .../string/IsinStringGeneratorTests.java | 32 ++++---- .../string/RegexStringGeneratorTests.java | 77 +++++++------------ .../string/SedolStringGeneratorTests.java | 21 +++-- .../helpers/StringGeneratorHelper.java | 2 +- .../TextualRestrictionsTests.java | 39 +++++----- 7 files changed, 98 insertions(+), 102 deletions(-) diff --git a/generator/src/test/java/com/scottlogic/deg/generator/fieldspecs/FieldSpecTests.java b/generator/src/test/java/com/scottlogic/deg/generator/fieldspecs/FieldSpecTests.java index 246b6b4b4..0c17e83f4 100644 --- a/generator/src/test/java/com/scottlogic/deg/generator/fieldspecs/FieldSpecTests.java +++ b/generator/src/test/java/com/scottlogic/deg/generator/fieldspecs/FieldSpecTests.java @@ -20,7 +20,7 @@ import com.scottlogic.deg.common.profile.constraints.atomic.IsOfTypeConstraint.Types; import com.scottlogic.deg.generator.fieldspecs.whitelist.DistributedSet; import com.scottlogic.deg.generator.fieldspecs.whitelist.FrequencyDistributedSet; -import com.scottlogic.deg.generator.generation.string.StringGenerator; +import com.scottlogic.deg.generator.generation.string.generators.StringGenerator; import com.scottlogic.deg.generator.restrictions.*; import com.scottlogic.deg.generator.utils.SetUtils; import org.junit.Assert; @@ -32,7 +32,10 @@ import java.math.BigDecimal; import java.time.OffsetDateTime; import java.time.ZoneOffset; -import java.util.*; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; import java.util.stream.Stream; import static org.hamcrest.core.IsEqual.equalTo; diff --git a/generator/src/test/java/com/scottlogic/deg/generator/generation/string/CusipStringGeneratorTests.java b/generator/src/test/java/com/scottlogic/deg/generator/generation/string/CusipStringGeneratorTests.java index 2f8edbd42..157f7328f 100644 --- a/generator/src/test/java/com/scottlogic/deg/generator/generation/string/CusipStringGeneratorTests.java +++ b/generator/src/test/java/com/scottlogic/deg/generator/generation/string/CusipStringGeneratorTests.java @@ -16,45 +16,49 @@ package com.scottlogic.deg.generator.generation.string; -import org.junit.Assert; +import com.scottlogic.deg.generator.generation.string.generators.StringGenerator; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import static com.scottlogic.deg.generator.generation.string.generators.ChecksumStringGeneratorFactory.createCusipGenerator; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; public class CusipStringGeneratorTests { @Test public void shouldMatchAValidCusipCodeWhenNotNegated(){ - StringGenerator cusipGenerator = new CusipStringGenerator(); + StringGenerator cusipGenerator = createCusipGenerator(); - boolean matches = cusipGenerator.match("38259P508"); + boolean matches = cusipGenerator.matches("38259P508"); assertTrue(matches); } @Test public void shouldNotMatchAnInvalidCusipCodeWhenNotNegated(){ - StringGenerator cusipGenerator = new CusipStringGenerator(); + StringGenerator cusipGenerator = createCusipGenerator(); - boolean matches = cusipGenerator.match("not a cusip"); + boolean matches = cusipGenerator.matches("not a cusip"); assertFalse(matches); } @Test + @Disabled("Standard constraints e.g. ISINs currently cannot be negated") public void shouldNotMatchAValidCusipCodeWhenNegated(){ - StringGenerator cusipGenerator = new CusipStringGenerator().complement(); + StringGenerator cusipGenerator = createCusipGenerator().complement(); - boolean matches = cusipGenerator.match("38259P508"); + boolean matches = cusipGenerator.matches("38259P508"); assertFalse(matches); } @Test + @Disabled("Standard constraints e.g. ISINs currently cannot be negated") public void shouldMatchAnInvalidCusipCodeWhenNegated(){ - StringGenerator cusipGenerator = new CusipStringGenerator().complement(); + StringGenerator cusipGenerator = createCusipGenerator().complement(); - boolean matches = cusipGenerator.match("not a cusip"); + boolean matches = cusipGenerator.matches("not a cusip"); assertTrue(matches); } diff --git a/generator/src/test/java/com/scottlogic/deg/generator/generation/string/IsinStringGeneratorTests.java b/generator/src/test/java/com/scottlogic/deg/generator/generation/string/IsinStringGeneratorTests.java index 6a5126481..5970c4d15 100644 --- a/generator/src/test/java/com/scottlogic/deg/generator/generation/string/IsinStringGeneratorTests.java +++ b/generator/src/test/java/com/scottlogic/deg/generator/generation/string/IsinStringGeneratorTests.java @@ -16,25 +16,26 @@ package com.scottlogic.deg.generator.generation.string; +import com.scottlogic.deg.generator.generation.string.generators.StringGenerator; import com.scottlogic.deg.generator.utils.FinancialCodeUtils; -import com.scottlogic.deg.generator.utils.IterableAsStream; import com.scottlogic.deg.generator.utils.JavaUtilRandomNumberGenerator; import org.junit.Assert; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import java.util.Iterator; import java.util.concurrent.atomic.AtomicInteger; +import static com.scottlogic.deg.generator.generation.string.generators.ChecksumStringGeneratorFactory.createIsinGenerator; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; public class IsinStringGeneratorTests { @Test public void shouldEndAllIsinsWithValidCheckDigit() { - IsinStringGenerator target = new IsinStringGenerator(); + StringGenerator target = createIsinGenerator(); final int NumberOfTests = 100; final Iterator allIsins = target.generateAllValues().iterator(); @@ -48,7 +49,7 @@ public void shouldEndAllIsinsWithValidCheckDigit() { @Test public void shouldEndAllRandomIsinsWithValidCheckDigit() { - IsinStringGenerator target = new IsinStringGenerator(); + StringGenerator target = createIsinGenerator(); final int NumberOfTests = 100; @@ -66,7 +67,7 @@ public void shouldUseSedolWhenCountryIsGB() { // this assumes that the first batch of values produced by the generator are GB-flavoured. If this changes in the future, this test might need to get more complicated AtomicInteger numberOfIsinsTested = new AtomicInteger(0); - IterableAsStream.convert(new IsinStringGenerator().generateAllValues()) + createIsinGenerator().generateAllValues() .limit(100) .forEach(isinString -> { if (!isinString.substring(0, 2).equals("GB")) @@ -83,8 +84,9 @@ public void shouldUseSedolWhenCountryIsGB() { } @Test + @Disabled("Standard constraints e.g. ISINs currently cannot be negated") public void complementShouldProduceNoRandomValidIsins() { - StringGenerator target = new IsinStringGenerator().complement(); + StringGenerator target = createIsinGenerator().complement(); final int NumberOfTests = 100; @@ -98,36 +100,38 @@ public void complementShouldProduceNoRandomValidIsins() { @Test public void shouldMatchAValidIsinCodeWhenNotNegated(){ - StringGenerator isinGenerator = new IsinStringGenerator(); + StringGenerator isinGenerator = createIsinGenerator(); - boolean matches = isinGenerator.match("GB0002634946"); + boolean matches = isinGenerator.matches("GB0002634946"); Assert.assertTrue(matches); } @Test public void shouldNotMatchAnInvalidIsinCodeWhenNotNegated(){ - StringGenerator isinGenerator = new IsinStringGenerator(); + StringGenerator isinGenerator = createIsinGenerator(); - boolean matches = isinGenerator.match("not an isin"); + boolean matches = isinGenerator.matches("not an isin"); Assert.assertFalse(matches); } @Test + @Disabled("Standard constraints e.g. ISINs currently cannot be negated") public void shouldNotMatchAValidIsinCodeWhenNegated(){ - StringGenerator isinGenerator = new IsinStringGenerator().complement(); + StringGenerator isinGenerator = createIsinGenerator().complement(); - boolean matches = isinGenerator.match("GB0002634946"); + boolean matches = isinGenerator.matches("GB0002634946"); Assert.assertFalse(matches); } @Test + @Disabled("Standard constraints e.g. ISINs currently cannot be negated") public void shouldMatchAnInvalidIsinCodeWhenNegated(){ - StringGenerator isinGenerator = new IsinStringGenerator().complement(); + StringGenerator isinGenerator = createIsinGenerator().complement(); - boolean matches = isinGenerator.match("not an isin"); + boolean matches = isinGenerator.matches("not an isin"); Assert.assertTrue(matches); } diff --git a/generator/src/test/java/com/scottlogic/deg/generator/generation/string/RegexStringGeneratorTests.java b/generator/src/test/java/com/scottlogic/deg/generator/generation/string/RegexStringGeneratorTests.java index 57ca34259..44c15531d 100644 --- a/generator/src/test/java/com/scottlogic/deg/generator/generation/string/RegexStringGeneratorTests.java +++ b/generator/src/test/java/com/scottlogic/deg/generator/generation/string/RegexStringGeneratorTests.java @@ -16,7 +16,8 @@ package com.scottlogic.deg.generator.generation.string; -import com.scottlogic.deg.generator.utils.IterableAsStream; +import com.scottlogic.deg.generator.generation.string.generators.RegexStringGenerator; +import com.scottlogic.deg.generator.generation.string.generators.StringGenerator; import com.scottlogic.deg.generator.utils.JavaUtilRandomNumberGenerator; import org.hamcrest.core.Is; import org.junit.jupiter.api.BeforeEach; @@ -24,6 +25,7 @@ import java.util.*; import java.util.stream.Collectors; +import java.util.stream.Stream; import java.util.stream.StreamSupport; import static com.scottlogic.deg.generator.helpers.StringGeneratorHelper.assertGeneratorCanGenerateAtLeastOneStringWithinLengthBounds; @@ -105,10 +107,10 @@ void shouldCorrectlyReplaceCharacterGroups() { void generateInterestingValuesShouldGenerateShortestAndLongestValues() { StringGenerator generator = new RegexStringGenerator("Test_(\\d{3}|[A-Z]{5})_(banana|apple)", true); - Iterable resultsIterable = generator.generateInterestingValues(); + List results = generator.generateInterestingValues().collect(Collectors.toList()); assertThat( - resultsIterable, + results, containsInAnyOrder( "Test_000_apple", "Test_AAAAA_banana")); @@ -118,9 +120,9 @@ void generateInterestingValuesShouldGenerateShortestAndLongestValues() { void interestingValuesShouldBePrintable() { StringGenerator generator = new RegexStringGenerator("Test.Test", true); - Iterable resultsIterable = generator.generateInterestingValues(); + List results = generator.generateInterestingValues().collect(Collectors.toList()); - for (String interestingValue : resultsIterable) { + for (String interestingValue : results) { for (char character : interestingValue.toCharArray()) { assertThat(character, greaterThanOrEqualTo((char)32)); } @@ -131,43 +133,22 @@ void interestingValuesShouldBePrintable() { void interestingValuesShouldBeBounds() { StringGenerator generator = new RegexStringGenerator(".{10,20}", true); - Iterable resultsIterable = generator.generateInterestingValues(); - - ArrayList results = new ArrayList<>(); - - resultsIterable.iterator().forEachRemaining(results::add); + List results = generator.generateInterestingValues().collect(Collectors.toList()); assertThat(results.size(), Is.is(2)); assertThat(results.get(0).length(), Is.is(10)); assertThat(results.get(1).length(), Is.is(20)); } - @Test - void iterableShouldBeRepeatable() { - StringGenerator generator = new RegexStringGenerator("Test", true); - - Iterable resultsIterable = generator.generateInterestingValues(); - - resultsIterable.iterator().forEachRemaining(string -> { - }); // once - - resultsIterable.iterator().forEachRemaining(string -> { - }); // twice - } - @Test void shouldCreateZeroLengthInterestingValue() { StringGenerator generator = new RegexStringGenerator("(Test)?", true); - Iterable resultsIterable = generator.generateInterestingValues(); - - String[] sampleValues = - IterableAsStream.convert(resultsIterable) - .toArray(String[]::new); + List results = generator.generateInterestingValues().collect(Collectors.toList()); assertThat( - sampleValues, - arrayContainingInAnyOrder( + results, + containsInAnyOrder( "", "Test")); } @@ -176,12 +157,12 @@ void shouldCreateZeroLengthInterestingValue() { void shouldCorrectlySampleInfiniteResults() { StringGenerator generator = new RegexStringGenerator("[a]+", false); - Iterable resultsIterable = generator.generateRandomValues(new JavaUtilRandomNumberGenerator(0)); + Stream results = generator.generateRandomValues(new JavaUtilRandomNumberGenerator(0)); List sampleValues = - IterableAsStream.convert(resultsIterable) - .limit(1000) - .collect(Collectors.toList()); + results + .limit(1000) + .collect(Collectors.toList()); assertThat(sampleValues, not(contains(null, ""))); } @@ -238,8 +219,8 @@ void shouldReturnValuesWhenNonContradictingConstraints() { @Test void shouldNotGenerateInvalidUnicodeCodePoints() { StringGenerator generator = new RegexStringGenerator("[😁-😘]{1}", true); - Iterable resultsIterable = generator.generateAllValues(); - for (String s : resultsIterable) { + List results = generator.generateAllValues().collect(Collectors.toList()); + for (String s : results) { if (s != null && doesStringContainSurrogates(s)) { fail("string contains surrogate character"); } @@ -362,13 +343,13 @@ private void expectFirstResult(String expectedValue) { private void expectMatch(String subject, boolean matchFullString) { StringGenerator generator = constructGenerator(matchFullString); - assertTrue(generator.match(subject)); + assertTrue(generator.matches(subject)); } private void expectNoMatch(String subject, boolean matchFullString) { StringGenerator generator = constructGenerator(matchFullString); - assertFalse(generator.match(subject)); + assertFalse(generator.matches(subject)); } @Test @@ -397,11 +378,9 @@ void generateInterestingValues_withShorterThanAndContainingAndMatchingRegex_shou StringGenerator intersected = shorterThan.intersect(matchingRegex).intersect(containingRegex); - Iterable result = intersected.generateInterestingValues(); + List results = intersected.generateInterestingValues().collect(Collectors.toList()); - ArrayList strings = new ArrayList<>(); - result.iterator().forEachRemaining(strings::add); - assertThat(strings, not(empty())); + assertThat(results, not(empty())); } @Test @@ -411,18 +390,16 @@ void generateInterestingValues_withShorterThanAndMatchingRegex_shouldBeAbleToCre StringGenerator intersected = shorterThan.intersect(matchingRegex); - Iterable result = intersected.generateInterestingValues(); + List results = intersected.generateInterestingValues().collect(Collectors.toList()); - ArrayList strings = new ArrayList<>(); - result.iterator().forEachRemaining(strings::add); - assertThat(strings, not(empty())); + assertThat(results, not(empty())); } @Test void match_withInputMatchingRequiredLength_shouldMatch(){ RegexStringGenerator shorterThan = new RegexStringGenerator("^.{0,1}$", true); - boolean match = shorterThan.match("a"); + boolean match = shorterThan.matches("a"); assertThat(match, is(true)); } @@ -431,7 +408,7 @@ void match_withInputMatchingRequiredLength_shouldMatch(){ void match_withInputMatchingFirstRequiredLength_shouldMatch(){ RegexStringGenerator shorterThan = new RegexStringGenerator("^(.{0,1}|.{3,10})$", true); - boolean match = shorterThan.match("a"); + boolean match = shorterThan.matches("a"); assertThat(match, is(true)); } @@ -440,7 +417,7 @@ void match_withInputMatchingFirstRequiredLength_shouldMatch(){ void match_withInputMatchingSecondRequiredLength_shouldMatch(){ RegexStringGenerator shorterThan = new RegexStringGenerator("^(.{0,1}|.{3,10})$", true); - boolean match = shorterThan.match("aaa"); + boolean match = shorterThan.matches("aaa"); assertThat(match, is(true)); } @@ -449,7 +426,7 @@ void match_withInputMatchingSecondRequiredLength_shouldMatch(){ void match_withInputNotMatchingAnyRequiredLength_shouldNotMatch(){ RegexStringGenerator shorterThan = new RegexStringGenerator("^(.{0,1}|.{3,10})$", true); - boolean match = shorterThan.match("aa"); + boolean match = shorterThan.matches("aa"); assertThat(match, is(false)); } diff --git a/generator/src/test/java/com/scottlogic/deg/generator/generation/string/SedolStringGeneratorTests.java b/generator/src/test/java/com/scottlogic/deg/generator/generation/string/SedolStringGeneratorTests.java index 4199fdc97..cc1e737b8 100644 --- a/generator/src/test/java/com/scottlogic/deg/generator/generation/string/SedolStringGeneratorTests.java +++ b/generator/src/test/java/com/scottlogic/deg/generator/generation/string/SedolStringGeneratorTests.java @@ -16,44 +16,49 @@ package com.scottlogic.deg.generator.generation.string; +import com.scottlogic.deg.generator.generation.string.generators.StringGenerator; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import static com.scottlogic.deg.generator.generation.string.generators.ChecksumStringGeneratorFactory.createSedolGenerator; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; public class SedolStringGeneratorTests { @Test public void shouldMatchAValidSedolCodeWhenNotNegated(){ - StringGenerator SedolGenerator = new SedolStringGenerator(); + StringGenerator SedolGenerator = createSedolGenerator(); - boolean matches = SedolGenerator.match("2634946"); + boolean matches = SedolGenerator.matches("2634946"); assertTrue(matches); } @Test public void shouldNotMatchAnInvalidSedolCodeWhenNotNegated(){ - StringGenerator SedolGenerator = new SedolStringGenerator(); + StringGenerator SedolGenerator = createSedolGenerator(); - boolean matches = SedolGenerator.match("not a sedol"); + boolean matches = SedolGenerator.matches("not a sedol"); assertFalse(matches); } @Test + @Disabled("Standard constraints e.g. ISINs currently cannot be negated") public void shouldNotMatchAValidSedolCodeWhenNegated(){ - StringGenerator SedolGenerator = new SedolStringGenerator().complement(); + StringGenerator SedolGenerator = createSedolGenerator().complement(); - boolean matches = SedolGenerator.match("2634946"); + boolean matches = SedolGenerator.matches("2634946"); assertFalse(matches); } @Test + @Disabled("Standard constraints e.g. ISINs currently cannot be negated") public void shouldMatchAnInvalidSedolCodeWhenNegated(){ - StringGenerator SedolGenerator = new SedolStringGenerator().complement(); + StringGenerator SedolGenerator = createSedolGenerator().complement(); - boolean matches = SedolGenerator.match("not a sedol"); + boolean matches = SedolGenerator.matches("not a sedol"); assertTrue(matches); } diff --git a/generator/src/test/java/com/scottlogic/deg/generator/helpers/StringGeneratorHelper.java b/generator/src/test/java/com/scottlogic/deg/generator/helpers/StringGeneratorHelper.java index a1c8b4834..96e91e19f 100644 --- a/generator/src/test/java/com/scottlogic/deg/generator/helpers/StringGeneratorHelper.java +++ b/generator/src/test/java/com/scottlogic/deg/generator/helpers/StringGeneratorHelper.java @@ -16,7 +16,7 @@ package com.scottlogic.deg.generator.helpers; -import com.scottlogic.deg.generator.generation.string.StringGenerator; +import com.scottlogic.deg.generator.generation.string.generators.StringGenerator; import org.junit.Assert; import java.util.Iterator; diff --git a/generator/src/test/java/com/scottlogic/deg/generator/restrictions/TextualRestrictionsTests.java b/generator/src/test/java/com/scottlogic/deg/generator/restrictions/TextualRestrictionsTests.java index fde91e293..cbbb30eda 100644 --- a/generator/src/test/java/com/scottlogic/deg/generator/restrictions/TextualRestrictionsTests.java +++ b/generator/src/test/java/com/scottlogic/deg/generator/restrictions/TextualRestrictionsTests.java @@ -17,10 +17,10 @@ package com.scottlogic.deg.generator.restrictions; import com.scottlogic.deg.common.profile.constraints.atomic.StandardConstraintTypes; -import com.scottlogic.deg.generator.generation.string.IsinStringGenerator; -import com.scottlogic.deg.generator.generation.string.RegexStringGenerator; -import com.scottlogic.deg.generator.generation.string.StringGenerator; +import com.scottlogic.deg.generator.generation.string.generators.RegexStringGenerator; +import com.scottlogic.deg.generator.generation.string.generators.StringGenerator; import org.junit.Assert; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import java.util.Collections; @@ -30,6 +30,7 @@ import static com.scottlogic.deg.generator.helpers.StringGeneratorHelper.*; import static org.hamcrest.Matchers.*; import static org.hamcrest.core.IsNull.nullValue; +import static org.junit.jupiter.api.Assertions.assertTrue; class TextualRestrictionsTests { @Test @@ -392,26 +393,26 @@ void createGenerator_withMinAndMaxLengthAndContainingRegexConstraint_shouldCreat @Test void createGenerator_withOnlyAMatchingStandardConstraint_shouldCreateSomeStrings() { - StringRestrictions restrictions = aValid(StandardConstraintTypes.ISIN, false); + StringRestrictions restrictions = aValid(StandardConstraintTypes.ISIN); StringGenerator generator = restrictions.createGenerator(); - Assert.assertThat(generator, instanceOf(IsinStringGenerator.class)); + assertTrue(generator.generateAllValues().limit(1).count() > 0); } @Test void createGenerator_withMinLengthAndMatchingStandardConstraint_shouldCreateSomeStrings() { - StringRestrictions restrictions = aValid(StandardConstraintTypes.ISIN, false) + StringRestrictions restrictions = aValid(StandardConstraintTypes.ISIN) .intersect(minLength(1)).restrictions; StringGenerator generator = restrictions.createGenerator(); - Assert.assertThat(generator, instanceOf(IsinStringGenerator.class)); + assertTrue(generator.generateAllValues().limit(1).count() > 0); } @Test void createGenerator_withMaxLengthShorterThanCodeLengthAndMatchingStandardConstraint_shouldCreateNoStrings() { - MergeResult intersect = aValid(StandardConstraintTypes.ISIN, false) + MergeResult intersect = aValid(StandardConstraintTypes.ISIN) .intersect(maxLength(10)); Assert.assertFalse(intersect.successful); @@ -419,37 +420,38 @@ void createGenerator_withMaxLengthShorterThanCodeLengthAndMatchingStandardConstr @Test void createGenerator_withMaxLengthAtLengthOfCodeLengthAndMatchingStandardConstraint_shouldCreateSomeStrings() { - StringRestrictions restrictions = aValid(StandardConstraintTypes.ISIN, false) + StringRestrictions restrictions = aValid(StandardConstraintTypes.ISIN) .intersect(maxLength(12)).restrictions; StringGenerator generator = restrictions.createGenerator(); - Assert.assertThat(generator, instanceOf(IsinStringGenerator.class)); + assertTrue(generator.generateAllValues().limit(1).count() > 0); } @Test void createGenerator_withMaxLengthLongerThanCodeLengthAndMatchingStandardConstraint_shouldCreateSomeStrings() { - StringRestrictions restrictions = aValid(StandardConstraintTypes.ISIN, false) + StringRestrictions restrictions = aValid(StandardConstraintTypes.ISIN) .intersect(maxLength(100)).restrictions; StringGenerator generator = restrictions.createGenerator(); - Assert.assertThat(generator, instanceOf(IsinStringGenerator.class)); + assertTrue(generator.generateAllValues().limit(1).count() > 0); } @Test void createGenerator_withOfLengthAndMatchingStandardConstraint_shouldCreateSomeStrings() { - StringRestrictions restrictions = aValid(StandardConstraintTypes.ISIN, false) + StringRestrictions restrictions = aValid(StandardConstraintTypes.ISIN) .intersect(ofLength(12, false)).restrictions; StringGenerator generator = restrictions.createGenerator(); - Assert.assertThat(generator, instanceOf(IsinStringGenerator.class)); + assertTrue(generator.generateAllValues().limit(1).count() > 0); } @Test + @Disabled("Regex constraints cannot currently be combined with standard constraints e.g. ISINs") void createGenerator_withMatchingRegexAndMatchingStandardConstraint_shouldCreateStrings() { - StringRestrictions restrictions = aValid(StandardConstraintTypes.ISIN, false) + StringRestrictions restrictions = aValid(StandardConstraintTypes.ISIN) .intersect(matchingRegex("[a-zA-Z0-9]{12}", false)).restrictions; StringGenerator generator = restrictions.createGenerator(); @@ -458,8 +460,9 @@ void createGenerator_withMatchingRegexAndMatchingStandardConstraint_shouldCreate } @Test + @Disabled("Regex constraints cannot currently be combined with standard constraints e.g. ISINs") void createGenerator_withContainingRegexAndMatchingStandardConstraint_shouldCreateStrings() { - StringRestrictions restrictions = aValid(StandardConstraintTypes.ISIN, false) + StringRestrictions restrictions = aValid(StandardConstraintTypes.ISIN) .intersect(containsRegex("[a-zA-Z0-9]{12}", false)).restrictions; StringGenerator generator = restrictions.createGenerator(); @@ -686,8 +689,8 @@ private static StringRestrictions containsRegex(String regex, @SuppressWarnings( negate ? Collections.singleton(pattern) : Collections.emptySet()); } - private static StringRestrictions aValid(@SuppressWarnings("SameParameterValue") StandardConstraintTypes type, @SuppressWarnings("SameParameterValue") boolean negate){ - return new MatchesStandardStringRestrictions(type, negate); + private static StringRestrictions aValid(StandardConstraintTypes type){ + return new MatchesStandardStringRestrictions(type); } private static void assertGeneratorCannotGenerateAnyStrings(StringGenerator generator) { From bfaf559376ae234b63524a479d54d7d2d459be9b Mon Sep 17 00:00:00 2001 From: Matthew Date: Wed, 21 Aug 2019 16:05:03 +0100 Subject: [PATCH 10/20] Ignore cucumber tests relating to ISIN and similar constraints being combined with other constraints --- .../orchestrator/cucumber/features/Random.feature | 3 +++ .../operators/general/OfTypeFinancialCodes.feature | 14 ++++++++++++++ .../features/operators/string/LongerThan.feature | 6 ++++++ 3 files changed, 23 insertions(+) diff --git a/orchestrator/src/test/java/com/scottlogic/deg/orchestrator/cucumber/features/Random.feature b/orchestrator/src/test/java/com/scottlogic/deg/orchestrator/cucumber/features/Random.feature index ca8362631..514196b7c 100644 --- a/orchestrator/src/test/java/com/scottlogic/deg/orchestrator/cucumber/features/Random.feature +++ b/orchestrator/src/test/java/com/scottlogic/deg/orchestrator/cucumber/features/Random.feature @@ -66,6 +66,7 @@ Feature: User can generate valid data for all types (string, integer, decimal, o Then 5 rows of data are generated And foo contains strings matching /[A-Z]{2}[A-Z0-9]{9}[0-9]{1}/ + @ignore "Standard constraints e.g. ISINs cannot yet be combined with not equal to constraints." Scenario: The generator produces valid ISIN data in random mode when combined with a not equal to constraint Given foo is of type "ISIN" And foo is anything but equal to "GB009CJ9GB62" @@ -80,6 +81,7 @@ Feature: User can generate valid data for all types (string, integer, decimal, o Then 5 rows of data are generated And foo contains strings matching /[B-DF-HJ-NP-TV-Z0-9]{6}[0-9]/ + @ignore "Standard constraints e.g. ISINs cannot yet be combined with not equal to constraints." Scenario: The generator produces valid SEDOL data in random mode when combined with a not equal to constraint Given foo is of type "SEDOL" And foo is anything but equal to "3091357" @@ -94,6 +96,7 @@ Feature: User can generate valid data for all types (string, integer, decimal, o Then 5 rows of data are generated And foo contains strings matching /[0-9]{3}[A-Z0-9]{5}[0-9]/ + @ignore "Standard constraints e.g. ISINs cannot yet be combined with not equal to constraints." Scenario: The generator produces valid CUSIP data in random mode when combined with a not equal to constraint Given foo is of type "CUSIP" And foo is anything but equal to "594918104" diff --git a/orchestrator/src/test/java/com/scottlogic/deg/orchestrator/cucumber/features/operators/general/OfTypeFinancialCodes.feature b/orchestrator/src/test/java/com/scottlogic/deg/orchestrator/cucumber/features/operators/general/OfTypeFinancialCodes.feature index b8a38c290..04178ae4f 100644 --- a/orchestrator/src/test/java/com/scottlogic/deg/orchestrator/cucumber/features/operators/general/OfTypeFinancialCodes.feature +++ b/orchestrator/src/test/java/com/scottlogic/deg/orchestrator/cucumber/features/operators/general/OfTypeFinancialCodes.feature @@ -82,6 +82,7 @@ Feature: User can specify that a field must be a financial code type | null | | "GB0002634946" | + @ignore "Standard constraints e.g. ISINs cannot yet be negated." Scenario: An ISIN constraint combined with a non-ISIN constraint generates no data Given foo is of type "ISIN" And foo is anything but null @@ -322,6 +323,7 @@ Feature: User can specify that a field must be a financial code type | "GB0002634946" | | null | + @ignore "Standard constraints e.g. ISINs cannot yet be combined with regex constraints." Scenario: An ISIN constraint combined with a matching regex constraint that matches valid ISINs should generate matching valid ISINs Given foo is of type "ISIN" And foo is matching regex "US9311421039" @@ -330,6 +332,7 @@ Feature: User can specify that a field must be a financial code type | "US9311421039" | | null | + @ignore "Standard constraints e.g. ISINs cannot yet be combined with regex constraints." Scenario: An ISIN constraint combined with a matching regex constraint that cannot match any valid ISIN due to its length should only generate null Given foo is of type "ISIN" And foo is matching regex "US[0-9]{9}" @@ -337,6 +340,7 @@ Feature: User can specify that a field must be a financial code type | foo | | null | + @ignore "Standard constraints e.g. ISINs cannot yet be combined with regex constraints." Scenario: An ISIN constraint combined with a matching regex constraint that cannot match any valid ISIN due to its check digit should only generate null Given foo is of type "ISIN" And foo is matching regex "US9311421038" @@ -354,6 +358,7 @@ Feature: User can specify that a field must be a financial code type | null | | "0263494" | + @ignore "Standard constraints e.g. ISINs cannot yet be negated." Scenario: A SEDOL constraint combined with a non-SEDOL constraint generates no data Given foo is of type "SEDOL" And foo is anything but null @@ -581,6 +586,7 @@ Feature: User can specify that a field must be a financial code type | "0263494" | | null | + @ignore "Standard constraints e.g. ISINs cannot yet be combined with date constraints." Scenario: A SEDOL constraint combined with a not before or at constraint generates valid SEDOLs Given foo is of type "SEDOL" And foo is anything but before or at 2019-01-01T00:00:00.000Z @@ -594,6 +600,7 @@ Feature: User can specify that a field must be a financial code type | "0263494" | | null | + @ignore "Standard constraints e.g. ISINs cannot yet be combined with regex constraints." Scenario: A SEDOL constraint combined with a matching regex constraint that matches valid SEDOLs should generate valid SEDOLs Given foo is of type "SEDOL" And foo is matching regex "0263494" @@ -602,6 +609,7 @@ Feature: User can specify that a field must be a financial code type | "0263494" | | null | + @ignore "Standard constraints e.g. ISINs cannot yet be combined with regex constraints." Scenario: A SEDOL constraint combined with a matching regex constraint that cannot match any valid SEDOL because it has the wrong check digit should only generate null Given foo is of type "SEDOL" And foo is matching regex "0263492" @@ -609,6 +617,7 @@ Feature: User can specify that a field must be a financial code type | foo | | null | + @ignore "Standard constraints e.g. ISINs cannot yet be combined with regex constraints." Scenario: A SEDOL constraint combined with a matching regex constraint that cannot match any valid SEDOL because it has the wrong length should only generate null Given foo is of type "SEDOL" And foo is matching regex "[0-9]{6}" @@ -616,6 +625,7 @@ Feature: User can specify that a field must be a financial code type | foo | | null | + @ignore "Standard constraints e.g. ISINs cannot yet be combined with regex constraints." Scenario: A SEDOL constraint combined with a matching regex constraint that cannot match any valid SEDOL because it cannot have a correct check digit should only generate null Given foo is of type "SEDOL" And foo is matching regex "0[023]63492" @@ -633,6 +643,7 @@ Feature: User can specify that a field must be a financial code type | null | | "38259P508" | + @ignore "Standard constraints e.g. ISINs cannot yet be negated." Scenario: A CUSIP constraint combined with a non-CUSIP constraint generates no data Given foo is of type "CUSIP" And foo is anything but null @@ -873,6 +884,7 @@ Feature: User can specify that a field must be a financial code type | "38259P508" | | null | + @ignore "Standard constraints e.g. ISINs cannot yet be combined with regex constraints." Scenario: A CUSIP constraint combined with a matching regex constraint that matches a valid CUSIP generates valid CUSIPs Given foo is of type "CUSIP" And foo is matching regex "38259P508" @@ -881,6 +893,7 @@ Feature: User can specify that a field must be a financial code type | "38259P508" | | null | + @ignore "Standard constraints e.g. ISINs cannot yet be combined with regex constraints." Scenario: A CUSIP constraint combined with a matching regex constraint that cannot match a valid CUSIP because it has an invalid check digit should only generate null Given foo is of type "CUSIP" And foo is matching regex "38259P509" @@ -888,6 +901,7 @@ Feature: User can specify that a field must be a financial code type | foo | | null | + @ignore "Standard constraints e.g. ISINs cannot yet be combined with regex constraints." Scenario: A CUSIP constraint combined with a matching regex constraint that cannot match a valid CUSIP because it has the wrong length should only generate null Given foo is of type "CUSIP" And foo is matching regex "[0-9]{3}.{4}[0-9]" diff --git a/orchestrator/src/test/java/com/scottlogic/deg/orchestrator/cucumber/features/operators/string/LongerThan.feature b/orchestrator/src/test/java/com/scottlogic/deg/orchestrator/cucumber/features/operators/string/LongerThan.feature index 6c4384e1c..9fa67d8a5 100644 --- a/orchestrator/src/test/java/com/scottlogic/deg/orchestrator/cucumber/features/operators/string/LongerThan.feature +++ b/orchestrator/src/test/java/com/scottlogic/deg/orchestrator/cucumber/features/operators/string/LongerThan.feature @@ -229,6 +229,7 @@ Feature: User can specify that a string length is longer than, a specified numbe | "GB00YG2XYC52" | | "US0378331005" | + @ignore "Standard constraints e.g. ISINs cannot yet be negated." Scenario: A longer than constraint combined with a non-ISIN constraint generates data that matches the longer than constraint and contains no valid ISINs Given foo is longer than 2 And foo is anything but null @@ -263,6 +264,7 @@ Feature: User can specify that a string length is longer than, a specified numbe | foo | | null | + @ignore "Standard constraints e.g. ISINs cannot yet be negated." Scenario: A not longer than constraint combined with a non-ISIN constraint generates data that contains no valid ISINs Given foo is anything but longer than 12 And foo is anything but null @@ -290,6 +292,7 @@ Feature: User can specify that a string length is longer than, a specified numbe | "0263494" | | "3091357" | + @ignore "Standard constraints e.g. ISINs cannot yet be negated." Scenario: A longer than constraint combined with a non-SEDOL constraint generates data that matches the longer than constraint and contains no valid SEDOLs Given foo is longer than 2 And foo is anything but null @@ -324,6 +327,7 @@ Feature: User can specify that a string length is longer than, a specified numbe | foo | | null | + @ignore "Standard constraints e.g. ISINs cannot yet be negated." Scenario: A not longer than constraint combined with a non-SEDOL constraint generates data that matches the longer than constraint and contains no valid SEDOLs Given foo is anything but longer than 7 And foo is anything but null @@ -351,6 +355,7 @@ Feature: User can specify that a string length is longer than, a specified numbe | "38259P508" | | "594918104" | + @ignore "Standard constraints e.g. ISINs cannot yet be negated." Scenario: A longer than constraint combined with a non-CUSIP constraint generates data that matches the longer than constraint and contains no valid CUSIPs Given foo is longer than 2 And foo is anything but null @@ -385,6 +390,7 @@ Feature: User can specify that a string length is longer than, a specified numbe | foo | | null | + @ignore "Standard constraints e.g. ISINs cannot yet be negated." Scenario: A not longer than constraint combined with a non-CUSIP constraint generates data that matches the not longer than constraint and contains no valid CUSIPs Given foo is anything but longer than 9 And foo is anything but null From 49b3cc195f44af7a69ba9f2a3471f459a2cba993 Mon Sep 17 00:00:00 2001 From: Matthew Date: Wed, 21 Aug 2019 16:23:49 +0100 Subject: [PATCH 11/20] Change test of GB isins to no longer rely on GB being the first country produced by the full sequential mode of ISINs --- .../generation/string/IsinStringGeneratorTests.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/generator/src/test/java/com/scottlogic/deg/generator/generation/string/IsinStringGeneratorTests.java b/generator/src/test/java/com/scottlogic/deg/generator/generation/string/IsinStringGeneratorTests.java index 5970c4d15..157ac62fd 100644 --- a/generator/src/test/java/com/scottlogic/deg/generator/generation/string/IsinStringGeneratorTests.java +++ b/generator/src/test/java/com/scottlogic/deg/generator/generation/string/IsinStringGeneratorTests.java @@ -16,9 +16,11 @@ package com.scottlogic.deg.generator.generation.string; +import com.scottlogic.deg.generator.generation.fieldvaluesources.datetime.DateTimeFieldValueSourceTests; import com.scottlogic.deg.generator.generation.string.generators.StringGenerator; import com.scottlogic.deg.generator.utils.FinancialCodeUtils; import com.scottlogic.deg.generator.utils.JavaUtilRandomNumberGenerator; +import com.scottlogic.deg.generator.utils.RandomNumberGenerator; import org.junit.Assert; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -30,6 +32,8 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; public class IsinStringGeneratorTests { @@ -64,15 +68,11 @@ public void shouldEndAllRandomIsinsWithValidCheckDigit() { @Test public void shouldUseSedolWhenCountryIsGB() { - // this assumes that the first batch of values produced by the generator are GB-flavoured. If this changes in the future, this test might need to get more complicated - AtomicInteger numberOfIsinsTested = new AtomicInteger(0); - createIsinGenerator().generateAllValues() + createIsinGenerator().generateRandomValues(new JavaUtilRandomNumberGenerator()) + .filter(isinString -> isinString.substring(0, 2).equals("GB")) .limit(100) .forEach(isinString -> { - if (!isinString.substring(0, 2).equals("GB")) - throw new IllegalStateException("Test assumes that the first 100 ISINs will be GB-flavoured"); - assertThat( FinancialCodeUtils.isValidSedolNsin(isinString.substring(2, 11)), is(true)); From 118a821759bf6a88b837eea4b78da1b84a858815 Mon Sep 17 00:00:00 2001 From: Matthew Date: Wed, 21 Aug 2019 16:27:52 +0100 Subject: [PATCH 12/20] Add all officially assigned ISIN country codes. List taken from https://www.isin.net/country-codes/ --- .../string/generators/IsinCountryCode.java | 248 +++++++++++++++++- 1 file changed, 247 insertions(+), 1 deletion(-) diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/IsinCountryCode.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/IsinCountryCode.java index becab1a8e..3490c5802 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/IsinCountryCode.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/IsinCountryCode.java @@ -20,9 +20,255 @@ import static com.scottlogic.deg.generator.generation.string.generators.ChecksumStringGeneratorFactory.createSedolGenerator; public enum IsinCountryCode { + AD, + AE, + AF, + AG, + AI, + AL, + AM, + AO, + AQ, + AR, + AS, + AT, + AU, + AW, + AX, + AZ, + BA, + BB, + BD, + BE, + BF, + BG, + BH, + BI, + BJ, + BL, + BM, + BN, + BO, + BQ, + BR, + BS, + BT, + BV, + BW, + BY, + BZ, + CA, + CC, + CD, + CF, + CG, + CH, + CI, + CK, + CL, + CM, + CN, + CO, + CR, + CU, + CV, + CW, + CX, + CY, + CZ, + DE, + DJ, + DK, + DM, + DO, + DZ, + EC, + EE, + EG, + EH, + ER, + ES, + ET, + FI, + FJ, + FK, + FM, + FO, + FR, + GA, GB(prefix("GB00", createSedolGenerator())), + GD, + GE, + GF, + GG, + GH, + GI, + GL, + GM, + GN, + GP, + GQ, + GR, + GS, + GT, + GU, + GW, + GY, + HK, + HM, + HN, + HR, + HT, + HU, + ID, + IE, + IL, + IM, + IN, + IO, + IQ, + IR, + IS, + IT, + JE, + JM, + JO, + JP, + KE, + KG, + KH, + KI, + KM, + KN, + KP, + KR, + KW, + KY, + KZ, + LA, + LB, + LC, + LI, + LK, + LR, + LS, + LT, + LU, + LV, + LY, + MA, + MC, + MD, + ME, + MF, + MG, + MH, + MK, + ML, + MM, + MN, + MO, + MP, + MQ, + MR, + MS, + MT, + MU, + MV, + MW, + MX, + MY, + MZ, + NA, + NC, + NE, + NF, + NG, + NI, + NL, + NO, + NP, + NR, + NU, + NZ, + OM, + PA, + PE, + PF, + PG, + PH, + PK, + PL, + PM, + PN, + PR, + PS, + PT, + PW, + PY, + QA, + RE, + RO, + RS, + RU, + RW, + SA, + SB, + SC, + SD, + SE, + SG, + SH, + SI, + SJ, + SK, + SL, + SM, + SN, + SO, + SR, + SS, + ST, + SV, + SX, + SY, + SZ, + TC, + TD, + TF, + TG, + TH, + TJ, + TK, + TL, + TM, + TN, + TO, + TR, + TT, + TV, + TW, + TZ, + UA, + UG, + UM, US(prefix("US", createCusipGenerator())), - DN; + UY, + UZ, + VA, + VC, + VE, + VG, + VI, + VN, + VU, + WF, + WS, + YE, + YT, + ZA, + ZM, + ZW; String GENERIC_NSIN_REGEX = "[A-Z0-9]{9}"; private final StringGenerator checksumlessStringGenerator; From 120bb5d363dcd3858dd594233b340e72d2193281 Mon Sep 17 00:00:00 2001 From: Matthew Date: Wed, 21 Aug 2019 16:34:22 +0100 Subject: [PATCH 13/20] Fix test for full sequential mode of ISINs --- .../operators/general/OfTypeFinancialCodes.feature | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/orchestrator/src/test/java/com/scottlogic/deg/orchestrator/cucumber/features/operators/general/OfTypeFinancialCodes.feature b/orchestrator/src/test/java/com/scottlogic/deg/orchestrator/cucumber/features/operators/general/OfTypeFinancialCodes.feature index 04178ae4f..6f5a3f35a 100644 --- a/orchestrator/src/test/java/com/scottlogic/deg/orchestrator/cucumber/features/operators/general/OfTypeFinancialCodes.feature +++ b/orchestrator/src/test/java/com/scottlogic/deg/orchestrator/cucumber/features/operators/general/OfTypeFinancialCodes.feature @@ -19,10 +19,10 @@ Feature: User can specify that a field must be a financial code type And the generator can generate at most 4 rows Then the following data should be generated: | foo | - | "GB0000000009" | - | "GB0000000116" | - | "GB0000000223" | - | "GB0000000330" | + | "AD0000000003" | + | "AD0000000011" | + | "AD0000000029" | + | "AD0000000037" | Scenario: An ofType constraint with the value "isin" fails with an invalid profile error message Given foo is of type "isin" From 9e15eda83855ac4cab4e3c825f90d09dd7cf03d4 Mon Sep 17 00:00:00 2001 From: Matthew Date: Wed, 21 Aug 2019 16:53:35 +0100 Subject: [PATCH 14/20] Add tests for non-GB ISIN generation --- .../string/IsinStringGeneratorTests.java | 44 +++++++++++++++++-- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/generator/src/test/java/com/scottlogic/deg/generator/generation/string/IsinStringGeneratorTests.java b/generator/src/test/java/com/scottlogic/deg/generator/generation/string/IsinStringGeneratorTests.java index 157ac62fd..1365bf1ab 100644 --- a/generator/src/test/java/com/scottlogic/deg/generator/generation/string/IsinStringGeneratorTests.java +++ b/generator/src/test/java/com/scottlogic/deg/generator/generation/string/IsinStringGeneratorTests.java @@ -16,11 +16,10 @@ package com.scottlogic.deg.generator.generation.string; -import com.scottlogic.deg.generator.generation.fieldvaluesources.datetime.DateTimeFieldValueSourceTests; +import com.scottlogic.deg.generator.generation.string.generators.RegexStringGenerator; import com.scottlogic.deg.generator.generation.string.generators.StringGenerator; import com.scottlogic.deg.generator.utils.FinancialCodeUtils; import com.scottlogic.deg.generator.utils.JavaUtilRandomNumberGenerator; -import com.scottlogic.deg.generator.utils.RandomNumberGenerator; import org.junit.Assert; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -32,8 +31,7 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; +import static org.junit.jupiter.api.Assertions.assertTrue; public class IsinStringGeneratorTests { @@ -83,6 +81,44 @@ public void shouldUseSedolWhenCountryIsGB() { assertThat(numberOfIsinsTested.get(), equalTo(100)); } + @Test + public void shouldUseCusipWhenCountryIsUS() { + AtomicInteger numberOfIsinsTested = new AtomicInteger(0); + createIsinGenerator().generateRandomValues(new JavaUtilRandomNumberGenerator()) + .filter(isinString -> isinString.substring(0, 2).equals("US")) + .limit(100) + .forEach(isinString -> { + assertThat( + FinancialCodeUtils.isValidCusipNsin(isinString.substring(2, 11)), is(true)); + + numberOfIsinsTested.incrementAndGet(); + }); + + // make sure we tested the number we expected + assertThat(numberOfIsinsTested.get(), equalTo(100)); + } + + @Test + public void shouldUseGeneralRegexWhenCountryIsNotGbOrUs() { + AtomicInteger numberOfIsinsTested = new AtomicInteger(0); + createIsinGenerator().generateRandomValues(new JavaUtilRandomNumberGenerator()) + .filter(isinString -> { + String countryCode = isinString.substring(0, 2); + return !countryCode.equals("GB") && !countryCode.equals("US"); + }) + .limit(100) + .forEach(isinString -> { + String APPROX_ISIN_REGEX = "[A-Z]{2}[A-Z0-9]{9}[0-9]"; + RegexStringGenerator regexStringGenerator = new RegexStringGenerator(APPROX_ISIN_REGEX, true); + assertTrue(regexStringGenerator.matches(isinString)); + + numberOfIsinsTested.incrementAndGet(); + }); + + // make sure we tested the number we expected + assertThat(numberOfIsinsTested.get(), equalTo(100)); + } + @Test @Disabled("Standard constraints e.g. ISINs currently cannot be negated") public void complementShouldProduceNoRandomValidIsins() { From d26324d534a4edf2315d869b8e8b263595449921 Mon Sep 17 00:00:00 2001 From: Matthew Date: Wed, 21 Aug 2019 17:02:29 +0100 Subject: [PATCH 15/20] Add checksum tests for sedols and cusips --- .../string/CusipStringGeneratorTests.java | 35 +++++++++++++++++++ .../string/SedolStringGeneratorTests.java | 34 ++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/generator/src/test/java/com/scottlogic/deg/generator/generation/string/CusipStringGeneratorTests.java b/generator/src/test/java/com/scottlogic/deg/generator/generation/string/CusipStringGeneratorTests.java index 157f7328f..4f3eee347 100644 --- a/generator/src/test/java/com/scottlogic/deg/generator/generation/string/CusipStringGeneratorTests.java +++ b/generator/src/test/java/com/scottlogic/deg/generator/generation/string/CusipStringGeneratorTests.java @@ -17,14 +17,49 @@ package com.scottlogic.deg.generator.generation.string; import com.scottlogic.deg.generator.generation.string.generators.StringGenerator; +import com.scottlogic.deg.generator.utils.FinancialCodeUtils; +import com.scottlogic.deg.generator.utils.JavaUtilRandomNumberGenerator; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import java.util.Iterator; + import static com.scottlogic.deg.generator.generation.string.generators.ChecksumStringGeneratorFactory.createCusipGenerator; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; public class CusipStringGeneratorTests { + @Test + public void shouldEndAllCusipsWithValidCheckDigit() { + StringGenerator target = createCusipGenerator(); + final int NumberOfTests = 100; + + final Iterator allCusips = target.generateAllValues().iterator(); + + for (int ii = 0; ii < NumberOfTests; ++ii) { + final String nextCusip = allCusips.next(); + final char checkDigit = FinancialCodeUtils.calculateCusipCheckDigit(nextCusip.substring(0, 8)); + assertThat(nextCusip.charAt(8), equalTo(checkDigit)); + } + } + + @Test + public void shouldEndAllRandomCusipsWithValidCheckDigit() { + StringGenerator target = createCusipGenerator(); + + final int NumberOfTests = 100; + + final Iterator allCusips = target.generateRandomValues(new JavaUtilRandomNumberGenerator()).iterator(); + + for (int ii = 0; ii < NumberOfTests; ++ii) { + final String nextCusip = allCusips.next(); + final char checkDigit = FinancialCodeUtils.calculateCusipCheckDigit(nextCusip.substring(0, 8)); + assertThat(nextCusip.charAt(8), equalTo(checkDigit)); + } + } + @Test public void shouldMatchAValidCusipCodeWhenNotNegated(){ StringGenerator cusipGenerator = createCusipGenerator(); diff --git a/generator/src/test/java/com/scottlogic/deg/generator/generation/string/SedolStringGeneratorTests.java b/generator/src/test/java/com/scottlogic/deg/generator/generation/string/SedolStringGeneratorTests.java index cc1e737b8..083e0348a 100644 --- a/generator/src/test/java/com/scottlogic/deg/generator/generation/string/SedolStringGeneratorTests.java +++ b/generator/src/test/java/com/scottlogic/deg/generator/generation/string/SedolStringGeneratorTests.java @@ -17,14 +17,48 @@ package com.scottlogic.deg.generator.generation.string; import com.scottlogic.deg.generator.generation.string.generators.StringGenerator; +import com.scottlogic.deg.generator.utils.FinancialCodeUtils; +import com.scottlogic.deg.generator.utils.JavaUtilRandomNumberGenerator; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import java.util.Iterator; + import static com.scottlogic.deg.generator.generation.string.generators.ChecksumStringGeneratorFactory.createSedolGenerator; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; public class SedolStringGeneratorTests { + @Test + public void shouldEndAllSedolsWithValidCheckDigit() { + StringGenerator target = createSedolGenerator(); + final int NumberOfTests = 100; + + final Iterator allSedols = target.generateAllValues().iterator(); + + for (int ii = 0; ii < NumberOfTests; ++ii) { + final String nextSedol = allSedols.next(); + final char checkDigit = FinancialCodeUtils.calculateSedolCheckDigit(nextSedol.substring(0, 6)); + assertThat(nextSedol.charAt(6), equalTo(checkDigit)); + } + } + + @Test + public void shouldEndAllRandomCusipsWithValidCheckDigit() { + StringGenerator target = createSedolGenerator(); + + final int NumberOfTests = 100; + + final Iterator allSedols = target.generateRandomValues(new JavaUtilRandomNumberGenerator()).iterator(); + + for (int ii = 0; ii < NumberOfTests; ++ii) { + final String nextSedol = allSedols.next(); + final char checkDigit = FinancialCodeUtils.calculateSedolCheckDigit(nextSedol.substring(0, 6)); + assertThat(nextSedol.charAt(6), equalTo(checkDigit)); + } + } @Test public void shouldMatchAValidSedolCodeWhenNotNegated(){ StringGenerator SedolGenerator = createSedolGenerator(); From 8395d7c344cfa3a85db12c1c0e9f369e89c3cfb7 Mon Sep 17 00:00:00 2001 From: Matthew Date: Thu, 22 Aug 2019 13:20:46 +0100 Subject: [PATCH 16/20] Add tests for matches methods on string generators --- .../ChecksumStringGeneratorTests.java | 63 +++++++++++++++++++ .../ChecksumlessIsinGeneratorTests.java | 55 ++++++++++++++++ .../PrefixingStringGeneratorTests.java | 55 ++++++++++++++++ 3 files changed, 173 insertions(+) create mode 100644 generator/src/test/java/com/scottlogic/deg/generator/generation/string/generators/ChecksumStringGeneratorTests.java create mode 100644 generator/src/test/java/com/scottlogic/deg/generator/generation/string/generators/ChecksumlessIsinGeneratorTests.java create mode 100644 generator/src/test/java/com/scottlogic/deg/generator/generation/string/generators/PrefixingStringGeneratorTests.java diff --git a/generator/src/test/java/com/scottlogic/deg/generator/generation/string/generators/ChecksumStringGeneratorTests.java b/generator/src/test/java/com/scottlogic/deg/generator/generation/string/generators/ChecksumStringGeneratorTests.java new file mode 100644 index 000000000..68918fea3 --- /dev/null +++ b/generator/src/test/java/com/scottlogic/deg/generator/generation/string/generators/ChecksumStringGeneratorTests.java @@ -0,0 +1,63 @@ +package com.scottlogic.deg.generator.generation.string.generators; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +/* + * Copyright 2019 Scott Logic Ltd + * + * 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. + */ +class ChecksumStringGeneratorTests { + @Test + void matches_withInvalidPreChecksum_returnsFalse() { + String preChecksum = "abc"; + Character checksum = 'a'; + StringGenerator mockGenerator = mock(StringGenerator.class); + when(mockGenerator.matches(preChecksum)).thenReturn(false); + ChecksumMaker mockChecksumMaker = input -> input.charAt(0); + + ChecksumStringGenerator checksumStringGenerator = new ChecksumStringGenerator(mockGenerator, mockChecksumMaker); + + assertFalse(checksumStringGenerator.matches(preChecksum + checksum)); + } + + @Test + void matches_withInvalidChecksum_returnsFalse() { + String preChecksum = "abc"; + Character checksum = 'b'; + StringGenerator mockGenerator = mock(StringGenerator.class); + when(mockGenerator.matches(preChecksum)).thenReturn(true); + ChecksumMaker mockChecksumMaker = input -> input.charAt(0); + + ChecksumStringGenerator checksumStringGenerator = new ChecksumStringGenerator(mockGenerator, mockChecksumMaker); + + assertFalse(checksumStringGenerator.matches(preChecksum + checksum)); + } + + @Test + void matches_withValidString_returnsTrue() { + String preChecksum = "abc"; + Character checksum = 'a'; + StringGenerator mockGenerator = mock(StringGenerator.class); + when(mockGenerator.matches(preChecksum)).thenReturn(true); + ChecksumMaker mockChecksumMaker = input -> input.charAt(0); + + ChecksumStringGenerator checksumStringGenerator = new ChecksumStringGenerator(mockGenerator, mockChecksumMaker); + + assertTrue(checksumStringGenerator.matches(preChecksum + checksum)); + } +} diff --git a/generator/src/test/java/com/scottlogic/deg/generator/generation/string/generators/ChecksumlessIsinGeneratorTests.java b/generator/src/test/java/com/scottlogic/deg/generator/generation/string/generators/ChecksumlessIsinGeneratorTests.java new file mode 100644 index 000000000..2aad5eda8 --- /dev/null +++ b/generator/src/test/java/com/scottlogic/deg/generator/generation/string/generators/ChecksumlessIsinGeneratorTests.java @@ -0,0 +1,55 @@ +package com.scottlogic.deg.generator.generation.string.generators; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/* + * Copyright 2019 Scott Logic Ltd + * + * 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. + */ +class ChecksumlessIsinGeneratorTests { + @Test + void matches_withInvalidCountryCode_returnsFalse() { + String checksumlessIsin = "A000000KPAL"; + ChecksumlessIsinGenerator generator = new ChecksumlessIsinGenerator(); + + assertFalse(generator.matches(checksumlessIsin)); + } + + @Test + void matches_withInvalidLength_returnsFalse() { + String checksumlessIsin = "ADKPAL"; + ChecksumlessIsinGenerator generator = new ChecksumlessIsinGenerator(); + + assertFalse(generator.matches(checksumlessIsin)); + } + + @Test + void matches_withInvalidGbCode_returnsFalse() { + String checksumlessIsin = "GB11RJ6BYL2"; + ChecksumlessIsinGenerator generator = new ChecksumlessIsinGenerator(); + + assertFalse(generator.matches(checksumlessIsin)); + } + + @Test + void matches_withValidString_returnsTrue() { + String checksumlessIsin = "AD00000KPAL"; + ChecksumlessIsinGenerator generator = new ChecksumlessIsinGenerator(); + + assertTrue(generator.matches(checksumlessIsin)); + } +} diff --git a/generator/src/test/java/com/scottlogic/deg/generator/generation/string/generators/PrefixingStringGeneratorTests.java b/generator/src/test/java/com/scottlogic/deg/generator/generation/string/generators/PrefixingStringGeneratorTests.java new file mode 100644 index 000000000..d606330c0 --- /dev/null +++ b/generator/src/test/java/com/scottlogic/deg/generator/generation/string/generators/PrefixingStringGeneratorTests.java @@ -0,0 +1,55 @@ +/* + * Copyright 2019 Scott Logic Ltd + * + * 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.scottlogic.deg.generator.generation.string.generators; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class PrefixingStringGeneratorTests { + @Test + void matches_withInvalidPrefix_returnsFalse() { + String testPrefix = "BB"; + String testSuffix = "penguins"; + StringGenerator mockGenerator = mock(StringGenerator.class); + when(mockGenerator.matches(testSuffix)).thenReturn(true); + PrefixingStringGenerator prefixingStringGenerator = new PrefixingStringGenerator("AA", mockGenerator); + assertFalse(prefixingStringGenerator.matches(testPrefix + testSuffix)); + } + + @Test + void matches_withInvalidSuffix_returnsFalse() { + String testPrefix = "AA"; + String testSuffix = "penguins"; + StringGenerator mockGenerator = mock(StringGenerator.class); + when(mockGenerator.matches(testSuffix)).thenReturn(false); + PrefixingStringGenerator prefixingStringGenerator = new PrefixingStringGenerator("AA", mockGenerator); + assertFalse(prefixingStringGenerator.matches(testPrefix + testSuffix)); + } + + @Test + void matches_withValidString_returnsTrue() { + String testPrefix = "AA"; + String testSuffix = "penguins"; + StringGenerator mockGenerator = mock(StringGenerator.class); + when(mockGenerator.matches(testSuffix)).thenReturn(true); + PrefixingStringGenerator prefixingStringGenerator = new PrefixingStringGenerator("AA", mockGenerator); + assertTrue(prefixingStringGenerator.matches(testPrefix + testSuffix)); + } +} From 8b0ed53333ed9e785d2323681bc523b9f893236d Mon Sep 17 00:00:00 2001 From: Matthew Date: Thu, 22 Aug 2019 13:30:21 +0100 Subject: [PATCH 17/20] Catch all UnsupportedOperation exceptions and print only the message --- .../generator/generation/DecisionTreeDataGenerator.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/DecisionTreeDataGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/DecisionTreeDataGenerator.java index 048653664..6f8bd107e 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/DecisionTreeDataGenerator.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/DecisionTreeDataGenerator.java @@ -65,12 +65,11 @@ public Stream generateData(Profile profile) { monitor.generationStarting(); DecisionTree decisionTree = decisionTreeGenerator.analyse(profile); - decisionTree = upfrontTreePruner.runUpfrontPrune(decisionTree, monitor); - if (decisionTree.getRootNode() == null) { - return Stream.empty(); - } - try { + decisionTree = upfrontTreePruner.runUpfrontPrune(decisionTree, monitor); + if (decisionTree.getRootNode() == null) { + return Stream.empty(); + } Stream> partitionedDataBags = treePartitioner .splitTreeIntoPartitions(decisionTree) .map(treeOptimiser::optimiseTree) From c7484b2fba892a7fa79fe2b591ca4e80b522e328 Mon Sep 17 00:00:00 2001 From: Matthew Date: Wed, 28 Aug 2019 09:57:49 +0100 Subject: [PATCH 18/20] Change UnsupportedOperationExceptions to return a NoStringsStringGenerator --- .../generation/string/generators/ChecksumStringGenerator.java | 2 +- .../generation/string/generators/ChecksumlessIsinGenerator.java | 2 +- .../generation/string/generators/PrefixingStringGenerator.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/ChecksumStringGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/ChecksumStringGenerator.java index f96c09cdc..c0c032e17 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/ChecksumStringGenerator.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/ChecksumStringGenerator.java @@ -61,6 +61,6 @@ public boolean matches(String string) { @Override public StringGenerator intersect(StringGenerator stringGenerator) { - throw new UnsupportedOperationException("Checksum constraints can only be used with length and equalTo constraints."); + return new NoStringsStringGenerator("These constraints cannot be combined."); } } diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/ChecksumlessIsinGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/ChecksumlessIsinGenerator.java index 5e8244464..8e89f61fa 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/ChecksumlessIsinGenerator.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/ChecksumlessIsinGenerator.java @@ -65,6 +65,6 @@ public boolean matches(String string) { @Override public StringGenerator intersect(StringGenerator stringGenerator) { - throw new UnsupportedOperationException("Constraints with ISINs can only be used with length and equalTo constraints."); + return new NoStringsStringGenerator("Constraints with ISINs can only be used with length and equalTo constraints."); } } diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/PrefixingStringGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/PrefixingStringGenerator.java index 4064888b3..e2529b708 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/PrefixingStringGenerator.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/PrefixingStringGenerator.java @@ -61,6 +61,6 @@ public boolean matches(String string) { @Override public StringGenerator intersect(StringGenerator stringGenerator) { - throw new UnsupportedOperationException(); + return new NoStringsStringGenerator("The prefixing generator cannot be combined "); } } From ce72111e4fb9b8ac744e3ab2a745a3aa1493abd0 Mon Sep 17 00:00:00 2001 From: Matthew Date: Wed, 28 Aug 2019 10:19:58 +0100 Subject: [PATCH 19/20] Use ValidationExceptions instead of UnsupportedOperationExceptions or NoStringsStringGenerator. Removed try catch --- .../generation/DecisionTreeDataGenerator.java | 28 ++++++++----------- .../generators/ChecksumStringGenerator.java | 3 +- .../generators/ChecksumlessIsinGenerator.java | 3 +- .../generators/PrefixingStringGenerator.java | 3 +- .../MatchesStandardStringRestrictions.java | 3 +- 5 files changed, 19 insertions(+), 21 deletions(-) diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/DecisionTreeDataGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/DecisionTreeDataGenerator.java index 6f8bd107e..95c623928 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/DecisionTreeDataGenerator.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/DecisionTreeDataGenerator.java @@ -65,24 +65,18 @@ public Stream generateData(Profile profile) { monitor.generationStarting(); DecisionTree decisionTree = decisionTreeGenerator.analyse(profile); - try { - decisionTree = upfrontTreePruner.runUpfrontPrune(decisionTree, monitor); - if (decisionTree.getRootNode() == null) { - return Stream.empty(); - } - Stream> partitionedDataBags = treePartitioner - .splitTreeIntoPartitions(decisionTree) - .map(treeOptimiser::optimiseTree) - .map(treeWalker::walk); - - return partitionCombiner.permute(partitionedDataBags) - .map(d->(GeneratedObject)d) - .limit(maxRows) - .peek(monitor::rowEmitted); - } catch (UnsupportedOperationException ex) { - monitor.addLineToPrintAtEndOfGeneration(""); - monitor.addLineToPrintAtEndOfGeneration(ex.getMessage()); + decisionTree = upfrontTreePruner.runUpfrontPrune(decisionTree, monitor); + if (decisionTree.getRootNode() == null) { return Stream.empty(); } + Stream> partitionedDataBags = treePartitioner + .splitTreeIntoPartitions(decisionTree) + .map(treeOptimiser::optimiseTree) + .map(treeWalker::walk); + + return partitionCombiner.permute(partitionedDataBags) + .map(d->(GeneratedObject)d) + .limit(maxRows) + .peek(monitor::rowEmitted); } } diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/ChecksumStringGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/ChecksumStringGenerator.java index c0c032e17..5cefd09a6 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/ChecksumStringGenerator.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/ChecksumStringGenerator.java @@ -15,6 +15,7 @@ */ package com.scottlogic.deg.generator.generation.string.generators; +import com.scottlogic.deg.common.ValidationException; import com.scottlogic.deg.generator.utils.RandomNumberGenerator; import java.util.stream.Stream; @@ -61,6 +62,6 @@ public boolean matches(String string) { @Override public StringGenerator intersect(StringGenerator stringGenerator) { - return new NoStringsStringGenerator("These constraints cannot be combined."); + throw new ValidationException("These constraints cannot be combined."); } } diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/ChecksumlessIsinGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/ChecksumlessIsinGenerator.java index 8e89f61fa..59bc58142 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/ChecksumlessIsinGenerator.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/ChecksumlessIsinGenerator.java @@ -15,6 +15,7 @@ */ package com.scottlogic.deg.generator.generation.string.generators; +import com.scottlogic.deg.common.ValidationException; import com.scottlogic.deg.generator.utils.RandomNumberGenerator; import java.util.Arrays; @@ -65,6 +66,6 @@ public boolean matches(String string) { @Override public StringGenerator intersect(StringGenerator stringGenerator) { - return new NoStringsStringGenerator("Constraints with ISINs can only be used with length and equalTo constraints."); + throw new ValidationException("Constraints with ISINs can only be used with length and equalTo constraints."); } } diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/PrefixingStringGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/PrefixingStringGenerator.java index e2529b708..889b55ac5 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/PrefixingStringGenerator.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/PrefixingStringGenerator.java @@ -15,6 +15,7 @@ */ package com.scottlogic.deg.generator.generation.string.generators; +import com.scottlogic.deg.common.ValidationException; import com.scottlogic.deg.generator.utils.RandomNumberGenerator; import java.util.stream.Stream; @@ -61,6 +62,6 @@ public boolean matches(String string) { @Override public StringGenerator intersect(StringGenerator stringGenerator) { - return new NoStringsStringGenerator("The prefixing generator cannot be combined "); + throw new ValidationException("The prefixing generator cannot be combined "); } } diff --git a/generator/src/main/java/com/scottlogic/deg/generator/restrictions/MatchesStandardStringRestrictions.java b/generator/src/main/java/com/scottlogic/deg/generator/restrictions/MatchesStandardStringRestrictions.java index 8f2ec4114..47f3c0f57 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/restrictions/MatchesStandardStringRestrictions.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/restrictions/MatchesStandardStringRestrictions.java @@ -16,6 +16,7 @@ package com.scottlogic.deg.generator.restrictions; +import com.scottlogic.deg.common.ValidationException; import com.scottlogic.deg.common.profile.constraints.atomic.StandardConstraintTypes; import com.scottlogic.deg.generator.generation.string.generators.NoStringsStringGenerator; import com.scottlogic.deg.generator.generation.string.generators.RegexStringGenerator; @@ -76,7 +77,7 @@ public MergeResult intersect(StringRestrictions other) { private MergeResult isLengthAcceptable(TextualRestrictions other) { if (anyRegexes(other)){ - throw new UnsupportedOperationException("Combining a regex constraint with an " + this.toString() + " constraint is not supported."); + throw new ValidationException("Combining a regex constraint with an " + this.toString() + " constraint is not supported."); } StringGenerator intersect = other.createGenerator().intersect(new RegexStringGenerator(type.getRegex(), true)); From c01ef5a3a1dd7e34759004a582f2c1aaf4d2c1b8 Mon Sep 17 00:00:00 2001 From: Paul Daulby Date: Mon, 2 Sep 2019 10:59:12 +0100 Subject: [PATCH 20/20] fix(#1195): fix isin generation --- .../string/generators/ChecksumStringGenerator.java | 12 +++++++++--- .../MatchesStandardStringRestrictions.java | 2 +- .../generation/string/SedolStringGeneratorTests.java | 4 ++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/ChecksumStringGenerator.java b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/ChecksumStringGenerator.java index 5cefd09a6..0172bfbc4 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/ChecksumStringGenerator.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/generation/string/generators/ChecksumStringGenerator.java @@ -18,6 +18,7 @@ import com.scottlogic.deg.common.ValidationException; import com.scottlogic.deg.generator.utils.RandomNumberGenerator; +import java.util.function.Function; import java.util.stream.Stream; public class ChecksumStringGenerator implements StringGenerator { @@ -33,19 +34,24 @@ public ChecksumStringGenerator(StringGenerator checksumlessGenerator, ChecksumMa @Override public Stream generateAllValues() { return checksumlessGenerator.generateAllValues() - .map(string -> string + checksumMaker.makeChecksum(string)); + .map(addChecksum()); } + @Override public Stream generateRandomValues(RandomNumberGenerator randomNumberGenerator) { return checksumlessGenerator.generateRandomValues(randomNumberGenerator) - .map(string -> string + checksumMaker.makeChecksum(string)); + .map(addChecksum()); } @Override public Stream generateInterestingValues() { return checksumlessGenerator.generateInterestingValues() - .map(string -> string + checksumMaker.makeChecksum(string)); + .map(addChecksum()); + } + + private Function addChecksum() { + return string -> string + checksumMaker.makeChecksum(string); } @Override diff --git a/generator/src/main/java/com/scottlogic/deg/generator/restrictions/MatchesStandardStringRestrictions.java b/generator/src/main/java/com/scottlogic/deg/generator/restrictions/MatchesStandardStringRestrictions.java index 47f3c0f57..cdf8133d3 100644 --- a/generator/src/main/java/com/scottlogic/deg/generator/restrictions/MatchesStandardStringRestrictions.java +++ b/generator/src/main/java/com/scottlogic/deg/generator/restrictions/MatchesStandardStringRestrictions.java @@ -77,7 +77,7 @@ public MergeResult intersect(StringRestrictions other) { private MergeResult isLengthAcceptable(TextualRestrictions other) { if (anyRegexes(other)){ - throw new ValidationException("Combining a regex constraint with an " + this.toString() + " constraint is not supported."); + throw new ValidationException("Combining a regex constraint with a " + this.toString() + " constraint is not supported."); } StringGenerator intersect = other.createGenerator().intersect(new RegexStringGenerator(type.getRegex(), true)); diff --git a/generator/src/test/java/com/scottlogic/deg/generator/generation/string/SedolStringGeneratorTests.java b/generator/src/test/java/com/scottlogic/deg/generator/generation/string/SedolStringGeneratorTests.java index 083e0348a..f13eba1e0 100644 --- a/generator/src/test/java/com/scottlogic/deg/generator/generation/string/SedolStringGeneratorTests.java +++ b/generator/src/test/java/com/scottlogic/deg/generator/generation/string/SedolStringGeneratorTests.java @@ -38,7 +38,7 @@ public void shouldEndAllSedolsWithValidCheckDigit() { final Iterator allSedols = target.generateAllValues().iterator(); - for (int ii = 0; ii < NumberOfTests; ++ii) { + for (int i = 0; i < NumberOfTests; ++i) { final String nextSedol = allSedols.next(); final char checkDigit = FinancialCodeUtils.calculateSedolCheckDigit(nextSedol.substring(0, 6)); assertThat(nextSedol.charAt(6), equalTo(checkDigit)); @@ -53,7 +53,7 @@ public void shouldEndAllRandomCusipsWithValidCheckDigit() { final Iterator allSedols = target.generateRandomValues(new JavaUtilRandomNumberGenerator()).iterator(); - for (int ii = 0; ii < NumberOfTests; ++ii) { + for (int i = 0; i < NumberOfTests; ++i) { final String nextSedol = allSedols.next(); final char checkDigit = FinancialCodeUtils.calculateSedolCheckDigit(nextSedol.substring(0, 6)); assertThat(nextSedol.charAt(6), equalTo(checkDigit));