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 1e862d4c5b..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,24 @@ 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) {
- return resolution.getSupportedAlignments().contains(alignmentHint)? alignmentHint : resolution.getSupportedAlignments().iterator().next();
+ private static Alignment getFittingAlignment(Alignment alignmentHint, Resolution resolution) {
+ if(resolution.isAlignmentSupported(alignmentHint) ) {
+ return alignmentHint;
+ }
+ return resolution.getDefaultAlignment();
}
/**
@@ -141,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.getSupportedAlignments().contains(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/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/error/ConqueryError.java b/backend/src/main/java/com/bakdata/conquery/models/error/ConqueryError.java
index 5405a26dfb..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
@@ -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;
@@ -231,8 +232,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 + "} are not compatible.";
/**
* Constructor for deserialization.
@@ -242,11 +242,10 @@ 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));
- getContext().put(ALIGNMENT_SUPPORTED, Objects.toString(resolution.getSupportedAlignments()));
}
}
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/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 5bd2901173..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,7 +7,9 @@
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;
import com.bakdata.conquery.models.query.QueryExecutionContext;
import com.bakdata.conquery.apiv1.query.concept.specific.temporal.TemporalSampler;
@@ -41,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<>();
@@ -197,13 +199,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..97ede3ad29
--- /dev/null
+++ b/backend/src/main/java/com/bakdata/conquery/models/forms/util/Alignment.java
@@ -0,0 +1,70 @@
+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.OptionalInt;
+import java.util.function.Function;
+
+/**
+ * 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){
+ @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;
+
+ @JsonIgnore
+ 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) {
+ Map amountMap = getAmountPerResolution();
+ if (amountMap.containsKey(resolution)) {
+ return OptionalInt.of(amountMap.get(resolution));
+ }
+ return OptionalInt.empty();
+ }
+}
+
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..dea1471b28
--- /dev/null
+++ b/backend/src/main/java/com/bakdata/conquery/models/forms/util/CalendarUnit.java
@@ -0,0 +1,19 @@
+package com.bakdata.conquery.models.forms.util;
+
+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),
+ 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 2baf9b8eae..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
@@ -7,18 +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;
import lombok.Getter;
@@ -34,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
@@ -51,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;
@@ -101,189 +88,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
- /**
- * 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, Map.of(
- Alignment.NO_ALIGN, 1)) {
- @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, Map.of(
- Alignment.YEAR, 1,
- Alignment.QUARTER, 4,
- Alignment.DAY, 365)) {
- @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, Map.of(
- Alignment.QUARTER, 1,
- Alignment.DAY, 90)) {
- @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, Map.of(
- Alignment.DAY, 1)) {
- @Override
- public String toString(Locale locale) {
-
- return C10N.get(DateContextResolutionC10n.class, locale).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 final Map compatibleAlignmentsAndAmount;
-
-
- private List thisAndCoarserSubdivisions;
-
- public abstract String toString(Locale locale);
-
- @JsonIgnore
- public Collection getSupportedAlignments(){
- return compatibleAlignmentsAndAmount.keySet();
- }
-
- /**
- * Returns the amount of calendar alignment sub date ranges that would fit in to this resolution.
- */
- @JsonIgnore
- public OptionalInt getAmountForAlignment(Alignment alignment){
- if (!this.compatibleAlignmentsAndAmount.containsKey(alignment)) {
- return OptionalInt.empty();
- }
- return OptionalInt.of(this.compatibleAlignmentsAndAmount.get(alignment));
- }
-
- @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);
-
- @Getter @JsonIgnore
- private final Function> subdivider;
- }
-
- @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}.
@@ -293,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) -> {
@@ -338,7 +140,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 + ")");
@@ -409,7 +211,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;
}
@@ -451,7 +253,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/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..8eac10178f
--- /dev/null
+++ b/backend/src/main/java/com/bakdata/conquery/models/forms/util/Resolution.java
@@ -0,0 +1,148 @@
+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.*;
+
+/**
+ * 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.
+ */
+@RequiredArgsConstructor
+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();
+ }
+
+ @Override
+ protected List getCompatibleAlignments() {
+ return List.of(Alignment.NO_ALIGN);
+ }
+ },
+
+ /**
+ * 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();
+ }
+
+ @Override
+ protected List getCompatibleAlignments() {
+ return List.of(
+ Alignment.YEAR,
+ Alignment.QUARTER,
+ Alignment.DAY);
+ }
+ },
+
+ /**
+ * 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();
+ }
+
+ @Override
+ protected List getCompatibleAlignments() {
+ return List.of(
+ Alignment.QUARTER,
+ Alignment.DAY);
+ }
+ },
+
+ /**
+ * 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();
+ }
+
+ @Override
+ protected List getCompatibleAlignments() {
+ return List.of(Alignment.DAY);
+ }
+ };
+
+
+ @JsonIgnore
+ private final Resolution coarser;
+
+ 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 getCompatibleAlignments().contains(alignment);
+ }
+
+ @JsonIgnore
+ public Alignment getDefaultAlignment() {
+ // The first alignment is considered the default
+ return getCompatibleAlignments().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 alignment.getAmountForResolution(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/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 78e55632e7..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;
@@ -12,8 +13,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 {
@@ -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;
@@ -277,9 +278,9 @@ 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;
+ CalendarUnit timeUnit = CalendarUnit.DAYS;
LocalDate eventDate = LocalDate.of(2001, 5, 23);
int event = CDate.ofLocalDate(eventDate);
int featureTime = 2;
@@ -296,4 +297,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.
+
+ CalendarUnit timeUnit = 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)
+ );
+ }
}
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)