diff --git a/core/src/main/java/com/scottlogic/datahelix/generator/core/fieldspecs/relations/EqualToOffsetRelation.java b/core/src/main/java/com/scottlogic/datahelix/generator/core/fieldspecs/relations/EqualToOffsetRelation.java index 87fcffd19..af6b9cdf6 100644 --- a/core/src/main/java/com/scottlogic/datahelix/generator/core/fieldspecs/relations/EqualToOffsetRelation.java +++ b/core/src/main/java/com/scottlogic/datahelix/generator/core/fieldspecs/relations/EqualToOffsetRelation.java @@ -19,14 +19,17 @@ import com.scottlogic.datahelix.generator.common.profile.Field; import com.scottlogic.datahelix.generator.common.profile.FieldType; import com.scottlogic.datahelix.generator.common.profile.Granularity; +import com.scottlogic.datahelix.generator.common.whitelist.WeightedElement; import com.scottlogic.datahelix.generator.core.fieldspecs.*; import com.scottlogic.datahelix.generator.common.whitelist.DistributedList; import com.scottlogic.datahelix.generator.core.generation.databags.DataBagValue; import com.scottlogic.datahelix.generator.core.profile.constraints.Constraint; import com.scottlogic.datahelix.generator.core.restrictions.linear.LinearRestrictions; -public class EqualToOffsetRelation> implements FieldSpecRelation -{ +import java.util.List; +import java.util.stream.Collectors; + +public class EqualToOffsetRelation> implements FieldSpecRelation { private final Field main; private final Field other; private final Granularity offsetGranularity; @@ -44,14 +47,21 @@ public EqualToOffsetRelation(Field main, @Override public FieldSpec createModifierFromOtherFieldSpec(FieldSpec otherFieldSpec) { - if (otherFieldSpec instanceof NullOnlyFieldSpec){ + if (otherFieldSpec instanceof NullOnlyFieldSpec) { return FieldSpecFactory.nullOnly(); } if (otherFieldSpec instanceof WhitelistFieldSpec) { - throw new UnsupportedOperationException("cannot combine sets with equal to offset relation, Issue #1489"); + WhitelistFieldSpec whitelistFieldSpec = (WhitelistFieldSpec) otherFieldSpec; + List> modified = whitelistFieldSpec + .getWhitelist() + .distributedList() + .stream() + .map(x -> new WeightedElement<>(offsetGranularity.getNext((T) x.element(), offset), x.weight())) + .collect(Collectors.toList()); + return FieldSpecFactory.fromList((DistributedList) new DistributedList<>(modified)); } - LinearRestrictions otherRestrictions = (LinearRestrictions)((RestrictionsFieldSpec) otherFieldSpec).getRestrictions(); + LinearRestrictions otherRestrictions = (LinearRestrictions) ((RestrictionsFieldSpec) otherFieldSpec).getRestrictions(); if (otherRestrictions.isContradictory()) { return FieldSpecFactory.nullOnly(); diff --git a/core/src/test/java/com/scottlogic/datahelix/generator/core/fieldspecs/relations/AfterDateRelationTest.java b/core/src/test/java/com/scottlogic/datahelix/generator/core/fieldspecs/relations/AfterRelationTest.java similarity index 99% rename from core/src/test/java/com/scottlogic/datahelix/generator/core/fieldspecs/relations/AfterDateRelationTest.java rename to core/src/test/java/com/scottlogic/datahelix/generator/core/fieldspecs/relations/AfterRelationTest.java index 5e6326749..5881278fe 100644 --- a/core/src/test/java/com/scottlogic/datahelix/generator/core/fieldspecs/relations/AfterDateRelationTest.java +++ b/core/src/test/java/com/scottlogic/datahelix/generator/core/fieldspecs/relations/AfterRelationTest.java @@ -31,7 +31,7 @@ import static com.scottlogic.datahelix.generator.common.util.Defaults.ISO_MAX_DATE; import static org.junit.jupiter.api.Assertions.assertEquals; -public class AfterDateRelationTest { +public class AfterRelationTest { private final Field a = new Field("a", StandardSpecificFieldType.DATETIME.toSpecificFieldType(), false, "", false, false, null); private final Field b = new Field("b", StandardSpecificFieldType.DATETIME.toSpecificFieldType(), false, "", false, false, null); diff --git a/core/src/test/java/com/scottlogic/datahelix/generator/core/fieldspecs/relations/BeforeDateRelationTest.java b/core/src/test/java/com/scottlogic/datahelix/generator/core/fieldspecs/relations/BeforeRelationTest.java similarity index 99% rename from core/src/test/java/com/scottlogic/datahelix/generator/core/fieldspecs/relations/BeforeDateRelationTest.java rename to core/src/test/java/com/scottlogic/datahelix/generator/core/fieldspecs/relations/BeforeRelationTest.java index d417140ef..f0c2f59a4 100644 --- a/core/src/test/java/com/scottlogic/datahelix/generator/core/fieldspecs/relations/BeforeDateRelationTest.java +++ b/core/src/test/java/com/scottlogic/datahelix/generator/core/fieldspecs/relations/BeforeRelationTest.java @@ -31,7 +31,7 @@ import static com.scottlogic.datahelix.generator.common.util.Defaults.ISO_MIN_DATE; import static org.junit.jupiter.api.Assertions.assertEquals; -public class BeforeDateRelationTest { +public class BeforeRelationTest { private final Field a = new Field("a", StandardSpecificFieldType.DATETIME.toSpecificFieldType(), false, "", false, false, null); private final Field b = new Field("b", StandardSpecificFieldType.DATETIME.toSpecificFieldType(), false, "", false, false, null); diff --git a/core/src/test/java/com/scottlogic/datahelix/generator/core/fieldspecs/relations/EqualToDateRelationTest.java b/core/src/test/java/com/scottlogic/datahelix/generator/core/fieldspecs/relations/EqualToRelationTest.java similarity index 98% rename from core/src/test/java/com/scottlogic/datahelix/generator/core/fieldspecs/relations/EqualToDateRelationTest.java rename to core/src/test/java/com/scottlogic/datahelix/generator/core/fieldspecs/relations/EqualToRelationTest.java index 92c5be8ce..4df07cb61 100644 --- a/core/src/test/java/com/scottlogic/datahelix/generator/core/fieldspecs/relations/EqualToDateRelationTest.java +++ b/core/src/test/java/com/scottlogic/datahelix/generator/core/fieldspecs/relations/EqualToRelationTest.java @@ -30,7 +30,7 @@ import static com.shazam.shazamcrest.MatcherAssert.assertThat; import static com.shazam.shazamcrest.matcher.Matchers.sameBeanAs; -class EqualToDateRelationTest { +class EqualToRelationTest { private final Field a = new Field("a", StandardSpecificFieldType.DATETIME.toSpecificFieldType(), false ,"", false, false, null); private final Field b = new Field("b", StandardSpecificFieldType.DATETIME.toSpecificFieldType(), false, "", false, false, null); diff --git a/core/src/test/java/com/scottlogic/datahelix/generator/core/fieldspecs/relations/FieldSpecRelationTest.java b/core/src/test/java/com/scottlogic/datahelix/generator/core/fieldspecs/relations/FieldSpecRelationTest.java index 6bf1320b0..e15496455 100644 --- a/core/src/test/java/com/scottlogic/datahelix/generator/core/fieldspecs/relations/FieldSpecRelationTest.java +++ b/core/src/test/java/com/scottlogic/datahelix/generator/core/fieldspecs/relations/FieldSpecRelationTest.java @@ -15,19 +15,23 @@ */ package com.scottlogic.datahelix.generator.core.fieldspecs.relations; -import com.scottlogic.datahelix.generator.common.profile.DateTimeGranularity; -import com.scottlogic.datahelix.generator.common.profile.Field; -import com.scottlogic.datahelix.generator.common.profile.SpecificFieldType; -import com.scottlogic.datahelix.generator.common.profile.StandardSpecificFieldType; +import com.scottlogic.datahelix.generator.common.profile.*; import com.scottlogic.datahelix.generator.common.util.defaults.DateTimeDefaults; +import com.scottlogic.datahelix.generator.common.whitelist.DistributedList; import com.scottlogic.datahelix.generator.core.fieldspecs.FieldSpec; import com.scottlogic.datahelix.generator.core.fieldspecs.FieldSpecFactory; import com.scottlogic.datahelix.generator.core.fieldspecs.RestrictionsFieldSpec; +import com.scottlogic.datahelix.generator.core.fieldspecs.WhitelistFieldSpec; import com.scottlogic.datahelix.generator.core.restrictions.linear.LinearRestrictions; +import com.scottlogic.datahelix.generator.core.restrictions.linear.LinearRestrictionsFactory; import org.junit.jupiter.api.Test; +import java.math.BigDecimal; import java.time.OffsetDateTime; import java.time.ZoneOffset; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; import static com.scottlogic.datahelix.generator.common.profile.FieldBuilder.createField; import static com.scottlogic.datahelix.generator.common.util.Defaults.ISO_MAX_DATE; @@ -38,13 +42,12 @@ import static java.time.temporal.ChronoUnit.YEARS; import static org.junit.Assert.assertEquals; -class FieldSpecRelationTest -{ +class FieldSpecRelationTest { private Field main = createField("main", StandardSpecificFieldType.DATETIME.toSpecificFieldType()); private Field other = createField("other", StandardSpecificFieldType.DATETIME.toSpecificFieldType()); @Test - public void equalTo_exactValue_returnsSame(){ + public void equalTo_exactValue_returnsSame() { FieldSpec fieldSpec = forYears(2018, 2018); EqualToRelation relation = new EqualToRelation(main, other); @@ -55,7 +58,7 @@ public void equalTo_exactValue_returnsSame(){ } @Test - public void equalTo_range_returnsSame(){ + public void equalTo_range_returnsSame() { FieldSpec fieldSpec = forYears(2018, 2020); EqualToRelation relation = new EqualToRelation(main, other); @@ -66,7 +69,7 @@ public void equalTo_range_returnsSame(){ } @Test - public void afterOrAt_exactValue_returnsBetween(){ + public void afterOrAt_exactValue_returnsBetween() { FieldSpec fieldSpec = forYears(2018, 2018); DateTimeGranularity offsetGranularity = DateTimeGranularity.create("MILLIS"); AfterRelation relation = new AfterRelation(main, other, true, DateTimeDefaults.get(), offsetGranularity, 0); @@ -78,7 +81,7 @@ public void afterOrAt_exactValue_returnsBetween(){ } @Test - public void afterOrAt_range_returnsFromMin(){ + public void afterOrAt_range_returnsFromMin() { FieldSpec fieldSpec = forYears(2018, 2020); DateTimeGranularity offsetGranularity = DateTimeGranularity.create("MILLIS"); AfterRelation relation = new AfterRelation(main, other, true, DateTimeDefaults.get(), offsetGranularity, 0); @@ -104,14 +107,14 @@ public void after_range_returnsFromMin() { OffsetDateTime expectedMin = OffsetDateTime.of(minYear, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC) .plusNanos(1000000); // Current smallest granularity is milliseconds. - OffsetDateTime expectedMax =DateTimeDefaults.get().max(); + OffsetDateTime expectedMax = DateTimeDefaults.get().max(); assertEquals(actualMin.compareTo(expectedMin), 0); assertEquals(actualMax.compareTo(expectedMax), 0); } @Test - public void beforeOrAt_exactValue_returnsBetween(){ + public void beforeOrAt_exactValue_returnsBetween() { FieldSpec fieldSpec = forYears(2018, 2018); DateTimeGranularity offsetGranularity = DateTimeGranularity.create("MILLIS"); BeforeRelation relation = new BeforeRelation(main, other, true, DateTimeDefaults.get(), offsetGranularity, 0); @@ -123,7 +126,7 @@ public void beforeOrAt_exactValue_returnsBetween(){ } @Test - public void beforeOrAt_range_returnsFromMin(){ + public void beforeOrAt_range_returnsFromMin() { FieldSpec fieldSpec = forYears(2018, 2020); DateTimeGranularity offsetGranularity = DateTimeGranularity.create("MILLIS"); BeforeRelation relation = new BeforeRelation(main, other, true, DateTimeDefaults.get(), offsetGranularity, 0); @@ -135,10 +138,10 @@ public void beforeOrAt_range_returnsFromMin(){ } @Test - public void before_range_returnsFromMin(){ + public void before_range_returnsFromMin() { int maxYear = 2020; DateTimeGranularity offsetGranularity = DateTimeGranularity.create("MILLIS"); - FieldSpec fieldSpec = forYears(maxYear-3, maxYear); + FieldSpec fieldSpec = forYears(maxYear - 3, maxYear); BeforeRelation relation = new BeforeRelation(main, other, false, DateTimeDefaults.get(), offsetGranularity, 0); RestrictionsFieldSpec actualFieldSpec = (RestrictionsFieldSpec) relation.createModifierFromOtherFieldSpec(fieldSpec); @@ -154,6 +157,30 @@ public void before_range_returnsFromMin(){ assertEquals(actualMax.compareTo(expectedMax), 0); } + @Test + public void equalTo_forSet_returns() { + DistributedList expectedValues = DistributedList.uniform( + Stream.of("2", "3", "4") + .map(BigDecimal::new) + .collect(Collectors.toSet())); + WhitelistFieldSpec expected = FieldSpecFactory.fromList(expectedValues); + + DistributedList secondValues = DistributedList.uniform( + Stream.of("1", "2", "3") + .map(BigDecimal::new) + .collect(Collectors.toSet())); + WhitelistFieldSpec second = FieldSpecFactory.fromList(secondValues); + + Field firstField = FieldBuilder.createField("first"); + Field secondField = FieldBuilder.createField("second"); + + FieldSpecRelation equalTo = new EqualToOffsetRelation<>(firstField, secondField, NumericGranularity.INTEGER_DEFAULT, 1); + + FieldSpec result = equalTo.createModifierFromOtherFieldSpec(second); + + assertEquals(expected, result); + } + private FieldSpec fromMin(int year) { OffsetDateTime min = OffsetDateTime.of(year, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC); LinearRestrictions restrictions = new LinearRestrictions(min, ISO_MAX_DATE, new DateTimeGranularity(MILLIS)); diff --git a/examples/integerOffsetFromSet/README.md b/examples/integerOffsetFromSet/README.md new file mode 100644 index 000000000..731926b84 --- /dev/null +++ b/examples/integerOffsetFromSet/README.md @@ -0,0 +1,3 @@ +Creates two integer fields, loaded from sets. + +The integers are linked by the condition that `Second` must be one greater than `First`. \ No newline at end of file diff --git a/examples/integerOffsetFromSet/profile.json b/examples/integerOffsetFromSet/profile.json new file mode 100644 index 000000000..44d881092 --- /dev/null +++ b/examples/integerOffsetFromSet/profile.json @@ -0,0 +1,24 @@ +{ + "fields" : [ { + "name" : "First", + "type" : "integer", + "unique" : false, + "nullable" : false + }, { + "name" : "Second", + "type" : "integer", + "unique" : false, + "nullable" : false + } ], + "constraints" : [ { + "field" : "First", + "inSet" : [1, 2, 3] + }, { + "field" : "Second", + "inSet" : [3, 4, 5] + }, { + "field" : "Second", + "equalToField" : "First", + "offset": 1 + }] +} \ No newline at end of file