From 292ca7521e3f80722f260a8e5d6df734978af523 Mon Sep 17 00:00:00 2001 From: Max Thonagel <12283268+thoniTUB@users.noreply.github.com> Date: Tue, 31 Aug 2021 12:51:10 +0200 Subject: [PATCH 01/10] use ordered datastructure for Alignment to fallback to the correct one --- .../apiv1/forms/export_form/ExportForm.java | 2 +- .../models/forms/util/DateContext.java | 58 ++++++++++++++----- .../models/forms/DateContextTest.java | 32 +++++++++- 3 files changed, 74 insertions(+), 18 deletions(-) diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/ExportForm.java b/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/ExportForm.java index 1e862d4c5b..12cf0944a7 100644 --- a/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/ExportForm.java +++ b/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/ExportForm.java @@ -132,7 +132,7 @@ public static List getResolutionAlignmentMap( } private static DateContext.Alignment getFittingAlignment(DateContext.Alignment alignmentHint, DateContext.Resolution resolution) { - return resolution.getSupportedAlignments().contains(alignmentHint)? alignmentHint : resolution.getSupportedAlignments().iterator().next(); + return resolution.getSupportedAlignments().contains(alignmentHint)? alignmentHint : resolution.getSupportedAlignments().get(0); } /** diff --git a/backend/src/main/java/com/bakdata/conquery/models/forms/util/DateContext.java b/backend/src/main/java/com/bakdata/conquery/models/forms/util/DateContext.java index 2baf9b8eae..d7d81ec48b 100644 --- a/backend/src/main/java/com/bakdata/conquery/models/forms/util/DateContext.java +++ b/backend/src/main/java/com/bakdata/conquery/models/forms/util/DateContext.java @@ -159,8 +159,7 @@ public static enum Resolution implements Localized { * For returning contexts with a single {@link CDateRange} for the entire * {@link FeatureGroup}. */ - COMPLETE(null, Map.of( - Alignment.NO_ALIGN, 1)) { + COMPLETE(null) { @Override public String toString(Locale locale) { @@ -172,10 +171,8 @@ public String toString(Locale locale) { * The {@link CDateRange} contexts per {@link FeatureGroup} are subdivided into * years. */ - YEARS(COMPLETE, Map.of( - Alignment.YEAR, 1, - Alignment.QUARTER, 4, - Alignment.DAY, 365)) { + + YEARS(COMPLETE) { @Override public String toString(Locale locale) { @@ -187,9 +184,7 @@ public String toString(Locale locale) { * The {@link CDateRange} contexts per {@link FeatureGroup} are subdivided into * quarters. */ - QUARTERS(YEARS, Map.of( - Alignment.QUARTER, 1, - Alignment.DAY, 90)) { + QUARTERS(YEARS) { @Override public String toString(Locale locale) { @@ -201,8 +196,7 @@ public String toString(Locale locale) { * The {@link CDateRange} contexts per {@link FeatureGroup} are subdivided into * days. */ - DAYS(QUARTERS, Map.of( - Alignment.DAY, 1)) { + DAYS(QUARTERS) { @Override public String toString(Locale locale) { @@ -210,6 +204,22 @@ public String toString(Locale locale) { } }; + static { + // We need to define this in a static block so the runtime can solve this cyclic + // dependency between Resolution and alignment. Otherwise a NPE is thrown by the + // Collection + COMPLETE.compatibleAlignments = List.of(Alignment.NO_ALIGN); + YEARS.compatibleAlignments = List.of( + Alignment.YEAR, + Alignment.QUARTER, + Alignment.DAY); + QUARTERS.compatibleAlignments = List.of( + Alignment.QUARTER, + Alignment.DAY); + DAYS.compatibleAlignments = List.of(Alignment.DAY); + + } + @JsonIgnore private final Resolution coarser; @@ -219,7 +229,7 @@ public String toString(Locale locale) { * the amount of how many of such subdividions fill in this resolusion subdivision. */ @JsonIgnore - private final Map compatibleAlignmentsAndAmount; + private List compatibleAlignments; private List thisAndCoarserSubdivisions; @@ -227,8 +237,8 @@ public String toString(Locale locale) { public abstract String toString(Locale locale); @JsonIgnore - public Collection getSupportedAlignments(){ - return compatibleAlignmentsAndAmount.keySet(); + public List getSupportedAlignments(){ + return compatibleAlignments; } /** @@ -236,10 +246,10 @@ public Collection getSupportedAlignments(){ */ @JsonIgnore public OptionalInt getAmountForAlignment(Alignment alignment){ - if (!this.compatibleAlignmentsAndAmount.containsKey(alignment)) { + if (!this.compatibleAlignments.contains(alignment)) { return OptionalInt.empty(); } - return OptionalInt.of(this.compatibleAlignmentsAndAmount.get(alignment)); + return OptionalInt.of(alignment.getAmountPerResolution().get(this)); } @JsonIgnore @@ -270,8 +280,24 @@ public static enum Alignment { QUARTER(CDateRange::getCoveredQuarters), YEAR(CDateRange::getCoveredYears); + static { + NO_ALIGN.amountPerResolution = Map.of(Resolution.COMPLETE, 1); + DAY.amountPerResolution = Map.of( + Resolution.YEARS, 365, + Resolution.QUARTERS, 90, + Resolution.DAYS, 1); + QUARTER.amountPerResolution = Map.of( + Resolution.YEARS, 4, + Resolution.QUARTERS, 1); + YEAR.amountPerResolution = Map.of( + Resolution.YEARS, 1); + } + @Getter @JsonIgnore private final Function> subdivider; + + @Getter @JsonIgnore + private Map amountPerResolution; } @RequiredArgsConstructor diff --git a/backend/src/test/java/com/bakdata/conquery/models/forms/DateContextTest.java b/backend/src/test/java/com/bakdata/conquery/models/forms/DateContextTest.java index 78e55632e7..900138b083 100644 --- a/backend/src/test/java/com/bakdata/conquery/models/forms/DateContextTest.java +++ b/backend/src/test/java/com/bakdata/conquery/models/forms/DateContextTest.java @@ -277,7 +277,7 @@ public void rangeRelYearsAlignQuarterNeutralTest() { @Test public void rangeRelDaysAlignQuarterNeutralTest() { - // This should ignore the QUARTER alignment hint be cause it does not make sense to align a finer resolution than the alignment. + // This should ignore the QUARTER alignment hint because it does not make sense to align a finer resolution than the alignment. DateContext.CalendarUnit timeUnit = DateContext.CalendarUnit.DAYS; LocalDate eventDate = LocalDate.of(2001, 5, 23); @@ -296,4 +296,34 @@ public void rangeRelDaysAlignQuarterNeutralTest() { new DateContext(CDateRange.of(LocalDate.of(2001, 5, 25), LocalDate.of(2001, 5, 25)), FeatureGroup.OUTCOME, 2, eventDate, DAYS) ); } + + + @Test + public void rangeRelYearsQuarterAlignYearsNeutralTest() { + // This should ignore the YEAR alignment hint for QUARTERS because the alignment is to coarse. For QUARTERS it should fallback to QUARTER. + + DateContext.CalendarUnit timeUnit = DateContext.CalendarUnit.QUARTERS; + LocalDate eventDate = LocalDate.of(2001, 5, 23); + int event = CDate.ofLocalDate(eventDate); + int featureTime = 3; + int outcomeTime = 3; + IndexPlacement indexPlacement = IndexPlacement.NEUTRAL; + + + List contexts = DateContext.generateRelativeContexts(event, indexPlacement, featureTime, outcomeTime, timeUnit, ExportForm.getResolutionAlignmentMap(List.of(YEARS, QUARTERS), YEAR)); + + assertThat(contexts).containsExactly ( + new DateContext(CDateRange.of(LocalDate.of(2000, 7, 1), LocalDate.of(2000, 12, 31)), FeatureGroup.FEATURE, -2, eventDate, YEARS), + new DateContext(CDateRange.of(LocalDate.of(2001, 1, 1), LocalDate.of(2001, 3, 31)), FeatureGroup.FEATURE, -1, eventDate, YEARS), + new DateContext(CDateRange.of(LocalDate.of(2001, 7, 1), LocalDate.of(2001, 12, 31)), FeatureGroup.OUTCOME, 1, eventDate, YEARS), + new DateContext(CDateRange.of(LocalDate.of(2002, 1, 1), LocalDate.of(2002, 3, 31)), FeatureGroup.OUTCOME, 2, eventDate, YEARS), + + new DateContext(CDateRange.of(LocalDate.of(2000, 7, 1), LocalDate.of(2000, 9, 30)), FeatureGroup.FEATURE, -3, eventDate, QUARTERS), + new DateContext(CDateRange.of(LocalDate.of(2000, 10, 1), LocalDate.of(2000, 12, 31)), FeatureGroup.FEATURE, -2, eventDate, QUARTERS), + new DateContext(CDateRange.of(LocalDate.of(2001, 1, 1), LocalDate.of(2001, 3, 31)), FeatureGroup.FEATURE, -1, eventDate, QUARTERS), + new DateContext(CDateRange.of(LocalDate.of(2001, 7, 1), LocalDate.of(2001, 9, 30)), FeatureGroup.OUTCOME, 1, eventDate, QUARTERS), + new DateContext(CDateRange.of(LocalDate.of(2001, 10, 1), LocalDate.of(2001, 12, 31)), FeatureGroup.OUTCOME, 2, eventDate, QUARTERS), + new DateContext(CDateRange.of(LocalDate.of(2002, 1, 1), LocalDate.of(2002, 3, 31)), FeatureGroup.OUTCOME, 3, eventDate, QUARTERS) + ); + } } From c7c561c100122f2fad8473ab9dde2b181c80bae6 Mon Sep 17 00:00:00 2001 From: Max Thonagel <12283268+thoniTUB@users.noreply.github.com> Date: Tue, 31 Aug 2021 12:51:39 +0200 Subject: [PATCH 02/10] makes Resolution less leaky --- .../conquery/apiv1/forms/export_form/ExportForm.java | 7 +++++-- .../bakdata/conquery/models/error/ConqueryError.java | 4 +--- .../conquery/models/forms/util/DateContext.java | 11 +++++++++-- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/ExportForm.java b/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/ExportForm.java index 12cf0944a7..04b588d736 100644 --- a/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/ExportForm.java +++ b/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/ExportForm.java @@ -132,7 +132,10 @@ public static List getResolutionAlignmentMap( } private static DateContext.Alignment getFittingAlignment(DateContext.Alignment alignmentHint, DateContext.Resolution resolution) { - return resolution.getSupportedAlignments().contains(alignmentHint)? alignmentHint : resolution.getSupportedAlignments().get(0); + if(resolution.supportsAlignment(alignmentHint) ) { + return alignmentHint; + } + return resolution.getDefaultAlignment(); } /** @@ -146,7 +149,7 @@ public static class ResolutionAndAlignment { @JsonCreator public static ResolutionAndAlignment of(DateContext.Resolution resolution, DateContext.Alignment alignment){ - if (!resolution.getSupportedAlignments().contains(alignment)) { + if (!resolution.supportsAlignment(alignment)) { throw new ValidationException(String.format("The alignment %s is not supported by the resolution %s", alignment, resolution)); } diff --git a/backend/src/main/java/com/bakdata/conquery/models/error/ConqueryError.java b/backend/src/main/java/com/bakdata/conquery/models/error/ConqueryError.java index 5405a26dfb..ba21cde925 100644 --- a/backend/src/main/java/com/bakdata/conquery/models/error/ConqueryError.java +++ b/backend/src/main/java/com/bakdata/conquery/models/error/ConqueryError.java @@ -231,8 +231,7 @@ public static class ExecutionCreationPlanDateContextError extends ContextError { private final static String ALIGNMENT = "alignment"; private final static String RESOLUTION = "resolution"; - private final static String ALIGNMENT_SUPPORTED = "alignmentsSupported"; - private final static String TEMPLATE = "Alignment ${" + ALIGNMENT + "} and resolution ${" + RESOLUTION + "} don't fit together. The resolution only supports these alignments: ${" + ALIGNMENT_SUPPORTED + "}"; + private final static String TEMPLATE = "Alignment ${" + ALIGNMENT + "} and resolution ${" + RESOLUTION + "} don't fit together."; /** * Constructor for deserialization. @@ -246,7 +245,6 @@ public ExecutionCreationPlanDateContextError(DateContext.Alignment alignment, Da this(); getContext().put(ALIGNMENT, Objects.toString(alignment)); getContext().put(RESOLUTION, Objects.toString(resolution)); - getContext().put(ALIGNMENT_SUPPORTED, Objects.toString(resolution.getSupportedAlignments())); } } diff --git a/backend/src/main/java/com/bakdata/conquery/models/forms/util/DateContext.java b/backend/src/main/java/com/bakdata/conquery/models/forms/util/DateContext.java index d7d81ec48b..5fbded9219 100644 --- a/backend/src/main/java/com/bakdata/conquery/models/forms/util/DateContext.java +++ b/backend/src/main/java/com/bakdata/conquery/models/forms/util/DateContext.java @@ -209,6 +209,7 @@ public String toString(Locale locale) { // dependency between Resolution and alignment. Otherwise a NPE is thrown by the // Collection COMPLETE.compatibleAlignments = List.of(Alignment.NO_ALIGN); + // Beware that the first alignment is considered the default. YEARS.compatibleAlignments = List.of( Alignment.YEAR, Alignment.QUARTER, @@ -237,8 +238,14 @@ public String toString(Locale locale) { public abstract String toString(Locale locale); @JsonIgnore - public List getSupportedAlignments(){ - return compatibleAlignments; + public boolean supportsAlignment(Alignment alignment){ + return compatibleAlignments.contains(alignment); + } + + @JsonIgnore + public Alignment getDefaultAlignment(){ + // The first alignment is considered the default + return compatibleAlignments.get(0); } /** From 48fa60567ff37fa1083cd2f6fc2c9df827b9a4a9 Mon Sep 17 00:00:00 2001 From: Max Thonagel <12283268+thoniTUB@users.noreply.github.com> Date: Tue, 31 Aug 2021 15:56:10 +0200 Subject: [PATCH 03/10] refactor Resolution and Alignment class --- .../apiv1/forms/export_form/AbsoluteMode.java | 4 +- .../forms/export_form/EntityDateMode.java | 4 +- .../apiv1/forms/export_form/ExportForm.java | 23 +-- .../conquery/models/error/ConqueryError.java | 5 +- .../models/externalservice/ResultType.java | 8 +- .../forms/managed/RelativeFormQueryPlan.java | 7 +- .../conquery/models/forms/util/Alignment.java | 45 +++++ .../models/forms/util/DateContext.java | 166 ------------------ .../models/forms/util/Resolution.java | 140 +++++++++++++++ .../test/java/com/bakdata/conquery/Test.java | 26 +++ .../conquery/io/result/ResultTestUtil.java | 5 +- .../conquery/models/SerializationTests.java | 7 +- .../externalservice/ResultTypeTest.java | 10 +- .../models/forms/DateContextTest.java | 4 +- 14 files changed, 250 insertions(+), 204 deletions(-) create mode 100644 backend/src/main/java/com/bakdata/conquery/models/forms/util/Alignment.java create mode 100644 backend/src/main/java/com/bakdata/conquery/models/forms/util/Resolution.java create mode 100644 backend/src/test/java/com/bakdata/conquery/Test.java diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/AbsoluteMode.java b/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/AbsoluteMode.java index 83164d018e..d473d53344 100644 --- a/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/AbsoluteMode.java +++ b/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/AbsoluteMode.java @@ -15,7 +15,7 @@ import com.bakdata.conquery.models.common.Range; import com.bakdata.conquery.models.datasets.Dataset; import com.bakdata.conquery.models.forms.export.AbsExportGenerator; -import com.bakdata.conquery.models.forms.util.DateContext; +import com.bakdata.conquery.models.forms.util.Alignment; import com.bakdata.conquery.models.query.DateAggregationMode; import com.bakdata.conquery.models.query.QueryResolveContext; import com.bakdata.conquery.models.query.Visitable; @@ -39,7 +39,7 @@ public void visit(Consumer visitor) { } @NotNull - private DateContext.Alignment alignmentHint = DateContext.Alignment.QUARTER; + private Alignment alignmentHint = Alignment.QUARTER; @Override public Query createSpecializedQuery(DatasetRegistry datasets, User user, Dataset submittedDataset) { diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/EntityDateMode.java b/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/EntityDateMode.java index f834ff7d8f..dbd16112c5 100644 --- a/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/EntityDateMode.java +++ b/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/EntityDateMode.java @@ -19,7 +19,7 @@ import com.bakdata.conquery.models.common.daterange.CDateRange; import com.bakdata.conquery.models.datasets.Dataset; import com.bakdata.conquery.models.forms.managed.EntityDateQuery; -import com.bakdata.conquery.models.forms.util.DateContext; +import com.bakdata.conquery.models.forms.util.Alignment; import com.bakdata.conquery.models.query.DateAggregationMode; import com.bakdata.conquery.models.query.QueryResolveContext; import com.bakdata.conquery.models.query.Visitable; @@ -51,7 +51,7 @@ public void visit(Consumer visitor) { } @NotNull - private DateContext.Alignment alignmentHint = DateContext.Alignment.QUARTER; + private Alignment alignmentHint = Alignment.QUARTER; @Override public void resolve(QueryResolveContext context) { diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/ExportForm.java b/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/ExportForm.java index 04b588d736..486bb45379 100644 --- a/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/ExportForm.java +++ b/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/ExportForm.java @@ -25,7 +25,8 @@ import com.bakdata.conquery.models.execution.ManagedExecution; import com.bakdata.conquery.models.forms.managed.ManagedForm; import com.bakdata.conquery.models.forms.managed.ManagedInternalForm; -import com.bakdata.conquery.models.forms.util.DateContext; +import com.bakdata.conquery.models.forms.util.Alignment; +import com.bakdata.conquery.models.forms.util.Resolution; import com.bakdata.conquery.models.i18n.I18n; import com.bakdata.conquery.models.identifiable.ids.specific.ManagedExecutionId; import com.bakdata.conquery.models.query.ManagedQuery; @@ -56,14 +57,14 @@ public class ExportForm extends Form { private Mode timeMode; @NotNull @NotEmpty - private List resolution = List.of(DateContext.Resolution.COMPLETE); + private List resolution = List.of(Resolution.COMPLETE); private boolean alsoCreateCoarserSubdivisions = true; @JsonIgnore private Query prerequisite; @JsonIgnore - private List resolvedResolutions; + private List resolvedResolutions; @Override public void visit(Consumer visitor) { @@ -118,21 +119,21 @@ public String getLocalizedTypeLabel() { /** * Maps the given resolution to a fitting alignment. It tries to use the alignment which was given as a hint. * If the alignment does not fit to a resolution (resolution is finer than the alignment), the first alignment that - * this resolution supports is chosen (see the alignment order in {@link DateContext.Resolution}) + * this resolution supports is chosen (see the alignment order in {@link Resolution}) * @param resolutions The temporal resolutions for which sub queries should be generated per entity * @param alignmentHint The preferred calendar alignment on which the sub queries of each resolution should be aligned. * Note that this alignment is chosen when a resolution is equal or coarser. * @return The given resolutions mapped to a fitting calendar alignment. */ - public static List getResolutionAlignmentMap(List resolutions, DateContext.Alignment alignmentHint) { + public static List getResolutionAlignmentMap(List resolutions, Alignment alignmentHint) { return resolutions.stream() .map(r -> ResolutionAndAlignment.of(r, getFittingAlignment(alignmentHint, r))) .collect(Collectors.toList()); } - private static DateContext.Alignment getFittingAlignment(DateContext.Alignment alignmentHint, DateContext.Resolution resolution) { - if(resolution.supportsAlignment(alignmentHint) ) { + private static Alignment getFittingAlignment(Alignment alignmentHint, Resolution resolution) { + if(resolution.isAlignmentSupported(alignmentHint) ) { return alignmentHint; } return resolution.getDefaultAlignment(); @@ -144,12 +145,12 @@ private static DateContext.Alignment getFittingAlignment(DateContext.Alignment a @RequiredArgsConstructor(access = AccessLevel.PRIVATE) @Getter public static class ResolutionAndAlignment { - private final DateContext.Resolution resolution; - private final DateContext.Alignment alignment; + private final Resolution resolution; + private final Alignment alignment; @JsonCreator - public static ResolutionAndAlignment of(DateContext.Resolution resolution, DateContext.Alignment alignment){ - if (!resolution.supportsAlignment(alignment)) { + public static ResolutionAndAlignment of(Resolution resolution, Alignment alignment){ + if (!resolution.isAlignmentSupported(alignment)) { throw new ValidationException(String.format("The alignment %s is not supported by the resolution %s", alignment, resolution)); } diff --git a/backend/src/main/java/com/bakdata/conquery/models/error/ConqueryError.java b/backend/src/main/java/com/bakdata/conquery/models/error/ConqueryError.java index ba21cde925..2c91477e45 100644 --- a/backend/src/main/java/com/bakdata/conquery/models/error/ConqueryError.java +++ b/backend/src/main/java/com/bakdata/conquery/models/error/ConqueryError.java @@ -2,7 +2,8 @@ import com.bakdata.conquery.io.cps.CPSBase; import com.bakdata.conquery.io.cps.CPSType; -import com.bakdata.conquery.models.forms.util.DateContext; +import com.bakdata.conquery.models.forms.util.Alignment; +import com.bakdata.conquery.models.forms.util.Resolution; import com.bakdata.conquery.models.identifiable.ids.IId; import com.bakdata.conquery.models.query.entity.Entity; import com.bakdata.conquery.models.query.queryplan.QueryPlan; @@ -241,7 +242,7 @@ private ExecutionCreationPlanDateContextError() { super(TEMPLATE); } - public ExecutionCreationPlanDateContextError(DateContext.Alignment alignment, DateContext.Resolution resolution) { + public ExecutionCreationPlanDateContextError(Alignment alignment, Resolution resolution) { this(); getContext().put(ALIGNMENT, Objects.toString(alignment)); getContext().put(RESOLUTION, Objects.toString(resolution)); diff --git a/backend/src/main/java/com/bakdata/conquery/models/externalservice/ResultType.java b/backend/src/main/java/com/bakdata/conquery/models/externalservice/ResultType.java index c69fb0897f..a3c19b8933 100644 --- a/backend/src/main/java/com/bakdata/conquery/models/externalservice/ResultType.java +++ b/backend/src/main/java/com/bakdata/conquery/models/externalservice/ResultType.java @@ -5,7 +5,7 @@ import com.bakdata.conquery.io.cps.CPSBase; import com.bakdata.conquery.io.cps.CPSType; import com.bakdata.conquery.models.events.MajorTypeId; -import com.bakdata.conquery.models.forms.util.DateContext; +import com.bakdata.conquery.models.forms.util.Resolution; import com.bakdata.conquery.models.query.PrintSettings; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonTypeInfo; @@ -139,13 +139,13 @@ public static class ResolutionT extends PrimitiveResultType { @Override public String print(PrintSettings cfg, Object f) { - if (f instanceof DateContext.Resolution) { - return ((DateContext.Resolution) f).toString(cfg.getLocale()); + if (f instanceof Resolution) { + return ((Resolution) f).toString(cfg.getLocale()); } try { // If the object was parsed as a simple string, try to convert it to a // DateContextMode to get Internationalization - return DateContext.Resolution.valueOf(f.toString()).toString(cfg.getLocale()); + return Resolution.valueOf(f.toString()).toString(cfg.getLocale()); } catch (Exception e) { throw new IllegalArgumentException(f + " is not a valid resolution.", e); } diff --git a/backend/src/main/java/com/bakdata/conquery/models/forms/managed/RelativeFormQueryPlan.java b/backend/src/main/java/com/bakdata/conquery/models/forms/managed/RelativeFormQueryPlan.java index 5bd2901173..31129b7442 100644 --- a/backend/src/main/java/com/bakdata/conquery/models/forms/managed/RelativeFormQueryPlan.java +++ b/backend/src/main/java/com/bakdata/conquery/models/forms/managed/RelativeFormQueryPlan.java @@ -8,6 +8,7 @@ import com.bakdata.conquery.models.common.CDateSet; import com.bakdata.conquery.models.error.ConqueryError; import com.bakdata.conquery.models.forms.util.DateContext; +import com.bakdata.conquery.models.forms.util.Resolution; import com.bakdata.conquery.models.forms.util.ResultModifier; import com.bakdata.conquery.models.query.QueryExecutionContext; import com.bakdata.conquery.apiv1.query.concept.specific.temporal.TemporalSampler; @@ -197,13 +198,13 @@ private boolean hasCompleteDateContexts(List contexts) { if (featurePlan.getAggregatorSize() > 0 && outcomePlan.getAggregatorSize() > 0) { // We have features and outcomes check if both have complete date ranges (they should be at the beginning of the list) return contexts.size()>=2 - && contexts.get(0).getSubdivisionMode().equals(DateContext.Resolution.COMPLETE) - && contexts.get(1).getSubdivisionMode().equals(DateContext.Resolution.COMPLETE) + && contexts.get(0).getSubdivisionMode().equals(Resolution.COMPLETE) + && contexts.get(1).getSubdivisionMode().equals(Resolution.COMPLETE) && !contexts.get(0).getFeatureGroup().equals(contexts.get(1).getFeatureGroup()); } // Otherwise, if only features or outcomes are given check the first date context. The empty feature/outcome query // will still return an empty result which will be merged with to a complete result. - return contexts.get(0).getSubdivisionMode().equals(DateContext.Resolution.COMPLETE); + return contexts.get(0).getSubdivisionMode().equals(Resolution.COMPLETE); } private FormQueryPlan createSubQuery(ArrayConceptQueryPlan subPlan, List contexts, FeatureGroup featureGroup) { diff --git a/backend/src/main/java/com/bakdata/conquery/models/forms/util/Alignment.java b/backend/src/main/java/com/bakdata/conquery/models/forms/util/Alignment.java new file mode 100644 index 0000000000..eccb7cf1a8 --- /dev/null +++ b/backend/src/main/java/com/bakdata/conquery/models/forms/util/Alignment.java @@ -0,0 +1,45 @@ +package com.bakdata.conquery.models.forms.util; + +import com.bakdata.conquery.models.common.daterange.CDateRange; +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +import java.util.List; +import java.util.Map; +import java.util.function.Function; + +@RequiredArgsConstructor +/** + * Specifier for the alignment of {@link DateContext}s of a certain resolution. + * The alignment provides a method to sub divide a dateRangeMask into ranges aligned to the calendar equivalent. + * These sub divisions can then be merged to form the equally grain or coarser desired resolution for the + * {@link DateContext}s. + */ +public enum Alignment { + NO_ALIGN(List::of), // Special case for resolution == COMPLETE + DAY(CDateRange::getCoveredDays), + QUARTER(CDateRange::getCoveredQuarters), + YEAR(CDateRange::getCoveredYears); + + static { + NO_ALIGN.amountPerResolution = Map.of(Resolution.COMPLETE, 1); + DAY.amountPerResolution = Map.of( + Resolution.YEARS, 365, + Resolution.QUARTERS, 90, + Resolution.DAYS, 1); + QUARTER.amountPerResolution = Map.of( + Resolution.YEARS, 4, + Resolution.QUARTERS, 1); + YEAR.amountPerResolution = Map.of( + Resolution.YEARS, 1); + } + + @Getter + @JsonIgnore + private final Function> subdivider; + + @Getter + @JsonIgnore + private Map amountPerResolution; +} diff --git a/backend/src/main/java/com/bakdata/conquery/models/forms/util/DateContext.java b/backend/src/main/java/com/bakdata/conquery/models/forms/util/DateContext.java index 5fbded9219..e770ec3d02 100644 --- a/backend/src/main/java/com/bakdata/conquery/models/forms/util/DateContext.java +++ b/backend/src/main/java/com/bakdata/conquery/models/forms/util/DateContext.java @@ -7,17 +7,13 @@ import javax.annotation.Nullable; -import c10n.C10N; import com.bakdata.conquery.apiv1.forms.FeatureGroup; import com.bakdata.conquery.apiv1.forms.IndexPlacement; import com.bakdata.conquery.apiv1.forms.export_form.ExportForm; -import com.bakdata.conquery.internationalization.DateContextResolutionC10n; -import com.bakdata.conquery.internationalization.Localized; import com.bakdata.conquery.models.common.CDate; import com.bakdata.conquery.models.common.QuarterUtils; import com.bakdata.conquery.models.common.daterange.CDateRange; import com.bakdata.conquery.models.error.ConqueryError; -import com.fasterxml.jackson.annotation.JsonIgnore; import com.google.common.collect.Lists; import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; @@ -145,168 +141,6 @@ public CDateRange makeMergedRange(CDateRange lastDaterange, int prioInteressingB public abstract CDateRange makeMergedRange(CDateRange lastDaterange, int prioInteressingBorder); } - @RequiredArgsConstructor - /** - * Defines the granularity into which a given date range mask is chunked. - * The actual size in days depends on the chosen {@link Alignment}, e.g.: - * If the resolution is YEARS and it should be aligned on the actual YEAR, the resulting contexts days might vary - * depending on if that year was a leap year. - * If the alignment is DAY, then all context will have a length of 365 day, except the dateRangeMask intersects an - * edge context. - */ - public static enum Resolution implements Localized { - /** - * For returning contexts with a single {@link CDateRange} for the entire - * {@link FeatureGroup}. - */ - COMPLETE(null) { - @Override - public String toString(Locale locale) { - - return C10N.get(DateContextResolutionC10n.class, locale).complete(); - } - }, - - /** - * The {@link CDateRange} contexts per {@link FeatureGroup} are subdivided into - * years. - */ - - YEARS(COMPLETE) { - @Override - public String toString(Locale locale) { - - return C10N.get(DateContextResolutionC10n.class, locale).year(); - } - }, - - /** - * The {@link CDateRange} contexts per {@link FeatureGroup} are subdivided into - * quarters. - */ - QUARTERS(YEARS) { - @Override - public String toString(Locale locale) { - - return C10N.get(DateContextResolutionC10n.class, locale).quarter(); - } - }, - - /** - * The {@link CDateRange} contexts per {@link FeatureGroup} are subdivided into - * days. - */ - DAYS(QUARTERS) { - @Override - public String toString(Locale locale) { - - return C10N.get(DateContextResolutionC10n.class, locale).day(); - } - }; - - static { - // We need to define this in a static block so the runtime can solve this cyclic - // dependency between Resolution and alignment. Otherwise a NPE is thrown by the - // Collection - COMPLETE.compatibleAlignments = List.of(Alignment.NO_ALIGN); - // Beware that the first alignment is considered the default. - YEARS.compatibleAlignments = List.of( - Alignment.YEAR, - Alignment.QUARTER, - Alignment.DAY); - QUARTERS.compatibleAlignments = List.of( - Alignment.QUARTER, - Alignment.DAY); - DAYS.compatibleAlignments = List.of(Alignment.DAY); - - } - - - @JsonIgnore - private final Resolution coarser; - - /** - * Holds which calendar alignments are supported by this resolution and - * the amount of how many of such subdividions fill in this resolusion subdivision. - */ - @JsonIgnore - private List compatibleAlignments; - - - private List thisAndCoarserSubdivisions; - - public abstract String toString(Locale locale); - - @JsonIgnore - public boolean supportsAlignment(Alignment alignment){ - return compatibleAlignments.contains(alignment); - } - - @JsonIgnore - public Alignment getDefaultAlignment(){ - // The first alignment is considered the default - return compatibleAlignments.get(0); - } - - /** - * Returns the amount of calendar alignment sub date ranges that would fit in to this resolution. - */ - @JsonIgnore - public OptionalInt getAmountForAlignment(Alignment alignment){ - if (!this.compatibleAlignments.contains(alignment)) { - return OptionalInt.empty(); - } - return OptionalInt.of(alignment.getAmountPerResolution().get(this)); - } - - @JsonIgnore - public List getThisAndCoarserSubdivisions() { - if (thisAndCoarserSubdivisions != null) { - return thisAndCoarserSubdivisions; - } - List thisAndCoarser = new ArrayList<>(); - if (coarser != null) { - thisAndCoarser.addAll(coarser.getThisAndCoarserSubdivisions()); - } - thisAndCoarser.add(this); - return thisAndCoarserSubdivisions = Collections.unmodifiableList(thisAndCoarser); - - } - } - - @RequiredArgsConstructor - /** - * Specifier for the alignment of {@link DateContext}s of a certain resolution. - * The alignment provides a method to sub divide a dateRangeMask into ranges aligned to the calendar equivalent. - * These sub divisions can then be merged to form the equally grain or coarser desired resolution for the - * {@link DateContext}s. - */ - public static enum Alignment { - NO_ALIGN(List::of), // Special case for resolution == COMPLETE - DAY(CDateRange::getCoveredDays), - QUARTER(CDateRange::getCoveredQuarters), - YEAR(CDateRange::getCoveredYears); - - static { - NO_ALIGN.amountPerResolution = Map.of(Resolution.COMPLETE, 1); - DAY.amountPerResolution = Map.of( - Resolution.YEARS, 365, - Resolution.QUARTERS, 90, - Resolution.DAYS, 1); - QUARTER.amountPerResolution = Map.of( - Resolution.YEARS, 4, - Resolution.QUARTERS, 1); - YEAR.amountPerResolution = Map.of( - Resolution.YEARS, 1); - } - - @Getter @JsonIgnore - private final Function> subdivider; - - @Getter @JsonIgnore - private Map amountPerResolution; - } - @RequiredArgsConstructor public static enum CalendarUnit { DAYS(Alignment.DAY), diff --git a/backend/src/main/java/com/bakdata/conquery/models/forms/util/Resolution.java b/backend/src/main/java/com/bakdata/conquery/models/forms/util/Resolution.java new file mode 100644 index 0000000000..67eb3bf94b --- /dev/null +++ b/backend/src/main/java/com/bakdata/conquery/models/forms/util/Resolution.java @@ -0,0 +1,140 @@ +package com.bakdata.conquery.models.forms.util; + +import c10n.C10N; +import com.bakdata.conquery.apiv1.forms.FeatureGroup; +import com.bakdata.conquery.internationalization.DateContextResolutionC10n; +import com.bakdata.conquery.internationalization.Localized; +import com.bakdata.conquery.models.common.daterange.CDateRange; +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.RequiredArgsConstructor; + +import java.util.*; + +@RequiredArgsConstructor +/** + * Defines the granularity into which a given date range mask is chunked. + * The actual size in days depends on the chosen {@link Alignment}, e.g.: + * If the resolution is YEARS and it should be aligned on the actual YEAR, the resulting contexts days might vary + * depending on if that year was a leap year. + * If the alignment is DAY, then all context will have a length of 365 day, except the dateRangeMask intersects an + * edge context. + */ +public enum Resolution implements Localized { + /** + * For returning contexts with a single {@link CDateRange} for the entire + * {@link FeatureGroup}. + */ + COMPLETE(null) { + @Override + public String toString(Locale locale) { + + return C10N.get(DateContextResolutionC10n.class, locale).complete(); + } + }, + + /** + * The {@link CDateRange} contexts per {@link FeatureGroup} are subdivided into + * years. + */ + + YEARS(COMPLETE) { + @Override + public String toString(Locale locale) { + + return C10N.get(DateContextResolutionC10n.class, locale).year(); + } + }, + + /** + * The {@link CDateRange} contexts per {@link FeatureGroup} are subdivided into + * quarters. + */ + QUARTERS(YEARS) { + @Override + public String toString(Locale locale) { + + return C10N.get(DateContextResolutionC10n.class, locale).quarter(); + } + }, + + /** + * The {@link CDateRange} contexts per {@link FeatureGroup} are subdivided into + * days. + */ + DAYS(QUARTERS) { + @Override + public String toString(Locale locale) { + + return C10N.get(DateContextResolutionC10n.class, locale).day(); + } + }; + + static { + // We need to define this in a static block so the runtime can solve this cyclic + // dependency between Resolution and alignment. Otherwise a NPE is thrown by the + // Collection + COMPLETE.compatibleAlignments = List.of(Alignment.NO_ALIGN); + // Beware that the first alignment is considered the default. + YEARS.compatibleAlignments = List.of( + Alignment.YEAR, + Alignment.QUARTER, + Alignment.DAY); + QUARTERS.compatibleAlignments = List.of( + Alignment.QUARTER, + Alignment.DAY); + DAYS.compatibleAlignments = List.of(Alignment.DAY); + + } + + + @JsonIgnore + private final Resolution coarser; + + /** + * Holds which calendar alignments are supported by this resolution and + * the amount of how many of such subdividions fill in this resolusion subdivision. + */ + @JsonIgnore + private List compatibleAlignments; + + + private List thisAndCoarserSubdivisions; + + public abstract String toString(Locale locale); + + @JsonIgnore + public boolean isAlignmentSupported(Alignment alignment) { + return compatibleAlignments.contains(alignment); + } + + @JsonIgnore + public Alignment getDefaultAlignment() { + // The first alignment is considered the default + return compatibleAlignments.get(0); + } + + /** + * Returns the amount of calendar alignment sub date ranges that would fit in to this resolution. + */ + @JsonIgnore + public OptionalInt getAmountForAlignment(Alignment alignment) { + if (!isAlignmentSupported(alignment)) { + return OptionalInt.empty(); + } + return OptionalInt.of(alignment.getAmountPerResolution().get(this)); + } + + @JsonIgnore + public List getThisAndCoarserSubdivisions() { + if (thisAndCoarserSubdivisions != null) { + return thisAndCoarserSubdivisions; + } + List thisAndCoarser = new ArrayList<>(); + if (coarser != null) { + thisAndCoarser.addAll(coarser.getThisAndCoarserSubdivisions()); + } + thisAndCoarser.add(this); + return thisAndCoarserSubdivisions = Collections.unmodifiableList(thisAndCoarser); + + } +} diff --git a/backend/src/test/java/com/bakdata/conquery/Test.java b/backend/src/test/java/com/bakdata/conquery/Test.java new file mode 100644 index 0000000000..cc4e4ee652 --- /dev/null +++ b/backend/src/test/java/com/bakdata/conquery/Test.java @@ -0,0 +1,26 @@ +package com.bakdata.conquery; + +import lombok.RequiredArgsConstructor; +import java.util.List; + +public class Test { + + @org.junit.jupiter.api.Test + public void test() { + E1 e = E1.A; + } + + @RequiredArgsConstructor + public static enum E1{ + A(E2.a); + + private final E2 e; + } + + @RequiredArgsConstructor + public static enum E2 { + a(E1.A); + + private final E1 e; + } +} diff --git a/backend/src/test/java/com/bakdata/conquery/io/result/ResultTestUtil.java b/backend/src/test/java/com/bakdata/conquery/io/result/ResultTestUtil.java index 7d1c838fad..07c57935fc 100644 --- a/backend/src/test/java/com/bakdata/conquery/io/result/ResultTestUtil.java +++ b/backend/src/test/java/com/bakdata/conquery/io/result/ResultTestUtil.java @@ -3,7 +3,7 @@ import com.bakdata.conquery.models.datasets.concepts.select.Select; import com.bakdata.conquery.models.events.Bucket; import com.bakdata.conquery.models.externalservice.ResultType; -import com.bakdata.conquery.models.forms.util.DateContext; +import com.bakdata.conquery.models.forms.util.Resolution; import com.bakdata.conquery.models.query.queryplan.aggregators.Aggregator; import com.bakdata.conquery.models.query.queryplan.clone.CloneContext; import com.bakdata.conquery.models.query.results.EntityResult; @@ -12,7 +12,6 @@ import lombok.experimental.UtilityClass; import org.jetbrains.annotations.NotNull; -import java.time.LocalDate; import java.util.List; @UtilityClass @@ -40,7 +39,7 @@ public static List getResultTypes() { @NotNull public static List getTestEntityResults() { List results = List.of( - new SinglelineEntityResult(1, new Object[]{Boolean.TRUE, 2345634, 123423.34, "CAT1", DateContext.Resolution.DAYS.toString(), 5646, List.of(345, 534), "test_string", 4521, List.of(true, false), List.of(List.of(345, 534), List.of(1, 2)), List.of("fizz", "buzz")}), + new SinglelineEntityResult(1, new Object[]{Boolean.TRUE, 2345634, 123423.34, "CAT1", Resolution.DAYS.toString(), 5646, List.of(345, 534), "test_string", 4521, List.of(true, false), List.of(List.of(345, 534), List.of(1, 2)), List.of("fizz", "buzz")}), new SinglelineEntityResult(2, new Object[]{Boolean.FALSE, null, null, null, null, null, null, null, null, List.of(), List.of(List.of(1234, Integer.MAX_VALUE)), List.of()}), new SinglelineEntityResult(2, new Object[]{Boolean.TRUE, null, null, null, null, null, null, null, null, List.of(false, false), null, null}), new MultilineEntityResult(3, List.of( diff --git a/backend/src/test/java/com/bakdata/conquery/models/SerializationTests.java b/backend/src/test/java/com/bakdata/conquery/models/SerializationTests.java index 5b2a1b141c..b9e13df8ce 100644 --- a/backend/src/test/java/com/bakdata/conquery/models/SerializationTests.java +++ b/backend/src/test/java/com/bakdata/conquery/models/SerializationTests.java @@ -41,7 +41,8 @@ import com.bakdata.conquery.models.forms.configs.FormConfig; import com.bakdata.conquery.models.forms.frontendconfiguration.FormConfigProcessor; import com.bakdata.conquery.models.forms.managed.AbsoluteFormQuery; -import com.bakdata.conquery.models.forms.util.DateContext; +import com.bakdata.conquery.models.forms.util.Alignment; +import com.bakdata.conquery.models.forms.util.Resolution; import com.bakdata.conquery.models.identifiable.CentralRegistry; import com.bakdata.conquery.models.identifiable.IdMapSerialisationTest; import com.bakdata.conquery.models.identifiable.ids.specific.DatasetId; @@ -364,8 +365,8 @@ public void testFormQuery() throws IOException, JSONException { CDateRange.exactly(LocalDate.now()).toSimpleRange(), ArrayConceptQuery.createFromFeatures(Collections.singletonList(features)), List.of( - ExportForm.ResolutionAndAlignment.of(DateContext.Resolution.COMPLETE, DateContext.Alignment.NO_ALIGN), - ExportForm.ResolutionAndAlignment.of(DateContext.Resolution.QUARTERS, DateContext.Alignment.QUARTER) + ExportForm.ResolutionAndAlignment.of(Resolution.COMPLETE, Alignment.NO_ALIGN), + ExportForm.ResolutionAndAlignment.of(Resolution.QUARTERS, Alignment.QUARTER) ) ); diff --git a/backend/src/test/java/com/bakdata/conquery/models/externalservice/ResultTypeTest.java b/backend/src/test/java/com/bakdata/conquery/models/externalservice/ResultTypeTest.java index da645ca8f1..d883be8ade 100644 --- a/backend/src/test/java/com/bakdata/conquery/models/externalservice/ResultTypeTest.java +++ b/backend/src/test/java/com/bakdata/conquery/models/externalservice/ResultTypeTest.java @@ -5,16 +5,14 @@ import java.io.IOException; import java.math.BigDecimal; import java.time.LocalDate; -import java.time.format.DateTimeFormatter; import java.util.Currency; import java.util.List; import java.util.Locale; import java.util.Map; -import java.util.stream.Stream; -import com.bakdata.conquery.models.forms.util.DateContext; import com.bakdata.conquery.io.jackson.Jackson; import com.bakdata.conquery.models.config.ConqueryConfig; +import com.bakdata.conquery.models.forms.util.Resolution; import com.bakdata.conquery.models.i18n.I18n; import com.bakdata.conquery.models.query.PrintSettings; import com.google.common.collect.ImmutableMap; @@ -44,8 +42,8 @@ public static List testData() { Arguments.of(PRETTY, ResultType.BooleanT.INSTANCE, true, "Yes"), Arguments.of(PRETTY, ResultType.BooleanT.INSTANCE, false, "No"), Arguments.of(PRETTY, ResultType.CategoricalT.INSTANCE, "test", "test"), - Arguments.of(PRETTY, ResultType.ResolutionT.INSTANCE, DateContext.Resolution.COMPLETE.name(), "complete"), - Arguments.of(PRETTY_DE, ResultType.ResolutionT.INSTANCE, DateContext.Resolution.COMPLETE.name(), "Gesamt"), + Arguments.of(PRETTY, ResultType.ResolutionT.INSTANCE, Resolution.COMPLETE.name(), "complete"), + Arguments.of(PRETTY_DE, ResultType.ResolutionT.INSTANCE, Resolution.COMPLETE.name(), "Gesamt"), Arguments.of(PRETTY, ResultType.DateT.INSTANCE, LocalDate.of(2013, 7, 12).toEpochDay(), "2013-07-12"), Arguments.of(PRETTY_DE, ResultType.DateT.INSTANCE, LocalDate.of(2013, 7, 12).toEpochDay(), "12.07.2013"), Arguments.of(PRETTY, ResultType.DateRangeT.INSTANCE, List.of(Long.valueOf(LocalDate.of(2013, 7, 12).toEpochDay()).intValue(), Long.valueOf(LocalDate.of(2013, 7, 12).toEpochDay()).intValue()), "2013-07-12"), @@ -71,7 +69,7 @@ public static List testData() { Arguments.of(PLAIN, ResultType.NumericT.INSTANCE, 0.2, "0.2"), Arguments.of(PLAIN, ResultType.NumericT.INSTANCE, new BigDecimal("716283712389817246892743124.12312"), "716283712389817246892743124.12312"), Arguments.of(PLAIN, ResultType.StringT.INSTANCE, "test", "test"), - Arguments.of(PLAIN, ResultType.CategoricalT.INSTANCE, DateContext.Resolution.COMPLETE.name(), "COMPLETE"), + Arguments.of(PLAIN, ResultType.CategoricalT.INSTANCE, Resolution.COMPLETE.name(), "COMPLETE"), Arguments.of(PLAIN, ResultType.StringT.INSTANCE, ImmutableMap.of("a", 2, "c", 1), "{a=2, c=1}") ); } diff --git a/backend/src/test/java/com/bakdata/conquery/models/forms/DateContextTest.java b/backend/src/test/java/com/bakdata/conquery/models/forms/DateContextTest.java index 900138b083..00c3b1ed87 100644 --- a/backend/src/test/java/com/bakdata/conquery/models/forms/DateContextTest.java +++ b/backend/src/test/java/com/bakdata/conquery/models/forms/DateContextTest.java @@ -12,8 +12,8 @@ import java.util.Arrays; import java.util.List; -import static com.bakdata.conquery.models.forms.util.DateContext.Alignment.*; -import static com.bakdata.conquery.models.forms.util.DateContext.Resolution.*; +import static com.bakdata.conquery.models.forms.util.Alignment.*; +import static com.bakdata.conquery.models.forms.util.Resolution.*; import static org.assertj.core.api.Assertions.assertThat; public class DateContextTest { From f7fbf9cf57e4e8ba79f7f088105e62c2cd60f92e Mon Sep 17 00:00:00 2001 From: Max Thonagel <12283268+thoniTUB@users.noreply.github.com> Date: Tue, 31 Aug 2021 15:58:11 +0200 Subject: [PATCH 04/10] refactor CalendarUnit and AlignmentReference class --- .../apiv1/forms/export_form/RelativeMode.java | 4 +- .../forms/export/RelExportGenerator.java | 4 +- .../forms/managed/RelativeFormQuery.java | 4 +- .../forms/managed/RelativeFormQueryPlan.java | 3 +- .../models/forms/util/AlignmentReference.java | 52 ++++++++++++++++ .../models/forms/util/CalendarUnit.java | 14 +++++ .../models/forms/util/DateContext.java | 61 +------------------ .../models/forms/DateContextTest.java | 21 ++++--- 8 files changed, 88 insertions(+), 75 deletions(-) create mode 100644 backend/src/main/java/com/bakdata/conquery/models/forms/util/AlignmentReference.java create mode 100644 backend/src/main/java/com/bakdata/conquery/models/forms/util/CalendarUnit.java diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/RelativeMode.java b/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/RelativeMode.java index 8bf7d27921..8f16f6478b 100644 --- a/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/RelativeMode.java +++ b/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/RelativeMode.java @@ -14,7 +14,7 @@ import com.bakdata.conquery.models.datasets.Dataset; import com.bakdata.conquery.models.forms.export.RelExportGenerator; import com.bakdata.conquery.models.forms.managed.RelativeFormQuery; -import com.bakdata.conquery.models.forms.util.DateContext; +import com.bakdata.conquery.models.forms.util.CalendarUnit; import com.bakdata.conquery.models.query.DateAggregationMode; import com.bakdata.conquery.models.query.QueryResolveContext; import com.bakdata.conquery.models.query.Visitable; @@ -30,7 +30,7 @@ @CPSType(id="RELATIVE", base=Mode.class) public class RelativeMode extends Mode { @NotNull - private DateContext.CalendarUnit timeUnit; + private CalendarUnit timeUnit; @Min(0) private int timeCountBefore; @Min(0) diff --git a/backend/src/main/java/com/bakdata/conquery/models/forms/export/RelExportGenerator.java b/backend/src/main/java/com/bakdata/conquery/models/forms/export/RelExportGenerator.java index 217fd1f287..3312efe0ed 100644 --- a/backend/src/main/java/com/bakdata/conquery/models/forms/export/RelExportGenerator.java +++ b/backend/src/main/java/com/bakdata/conquery/models/forms/export/RelExportGenerator.java @@ -12,7 +12,7 @@ import com.bakdata.conquery.apiv1.query.concept.specific.ResultInfoDecorator; import com.bakdata.conquery.apiv1.query.concept.specific.temporal.TemporalSampler; import com.bakdata.conquery.models.forms.managed.RelativeFormQuery; -import com.bakdata.conquery.models.forms.util.DateContext; +import com.bakdata.conquery.models.forms.util.CalendarUnit; import com.google.common.collect.ImmutableClassToInstanceMap; import lombok.AllArgsConstructor; @@ -27,7 +27,7 @@ public static RelativeFormQuery generate(RelativeMode mode) { return generate(mode.getForm().getPrerequisite(), mode.getResolvedFeatures(), mode.getResolvedOutcomes(), mode.getIndexSelector(), mode.getIndexPlacement(), mode.getTimeCountBefore(), mode.getTimeCountAfter(), mode.getTimeUnit(), resolutionsAndAlignments); } - public static RelativeFormQuery generate(Query query, ArrayConceptQuery features, ArrayConceptQuery outcomes, TemporalSampler indexSelector, IndexPlacement indexPlacement, int timeCountBefore, int timeCountAfter, DateContext.CalendarUnit timeUnit, List resolutionsAndAlignments) { + public static RelativeFormQuery generate(Query query, ArrayConceptQuery features, ArrayConceptQuery outcomes, TemporalSampler indexSelector, IndexPlacement indexPlacement, int timeCountBefore, int timeCountAfter, CalendarUnit timeUnit, List resolutionsAndAlignments) { return new RelativeFormQuery( query, diff --git a/backend/src/main/java/com/bakdata/conquery/models/forms/managed/RelativeFormQuery.java b/backend/src/main/java/com/bakdata/conquery/models/forms/managed/RelativeFormQuery.java index 875345559b..54e65a5ae3 100644 --- a/backend/src/main/java/com/bakdata/conquery/models/forms/managed/RelativeFormQuery.java +++ b/backend/src/main/java/com/bakdata/conquery/models/forms/managed/RelativeFormQuery.java @@ -17,7 +17,7 @@ import com.bakdata.conquery.apiv1.query.concept.specific.temporal.TemporalSampler; import com.bakdata.conquery.io.cps.CPSType; import com.bakdata.conquery.models.execution.ManagedExecution; -import com.bakdata.conquery.models.forms.util.DateContext; +import com.bakdata.conquery.models.forms.util.CalendarUnit; import com.bakdata.conquery.models.query.DateAggregationMode; import com.bakdata.conquery.models.query.QueryPlanContext; import com.bakdata.conquery.models.query.QueryResolveContext; @@ -47,7 +47,7 @@ public class RelativeFormQuery extends Query { @Min(0) private final int timeCountAfter; @NotNull - private final DateContext.CalendarUnit timeUnit; + private final CalendarUnit timeUnit; @NotNull private final List resolutionsAndAlignmentMap; diff --git a/backend/src/main/java/com/bakdata/conquery/models/forms/managed/RelativeFormQueryPlan.java b/backend/src/main/java/com/bakdata/conquery/models/forms/managed/RelativeFormQueryPlan.java index 31129b7442..4fb6c70567 100644 --- a/backend/src/main/java/com/bakdata/conquery/models/forms/managed/RelativeFormQueryPlan.java +++ b/backend/src/main/java/com/bakdata/conquery/models/forms/managed/RelativeFormQueryPlan.java @@ -7,6 +7,7 @@ import com.bakdata.conquery.apiv1.forms.export_form.ExportForm; import com.bakdata.conquery.models.common.CDateSet; import com.bakdata.conquery.models.error.ConqueryError; +import com.bakdata.conquery.models.forms.util.CalendarUnit; import com.bakdata.conquery.models.forms.util.DateContext; import com.bakdata.conquery.models.forms.util.Resolution; import com.bakdata.conquery.models.forms.util.ResultModifier; @@ -42,7 +43,7 @@ public class RelativeFormQueryPlan implements QueryPlan { private final IndexPlacement indexPlacement; private final int timeCountBefore; private final int timeCountAfter; - private final DateContext.CalendarUnit timeUnit; + private final CalendarUnit timeUnit; private final List resolutionsAndAlignmentMap; private final transient List featureSubqueries = new ArrayList<>(); diff --git a/backend/src/main/java/com/bakdata/conquery/models/forms/util/AlignmentReference.java b/backend/src/main/java/com/bakdata/conquery/models/forms/util/AlignmentReference.java new file mode 100644 index 0000000000..0cb22624c6 --- /dev/null +++ b/backend/src/main/java/com/bakdata/conquery/models/forms/util/AlignmentReference.java @@ -0,0 +1,52 @@ +package com.bakdata.conquery.models.forms.util; + +import com.bakdata.conquery.models.common.daterange.CDateRange; +import com.google.common.collect.Lists; + +import java.util.List; + +/** + * Specifies whether the sub date ranges (which have the maximum length specified by the {@link Resolution}) + * are aligned with regard to beginning or the end of a date range mask. This affects the generated sub date ranges + * only if the {@link Alignment} is finer than the {@link Resolution}. + */ +public enum AlignmentReference { + START() { + @Override + public List getAlignedIterationDirection(List alignedSubDivisions) { + return alignedSubDivisions; + } + + @Override + public int getInterestingBorder(CDateRange daterange) { + return daterange.getMinValue(); + } + + @Override + public CDateRange makeMergedRange(CDateRange lastDaterange, int prioInteressingBorder) { + return CDateRange.of(prioInteressingBorder, lastDaterange.getMaxValue()); + } + }, + END() { + @Override + public List getAlignedIterationDirection(List alignedSubDivisions) { + return Lists.reverse(alignedSubDivisions); + } + + @Override + public int getInterestingBorder(CDateRange daterange) { + return daterange.getMaxValue(); + } + + @Override + public CDateRange makeMergedRange(CDateRange lastDaterange, int prioInteressingBorder) { + return CDateRange.of(lastDaterange.getMinValue(), prioInteressingBorder); + } + }; + + public abstract List getAlignedIterationDirection(List alignedSubDivisions); + + public abstract int getInterestingBorder(CDateRange daterange); + + public abstract CDateRange makeMergedRange(CDateRange lastDaterange, int prioInteressingBorder); +} diff --git a/backend/src/main/java/com/bakdata/conquery/models/forms/util/CalendarUnit.java b/backend/src/main/java/com/bakdata/conquery/models/forms/util/CalendarUnit.java new file mode 100644 index 0000000000..68f05af49c --- /dev/null +++ b/backend/src/main/java/com/bakdata/conquery/models/forms/util/CalendarUnit.java @@ -0,0 +1,14 @@ +package com.bakdata.conquery.models.forms.util; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public enum CalendarUnit { + DAYS(Alignment.DAY), + QUARTERS(Alignment.QUARTER), + YEARS(Alignment.YEAR); + + @Getter + private final Alignment alignment; +} diff --git a/backend/src/main/java/com/bakdata/conquery/models/forms/util/DateContext.java b/backend/src/main/java/com/bakdata/conquery/models/forms/util/DateContext.java index e770ec3d02..dd37ed0466 100644 --- a/backend/src/main/java/com/bakdata/conquery/models/forms/util/DateContext.java +++ b/backend/src/main/java/com/bakdata/conquery/models/forms/util/DateContext.java @@ -14,7 +14,6 @@ import com.bakdata.conquery.models.common.QuarterUtils; import com.bakdata.conquery.models.common.daterange.CDateRange; import com.bakdata.conquery.models.error.ConqueryError; -import com.google.common.collect.Lists; import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; import lombok.Getter; @@ -97,60 +96,6 @@ public static List generateAbsoluteContexts(CDateRange dateRangeMas return dcList; } - /** - * Specifies whether the sub date ranges (which have the maximum length specified by the {@link Resolution}) - * are aligned with regard to beginning or the end of a date range mask. This affects the generated sub date ranges - * only if the {@link Alignment} is finer than the {@link Resolution}. - */ - public static enum AlignmentReference { - START(){ - @Override - public List getAlignedIterationDirection(List alignedSubDivisions) { - return alignedSubDivisions; - } - - @Override - public int getInterestingBorder(CDateRange daterange) { - return daterange.getMinValue(); - } - - @Override - public CDateRange makeMergedRange(CDateRange lastDaterange, int prioInteressingBorder) { - return CDateRange.of(prioInteressingBorder, lastDaterange.getMaxValue()); - } - }, - END(){ - @Override - public List getAlignedIterationDirection(List alignedSubDivisions) { - return Lists.reverse(alignedSubDivisions); - } - - @Override - public int getInterestingBorder(CDateRange daterange) { - return daterange.getMaxValue(); - } - - @Override - public CDateRange makeMergedRange(CDateRange lastDaterange, int prioInteressingBorder) { - return CDateRange.of(lastDaterange.getMinValue(), prioInteressingBorder); - } - }; - - public abstract List getAlignedIterationDirection(List alignedSubDivisions); - public abstract int getInterestingBorder(CDateRange daterange); - public abstract CDateRange makeMergedRange(CDateRange lastDaterange, int prioInteressingBorder); - } - - @RequiredArgsConstructor - public static enum CalendarUnit { - DAYS(Alignment.DAY), - QUARTERS(Alignment.QUARTER), - YEARS(Alignment.YEAR); - - @Getter - private final Alignment alignment; - } - /** * Factory function that produces a list of {@link CDateRange}s from a given dateRangeMask according to the given * {@link AlignmentReference}, {@link Resolution} and {@link Alignment}. @@ -205,7 +150,7 @@ public static Function> getDateRangeSubdivider(Align * The event (a certain day) itself is expanded to a date range according to the desired alignment and the indexPlacement * determines to which group it belongs. */ - public static List generateRelativeContexts(int event, IndexPlacement indexPlacement, int featureTime, int outcomeTime, DateContext.CalendarUnit timeUnit, List resolutionAndAlignment) { + public static List generateRelativeContexts(int event, IndexPlacement indexPlacement, int featureTime, int outcomeTime, CalendarUnit timeUnit, List resolutionAndAlignment) { if (featureTime < 1 && outcomeTime < 1) { throw new IllegalArgumentException("Both relative times were smaller than 1 (featureTime: " + featureTime + "; outcomeTime: " + outcomeTime + ")"); @@ -276,7 +221,7 @@ public static List generateRelativeContexts(int event, IndexPlaceme * @param timeUnit The time unit. * @return The feature range. */ - private static CDateRange generateFeatureRange(int event, IndexPlacement indexPlacement, int featureTime, DateContext.CalendarUnit timeUnit) { + private static CDateRange generateFeatureRange(int event, IndexPlacement indexPlacement, int featureTime, CalendarUnit timeUnit) { if(featureTime <= 0){ return null; } @@ -318,7 +263,7 @@ private static CDateRange generateFeatureRange(int event, IndexPlacement indexPl * @param resolution The time unit. * @return The outcome range. */ - private static CDateRange generateOutcomeRange(int event, IndexPlacement indexPlacement, int outcomeTime, DateContext.CalendarUnit resolution) { + private static CDateRange generateOutcomeRange(int event, IndexPlacement indexPlacement, int outcomeTime, CalendarUnit resolution) { if (outcomeTime <= 0) { return null; } diff --git a/backend/src/test/java/com/bakdata/conquery/models/forms/DateContextTest.java b/backend/src/test/java/com/bakdata/conquery/models/forms/DateContextTest.java index 00c3b1ed87..f3d1a48a13 100644 --- a/backend/src/test/java/com/bakdata/conquery/models/forms/DateContextTest.java +++ b/backend/src/test/java/com/bakdata/conquery/models/forms/DateContextTest.java @@ -5,6 +5,7 @@ import com.bakdata.conquery.apiv1.forms.export_form.ExportForm; import com.bakdata.conquery.models.common.CDate; import com.bakdata.conquery.models.common.daterange.CDateRange; +import com.bakdata.conquery.models.forms.util.CalendarUnit; import com.bakdata.conquery.models.forms.util.DateContext; import org.junit.jupiter.api.Test; @@ -107,7 +108,7 @@ public void rangeAbsQuarterTestWithoutCoarse() { @Test public void rangeRelDaysBeforeTest() { - DateContext.CalendarUnit timeUnit = DateContext.CalendarUnit.DAYS; + CalendarUnit timeUnit = CalendarUnit.DAYS; LocalDate eventDate = LocalDate.of(2001, 5, 23); int event = CDate.ofLocalDate(eventDate); int featureTime = 2; @@ -128,7 +129,7 @@ public void rangeRelDaysBeforeTest() { @Test public void rangeRelDaysBeforeCompleteOnlyTest() { - DateContext.CalendarUnit timeUnit = DateContext.CalendarUnit.DAYS; + CalendarUnit timeUnit = CalendarUnit.DAYS; LocalDate eventDate = LocalDate.of(2001, 5, 23); int event = CDate.ofLocalDate(eventDate); int featureTime = 2; @@ -147,7 +148,7 @@ public void rangeRelDaysBeforeCompleteOnlyTest() { @Test public void rangeRelDaysAfterTest() { - DateContext.CalendarUnit timeUnit = DateContext.CalendarUnit.DAYS; + CalendarUnit timeUnit = CalendarUnit.DAYS; LocalDate eventDate = LocalDate.of(2001, 5, 23); int event = CDate.ofLocalDate(eventDate); int featureTime = 2; @@ -169,7 +170,7 @@ public void rangeRelDaysAfterTest() { @Test public void rangeRelDaysNeutralTest() { - DateContext.CalendarUnit timeUnit = DateContext.CalendarUnit.DAYS; + CalendarUnit timeUnit = CalendarUnit.DAYS; LocalDate eventDate = LocalDate.of(2001, 5, 23); int event = CDate.ofLocalDate(eventDate); int featureTime = 2; @@ -191,7 +192,7 @@ public void rangeRelDaysNeutralTest() { @Test public void rangeRelQuarterBeforeTest() { - DateContext.CalendarUnit timeUnit = DateContext.CalendarUnit.QUARTERS; + CalendarUnit timeUnit = CalendarUnit.QUARTERS; LocalDate eventDate = LocalDate.of(2001, 5, 23); int event = CDate.ofLocalDate(eventDate); int featureTime = 2; @@ -212,7 +213,7 @@ public void rangeRelQuarterBeforeTest() { @Test public void rangeRelQuarterAfterTest() { - DateContext.CalendarUnit timeUnit = DateContext.CalendarUnit.QUARTERS; + CalendarUnit timeUnit = CalendarUnit.QUARTERS; LocalDate eventDate = LocalDate.of(2001, 5, 23); int event = CDate.ofLocalDate(eventDate); int featureTime = 2; @@ -234,7 +235,7 @@ public void rangeRelQuarterAfterTest() { @Test public void rangeRelQuarterNeutralTest() { - DateContext.CalendarUnit timeUnit = DateContext.CalendarUnit.QUARTERS; + CalendarUnit timeUnit = CalendarUnit.QUARTERS; LocalDate eventDate = LocalDate.of(2001, 5, 23); int event = CDate.ofLocalDate(eventDate); int featureTime = 2; @@ -256,7 +257,7 @@ public void rangeRelQuarterNeutralTest() { @Test public void rangeRelYearsAlignQuarterNeutralTest() { - DateContext.CalendarUnit timeUnit = DateContext.CalendarUnit.QUARTERS; + CalendarUnit timeUnit = CalendarUnit.QUARTERS; LocalDate eventDate = LocalDate.of(2001, 5, 23); int event = CDate.ofLocalDate(eventDate); int featureTime = 2; @@ -279,7 +280,7 @@ public void rangeRelYearsAlignQuarterNeutralTest() { public void rangeRelDaysAlignQuarterNeutralTest() { // This should ignore the QUARTER alignment hint because it does not make sense to align a finer resolution than the alignment. - DateContext.CalendarUnit timeUnit = DateContext.CalendarUnit.DAYS; + CalendarUnit timeUnit = CalendarUnit.DAYS; LocalDate eventDate = LocalDate.of(2001, 5, 23); int event = CDate.ofLocalDate(eventDate); int featureTime = 2; @@ -302,7 +303,7 @@ public void rangeRelDaysAlignQuarterNeutralTest() { public void rangeRelYearsQuarterAlignYearsNeutralTest() { // This should ignore the YEAR alignment hint for QUARTERS because the alignment is to coarse. For QUARTERS it should fallback to QUARTER. - DateContext.CalendarUnit timeUnit = DateContext.CalendarUnit.QUARTERS; + CalendarUnit timeUnit = CalendarUnit.QUARTERS; LocalDate eventDate = LocalDate.of(2001, 5, 23); int event = CDate.ofLocalDate(eventDate); int featureTime = 3; From 304281499601cdb35e23839281ea90a2cfdd0989 Mon Sep 17 00:00:00 2001 From: Max Thonagel <12283268+thoniTUB@users.noreply.github.com> Date: Tue, 31 Aug 2021 15:59:49 +0200 Subject: [PATCH 05/10] removes warnings --- .../conquery/models/forms/util/DateContext.java | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/backend/src/main/java/com/bakdata/conquery/models/forms/util/DateContext.java b/backend/src/main/java/com/bakdata/conquery/models/forms/util/DateContext.java index dd37ed0466..6c12182941 100644 --- a/backend/src/main/java/com/bakdata/conquery/models/forms/util/DateContext.java +++ b/backend/src/main/java/com/bakdata/conquery/models/forms/util/DateContext.java @@ -29,16 +29,12 @@ public class DateContext { /** * The date range. - * - * @return The date range */ @Getter private final CDateRange dateRange; /** * Indicates to which group the context belongs. - * - * @return The groups. */ @Getter @Setter @@ -46,16 +42,12 @@ public class DateContext { /** * Indicates the relative position of the context to the event context. - * - * @return The index. */ @Getter private Integer index = null; /** * The date from which the relative context were generated. - * - * @return The event date */ @Getter @Setter private LocalDate eventDate = null; @@ -105,9 +97,7 @@ public static Function> getDateRangeSubdivider(Align if (alignedPerResolution == 1) { // When the alignment fits the resolution we can use the the alignment subdivision directly - return (dateRange) -> { - return alignment.getSubdivider().apply(dateRange); - }; + return (dateRange) -> alignment.getSubdivider().apply(dateRange); } return (dateRange) -> { From 33ba59a9032de32288cec1a4b37751c6eed1c940 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 31 Aug 2021 14:02:28 +0000 Subject: [PATCH 06/10] Update AutoDoc --- docs/REST API JSONs.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/REST API JSONs.md b/docs/REST API JSONs.md index bfd9d99f9c..896b55c6b6 100644 --- a/docs/REST API JSONs.md +++ b/docs/REST API JSONs.md @@ -299,7 +299,7 @@ No fields can be set for this type.

-### EXPORT_FORM [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/ExportForm.java#L44) +### EXPORT_FORM [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/ExportForm.java#L45)
Details

@@ -310,10 +310,10 @@ Supported Fields: | | Field | Type | Default | Example | Description | | --- | --- | --- | --- | --- | --- | -| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/ExportForm.java#L61) | alsoCreateCoarserSubdivisions | `boolean` | `true` | | | -| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/ExportForm.java#L48) | queryGroupId | ID of `ManagedExecution` | ␀ | | | -| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/ExportForm.java#L58) | resolution | list of one of COMPLETE, YEARS, QUARTERS, DAYS | `["COMPLETE"]` | | | -| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/ExportForm.java#L55) | timeMode | `@NotNull @Valid Mode` | `null` | | | +| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/ExportForm.java#L62) | alsoCreateCoarserSubdivisions | `boolean` | `true` | | | +| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/ExportForm.java#L49) | queryGroupId | ID of `ManagedExecution` | ␀ | | | +| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/ExportForm.java#L59) | resolution | list of one of COMPLETE, YEARS, QUARTERS, DAYS | `["COMPLETE"]` | | | +| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/ExportForm.java#L56) | timeMode | `@NotNull @Valid Mode` | `null` | | |

### FULL_EXPORT_FORM [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/FullExportForm.java#L44) From aff26e4bbdfaa797e393f8620442e081bfa4ef14 Mon Sep 17 00:00:00 2001 From: Max Thonagel <12283268+thoniTUB@users.noreply.github.com> Date: Tue, 31 Aug 2021 16:18:05 +0200 Subject: [PATCH 07/10] remmoves static initializer blocks --- .../conquery/models/forms/util/Alignment.java | 65 ++++++++++++------ .../models/forms/util/Resolution.java | 66 +++++++++++-------- 2 files changed, 82 insertions(+), 49 deletions(-) diff --git a/backend/src/main/java/com/bakdata/conquery/models/forms/util/Alignment.java b/backend/src/main/java/com/bakdata/conquery/models/forms/util/Alignment.java index eccb7cf1a8..ac7aa8a743 100644 --- a/backend/src/main/java/com/bakdata/conquery/models/forms/util/Alignment.java +++ b/backend/src/main/java/com/bakdata/conquery/models/forms/util/Alignment.java @@ -7,39 +7,64 @@ import java.util.List; import java.util.Map; +import java.util.OptionalInt; import java.util.function.Function; -@RequiredArgsConstructor /** * Specifier for the alignment of {@link DateContext}s of a certain resolution. * The alignment provides a method to sub divide a dateRangeMask into ranges aligned to the calendar equivalent. * These sub divisions can then be merged to form the equally grain or coarser desired resolution for the * {@link DateContext}s. */ +@RequiredArgsConstructor public enum Alignment { - NO_ALIGN(List::of), // Special case for resolution == COMPLETE - DAY(CDateRange::getCoveredDays), - QUARTER(CDateRange::getCoveredQuarters), - YEAR(CDateRange::getCoveredYears); - - static { - NO_ALIGN.amountPerResolution = Map.of(Resolution.COMPLETE, 1); - DAY.amountPerResolution = Map.of( - Resolution.YEARS, 365, - Resolution.QUARTERS, 90, - Resolution.DAYS, 1); - QUARTER.amountPerResolution = Map.of( - Resolution.YEARS, 4, - Resolution.QUARTERS, 1); - YEAR.amountPerResolution = Map.of( - Resolution.YEARS, 1); - } + NO_ALIGN(List::of){ + @Override + protected Map getAmountPerResolution() { + return Map.of(Resolution.COMPLETE, 1); + } + }, // Special case for resolution == COMPLETE + DAY(CDateRange::getCoveredDays) { + @Override + protected Map getAmountPerResolution() { + return Map.of( + Resolution.YEARS, 365, + Resolution.QUARTERS, 90, + Resolution.DAYS, 1); + } + }, + QUARTER(CDateRange::getCoveredQuarters) { + @Override + protected Map getAmountPerResolution() { + return Map.of( + Resolution.YEARS, 4, + Resolution.QUARTERS, 1); + } + }, + YEAR(CDateRange::getCoveredYears) { + @Override + protected Map getAmountPerResolution() { + return Map.of(Resolution.YEARS, 1); + } + }; @Getter @JsonIgnore private final Function> subdivider; - @Getter @JsonIgnore - private Map amountPerResolution; + protected abstract Map getAmountPerResolution(); + + /** + * Returns the amount of calendar alignment sub date ranges that would fit in to this resolution. + */ + @JsonIgnore + public OptionalInt getAmountForResolution(Resolution resolution) { + Integer amount = getAmountPerResolution().get(resolution); + if (amount == null) { + return OptionalInt.empty(); + } + return OptionalInt.of(amount); + } } + diff --git a/backend/src/main/java/com/bakdata/conquery/models/forms/util/Resolution.java b/backend/src/main/java/com/bakdata/conquery/models/forms/util/Resolution.java index 67eb3bf94b..8eac10178f 100644 --- a/backend/src/main/java/com/bakdata/conquery/models/forms/util/Resolution.java +++ b/backend/src/main/java/com/bakdata/conquery/models/forms/util/Resolution.java @@ -10,7 +10,6 @@ import java.util.*; -@RequiredArgsConstructor /** * Defines the granularity into which a given date range mask is chunked. * The actual size in days depends on the chosen {@link Alignment}, e.g.: @@ -19,6 +18,7 @@ * If the alignment is DAY, then all context will have a length of 365 day, except the dateRangeMask intersects an * edge context. */ +@RequiredArgsConstructor public enum Resolution implements Localized { /** * For returning contexts with a single {@link CDateRange} for the entire @@ -30,6 +30,11 @@ public String toString(Locale locale) { return C10N.get(DateContextResolutionC10n.class, locale).complete(); } + + @Override + protected List getCompatibleAlignments() { + return List.of(Alignment.NO_ALIGN); + } }, /** @@ -43,6 +48,14 @@ public String toString(Locale locale) { return C10N.get(DateContextResolutionC10n.class, locale).year(); } + + @Override + protected List getCompatibleAlignments() { + return List.of( + Alignment.YEAR, + Alignment.QUARTER, + Alignment.DAY); + } }, /** @@ -55,6 +68,13 @@ public String toString(Locale locale) { return C10N.get(DateContextResolutionC10n.class, locale).quarter(); } + + @Override + protected List getCompatibleAlignments() { + return List.of( + Alignment.QUARTER, + Alignment.DAY); + } }, /** @@ -67,50 +87,38 @@ public String toString(Locale locale) { return C10N.get(DateContextResolutionC10n.class, locale).day(); } - }; - - static { - // We need to define this in a static block so the runtime can solve this cyclic - // dependency between Resolution and alignment. Otherwise a NPE is thrown by the - // Collection - COMPLETE.compatibleAlignments = List.of(Alignment.NO_ALIGN); - // Beware that the first alignment is considered the default. - YEARS.compatibleAlignments = List.of( - Alignment.YEAR, - Alignment.QUARTER, - Alignment.DAY); - QUARTERS.compatibleAlignments = List.of( - Alignment.QUARTER, - Alignment.DAY); - DAYS.compatibleAlignments = List.of(Alignment.DAY); - } + @Override + protected List getCompatibleAlignments() { + return List.of(Alignment.DAY); + } + }; @JsonIgnore private final Resolution coarser; - /** - * Holds which calendar alignments are supported by this resolution and - * the amount of how many of such subdividions fill in this resolusion subdivision. - */ - @JsonIgnore - private List compatibleAlignments; - - private List thisAndCoarserSubdivisions; public abstract String toString(Locale locale); + /** + * Returns the alignments, that are compatible with this resolution. + * + * @implNote The first aligment of the returned list is considered the default (see getDefaultAlignment) + */ + @JsonIgnore + protected abstract List getCompatibleAlignments(); + @JsonIgnore public boolean isAlignmentSupported(Alignment alignment) { - return compatibleAlignments.contains(alignment); + return getCompatibleAlignments().contains(alignment); } @JsonIgnore public Alignment getDefaultAlignment() { // The first alignment is considered the default - return compatibleAlignments.get(0); + return getCompatibleAlignments().get(0); } /** @@ -121,7 +129,7 @@ public OptionalInt getAmountForAlignment(Alignment alignment) { if (!isAlignmentSupported(alignment)) { return OptionalInt.empty(); } - return OptionalInt.of(alignment.getAmountPerResolution().get(this)); + return alignment.getAmountForResolution(this); } @JsonIgnore From 47d600002479c7d6cac998079aa6bff8973bfd0b Mon Sep 17 00:00:00 2001 From: MT <12283268+thoniTUB@users.noreply.github.com> Date: Tue, 31 Aug 2021 16:21:48 +0200 Subject: [PATCH 08/10] Update backend/src/main/java/com/bakdata/conquery/models/error/ConqueryError.java Co-authored-by: awildturtok <1553491+awildturtok@users.noreply.github.com> --- .../java/com/bakdata/conquery/models/error/ConqueryError.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/com/bakdata/conquery/models/error/ConqueryError.java b/backend/src/main/java/com/bakdata/conquery/models/error/ConqueryError.java index 2c91477e45..c266cd63b0 100644 --- a/backend/src/main/java/com/bakdata/conquery/models/error/ConqueryError.java +++ b/backend/src/main/java/com/bakdata/conquery/models/error/ConqueryError.java @@ -232,7 +232,7 @@ public static class ExecutionCreationPlanDateContextError extends ContextError { private final static String ALIGNMENT = "alignment"; private final static String RESOLUTION = "resolution"; - private final static String TEMPLATE = "Alignment ${" + ALIGNMENT + "} and resolution ${" + RESOLUTION + "} don't fit together."; + private final static String TEMPLATE = "Alignment ${" + ALIGNMENT + "} and resolution ${" + RESOLUTION + "} are not compatible."; /** * Constructor for deserialization. From ed6fa31d271a5e5664379dd4b8d8505cd4bfb779 Mon Sep 17 00:00:00 2001 From: Max Thonagel <12283268+thoniTUB@users.noreply.github.com> Date: Tue, 31 Aug 2021 16:23:43 +0200 Subject: [PATCH 09/10] removes scratch test class --- .../test/java/com/bakdata/conquery/Test.java | 26 ------------------- 1 file changed, 26 deletions(-) delete mode 100644 backend/src/test/java/com/bakdata/conquery/Test.java diff --git a/backend/src/test/java/com/bakdata/conquery/Test.java b/backend/src/test/java/com/bakdata/conquery/Test.java deleted file mode 100644 index cc4e4ee652..0000000000 --- a/backend/src/test/java/com/bakdata/conquery/Test.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.bakdata.conquery; - -import lombok.RequiredArgsConstructor; -import java.util.List; - -public class Test { - - @org.junit.jupiter.api.Test - public void test() { - E1 e = E1.A; - } - - @RequiredArgsConstructor - public static enum E1{ - A(E2.a); - - private final E2 e; - } - - @RequiredArgsConstructor - public static enum E2 { - a(E1.A); - - private final E1 e; - } -} From 370932ffd91055d9b28c3a9ee9f89e989f549031 Mon Sep 17 00:00:00 2001 From: Max Thonagel <12283268+thoniTUB@users.noreply.github.com> Date: Tue, 31 Aug 2021 16:56:38 +0200 Subject: [PATCH 10/10] adds documentation for CalendarUnit --- .../com/bakdata/conquery/models/forms/util/Alignment.java | 8 ++++---- .../bakdata/conquery/models/forms/util/CalendarUnit.java | 5 +++++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/backend/src/main/java/com/bakdata/conquery/models/forms/util/Alignment.java b/backend/src/main/java/com/bakdata/conquery/models/forms/util/Alignment.java index ac7aa8a743..97ede3ad29 100644 --- a/backend/src/main/java/com/bakdata/conquery/models/forms/util/Alignment.java +++ b/backend/src/main/java/com/bakdata/conquery/models/forms/util/Alignment.java @@ -60,11 +60,11 @@ protected Map getAmountPerResolution() { */ @JsonIgnore public OptionalInt getAmountForResolution(Resolution resolution) { - Integer amount = getAmountPerResolution().get(resolution); - if (amount == null) { - return OptionalInt.empty(); + Map amountMap = getAmountPerResolution(); + if (amountMap.containsKey(resolution)) { + return OptionalInt.of(amountMap.get(resolution)); } - return OptionalInt.of(amount); + return OptionalInt.empty(); } } diff --git a/backend/src/main/java/com/bakdata/conquery/models/forms/util/CalendarUnit.java b/backend/src/main/java/com/bakdata/conquery/models/forms/util/CalendarUnit.java index 68f05af49c..dea1471b28 100644 --- a/backend/src/main/java/com/bakdata/conquery/models/forms/util/CalendarUnit.java +++ b/backend/src/main/java/com/bakdata/conquery/models/forms/util/CalendarUnit.java @@ -3,6 +3,11 @@ import lombok.Getter; import lombok.RequiredArgsConstructor; +/** + * Unit that corresponds to the amounts given in a {@link com.bakdata.conquery.apiv1.forms.export_form.RelativeMode}, to + * determine the concrete feature and outcome date ranges. These are then subdivided in smaller stratification intervals + * based on provided {@link Resolution}s and {@link Alignment}s (see {@link DateContext}). + */ @RequiredArgsConstructor public enum CalendarUnit { DAYS(Alignment.DAY),