From 324cc58708dc856c506a8b847781e9ed5551cf0b Mon Sep 17 00:00:00 2001
From: Fabian Kovacs <1553491+awildturtok@users.noreply.github.com>
Date: Tue, 6 Jul 2021 16:33:40 +0200
Subject: [PATCH 01/82] initial rework of IdMapping including CQExternal,
toward explicitly stated Ids instead of guessing the used Ids
Also refactors reading of IdMapping to use Headers and not indices, we don't need insane performance here anyway
---
.../conquery/apiv1/QueryProcessor.java | 2 +-
.../apiv1/query/QueryDescription.java | 2 +-
.../query/concept/specific/CQExternal.java | 195 ------------------
.../concept/specific/external/CQExternal.java | 194 +++++++++++++++++
.../concept/specific/external/DateColumn.java | 50 +++++
.../concept/specific/external/DateFormat.java | 78 +++++++
.../specific/external/DateSetColumn.java | 6 +
.../specific/external/FormatColumn.java | 18 ++
.../concept/specific/external/IdColumn.java | 13 ++
.../PersistentIdMapDeserializer.java | 18 +-
.../serializer/PersistentIdMapSerializer.java | 20 +-
.../conquery/io/result/ResultUtil.java | 30 +--
.../conquery/io/result/csv/CsvRenderer.java | 4 +-
.../conquery/io/storage/NamespaceStorage.java | 9 +-
.../conquery/io/storage/StoreInfo.java | 4 +-
.../conquery/models/config/NoIdMapping.java | 62 +-----
.../models/config/SimpleIdMapping.java | 41 ++--
.../conquery/models/config/StoreFactory.java | 4 +-
.../models/config/XodusStoreFactory.java | 6 +-
.../conquery/models/datasets/Table.java | 8 +
.../models/exceptions/ParsingException.java | 2 +-
.../exceptions/validators/ValidCSVFormat.java | 90 --------
.../identifiable/mapping/CsvEntityId.java | 2 +-
.../mapping/DefaultIdAccessorImpl.java | 18 --
.../mapping/DefaultIdMappingAccessor.java | 38 ----
.../models/identifiable/mapping/EntityId.java | 5 -
.../identifiable/mapping/EntityIdMap.java | 72 +++++++
...ternalEntityId.java => EntityPrintId.java} | 10 +-
.../identifiable/mapping/IdAccessor.java | 14 --
.../identifiable/mapping/IdAccessorImpl.java | 79 -------
.../models/identifiable/mapping/IdMapper.java | 27 ---
.../mapping/IdMappingAccessor.java | 67 ------
.../identifiable/mapping/IdMappingConfig.java | 75 +++----
.../identifiable/mapping/PersistentIdMap.java | 78 -------
.../identifiable/mapping/PrintIdMapper.java | 2 +-
...lEntityId.java => UnresolvedEntityId.java} | 4 +-
.../parser/specific/DateRangeParser.java | 4 +-
.../models/query/ExecutionManager.java | 10 +-
.../conquery/models/query/ManagedQuery.java | 2 +-
.../admin/rest/AdminDatasetProcessor.java | 61 ++----
.../admin/ui/DatasetsUIResource.java | 4 +-
.../com/bakdata/conquery/util/QueryUtils.java | 2 +-
.../api/StoredQueriesProcessorTest.java | 2 +-
.../integration/common/IntegrationUtils.java | 2 +
.../integration/common/LoadingUtil.java | 18 +-
.../integration/common/RequiredTable.java | 3 +
.../json/AbstractQueryEngineTest.java | 29 ++-
.../conquery/integration/json/FormTest.java | 2 +-
.../conquery/integration/json/QueryTest.java | 3 +-
.../integration/json/filter/FilterTest.java | 9 +-
.../tests/ConceptPermissionTest.java | 2 +-
.../integration/tests/RestartTest.java | 12 +-
.../integration/tests/ReusedQueryTest.java | 2 +-
.../ConceptUpdateAndDeletionTest.java | 2 +-
.../tests/deletion/DatasetDeletionTest.java | 6 +-
.../tests/deletion/ImportDeletionTest.java | 2 +-
.../tests/deletion/TableDeletionTest.java | 9 +-
.../io/result/CsvLineStreamRenderer.java | 6 +-
.../arrow/ArrowResultGenerationTest.java | 4 +-
.../result/csv/CsvResultGenerationTest.java | 4 +-
.../result/excel/ExcelResultRenderTest.java | 4 +-
.../conquery/models/SerializationTests.java | 4 +-
.../models/execution/DefaultLabelTest.java | 2 +-
.../identifiable/IdMapSerialisationTest.java | 22 +-
.../util/NonPersistentStoreFactory.java | 4 +-
docs/REST API JSONs.md | 2 +-
66 files changed, 663 insertions(+), 922 deletions(-)
delete mode 100644 backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/CQExternal.java
create mode 100644 backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java
create mode 100644 backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateColumn.java
create mode 100644 backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateFormat.java
create mode 100644 backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateSetColumn.java
create mode 100644 backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/FormatColumn.java
create mode 100644 backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/IdColumn.java
delete mode 100644 backend/src/main/java/com/bakdata/conquery/models/exceptions/validators/ValidCSVFormat.java
delete mode 100644 backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/DefaultIdAccessorImpl.java
delete mode 100644 backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/DefaultIdMappingAccessor.java
delete mode 100644 backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/EntityId.java
create mode 100644 backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/EntityIdMap.java
rename backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/{ExternalEntityId.java => EntityPrintId.java} (63%)
delete mode 100644 backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/IdAccessor.java
delete mode 100644 backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/IdAccessorImpl.java
delete mode 100644 backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/IdMapper.java
delete mode 100644 backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/IdMappingAccessor.java
delete mode 100644 backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/PersistentIdMap.java
rename backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/{SufficientExternalEntityId.java => UnresolvedEntityId.java} (69%)
diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/QueryProcessor.java b/backend/src/main/java/com/bakdata/conquery/apiv1/QueryProcessor.java
index c8665e2246..69d79fc520 100644
--- a/backend/src/main/java/com/bakdata/conquery/apiv1/QueryProcessor.java
+++ b/backend/src/main/java/com/bakdata/conquery/apiv1/QueryProcessor.java
@@ -2,7 +2,7 @@
import com.bakdata.conquery.apiv1.query.*;
import com.bakdata.conquery.apiv1.query.concept.specific.CQAnd;
-import com.bakdata.conquery.apiv1.query.concept.specific.CQExternal;
+import com.bakdata.conquery.apiv1.query.concept.specific.external.CQExternal;
import com.bakdata.conquery.io.result.ResultRender.ResultRendererProvider;
import com.bakdata.conquery.io.storage.MetaStorage;
import com.bakdata.conquery.metrics.ExecutionMetrics;
diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/query/QueryDescription.java b/backend/src/main/java/com/bakdata/conquery/apiv1/query/QueryDescription.java
index 965000dcbd..44a419493f 100644
--- a/backend/src/main/java/com/bakdata/conquery/apiv1/query/QueryDescription.java
+++ b/backend/src/main/java/com/bakdata/conquery/apiv1/query/QueryDescription.java
@@ -16,7 +16,7 @@
import com.bakdata.conquery.models.identifiable.ids.NamespacedIdentifiable;
import com.bakdata.conquery.models.query.QueryResolveContext;
import com.bakdata.conquery.models.query.Visitable;
-import com.bakdata.conquery.apiv1.query.concept.specific.CQExternal;
+import com.bakdata.conquery.apiv1.query.concept.specific.external.CQExternal;
import com.bakdata.conquery.models.query.visitor.QueryVisitor;
import com.bakdata.conquery.models.worker.DatasetRegistry;
import com.bakdata.conquery.util.QueryUtils;
diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/CQExternal.java b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/CQExternal.java
deleted file mode 100644
index feb8337408..0000000000
--- a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/CQExternal.java
+++ /dev/null
@@ -1,195 +0,0 @@
-package com.bakdata.conquery.apiv1.query.concept.specific;
-
-import java.time.LocalDate;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
-
-import javax.validation.constraints.NotEmpty;
-
-import com.bakdata.conquery.apiv1.query.CQElement;
-import com.bakdata.conquery.io.cps.CPSType;
-import com.bakdata.conquery.io.jackson.InternalOnly;
-import com.bakdata.conquery.models.common.CDateSet;
-import com.bakdata.conquery.models.common.daterange.CDateRange;
-import com.bakdata.conquery.models.dictionary.EncodedDictionary;
-import com.bakdata.conquery.models.error.ConqueryError;
-import com.bakdata.conquery.models.exceptions.ParsingException;
-import com.bakdata.conquery.models.exceptions.validators.ValidCSVFormat;
-import com.bakdata.conquery.models.identifiable.mapping.CsvEntityId;
-import com.bakdata.conquery.models.identifiable.mapping.IdAccessor;
-import com.bakdata.conquery.models.identifiable.mapping.IdAccessorImpl;
-import com.bakdata.conquery.models.identifiable.mapping.IdMappingConfig;
-import com.bakdata.conquery.models.preproc.parser.specific.DateRangeParser;
-import com.bakdata.conquery.models.query.QueryPlanContext;
-import com.bakdata.conquery.models.query.QueryResolveContext;
-import com.bakdata.conquery.models.query.queryplan.ConceptQueryPlan;
-import com.bakdata.conquery.models.query.queryplan.QPNode;
-import com.bakdata.conquery.models.query.queryplan.specific.ExternalNode;
-import com.bakdata.conquery.models.query.resultinfo.ResultInfoCollector;
-import com.bakdata.conquery.util.DateFormats;
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.google.common.collect.MoreCollectors;
-import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-
-@Slf4j
-@CPSType(id = "EXTERNAL", base = CQElement.class)
-@RequiredArgsConstructor(onConstructor_ = @JsonCreator)
-public class CQExternal extends CQElement {
-
- @Getter
- @NotEmpty
- @ValidCSVFormat
- private final List format;
- @Getter
- @NotEmpty
- private final String[][] values;
-
- @Getter @InternalOnly
- private Map valuesResolved;
-
- @Override
- public QPNode createQueryPlan(QueryPlanContext context, ConceptQueryPlan plan) {
- if (valuesResolved == null) {
- throw new IllegalStateException("CQExternal needs to be resolved before creating a plan");
- }
- return new ExternalNode(context.getStorage().getDataset().getAllIdsTable(), valuesResolved);
- }
-
-
- @Override
- public void resolve(QueryResolveContext context) {
- EncodedDictionary primary = context.getNamespace().getStorage().getPrimaryDictionary();
- Optional dateFormat = format.stream()
- .map(FormatColumn::getDateFormat)
- .filter(Objects::nonNull)
- .distinct()
- .collect(MoreCollectors.toOptional());
- int[] dateIndices = format.stream()
- .filter(fc -> fc.getDateFormat() != null)
- .mapToInt(format::indexOf)
- .toArray();
-
- valuesResolved = new Int2ObjectOpenHashMap<>();
-
- IdMappingConfig mapping = context.getConfig().getIdMapping();
-
- IdAccessor idAccessor = mapping.mappingFromCsvHeader(
- IdAccessorImpl.selectIdFields(values[0], format),
- context.getNamespace().getStorage().getIdMapping()
- );
- List> nonResolved = new ArrayList<>();
-
- if (values[0].length != format.size()) {
- throw new ConqueryError.ExternalResolveFormatError(format.size(), values[0].length);
- }
-
-
- // ignore the first row, because this is the header
- for (int i = 1; i < values.length; i++) {
- String[] row = values[i];
-
- //read the dates from the row
- try {
- CDateSet dates = dateFormat.map(df -> {
- try {
- return df.readDates(dateIndices, row, context.getConfig().getPreprocessor().getParsers().getDateFormats());
- }
- catch (Exception e) {
- throw new RuntimeException(e);
- }
- }).orElseGet(CDateSet::createFull);
- // remove all fields from the data line that are not id fields, in case the mapping is not possible we avoid the data columns to be joined
- CsvEntityId id = idAccessor.getCsvEntityId(IdAccessorImpl.selectIdFields(row, format));
-
- int resolvedId;
- if (id != null && (resolvedId = primary.getId(id.getCsvId())) != -1) {
- valuesResolved.put(resolvedId, dates);
- }
- else {
- nonResolved.add(Arrays.asList(row));
- }
- }
- catch (Exception e) {
- log.warn("Failed to parse id from " + Arrays.toString(row), e);
- }
- }
- if (!nonResolved.isEmpty()) {
- log.warn(
- "Could not resolve {} of the {} rows. Not resolved: {}",
- nonResolved.size(),
- values.length - 1,
- nonResolved.subList(0, Math.min(nonResolved.size(), 10))
- );
- }
-
- if (valuesResolved.isEmpty()) {
- throw new ConqueryError.ExternalResolveEmptyError();
- }
- }
-
- @Override
- public void collectResultInfos(ResultInfoCollector collector) {
- }
-
- public enum DateFormat {
- EVENT_DATE {
- @Override
- public CDateSet readDates(int[] dateIndices, String[] row, DateFormats dateFormats) throws ParsingException {
- return CDateSet.create(Collections.singleton(CDateRange.exactly(dateFormats.parseToLocalDate(row[dateIndices[0]]))));
- }
- },
- START_END_DATE {
- @Override
- public CDateSet readDates(int[] dateIndices, String[] row, DateFormats dateFormats) throws ParsingException {
- LocalDate start = row[dateIndices[0]] == null ? null : dateFormats.parseToLocalDate(row[dateIndices[0]]);
-
- LocalDate end = (dateIndices.length < 2 || row[dateIndices[1]] == null) ?
- null :
- dateFormats.parseToLocalDate(row[dateIndices[1]]);
-
- if (start == null && end == null) {
- return null;
- }
-
- return CDateSet.create(Collections.singleton(CDateRange.of(start, end)));
- }
- },
- DATE_RANGE {
- @Override
- public CDateSet readDates(int[] dateIndices, String[] row, DateFormats dateFormats) throws ParsingException {
- return CDateSet.create(Collections.singleton(DateRangeParser.parseISORange(row[dateIndices[0]], dateFormats)));
- }
- },
- DATE_SET {
- @Override
- public CDateSet readDates(int[] dateIndices, String[] row, DateFormats dateFormats) throws ParsingException {
- return CDateSet.parse(row[dateIndices[0]], dateFormats);
- }
- };
-
- public abstract CDateSet readDates(int[] dateIndices, String[] row, DateFormats dateFormats) throws ParsingException;
- }
-
- @RequiredArgsConstructor
- @Getter
- public enum FormatColumn {
- ID(true, null),
- EVENT_DATE(false, DateFormat.EVENT_DATE),
- START_DATE(false, DateFormat.START_END_DATE),
- END_DATE(false, DateFormat.START_END_DATE),
- DATE_RANGE(false, DateFormat.DATE_RANGE),
- DATE_SET(false, DateFormat.DATE_SET),
- IGNORE(true, null);
-
- private final boolean duplicatesAllowed;
- private final DateFormat dateFormat;
- }
-}
diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java
new file mode 100644
index 0000000000..094f6f026f
--- /dev/null
+++ b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java
@@ -0,0 +1,194 @@
+package com.bakdata.conquery.apiv1.query.concept.specific.external;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import javax.validation.constraints.NotEmpty;
+
+import com.bakdata.conquery.apiv1.query.CQElement;
+import com.bakdata.conquery.io.cps.CPSType;
+import com.bakdata.conquery.io.jackson.InternalOnly;
+import com.bakdata.conquery.models.common.CDateSet;
+import com.bakdata.conquery.models.dictionary.EncodedDictionary;
+import com.bakdata.conquery.models.error.ConqueryError;
+import com.bakdata.conquery.models.identifiable.mapping.CsvEntityId;
+import com.bakdata.conquery.models.identifiable.mapping.EntityIdMap;
+import com.bakdata.conquery.models.identifiable.mapping.UnresolvedEntityId;
+import com.bakdata.conquery.models.query.QueryPlanContext;
+import com.bakdata.conquery.models.query.QueryResolveContext;
+import com.bakdata.conquery.models.query.queryplan.ConceptQueryPlan;
+import com.bakdata.conquery.models.query.queryplan.QPNode;
+import com.bakdata.conquery.models.query.queryplan.specific.ExternalNode;
+import com.bakdata.conquery.models.query.resultinfo.ResultInfoCollector;
+import com.bakdata.conquery.util.DateFormats;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.google.common.collect.MoreCollectors;
+import io.dropwizard.validation.ValidationMethod;
+import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
+import lombok.Getter;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+@CPSType(id = "EXTERNAL", base = CQElement.class)
+public class CQExternal extends CQElement {
+
+ @Getter
+ @NotEmpty
+ private final List format;
+ @Getter
+ @NotEmpty
+ private final String[][] values;
+
+ @Getter
+ @InternalOnly
+ private Map valuesResolved;
+
+ public CQExternal(@NotEmpty List format, @NotEmpty String[][] values) {
+ this.format = format;
+ this.values = values;
+
+ for (int index = 0; index < format.size(); index++) {
+ format.get(index).setPosition(index);
+ }
+ }
+
+ @Override
+ public QPNode createQueryPlan(QueryPlanContext context, ConceptQueryPlan plan) {
+ if (valuesResolved == null) {
+ throw new IllegalStateException("CQExternal needs to be resolved before creating a plan");
+ }
+ return new ExternalNode(context.getStorage().getDataset().getAllIdsTable(), valuesResolved);
+ }
+
+
+ @Override
+ public void resolve(QueryResolveContext context) {
+
+ valuesResolved = new Int2ObjectOpenHashMap<>();
+
+
+ //TODO probably easy to simplify.
+
+ final DateColumn[] dateColumns = format.stream()
+ .filter(DateColumn.class::isInstance)
+ .map(DateColumn.class::cast)
+ .toArray(DateColumn[]::new);
+
+ //TODO verify dateColumns match
+
+ final DateFormat dateFormat = dateColumns.length > 0 ? dateColumns[0].getFormat() : DateFormat.ALL;
+
+
+ final IdColumn idColumn = this.format.stream()
+ .filter(IdColumn.class::isInstance)
+ .map(IdColumn.class::cast)
+ .collect(MoreCollectors.onlyElement());
+
+
+ final EncodedDictionary primary = context.getNamespace().getStorage().getPrimaryDictionary();
+ final EntityIdMap mapping = context.getNamespace().getStorage().getIdMapping();
+ final DateFormats dateFormats = context.getConfig().getPreprocessor().getParsers().getDateFormats();
+
+
+ List nonResolved = new ArrayList<>();
+
+
+ // ignore the first row, because this is the header
+ for (int i = 1; i < values.length; i++) {
+ final String[] row = values[i];
+ final UnresolvedEntityId externalId = idColumn.read(row);
+
+
+ //read the dates from the row
+ try {
+
+ CDateSet dates = dateFormat.readDates(dateColumns, row, dateFormats);
+
+ Optional id = mapping.toInternal(externalId);
+
+ int resolvedId;
+
+ if (id.isPresent() && (resolvedId = primary.getId(id.get().getCsvId())) != -1) {
+ valuesResolved.put(resolvedId, dates);
+ }
+ else {
+ nonResolved.add(row);
+ }
+ }
+ catch (Exception e) {
+ log.warn("Failed to parse id from {}", row, e);
+ }
+ }
+ if (!nonResolved.isEmpty()) {
+ log.warn(
+ "Could not resolve {} of the {} rows. Not resolved: {}",
+ nonResolved.size(),
+ values.length - 1,
+ nonResolved.subList(0, Math.min(nonResolved.size(), 10))
+ );
+ }
+
+ if (valuesResolved.isEmpty()) {
+ throw new ConqueryError.ExternalResolveEmptyError();
+ }
+ }
+
+ @Override
+ public void collectResultInfos(ResultInfoCollector collector) {
+ }
+
+ // @RequiredArgsConstructor
+ // @Getter
+ // public enum FormatColumn {
+ // ID(true, null),
+ // EVENT_DATE(false, DateFormat.EVENT_DATE),
+ // START_DATE(false, DateFormat.START_END_DATE),
+ // END_DATE(false, DateFormat.START_END_DATE),
+ // DATE_RANGE(false, DateFormat.DATE_RANGE),
+ // DATE_SET(false, DateFormat.DATE_SET),
+ // IGNORE(true, null);
+ //
+ // private final boolean duplicatesAllowed;
+ // private final DateFormat dateFormat;
+ // }
+
+
+ @JsonIgnore
+ @ValidationMethod(message = "Values and Format are not of same width.")
+ public boolean isAllSameLength() {
+ final int expected = format.size();
+ return Arrays.stream(values).mapToInt(a -> a.length).allMatch(v -> expected == v);
+ }
+
+ @JsonIgnore
+ @ValidationMethod(message = "Must use one Id.")
+ public boolean isOnlyOneId() {
+ return format.stream().filter(IdColumn.class::isInstance).count() == 1;
+ }
+
+ //TODO implement this
+
+ // @ValidationMethod(message = "Wrong usage of Dates.")
+ // public boolean isDatesAccessorExclusive() {
+ // if (format.contains(FormatColumn.DATE_RANGE)) {
+ // return !(format.contains(FormatColumn.DATE_SET) || format.contains(FormatColumn.START_DATE) || format.contains(FormatColumn.END_DATE));
+ // }
+ //
+ // if (format.contains(FormatColumn.DATE_SET)) {
+ // return !(format.contains(FormatColumn.START_DATE) || format.contains(FormatColumn.END_DATE));
+ // }
+ //
+ // if (format.stream().filter(FormatColumn.START_DATE::equals).count() > 1) {
+ // return false;
+ // }
+ //
+ // if (format.stream().filter(FormatColumn.END_DATE::equals).count() > 1) {
+ // return false;
+ // }
+ //
+ // return true;
+ // }
+}
diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateColumn.java b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateColumn.java
new file mode 100644
index 0000000000..ec752f10d0
--- /dev/null
+++ b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateColumn.java
@@ -0,0 +1,50 @@
+package com.bakdata.conquery.apiv1.query.concept.specific.external;
+
+import com.bakdata.conquery.io.cps.CPSType;
+import lombok.Getter;
+
+@Getter
+public abstract class DateColumn extends FormatColumn {
+
+ private final DateFormat format;
+
+ public DateColumn(DateFormat format) {
+ this.format = format;
+ }
+
+ @CPSType(id = "DATE_SET", base = FormatColumn.class)
+ public static class DateSet extends DateColumn {
+ public DateSet() {
+ super(DateFormat.DATE_SET);
+ }
+ }
+
+ @CPSType(id = "DATE_RANGE", base = FormatColumn.class)
+ public static class DateRange extends DateColumn {
+ public DateRange() {
+ super(DateFormat.DATE_RANGE);
+ }
+ }
+
+ @CPSType(id = "EVENT_DATE", base = FormatColumn.class)
+ public static class EventDate extends DateColumn {
+ public EventDate() {
+ super(DateFormat.EVENT_DATE);
+ }
+ }
+
+
+ @CPSType(id = "START_DATE", base = FormatColumn.class)
+ public static class DateStart extends DateColumn {
+ public DateStart() {
+ super(DateFormat.START_END_DATE);
+ }
+ }
+
+ @CPSType(id = "END_DATE", base = FormatColumn.class)
+ public static class DateEnd extends DateColumn {
+ public DateEnd() {
+ super(DateFormat.START_END_DATE);
+ }
+ }
+}
diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateFormat.java b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateFormat.java
new file mode 100644
index 0000000000..cd4c15dbe7
--- /dev/null
+++ b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateFormat.java
@@ -0,0 +1,78 @@
+package com.bakdata.conquery.apiv1.query.concept.specific.external;
+
+import java.time.LocalDate;
+import java.util.Arrays;
+import java.util.Collections;
+
+import com.bakdata.conquery.models.common.CDateSet;
+import com.bakdata.conquery.models.common.daterange.CDateRange;
+import com.bakdata.conquery.models.preproc.parser.specific.DateRangeParser;
+import com.bakdata.conquery.util.DateFormats;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.MoreCollectors;
+
+public enum DateFormat {
+ EVENT_DATE {
+ @Override
+ public CDateSet readDates(DateColumn[] dateIndices, String[] row, DateFormats dateFormats) {
+ Preconditions.checkArgument(dateIndices.length == 1);
+
+ return CDateSet.create(Collections.singleton(CDateRange.exactly(dateFormats.parseToLocalDate(row[dateIndices[0].getPosition()]))));
+ }
+ },
+ START_END_DATE {
+ @Override
+ public CDateSet readDates(DateColumn[] dateIndices, String[] row, DateFormats dateFormats) {
+ Preconditions.checkArgument(dateIndices.length == 1 || dateIndices.length == 2);
+
+
+ LocalDate start = Arrays.stream(dateIndices)
+ .filter(DateColumn.DateStart.class::isInstance)
+ .map(DateColumn::getPosition)
+ .map(idx -> row[idx])
+ .map(dateFormats::parseToLocalDate)
+ .collect(MoreCollectors.toOptional())
+ .orElse(null);
+
+ LocalDate end = Arrays.stream(dateIndices)
+ .filter(DateColumn.DateEnd.class::isInstance)
+ .map(DateColumn::getPosition)
+ .map(idx -> row[idx])
+ .map(dateFormats::parseToLocalDate)
+ .collect(MoreCollectors.toOptional())
+ .orElse(null);
+
+ if (start == null && end == null) {
+ return null;
+ }
+
+ return CDateSet.create(Collections.singleton(CDateRange.of(start, end)));
+ }
+ },
+ DATE_RANGE {
+ @Override
+ public CDateSet readDates(DateColumn[] dateIndices, String[] row, DateFormats dateFormats) {
+ Preconditions.checkArgument(dateIndices.length == 1);
+
+ return CDateSet.create(Collections.singleton(DateRangeParser.parseISORange(row[dateIndices[0].getPosition()], dateFormats)));
+ }
+ },
+ DATE_SET {
+ @Override
+ public CDateSet readDates(DateColumn[] dateIndices, String[] row, DateFormats dateFormats) {
+ Preconditions.checkArgument(dateIndices.length == 1);
+
+ return CDateSet.parse(row[dateIndices[0].getPosition()], dateFormats);
+ }
+ },
+ ALL {
+ @Override
+ public CDateSet readDates(DateColumn[] dateIndices, String[] row, DateFormats dateFormats) {
+ Preconditions.checkArgument(dateIndices.length == 0);
+
+ return CDateSet.createFull();
+ }
+ };
+
+ public abstract CDateSet readDates(DateColumn[] dateIndices, String[] row, DateFormats dateFormats);
+}
diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateSetColumn.java b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateSetColumn.java
new file mode 100644
index 0000000000..80efa72de5
--- /dev/null
+++ b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateSetColumn.java
@@ -0,0 +1,6 @@
+package com.bakdata.conquery.apiv1.query.concept.specific.external;
+
+import com.bakdata.conquery.apiv1.forms.Form;
+import com.bakdata.conquery.io.cps.CPSType;
+
+
diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/FormatColumn.java b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/FormatColumn.java
new file mode 100644
index 0000000000..62f304a28d
--- /dev/null
+++ b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/FormatColumn.java
@@ -0,0 +1,18 @@
+package com.bakdata.conquery.apiv1.query.concept.specific.external;
+
+import com.bakdata.conquery.io.cps.CPSBase;
+import com.bakdata.conquery.io.jackson.InternalOnly;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import lombok.Data;
+import lombok.Getter;
+import lombok.Setter;
+
+@CPSBase
+@JsonTypeInfo(use = JsonTypeInfo.Id.CUSTOM, property = "type")
+@Data
+public abstract class FormatColumn {
+
+ @InternalOnly @Setter @Getter
+ private int position;
+
+}
diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/IdColumn.java b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/IdColumn.java
new file mode 100644
index 0000000000..5531120f7e
--- /dev/null
+++ b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/IdColumn.java
@@ -0,0 +1,13 @@
+package com.bakdata.conquery.apiv1.query.concept.specific.external;
+
+import com.bakdata.conquery.io.cps.CPSType;
+import com.bakdata.conquery.models.identifiable.mapping.UnresolvedEntityId;
+
+@CPSType(id = "ID", base = FormatColumn.class)
+public class IdColumn extends FormatColumn {
+
+
+ public UnresolvedEntityId read(String[] row) {
+ return new UnresolvedEntityId(row[getPosition()]);
+ }
+}
diff --git a/backend/src/main/java/com/bakdata/conquery/io/jackson/serializer/PersistentIdMapDeserializer.java b/backend/src/main/java/com/bakdata/conquery/io/jackson/serializer/PersistentIdMapDeserializer.java
index 265fd27ddc..69cee6fe60 100644
--- a/backend/src/main/java/com/bakdata/conquery/io/jackson/serializer/PersistentIdMapDeserializer.java
+++ b/backend/src/main/java/com/bakdata/conquery/io/jackson/serializer/PersistentIdMapDeserializer.java
@@ -7,30 +7,30 @@
import java.util.Map;
import com.bakdata.conquery.models.identifiable.mapping.CsvEntityId;
-import com.bakdata.conquery.models.identifiable.mapping.ExternalEntityId;
-import com.bakdata.conquery.models.identifiable.mapping.PersistentIdMap;
-import com.bakdata.conquery.models.identifiable.mapping.SufficientExternalEntityId;
+import com.bakdata.conquery.models.identifiable.mapping.EntityPrintId;
+import com.bakdata.conquery.models.identifiable.mapping.EntityIdMap;
+import com.bakdata.conquery.models.identifiable.mapping.UnresolvedEntityId;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
-public class PersistentIdMapDeserializer extends JsonDeserializer {
+public class PersistentIdMapDeserializer extends JsonDeserializer {
private static final TypeReference arrayOfMapEntryType = new TypeReference>() {};
- private static final TypeReference mapOfCsvToExternalIdType = new TypeReference
-### EXTERNAL [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java#L34)
-
+### EXTERNAL [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java#L36-L38)
+Allows uploading lists of entities.
Details
@@ -755,7 +755,7 @@ Supported Fields:
| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/resources/api/ConceptResource.java#L68) | concepts | list of `String` | `null` | | |
-### Type CurrencyConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L20)
+### Type CurrencyConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L98)
Details
@@ -766,10 +766,10 @@ Supported Fields:
| | Field | Type | Default | Example | Description |
| --- | --- | --- | --- | --- | --- |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L26) | decimalScale | `int` | `2` | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L25) | decimalSeparator | `String` | `","` | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L23) | prefix | `String` | `"€"` | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L24) | thousandSeparator | `String` | `"."` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L103) | decimalScale | `int` | `2` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L102) | decimalSeparator | `String` | `","` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L100) | prefix | `String` | `"€"` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L101) | thousandSeparator | `String` | `"."` | | |
### Type ExecutionStatus [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/apiv1/ExecutionStatus.java#L18)
@@ -885,7 +885,7 @@ No fields can be set for this type.
-### Type FrontendConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L13)
+### Type FrontendConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L25)
Details
@@ -896,8 +896,9 @@ Supported Fields:
| | Field | Type | Default | Example | Description |
| --- | --- | --- | --- | --- | --- |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L17) | currency | [CurrencyConfig](#Type-CurrencyConfig) | | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L16) | version | `String` | `"0.0.0-SNAPSHOT"` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L32) | currency | [CurrencyConfig](#Type-CurrencyConfig) | | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L36) | queryUpload | `UploadConfig` | | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L31) | version | `String` | `"0.0.0-SNAPSHOT"` | | |
### Type FullExecutionStatus [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/apiv1/FullExecutionStatus.java#L20-L24)
From ac83e180d946825630af081c6e9557126ab2b535 Mon Sep 17 00:00:00 2001
From: Fabian Kovacs <1553491+awildturtok@users.noreply.github.com>
Date: Thu, 8 Jul 2021 12:10:17 +0200
Subject: [PATCH 07/82] Add Id kind as part of IdMapping resolve step, to
dissambiguate between keys
---
.../concept/specific/external/CQExternal.java | 39 ++++++------
.../concept/specific/external/IdColumn.java | 4 +-
.../identifiable/mapping/EntityIdMap.java | 59 +++++++++++++++----
.../identifiable/mapping/IdMappingConfig.java | 5 +-
.../admin/ui/DatasetsUIResource.java | 4 +-
5 files changed, 74 insertions(+), 37 deletions(-)
diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java
index b9c7bacd9c..0728d7df07 100644
--- a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java
+++ b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java
@@ -102,40 +102,43 @@ public void resolve(QueryResolveContext context) {
final DateFormats dateFormats = context.getConfig().getPreprocessor().getParsers().getDateFormats();
- List nonResolved = new ArrayList<>();
-
+ List unresolved = new ArrayList<>();
// ignore the first row, because this is the header
for (int i = 1; i < values.length; i++) {
final String[] row = values[i];
- final String externalId = idColumn.read(row);
+ final String[] externalId = idColumn.read(row);
- //read the dates from the row
- try {
+ final Optional id = mapping.toInternal(externalId);
- CDateSet dates = dateFormat.readDates(dateColumns, row, dateFormats);
+ if (id.isEmpty()){
+ continue;
+ }
- Optional id = mapping.toInternal(externalId);
+ final int resolvedId;
- int resolvedId;
+ if ((resolvedId = primary.getId(id.get())) == -1) {
+ unresolved.add(row);
+ continue;
+ }
+
+ //read the dates from the row
+ try {
+ CDateSet dates = dateFormat.readDates(dateColumns, row, dateFormats);
- if (id.isPresent() && (resolvedId = primary.getId(id.get())) != -1) {
- valuesResolved.put(resolvedId, dates);
- }
- else {
- nonResolved.add(row);
- }
+ valuesResolved.put(resolvedId, dates);
}
catch (Exception e) {
- log.warn("Failed to parse id from {}", row, e);
+ log.warn("Failed to parse Date from {}", row, e);
+ unresolved.add(row);
}
}
- if (!nonResolved.isEmpty()) {
+ if (!unresolved.isEmpty()) {
log.warn(
"Could not resolve {} of the {} rows. Not resolved: {}",
- nonResolved.size(),
+ unresolved.size(),
values.length - 1,
- nonResolved.subList(0, Math.min(nonResolved.size(), 10))
+ unresolved.subList(0, Math.min(unresolved.size(), 10))
);
}
diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/IdColumn.java b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/IdColumn.java
index 6572656e11..e90633ff69 100644
--- a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/IdColumn.java
+++ b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/IdColumn.java
@@ -5,7 +5,7 @@
@CPSType(id = "ID", base = FormatColumn.class)
public class IdColumn extends FormatColumn {
- public String read(String[] row) {
- return row[getPosition()];
+ public String[] read(String[] row) {
+ return new String[]{row[getPosition()]};
}
}
diff --git a/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/EntityIdMap.java b/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/EntityIdMap.java
index 6e6d2b48ba..71f5a8b5be 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/EntityIdMap.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/EntityIdMap.java
@@ -1,14 +1,16 @@
package com.bakdata.conquery.models.identifiable.mapping;
+import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
-import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
-import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonValue;
+import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Getter;
-import lombok.RequiredArgsConstructor;
+import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
/**
@@ -17,38 +19,64 @@
*/
@Getter
@EqualsAndHashCode
-@RequiredArgsConstructor
@Slf4j
+@NoArgsConstructor
public class EntityIdMap {
+
/**
* The map from csv entity ids to external entity ids.
*/
- private final Map csvIdToExternalIdMap = new HashMap<>();
+ private final Map internalToPrint = new HashMap<>();
/**
* The map from external entity ids to csv entity ids.
*/
- private final Map externalIdPartCsvIdMap = new HashMap<>();
+ private final Map external2Internal = new HashMap<>();
+
+
+ @Data
+ protected static class Container {
+ private final Collection> external2Internal;
+ private final Map internalToPrint;
+ }
+
+ @JsonCreator
+ protected EntityIdMap fromContainer(Container container) {
+ final EntityIdMap out = new EntityIdMap();
+
+ for (Map.Entry entry : container.getExternal2Internal()) {
+ out.getExternal2Internal().put(entry.getKey(), entry.getValue());
+ }
+
+ out.getInternalToPrint().putAll(container.getInternalToPrint());
+
+ return out;
+ }
+
+ @JsonValue
+ protected Container getContainer() {
+ return new Container(external2Internal.entrySet(), internalToPrint);
+ }
/**
* Map an internal id to an external.
*/
public EntityPrintId toExternal(String internal) {
- return csvIdToExternalIdMap.get(internal);
+ return internalToPrint.get(internal);
}
/**
- * Map an external to an internal id.
+ * Resolve an external to an internal id.
* @param external
*/
- public Optional toInternal(String external) {
- return Optional.ofNullable(externalIdPartCsvIdMap.get(external));
+ public Optional toInternal(String... external) {
+ return Optional.ofNullable(external2Internal.get(new ExternalId(external)));
}
public void addOutputMapping(String csvEntityId, EntityPrintId externalEntityId) {
- final EntityPrintId prior = csvIdToExternalIdMap.put(csvEntityId, externalEntityId);
+ final EntityPrintId prior = internalToPrint.put(csvEntityId, externalEntityId);
if (prior != null && prior.equals(externalEntityId)) {
log.warn("Duplicate mapping for {} to {} and {}", csvEntityId, externalEntityId, prior);
@@ -56,13 +84,18 @@ public void addOutputMapping(String csvEntityId, EntityPrintId externalEntityId)
}
- public void addInputMapping(String csvEntityId, String externalEntityId) {
+ public void addInputMapping(String csvEntityId, String... externalEntityId) {
- final String prior = externalIdPartCsvIdMap.put(externalEntityId, csvEntityId);
+ final String prior = external2Internal.put(new ExternalId(externalEntityId), csvEntityId);
if (prior != null && prior.equals(csvEntityId)) {
log.warn("Duplicate mapping for {} to {} and {}", externalEntityId, csvEntityId, prior);
}
}
+ @Data
+ private static class ExternalId {
+ private final String[] parts;
+ }
+
}
diff --git a/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/IdMappingConfig.java b/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/IdMappingConfig.java
index 20567851f1..d0985f7ee7 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/IdMappingConfig.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/IdMappingConfig.java
@@ -24,8 +24,6 @@ public EntityIdMap generateIdMapping(CsvParser parser) throws IllegalArgumentExc
EntityIdMap mapping = new EntityIdMap();
- //TODO Check headers match parser.getContext().headers();
-
Record record;
while((record = parser.parseNextRecord()) != null){
@@ -37,6 +35,9 @@ public EntityIdMap generateIdMapping(CsvParser parser) throws IllegalArgumentExc
return mapping;
}
+ /**
+ * Process a single record and generate all found ids.
+ */
protected abstract void processRecord(Record record, String id, EntityIdMap mapping);
@JsonIgnore
diff --git a/backend/src/main/java/com/bakdata/conquery/resources/admin/ui/DatasetsUIResource.java b/backend/src/main/java/com/bakdata/conquery/resources/admin/ui/DatasetsUIResource.java
index e0d12a0613..9c9c5409b4 100644
--- a/backend/src/main/java/com/bakdata/conquery/resources/admin/ui/DatasetsUIResource.java
+++ b/backend/src/main/java/com/bakdata/conquery/resources/admin/ui/DatasetsUIResource.java
@@ -114,8 +114,8 @@ imp, getNamespace().getStorage().getAllConcepts()
@Path("mapping")
public View getIdMapping() {
EntityIdMap mapping = namespace.getStorage().getIdMapping();
- if (mapping != null && mapping.getCsvIdToExternalIdMap() != null) {
- return new UIView<>("idmapping.html.ftl", uiProcessor.getUIContext(), mapping.getCsvIdToExternalIdMap());
+ if (mapping != null && mapping.getInternalToPrint() != null) {
+ return new UIView<>("idmapping.html.ftl", uiProcessor.getUIContext(), mapping.getInternalToPrint());
}
return new UIView<>("add_idmapping.html.ftl", uiProcessor.getUIContext(), namespace.getDataset().getId());
}
From df98f556dbe2ceebd4b08a5dbdfd984846030a4d Mon Sep 17 00:00:00 2001
From: Fabian Kovacs <1553491+awildturtok@users.noreply.github.com>
Date: Thu, 8 Jul 2021 17:29:37 +0200
Subject: [PATCH 08/82] don't use weird reflection magic
---
.../concept/specific/external/CQExternal.java | 104 +++++++++---------
.../concept/specific/external/DateColumn.java | 29 +++--
.../concept/specific/external/DateFormat.java | 59 +++++-----
.../specific/external/FormatColumn.java | 37 +------
.../concept/specific/external/IdColumn.java | 11 +-
.../specific/external/IgnoreColumn.java | 3 +-
.../models/config/FrontendConfig.java | 46 ++++----
.../conquery/models/config/NoIdMapping.java | 3 +
.../models/config/SimpleIdMapping.java | 26 +++--
.../identifiable/mapping/IdMappingConfig.java | 24 +++-
10 files changed, 170 insertions(+), 172 deletions(-)
diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java
index 0728d7df07..7e812eef3b 100644
--- a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java
+++ b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java
@@ -2,17 +2,14 @@
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Date;
import java.util.List;
import java.util.Map;
-import java.util.Objects;
import java.util.Optional;
import javax.validation.constraints.NotEmpty;
import com.bakdata.conquery.apiv1.query.CQElement;
import com.bakdata.conquery.io.cps.CPSType;
-import com.bakdata.conquery.io.cps.CPSTypeIdResolver;
import com.bakdata.conquery.io.jackson.InternalOnly;
import com.bakdata.conquery.models.common.CDateSet;
import com.bakdata.conquery.models.dictionary.EncodedDictionary;
@@ -26,12 +23,11 @@
import com.bakdata.conquery.models.query.resultinfo.ResultInfoCollector;
import com.bakdata.conquery.util.DateFormats;
import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.google.common.collect.MoreCollectors;
import io.dropwizard.validation.ValidationMethod;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import lombok.Getter;
-import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
+import org.jetbrains.annotations.NotNull;
/**
* Allows uploading lists of entities.
@@ -71,47 +67,34 @@ public QPNode createQueryPlan(QueryPlanContext context, ConceptQueryPlan plan) {
@Override
public void resolve(QueryResolveContext context) {
-
- List resolvedFormats = instantiateFormatIds(format);
-
-
- for (int index = 0; index < resolvedFormats.size(); index++) {
- resolvedFormats.get(index).setPosition(index);
- }
-
valuesResolved = new Int2ObjectOpenHashMap<>();
- final DateColumn[] dateColumns = resolvedFormats.stream()
- .filter(DateColumn.class::isInstance)
- .map(DateColumn.class::cast)
- .toArray(DateColumn[]::new);
- //TODO verify dateColumns match
+ final EntityIdMap mapping = context.getNamespace().getStorage().getIdMapping();
+
+ final Map stringFormatColumnMap = context.getConfig().getIdMapping().getFormatColumns();
- final DateFormat dateFormat = dateColumns.length > 0 ? dateColumns[0].getFormat() : DateFormat.ALL;
+ final FormatColumn[] resolvedFormats = resolveFormats(stringFormatColumnMap);
+ final DateFormat dateFormat = getDateFormat(resolvedFormats);
- final IdColumn idColumn = resolvedFormats.stream()
- .filter(IdColumn.class::isInstance)
- .map(IdColumn.class::cast)
- .collect(MoreCollectors.onlyElement());
+ final int idIndex = getIdIndex(resolvedFormats);
+ final IdColumn idColumn = (IdColumn) resolvedFormats[idIndex];
final EncodedDictionary primary = context.getNamespace().getStorage().getPrimaryDictionary();
- final EntityIdMap mapping = context.getNamespace().getStorage().getIdMapping();
final DateFormats dateFormats = context.getConfig().getPreprocessor().getParsers().getDateFormats();
-
List unresolved = new ArrayList<>();
// ignore the first row, because this is the header
for (int i = 1; i < values.length; i++) {
final String[] row = values[i];
- final String[] externalId = idColumn.read(row);
+ final String[] externalId = idColumn.read(row, idIndex);
final Optional id = mapping.toInternal(externalId);
- if (id.isEmpty()){
+ if (id.isEmpty()) {
continue;
}
@@ -124,7 +107,7 @@ public void resolve(QueryResolveContext context) {
//read the dates from the row
try {
- CDateSet dates = dateFormat.readDates(dateColumns, row, dateFormats);
+ CDateSet dates = dateFormat.readDates(resolvedFormats, row, dateFormats);
valuesResolved.put(resolvedId, dates);
}
@@ -133,6 +116,7 @@ public void resolve(QueryResolveContext context) {
unresolved.add(row);
}
}
+
if (!unresolved.isEmpty()) {
log.warn(
"Could not resolve {} of the {} rows. Not resolved: {}",
@@ -147,41 +131,53 @@ public void resolve(QueryResolveContext context) {
}
}
- /**
- * Helper method to flatten API surface, allowing plain passing of type-ids instead of using objects of only type.
- */
- @SneakyThrows
- private static List instantiateFormatIds(@NotEmpty List formats) {
- List resolvedFormats = new ArrayList<>();
- for (String s : formats) {
-
- Class extends FormatColumn> clazz = CPSTypeIdResolver.getImplementation(FormatColumn.class, s);
- // We've already established at startup, that this should not fail.
- FormatColumn newInstance = clazz.getConstructor().newInstance();
- resolvedFormats.add(newInstance);
+ @NotNull
+ private DateFormat getDateFormat(FormatColumn[] resolvedFormats) {
+ DateFormat dateFormat = null;
+
+ for (FormatColumn col : resolvedFormats) {
+ if (!(col instanceof DateColumn)) {
+ continue;
+ }
+
+ if (dateFormat != null && !dateFormat.equals(((DateColumn) col).getFormat())) {
+ throw new IllegalStateException("Use of multiple Date Formats.");
+ }
+
+ dateFormat = ((DateColumn) col).getFormat();
}
- return resolvedFormats;
+ return dateFormat == null ? DateFormat.ALL : dateFormat;
}
- @Override
- public void collectResultInfos(ResultInfoCollector collector) {
+ private int getIdIndex(FormatColumn[] resolvedFormats) {
+ for (int index = 0; index < resolvedFormats.length; index++) {
+ if (resolvedFormats[index] instanceof IdColumn) {
+ return index;
+ }
+ }
+
+ throw new IllegalStateException("No IdColumn provided");
}
+ @NotNull
+ private FormatColumn[] resolveFormats(Map stringFormatColumnMap) {
+ final List resolvedFormats = new ArrayList<>();
- @JsonIgnore
- @ValidationMethod(message = "Must contain only valid FormatColumn Ids.")
- public boolean isValidFormatIds() {
- return format.stream().map(id -> CPSTypeIdResolver.getImplementation(FormatColumn.class, id)).noneMatch(Objects::isNull);
+ for (String columnType : format) {
+ FormatColumn formatColumn = stringFormatColumnMap.get(columnType);
+
+ if (formatColumn == null) {
+ throw new IllegalStateException(String.format("Don't know of format %s", columnType));
+ }
+
+ resolvedFormats.add(formatColumn);
+ }
+ return resolvedFormats.toArray(FormatColumn[]::new);
}
- @JsonIgnore
- @ValidationMethod(message = "Must use one IdColumn.")
- public boolean isOnlyOneIdColumn() {
- return format.stream()
- .map(id -> CPSTypeIdResolver.getImplementation(FormatColumn.class, id))
- .filter(IdColumn.class::isAssignableFrom)
- .count() == 1;
+ @Override
+ public void collectResultInfos(ResultInfoCollector collector) {
}
diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateColumn.java b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateColumn.java
index ec752f10d0..679189365c 100644
--- a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateColumn.java
+++ b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateColumn.java
@@ -1,49 +1,58 @@
package com.bakdata.conquery.apiv1.query.concept.specific.external;
import com.bakdata.conquery.io.cps.CPSType;
+import lombok.AllArgsConstructor;
import lombok.Getter;
+import lombok.With;
@Getter
public abstract class DateColumn extends FormatColumn {
private final DateFormat format;
- public DateColumn(DateFormat format) {
+ protected DateColumn(DateFormat format) {
this.format = format;
}
- @CPSType(id = "DATE_SET", base = FormatColumn.class)
+
public static class DateSet extends DateColumn {
+ public static String HANDLE = "DATE_SET";
+
public DateSet() {
super(DateFormat.DATE_SET);
}
}
- @CPSType(id = "DATE_RANGE", base = FormatColumn.class)
public static class DateRange extends DateColumn {
+ public static String HANDLE = "DATE_RANGE";
+
public DateRange() {
super(DateFormat.DATE_RANGE);
}
}
- @CPSType(id = "EVENT_DATE", base = FormatColumn.class)
public static class EventDate extends DateColumn {
+ public static String HANDLE = "EVENT_DATE";
+
+
public EventDate() {
super(DateFormat.EVENT_DATE);
}
}
- @CPSType(id = "START_DATE", base = FormatColumn.class)
- public static class DateStart extends DateColumn {
- public DateStart() {
+ public static class StartDate extends DateColumn {
+ public static String HANDLE = "START_DATE";
+
+ public StartDate() {
super(DateFormat.START_END_DATE);
}
}
- @CPSType(id = "END_DATE", base = FormatColumn.class)
- public static class DateEnd extends DateColumn {
- public DateEnd() {
+ public static class EndDate extends DateColumn {
+ public static String HANDLE = "END_DATE";
+
+ public EndDate() {
super(DateFormat.START_END_DATE);
}
}
diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateFormat.java b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateFormat.java
index cd4c15dbe7..5a0253b276 100644
--- a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateFormat.java
+++ b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateFormat.java
@@ -3,44 +3,35 @@
import java.time.LocalDate;
import java.util.Arrays;
import java.util.Collections;
+import java.util.Enumeration;
+import com.bakdata.conquery.apiv1.forms.Form;
import com.bakdata.conquery.models.common.CDateSet;
import com.bakdata.conquery.models.common.daterange.CDateRange;
import com.bakdata.conquery.models.preproc.parser.specific.DateRangeParser;
import com.bakdata.conquery.util.DateFormats;
import com.google.common.base.Preconditions;
import com.google.common.collect.MoreCollectors;
+import org.apache.commons.collections.EnumerationUtils;
public enum DateFormat {
EVENT_DATE {
@Override
- public CDateSet readDates(DateColumn[] dateIndices, String[] row, DateFormats dateFormats) {
- Preconditions.checkArgument(dateIndices.length == 1);
+ public CDateSet readDates(FormatColumn[] formats, String[] row, DateFormats dateFormats) {
+ final int index = findIndex(formats, DateColumn.EventDate.class);
- return CDateSet.create(Collections.singleton(CDateRange.exactly(dateFormats.parseToLocalDate(row[dateIndices[0].getPosition()]))));
+ return CDateSet.create(Collections.singleton(CDateRange.exactly(dateFormats.parseToLocalDate(row[index]))));
}
},
START_END_DATE {
@Override
- public CDateSet readDates(DateColumn[] dateIndices, String[] row, DateFormats dateFormats) {
- Preconditions.checkArgument(dateIndices.length == 1 || dateIndices.length == 2);
+ public CDateSet readDates(FormatColumn[] formats, String[] row, DateFormats dateFormats) {
+ final int startIndex = findIndex(formats, DateColumn.StartDate.class);
+ final int endIndex = findIndex(formats, DateColumn.EndDate.class);
- LocalDate start = Arrays.stream(dateIndices)
- .filter(DateColumn.DateStart.class::isInstance)
- .map(DateColumn::getPosition)
- .map(idx -> row[idx])
- .map(dateFormats::parseToLocalDate)
- .collect(MoreCollectors.toOptional())
- .orElse(null);
-
- LocalDate end = Arrays.stream(dateIndices)
- .filter(DateColumn.DateEnd.class::isInstance)
- .map(DateColumn::getPosition)
- .map(idx -> row[idx])
- .map(dateFormats::parseToLocalDate)
- .collect(MoreCollectors.toOptional())
- .orElse(null);
+ LocalDate start = dateFormats.parseToLocalDate(row[startIndex]);
+ LocalDate end = dateFormats.parseToLocalDate(row[endIndex]);
if (start == null && end == null) {
return null;
@@ -51,28 +42,36 @@ public CDateSet readDates(DateColumn[] dateIndices, String[] row, DateFormats da
},
DATE_RANGE {
@Override
- public CDateSet readDates(DateColumn[] dateIndices, String[] row, DateFormats dateFormats) {
- Preconditions.checkArgument(dateIndices.length == 1);
+ public CDateSet readDates(FormatColumn[] formats, String[] row, DateFormats dateFormats) {
+ final int index = findIndex(formats, DateColumn.DateRange.class);
- return CDateSet.create(Collections.singleton(DateRangeParser.parseISORange(row[dateIndices[0].getPosition()], dateFormats)));
+ return CDateSet.create(Collections.singleton(DateRangeParser.parseISORange(row[index], dateFormats)));
}
},
DATE_SET {
@Override
- public CDateSet readDates(DateColumn[] dateIndices, String[] row, DateFormats dateFormats) {
- Preconditions.checkArgument(dateIndices.length == 1);
+ public CDateSet readDates(FormatColumn[] formats, String[] row, DateFormats dateFormats) {
+ final int index = findIndex(formats, DateColumn.DateSet.class);
- return CDateSet.parse(row[dateIndices[0].getPosition()], dateFormats);
+ return CDateSet.parse(row[index], dateFormats);
}
},
ALL {
@Override
- public CDateSet readDates(DateColumn[] dateIndices, String[] row, DateFormats dateFormats) {
- Preconditions.checkArgument(dateIndices.length == 0);
-
+ public CDateSet readDates(FormatColumn[] formats, String[] row, DateFormats dateFormats) {
return CDateSet.createFull();
}
};
- public abstract CDateSet readDates(DateColumn[] dateIndices, String[] row, DateFormats dateFormats);
+ public abstract CDateSet readDates(FormatColumn[] formats, String[] row, DateFormats dateFormats);
+
+ protected static int findIndex(FormatColumn[] formats, Class extends DateColumn> clazz){
+ for (int index = 0; index < formats.length; index++) {
+ if (clazz.isInstance(formats[index])) {
+ return index;
+ }
+ }
+
+ return -1;
+ }
}
diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/FormatColumn.java b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/FormatColumn.java
index 83b8701c56..27f769c8e8 100644
--- a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/FormatColumn.java
+++ b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/FormatColumn.java
@@ -1,43 +1,10 @@
package com.bakdata.conquery.apiv1.query.concept.specific.external;
-import java.lang.reflect.InvocationTargetException;
-import java.util.Set;
-
-import com.bakdata.conquery.apiv1.forms.Form;
-import com.bakdata.conquery.io.cps.CPSBase;
-import com.bakdata.conquery.io.cps.CPSType;
-import com.bakdata.conquery.io.cps.CPSTypeIdResolver;
-import com.bakdata.conquery.io.jackson.InternalOnly;
-import com.fasterxml.jackson.annotation.JsonTypeInfo;
import lombok.Data;
-import lombok.Getter;
-import lombok.Setter;
+import lombok.With;
import lombok.extern.slf4j.Slf4j;
-@CPSBase
-@JsonTypeInfo(use = JsonTypeInfo.Id.CUSTOM, property = "type")
-@Data
-@Slf4j
-public abstract class FormatColumn {
-
- @InternalOnly @Setter @Getter
- private int position;
- static {
- // For each implementation of FormatColumn, test if we can instantiate it using default constructor. Fail start-up if not possible.
- final Set> implementations = CPSTypeIdResolver.listImplementations(FormatColumn.class);
-
- for (Class extends FormatColumn> impl : implementations) {
- final String id = impl.getAnnotation(CPSType.class).id();
- try {
- // Try and get no-args constructor
- impl.getConstructor().newInstance();
- }
- catch (Exception e) {
- log.error("FormatColumn {} has no default constructor.", id);
- throw new RuntimeException(e);
- }
- }
- }
+public abstract class FormatColumn {
}
diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/IdColumn.java b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/IdColumn.java
index e90633ff69..1877249878 100644
--- a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/IdColumn.java
+++ b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/IdColumn.java
@@ -1,11 +1,14 @@
package com.bakdata.conquery.apiv1.query.concept.specific.external;
-import com.bakdata.conquery.io.cps.CPSType;
+import lombok.AllArgsConstructor;
+import lombok.Value;
+import lombok.With;
-@CPSType(id = "ID", base = FormatColumn.class)
public class IdColumn extends FormatColumn {
- public String[] read(String[] row) {
- return new String[]{row[getPosition()]};
+ public static String HANDLE = "ID";
+
+ public String[] read(String[] row, int position) {
+ return new String[]{row[position]};
}
}
diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/IgnoreColumn.java b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/IgnoreColumn.java
index 5ef653ab12..4a1c314d84 100644
--- a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/IgnoreColumn.java
+++ b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/IgnoreColumn.java
@@ -2,9 +2,10 @@
import com.bakdata.conquery.io.cps.CPSType;
-@CPSType(id = "IGNORE", base = FormatColumn.class)
public class IgnoreColumn extends FormatColumn {
+ public static final String HANDLE = "IGNORED";
+
public String read(String[] row) {
return null;
}
diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java b/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java
index 7dbba4645a..dc958d672f 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java
@@ -14,7 +14,9 @@
import com.bakdata.conquery.apiv1.query.concept.specific.external.IdColumn;
import com.bakdata.conquery.io.cps.CPSType;
import com.bakdata.conquery.io.cps.CPSTypeIdResolver;
+import com.bakdata.conquery.models.identifiable.mapping.IdMappingConfig;
import com.bakdata.conquery.util.VersionInfo;
+import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonIgnore;
import groovy.transform.ToString;
import io.dropwizard.validation.ValidationMethod;
@@ -27,7 +29,6 @@
@Setter
public class FrontendConfig {
-
private String version = VersionInfo.INSTANCE.getProjectVersion();
@Valid
@NotNull
@@ -35,56 +36,49 @@ public class FrontendConfig {
private UploadConfig queryUpload = new UploadConfig();
- @Data
+ @Getter @Setter
public static class UploadConfig {
- private final static List DEFAULT_IDS = new ArrayList<>();
-
-
- static {
- // Collect all implementations of IdClass.
-
- final Set> idClasses = CPSTypeIdResolver.listImplementations(FormatColumn.class);
-
- for (Class extends FormatColumn> idClass : idClasses) {
-
- if (!IdColumn.class.isAssignableFrom(idClass)) {
- continue;
- }
-
- final String id = idClass.getAnnotation(CPSType.class).id();
- DEFAULT_IDS.add(new ColumnConfig(id, Map.of("en", id), Map.of("en", id)));
- }
- }
@NotEmpty
- private List ids = DEFAULT_IDS;
+ private List ids = List.of(new ColumnConfig(IdColumn.HANDLE, Map.of("en", "Id"), Map.of("en", "Id of the Entity.")));
@NotNull
private ColumnConfig dateStart =
- new ColumnConfig(DateColumn.DateStart.class.getAnnotation(CPSType.class).id(), Map.of("en", "Begin"), Map.of("en", "Begin of Date"));
+ new ColumnConfig(DateColumn.StartDate.HANDLE, Map.of("en", "Begin"), Map.of("en", "Begin of Date-range"));
@NotNull
private ColumnConfig dateEnd =
- new ColumnConfig(DateColumn.DateEnd.class.getAnnotation(CPSType.class).id(), Map.of("en", "Begin"), Map.of("en", "Begin of Date"));
+ new ColumnConfig(DateColumn.EndDate.HANDLE, Map.of("en", "Begin"), Map.of("en", "End of Date-range"));
@NotNull
private ColumnConfig dateRange =
- new ColumnConfig(DateColumn.DateRange.class.getAnnotation(CPSType.class).id(), Map.of("en", "Date Range"), Map.of("en", "Full Date Range"));
+ new ColumnConfig(DateColumn.DateRange.HANDLE, Map.of("en", "Date Range"), Map.of("en", "Full Date Range"));
@NotNull
private ColumnConfig dateSet =
- new ColumnConfig(DateColumn.DateSet.class.getAnnotation(CPSType.class).id(), Map.of("en", "Dateset"), Map.of("en", "Set of Date-Ranges"));
+ new ColumnConfig(DateColumn.DateSet.HANDLE, Map.of("en", "Dateset"), Map.of("en", "Set of Date-Ranges"));
@NotNull
private ColumnConfig eventDate =
- new ColumnConfig(DateColumn.EventDate.class.getAnnotation(CPSType.class).id(), Map.of("en", "Event Date"), Map.of("en", "Single day"));
+ new ColumnConfig(DateColumn.EventDate.HANDLE, Map.of("en", "Event Date"), Map.of("en", "Single event"));
@Data
public static class ColumnConfig {
+
+ /**
+ * Name of the Column, used to resolve the specific entry at {@link IdMappingConfig#getFormatColumns()}
+ */
@NotEmpty
private final String name;
+ /**
+ * Map of Localized labels.
+ */
private final Map label;
+
+ /**
+ * Map of Localized description.
+ */
private final Map description;
@JsonIgnore
diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/NoIdMapping.java b/backend/src/main/java/com/bakdata/conquery/models/config/NoIdMapping.java
index b6cd730c2a..394ba14338 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/config/NoIdMapping.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/config/NoIdMapping.java
@@ -8,6 +8,9 @@
import com.bakdata.conquery.models.identifiable.mapping.EntityIdMap;
import com.univocity.parsers.common.record.Record;
+/**
+ * Disables Id-Mapping completely.
+ */
@CPSType(base = IdMappingConfig.class, id = "NO_ID_MAPPING")
public class NoIdMapping extends IdMappingConfig {
private static final String[] HEADER = new String[]{"result"};
diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/SimpleIdMapping.java b/backend/src/main/java/com/bakdata/conquery/models/config/SimpleIdMapping.java
index 4355276bcc..f85eeb104f 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/config/SimpleIdMapping.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/config/SimpleIdMapping.java
@@ -1,7 +1,10 @@
package com.bakdata.conquery.models.config;
-import java.util.List;
+import java.util.HashMap;
+import java.util.Map;
+import com.bakdata.conquery.apiv1.query.concept.specific.external.FormatColumn;
+import com.bakdata.conquery.apiv1.query.concept.specific.external.IdColumn;
import com.bakdata.conquery.io.cps.CPSType;
import com.bakdata.conquery.models.identifiable.mapping.EntityIdMap;
import com.bakdata.conquery.models.identifiable.mapping.EntityPrintId;
@@ -9,12 +12,19 @@
import com.univocity.parsers.common.record.Record;
/**
- * Identity mapping.
- *
- * TODO should this actually map to a separate column?
+ * Maps input to itself for upload.
*/
@CPSType(base = IdMappingConfig.class, id = "SIMPLE")
-public class SimpleIdMapping extends IdMappingConfig {
+public class SimpleIdMapping extends NoIdMapping {
+
+ @Override
+ public Map getFormatColumns() {
+ final HashMap out = new HashMap<>(super.getFormatColumns());
+
+ out.put(IdColumn.HANDLE, new IdColumn());
+
+ return out;
+ }
@Override
protected void processRecord(Record record, String id, EntityIdMap mapping) {
@@ -26,10 +36,4 @@ protected void processRecord(Record record, String id, EntityIdMap mapping) {
mapping.addInputMapping(id, id);
}
-
- @Override
- public List getPrintIdFields() {
- return List.of("result");
- }
-
}
diff --git a/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/IdMappingConfig.java b/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/IdMappingConfig.java
index d0985f7ee7..81495d0e86 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/IdMappingConfig.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/IdMappingConfig.java
@@ -2,6 +2,9 @@
import java.util.*;
+import com.bakdata.conquery.apiv1.query.concept.specific.external.DateColumn;
+import com.bakdata.conquery.apiv1.query.concept.specific.external.FormatColumn;
+import com.bakdata.conquery.apiv1.query.concept.specific.external.IgnoreColumn;
import com.bakdata.conquery.io.cps.CPSBase;
import com.bakdata.conquery.models.auth.entities.User;
import com.bakdata.conquery.models.execution.ManagedExecution;
@@ -20,7 +23,23 @@
@JsonTypeInfo(use = JsonTypeInfo.Id.CUSTOM, property = "type")
public abstract class IdMappingConfig {
- public EntityIdMap generateIdMapping(CsvParser parser) throws IllegalArgumentException {
+ @JsonIgnore
+ public Map getFormatColumns() {
+ return Map.of(
+ DateColumn.DateSet.HANDLE, new DateColumn.DateSet(),
+ DateColumn.DateRange.HANDLE, new DateColumn.DateRange(),
+ DateColumn.EventDate.HANDLE, new DateColumn.EventDate(),
+ DateColumn.StartDate.HANDLE, new DateColumn.StartDate(),
+ DateColumn.EndDate.HANDLE, new DateColumn.EndDate(),
+ IgnoreColumn.HANDLE, new IgnoreColumn()
+ );
+ }
+
+
+ /**
+ * Read incoming CSV-file extracting Id-Mappings for in and Output.
+ */
+ public EntityIdMap generateIdMapping(CsvParser parser) {
EntityIdMap mapping = new EntityIdMap();
@@ -40,6 +59,9 @@ public EntityIdMap generateIdMapping(CsvParser parser) throws IllegalArgumentExc
*/
protected abstract void processRecord(Record record, String id, EntityIdMap mapping);
+ /**
+ * Headers for Output CSV.
+ */
@JsonIgnore
public abstract List getPrintIdFields();
From 5c51afa4237971a5e190a6249931d184ec188f15 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Thu, 8 Jul 2021 15:32:15 +0000
Subject: [PATCH 09/82] Update AutoDoc
---
docs/Config JSON.md | 26 +++++++++++++-------------
docs/REST API JSONs.md | 20 ++++++++++----------
2 files changed, 23 insertions(+), 23 deletions(-)
diff --git a/docs/Config JSON.md b/docs/Config JSON.md
index 264cd0fd45..b82a65e60c 100644
--- a/docs/Config JSON.md
+++ b/docs/Config JSON.md
@@ -141,8 +141,8 @@ An `IdMappingConfig` is used to define how multi column entity IDs are printed a
Different types of IdMappingConfig can be used by setting `type` to one of the following values:
-### NO_ID_MAPPING [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/NoIdMapping.java#L11)
-
+### NO_ID_MAPPING [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/NoIdMapping.java#L11-L13)
+Disables Id-Mapping completely.
Details
@@ -152,8 +152,8 @@ No fields can be set for this type.
-### SIMPLE [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/SimpleIdMapping.java#L11-L15)
-Identity mapping. TODO should this actually map to a separate column?
+### SIMPLE [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/SimpleIdMapping.java#L14-L16)
+Maps input to itself for upload.
Details
@@ -256,7 +256,7 @@ Supported Fields:
| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/ConqueryConfig.java#L68) | storage | `@Valid @NotNull StoreFactory` | | | |
-### Type CurrencyConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L98)
+### Type CurrencyConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L92)
Details
@@ -267,13 +267,13 @@ Supported Fields:
| | Field | Type | Default | Example | Description |
| --- | --- | --- | --- | --- | --- |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L103) | decimalScale | `int` | `2` | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L102) | decimalSeparator | `String` | `","` | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L100) | prefix | `String` | `"€"` | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L101) | thousandSeparator | `String` | `"."` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L97) | decimalScale | `int` | `2` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L96) | decimalSeparator | `String` | `","` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L94) | prefix | `String` | `"€"` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L95) | thousandSeparator | `String` | `"."` | | |
-### Type FrontendConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L25)
+### Type FrontendConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L27)
Details
@@ -284,9 +284,9 @@ Supported Fields:
| | Field | Type | Default | Example | Description |
| --- | --- | --- | --- | --- | --- |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L32) | currency | [CurrencyConfig](#Type-CurrencyConfig) | | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L36) | queryUpload | `UploadConfig` | | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L31) | version | `String` | `"0.0.0-SNAPSHOT"` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L33) | currency | [CurrencyConfig](#Type-CurrencyConfig) | | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L37) | queryUpload | `UploadConfig` | | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L32) | version | `String` | `"0.0.0-SNAPSHOT"` | | |
### Type LocaleConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/LocaleConfig.java#L11)
diff --git a/docs/REST API JSONs.md b/docs/REST API JSONs.md
index ef647b37fc..536882392a 100644
--- a/docs/REST API JSONs.md
+++ b/docs/REST API JSONs.md
@@ -509,7 +509,7 @@ Supported Fields:
| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/apiv1/query/CQElement.java#L31-L33) | label | `String` | ? | | Allows the user to define labels. |
-### EXTERNAL [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java#L36-L38)
+### EXTERNAL [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java#L32-L34)
Allows uploading lists of entities.
Details
@@ -755,7 +755,7 @@ Supported Fields:
| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/resources/api/ConceptResource.java#L68) | concepts | list of `String` | `null` | | |
-### Type CurrencyConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L98)
+### Type CurrencyConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L92)
Details
@@ -766,10 +766,10 @@ Supported Fields:
| | Field | Type | Default | Example | Description |
| --- | --- | --- | --- | --- | --- |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L103) | decimalScale | `int` | `2` | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L102) | decimalSeparator | `String` | `","` | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L100) | prefix | `String` | `"€"` | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L101) | thousandSeparator | `String` | `"."` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L97) | decimalScale | `int` | `2` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L96) | decimalSeparator | `String` | `","` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L94) | prefix | `String` | `"€"` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L95) | thousandSeparator | `String` | `"."` | | |
### Type ExecutionStatus [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/apiv1/ExecutionStatus.java#L18)
@@ -885,7 +885,7 @@ No fields can be set for this type.
-### Type FrontendConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L25)
+### Type FrontendConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L27)
Details
@@ -896,9 +896,9 @@ Supported Fields:
| | Field | Type | Default | Example | Description |
| --- | --- | --- | --- | --- | --- |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L32) | currency | [CurrencyConfig](#Type-CurrencyConfig) | | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L36) | queryUpload | `UploadConfig` | | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L31) | version | `String` | `"0.0.0-SNAPSHOT"` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L33) | currency | [CurrencyConfig](#Type-CurrencyConfig) | | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L37) | queryUpload | `UploadConfig` | | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L32) | version | `String` | `"0.0.0-SNAPSHOT"` | | |
### Type FullExecutionStatus [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/apiv1/FullExecutionStatus.java#L20-L24)
From 6b1685aac6c775df3233321e41859a6a34f1aaee Mon Sep 17 00:00:00 2001
From: Fabian Kovacs <1553491+awildturtok@users.noreply.github.com>
Date: Thu, 15 Jul 2021 17:04:05 +0200
Subject: [PATCH 10/82] Don't use fancy CPS instead define mappings in config
---
.../java/com/bakdata/conquery/Conquery.java | 2 -
.../concept/specific/external/CQExternal.java | 92 ++--------
.../concept/specific/external/DateFormat.java | 49 ++---
.../serializer/CDateRangeDeserializer.java | 10 +-
.../serializer/CDateSetDeserializer.java | 6 +-
.../serializer/FormatedDateDeserializer.java | 6 +-
.../conquery/io/storage/NamespaceStorage.java | 7 +
.../conquery/models/common/CDateSet.java | 8 +-
.../models/common/daterange/CDateRange.java | 3 -
.../models/config/ConqueryConfig.java | 8 +-
.../conquery/models/config/NoIdMapping.java | 5 -
.../conquery/models/config/ParserConfig.java | 26 +--
.../models/config/SimpleIdMapping.java | 19 --
.../identifiable/mapping/EntityIdMap.java | 15 +-
.../identifiable/mapping/IdMappingConfig.java | 170 +++++++++++++++---
.../conquery/models/preproc/Preprocessor.java | 8 +-
.../models/preproc/outputs/CopyOutput.java | 4 +-
.../preproc/outputs/DateRangeOutput.java | 8 +-
.../preproc/outputs/EpochDateRangeOutput.java | 4 +-
.../models/preproc/outputs/EpochOutput.java | 4 +-
.../models/preproc/outputs/LineOutput.java | 4 +-
.../models/preproc/outputs/NullOutput.java | 4 +-
.../preproc/outputs/OutputDescription.java | 6 +-
.../preproc/parser/specific/DateParser.java | 8 +-
.../parser/specific/DateRangeParser.java | 16 +-
.../{DateFormats.java => DateReader.java} | 31 ++--
.../json/AbstractQueryEngineTest.java | 1 -
27 files changed, 268 insertions(+), 256 deletions(-)
rename backend/src/main/java/com/bakdata/conquery/util/{DateFormats.java => DateReader.java} (85%)
diff --git a/backend/src/main/java/com/bakdata/conquery/Conquery.java b/backend/src/main/java/com/bakdata/conquery/Conquery.java
index d8de33ae49..af84bae5d4 100644
--- a/backend/src/main/java/com/bakdata/conquery/Conquery.java
+++ b/backend/src/main/java/com/bakdata/conquery/Conquery.java
@@ -15,11 +15,9 @@
import com.bakdata.conquery.io.jackson.Jackson;
import com.bakdata.conquery.io.jackson.MutableInjectableValues;
import com.bakdata.conquery.models.config.ConqueryConfig;
-import com.bakdata.conquery.util.DateFormats;
import com.bakdata.conquery.util.UrlRewriteBundle;
import io.dropwizard.Application;
import io.dropwizard.ConfiguredBundle;
-import io.dropwizard.configuration.EnvironmentVariableSubstitutor;
import io.dropwizard.configuration.JsonConfigurationFactory;
import io.dropwizard.configuration.SubstitutingSourceProvider;
import io.dropwizard.servlets.assets.AssetServlet;
diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java
index 7e812eef3b..88e90c99b1 100644
--- a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java
+++ b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java
@@ -4,7 +4,6 @@
import java.util.Arrays;
import java.util.List;
import java.util.Map;
-import java.util.Optional;
import javax.validation.constraints.NotEmpty;
@@ -12,18 +11,19 @@
import com.bakdata.conquery.io.cps.CPSType;
import com.bakdata.conquery.io.jackson.InternalOnly;
import com.bakdata.conquery.models.common.CDateSet;
-import com.bakdata.conquery.models.dictionary.EncodedDictionary;
import com.bakdata.conquery.models.error.ConqueryError;
import com.bakdata.conquery.models.identifiable.mapping.EntityIdMap;
+import com.bakdata.conquery.models.identifiable.mapping.IdMappingConfig;
import com.bakdata.conquery.models.query.QueryPlanContext;
import com.bakdata.conquery.models.query.QueryResolveContext;
import com.bakdata.conquery.models.query.queryplan.ConceptQueryPlan;
import com.bakdata.conquery.models.query.queryplan.QPNode;
import com.bakdata.conquery.models.query.queryplan.specific.ExternalNode;
import com.bakdata.conquery.models.query.resultinfo.ResultInfoCollector;
-import com.bakdata.conquery.util.DateFormats;
+import com.bakdata.conquery.util.DateReader;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.dropwizard.validation.ValidationMethod;
+import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
@@ -69,52 +69,40 @@ public QPNode createQueryPlan(QueryPlanContext context, ConceptQueryPlan plan) {
public void resolve(QueryResolveContext context) {
valuesResolved = new Int2ObjectOpenHashMap<>();
-
final EntityIdMap mapping = context.getNamespace().getStorage().getIdMapping();
- final Map stringFormatColumnMap = context.getConfig().getIdMapping().getFormatColumns();
-
- final FormatColumn[] resolvedFormats = resolveFormats(stringFormatColumnMap);
+ final DateReader dateReader = context.getConfig().getPreprocessor().getParsers().getDateReader();
- final DateFormat dateFormat = getDateFormat(resolvedFormats);
+ final IdMappingConfig mappingConfig = context.getConfig().getIdMapping();
- final int idIndex = getIdIndex(resolvedFormats);
- final IdColumn idColumn = (IdColumn) resolvedFormats[idIndex];
+ // extract dates from rows
+ final Int2ObjectMap rowDates = mappingConfig.readDates(values, format, dateReader);
+ final int idIndex = mappingConfig.getIdIndex(format);
- final EncodedDictionary primary = context.getNamespace().getStorage().getPrimaryDictionary();
- final DateFormats dateFormats = context.getConfig().getPreprocessor().getParsers().getDateFormats();
+ final IdMappingConfig.InputMapper reader = mappingConfig.getIdMapper(format.get(idIndex));
- List unresolved = new ArrayList<>();
+ final List unresolved = new ArrayList<>();
// ignore the first row, because this is the header
- for (int i = 1; i < values.length; i++) {
- final String[] row = values[i];
- final String[] externalId = idColumn.read(row, idIndex);
+ for (int rowNum = 1; rowNum < values.length; rowNum++) {
+ final String[] row = values[rowNum];
+ final String externalId = reader.read(row[idIndex]);
- final Optional id = mapping.toInternal(externalId);
+ final int resolvedId = mapping.resolve(reader.getName(), externalId);
- if (id.isEmpty()) {
+ if (resolvedId == -1) {
+ unresolved.add(row);
continue;
}
- final int resolvedId;
-
- if ((resolvedId = primary.getId(id.get())) == -1) {
+ if (!rowDates.containsKey(rowNum)) {
unresolved.add(row);
continue;
}
//read the dates from the row
- try {
- CDateSet dates = dateFormat.readDates(resolvedFormats, row, dateFormats);
-
- valuesResolved.put(resolvedId, dates);
- }
- catch (Exception e) {
- log.warn("Failed to parse Date from {}", row, e);
- unresolved.add(row);
- }
+ valuesResolved.put(resolvedId, rowDates.get(rowNum));
}
if (!unresolved.isEmpty()) {
@@ -131,50 +119,6 @@ public void resolve(QueryResolveContext context) {
}
}
- @NotNull
- private DateFormat getDateFormat(FormatColumn[] resolvedFormats) {
- DateFormat dateFormat = null;
-
- for (FormatColumn col : resolvedFormats) {
- if (!(col instanceof DateColumn)) {
- continue;
- }
-
- if (dateFormat != null && !dateFormat.equals(((DateColumn) col).getFormat())) {
- throw new IllegalStateException("Use of multiple Date Formats.");
- }
-
- dateFormat = ((DateColumn) col).getFormat();
- }
-
- return dateFormat == null ? DateFormat.ALL : dateFormat;
- }
-
- private int getIdIndex(FormatColumn[] resolvedFormats) {
- for (int index = 0; index < resolvedFormats.length; index++) {
- if (resolvedFormats[index] instanceof IdColumn) {
- return index;
- }
- }
-
- throw new IllegalStateException("No IdColumn provided");
- }
-
- @NotNull
- private FormatColumn[] resolveFormats(Map stringFormatColumnMap) {
- final List resolvedFormats = new ArrayList<>();
-
- for (String columnType : format) {
- FormatColumn formatColumn = stringFormatColumnMap.get(columnType);
-
- if (formatColumn == null) {
- throw new IllegalStateException(String.format("Don't know of format %s", columnType));
- }
-
- resolvedFormats.add(formatColumn);
- }
- return resolvedFormats.toArray(FormatColumn[]::new);
- }
@Override
public void collectResultInfos(ResultInfoCollector collector) {
diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateFormat.java b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateFormat.java
index 5a0253b276..96461ebfaf 100644
--- a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateFormat.java
+++ b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateFormat.java
@@ -1,37 +1,31 @@
package com.bakdata.conquery.apiv1.query.concept.specific.external;
import java.time.LocalDate;
-import java.util.Arrays;
import java.util.Collections;
-import java.util.Enumeration;
-import com.bakdata.conquery.apiv1.forms.Form;
import com.bakdata.conquery.models.common.CDateSet;
import com.bakdata.conquery.models.common.daterange.CDateRange;
import com.bakdata.conquery.models.preproc.parser.specific.DateRangeParser;
-import com.bakdata.conquery.util.DateFormats;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.MoreCollectors;
-import org.apache.commons.collections.EnumerationUtils;
+import com.bakdata.conquery.util.DateReader;
public enum DateFormat {
EVENT_DATE {
@Override
- public CDateSet readDates(FormatColumn[] formats, String[] row, DateFormats dateFormats) {
- final int index = findIndex(formats, DateColumn.EventDate.class);
+ public CDateSet readDates(int[] formats, String[] row, DateReader dateReader) {
+ final int index = formats[0];
- return CDateSet.create(Collections.singleton(CDateRange.exactly(dateFormats.parseToLocalDate(row[index]))));
+ return CDateSet.create(Collections.singleton(CDateRange.exactly(dateReader.parseToLocalDate(row[index]))));
}
},
START_END_DATE {
@Override
- public CDateSet readDates(FormatColumn[] formats, String[] row, DateFormats dateFormats) {
+ public CDateSet readDates(int[] formats, String[] row, DateReader dateReader) {
- final int startIndex = findIndex(formats, DateColumn.StartDate.class);
- final int endIndex = findIndex(formats, DateColumn.EndDate.class);
+ final int startIndex = formats[0];
+ final int endIndex = formats[1];
- LocalDate start = dateFormats.parseToLocalDate(row[startIndex]);
- LocalDate end = dateFormats.parseToLocalDate(row[endIndex]);
+ LocalDate start = dateReader.parseToLocalDate(row[startIndex]);
+ LocalDate end = dateReader.parseToLocalDate(row[endIndex]);
if (start == null && end == null) {
return null;
@@ -42,36 +36,27 @@ public CDateSet readDates(FormatColumn[] formats, String[] row, DateFormats date
},
DATE_RANGE {
@Override
- public CDateSet readDates(FormatColumn[] formats, String[] row, DateFormats dateFormats) {
- final int index = findIndex(formats, DateColumn.DateRange.class);
+ public CDateSet readDates(int[] formats, String[] row, DateReader dateReader) {
+ final int index = formats[0];
- return CDateSet.create(Collections.singleton(DateRangeParser.parseISORange(row[index], dateFormats)));
+ return CDateSet.create(Collections.singleton(DateRangeParser.parseISORange(row[index], dateReader)));
}
},
DATE_SET {
@Override
- public CDateSet readDates(FormatColumn[] formats, String[] row, DateFormats dateFormats) {
- final int index = findIndex(formats, DateColumn.DateSet.class);
+ public CDateSet readDates(int[] formats, String[] row, DateReader dateReader) {
+ final int index = formats[0];
- return CDateSet.parse(row[index], dateFormats);
+ return CDateSet.parse(row[index], dateReader);
}
},
ALL {
@Override
- public CDateSet readDates(FormatColumn[] formats, String[] row, DateFormats dateFormats) {
+ public CDateSet readDates(int[] formats, String[] row, DateReader dateReader) {
return CDateSet.createFull();
}
};
- public abstract CDateSet readDates(FormatColumn[] formats, String[] row, DateFormats dateFormats);
+ public abstract CDateSet readDates(int[] formats, String[] row, DateReader dateReader);
- protected static int findIndex(FormatColumn[] formats, Class extends DateColumn> clazz){
- for (int index = 0; index < formats.length; index++) {
- if (clazz.isInstance(formats[index])) {
- return index;
- }
- }
-
- return -1;
- }
}
diff --git a/backend/src/main/java/com/bakdata/conquery/io/jackson/serializer/CDateRangeDeserializer.java b/backend/src/main/java/com/bakdata/conquery/io/jackson/serializer/CDateRangeDeserializer.java
index ee2f502587..4d445ad9c4 100644
--- a/backend/src/main/java/com/bakdata/conquery/io/jackson/serializer/CDateRangeDeserializer.java
+++ b/backend/src/main/java/com/bakdata/conquery/io/jackson/serializer/CDateRangeDeserializer.java
@@ -2,7 +2,7 @@
import com.bakdata.conquery.models.common.daterange.CDateRange;
import com.bakdata.conquery.models.preproc.parser.specific.DateRangeParser;
-import com.bakdata.conquery.util.DateFormats;
+import com.bakdata.conquery.util.DateReader;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
@@ -13,16 +13,16 @@
public class CDateRangeDeserializer extends StdDeserializer {
- private final DateFormats dateFormats;
+ private final DateReader dateReader;
- protected CDateRangeDeserializer(DateFormats dateFormats) {
+ protected CDateRangeDeserializer(DateReader dateReader) {
super(CDateRange.class);
- this.dateFormats = dateFormats;
+ this.dateReader = dateReader;
}
@SneakyThrows
@Override
public CDateRange deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
- return DateRangeParser.parseISORange(p.getText(), dateFormats);
+ return DateRangeParser.parseISORange(p.getText(), dateReader);
}
}
diff --git a/backend/src/main/java/com/bakdata/conquery/io/jackson/serializer/CDateSetDeserializer.java b/backend/src/main/java/com/bakdata/conquery/io/jackson/serializer/CDateSetDeserializer.java
index 0eecf28ebf..356cd167e7 100644
--- a/backend/src/main/java/com/bakdata/conquery/io/jackson/serializer/CDateSetDeserializer.java
+++ b/backend/src/main/java/com/bakdata/conquery/io/jackson/serializer/CDateSetDeserializer.java
@@ -4,7 +4,7 @@
import com.bakdata.conquery.models.common.CDateSet;
import com.bakdata.conquery.models.common.daterange.CDateRange;
-import com.bakdata.conquery.util.DateFormats;
+import com.bakdata.conquery.util.DateReader;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.JsonToken;
@@ -15,10 +15,10 @@ public class CDateSetDeserializer extends StdDeserializer {
private static final long serialVersionUID = 1L;
- private final DateFormats formats;
+ private final DateReader formats;
- public CDateSetDeserializer(DateFormats formats) {
+ public CDateSetDeserializer(DateReader formats) {
super(CDateSet.class);
this.formats = formats;
}
diff --git a/backend/src/main/java/com/bakdata/conquery/io/jackson/serializer/FormatedDateDeserializer.java b/backend/src/main/java/com/bakdata/conquery/io/jackson/serializer/FormatedDateDeserializer.java
index 21022449c9..ead4a01e79 100644
--- a/backend/src/main/java/com/bakdata/conquery/io/jackson/serializer/FormatedDateDeserializer.java
+++ b/backend/src/main/java/com/bakdata/conquery/io/jackson/serializer/FormatedDateDeserializer.java
@@ -1,6 +1,6 @@
package com.bakdata.conquery.io.jackson.serializer;
-import com.bakdata.conquery.util.DateFormats;
+import com.bakdata.conquery.util.DateReader;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
@@ -11,9 +11,9 @@
public class FormatedDateDeserializer extends StdDeserializer {
- private final DateFormats formats;
+ private final DateReader formats;
- public FormatedDateDeserializer(DateFormats formats) {
+ public FormatedDateDeserializer(DateReader formats) {
super(LocalDate.class);
this.formats = formats;
}
diff --git a/backend/src/main/java/com/bakdata/conquery/io/storage/NamespaceStorage.java b/backend/src/main/java/com/bakdata/conquery/io/storage/NamespaceStorage.java
index 0c311b7492..c85f6188dc 100644
--- a/backend/src/main/java/com/bakdata/conquery/io/storage/NamespaceStorage.java
+++ b/backend/src/main/java/com/bakdata/conquery/io/storage/NamespaceStorage.java
@@ -36,6 +36,13 @@ public NamespaceStorage(Validator validator, StoreFactory storageFactory, String
idMapping = storageFactory.createIdMappingStore(pathName);
structure = storageFactory.createStructureStore(pathName, new SingletonNamespaceCollection(getCentralRegistry()));
workerToBuckets = storageFactory.createWorkerToBucketsStore(pathName);
+
+
+ decorateIdMapping(idMapping);
+ }
+
+ private void decorateIdMapping(SingletonStore idMapping) {
+ idMapping.onAdd(mapping -> mapping.setDictionary(getPrimaryDictionary()));
}
diff --git a/backend/src/main/java/com/bakdata/conquery/models/common/CDateSet.java b/backend/src/main/java/com/bakdata/conquery/models/common/CDateSet.java
index 7b04f46740..d54efeba74 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/common/CDateSet.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/common/CDateSet.java
@@ -16,7 +16,7 @@
import com.bakdata.conquery.models.common.daterange.CDateRange;
import com.bakdata.conquery.models.preproc.parser.specific.DateRangeParser;
-import com.bakdata.conquery.util.DateFormats;
+import com.bakdata.conquery.util.DateReader;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.google.common.base.Joiner;
import com.google.common.collect.ForwardingCollection;
@@ -24,7 +24,7 @@
import lombok.EqualsAndHashCode;
/**
- * (De-)Serializers are are registered programmatically because they depend on {@link com.bakdata.conquery.util.DateFormats}
+ * (De-)Serializers are are registered programmatically because they depend on {@link DateReader}
*/
@EqualsAndHashCode
public class CDateSet {
@@ -445,13 +445,13 @@ public int getMaxValue() {
return rangesByLowerBound.lastEntry().getValue().getMaxValue();
}
- public static CDateSet parse(String value, DateFormats dateFormats) {
+ public static CDateSet parse(String value, DateReader dateReader) {
List ranges = PARSE_PATTERN
.matcher(value)
.results()
.map(mr -> {
try {
- return DateRangeParser.parseISORange(mr.group(2), dateFormats);
+ return DateRangeParser.parseISORange(mr.group(2), dateReader);
}
catch(Exception e) {
throw new RuntimeException(e);
diff --git a/backend/src/main/java/com/bakdata/conquery/models/common/daterange/CDateRange.java b/backend/src/main/java/com/bakdata/conquery/models/common/daterange/CDateRange.java
index 51a77739ee..bf42591f8f 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/common/daterange/CDateRange.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/common/daterange/CDateRange.java
@@ -15,9 +15,6 @@
import com.bakdata.conquery.models.common.IRange;
import com.bakdata.conquery.models.common.QuarterUtils;
import com.bakdata.conquery.models.common.Range;
-import com.bakdata.conquery.models.exceptions.ParsingException;
-import com.bakdata.conquery.models.preproc.parser.specific.DateRangeParser;
-import com.bakdata.conquery.util.DateFormats;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonValue;
diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/ConqueryConfig.java b/backend/src/main/java/com/bakdata/conquery/models/config/ConqueryConfig.java
index a05b2f6fdf..6e1275af23 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/config/ConqueryConfig.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/config/ConqueryConfig.java
@@ -20,7 +20,7 @@
import com.bakdata.conquery.models.config.auth.DevelopmentAuthorizationConfig;
import com.bakdata.conquery.models.common.CDateSet;
import com.bakdata.conquery.models.identifiable.mapping.IdMappingConfig;
-import com.bakdata.conquery.util.DateFormats;
+import com.bakdata.conquery.util.DateReader;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.google.common.collect.MoreCollectors;
@@ -137,10 +137,10 @@ public ObjectMapper configureObjectMapper(ObjectMapper objectMapper) {
public static class ConfiguredModule extends SimpleModule {
public ConfiguredModule(ConqueryConfig config){
- DateFormats dateFormats = config.getPreprocessor().getParsers().getDateFormats();
- addDeserializer(LocalDate.class, new FormatedDateDeserializer(dateFormats));
+ DateReader dateReader = config.getPreprocessor().getParsers().getDateReader();
+ addDeserializer(LocalDate.class, new FormatedDateDeserializer(dateReader));
- addDeserializer(CDateSet.class, new CDateSetDeserializer(dateFormats));
+ addDeserializer(CDateSet.class, new CDateSetDeserializer(dateReader));
addSerializer(CDateSet.class, new CDateSetSerializer());
}
}
diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/NoIdMapping.java b/backend/src/main/java/com/bakdata/conquery/models/config/NoIdMapping.java
index 394ba14338..f7a84dbb06 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/config/NoIdMapping.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/config/NoIdMapping.java
@@ -11,14 +11,9 @@
/**
* Disables Id-Mapping completely.
*/
-@CPSType(base = IdMappingConfig.class, id = "NO_ID_MAPPING")
public class NoIdMapping extends IdMappingConfig {
private static final String[] HEADER = new String[]{"result"};
- @Override
- protected void processRecord(Record record, String id, EntityIdMap mapping) {
- // Do nothing.
- }
@Override
public List getPrintIdFields() {
diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/ParserConfig.java b/backend/src/main/java/com/bakdata/conquery/models/config/ParserConfig.java
index 216b706e4a..2080c75c0d 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/config/ParserConfig.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/config/ParserConfig.java
@@ -1,31 +1,11 @@
package com.bakdata.conquery.models.config;
-import com.bakdata.conquery.models.common.daterange.CDateRange;
-import com.bakdata.conquery.models.exceptions.ParsingException;
-import com.bakdata.conquery.util.DateFormats;
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.JsonDeserializer;
-import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Strings;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
+import com.bakdata.conquery.util.DateReader;
import lombok.Data;
import lombok.Setter;
-import lombok.experimental.UtilityClass;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.StringUtils;
import javax.validation.constraints.NotNull;
-import java.io.IOException;
-import java.time.LocalDate;
-import java.time.format.DateTimeFormatter;
-import java.time.format.DateTimeFormatterBuilder;
-import java.time.format.DateTimeParseException;
+
import java.util.*;
@Data
@@ -51,7 +31,7 @@ public class ParserConfig {
* Date formats that are available for parsing.
*/
@NotNull
- private DateFormats dateFormats = new DateFormats(List.of(
+ private DateReader dateReader = new DateReader(List.of(
"yyyy-MM-dd", "yyyyMMdd", "dd.MM.yyyy"
));
}
diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/SimpleIdMapping.java b/backend/src/main/java/com/bakdata/conquery/models/config/SimpleIdMapping.java
index f85eeb104f..597b3d941a 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/config/SimpleIdMapping.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/config/SimpleIdMapping.java
@@ -14,26 +14,7 @@
/**
* Maps input to itself for upload.
*/
-@CPSType(base = IdMappingConfig.class, id = "SIMPLE")
public class SimpleIdMapping extends NoIdMapping {
- @Override
- public Map getFormatColumns() {
- final HashMap out = new HashMap<>(super.getFormatColumns());
- out.put(IdColumn.HANDLE, new IdColumn());
-
- return out;
- }
-
- @Override
- protected void processRecord(Record record, String id, EntityIdMap mapping) {
-
- final EntityPrintId entityPrintId = EntityPrintId.from(id);
-
- mapping.addOutputMapping(id, entityPrintId);
-
- mapping.addInputMapping(id, id);
-
- }
}
diff --git a/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/EntityIdMap.java b/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/EntityIdMap.java
index 71f5a8b5be..f490741758 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/EntityIdMap.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/EntityIdMap.java
@@ -5,12 +5,14 @@
import java.util.Map;
import java.util.Optional;
+import com.bakdata.conquery.models.dictionary.EncodedDictionary;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
+import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
/**
@@ -23,7 +25,8 @@
@NoArgsConstructor
public class EntityIdMap {
-
+ @Setter
+ private EncodedDictionary dictionary;
/**
* The map from csv entity ids to external entity ids.
@@ -75,6 +78,16 @@ public Optional toInternal(String... external) {
return Optional.ofNullable(external2Internal.get(new ExternalId(external)));
}
+ public int resolve(String... external) {
+ String value = external2Internal.get(new ExternalId(external));
+
+ if (value != null) {
+ return dictionary.getId(value);
+ }
+
+ return -1;
+ }
+
public void addOutputMapping(String csvEntityId, EntityPrintId externalEntityId) {
final EntityPrintId prior = internalToPrint.put(csvEntityId, externalEntityId);
diff --git a/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/IdMappingConfig.java b/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/IdMappingConfig.java
index 81495d0e86..d2462d4460 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/IdMappingConfig.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/IdMappingConfig.java
@@ -1,40 +1,52 @@
package com.bakdata.conquery.models.identifiable.mapping;
-import java.util.*;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
import com.bakdata.conquery.apiv1.query.concept.specific.external.DateColumn;
-import com.bakdata.conquery.apiv1.query.concept.specific.external.FormatColumn;
-import com.bakdata.conquery.apiv1.query.concept.specific.external.IgnoreColumn;
+import com.bakdata.conquery.apiv1.query.concept.specific.external.DateFormat;
import com.bakdata.conquery.io.cps.CPSBase;
import com.bakdata.conquery.models.auth.entities.User;
+import com.bakdata.conquery.models.common.CDateSet;
import com.bakdata.conquery.models.execution.ManagedExecution;
import com.bakdata.conquery.models.worker.Namespace;
+import com.bakdata.conquery.util.DateReader;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.google.common.base.Strings;
import com.univocity.parsers.common.record.Record;
import com.univocity.parsers.csv.CsvParser;
-import lombok.RequiredArgsConstructor;
+import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap;
+import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
+import it.unimi.dsi.fastutil.ints.IntArrayList;
+import it.unimi.dsi.fastutil.ints.IntList;
+import lombok.Data;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
@Slf4j
-@CPSBase
-@RequiredArgsConstructor
-@JsonTypeInfo(use = JsonTypeInfo.Id.CUSTOM, property = "type")
-public abstract class IdMappingConfig {
+@NoArgsConstructor
+@Setter
+@Getter
+public class IdMappingConfig {
- @JsonIgnore
- public Map getFormatColumns() {
- return Map.of(
- DateColumn.DateSet.HANDLE, new DateColumn.DateSet(),
- DateColumn.DateRange.HANDLE, new DateColumn.DateRange(),
- DateColumn.EventDate.HANDLE, new DateColumn.EventDate(),
- DateColumn.StartDate.HANDLE, new DateColumn.StartDate(),
- DateColumn.EndDate.HANDLE, new DateColumn.EndDate(),
- IgnoreColumn.HANDLE, new IgnoreColumn()
- );
- }
+ public final Map dateFormats = Map.of(
+ DateColumn.DateSet.HANDLE, DateFormat.DATE_SET,
+ DateColumn.DateRange.HANDLE, DateFormat.DATE_RANGE,
+ DateColumn.EventDate.HANDLE, DateFormat.EVENT_DATE,
+ DateColumn.StartDate.HANDLE, DateFormat.START_END_DATE,
+ DateColumn.EndDate.HANDLE, DateFormat.START_END_DATE
+ );
+
+ private List mappers = List.of(new InputMapper("ID", "id", "0", -1, Collections.emptyMap(), Collections.emptyMap()));
+
+ private OutputMapper outputMapper = new OutputMapper();
/**
* Read incoming CSV-file extracting Id-Mappings for in and Output.
@@ -45,25 +57,29 @@ public EntityIdMap generateIdMapping(CsvParser parser) {
Record record;
- while((record = parser.parseNextRecord()) != null){
+ while ((record = parser.parseNextRecord()) != null) {
final String id = record.getString("id");
- processRecord(record, id, mapping);
+ for (InputMapper mapper : mappers) {
+ final String otherId = record.getString(mapper.getField());
+ final String transformed = mapper.read(otherId);
+
+ mapping.addInputMapping(id, mapper.getName(), transformed);
+ }
+
+ mapping.addOutputMapping(id, outputMapper.extractOutputId(record));
}
return mapping;
}
- /**
- * Process a single record and generate all found ids.
- */
- protected abstract void processRecord(Record record, String id, EntityIdMap mapping);
-
/**
* Headers for Output CSV.
*/
@JsonIgnore
- public abstract List getPrintIdFields();
+ public List getPrintIdFields() {
+ return List.of(outputMapper.getHeaders());
+ }
/**
* Is called once before a mapping is used before a query result is created to
@@ -93,4 +109,104 @@ public EntityPrintId toExternal(String csvEntityId, Namespace namespace, IdMappi
return externalEntityId;
}
+ public InputMapper getIdMapper(String name) {
+ return mappers.stream().filter(mapper -> mapper.getName().equals(name)).findFirst().orElse(null);
+ }
+
+ public int getIdIndex(List format) {
+ for (int index = 0; index < format.size(); index++) {
+ final String current = format.get(index);
+
+ if (mappers.stream().map(InputMapper::getName).anyMatch(current::equals)) {
+ return index;
+ }
+ }
+
+ return -1;
+ }
+
+
+ public Int2ObjectMap readDates(String[][] values, List format, DateReader dateReader) {
+ Int2ObjectMap out = new Int2ObjectAVLTreeMap<>();
+
+ DateFormat dateFormat = null;
+
+
+ IntList dateColumns = new IntArrayList(format.size());
+
+ for (int col = 0; col < format.size(); col++) {
+ String desc = format.get(col);
+
+ dateFormat = resolveDateFormat(desc);
+
+ if (dateFormat == null) {
+ continue;
+ }
+
+ dateColumns.add(col);
+ }
+
+ dateFormat = dateFormat == null ? DateFormat.ALL : dateFormat;
+ final int[] datePositions = dateColumns.toIntArray();
+
+ for (int row = 1; row < values.length; row++) {
+ try {
+ final CDateSet dates = dateFormat.readDates(datePositions, values[row], dateReader);
+
+ if (dates == null) {
+ continue;
+ }
+
+ out.put(row, dates);
+ }
+ catch (Exception e) {
+ log.warn("Failed to parse Date from {}", row, e);
+ }
+ }
+
+ return out;
+ }
+
+ public DateFormat resolveDateFormat(String desc) {
+ return dateFormats.get(desc);
+ }
+
+ @Data
+ public static class InputMapper {
+ private final String name;
+
+ private final String field;
+
+ private final String pad;
+ private final int length;
+
+ private final Map label;
+ private final Map description;
+
+ public String read(String value) {
+ if (Strings.isNullOrEmpty(value)) {
+ return null;
+ }
+
+ if (length == -1) {
+ return value;
+ }
+
+ return StringUtils.leftPad(value, length, pad);
+ }
+ }
+
+ @CPSBase
+ @JsonTypeInfo(use = JsonTypeInfo.Id.CUSTOM, property = "type")
+ @NoArgsConstructor
+ public static class OutputMapper {
+ @JsonIgnore
+ public String[] getHeaders() {
+ return new String[]{"result"};
+ }
+
+ public EntityPrintId extractOutputId(Record record) {
+ return new EntityPrintId(new String[]{record.getString("id")});
+ }
+ }
}
diff --git a/backend/src/main/java/com/bakdata/conquery/models/preproc/Preprocessor.java b/backend/src/main/java/com/bakdata/conquery/models/preproc/Preprocessor.java
index ec09ddc9cd..900737ded3 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/preproc/Preprocessor.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/preproc/Preprocessor.java
@@ -19,7 +19,7 @@
import com.bakdata.conquery.models.exceptions.ParsingException;
import com.bakdata.conquery.models.preproc.outputs.OutputDescription;
import com.bakdata.conquery.models.preproc.parser.Parser;
-import com.bakdata.conquery.util.DateFormats;
+import com.bakdata.conquery.util.DateReader;
import com.bakdata.conquery.util.io.ConqueryMDC;
import com.bakdata.conquery.util.io.FileUtil;
import com.bakdata.conquery.util.io.LogUtil;
@@ -124,13 +124,13 @@ public static void preprocess(PreprocessingJob preprocessingJob, ProgressBar tot
final GroovyPredicate filter = input.createFilter(headers);
- DateFormats dateFormats = config.getPreprocessor().getParsers().getDateFormats();
- final OutputDescription.Output primaryOut = input.getPrimary().createForHeaders(headerMap, dateFormats);
+ DateReader dateReader = config.getPreprocessor().getParsers().getDateReader();
+ final OutputDescription.Output primaryOut = input.getPrimary().createForHeaders(headerMap, dateReader);
final List outputs = new ArrayList<>();
// Instantiate Outputs based on descriptors (apply header positions)
for (OutputDescription op : input.getOutput()) {
- outputs.add(op.createForHeaders(headerMap, dateFormats));
+ outputs.add(op.createForHeaders(headerMap, dateReader));
}
String[] row;
diff --git a/backend/src/main/java/com/bakdata/conquery/models/preproc/outputs/CopyOutput.java b/backend/src/main/java/com/bakdata/conquery/models/preproc/outputs/CopyOutput.java
index 949dae4afb..2d4060c7cc 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/preproc/outputs/CopyOutput.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/preproc/outputs/CopyOutput.java
@@ -6,7 +6,7 @@
import com.bakdata.conquery.models.events.MajorTypeId;
import com.bakdata.conquery.models.exceptions.ParsingException;
import com.bakdata.conquery.models.preproc.parser.Parser;
-import com.bakdata.conquery.util.DateFormats;
+import com.bakdata.conquery.util.DateReader;
import it.unimi.dsi.fastutil.objects.Object2IntArrayMap;
import lombok.Data;
import lombok.NoArgsConstructor;
@@ -47,7 +47,7 @@ public int hashCode(){
private MajorTypeId inputType;
@Override
- public Output createForHeaders(Object2IntArrayMap headers, DateFormats dateFormats) {
+ public Output createForHeaders(Object2IntArrayMap headers, DateReader dateReader) {
assertRequiredHeaders(headers, inputColumn);
final int column = headers.getInt(inputColumn);
diff --git a/backend/src/main/java/com/bakdata/conquery/models/preproc/outputs/DateRangeOutput.java b/backend/src/main/java/com/bakdata/conquery/models/preproc/outputs/DateRangeOutput.java
index a97f29e513..a48dd337ca 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/preproc/outputs/DateRangeOutput.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/preproc/outputs/DateRangeOutput.java
@@ -9,7 +9,7 @@
import com.bakdata.conquery.models.events.MajorTypeId;
import com.bakdata.conquery.models.exceptions.ParsingException;
import com.bakdata.conquery.models.preproc.parser.Parser;
-import com.bakdata.conquery.util.DateFormats;
+import com.bakdata.conquery.util.DateReader;
import com.google.common.base.Strings;
import it.unimi.dsi.fastutil.objects.Object2IntArrayMap;
import lombok.Data;
@@ -43,7 +43,7 @@ public int hashCode(){
}
@Override
- public Output createForHeaders(Object2IntArrayMap headers, DateFormats dateFormats) {
+ public Output createForHeaders(Object2IntArrayMap headers, DateReader dateReader) {
assertRequiredHeaders(headers, startColumn, endColumn);
final int startIndex = headers.getInt(startColumn);
@@ -61,8 +61,8 @@ protected Object parseLine(String[] row, Parser type, long sourceLine) throws Pa
throw new IllegalArgumentException("Open Ranges are not allowed.");
}
- LocalDate start = dateFormats.parseToLocalDate(row[startIndex]);
- LocalDate end = dateFormats.parseToLocalDate(row[endIndex]);
+ LocalDate start = dateReader.parseToLocalDate(row[startIndex]);
+ LocalDate end = dateReader.parseToLocalDate(row[endIndex]);
return CDateRange.of(start, end);
}
diff --git a/backend/src/main/java/com/bakdata/conquery/models/preproc/outputs/EpochDateRangeOutput.java b/backend/src/main/java/com/bakdata/conquery/models/preproc/outputs/EpochDateRangeOutput.java
index a8fef5d2e1..46b9a8bef8 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/preproc/outputs/EpochDateRangeOutput.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/preproc/outputs/EpochDateRangeOutput.java
@@ -7,7 +7,7 @@
import com.bakdata.conquery.models.events.MajorTypeId;
import com.bakdata.conquery.models.exceptions.ParsingException;
import com.bakdata.conquery.models.preproc.parser.Parser;
-import com.bakdata.conquery.util.DateFormats;
+import com.bakdata.conquery.util.DateReader;
import com.google.common.base.Strings;
import it.unimi.dsi.fastutil.objects.Object2IntArrayMap;
import lombok.Data;
@@ -41,7 +41,7 @@ public int hashCode(){
}
@Override
- public Output createForHeaders(Object2IntArrayMap headers, DateFormats dateFormats) {
+ public Output createForHeaders(Object2IntArrayMap headers, DateReader dateReader) {
assertRequiredHeaders(headers, startColumn, endColumn);
final int startIndex = headers.getInt(startColumn);
diff --git a/backend/src/main/java/com/bakdata/conquery/models/preproc/outputs/EpochOutput.java b/backend/src/main/java/com/bakdata/conquery/models/preproc/outputs/EpochOutput.java
index d28ff81618..6b77946b2e 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/preproc/outputs/EpochOutput.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/preproc/outputs/EpochOutput.java
@@ -6,7 +6,7 @@
import com.bakdata.conquery.models.events.MajorTypeId;
import com.bakdata.conquery.models.exceptions.ParsingException;
import com.bakdata.conquery.models.preproc.parser.Parser;
-import com.bakdata.conquery.util.DateFormats;
+import com.bakdata.conquery.util.DateReader;
import it.unimi.dsi.fastutil.objects.Object2IntArrayMap;
import lombok.Data;
import lombok.ToString;
@@ -32,7 +32,7 @@ public int hashCode(){
}
@Override
- public Output createForHeaders(Object2IntArrayMap headers, DateFormats dateFormats) {
+ public Output createForHeaders(Object2IntArrayMap headers, DateReader dateReader) {
assertRequiredHeaders(headers, inputColumn);
final int columnIndex = headers.getInt(inputColumn);
diff --git a/backend/src/main/java/com/bakdata/conquery/models/preproc/outputs/LineOutput.java b/backend/src/main/java/com/bakdata/conquery/models/preproc/outputs/LineOutput.java
index b8f996a9d2..9cbb0ecf57 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/preproc/outputs/LineOutput.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/preproc/outputs/LineOutput.java
@@ -4,7 +4,7 @@
import com.bakdata.conquery.models.events.MajorTypeId;
import com.bakdata.conquery.models.exceptions.ParsingException;
import com.bakdata.conquery.models.preproc.parser.Parser;
-import com.bakdata.conquery.util.DateFormats;
+import com.bakdata.conquery.util.DateReader;
import com.fasterxml.jackson.annotation.JsonCreator;
import it.unimi.dsi.fastutil.objects.Object2IntArrayMap;
import lombok.NoArgsConstructor;
@@ -30,7 +30,7 @@ public boolean isRequired() {
}
@Override
- public Output createForHeaders(Object2IntArrayMap headers, DateFormats dateFormats) {
+ public Output createForHeaders(Object2IntArrayMap headers, DateReader dateReader) {
return new Output() {
@Override
protected Object parseLine(String[] row, Parser type, long sourceLine) throws ParsingException {
diff --git a/backend/src/main/java/com/bakdata/conquery/models/preproc/outputs/NullOutput.java b/backend/src/main/java/com/bakdata/conquery/models/preproc/outputs/NullOutput.java
index bb3bd6ede6..cf7fa73795 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/preproc/outputs/NullOutput.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/preproc/outputs/NullOutput.java
@@ -6,7 +6,7 @@
import com.bakdata.conquery.models.events.MajorTypeId;
import com.bakdata.conquery.models.exceptions.ParsingException;
import com.bakdata.conquery.models.preproc.parser.Parser;
-import com.bakdata.conquery.util.DateFormats;
+import com.bakdata.conquery.util.DateReader;
import it.unimi.dsi.fastutil.objects.Object2IntArrayMap;
import lombok.Data;
import org.apache.commons.lang3.builder.HashCodeBuilder;
@@ -37,7 +37,7 @@ public boolean isRequired() {
}
@Override
- public Output createForHeaders(Object2IntArrayMap headers, DateFormats dateFormats) {
+ public Output createForHeaders(Object2IntArrayMap headers, DateReader dateReader) {
return new Output() {
@Override
protected Object parseLine(String[] row, Parser type, long sourceLine) throws ParsingException {
diff --git a/backend/src/main/java/com/bakdata/conquery/models/preproc/outputs/OutputDescription.java b/backend/src/main/java/com/bakdata/conquery/models/preproc/outputs/OutputDescription.java
index c10b77a8e7..21aabbd52d 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/preproc/outputs/OutputDescription.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/preproc/outputs/OutputDescription.java
@@ -11,7 +11,7 @@
import com.bakdata.conquery.models.exceptions.ParsingException;
import com.bakdata.conquery.models.preproc.ColumnDescription;
import com.bakdata.conquery.models.preproc.parser.Parser;
-import com.bakdata.conquery.util.DateFormats;
+import com.bakdata.conquery.util.DateReader;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import it.unimi.dsi.fastutil.objects.Object2IntArrayMap;
@@ -110,10 +110,10 @@ protected void assertRequiredHeaders(Object2IntArrayMap actualHeaders, S
/**
* Instantiate the corresponding {@link Output} for the rows.
* @param headers A map from column names to column indices.
- * @param dateFormats
+ * @param dateReader
* @return the output for the specific headers.
*/
- public abstract Output createForHeaders(Object2IntArrayMap headers, DateFormats dateFormats);
+ public abstract Output createForHeaders(Object2IntArrayMap headers, DateReader dateReader);
/**
* The resulting type after {@link Output} has been applied.
diff --git a/backend/src/main/java/com/bakdata/conquery/models/preproc/parser/specific/DateParser.java b/backend/src/main/java/com/bakdata/conquery/models/preproc/parser/specific/DateParser.java
index fe12fee1a9..6c9da6a11b 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/preproc/parser/specific/DateParser.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/preproc/parser/specific/DateParser.java
@@ -10,7 +10,7 @@
import com.bakdata.conquery.models.exceptions.ParsingException;
import com.bakdata.conquery.models.preproc.parser.ColumnValues;
import com.bakdata.conquery.models.preproc.parser.Parser;
-import com.bakdata.conquery.util.DateFormats;
+import com.bakdata.conquery.util.DateReader;
import lombok.SneakyThrows;
import lombok.ToString;
@@ -18,12 +18,12 @@
public class DateParser extends Parser {
private IntegerParser subType;
- private DateFormats dateFormats;
+ private DateReader dateReader;
public DateParser(ParserConfig config) {
super(config);
subType = new IntegerParser(config);
- dateFormats = config.getDateFormats();
+ dateReader = config.getDateReader();
}
@@ -35,7 +35,7 @@ public void setLines(int lines) {
@Override
protected Integer parseValue(@Nonnull String value) throws ParsingException {
- return CDate.ofLocalDate(dateFormats.parseToLocalDate(value));
+ return CDate.ofLocalDate(dateReader.parseToLocalDate(value));
}
@Override
diff --git a/backend/src/main/java/com/bakdata/conquery/models/preproc/parser/specific/DateRangeParser.java b/backend/src/main/java/com/bakdata/conquery/models/preproc/parser/specific/DateRangeParser.java
index b123947d37..9fb8b9e473 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/preproc/parser/specific/DateRangeParser.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/preproc/parser/specific/DateRangeParser.java
@@ -10,20 +10,18 @@
import com.bakdata.conquery.models.exceptions.ParsingException;
import com.bakdata.conquery.models.preproc.parser.ColumnValues;
import com.bakdata.conquery.models.preproc.parser.Parser;
-import com.bakdata.conquery.util.DateFormats;
+import com.bakdata.conquery.util.DateReader;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
-import java.util.Date;
-
@Slf4j
@ToString(callSuper = true)
public class DateRangeParser extends Parser {
private final DateParser minParser;
private final DateParser maxParser;
- private final DateFormats dateFormats;
+ private final DateReader dateReader;
private boolean onlyQuarters = true;
private int maxValue = Integer.MIN_VALUE;
@@ -34,15 +32,15 @@ public DateRangeParser(ParserConfig config) {
super(config);
minParser = new DateParser(config);
maxParser = new DateParser(config);
- dateFormats = config.getDateFormats();
+ dateReader = config.getDateReader();
}
@Override
protected CDateRange parseValue(@Nonnull String value) {
- return DateRangeParser.parseISORange(value, dateFormats);
+ return DateRangeParser.parseISORange(value, dateReader);
}
- public static CDateRange parseISORange(String value, DateFormats dateFormats) {
+ public static CDateRange parseISORange(String value, DateReader dateReader) {
if (value == null) {
return null;
}
@@ -52,8 +50,8 @@ public static CDateRange parseISORange(String value, DateFormats dateFormats) {
}
return CDateRange.of(
- dateFormats.parseToLocalDate(parts[0]),
- dateFormats.parseToLocalDate(parts[1])
+ dateReader.parseToLocalDate(parts[0]),
+ dateReader.parseToLocalDate(parts[1])
);
}
diff --git a/backend/src/main/java/com/bakdata/conquery/util/DateFormats.java b/backend/src/main/java/com/bakdata/conquery/util/DateReader.java
similarity index 85%
rename from backend/src/main/java/com/bakdata/conquery/util/DateFormats.java
rename to backend/src/main/java/com/bakdata/conquery/util/DateReader.java
index 1eb424e9bd..bd1ec3be4b 100644
--- a/backend/src/main/java/com/bakdata/conquery/util/DateFormats.java
+++ b/backend/src/main/java/com/bakdata/conquery/util/DateReader.java
@@ -10,11 +10,12 @@
import java.util.Locale;
import java.util.Set;
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+
import com.bakdata.conquery.models.exceptions.ParsingException;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.fasterxml.jackson.databind.annotation.JsonAppend;
-import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
@@ -23,15 +24,12 @@
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
-import javax.validation.constraints.NotEmpty;
-import javax.validation.constraints.NotNull;
-
/**
* Utility class for parsing multiple dateformats. Parsing is cached in two ways: First parsed values are cached. Second, the last used parser is cached since it's likely that it will be used again, we therefore try to use it first, then try all others.
*/
@Slf4j
@NoArgsConstructor
-public class DateFormats {
+public class DateReader {
@NotNull
@NotEmpty
@@ -61,13 +59,12 @@ public class DateFormats {
*/
@JsonIgnore
private final LoadingCache DATE_CACHE = CacheBuilder.newBuilder()
- .softValues()
- .concurrencyLevel(10)
- .initialCapacity(64000)
- .build(CacheLoader.from(this::tryParse));
+ .weakValues()
+ .concurrencyLevel(10)
+ .build(CacheLoader.from(this::tryParse));
@JsonCreator
- public DateFormats(@NotEmpty List formats) {
+ public DateReader(@NotEmpty List formats) {
final Set formatters = new HashSet<>();
@@ -82,13 +79,13 @@ public DateFormats(@NotEmpty List formats) {
* Try parsing the String value to a LocalDate.
*/
public LocalDate parseToLocalDate(String value) throws ParsingException {
- if(Strings.isNullOrEmpty(value)) {
+ if (Strings.isNullOrEmpty(value)) {
return null;
}
final LocalDate out = DATE_CACHE.getUnchecked(value);
- if(out.equals(ERROR_DATE)) {
+ if (out.equals(ERROR_DATE)) {
throw new IllegalArgumentException(String.format("Failed to parse `%s` as LocalDate.", value));
}
@@ -97,7 +94,7 @@ public LocalDate parseToLocalDate(String value) throws ParsingException {
/**
* Try and parse with the last successful parser. If not successful try and parse with other parsers and update the last successful parser.
- *
+ *
* Method is private as it is only directly accessed via the Cache.
*/
private LocalDate tryParse(String value) {
@@ -107,7 +104,8 @@ private LocalDate tryParse(String value) {
if (formatter != null) {
try {
return LocalDate.parse(value, formatter);
- } catch (DateTimeParseException e) {
+ }
+ catch (DateTimeParseException e) {
//intentionally left blank
}
}
@@ -118,7 +116,8 @@ private LocalDate tryParse(String value) {
LocalDate res = LocalDate.parse(value, format);
lastFormat.set(format);
return res;
- } catch (DateTimeParseException e) {
+ }
+ catch (DateTimeParseException e) {
//intentionally left blank
}
}
diff --git a/backend/src/test/java/com/bakdata/conquery/integration/json/AbstractQueryEngineTest.java b/backend/src/test/java/com/bakdata/conquery/integration/json/AbstractQueryEngineTest.java
index 854d05cda8..b350b108d4 100644
--- a/backend/src/test/java/com/bakdata/conquery/integration/json/AbstractQueryEngineTest.java
+++ b/backend/src/test/java/com/bakdata/conquery/integration/json/AbstractQueryEngineTest.java
@@ -47,7 +47,6 @@ public void overrideConfig(ConqueryConfig config) {
@Override
public void executeTest(StandaloneSupport standaloneSupport) throws IOException {
DatasetRegistry namespaces = standaloneSupport.getNamespace().getNamespaces();
- Dataset dataset = standaloneSupport.getDataset();
Query query = getQuery();
From 45fad7028e4596ca5c454a3d4e44716f9e3c4868 Mon Sep 17 00:00:00 2001
From: Fabian Kovacs <1553491+awildturtok@users.noreply.github.com>
Date: Fri, 16 Jul 2021 12:55:38 +0200
Subject: [PATCH 11/82] fix serialization of EntityIdMap.java using
JsonValue/JsonCreator
---
.../identifiable/mapping/EntityIdMap.java | 57 ++++++++++++-------
1 file changed, 37 insertions(+), 20 deletions(-)
diff --git a/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/EntityIdMap.java b/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/EntityIdMap.java
index f490741758..8233eb0002 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/EntityIdMap.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/EntityIdMap.java
@@ -1,17 +1,20 @@
package com.bakdata.conquery.models.identifiable.mapping;
-import java.util.Collection;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.Optional;
import com.bakdata.conquery.models.dictionary.EncodedDictionary;
import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonValue;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
+import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
@@ -26,41 +29,61 @@
public class EntityIdMap {
@Setter
+ @JsonIgnore
private EncodedDictionary dictionary;
/**
* The map from csv entity ids to external entity ids.
*/
+ @JsonIgnore
private final Map internalToPrint = new HashMap<>();
/**
* The map from external entity ids to csv entity ids.
*/
+ @JsonIgnore
private final Map external2Internal = new HashMap<>();
+ /**
+ * Helper class for serialization.
+ */
@Data
- protected static class Container {
- private final Collection> external2Internal;
+ @Getter
+ @RequiredArgsConstructor(onConstructor_ = @JsonCreator)
+ private static class Container {
+ private final List keys;
+ private final List values;
private final Map internalToPrint;
}
+ /**
+ * Constructor to deserialize from {@link Container}.
+ */
@JsonCreator
- protected EntityIdMap fromContainer(Container container) {
- final EntityIdMap out = new EntityIdMap();
+ private EntityIdMap(Container container) {
- for (Map.Entry entry : container.getExternal2Internal()) {
- out.getExternal2Internal().put(entry.getKey(), entry.getValue());
+ for (int index = 0; index < container.keys.size(); index++) {
+ getExternal2Internal().put(container.keys.get(index), container.values.get(index));
}
- out.getInternalToPrint().putAll(container.getInternalToPrint());
-
- return out;
+ getInternalToPrint().putAll(container.internalToPrint);
}
+ /**
+ * JsonValue to Serialize as {@link Container}, as Jackson cannot handle complex classes as Map-keys (ie {@link ExternalId}.
+ */
@JsonValue
- protected Container getContainer() {
- return new Container(external2Internal.entrySet(), internalToPrint);
+ private Container getContainer() {
+ final List keys = new ArrayList<>(external2Internal.size());
+ final List values = new ArrayList<>(external2Internal.size());
+
+ external2Internal.forEach((key, value) -> {
+ keys.add(key);
+ values.add(value);
+ });
+
+ return new Container(keys, values, internalToPrint);
}
/**
@@ -70,14 +93,6 @@ public EntityPrintId toExternal(String internal) {
return internalToPrint.get(internal);
}
- /**
- * Resolve an external to an internal id.
- * @param external
- */
- public Optional toInternal(String... external) {
- return Optional.ofNullable(external2Internal.get(new ExternalId(external)));
- }
-
public int resolve(String... external) {
String value = external2Internal.get(new ExternalId(external));
@@ -107,7 +122,9 @@ public void addInputMapping(String csvEntityId, String... externalEntityId) {
}
@Data
+ @RequiredArgsConstructor(onConstructor_ = @JsonCreator)
private static class ExternalId {
+ @Getter
private final String[] parts;
}
From 9871230c2619d9836ebf3b80aaab7107c93e366c Mon Sep 17 00:00:00 2001
From: Fabian Kovacs <1553491+awildturtok@users.noreply.github.com>
Date: Tue, 20 Jul 2021 15:55:03 +0200
Subject: [PATCH 12/82] some more nudging the Mapping into FrontendConfig
---
.../concept/specific/external/CQExternal.java | 55 ++++++++-
.../models/config/FrontendConfig.java | 93 ++++++++-------
.../identifiable/mapping/EntityIdMap.java | 16 ++-
.../identifiable/mapping/IdMappingConfig.java | 106 ++++--------------
.../resources/api/ConfigResource.java | 5 +-
.../identifiable/IdMapSerialisationTest.java | 2 +-
6 files changed, 131 insertions(+), 146 deletions(-)
diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java
index 88e90c99b1..3f0e336bef 100644
--- a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java
+++ b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java
@@ -11,6 +11,8 @@
import com.bakdata.conquery.io.cps.CPSType;
import com.bakdata.conquery.io.jackson.InternalOnly;
import com.bakdata.conquery.models.common.CDateSet;
+import com.bakdata.conquery.models.config.ColumnConfig;
+import com.bakdata.conquery.models.config.FrontendConfig;
import com.bakdata.conquery.models.error.ConqueryError;
import com.bakdata.conquery.models.identifiable.mapping.EntityIdMap;
import com.bakdata.conquery.models.identifiable.mapping.IdMappingConfig;
@@ -23,11 +25,13 @@
import com.bakdata.conquery.util.DateReader;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.dropwizard.validation.ValidationMethod;
+import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
+import it.unimi.dsi.fastutil.ints.IntArrayList;
+import it.unimi.dsi.fastutil.ints.IntList;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
-import org.jetbrains.annotations.NotNull;
/**
* Allows uploading lists of entities.
@@ -65,6 +69,47 @@ public QPNode createQueryPlan(QueryPlanContext context, ConceptQueryPlan plan) {
}
+ private Int2ObjectMap readDates(String[][] values, List format, DateReader dateReader, FrontendConfig.UploadConfig queryUpload) {
+ Int2ObjectMap out = new Int2ObjectAVLTreeMap<>();
+
+ DateFormat dateFormat = null;
+
+
+ IntList dateColumns = new IntArrayList(format.size());
+
+ for (int col = 0; col < format.size(); col++) {
+ String desc = format.get(col);
+
+ dateFormat = queryUpload.resolveDateFormat(desc);
+
+ if (dateFormat == null) {
+ continue;
+ }
+
+ dateColumns.add(col);
+ }
+
+ dateFormat = dateFormat == null ? DateFormat.ALL : dateFormat;
+ final int[] datePositions = dateColumns.toIntArray();
+
+ for (int row = 1; row < values.length; row++) {
+ try {
+ final CDateSet dates = dateFormat.readDates(datePositions, values[row], dateReader);
+
+ if (dates == null) {
+ continue;
+ }
+
+ out.put(row, dates);
+ }
+ catch (Exception e) {
+ log.warn("Failed to parse Date from {}", row, e);
+ }
+ }
+
+ return out;
+ }
+
@Override
public void resolve(QueryResolveContext context) {
valuesResolved = new Int2ObjectOpenHashMap<>();
@@ -76,20 +121,20 @@ public void resolve(QueryResolveContext context) {
final IdMappingConfig mappingConfig = context.getConfig().getIdMapping();
// extract dates from rows
- final Int2ObjectMap rowDates = mappingConfig.readDates(values, format, dateReader);
+ final Int2ObjectMap rowDates = readDates(values, format, dateReader, context.getConfig().getFrontend().getQueryUpload());
final int idIndex = mappingConfig.getIdIndex(format);
- final IdMappingConfig.InputMapper reader = mappingConfig.getIdMapper(format.get(idIndex));
+ final ColumnConfig reader = mappingConfig.getIdMapper(format.get(idIndex));
final List unresolved = new ArrayList<>();
// ignore the first row, because this is the header
for (int rowNum = 1; rowNum < values.length; rowNum++) {
final String[] row = values[rowNum];
- final String externalId = reader.read(row[idIndex]);
+ final EntityIdMap.ExternalId externalId = reader.read(row[idIndex]);
- final int resolvedId = mapping.resolve(reader.getName(), externalId);
+ final int resolvedId = mapping.resolve(externalId);
if (resolvedId == -1) {
unresolved.add(row);
diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java b/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java
index dc958d672f..cbef3e2457 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java
@@ -1,32 +1,29 @@
package com.bakdata.conquery.models.config;
-import java.util.ArrayList;
import java.util.List;
import java.util.Map;
-import java.util.Set;
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import com.bakdata.conquery.apiv1.query.concept.specific.external.DateColumn;
-import com.bakdata.conquery.apiv1.query.concept.specific.external.FormatColumn;
-import com.bakdata.conquery.apiv1.query.concept.specific.external.IdColumn;
-import com.bakdata.conquery.io.cps.CPSType;
-import com.bakdata.conquery.io.cps.CPSTypeIdResolver;
-import com.bakdata.conquery.models.identifiable.mapping.IdMappingConfig;
+import com.bakdata.conquery.apiv1.query.concept.specific.external.DateFormat;
import com.bakdata.conquery.util.VersionInfo;
-import com.fasterxml.jackson.annotation.JsonBackReference;
-import com.fasterxml.jackson.annotation.JsonIgnore;
import groovy.transform.ToString;
-import io.dropwizard.validation.ValidationMethod;
+import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
+import lombok.NoArgsConstructor;
import lombok.Setter;
+import lombok.With;
@ToString
@Getter
@Setter
+@With
+@AllArgsConstructor
+@NoArgsConstructor
public class FrontendConfig {
private String version = VersionInfo.INSTANCE.getProjectVersion();
@@ -36,57 +33,59 @@ public class FrontendConfig {
private UploadConfig queryUpload = new UploadConfig();
- @Getter @Setter
+ @Getter
+ @Setter
+ @With
+ @AllArgsConstructor
+ @NoArgsConstructor
public static class UploadConfig {
@NotEmpty
- private List ids = List.of(new ColumnConfig(IdColumn.HANDLE, Map.of("en", "Id"), Map.of("en", "Id of the Entity.")));
+ private List ids;
@NotNull
- private ColumnConfig dateStart =
- new ColumnConfig(DateColumn.StartDate.HANDLE, Map.of("en", "Begin"), Map.of("en", "Begin of Date-range"));
+ private ColumnConfig dateStart = ColumnConfig.builder()
+ .name(DateColumn.StartDate.HANDLE)
+ .label(Map.of("en", "Begin"))
+ .description(Map.of("en", "Begin of Date-range"))
+ .build();
@NotNull
- private ColumnConfig dateEnd =
- new ColumnConfig(DateColumn.EndDate.HANDLE, Map.of("en", "Begin"), Map.of("en", "End of Date-range"));
+ private ColumnConfig dateEnd = ColumnConfig.builder()
+ .name(DateColumn.EndDate.HANDLE)
+ .label(Map.of("en", "End"))
+ .description(Map.of("en", "End of Date-range"))
+ .build();
+
@NotNull
- private ColumnConfig dateRange =
- new ColumnConfig(DateColumn.DateRange.HANDLE, Map.of("en", "Date Range"), Map.of("en", "Full Date Range"));
+ private ColumnConfig dateRange = ColumnConfig.builder()
+ .name(DateColumn.DateRange.HANDLE)
+ .label(Map.of("en", "Date Range"))
+ .description(Map.of("en", "Full Date Range"))
+ .build();
+
@NotNull
- private ColumnConfig dateSet =
- new ColumnConfig(DateColumn.DateSet.HANDLE, Map.of("en", "Dateset"), Map.of("en", "Set of Date-Ranges"));
+ private ColumnConfig dateSet = ColumnConfig.builder()
+ .name(DateColumn.DateSet.HANDLE)
+ .label(Map.of("en", "Dateset"))
+ .description(Map.of("en", "Set of Date-Ranges"))
+ .build();
+
@NotNull
- private ColumnConfig eventDate =
- new ColumnConfig(DateColumn.EventDate.HANDLE, Map.of("en", "Event Date"), Map.of("en", "Single event"));
-
- @Data
- public static class ColumnConfig {
-
- /**
- * Name of the Column, used to resolve the specific entry at {@link IdMappingConfig#getFormatColumns()}
- */
- @NotEmpty
- private final String name;
-
- /**
- * Map of Localized labels.
- */
- private final Map label;
-
- /**
- * Map of Localized description.
- */
- private final Map description;
-
- @JsonIgnore
- @ValidationMethod
- public boolean isExistingColumnFormat() {
- return CPSTypeIdResolver.getImplementation(FormatColumn.class, name) != null;
- }
+ private ColumnConfig eventDate = ColumnConfig.builder()
+ .name(DateColumn.EventDate.HANDLE)
+ .label(Map.of("en", "Event Date"))
+ .description(Map.of("en", "Single event"))
+ .build();
+
+ public DateFormat resolveDateFormat(String handle) {
+ return DateFormat.ALL; //TODO
}
+
+
}
@Data
diff --git a/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/EntityIdMap.java b/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/EntityIdMap.java
index 8233eb0002..2737e79a1b 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/EntityIdMap.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/EntityIdMap.java
@@ -4,7 +4,6 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.Optional;
import com.bakdata.conquery.models.dictionary.EncodedDictionary;
import com.fasterxml.jackson.annotation.JsonCreator;
@@ -93,8 +92,13 @@ public EntityPrintId toExternal(String internal) {
return internalToPrint.get(internal);
}
- public int resolve(String... external) {
- String value = external2Internal.get(new ExternalId(external));
+ /**
+ * Resolve external ID to Entity Id.
+ *
+ * Return -1 when not resolved.
+ */
+ public int resolve(ExternalId key) {
+ String value = external2Internal.get(key);
if (value != null) {
return dictionary.getId(value);
@@ -112,9 +116,9 @@ public void addOutputMapping(String csvEntityId, EntityPrintId externalEntityId)
}
- public void addInputMapping(String csvEntityId, String... externalEntityId) {
+ public void addInputMapping(String csvEntityId, ExternalId externalEntityId) {
- final String prior = external2Internal.put(new ExternalId(externalEntityId), csvEntityId);
+ final String prior = external2Internal.put(externalEntityId, csvEntityId);
if (prior != null && prior.equals(csvEntityId)) {
log.warn("Duplicate mapping for {} to {} and {}", externalEntityId, csvEntityId, prior);
@@ -123,7 +127,7 @@ public void addInputMapping(String csvEntityId, String... externalEntityId) {
@Data
@RequiredArgsConstructor(onConstructor_ = @JsonCreator)
- private static class ExternalId {
+ public static class ExternalId {
@Getter
private final String[] parts;
}
diff --git a/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/IdMappingConfig.java b/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/IdMappingConfig.java
index d2462d4460..d7d84b1408 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/IdMappingConfig.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/IdMappingConfig.java
@@ -1,6 +1,5 @@
package com.bakdata.conquery.models.identifiable.mapping;
-import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -8,25 +7,17 @@
import com.bakdata.conquery.apiv1.query.concept.specific.external.DateFormat;
import com.bakdata.conquery.io.cps.CPSBase;
import com.bakdata.conquery.models.auth.entities.User;
-import com.bakdata.conquery.models.common.CDateSet;
+import com.bakdata.conquery.models.config.ColumnConfig;
import com.bakdata.conquery.models.execution.ManagedExecution;
import com.bakdata.conquery.models.worker.Namespace;
-import com.bakdata.conquery.util.DateReader;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
-import com.google.common.base.Strings;
import com.univocity.parsers.common.record.Record;
import com.univocity.parsers.csv.CsvParser;
-import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap;
-import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
-import it.unimi.dsi.fastutil.ints.IntArrayList;
-import it.unimi.dsi.fastutil.ints.IntList;
-import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.StringUtils;
@Slf4j
@@ -44,7 +35,14 @@ public class IdMappingConfig {
DateColumn.EndDate.HANDLE, DateFormat.START_END_DATE
);
- private List mappers = List.of(new InputMapper("ID", "id", "0", -1, Collections.emptyMap(), Collections.emptyMap()));
+ private List mappers = List.of(
+ ColumnConfig.builder()
+ .name("ID")
+ .mapping(ColumnConfig.Mapping.builder()
+ .field("id")
+ .resolvable(true)
+ .build())
+ .build());
private OutputMapper outputMapper = new OutputMapper();
@@ -60,11 +58,12 @@ public EntityIdMap generateIdMapping(CsvParser parser) {
while ((record = parser.parseNextRecord()) != null) {
final String id = record.getString("id");
- for (InputMapper mapper : mappers) {
- final String otherId = record.getString(mapper.getField());
- final String transformed = mapper.read(otherId);
+ for (ColumnConfig columnConfig : mappers) {
- mapping.addInputMapping(id, mapper.getName(), transformed);
+ final String otherId = record.getString(columnConfig.getMapping().getField());
+ final EntityIdMap.ExternalId transformed = columnConfig.read(otherId);
+
+ mapping.addInputMapping(id, transformed);
}
mapping.addOutputMapping(id, outputMapper.extractOutputId(record));
@@ -109,15 +108,18 @@ public EntityPrintId toExternal(String csvEntityId, Namespace namespace, IdMappi
return externalEntityId;
}
- public InputMapper getIdMapper(String name) {
- return mappers.stream().filter(mapper -> mapper.getName().equals(name)).findFirst().orElse(null);
+ public ColumnConfig getIdMapper(String name) {
+ return mappers.stream()
+ .filter(mapper -> mapper.getName().equals(name)) //TODO use map
+ .findFirst()
+ .orElse(null);
}
public int getIdIndex(List format) {
for (int index = 0; index < format.size(); index++) {
final String current = format.get(index);
- if (mappers.stream().map(InputMapper::getName).anyMatch(current::equals)) {
+ if (mappers.stream().map(ColumnConfig::getName).anyMatch(current::equals)) {
return index;
}
}
@@ -126,75 +128,7 @@ public int getIdIndex(List format) {
}
- public Int2ObjectMap readDates(String[][] values, List format, DateReader dateReader) {
- Int2ObjectMap out = new Int2ObjectAVLTreeMap<>();
-
- DateFormat dateFormat = null;
-
-
- IntList dateColumns = new IntArrayList(format.size());
-
- for (int col = 0; col < format.size(); col++) {
- String desc = format.get(col);
-
- dateFormat = resolveDateFormat(desc);
-
- if (dateFormat == null) {
- continue;
- }
-
- dateColumns.add(col);
- }
-
- dateFormat = dateFormat == null ? DateFormat.ALL : dateFormat;
- final int[] datePositions = dateColumns.toIntArray();
-
- for (int row = 1; row < values.length; row++) {
- try {
- final CDateSet dates = dateFormat.readDates(datePositions, values[row], dateReader);
- if (dates == null) {
- continue;
- }
-
- out.put(row, dates);
- }
- catch (Exception e) {
- log.warn("Failed to parse Date from {}", row, e);
- }
- }
-
- return out;
- }
-
- public DateFormat resolveDateFormat(String desc) {
- return dateFormats.get(desc);
- }
-
- @Data
- public static class InputMapper {
- private final String name;
-
- private final String field;
-
- private final String pad;
- private final int length;
-
- private final Map label;
- private final Map description;
-
- public String read(String value) {
- if (Strings.isNullOrEmpty(value)) {
- return null;
- }
-
- if (length == -1) {
- return value;
- }
-
- return StringUtils.leftPad(value, length, pad);
- }
- }
@CPSBase
@JsonTypeInfo(use = JsonTypeInfo.Id.CUSTOM, property = "type")
diff --git a/backend/src/main/java/com/bakdata/conquery/resources/api/ConfigResource.java b/backend/src/main/java/com/bakdata/conquery/resources/api/ConfigResource.java
index 89188ca248..b75f7df718 100644
--- a/backend/src/main/java/com/bakdata/conquery/resources/api/ConfigResource.java
+++ b/backend/src/main/java/com/bakdata/conquery/resources/api/ConfigResource.java
@@ -20,6 +20,9 @@ public class ConfigResource {
@GET
@Path("frontend")
public FrontendConfig getFrontendConfig() {
- return config.getFrontend();
+
+
+ return config.getFrontend()
+ .withQueryUpload(config.getFrontend().getQueryUpload().withIds(config.getIdMapping().getMappers()));
}
}
\ No newline at end of file
diff --git a/backend/src/test/java/com/bakdata/conquery/models/identifiable/IdMapSerialisationTest.java b/backend/src/test/java/com/bakdata/conquery/models/identifiable/IdMapSerialisationTest.java
index 6e3eaf0367..a92ce8f261 100644
--- a/backend/src/test/java/com/bakdata/conquery/models/identifiable/IdMapSerialisationTest.java
+++ b/backend/src/test/java/com/bakdata/conquery/models/identifiable/IdMapSerialisationTest.java
@@ -8,7 +8,7 @@ public class IdMapSerialisationTest {
public static EntityIdMap createTestPersistentMap() {
EntityIdMap entityIdMap = new EntityIdMap();
- entityIdMap.addInputMapping("test1", "a");
+ entityIdMap.addInputMapping("test1", new EntityIdMap.ExternalId(new String[]{"a"}));
entityIdMap.addOutputMapping("test2", EntityPrintId.from("c"));
From 986ec60878386f6f4f894f0599e70d4370b3e8e0 Mon Sep 17 00:00:00 2001
From: Fabian Kovacs <1553491+awildturtok@users.noreply.github.com>
Date: Tue, 20 Jul 2021 16:28:19 +0200
Subject: [PATCH 13/82] Also make OutputMapping rely on ColumnConfig
---
.../conquery/models/config/ColumnConfig.java | 83 +++++++++++++++++++
.../identifiable/mapping/IdMappingConfig.java | 56 +++++++------
2 files changed, 115 insertions(+), 24 deletions(-)
create mode 100644 backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java
diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java b/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java
new file mode 100644
index 0000000000..52b3abcdce
--- /dev/null
+++ b/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java
@@ -0,0 +1,83 @@
+package com.bakdata.conquery.models.config;
+
+import java.util.Collections;
+import java.util.Map;
+
+import javax.validation.constraints.NotEmpty;
+
+import com.bakdata.conquery.apiv1.query.concept.specific.external.FormatColumn;
+import com.bakdata.conquery.io.cps.CPSTypeIdResolver;
+import com.bakdata.conquery.models.identifiable.mapping.EntityIdMap;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.google.common.base.Strings;
+import io.dropwizard.logback.shaded.checkerframework.checker.nullness.qual.Nullable;
+import io.dropwizard.validation.ValidationMethod;
+import lombok.Builder;
+import lombok.Data;
+import org.apache.commons.lang3.StringUtils;
+
+@Data
+@Builder
+public class ColumnConfig {
+
+ @Data
+ @Builder
+ public static class Mapping {
+ private final String field;
+
+ @Builder.Default
+ private final String pad = null;
+ @Builder.Default
+ private final int length = -1;
+
+ @Builder.Default
+ private final boolean resolvable = true;
+
+ private final boolean fillAnon = false;
+
+ }
+
+ public EntityIdMap.ExternalId read(String value) {
+ if(!mapping.isResolvable()){
+ return null; //TODO throw Exception?
+ }
+
+ if (Strings.isNullOrEmpty(value)) {
+ return null;
+ }
+
+ if (getMapping().getLength() == -1) {
+ return new EntityIdMap.ExternalId(new String[]{getName(), value});
+ }
+
+ String padded = StringUtils.leftPad(value, getMapping().getLength(), getMapping().getPad());
+
+ return new EntityIdMap.ExternalId(new String[]{getName(), padded});
+
+ }
+
+
+ @NotEmpty
+ private final String name;
+
+ /**
+ * Map of Localized labels.
+ */
+ @Builder.Default
+ private final Map label = Collections.emptyMap();
+
+ /**
+ * Map of Localized description.
+ */
+ @Builder.Default
+ private final Map description = Collections.emptyMap();
+
+ @Nullable
+ private final Mapping mapping;
+
+ @JsonIgnore
+ @ValidationMethod
+ public boolean isExistingColumnFormat() {
+ return CPSTypeIdResolver.getImplementation(FormatColumn.class, name) != null;
+ }
+}
diff --git a/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/IdMappingConfig.java b/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/IdMappingConfig.java
index d7d84b1408..6a82aa2be4 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/IdMappingConfig.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/IdMappingConfig.java
@@ -1,17 +1,18 @@
package com.bakdata.conquery.models.identifiable.mapping;
+import java.util.ArrayList;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
import com.bakdata.conquery.apiv1.query.concept.specific.external.DateColumn;
import com.bakdata.conquery.apiv1.query.concept.specific.external.DateFormat;
-import com.bakdata.conquery.io.cps.CPSBase;
import com.bakdata.conquery.models.auth.entities.User;
import com.bakdata.conquery.models.config.ColumnConfig;
import com.bakdata.conquery.models.execution.ManagedExecution;
import com.bakdata.conquery.models.worker.Namespace;
import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.univocity.parsers.common.record.Record;
import com.univocity.parsers.csv.CsvParser;
import lombok.Getter;
@@ -42,9 +43,9 @@ public class IdMappingConfig {
.field("id")
.resolvable(true)
.build())
- .build());
-
- private OutputMapper outputMapper = new OutputMapper();
+ .build()
+ );
+ private List idFieldsCached;
/**
* Read incoming CSV-file extracting Id-Mappings for in and Output.
@@ -55,29 +56,53 @@ public EntityIdMap generateIdMapping(CsvParser parser) {
Record record;
+
while ((record = parser.parseNextRecord()) != null) {
+ List idParts = new ArrayList<>(mappers.size());
+
final String id = record.getString("id");
for (ColumnConfig columnConfig : mappers) {
final String otherId = record.getString(columnConfig.getMapping().getField());
+
+ idParts.add(otherId);
+
+ if (otherId == null) {
+ continue;
+ }
+
+ if (!columnConfig.getMapping().isResolvable()) {
+ continue;
+ }
+
final EntityIdMap.ExternalId transformed = columnConfig.read(otherId);
mapping.addInputMapping(id, transformed);
}
- mapping.addOutputMapping(id, outputMapper.extractOutputId(record));
+ mapping.addOutputMapping(id, new EntityPrintId(idParts.toArray(new String[0])));
}
return mapping;
}
+
+
/**
* Headers for Output CSV.
*/
@JsonIgnore
public List getPrintIdFields() {
- return List.of(outputMapper.getHeaders());
+ if(idFieldsCached == null) {
+ idFieldsCached = mappers.stream()
+ .map(ColumnConfig::getMapping)
+ .filter(Objects::nonNull)
+ .map(ColumnConfig.Mapping::getField)
+ .collect(Collectors.toList());
+ }
+
+ return idFieldsCached;
}
/**
@@ -126,21 +151,4 @@ public int getIdIndex(List format) {
return -1;
}
-
-
-
-
- @CPSBase
- @JsonTypeInfo(use = JsonTypeInfo.Id.CUSTOM, property = "type")
- @NoArgsConstructor
- public static class OutputMapper {
- @JsonIgnore
- public String[] getHeaders() {
- return new String[]{"result"};
- }
-
- public EntityPrintId extractOutputId(Record record) {
- return new EntityPrintId(new String[]{record.getString("id")});
- }
- }
}
From 32f832dd15fab9772be6938e99325c2ca20a4689 Mon Sep 17 00:00:00 2001
From: Fabian Kovacs <1553491+awildturtok@users.noreply.github.com>
Date: Fri, 23 Jul 2021 14:47:03 +0200
Subject: [PATCH 14/82] migrate all usage to queryUpload config also implement
resolving of DateFormat
---
.../concept/specific/external/CQExternal.java | 31 ++---
.../concept/specific/external/DateColumn.java | 4 +-
.../concept/specific/external/DateFormat.java | 40 ++++++-
.../conquery/io/result/ResultUtil.java | 4 +-
.../io/result/arrow/ResultArrowProcessor.java | 40 +++----
.../io/result/csv/ResultCsvProcessor.java | 7 +-
.../io/result/excel/ResultExcelProcessor.java | 12 +-
.../models/config/ConqueryConfig.java | 3 -
.../models/config/FrontendConfig.java | 102 +++++++++++++++--
.../conquery/models/config/NoIdMapping.java | 23 ----
.../models/config/SimpleIdMapping.java | 20 ----
.../identifiable/mapping/EntityIdMap.java | 43 +++++++
.../identifiable/mapping/IdMappingConfig.java | 107 +-----------------
.../conquery/models/query/ManagedQuery.java | 6 +-
.../admin/rest/AdminDatasetProcessor.java | 2 +-
.../resources/api/ConfigResource.java | 3 +-
.../json/AbstractQueryEngineTest.java | 13 +--
.../conquery/integration/json/FormTest.java | 7 +-
18 files changed, 228 insertions(+), 239 deletions(-)
delete mode 100644 backend/src/main/java/com/bakdata/conquery/models/config/NoIdMapping.java
delete mode 100644 backend/src/main/java/com/bakdata/conquery/models/config/SimpleIdMapping.java
diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java
index 3f0e336bef..9cee81794e 100644
--- a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java
+++ b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java
@@ -4,6 +4,8 @@
import java.util.Arrays;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
import javax.validation.constraints.NotEmpty;
@@ -72,25 +74,14 @@ public QPNode createQueryPlan(QueryPlanContext context, ConceptQueryPlan plan) {
private Int2ObjectMap readDates(String[][] values, List format, DateReader dateReader, FrontendConfig.UploadConfig queryUpload) {
Int2ObjectMap out = new Int2ObjectAVLTreeMap<>();
- DateFormat dateFormat = null;
+ List dateFormats = format.stream().map(queryUpload::resolveDateFormat).collect(Collectors.toList());
- IntList dateColumns = new IntArrayList(format.size());
+ //validate structures
- for (int col = 0; col < format.size(); col++) {
- String desc = format.get(col);
+ final int[] datePositions = DateFormat.select(dateFormats);
- dateFormat = queryUpload.resolveDateFormat(desc);
-
- if (dateFormat == null) {
- continue;
- }
-
- dateColumns.add(col);
- }
-
- dateFormat = dateFormat == null ? DateFormat.ALL : dateFormat;
- final int[] datePositions = dateColumns.toIntArray();
+ DateFormat dateFormat = datePositions.length > 0 ? dateFormats.get(datePositions[0]) : DateFormat.ALL;
for (int row = 1; row < values.length; row++) {
try {
@@ -118,14 +109,14 @@ public void resolve(QueryResolveContext context) {
final DateReader dateReader = context.getConfig().getPreprocessor().getParsers().getDateReader();
- final IdMappingConfig mappingConfig = context.getConfig().getIdMapping();
-
// extract dates from rows
- final Int2ObjectMap rowDates = readDates(values, format, dateReader, context.getConfig().getFrontend().getQueryUpload());
+ final FrontendConfig.UploadConfig uploadConfig = context.getConfig().getFrontend().getQueryUpload();
+
+ final Int2ObjectMap rowDates = readDates(values, format, dateReader, uploadConfig);
- final int idIndex = mappingConfig.getIdIndex(format);
+ final int idIndex = uploadConfig.getIdIndex(format);
- final ColumnConfig reader = mappingConfig.getIdMapper(format.get(idIndex));
+ final ColumnConfig reader = uploadConfig.getIdMapper(format.get(idIndex));
final List unresolved = new ArrayList<>();
diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateColumn.java b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateColumn.java
index 679189365c..da784920b5 100644
--- a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateColumn.java
+++ b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateColumn.java
@@ -45,7 +45,7 @@ public static class StartDate extends DateColumn {
public static String HANDLE = "START_DATE";
public StartDate() {
- super(DateFormat.START_END_DATE);
+ super(DateFormat.START_DATE);
}
}
@@ -53,7 +53,7 @@ public static class EndDate extends DateColumn {
public static String HANDLE = "END_DATE";
public EndDate() {
- super(DateFormat.START_END_DATE);
+ super(DateFormat.END_DATE);
}
}
}
diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateFormat.java b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateFormat.java
index 96461ebfaf..d172a177c3 100644
--- a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateFormat.java
+++ b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateFormat.java
@@ -2,6 +2,9 @@
import java.time.LocalDate;
import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
import com.bakdata.conquery.models.common.CDateSet;
import com.bakdata.conquery.models.common.daterange.CDateRange;
@@ -17,10 +20,25 @@ public CDateSet readDates(int[] formats, String[] row, DateReader dateReader) {
return CDateSet.create(Collections.singleton(CDateRange.exactly(dateReader.parseToLocalDate(row[index]))));
}
},
- START_END_DATE {
+ END_DATE {
@Override
public CDateSet readDates(int[] formats, String[] row, DateReader dateReader) {
+ if (formats.length == 1) {
+ return CDateSet.create(CDateRange.atMost(dateReader.parseToLocalDate(row[0])));
+ }
+
+ return END_DATE.readDates(formats, row, dateReader);
+ }
+ },
+ START_DATE {
+ @Override
+ public CDateSet readDates(int[] formats, String[] row, DateReader dateReader) {
+
+ if (formats.length == 1) {
+ return CDateSet.create(CDateRange.atLeast(dateReader.parseToLocalDate(row[0])));
+ }
+
final int startIndex = formats[0];
final int endIndex = formats[1];
@@ -59,4 +77,24 @@ public CDateSet readDates(int[] formats, String[] row, DateReader dateReader) {
public abstract CDateSet readDates(int[] formats, String[] row, DateReader dateReader);
+ public static int[] select(List dateFormat) {
+ final List distinct = dateFormat.stream().filter(Objects::nonNull).distinct().sorted().collect(Collectors.toList());
+
+ // => ALL
+ if (distinct.isEmpty()) {
+ return new int[0];
+ }
+
+
+ if (distinct.size() == 1) {
+ return new int[]{dateFormat.indexOf(distinct.get(0))};
+ }
+
+ if (distinct.size() == 2 && distinct.get(0).equals(START_DATE) && distinct.get(1).equals(END_DATE)) {
+ return new int[]{dateFormat.indexOf(START_DATE), dateFormat.indexOf(END_DATE)};
+ }
+
+ throw new IllegalStateException("can only handle 1 or 2 format columns"); //TODO map error
+
+ }
}
diff --git a/backend/src/main/java/com/bakdata/conquery/io/result/ResultUtil.java b/backend/src/main/java/com/bakdata/conquery/io/result/ResultUtil.java
index cc0b805c12..974fd57aec 100644
--- a/backend/src/main/java/com/bakdata/conquery/io/result/ResultUtil.java
+++ b/backend/src/main/java/com/bakdata/conquery/io/result/ResultUtil.java
@@ -24,11 +24,11 @@
public class ResultUtil {
- public static EntityPrintId createId(Namespace namespace, EntityResult cer, IdMappingConfig idMappingConfig, IdMappingState mappingState) {
+ public static EntityPrintId createId(Namespace namespace, EntityResult cer, IdMappingState mappingState) {
EncodedDictionary dict = namespace.getStorage().getPrimaryDictionary();
final EntityIdMap idMapping = namespace.getStorage().getIdMapping();
- return idMappingConfig.toExternal(
+ return IdMappingConfig.toExternal(
dict.getElement(cer.getEntityId()), namespace,
mappingState, idMapping
);
diff --git a/backend/src/main/java/com/bakdata/conquery/io/result/arrow/ResultArrowProcessor.java b/backend/src/main/java/com/bakdata/conquery/io/result/arrow/ResultArrowProcessor.java
index 769dc1691f..237d56e4da 100644
--- a/backend/src/main/java/com/bakdata/conquery/io/result/arrow/ResultArrowProcessor.java
+++ b/backend/src/main/java/com/bakdata/conquery/io/result/arrow/ResultArrowProcessor.java
@@ -3,15 +3,10 @@
import static com.bakdata.conquery.io.result.ResultUtil.makeResponseWithFileName;
import static com.bakdata.conquery.io.result.arrow.ArrowRenderer.renderToStream;
import static com.bakdata.conquery.models.auth.AuthorizationHelper.authorizeDownloadDatasets;
-import static com.bakdata.conquery.resources.ResourceConstants.FILE_EXTENTION_ARROW_FILE;
-import static com.bakdata.conquery.resources.ResourceConstants.FILE_EXTENTION_ARROW_STREAM;
-import java.io.IOException;
import java.io.OutputStream;
-import java.nio.channels.Channels;
import java.util.function.Function;
-import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.StreamingOutput;
@@ -32,13 +27,9 @@
import com.bakdata.conquery.models.worker.DatasetRegistry;
import com.bakdata.conquery.models.worker.Namespace;
import com.bakdata.conquery.util.io.ConqueryMDC;
-import lombok.RequiredArgsConstructor;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.apache.arrow.vector.VectorSchemaRoot;
-import org.apache.arrow.vector.dictionary.DictionaryProvider;
-import org.apache.arrow.vector.ipc.ArrowFileWriter;
-import org.apache.arrow.vector.ipc.ArrowStreamWriter;
import org.apache.arrow.vector.ipc.ArrowWriter;
import org.apache.http.HttpStatus;
@@ -75,29 +66,24 @@ public static & SingleTableResult> Response getAr
}
// Get the locale extracted by the LocaleFilter
- IdMappingConfig idMappingConf = config.getIdMapping();
- IdMappingState mappingState = config.getIdMapping().initToExternal(user, exec);
+ IdMappingState mappingState = IdMappingConfig.initToExternal(user, exec);
PrintSettings settings = new PrintSettings(
pretty,
I18n.LOCALE.get(),
datasetRegistry,
config,
- (EntityResult cer) -> ResultUtil.createId(namespace, cer, config.getIdMapping(), mappingState));
-
-
- StreamingOutput out = new StreamingOutput() {
-
- @Override
- public void write(OutputStream output) throws IOException, WebApplicationException {
- renderToStream(writerProducer.apply(output),
- settings,
- config.getArrow().getBatchSize(),
- idMappingConf.getPrintIdFields(),
- exec.getResultInfo(),
- exec.streamResults());
-
- }
- };
+ (EntityResult cer) -> ResultUtil.createId(namespace, cer, mappingState)
+ );
+
+
+ StreamingOutput out = output -> renderToStream(
+ writerProducer.apply(output),
+ settings,
+ config.getArrow().getBatchSize(),
+ config.getFrontend().getQueryUpload().getPrintIdFields(),
+ exec.getResultInfo(),
+ exec.streamResults()
+ );
return makeResponseWithFileName(out, exec.getLabelWithoutAutoLabelSuffix(), fileExtension);
}
diff --git a/backend/src/main/java/com/bakdata/conquery/io/result/csv/ResultCsvProcessor.java b/backend/src/main/java/com/bakdata/conquery/io/result/csv/ResultCsvProcessor.java
index b9e9b81ccc..3f6ac4b16b 100644
--- a/backend/src/main/java/com/bakdata/conquery/io/result/csv/ResultCsvProcessor.java
+++ b/backend/src/main/java/com/bakdata/conquery/io/result/csv/ResultCsvProcessor.java
@@ -19,6 +19,7 @@
import com.bakdata.conquery.models.datasets.Dataset;
import com.bakdata.conquery.models.execution.ManagedExecution;
import com.bakdata.conquery.models.i18n.I18n;
+import com.bakdata.conquery.models.identifiable.mapping.IdMappingConfig;
import com.bakdata.conquery.models.identifiable.mapping.IdMappingState;
import com.bakdata.conquery.models.query.PrintSettings;
import com.bakdata.conquery.models.query.SingleTableResult;
@@ -49,7 +50,7 @@ public & SingleTableResult> Response getResult(Us
// Check if user is permitted to download on all datasets that were referenced by the query
authorizeDownloadDatasets(user, exec);
- IdMappingState mappingState = config.getIdMapping().initToExternal(user, exec);
+ IdMappingState mappingState = IdMappingConfig.initToExternal(user, exec);
// Get the locale extracted by the LocaleFilter
PrintSettings settings = new PrintSettings(
@@ -57,7 +58,7 @@ public & SingleTableResult> Response getResult(Us
I18n.LOCALE.get(),
datasetRegistry,
config,
- cer -> ResultUtil.createId(namespace, cer, config.getIdMapping(), mappingState)
+ cer -> ResultUtil.createId(namespace, cer, mappingState)
);
Charset charset = determineCharset(userAgent, queryCharset);
@@ -65,7 +66,7 @@ public & SingleTableResult> Response getResult(Us
StreamingOutput out = os -> {
try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, charset))) {
CsvRenderer renderer = new CsvRenderer(config.getCsv().createWriter(writer), settings);
- renderer.toCSV(config.getIdMapping().getPrintIdFields(), exec.getResultInfo(), exec.streamResults());
+ renderer.toCSV(config.getFrontend().getQueryUpload().getPrintIdFields(), exec.getResultInfo(), exec.streamResults());
}
catch (EofException e) {
log.info("User canceled download");
diff --git a/backend/src/main/java/com/bakdata/conquery/io/result/excel/ResultExcelProcessor.java b/backend/src/main/java/com/bakdata/conquery/io/result/excel/ResultExcelProcessor.java
index 5ce26459d5..86e08ea07d 100644
--- a/backend/src/main/java/com/bakdata/conquery/io/result/excel/ResultExcelProcessor.java
+++ b/backend/src/main/java/com/bakdata/conquery/io/result/excel/ResultExcelProcessor.java
@@ -1,7 +1,6 @@
package com.bakdata.conquery.io.result.excel;
import com.bakdata.conquery.io.result.ResultUtil;
-import com.bakdata.conquery.io.result.excel.ExcelRenderer;
import com.bakdata.conquery.models.auth.entities.User;
import com.bakdata.conquery.models.auth.permissions.Ability;
import com.bakdata.conquery.models.config.ConqueryConfig;
@@ -9,7 +8,6 @@
import com.bakdata.conquery.models.execution.ManagedExecution;
import com.bakdata.conquery.models.i18n.I18n;
import com.bakdata.conquery.models.identifiable.ids.specific.DatasetId;
-import com.bakdata.conquery.models.identifiable.ids.specific.ManagedExecutionId;
import com.bakdata.conquery.models.identifiable.mapping.IdMappingConfig;
import com.bakdata.conquery.models.identifiable.mapping.IdMappingState;
import com.bakdata.conquery.models.query.PrintSettings;
@@ -17,15 +15,12 @@
import com.bakdata.conquery.models.query.results.EntityResult;
import com.bakdata.conquery.models.worker.DatasetRegistry;
import com.bakdata.conquery.models.worker.Namespace;
-import com.bakdata.conquery.util.ResourceUtil;
import com.bakdata.conquery.util.io.ConqueryMDC;
import lombok.RequiredArgsConstructor;
-import javax.ws.rs.BadRequestException;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.StreamingOutput;
-import static com.bakdata.conquery.io.result.ResultUtil.checkSingleTableResult;
import static com.bakdata.conquery.io.result.ResultUtil.makeResponseWithFileName;
@RequiredArgsConstructor
@@ -44,20 +39,19 @@ public & SingleTableResult> Response getExcelResu
user.authorize(dataset, Ability.DOWNLOAD);
user.authorize(exec, Ability.READ);
- IdMappingConfig idMapping = config.getIdMapping();
- IdMappingState mappingState = idMapping.initToExternal(user, exec);
+ IdMappingState mappingState = IdMappingConfig.initToExternal(user, exec);
PrintSettings settings = new PrintSettings(
pretty,
I18n.LOCALE.get(),
datasetRegistry,
config,
- (EntityResult cer) -> ResultUtil.createId(namespace, cer, idMapping, mappingState));
+ (EntityResult cer) -> ResultUtil.createId(namespace, cer, mappingState));
ExcelRenderer excelRenderer = new ExcelRenderer(config.getExcel());
StreamingOutput out = output -> excelRenderer.renderToStream(
settings,
- idMapping.getPrintIdFields(),
+ config.getFrontend().getQueryUpload().getPrintIdFields(),
(ManagedExecution> & SingleTableResult)exec,
output
);
diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/ConqueryConfig.java b/backend/src/main/java/com/bakdata/conquery/models/config/ConqueryConfig.java
index 6e1275af23..54e931acc4 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/config/ConqueryConfig.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/config/ConqueryConfig.java
@@ -80,9 +80,6 @@ public class ConqueryConfig extends Configuration {
private ConqueryMetricsConfig metricsConfig = new ConqueryMetricsConfig();
- @NotNull
- @Valid
- private IdMappingConfig idMapping = new NoIdMapping();
@Valid
@NotNull
private List authentication = List.of(new DevAuthConfig());
diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java b/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java
index cbef3e2457..134edcde2e 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java
@@ -1,22 +1,28 @@
package com.bakdata.conquery.models.config;
+import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
-import com.bakdata.conquery.apiv1.query.concept.specific.external.DateColumn;
import com.bakdata.conquery.apiv1.query.concept.specific.external.DateFormat;
import com.bakdata.conquery.util.VersionInfo;
+import com.fasterxml.jackson.annotation.JsonIgnore;
import groovy.transform.ToString;
+import io.dropwizard.validation.ValidationMethod;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.With;
+import lombok.extern.slf4j.Slf4j;
@ToString
@Getter
@@ -24,6 +30,7 @@
@With
@AllArgsConstructor
@NoArgsConstructor
+@Slf4j
public class FrontendConfig {
private String version = VersionInfo.INSTANCE.getProjectVersion();
@@ -41,18 +48,64 @@ public class FrontendConfig {
public static class UploadConfig {
@NotEmpty
- private List ids;
+ private List ids = List.of(
+ ColumnConfig.builder()
+ .name("ID")
+ .mapping(ColumnConfig.Mapping.builder()
+ .field("id")
+ .resolvable(true)
+ .build())
+ .build()
+ );
+
+ @JsonIgnore
+ private List idFieldsCached;
+
+ /**
+ * Headers for Output CSV.
+ */
+ @JsonIgnore
+ public List getPrintIdFields() {
+ if (idFieldsCached == null) {
+ idFieldsCached = ids.stream()
+ .map(ColumnConfig::getMapping)
+ .filter(Objects::nonNull)
+ .map(ColumnConfig.Mapping::getField)
+ .collect(Collectors.toList());
+ }
+
+ return idFieldsCached;
+ }
+
+ public ColumnConfig getIdMapper(String name) {
+ return ids.stream()
+ .filter(mapper -> mapper.getName().equals(name)) //TODO use map
+ .findFirst()
+ .orElse(null);
+ }
+
+ public int getIdIndex(List format) {
+ for (int index = 0; index < format.size(); index++) {
+ final String current = format.get(index);
+
+ if (ids.stream().map(ColumnConfig::getName).anyMatch(current::equals)) {
+ return index;
+ }
+ }
+
+ return -1;
+ }
@NotNull
private ColumnConfig dateStart = ColumnConfig.builder()
- .name(DateColumn.StartDate.HANDLE)
+ .name(DateFormat.START_DATE.name())
.label(Map.of("en", "Begin"))
.description(Map.of("en", "Begin of Date-range"))
.build();
@NotNull
private ColumnConfig dateEnd = ColumnConfig.builder()
- .name(DateColumn.EndDate.HANDLE)
+ .name(DateFormat.END_DATE.name())
.label(Map.of("en", "End"))
.description(Map.of("en", "End of Date-range"))
.build();
@@ -60,7 +113,7 @@ public static class UploadConfig {
@NotNull
private ColumnConfig dateRange = ColumnConfig.builder()
- .name(DateColumn.DateRange.HANDLE)
+ .name(DateFormat.DATE_RANGE.name())
.label(Map.of("en", "Date Range"))
.description(Map.of("en", "Full Date Range"))
.build();
@@ -68,7 +121,7 @@ public static class UploadConfig {
@NotNull
private ColumnConfig dateSet = ColumnConfig.builder()
- .name(DateColumn.DateSet.HANDLE)
+ .name(DateFormat.DATE_SET.name())
.label(Map.of("en", "Dateset"))
.description(Map.of("en", "Set of Date-Ranges"))
.build();
@@ -76,13 +129,46 @@ public static class UploadConfig {
@NotNull
private ColumnConfig eventDate = ColumnConfig.builder()
- .name(DateColumn.EventDate.HANDLE)
+ .name(DateFormat.EVENT_DATE.name())
.label(Map.of("en", "Event Date"))
.description(Map.of("en", "Single event"))
.build();
+ @ValidationMethod(message = "Duplicate Claims for Mapping Columns.")
+ @JsonIgnore
+ public boolean isAllColsUnique() {
+ Map dupes = new HashMap<>();
+
+ final ArrayList candidates = new ArrayList<>(ids);
+ candidates.addAll(List.of(dateStart, dateEnd, dateSet, dateRange, eventDate));
+
+ for (ColumnConfig config : candidates) {
+ final ColumnConfig prior = dupes.put(config.getName(), config);
+
+ if (prior == null) {
+ continue;
+ }
+
+ log.error("Duplicate claims for Name = `{}` ({} / {})", config.getName(), config, prior);
+ return false;
+ }
+
+ return true;
+ }
+
+ @ValidationMethod(message = "Not all Id-Columns have mappings.")
+ @JsonIgnore
+ public boolean isIdColsHaveMapping() {
+ return ids.stream().map(ColumnConfig::getMapping).allMatch(Objects::nonNull);
+ }
+
public DateFormat resolveDateFormat(String handle) {
- return DateFormat.ALL; //TODO
+ try {
+ return DateFormat.valueOf(handle);
+ }
+ catch (IllegalArgumentException e) {
+ return null; // Does not exist
+ }
}
diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/NoIdMapping.java b/backend/src/main/java/com/bakdata/conquery/models/config/NoIdMapping.java
deleted file mode 100644
index f7a84dbb06..0000000000
--- a/backend/src/main/java/com/bakdata/conquery/models/config/NoIdMapping.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.bakdata.conquery.models.config;
-
-import java.util.Arrays;
-import java.util.List;
-
-import com.bakdata.conquery.io.cps.CPSType;
-import com.bakdata.conquery.models.identifiable.mapping.IdMappingConfig;
-import com.bakdata.conquery.models.identifiable.mapping.EntityIdMap;
-import com.univocity.parsers.common.record.Record;
-
-/**
- * Disables Id-Mapping completely.
- */
-public class NoIdMapping extends IdMappingConfig {
- private static final String[] HEADER = new String[]{"result"};
-
-
- @Override
- public List getPrintIdFields() {
- return Arrays.asList(HEADER);
- }
-
-}
diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/SimpleIdMapping.java b/backend/src/main/java/com/bakdata/conquery/models/config/SimpleIdMapping.java
deleted file mode 100644
index 597b3d941a..0000000000
--- a/backend/src/main/java/com/bakdata/conquery/models/config/SimpleIdMapping.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.bakdata.conquery.models.config;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import com.bakdata.conquery.apiv1.query.concept.specific.external.FormatColumn;
-import com.bakdata.conquery.apiv1.query.concept.specific.external.IdColumn;
-import com.bakdata.conquery.io.cps.CPSType;
-import com.bakdata.conquery.models.identifiable.mapping.EntityIdMap;
-import com.bakdata.conquery.models.identifiable.mapping.EntityPrintId;
-import com.bakdata.conquery.models.identifiable.mapping.IdMappingConfig;
-import com.univocity.parsers.common.record.Record;
-
-/**
- * Maps input to itself for upload.
- */
-public class SimpleIdMapping extends NoIdMapping {
-
-
-}
diff --git a/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/EntityIdMap.java b/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/EntityIdMap.java
index 2737e79a1b..5cbbeee4df 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/EntityIdMap.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/EntityIdMap.java
@@ -5,10 +5,13 @@
import java.util.List;
import java.util.Map;
+import com.bakdata.conquery.models.config.ColumnConfig;
import com.bakdata.conquery.models.dictionary.EncodedDictionary;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonValue;
+import com.univocity.parsers.common.record.Record;
+import com.univocity.parsers.csv.CsvParser;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Getter;
@@ -43,6 +46,46 @@ public class EntityIdMap {
@JsonIgnore
private final Map external2Internal = new HashMap<>();
+ /**
+ * Read incoming CSV-file extracting Id-Mappings for in and Output.
+ */
+ public static EntityIdMap generateIdMapping(CsvParser parser, List mappers) {
+
+ EntityIdMap mapping = new EntityIdMap();
+
+ Record record;
+
+
+ while ((record = parser.parseNextRecord()) != null) {
+ List idParts = new ArrayList<>(mappers.size());
+
+ final String id = record.getString("id");
+
+ for (ColumnConfig columnConfig : mappers) {
+
+ final String otherId = record.getString(columnConfig.getMapping().getField());
+
+ idParts.add(otherId);
+
+ if (otherId == null) {
+ continue;
+ }
+
+ if (!columnConfig.getMapping().isResolvable()) {
+ continue;
+ }
+
+ final ExternalId transformed = columnConfig.read(otherId);
+
+ mapping.addInputMapping(id, transformed);
+ }
+
+ mapping.addOutputMapping(id, new EntityPrintId(idParts.toArray(new String[0])));
+ }
+
+ return mapping;
+ }
+
/**
* Helper class for serialization.
diff --git a/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/IdMappingConfig.java b/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/IdMappingConfig.java
index 6a82aa2be4..6ed66d726c 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/IdMappingConfig.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/IdMappingConfig.java
@@ -2,19 +2,14 @@
import java.util.ArrayList;
import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.stream.Collectors;
-import com.bakdata.conquery.apiv1.query.concept.specific.external.DateColumn;
-import com.bakdata.conquery.apiv1.query.concept.specific.external.DateFormat;
import com.bakdata.conquery.models.auth.entities.User;
import com.bakdata.conquery.models.config.ColumnConfig;
import com.bakdata.conquery.models.execution.ManagedExecution;
import com.bakdata.conquery.models.worker.Namespace;
-import com.fasterxml.jackson.annotation.JsonIgnore;
import com.univocity.parsers.common.record.Record;
import com.univocity.parsers.csv.CsvParser;
+import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@@ -22,94 +17,17 @@
@Slf4j
-@NoArgsConstructor
+@NoArgsConstructor(access = AccessLevel.NONE)
@Setter
@Getter
public class IdMappingConfig {
- public final Map dateFormats = Map.of(
- DateColumn.DateSet.HANDLE, DateFormat.DATE_SET,
- DateColumn.DateRange.HANDLE, DateFormat.DATE_RANGE,
- DateColumn.EventDate.HANDLE, DateFormat.EVENT_DATE,
- DateColumn.StartDate.HANDLE, DateFormat.START_END_DATE,
- DateColumn.EndDate.HANDLE, DateFormat.START_END_DATE
- );
-
- private List mappers = List.of(
- ColumnConfig.builder()
- .name("ID")
- .mapping(ColumnConfig.Mapping.builder()
- .field("id")
- .resolvable(true)
- .build())
- .build()
- );
- private List idFieldsCached;
-
- /**
- * Read incoming CSV-file extracting Id-Mappings for in and Output.
- */
- public EntityIdMap generateIdMapping(CsvParser parser) {
-
- EntityIdMap mapping = new EntityIdMap();
-
- Record record;
-
-
- while ((record = parser.parseNextRecord()) != null) {
- List idParts = new ArrayList<>(mappers.size());
-
- final String id = record.getString("id");
-
- for (ColumnConfig columnConfig : mappers) {
-
- final String otherId = record.getString(columnConfig.getMapping().getField());
-
- idParts.add(otherId);
-
- if (otherId == null) {
- continue;
- }
-
- if (!columnConfig.getMapping().isResolvable()) {
- continue;
- }
-
- final EntityIdMap.ExternalId transformed = columnConfig.read(otherId);
-
- mapping.addInputMapping(id, transformed);
- }
-
- mapping.addOutputMapping(id, new EntityPrintId(idParts.toArray(new String[0])));
- }
-
- return mapping;
- }
-
-
-
- /**
- * Headers for Output CSV.
- */
- @JsonIgnore
- public List getPrintIdFields() {
- if(idFieldsCached == null) {
- idFieldsCached = mappers.stream()
- .map(ColumnConfig::getMapping)
- .filter(Objects::nonNull)
- .map(ColumnConfig.Mapping::getField)
- .collect(Collectors.toList());
- }
-
- return idFieldsCached;
- }
-
/**
* Is called once before a mapping is used before a query result is created to
* allow the mapping to have state information.
*/
- public IdMappingState initToExternal(User user, ManagedExecution> execution) {
+ public static IdMappingState initToExternal(User user, ManagedExecution> execution) {
// This mapping does not need a per-query state, so we return an immutable empty map.
return null;
}
@@ -117,7 +35,7 @@ public IdMappingState initToExternal(User user, ManagedExecution> execution) {
/**
* Converts the internal ID to the an external.
*/
- public EntityPrintId toExternal(String csvEntityId, Namespace namespace, IdMappingState state, EntityIdMap mapping) {
+ public static EntityPrintId toExternal(String csvEntityId, Namespace namespace, IdMappingState state, EntityIdMap mapping) {
// The state may be uses by implementations of this class
if (mapping == null) {
@@ -133,22 +51,5 @@ public EntityPrintId toExternal(String csvEntityId, Namespace namespace, IdMappi
return externalEntityId;
}
- public ColumnConfig getIdMapper(String name) {
- return mappers.stream()
- .filter(mapper -> mapper.getName().equals(name)) //TODO use map
- .findFirst()
- .orElse(null);
- }
-
- public int getIdIndex(List format) {
- for (int index = 0; index < format.size(); index++) {
- final String current = format.get(index);
-
- if (mappers.stream().map(ColumnConfig::getName).anyMatch(current::equals)) {
- return index;
- }
- }
- return -1;
- }
}
diff --git a/backend/src/main/java/com/bakdata/conquery/models/query/ManagedQuery.java b/backend/src/main/java/com/bakdata/conquery/models/query/ManagedQuery.java
index e2c5a96dcf..c8b4c33517 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/query/ManagedQuery.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/query/ManagedQuery.java
@@ -95,7 +95,7 @@ protected void doInitExecutable(@NonNull DatasetRegistry namespaces, ConqueryCon
involvedWorkers = namespace.getWorkers().size();
- query.resolve(new QueryResolveContext(getDataset(), namespaces, config,null));
+ query.resolve(new QueryResolveContext(getDataset(), namespaces, config, null));
}
@Override
@@ -161,13 +161,15 @@ protected void setAdditionalFieldsForStatusWithColumnDescription(@NonNull MetaSt
public List generateColumnDescriptions(DatasetRegistry datasetRegistry) {
Preconditions.checkArgument(isInitialized(), "The execution must have been initialized first");
List columnDescriptions = new ArrayList<>();
+
// First add the id columns to the descriptor list. The are the first columns
- for (String header : config.getIdMapping().getPrintIdFields()) {
+ for (String header : config.getFrontend().getQueryUpload().getPrintIdFields()) {
columnDescriptions.add(ColumnDescriptor.builder()
.label(header)
.type(ResultType.IdT.INSTANCE.typeInfo())
.build());
}
+
// Then all columns that originate from selects and static aggregators
PrintSettings settings = new PrintSettings(true, I18n.LOCALE.get(), datasetRegistry, config, null);
diff --git a/backend/src/main/java/com/bakdata/conquery/resources/admin/rest/AdminDatasetProcessor.java b/backend/src/main/java/com/bakdata/conquery/resources/admin/rest/AdminDatasetProcessor.java
index 1c075c5ad2..aafaf1dee9 100644
--- a/backend/src/main/java/com/bakdata/conquery/resources/admin/rest/AdminDatasetProcessor.java
+++ b/backend/src/main/java/com/bakdata/conquery/resources/admin/rest/AdminDatasetProcessor.java
@@ -260,7 +260,7 @@ public void setIdMapping(InputStream data, Namespace namespace) {
parser.beginParsing(data);
- EntityIdMap mapping = config.getIdMapping().generateIdMapping(parser);
+ EntityIdMap mapping = EntityIdMap.generateIdMapping(parser, config.getFrontend().getQueryUpload().getIds());
namespace.getStorage().updateIdMapping(mapping);
}
diff --git a/backend/src/main/java/com/bakdata/conquery/resources/api/ConfigResource.java b/backend/src/main/java/com/bakdata/conquery/resources/api/ConfigResource.java
index b75f7df718..a7655e84e3 100644
--- a/backend/src/main/java/com/bakdata/conquery/resources/api/ConfigResource.java
+++ b/backend/src/main/java/com/bakdata/conquery/resources/api/ConfigResource.java
@@ -22,7 +22,6 @@ public class ConfigResource {
public FrontendConfig getFrontendConfig() {
- return config.getFrontend()
- .withQueryUpload(config.getFrontend().getQueryUpload().withIds(config.getIdMapping().getMappers()));
+ return config.getFrontend();
}
}
\ No newline at end of file
diff --git a/backend/src/test/java/com/bakdata/conquery/integration/json/AbstractQueryEngineTest.java b/backend/src/test/java/com/bakdata/conquery/integration/json/AbstractQueryEngineTest.java
index b350b108d4..f98a1bea0b 100644
--- a/backend/src/test/java/com/bakdata/conquery/integration/json/AbstractQueryEngineTest.java
+++ b/backend/src/test/java/com/bakdata/conquery/integration/json/AbstractQueryEngineTest.java
@@ -6,24 +6,19 @@
import java.io.IOException;
import java.util.List;
import java.util.Locale;
-import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import com.bakdata.conquery.apiv1.query.Query;
import com.bakdata.conquery.integration.common.IntegrationUtils;
-import com.bakdata.conquery.integration.common.LoadingUtil;
import com.bakdata.conquery.integration.common.ResourceFile;
import com.bakdata.conquery.io.result.CsvLineStreamRenderer;
-import com.bakdata.conquery.io.result.ResultTestUtil;
import com.bakdata.conquery.io.result.ResultUtil;
import com.bakdata.conquery.models.auth.entities.User;
import com.bakdata.conquery.models.config.ConqueryConfig;
-import com.bakdata.conquery.models.datasets.Dataset;
import com.bakdata.conquery.models.execution.ExecutionState;
-import com.bakdata.conquery.models.execution.ManagedExecution;
import com.bakdata.conquery.models.identifiable.ids.specific.ManagedExecutionId;
+import com.bakdata.conquery.models.identifiable.mapping.IdMappingConfig;
import com.bakdata.conquery.models.identifiable.mapping.IdMappingState;
-import com.bakdata.conquery.models.query.ExecutionManager;
import com.bakdata.conquery.models.query.ManagedQuery;
import com.bakdata.conquery.models.query.PrintSettings;
import com.bakdata.conquery.models.query.resultinfo.ResultInfo;
@@ -74,7 +69,7 @@ public void executeTest(StandaloneSupport standaloneSupport) throws IOException
.as("Should have same size as result infos")
.allSatisfy(v -> assertThat(v).hasSameSizeAs(resultInfos));
- IdMappingState mappingState = config.getIdMapping().initToExternal(testUser, execution);
+ IdMappingState mappingState = IdMappingConfig.initToExternal(testUser, execution);
PrintSettings
PRINT_SETTINGS =
new PrintSettings(
@@ -82,14 +77,14 @@ public void executeTest(StandaloneSupport standaloneSupport) throws IOException
Locale.ENGLISH,
namespaces,
config,
- cer -> ResultUtil.createId(standaloneSupport.getNamespace(), cer, config.getIdMapping(), mappingState),
+ cer -> ResultUtil.createId(standaloneSupport.getNamespace(), cer,mappingState),
(columnInfo) -> columnInfo.getSelect().getId().toStringWithoutDataset()
);
CsvLineStreamRenderer renderer = new CsvLineStreamRenderer(config.getCsv().createWriter(), PRINT_SETTINGS);
List actual = renderer.toStream(
- config.getIdMapping().getPrintIdFields(),
+ config.getFrontend().getQueryUpload().getPrintIdFields(),
resultInfos,
execution.streamResults()
).collect(Collectors.toList());
diff --git a/backend/src/test/java/com/bakdata/conquery/integration/json/FormTest.java b/backend/src/test/java/com/bakdata/conquery/integration/json/FormTest.java
index 9abeee7fee..bb86e4efd6 100644
--- a/backend/src/test/java/com/bakdata/conquery/integration/json/FormTest.java
+++ b/backend/src/test/java/com/bakdata/conquery/integration/json/FormTest.java
@@ -105,7 +105,6 @@ public void importRequiredData(StandaloneSupport support) throws Exception {
log.info("{} PARSE JSON FORM DESCRIPTION", getLabel());
form = parseForm(support);
- idMappingConfig = support.getConfig().getIdMapping();
}
@Override
@@ -137,7 +136,7 @@ public void executeTest(StandaloneSupport support) throws Exception {
private void checkResults(StandaloneSupport standaloneSupport, ManagedForm managedForm, User user) throws IOException {
Map> managedMapping = managedForm.getSubQueries();
- IdMappingState mappingState = idMappingConfig.initToExternal(user, managedForm);
+ IdMappingState mappingState = IdMappingConfig.initToExternal(user, managedForm);
final ConqueryConfig config = standaloneSupport.getConfig();
PrintSettings
PRINT_SETTINGS =
@@ -146,7 +145,7 @@ private void checkResults(StandaloneSupport standaloneSupport, ManagedForm manag
Locale.ENGLISH,
standaloneSupport.getDatasetsProcessor().getDatasetRegistry(),
config,
- cer -> ResultUtil.createId(standaloneSupport.getNamespace(), cer, config.getIdMapping(), mappingState)
+ cer -> ResultUtil.createId(standaloneSupport.getNamespace(), cer, mappingState)
);
CsvLineStreamRenderer renderer = new CsvLineStreamRenderer(config.getCsv().createWriter(), PRINT_SETTINGS);
@@ -156,7 +155,7 @@ private void checkResults(StandaloneSupport standaloneSupport, ManagedForm manag
log.info("{} CSV TESTING: {}", getLabel(), managed.getKey());
List actual =
renderer.toStream(
- config.getIdMapping().getPrintIdFields(),
+ config.getFrontend().getQueryUpload().getPrintIdFields(),
resultInfos,
managed.getValue().stream().flatMap(ManagedQuery::streamResults)
)
From f832fe97d00991afb963fde273c316f2db688484 Mon Sep 17 00:00:00 2001
From: Fabian Kovacs <1553491+awildturtok@users.noreply.github.com>
Date: Fri, 23 Jul 2021 14:48:01 +0200
Subject: [PATCH 15/82] also migrate Pseudomizer
---
.../mapping/AutoIncrementingPseudomizer.java | 43 +++++++++++++++++++
.../mapping/PseudomizationTest.java | 28 ++++++++++++
2 files changed, 71 insertions(+)
create mode 100644 backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/AutoIncrementingPseudomizer.java
create mode 100644 backend/src/test/java/com/bakdata/conquery/models/identifiable/mapping/PseudomizationTest.java
diff --git a/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/AutoIncrementingPseudomizer.java b/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/AutoIncrementingPseudomizer.java
new file mode 100644
index 0000000000..71c0981299
--- /dev/null
+++ b/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/AutoIncrementingPseudomizer.java
@@ -0,0 +1,43 @@
+package com.bakdata.conquery.models.identifiable.mapping;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import com.bakdata.conquery.models.identifiable.mapping.EntityPrintId;
+import lombok.RequiredArgsConstructor;
+
+/**
+ * Used to generate pseudonymized ids for every query if the user does
+ * not have the rights to see the real data.
+ */
+@RequiredArgsConstructor
+public class AutoIncrementingPseudomizer {
+ private static final String ANONYMOUS_ID_PREFIX = "anon_"; // Abbreviation for anonymous
+
+ private final Map cachedIds = new ConcurrentHashMap<>();
+ private final AtomicInteger pseudoIdPointer = new AtomicInteger(0);
+
+ private final int size;
+ private final int position;
+
+ /**
+ * In the pseudo format the actual id columns are preserved but empty.
+ * Only the Pid Column is written with a new generated id.
+ */
+ public EntityPrintId getPseudoId(String csvEntityId) {
+
+ EntityPrintId pseudonym = cachedIds.computeIfAbsent(csvEntityId, this::createPseudonym);
+
+ return pseudonym;
+ }
+
+ private EntityPrintId createPseudonym(String ignored) {
+ final String name = ANONYMOUS_ID_PREFIX + pseudoIdPointer.getAndIncrement();
+ final String[] parts = new String[size];
+
+ parts[position] = name;
+
+ return EntityPrintId.from(parts);
+ }
+}
diff --git a/backend/src/test/java/com/bakdata/conquery/models/identifiable/mapping/PseudomizationTest.java b/backend/src/test/java/com/bakdata/conquery/models/identifiable/mapping/PseudomizationTest.java
new file mode 100644
index 0000000000..354172228b
--- /dev/null
+++ b/backend/src/test/java/com/bakdata/conquery/models/identifiable/mapping/PseudomizationTest.java
@@ -0,0 +1,28 @@
+package com.bakdata.conquery.models.identifiable.mapping;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.jupiter.api.Test;
+
+public class PseudomizationTest {
+
+ @Test
+ void pseudoIdGeneration() {
+ AutoIncrementingPseudomizer pseudomizer = new AutoIncrementingPseudomizer(4,2);
+
+ String csvId1 = "123";
+ String csvId1Copy = "123";
+ String csvId2 = "234";
+
+ // Id changes from internal to external
+ assertThat(pseudomizer.getPseudoId(csvId1)).isEqualTo(EntityPrintId.from(null, null, "anon_0", null));
+
+ // Id mapping is constant
+ assertThat(pseudomizer.getPseudoId(csvId1)).isEqualTo(pseudomizer.getPseudoId(csvId1Copy));
+
+ // Mapping produces differing external ids
+ assertThat(pseudomizer.getPseudoId(csvId1)).isNotEqualTo(pseudomizer.getPseudoId(csvId2));
+
+ }
+
+}
From a8bdcdaa8b6b642fff7d3fd4350c0f7d2c906ae1 Mon Sep 17 00:00:00 2001
From: Fabian Kovacs <1553491+awildturtok@users.noreply.github.com>
Date: Fri, 23 Jul 2021 15:29:15 +0200
Subject: [PATCH 16/82] move Pseduomization to IdPrinter and Conquery
---
.../concept/specific/external/CQExternal.java | 2 +-
.../concept/specific/external/DateColumn.java | 59 -------------------
.../specific/external/DateSetColumn.java | 6 --
.../specific/external/FormatColumn.java | 10 ----
.../concept/specific/external/IdColumn.java | 14 -----
.../specific/external/IgnoreColumn.java | 12 ----
.../conquery/io/result/ResultUtil.java | 17 ------
.../io/result/arrow/ResultArrowProcessor.java | 11 ++--
.../io/result/csv/ResultCsvProcessor.java | 10 ++--
.../io/result/excel/ResultExcelProcessor.java | 11 ++--
.../conquery/models/config/ColumnConfig.java | 10 +---
.../models/config/ConqueryConfig.java | 2 +-
.../models/config/FrontendConfig.java | 41 ++++++++++++-
.../mapping/AutoIncrementingPseudomizer.java | 24 ++++----
.../identifiable/mapping/FullIdPrinter.java | 35 +++++++++++
.../identifiable/mapping/IdMappingConfig.java | 55 -----------------
.../identifiable/mapping/IdMappingState.java | 8 ---
.../identifiable/mapping/IdPrinter.java | 7 +++
.../json/AbstractQueryEngineTest.java | 12 ++--
.../conquery/integration/json/FormTest.java | 14 ++---
.../mapping/PseudomizationTest.java | 12 ++--
21 files changed, 128 insertions(+), 244 deletions(-)
delete mode 100644 backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateColumn.java
delete mode 100644 backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateSetColumn.java
delete mode 100644 backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/FormatColumn.java
delete mode 100644 backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/IdColumn.java
delete mode 100644 backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/IgnoreColumn.java
create mode 100644 backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/FullIdPrinter.java
delete mode 100644 backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/IdMappingConfig.java
delete mode 100644 backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/IdMappingState.java
create mode 100644 backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/IdPrinter.java
diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java
index 9cee81794e..ba4994e0f2 100644
--- a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java
+++ b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java
@@ -17,7 +17,7 @@
import com.bakdata.conquery.models.config.FrontendConfig;
import com.bakdata.conquery.models.error.ConqueryError;
import com.bakdata.conquery.models.identifiable.mapping.EntityIdMap;
-import com.bakdata.conquery.models.identifiable.mapping.IdMappingConfig;
+
import com.bakdata.conquery.models.query.QueryPlanContext;
import com.bakdata.conquery.models.query.QueryResolveContext;
import com.bakdata.conquery.models.query.queryplan.ConceptQueryPlan;
diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateColumn.java b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateColumn.java
deleted file mode 100644
index da784920b5..0000000000
--- a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateColumn.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package com.bakdata.conquery.apiv1.query.concept.specific.external;
-
-import com.bakdata.conquery.io.cps.CPSType;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.With;
-
-@Getter
-public abstract class DateColumn extends FormatColumn {
-
- private final DateFormat format;
-
- protected DateColumn(DateFormat format) {
- this.format = format;
- }
-
-
- public static class DateSet extends DateColumn {
- public static String HANDLE = "DATE_SET";
-
- public DateSet() {
- super(DateFormat.DATE_SET);
- }
- }
-
- public static class DateRange extends DateColumn {
- public static String HANDLE = "DATE_RANGE";
-
- public DateRange() {
- super(DateFormat.DATE_RANGE);
- }
- }
-
- public static class EventDate extends DateColumn {
- public static String HANDLE = "EVENT_DATE";
-
-
- public EventDate() {
- super(DateFormat.EVENT_DATE);
- }
- }
-
-
- public static class StartDate extends DateColumn {
- public static String HANDLE = "START_DATE";
-
- public StartDate() {
- super(DateFormat.START_DATE);
- }
- }
-
- public static class EndDate extends DateColumn {
- public static String HANDLE = "END_DATE";
-
- public EndDate() {
- super(DateFormat.END_DATE);
- }
- }
-}
diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateSetColumn.java b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateSetColumn.java
deleted file mode 100644
index 80efa72de5..0000000000
--- a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateSetColumn.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.bakdata.conquery.apiv1.query.concept.specific.external;
-
-import com.bakdata.conquery.apiv1.forms.Form;
-import com.bakdata.conquery.io.cps.CPSType;
-
-
diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/FormatColumn.java b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/FormatColumn.java
deleted file mode 100644
index 27f769c8e8..0000000000
--- a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/FormatColumn.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.bakdata.conquery.apiv1.query.concept.specific.external;
-
-import lombok.Data;
-import lombok.With;
-import lombok.extern.slf4j.Slf4j;
-
-
-public abstract class FormatColumn {
-
-}
diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/IdColumn.java b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/IdColumn.java
deleted file mode 100644
index 1877249878..0000000000
--- a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/IdColumn.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.bakdata.conquery.apiv1.query.concept.specific.external;
-
-import lombok.AllArgsConstructor;
-import lombok.Value;
-import lombok.With;
-
-public class IdColumn extends FormatColumn {
-
- public static String HANDLE = "ID";
-
- public String[] read(String[] row, int position) {
- return new String[]{row[position]};
- }
-}
diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/IgnoreColumn.java b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/IgnoreColumn.java
deleted file mode 100644
index 4a1c314d84..0000000000
--- a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/IgnoreColumn.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.bakdata.conquery.apiv1.query.concept.specific.external;
-
-import com.bakdata.conquery.io.cps.CPSType;
-
-public class IgnoreColumn extends FormatColumn {
-
- public static final String HANDLE = "IGNORED";
-
- public String read(String[] row) {
- return null;
- }
-}
diff --git a/backend/src/main/java/com/bakdata/conquery/io/result/ResultUtil.java b/backend/src/main/java/com/bakdata/conquery/io/result/ResultUtil.java
index 974fd57aec..0e8eb2e94d 100644
--- a/backend/src/main/java/com/bakdata/conquery/io/result/ResultUtil.java
+++ b/backend/src/main/java/com/bakdata/conquery/io/result/ResultUtil.java
@@ -7,15 +7,8 @@
import javax.ws.rs.core.Response;
import javax.ws.rs.core.StreamingOutput;
-import com.bakdata.conquery.models.dictionary.EncodedDictionary;
import com.bakdata.conquery.models.execution.ManagedExecution;
-import com.bakdata.conquery.models.identifiable.mapping.EntityIdMap;
-import com.bakdata.conquery.models.identifiable.mapping.EntityPrintId;
-import com.bakdata.conquery.models.identifiable.mapping.IdMappingConfig;
-import com.bakdata.conquery.models.identifiable.mapping.IdMappingState;
import com.bakdata.conquery.models.query.SingleTableResult;
-import com.bakdata.conquery.models.query.results.EntityResult;
-import com.bakdata.conquery.models.worker.Namespace;
import com.bakdata.conquery.util.io.FileUtil;
import com.google.common.base.Strings;
import lombok.extern.slf4j.Slf4j;
@@ -24,16 +17,6 @@
public class ResultUtil {
- public static EntityPrintId createId(Namespace namespace, EntityResult cer, IdMappingState mappingState) {
- EncodedDictionary dict = namespace.getStorage().getPrimaryDictionary();
- final EntityIdMap idMapping = namespace.getStorage().getIdMapping();
-
- return IdMappingConfig.toExternal(
- dict.getElement(cer.getEntityId()), namespace,
- mappingState, idMapping
- );
- }
-
public static Response makeResponseWithFileName(StreamingOutput out, String label, String fileExtension) {
Response.ResponseBuilder response = Response.ok(out);
if (!(Strings.isNullOrEmpty(label) || label.isBlank())) {
diff --git a/backend/src/main/java/com/bakdata/conquery/io/result/arrow/ResultArrowProcessor.java b/backend/src/main/java/com/bakdata/conquery/io/result/arrow/ResultArrowProcessor.java
index 237d56e4da..39a1d4cda6 100644
--- a/backend/src/main/java/com/bakdata/conquery/io/result/arrow/ResultArrowProcessor.java
+++ b/backend/src/main/java/com/bakdata/conquery/io/result/arrow/ResultArrowProcessor.java
@@ -10,7 +10,6 @@
import javax.ws.rs.core.Response;
import javax.ws.rs.core.StreamingOutput;
-import com.bakdata.conquery.io.result.ResultUtil;
import com.bakdata.conquery.models.auth.entities.User;
import com.bakdata.conquery.models.auth.permissions.Ability;
import com.bakdata.conquery.models.config.ConqueryConfig;
@@ -18,8 +17,8 @@
import com.bakdata.conquery.models.execution.ManagedExecution;
import com.bakdata.conquery.models.forms.managed.ManagedForm;
import com.bakdata.conquery.models.i18n.I18n;
-import com.bakdata.conquery.models.identifiable.mapping.IdMappingConfig;
-import com.bakdata.conquery.models.identifiable.mapping.IdMappingState;
+
+import com.bakdata.conquery.models.identifiable.mapping.IdPrinter;
import com.bakdata.conquery.models.query.ManagedQuery;
import com.bakdata.conquery.models.query.PrintSettings;
import com.bakdata.conquery.models.query.SingleTableResult;
@@ -66,13 +65,15 @@ public static & SingleTableResult> Response getAr
}
// Get the locale extracted by the LocaleFilter
- IdMappingState mappingState = IdMappingConfig.initToExternal(user, exec);
+
+
+ IdPrinter idPrinter = config.getFrontend().getQueryUpload().getIdPrinter(user,exec,namespace);
PrintSettings settings = new PrintSettings(
pretty,
I18n.LOCALE.get(),
datasetRegistry,
config,
- (EntityResult cer) -> ResultUtil.createId(namespace, cer, mappingState)
+ idPrinter::createId
);
diff --git a/backend/src/main/java/com/bakdata/conquery/io/result/csv/ResultCsvProcessor.java b/backend/src/main/java/com/bakdata/conquery/io/result/csv/ResultCsvProcessor.java
index 3f6ac4b16b..b6d2b055fa 100644
--- a/backend/src/main/java/com/bakdata/conquery/io/result/csv/ResultCsvProcessor.java
+++ b/backend/src/main/java/com/bakdata/conquery/io/result/csv/ResultCsvProcessor.java
@@ -12,15 +12,14 @@
import javax.ws.rs.core.Response;
import javax.ws.rs.core.StreamingOutput;
-import com.bakdata.conquery.io.result.ResultUtil;
import com.bakdata.conquery.models.auth.entities.User;
import com.bakdata.conquery.models.auth.permissions.Ability;
import com.bakdata.conquery.models.config.ConqueryConfig;
import com.bakdata.conquery.models.datasets.Dataset;
import com.bakdata.conquery.models.execution.ManagedExecution;
import com.bakdata.conquery.models.i18n.I18n;
-import com.bakdata.conquery.models.identifiable.mapping.IdMappingConfig;
-import com.bakdata.conquery.models.identifiable.mapping.IdMappingState;
+
+import com.bakdata.conquery.models.identifiable.mapping.IdPrinter;
import com.bakdata.conquery.models.query.PrintSettings;
import com.bakdata.conquery.models.query.SingleTableResult;
import com.bakdata.conquery.models.worker.DatasetRegistry;
@@ -50,7 +49,8 @@ public & SingleTableResult> Response getResult(Us
// Check if user is permitted to download on all datasets that were referenced by the query
authorizeDownloadDatasets(user, exec);
- IdMappingState mappingState = IdMappingConfig.initToExternal(user, exec);
+ IdPrinter idPrinter = config.getFrontend().getQueryUpload().getIdPrinter(user,exec,namespace);
+
// Get the locale extracted by the LocaleFilter
PrintSettings settings = new PrintSettings(
@@ -58,7 +58,7 @@ public & SingleTableResult> Response getResult(Us
I18n.LOCALE.get(),
datasetRegistry,
config,
- cer -> ResultUtil.createId(namespace, cer, mappingState)
+ idPrinter::createId
);
Charset charset = determineCharset(userAgent, queryCharset);
diff --git a/backend/src/main/java/com/bakdata/conquery/io/result/excel/ResultExcelProcessor.java b/backend/src/main/java/com/bakdata/conquery/io/result/excel/ResultExcelProcessor.java
index 86e08ea07d..76cb20600f 100644
--- a/backend/src/main/java/com/bakdata/conquery/io/result/excel/ResultExcelProcessor.java
+++ b/backend/src/main/java/com/bakdata/conquery/io/result/excel/ResultExcelProcessor.java
@@ -1,6 +1,5 @@
package com.bakdata.conquery.io.result.excel;
-import com.bakdata.conquery.io.result.ResultUtil;
import com.bakdata.conquery.models.auth.entities.User;
import com.bakdata.conquery.models.auth.permissions.Ability;
import com.bakdata.conquery.models.config.ConqueryConfig;
@@ -8,8 +7,8 @@
import com.bakdata.conquery.models.execution.ManagedExecution;
import com.bakdata.conquery.models.i18n.I18n;
import com.bakdata.conquery.models.identifiable.ids.specific.DatasetId;
-import com.bakdata.conquery.models.identifiable.mapping.IdMappingConfig;
-import com.bakdata.conquery.models.identifiable.mapping.IdMappingState;
+
+import com.bakdata.conquery.models.identifiable.mapping.IdPrinter;
import com.bakdata.conquery.models.query.PrintSettings;
import com.bakdata.conquery.models.query.SingleTableResult;
import com.bakdata.conquery.models.query.results.EntityResult;
@@ -39,13 +38,15 @@ public & SingleTableResult> Response getExcelResu
user.authorize(dataset, Ability.DOWNLOAD);
user.authorize(exec, Ability.READ);
- IdMappingState mappingState = IdMappingConfig.initToExternal(user, exec);
+ IdPrinter idPrinter = config.getFrontend().getQueryUpload().getIdPrinter(user,exec,namespace);
+
PrintSettings settings = new PrintSettings(
pretty,
I18n.LOCALE.get(),
datasetRegistry,
config,
- (EntityResult cer) -> ResultUtil.createId(namespace, cer, mappingState));
+ idPrinter::createId
+ );
ExcelRenderer excelRenderer = new ExcelRenderer(config.getExcel());
diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java b/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java
index 52b3abcdce..7f9658aea5 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java
@@ -5,13 +5,9 @@
import javax.validation.constraints.NotEmpty;
-import com.bakdata.conquery.apiv1.query.concept.specific.external.FormatColumn;
-import com.bakdata.conquery.io.cps.CPSTypeIdResolver;
import com.bakdata.conquery.models.identifiable.mapping.EntityIdMap;
-import com.fasterxml.jackson.annotation.JsonIgnore;
import com.google.common.base.Strings;
import io.dropwizard.logback.shaded.checkerframework.checker.nullness.qual.Nullable;
-import io.dropwizard.validation.ValidationMethod;
import lombok.Builder;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
@@ -33,6 +29,7 @@ public static class Mapping {
@Builder.Default
private final boolean resolvable = true;
+ @Builder.Default
private final boolean fillAnon = false;
}
@@ -75,9 +72,4 @@ public EntityIdMap.ExternalId read(String value) {
@Nullable
private final Mapping mapping;
- @JsonIgnore
- @ValidationMethod
- public boolean isExistingColumnFormat() {
- return CPSTypeIdResolver.getImplementation(FormatColumn.class, name) != null;
- }
}
diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/ConqueryConfig.java b/backend/src/main/java/com/bakdata/conquery/models/config/ConqueryConfig.java
index 54e931acc4..0d62738b94 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/config/ConqueryConfig.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/config/ConqueryConfig.java
@@ -19,7 +19,7 @@
import com.bakdata.conquery.models.auth.develop.DevAuthConfig;
import com.bakdata.conquery.models.config.auth.DevelopmentAuthorizationConfig;
import com.bakdata.conquery.models.common.CDateSet;
-import com.bakdata.conquery.models.identifiable.mapping.IdMappingConfig;
+
import com.bakdata.conquery.util.DateReader;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java b/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java
index 134edcde2e..d1c873d0de 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java
@@ -6,12 +6,20 @@
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
+import java.util.stream.IntStream;
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import com.bakdata.conquery.apiv1.query.concept.specific.external.DateFormat;
+import com.bakdata.conquery.models.auth.entities.User;
+import com.bakdata.conquery.models.auth.permissions.Ability;
+import com.bakdata.conquery.models.execution.ManagedExecution;
+import com.bakdata.conquery.models.identifiable.mapping.AutoIncrementingPseudomizer;
+import com.bakdata.conquery.models.identifiable.mapping.FullIdPrinter;
+import com.bakdata.conquery.models.identifiable.mapping.IdPrinter;
+import com.bakdata.conquery.models.worker.Namespace;
import com.bakdata.conquery.util.VersionInfo;
import com.fasterxml.jackson.annotation.JsonIgnore;
import groovy.transform.ToString;
@@ -54,6 +62,7 @@ public static class UploadConfig {
.mapping(ColumnConfig.Mapping.builder()
.field("id")
.resolvable(true)
+ .fillAnon(true)
.build())
.build()
);
@@ -79,9 +88,9 @@ public List getPrintIdFields() {
public ColumnConfig getIdMapper(String name) {
return ids.stream()
- .filter(mapper -> mapper.getName().equals(name)) //TODO use map
- .findFirst()
- .orElse(null);
+ .filter(mapper -> mapper.getName().equals(name)) //TODO use map
+ .findFirst()
+ .orElse(null);
}
public int getIdIndex(List format) {
@@ -162,6 +171,17 @@ public boolean isIdColsHaveMapping() {
return ids.stream().map(ColumnConfig::getMapping).allMatch(Objects::nonNull);
}
+ @ValidationMethod(message = "Must have exactly one Column for Pseudomization.")
+ @JsonIgnore
+ public boolean isExactlyOnePseudo() {
+ return ids.stream()
+ .map(ColumnConfig::getMapping)
+ .filter(Objects::nonNull)
+ .filter(ColumnConfig.Mapping::isFillAnon)
+ .count() == 1;
+ }
+
+
public DateFormat resolveDateFormat(String handle) {
try {
return DateFormat.valueOf(handle);
@@ -172,6 +192,21 @@ public DateFormat resolveDateFormat(String handle) {
}
+ public IdPrinter getIdPrinter(User owner, ManagedExecution> execution, Namespace namespace) {
+
+ if (owner.isPermitted(execution.getDataset(), Ability.PRESERVE_ID)) {
+ return new FullIdPrinter(namespace.getStorage().getPrimaryDictionary(), namespace.getStorage().getIdMapping());
+ }
+
+ final int size = getPrintIdFields().size();
+ final int pos = IntStream.range(0, getIds().size())
+ .filter(idx -> getIds().get(idx).getMapping() != null)
+ .filter(idx -> getIds().get(idx).getMapping().isFillAnon())
+ .findFirst()
+ .orElseThrow();
+
+ return new AutoIncrementingPseudomizer(size,pos);
+ }
}
@Data
diff --git a/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/AutoIncrementingPseudomizer.java b/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/AutoIncrementingPseudomizer.java
index 71c0981299..efa7cc1e8e 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/AutoIncrementingPseudomizer.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/AutoIncrementingPseudomizer.java
@@ -1,10 +1,10 @@
package com.bakdata.conquery.models.identifiable.mapping;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
-import com.bakdata.conquery.models.identifiable.mapping.EntityPrintId;
+import com.bakdata.conquery.models.query.results.EntityResult;
+import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap;
+import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import lombok.RequiredArgsConstructor;
/**
@@ -12,27 +12,29 @@
* not have the rights to see the real data.
*/
@RequiredArgsConstructor
-public class AutoIncrementingPseudomizer {
+public class AutoIncrementingPseudomizer implements IdPrinter {
private static final String ANONYMOUS_ID_PREFIX = "anon_"; // Abbreviation for anonymous
- private final Map cachedIds = new ConcurrentHashMap<>();
+ private final Int2ObjectMap cachedIds = new Int2ObjectAVLTreeMap<>();
private final AtomicInteger pseudoIdPointer = new AtomicInteger(0);
private final int size;
private final int position;
+ @Override
+ public EntityPrintId createId(EntityResult entityResult) {
+ return getPseudoId(entityResult.getEntityId());
+ }
+
/**
* In the pseudo format the actual id columns are preserved but empty.
* Only the Pid Column is written with a new generated id.
*/
- public EntityPrintId getPseudoId(String csvEntityId) {
-
- EntityPrintId pseudonym = cachedIds.computeIfAbsent(csvEntityId, this::createPseudonym);
-
- return pseudonym;
+ public EntityPrintId getPseudoId(int csvEntityId) {
+ return cachedIds.computeIfAbsent(csvEntityId, this::createPseudonym);
}
- private EntityPrintId createPseudonym(String ignored) {
+ private EntityPrintId createPseudonym(int ignored) {
final String name = ANONYMOUS_ID_PREFIX + pseudoIdPointer.getAndIncrement();
final String[] parts = new String[size];
diff --git a/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/FullIdPrinter.java b/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/FullIdPrinter.java
new file mode 100644
index 0000000000..db1c3ba8b5
--- /dev/null
+++ b/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/FullIdPrinter.java
@@ -0,0 +1,35 @@
+package com.bakdata.conquery.models.identifiable.mapping;
+
+import com.bakdata.conquery.models.dictionary.EncodedDictionary;
+import com.bakdata.conquery.models.query.results.EntityResult;
+import lombok.RequiredArgsConstructor;
+
+/**
+ * Maker interface for implementation specific state object during query result to csv rendering.
+ */
+@RequiredArgsConstructor
+public class FullIdPrinter implements IdPrinter {
+
+ private final EncodedDictionary dictionary;
+ private final EntityIdMap idMapping;
+
+ @Override
+ public EntityPrintId createId(EntityResult entityResult){
+
+ String csvEntityId = dictionary.getElement(entityResult.getEntityId());
+ // The state may be uses by implementations of this class
+
+ if (idMapping == null) {
+ return EntityPrintId.from(csvEntityId);
+ }
+
+ EntityPrintId externalEntityId = idMapping.toExternal(csvEntityId);
+
+ if (externalEntityId == null) {
+ return EntityPrintId.from(csvEntityId);
+ }
+
+ return externalEntityId;
+ }
+
+}
diff --git a/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/IdMappingConfig.java b/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/IdMappingConfig.java
deleted file mode 100644
index 6ed66d726c..0000000000
--- a/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/IdMappingConfig.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package com.bakdata.conquery.models.identifiable.mapping;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import com.bakdata.conquery.models.auth.entities.User;
-import com.bakdata.conquery.models.config.ColumnConfig;
-import com.bakdata.conquery.models.execution.ManagedExecution;
-import com.bakdata.conquery.models.worker.Namespace;
-import com.univocity.parsers.common.record.Record;
-import com.univocity.parsers.csv.CsvParser;
-import lombok.AccessLevel;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-import lombok.extern.slf4j.Slf4j;
-
-
-@Slf4j
-@NoArgsConstructor(access = AccessLevel.NONE)
-@Setter
-@Getter
-public class IdMappingConfig {
-
-
- /**
- * Is called once before a mapping is used before a query result is created to
- * allow the mapping to have state information.
- */
- public static IdMappingState initToExternal(User user, ManagedExecution> execution) {
- // This mapping does not need a per-query state, so we return an immutable empty map.
- return null;
- }
-
- /**
- * Converts the internal ID to the an external.
- */
- public static EntityPrintId toExternal(String csvEntityId, Namespace namespace, IdMappingState state, EntityIdMap mapping) {
- // The state may be uses by implementations of this class
-
- if (mapping == null) {
- return EntityPrintId.from(csvEntityId);
- }
-
- EntityPrintId externalEntityId = mapping.toExternal(csvEntityId);
-
- if (externalEntityId == null) {
- return EntityPrintId.from(csvEntityId);
- }
-
- return externalEntityId;
- }
-
-
-}
diff --git a/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/IdMappingState.java b/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/IdMappingState.java
deleted file mode 100644
index 442db2db1a..0000000000
--- a/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/IdMappingState.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.bakdata.conquery.models.identifiable.mapping;
-
-/**
- * Maker interface for implementation specific state object during query result to csv rendering.
- */
-public interface IdMappingState {
-
-}
diff --git a/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/IdPrinter.java b/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/IdPrinter.java
new file mode 100644
index 0000000000..25a746694e
--- /dev/null
+++ b/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/IdPrinter.java
@@ -0,0 +1,7 @@
+package com.bakdata.conquery.models.identifiable.mapping;
+
+import com.bakdata.conquery.models.query.results.EntityResult;
+
+public interface IdPrinter {
+ EntityPrintId createId(EntityResult entityResult);
+}
diff --git a/backend/src/test/java/com/bakdata/conquery/integration/json/AbstractQueryEngineTest.java b/backend/src/test/java/com/bakdata/conquery/integration/json/AbstractQueryEngineTest.java
index f98a1bea0b..118536ad7e 100644
--- a/backend/src/test/java/com/bakdata/conquery/integration/json/AbstractQueryEngineTest.java
+++ b/backend/src/test/java/com/bakdata/conquery/integration/json/AbstractQueryEngineTest.java
@@ -1,7 +1,6 @@
package com.bakdata.conquery.integration.json;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.fail;
import java.io.IOException;
import java.util.List;
@@ -12,13 +11,11 @@
import com.bakdata.conquery.integration.common.IntegrationUtils;
import com.bakdata.conquery.integration.common.ResourceFile;
import com.bakdata.conquery.io.result.CsvLineStreamRenderer;
-import com.bakdata.conquery.io.result.ResultUtil;
import com.bakdata.conquery.models.auth.entities.User;
import com.bakdata.conquery.models.config.ConqueryConfig;
import com.bakdata.conquery.models.execution.ExecutionState;
import com.bakdata.conquery.models.identifiable.ids.specific.ManagedExecutionId;
-import com.bakdata.conquery.models.identifiable.mapping.IdMappingConfig;
-import com.bakdata.conquery.models.identifiable.mapping.IdMappingState;
+import com.bakdata.conquery.models.identifiable.mapping.IdPrinter;
import com.bakdata.conquery.models.query.ManagedQuery;
import com.bakdata.conquery.models.query.PrintSettings;
import com.bakdata.conquery.models.query.resultinfo.ResultInfo;
@@ -64,12 +61,13 @@ public void executeTest(StandaloneSupport standaloneSupport) throws IOException
assertThat(
execution.streamResults()
- .flatMap(EntityResult::streamValues)
+ .flatMap(EntityResult::streamValues)
)
.as("Should have same size as result infos")
.allSatisfy(v -> assertThat(v).hasSameSizeAs(resultInfos));
- IdMappingState mappingState = IdMappingConfig.initToExternal(testUser, execution);
+ IdPrinter idPrinter = config.getFrontend().getQueryUpload().getIdPrinter(testUser, execution, execution.getNamespace());
+
PrintSettings
PRINT_SETTINGS =
new PrintSettings(
@@ -77,7 +75,7 @@ public void executeTest(StandaloneSupport standaloneSupport) throws IOException
Locale.ENGLISH,
namespaces,
config,
- cer -> ResultUtil.createId(standaloneSupport.getNamespace(), cer,mappingState),
+ idPrinter::createId,
(columnInfo) -> columnInfo.getSelect().getId().toStringWithoutDataset()
);
diff --git a/backend/src/test/java/com/bakdata/conquery/integration/json/FormTest.java b/backend/src/test/java/com/bakdata/conquery/integration/json/FormTest.java
index bb86e4efd6..d35cc0f34b 100644
--- a/backend/src/test/java/com/bakdata/conquery/integration/json/FormTest.java
+++ b/backend/src/test/java/com/bakdata/conquery/integration/json/FormTest.java
@@ -21,7 +21,6 @@
import com.bakdata.conquery.integration.common.ResourceFile;
import com.bakdata.conquery.io.cps.CPSType;
import com.bakdata.conquery.io.result.CsvLineStreamRenderer;
-import com.bakdata.conquery.io.result.ResultUtil;
import com.bakdata.conquery.models.auth.entities.User;
import com.bakdata.conquery.models.datasets.concepts.Concept;
import com.bakdata.conquery.models.config.ConqueryConfig;
@@ -30,8 +29,8 @@
import com.bakdata.conquery.models.execution.ExecutionState;
import com.bakdata.conquery.models.execution.ManagedExecution;
import com.bakdata.conquery.models.forms.managed.ManagedForm;
-import com.bakdata.conquery.models.identifiable.mapping.IdMappingConfig;
-import com.bakdata.conquery.models.identifiable.mapping.IdMappingState;
+
+import com.bakdata.conquery.models.identifiable.mapping.IdPrinter;
import com.bakdata.conquery.models.query.ManagedQuery;
import com.bakdata.conquery.models.query.PrintSettings;
import com.bakdata.conquery.models.query.resultinfo.ResultInfo;
@@ -74,9 +73,6 @@ public class FormTest extends ConqueryTestSpec {
@JsonIgnore
private Form form;
- @JsonIgnore
- private IdMappingConfig idMappingConfig;
-
@Override
public void overrideConfig(ConqueryConfig config) {
config.setStorage(new NonPersistentStoreFactory());
@@ -136,7 +132,9 @@ public void executeTest(StandaloneSupport support) throws Exception {
private void checkResults(StandaloneSupport standaloneSupport, ManagedForm managedForm, User user) throws IOException {
Map> managedMapping = managedForm.getSubQueries();
- IdMappingState mappingState = IdMappingConfig.initToExternal(user, managedForm);
+
+ IdPrinter idPrinter = standaloneSupport.getConfig().getFrontend().getQueryUpload().getIdPrinter(user, managedForm, standaloneSupport.getNamespace());
+
final ConqueryConfig config = standaloneSupport.getConfig();
PrintSettings
PRINT_SETTINGS =
@@ -145,7 +143,7 @@ private void checkResults(StandaloneSupport standaloneSupport, ManagedForm manag
Locale.ENGLISH,
standaloneSupport.getDatasetsProcessor().getDatasetRegistry(),
config,
- cer -> ResultUtil.createId(standaloneSupport.getNamespace(), cer, mappingState)
+ idPrinter::createId
);
CsvLineStreamRenderer renderer = new CsvLineStreamRenderer(config.getCsv().createWriter(), PRINT_SETTINGS);
diff --git a/backend/src/test/java/com/bakdata/conquery/models/identifiable/mapping/PseudomizationTest.java b/backend/src/test/java/com/bakdata/conquery/models/identifiable/mapping/PseudomizationTest.java
index 354172228b..470024c659 100644
--- a/backend/src/test/java/com/bakdata/conquery/models/identifiable/mapping/PseudomizationTest.java
+++ b/backend/src/test/java/com/bakdata/conquery/models/identifiable/mapping/PseudomizationTest.java
@@ -9,19 +9,15 @@ public class PseudomizationTest {
@Test
void pseudoIdGeneration() {
AutoIncrementingPseudomizer pseudomizer = new AutoIncrementingPseudomizer(4,2);
-
- String csvId1 = "123";
- String csvId1Copy = "123";
- String csvId2 = "234";
-
+
// Id changes from internal to external
- assertThat(pseudomizer.getPseudoId(csvId1)).isEqualTo(EntityPrintId.from(null, null, "anon_0", null));
+ assertThat(pseudomizer.getPseudoId(0)).isEqualTo(EntityPrintId.from(null, null, "anon_0", null));
// Id mapping is constant
- assertThat(pseudomizer.getPseudoId(csvId1)).isEqualTo(pseudomizer.getPseudoId(csvId1Copy));
+ assertThat(pseudomizer.getPseudoId(0)).isEqualTo(pseudomizer.getPseudoId(0));
// Mapping produces differing external ids
- assertThat(pseudomizer.getPseudoId(csvId1)).isNotEqualTo(pseudomizer.getPseudoId(csvId2));
+ assertThat(pseudomizer.getPseudoId(1)).isNotEqualTo(pseudomizer.getPseudoId(0));
}
From 7a4ae6f97b8f86c9e39e909d99d96b206059d461 Mon Sep 17 00:00:00 2001
From: Fabian Kovacs <1553491+awildturtok@users.noreply.github.com>
Date: Fri, 23 Jul 2021 15:32:20 +0200
Subject: [PATCH 17/82] remove unused class
---
autodoc/src/main/java/com/bakdata/conquery/Constants.java | 2 --
1 file changed, 2 deletions(-)
diff --git a/autodoc/src/main/java/com/bakdata/conquery/Constants.java b/autodoc/src/main/java/com/bakdata/conquery/Constants.java
index d5267a1368..e37a36016b 100644
--- a/autodoc/src/main/java/com/bakdata/conquery/Constants.java
+++ b/autodoc/src/main/java/com/bakdata/conquery/Constants.java
@@ -62,7 +62,6 @@
import com.bakdata.conquery.models.forms.configs.FormConfig;
import com.bakdata.conquery.models.forms.configs.FormConfig.FormConfigFullRepresentation;
import com.bakdata.conquery.models.forms.configs.FormConfig.FormConfigOverviewRepresentation;
-import com.bakdata.conquery.models.identifiable.mapping.IdMappingConfig;
import com.bakdata.conquery.models.preproc.TableImportDescriptor;
import com.bakdata.conquery.models.preproc.TableInputDescriptor;
import com.bakdata.conquery.models.preproc.outputs.OutputDescription;
@@ -118,7 +117,6 @@ public class Constants {
.base(new Base(AuthorizationConfig.class, "An `AuthorizationConfig` defines the initial users that are created on application startup and other permission related options."))
.base(new Base(AuthenticationConfig.class, "An `AuthenticationConfig` is used to define how specific realms for authentication are configured."))
.base(new Base(PluginConfig.class, "A `PluginConfig` is used to define settings for Conquery plugins."))
- .base(new Base(IdMappingConfig.class, "An `IdMappingConfig` is used to define how multi column entity IDs are printed and parsed"))
.otherClass(APIConfig.class)
.otherClass(ConqueryConfig.class)
.otherClass(ClusterConfig.class)
From f2963f3a595d44304374f21397d099edebaf82fd Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Fri, 23 Jul 2021 13:34:17 +0000
Subject: [PATCH 18/82] Update AutoDoc
---
docs/Config JSON.md | 63 ++++++++++--------------------------------
docs/REST API JSONs.md | 20 +++++++-------
2 files changed, 25 insertions(+), 58 deletions(-)
diff --git a/docs/Config JSON.md b/docs/Config JSON.md
index b82a65e60c..97d541c2ee 100644
--- a/docs/Config JSON.md
+++ b/docs/Config JSON.md
@@ -133,38 +133,6 @@ Different types of PluginConfig can be used by setting `type` to one of the foll
----
-
-## Base IdMappingConfig
-An `IdMappingConfig` is used to define how multi column entity IDs are printed and parsed
-
-Different types of IdMappingConfig can be used by setting `type` to one of the following values:
-
-
-### NO_ID_MAPPING [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/NoIdMapping.java#L11-L13)
-Disables Id-Mapping completely.
-
-Details
-
-Java Type: `com.bakdata.conquery.models.config.NoIdMapping`
-
-No fields can be set for this type.
-
-
-
-### SIMPLE [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/SimpleIdMapping.java#L14-L16)
-Maps input to itself for upload.
-
-Details
-
-Java Type: `com.bakdata.conquery.models.config.SimpleIdMapping`
-
-No fields can be set for this type.
-
-
-
-
-
---
## Other Types
@@ -237,18 +205,17 @@ Supported Fields:
| --- | --- | --- | --- | --- | --- |
| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/ConqueryConfig.java#L74) | api | [APIConfig](#Type-APIConfig) | | | |
| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/ConqueryConfig.java#L50) | arrow | `@Valid @NotNull ArrowConfig` | | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/ConqueryConfig.java#L86) | authentication | list of [AuthenticationConfig](#Base-AuthenticationConfig) | | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/ConqueryConfig.java#L90) | authorization | [@Valid @NotNull AuthorizationConfig](#Base-AuthorizationConfig) | | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/ConqueryConfig.java#L83) | authentication | list of [AuthenticationConfig](#Base-AuthenticationConfig) | | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/ConqueryConfig.java#L87) | authorization | [@Valid @NotNull AuthorizationConfig](#Base-AuthorizationConfig) | | | |
| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/ConqueryConfig.java#L41) | cluster | [ClusterConfig](#Type-ClusterConfig) | | | |
| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/ConqueryConfig.java#L47) | csv | [CSVConfig](#Type-CSVConfig) | | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/ConqueryConfig.java#L99-L101) | debugMode | `boolean` or `null` | `null` | | null means here that we try to deduce from an attached agent |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/ConqueryConfig.java#L93) | excel | `@Valid @NotNull ExcelConfig` | | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/ConqueryConfig.java#L104) | failOnError | `boolean` | `false` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/ConqueryConfig.java#L96-L98) | debugMode | `boolean` or `null` | `null` | | null means here that we try to deduce from an attached agent |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/ConqueryConfig.java#L90) | excel | `@Valid @NotNull ExcelConfig` | | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/ConqueryConfig.java#L101) | failOnError | `boolean` | `false` | | |
| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/ConqueryConfig.java#L77) | frontend | [FrontendConfig](#Type-FrontendConfig) | | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/ConqueryConfig.java#L83) | idMapping | [@NotNull @Valid IdMappingConfig](#Base-IdMappingConfig) | | | |
| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/ConqueryConfig.java#L63) | locale | [LocaleConfig](#Type-LocaleConfig) | | | |
| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/ConqueryConfig.java#L81) | metricsConfig | `ConqueryMetricsConfig` | | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/ConqueryConfig.java#L97) | plugins | list of `PluginConfig` | `[]` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/ConqueryConfig.java#L94) | plugins | list of `PluginConfig` | `[]` | | |
| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/ConqueryConfig.java#L44) | preprocessor | [PreprocessingConfig](#Type-PreprocessingConfig) | | | |
| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/ConqueryConfig.java#L71) | queries | [QueryConfig](#Type-QueryConfig) | | | |
| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/ConqueryConfig.java#L53-L55) | resultProviders | list of `ResultRendererProvider` | | | The order of this lists determines the ordner of the generated result urls in a query status. |
@@ -256,7 +223,7 @@ Supported Fields:
| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/ConqueryConfig.java#L68) | storage | `@Valid @NotNull StoreFactory` | | | |
-### Type CurrencyConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L92)
+### Type CurrencyConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L212)
Details
@@ -267,13 +234,13 @@ Supported Fields:
| | Field | Type | Default | Example | Description |
| --- | --- | --- | --- | --- | --- |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L97) | decimalScale | `int` | `2` | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L96) | decimalSeparator | `String` | `","` | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L94) | prefix | `String` | `"€"` | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L95) | thousandSeparator | `String` | `"."` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L217) | decimalScale | `int` | `2` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L216) | decimalSeparator | `String` | `","` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L214) | prefix | `String` | `"€"` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L215) | thousandSeparator | `String` | `"."` | | |
-### Type FrontendConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L27)
+### Type FrontendConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L35)
Details
@@ -284,9 +251,9 @@ Supported Fields:
| | Field | Type | Default | Example | Description |
| --- | --- | --- | --- | --- | --- |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L33) | currency | [CurrencyConfig](#Type-CurrencyConfig) | | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L37) | queryUpload | `UploadConfig` | | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L32) | version | `String` | `"0.0.0-SNAPSHOT"` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L45) | currency | [CurrencyConfig](#Type-CurrencyConfig) | | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L49) | queryUpload | `UploadConfig` | | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L44) | version | `String` | `"0.0.0-SNAPSHOT"` | | |
### Type LocaleConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/LocaleConfig.java#L11)
diff --git a/docs/REST API JSONs.md b/docs/REST API JSONs.md
index 536882392a..34eecedd76 100644
--- a/docs/REST API JSONs.md
+++ b/docs/REST API JSONs.md
@@ -509,7 +509,7 @@ Supported Fields:
| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/apiv1/query/CQElement.java#L31-L33) | label | `String` | ? | | Allows the user to define labels. |
-### EXTERNAL [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java#L32-L34)
+### EXTERNAL [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java#L38-L40)
Allows uploading lists of entities.
Details
@@ -755,7 +755,7 @@ Supported Fields:
| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/resources/api/ConceptResource.java#L68) | concepts | list of `String` | `null` | | |
-### Type CurrencyConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L92)
+### Type CurrencyConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L212)
Details
@@ -766,10 +766,10 @@ Supported Fields:
| | Field | Type | Default | Example | Description |
| --- | --- | --- | --- | --- | --- |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L97) | decimalScale | `int` | `2` | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L96) | decimalSeparator | `String` | `","` | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L94) | prefix | `String` | `"€"` | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L95) | thousandSeparator | `String` | `"."` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L217) | decimalScale | `int` | `2` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L216) | decimalSeparator | `String` | `","` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L214) | prefix | `String` | `"€"` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L215) | thousandSeparator | `String` | `"."` | | |
### Type ExecutionStatus [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/apiv1/ExecutionStatus.java#L18)
@@ -885,7 +885,7 @@ No fields can be set for this type.
-### Type FrontendConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L27)
+### Type FrontendConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L35)
Details
@@ -896,9 +896,9 @@ Supported Fields:
| | Field | Type | Default | Example | Description |
| --- | --- | --- | --- | --- | --- |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L33) | currency | [CurrencyConfig](#Type-CurrencyConfig) | | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L37) | queryUpload | `UploadConfig` | | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L32) | version | `String` | `"0.0.0-SNAPSHOT"` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L45) | currency | [CurrencyConfig](#Type-CurrencyConfig) | | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L49) | queryUpload | `UploadConfig` | | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L44) | version | `String` | `"0.0.0-SNAPSHOT"` | | |
### Type FullExecutionStatus [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/apiv1/FullExecutionStatus.java#L20-L24)
From 4d7c6652916146a9a5d57db00c08f78668155ce3 Mon Sep 17 00:00:00 2001
From: Fabian Kovacs <1553491+awildturtok@users.noreply.github.com>
Date: Mon, 26 Jul 2021 09:37:54 +0200
Subject: [PATCH 19/82] adds json defaults
---
.../com/bakdata/conquery/models/config/ColumnConfig.java | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java b/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java
index 7f9658aea5..d1d04b79a9 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java
@@ -6,6 +6,7 @@
import javax.validation.constraints.NotEmpty;
import com.bakdata.conquery.models.identifiable.mapping.EntityIdMap;
+import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.Strings;
import io.dropwizard.logback.shaded.checkerframework.checker.nullness.qual.Nullable;
import lombok.Builder;
@@ -23,13 +24,17 @@ public static class Mapping {
@Builder.Default
private final String pad = null;
+
@Builder.Default
+ @JsonProperty(defaultValue = "-1")
private final int length = -1;
@Builder.Default
+ @JsonProperty(defaultValue = "true")
private final boolean resolvable = true;
@Builder.Default
+ @JsonProperty(defaultValue = "false")
private final boolean fillAnon = false;
}
From ac3cf5a5330ac4e82ec474eed9fb89badbc8a6d5 Mon Sep 17 00:00:00 2001
From: Fabian Kovacs <1553491+awildturtok@users.noreply.github.com>
Date: Mon, 26 Jul 2021 09:41:19 +0200
Subject: [PATCH 20/82] use noArgs+Setter instead
---
.../conquery/models/config/ColumnConfig.java | 21 +++++++++++--------
1 file changed, 12 insertions(+), 9 deletions(-)
diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java b/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java
index d1d04b79a9..a972be5a62 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java
@@ -9,33 +9,36 @@
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.Strings;
import io.dropwizard.logback.shaded.checkerframework.checker.nullness.qual.Nullable;
+import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
@Data
@Builder
public class ColumnConfig {
- @Data
@Builder
+ @NoArgsConstructor
+ @Getter
+ @Setter
public static class Mapping {
- private final String field;
+ private String field;
@Builder.Default
- private final String pad = null;
+ private String pad = null;
@Builder.Default
- @JsonProperty(defaultValue = "-1")
- private final int length = -1;
+ private int length = -1;
@Builder.Default
- @JsonProperty(defaultValue = "true")
- private final boolean resolvable = true;
+ private boolean resolvable = true;
@Builder.Default
- @JsonProperty(defaultValue = "false")
- private final boolean fillAnon = false;
+ private boolean fillAnon = false;
}
From c7e7bfc6cadc57146a019b410213beba93ca4bfa Mon Sep 17 00:00:00 2001
From: Fabian Kovacs <1553491+awildturtok@users.noreply.github.com>
Date: Mon, 26 Jul 2021 09:43:57 +0200
Subject: [PATCH 21/82] adds missing Allargs for builder
---
.../java/com/bakdata/conquery/models/config/ColumnConfig.java | 1 +
1 file changed, 1 insertion(+)
diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java b/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java
index a972be5a62..91f774b001 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java
@@ -22,6 +22,7 @@
public class ColumnConfig {
@Builder
+ @AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
From eb2c7434cc05b599b395f968754c414bbbe2058d Mon Sep 17 00:00:00 2001
From: Fabian Kovacs <1553491+awildturtok@users.noreply.github.com>
Date: Mon, 26 Jul 2021 12:05:03 +0200
Subject: [PATCH 22/82] fix missing negation for resolving
---
.../conquery/models/config/ColumnConfig.java | 58 +++++++------------
.../models/config/FrontendConfig.java | 23 +++-----
.../identifiable/mapping/EntityIdMap.java | 4 +-
3 files changed, 32 insertions(+), 53 deletions(-)
diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java b/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java
index 91f774b001..2ba551ccd2 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java
@@ -6,57 +6,32 @@
import javax.validation.constraints.NotEmpty;
import com.bakdata.conquery.models.identifiable.mapping.EntityIdMap;
-import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.Strings;
-import io.dropwizard.logback.shaded.checkerframework.checker.nullness.qual.Nullable;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
@Data
@Builder
+@AllArgsConstructor
public class ColumnConfig {
- @Builder
- @AllArgsConstructor
- @NoArgsConstructor
- @Getter
- @Setter
- public static class Mapping {
- private String field;
-
- @Builder.Default
- private String pad = null;
-
- @Builder.Default
- private int length = -1;
-
- @Builder.Default
- private boolean resolvable = true;
-
- @Builder.Default
- private boolean fillAnon = false;
-
- }
public EntityIdMap.ExternalId read(String value) {
- if(!mapping.isResolvable()){
- return null; //TODO throw Exception?
+ if (!isResolvable()) {
+ return null;
}
if (Strings.isNullOrEmpty(value)) {
return null;
}
- if (getMapping().getLength() == -1) {
+ if (getLength() == -1) {
return new EntityIdMap.ExternalId(new String[]{getName(), value});
}
- String padded = StringUtils.leftPad(value, getMapping().getLength(), getMapping().getPad());
+ String padded = StringUtils.leftPad(value, getLength(), getPad());
return new EntityIdMap.ExternalId(new String[]{getName(), padded});
@@ -64,21 +39,30 @@ public EntityIdMap.ExternalId read(String value) {
@NotEmpty
- private final String name;
+ private String name;
/**
* Map of Localized labels.
*/
- @Builder.Default
- private final Map label = Collections.emptyMap();
+
+ private Map label = Collections.emptyMap();
/**
* Map of Localized description.
*/
- @Builder.Default
- private final Map description = Collections.emptyMap();
+ private Map description = Collections.emptyMap();
+
+
+ private String field;
+
+ private String pad = null;
+
+
+ private int length = -1;
+
+ private boolean resolvable = false;
+
- @Nullable
- private final Mapping mapping;
+ private boolean fillAnon = false;
}
diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java b/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java
index d1c873d0de..366d050e39 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java
@@ -59,11 +59,9 @@ public static class UploadConfig {
private List ids = List.of(
ColumnConfig.builder()
.name("ID")
- .mapping(ColumnConfig.Mapping.builder()
- .field("id")
- .resolvable(true)
- .fillAnon(true)
- .build())
+ .field("id")
+ .resolvable(true)
+ .fillAnon(true)
.build()
);
@@ -77,9 +75,8 @@ public static class UploadConfig {
public List getPrintIdFields() {
if (idFieldsCached == null) {
idFieldsCached = ids.stream()
- .map(ColumnConfig::getMapping)
+ .map(ColumnConfig::getField)
.filter(Objects::nonNull)
- .map(ColumnConfig.Mapping::getField)
.collect(Collectors.toList());
}
@@ -168,16 +165,15 @@ public boolean isAllColsUnique() {
@ValidationMethod(message = "Not all Id-Columns have mappings.")
@JsonIgnore
public boolean isIdColsHaveMapping() {
- return ids.stream().map(ColumnConfig::getMapping).allMatch(Objects::nonNull);
+ return ids.stream().map(ColumnConfig::getField).allMatch(Objects::nonNull);
}
@ValidationMethod(message = "Must have exactly one Column for Pseudomization.")
@JsonIgnore
public boolean isExactlyOnePseudo() {
return ids.stream()
- .map(ColumnConfig::getMapping)
- .filter(Objects::nonNull)
- .filter(ColumnConfig.Mapping::isFillAnon)
+ .filter(conf -> conf.getField() != null)
+ .filter(ColumnConfig::isFillAnon)
.count() == 1;
}
@@ -200,12 +196,11 @@ public IdPrinter getIdPrinter(User owner, ManagedExecution> execution, Namespa
final int size = getPrintIdFields().size();
final int pos = IntStream.range(0, getIds().size())
- .filter(idx -> getIds().get(idx).getMapping() != null)
- .filter(idx -> getIds().get(idx).getMapping().isFillAnon())
+ .filter(idx -> getIds().get(idx).isFillAnon())
.findFirst()
.orElseThrow();
- return new AutoIncrementingPseudomizer(size,pos);
+ return new AutoIncrementingPseudomizer(size, pos);
}
}
diff --git a/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/EntityIdMap.java b/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/EntityIdMap.java
index 5cbbeee4df..77bcd6363d 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/EntityIdMap.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/EntityIdMap.java
@@ -63,7 +63,7 @@ public static EntityIdMap generateIdMapping(CsvParser parser, List
for (ColumnConfig columnConfig : mappers) {
- final String otherId = record.getString(columnConfig.getMapping().getField());
+ final String otherId = record.getString(columnConfig.getField());
idParts.add(otherId);
@@ -71,7 +71,7 @@ public static EntityIdMap generateIdMapping(CsvParser parser, List
continue;
}
- if (!columnConfig.getMapping().isResolvable()) {
+ if (!columnConfig.isResolvable()) {
continue;
}
From 05e1a02aa5b73dea15677bf0a58d845ed9b7ab0b Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Mon, 26 Jul 2021 10:07:07 +0000
Subject: [PATCH 23/82] Update AutoDoc
---
docs/Config JSON.md | 10 +++++-----
docs/REST API JSONs.md | 10 +++++-----
2 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/docs/Config JSON.md b/docs/Config JSON.md
index 97d541c2ee..c9248a656f 100644
--- a/docs/Config JSON.md
+++ b/docs/Config JSON.md
@@ -223,7 +223,7 @@ Supported Fields:
| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/ConqueryConfig.java#L68) | storage | `@Valid @NotNull StoreFactory` | | | |
-### Type CurrencyConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L212)
+### Type CurrencyConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L207)
Details
@@ -234,10 +234,10 @@ Supported Fields:
| | Field | Type | Default | Example | Description |
| --- | --- | --- | --- | --- | --- |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L217) | decimalScale | `int` | `2` | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L216) | decimalSeparator | `String` | `","` | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L214) | prefix | `String` | `"€"` | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L215) | thousandSeparator | `String` | `"."` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L212) | decimalScale | `int` | `2` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L211) | decimalSeparator | `String` | `","` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L209) | prefix | `String` | `"€"` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L210) | thousandSeparator | `String` | `"."` | | |
### Type FrontendConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L35)
diff --git a/docs/REST API JSONs.md b/docs/REST API JSONs.md
index 34eecedd76..71e7db192b 100644
--- a/docs/REST API JSONs.md
+++ b/docs/REST API JSONs.md
@@ -755,7 +755,7 @@ Supported Fields:
| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/resources/api/ConceptResource.java#L68) | concepts | list of `String` | `null` | | |
-### Type CurrencyConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L212)
+### Type CurrencyConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L207)
Details
@@ -766,10 +766,10 @@ Supported Fields:
| | Field | Type | Default | Example | Description |
| --- | --- | --- | --- | --- | --- |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L217) | decimalScale | `int` | `2` | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L216) | decimalSeparator | `String` | `","` | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L214) | prefix | `String` | `"€"` | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L215) | thousandSeparator | `String` | `"."` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L212) | decimalScale | `int` | `2` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L211) | decimalSeparator | `String` | `","` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L209) | prefix | `String` | `"€"` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L210) | thousandSeparator | `String` | `"."` | | |
### Type ExecutionStatus [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/apiv1/ExecutionStatus.java#L18)
From b1fb70a39bfa792f1d142baab37c4563f0d4e026 Mon Sep 17 00:00:00 2001
From: Fabian Kovacs <1553491+awildturtok@users.noreply.github.com>
Date: Mon, 26 Jul 2021 12:08:46 +0200
Subject: [PATCH 24/82] allow optional fields
---
.../com/bakdata/conquery/models/config/ColumnConfig.java | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java b/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java
index 2ba551ccd2..6ffc37ccf1 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java
@@ -10,11 +10,17 @@
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
import org.apache.commons.lang3.StringUtils;
-@Data
@Builder
@AllArgsConstructor
+@ToString
+@NoArgsConstructor @Setter
+@Getter
public class ColumnConfig {
From 02a188845a4c2ba62468858746a0199197a8aba5 Mon Sep 17 00:00:00 2001
From: Fabian Kovacs <1553491+awildturtok@users.noreply.github.com>
Date: Mon, 26 Jul 2021 12:19:01 +0200
Subject: [PATCH 25/82] add internalOnly anno
---
.../bakdata/conquery/models/config/ColumnConfig.java | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java b/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java
index 6ffc37ccf1..fc15fe7d5f 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java
@@ -5,11 +5,11 @@
import javax.validation.constraints.NotEmpty;
+import com.bakdata.conquery.io.jackson.InternalOnly;
import com.bakdata.conquery.models.identifiable.mapping.EntityIdMap;
import com.google.common.base.Strings;
import lombok.AllArgsConstructor;
import lombok.Builder;
-import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@@ -19,7 +19,8 @@
@Builder
@AllArgsConstructor
@ToString
-@NoArgsConstructor @Setter
+@NoArgsConstructor
+@Setter
@Getter
public class ColumnConfig {
@@ -58,17 +59,18 @@ public EntityIdMap.ExternalId read(String value) {
*/
private Map description = Collections.emptyMap();
-
+ @InternalOnly
private String field;
+ @InternalOnly
private String pad = null;
-
+ @InternalOnly
private int length = -1;
private boolean resolvable = false;
-
+ @InternalOnly
private boolean fillAnon = false;
}
From cb2c03917c2503ff41adfa74e5137241ba0f2388 Mon Sep 17 00:00:00 2001
From: Fabian Kovacs <1553491+awildturtok@users.noreply.github.com>
Date: Mon, 26 Jul 2021 16:33:41 +0200
Subject: [PATCH 26/82] also adds endpoint for uploading external result lists
---
.../conquery/apiv1/QueryProcessor.java | 38 ++++++++++
.../concept/specific/external/CQExternal.java | 73 +++++++++++++------
.../conquery/resources/api/QueryResource.java | 19 +++++
.../tests/endpoints/apiEndpointInfo.json | 5 ++
4 files changed, 111 insertions(+), 24 deletions(-)
diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/QueryProcessor.java b/backend/src/main/java/com/bakdata/conquery/apiv1/QueryProcessor.java
index bda960ed8d..db81e07e5e 100644
--- a/backend/src/main/java/com/bakdata/conquery/apiv1/QueryProcessor.java
+++ b/backend/src/main/java/com/bakdata/conquery/apiv1/QueryProcessor.java
@@ -13,6 +13,7 @@
import java.util.stream.Stream;
import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import com.bakdata.conquery.apiv1.query.CQElement;
@@ -44,10 +45,12 @@
import com.bakdata.conquery.models.query.visitor.QueryVisitor;
import com.bakdata.conquery.models.worker.DatasetRegistry;
import com.bakdata.conquery.models.worker.Namespace;
+import com.bakdata.conquery.resources.api.QueryResource;
import com.bakdata.conquery.util.QueryUtils;
import com.bakdata.conquery.util.QueryUtils.NamespacedIdentifiableCollector;
import com.google.common.collect.ClassToInstanceMap;
import com.google.common.collect.MutableClassToInstanceMap;
+import lombok.Data;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -359,5 +362,40 @@ public FullExecutionStatus getQueryFullStatus(ManagedExecution> query, User us
return status;
}
+ @Data
+ public static class UploadResponse {
+ private final ManagedExecutionId execution;
+ private final int resolved;
+
+ private final List unresolvedId;
+ private final List unreadableDate;
+ }
+
+ public Response uploadEntities(User user, Dataset dataset, QueryResource.ExternalUpload upload) {
+ final CQExternal.ResolveStatistic statistic = CQExternal.resolveEntities(upload.getValues(), upload.getFormat(),
+ datasetRegistry.get(dataset.getId()).getStorage().getIdMapping(),
+ config.getFrontend().getQueryUpload(),
+ config.getPreprocessor().getParsers().getDateReader()
+ );
+
+ // Resolving nothing is a problem and we fail.
+ if (statistic.getResolved().isEmpty()) {
+ return Response.status(Response.Status.BAD_REQUEST)
+ .entity(new UploadResponse(null, 0, statistic.getUnresolvedId(), statistic.getUnreadableDate()))
+ .build();
+ }
+
+ final ConceptQuery query = new ConceptQuery(new CQExternal(upload.getFormat(), upload.getValues()));
+ final ManagedExecution> execution = postQuery(dataset, query, user);
+
+ return Response.ok()
+ .entity(new UploadResponse(
+ execution.getId(),
+ statistic.getResolved().size(),
+ statistic.getUnresolvedId(),
+ statistic.getUnreadableDate()
+ ))
+ .build();
+ }
}
diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java
index ba4994e0f2..c4031c3464 100644
--- a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java
+++ b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java
@@ -4,10 +4,10 @@
import java.util.Arrays;
import java.util.List;
import java.util.Map;
-import java.util.Objects;
import java.util.stream.Collectors;
import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
import com.bakdata.conquery.apiv1.query.CQElement;
import com.bakdata.conquery.io.cps.CPSType;
@@ -30,8 +30,7 @@
import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
-import it.unimi.dsi.fastutil.ints.IntArrayList;
-import it.unimi.dsi.fastutil.ints.IntList;
+import lombok.Data;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
@@ -71,7 +70,7 @@ public QPNode createQueryPlan(QueryPlanContext context, ConceptQueryPlan plan) {
}
- private Int2ObjectMap readDates(String[][] values, List format, DateReader dateReader, FrontendConfig.UploadConfig queryUpload) {
+ private static Int2ObjectMap readDates(String[][] values, List format, DateReader dateReader, FrontendConfig.UploadConfig queryUpload) {
Int2ObjectMap out = new Int2ObjectAVLTreeMap<>();
@@ -103,14 +102,52 @@ private Int2ObjectMap readDates(String[][] values, List format
@Override
public void resolve(QueryResolveContext context) {
- valuesResolved = new Int2ObjectOpenHashMap<>();
+ final ResolveStatistic resolved = resolveEntities(values, format, context.getNamespace().getStorage().getIdMapping(), context.getConfig().getFrontend().getQueryUpload(), context.getConfig().getPreprocessor().getParsers().getDateReader());
- final EntityIdMap mapping = context.getNamespace().getStorage().getIdMapping();
+ if (resolved.getResolved().isEmpty()) {
+ throw new ConqueryError.ExternalResolveEmptyError();
+ }
+
+ if (!resolved.getUnreadableDate().isEmpty()) {
+ log.warn(
+ "Could not read dates {} of the {} rows. Not resolved: {}",
+ resolved.getUnreadableDate().size(),
+ values.length - 1,
+ resolved.getUnreadableDate().subList(0, Math.min(resolved.getUnreadableDate().size(), 10))
+ );
+ }
+
+ if (!resolved.getUnresolvedId().isEmpty()) {
+ log.warn(
+ "Could not read dates {} of the {} rows. Not resolved: {}",
+ resolved.getUnresolvedId().size(),
+ values.length - 1,
+ resolved.getUnresolvedId().subList(0, Math.min(resolved.getUnresolvedId().size(), 10))
+ );
+ }
+
+ valuesResolved = resolved.getResolved();
+ }
- final DateReader dateReader = context.getConfig().getPreprocessor().getParsers().getDateReader();
+ @Data
+ public static class ResolveStatistic {
+
+ @JsonIgnore
+ private final Map resolved;
+
+ private final List unreadableDate;
+ private final List unresolvedId;
+
+ }
+
+ public static ResolveStatistic resolveEntities(@NotEmpty String[][] values, @NotEmpty List format, EntityIdMap mapping, FrontendConfig.UploadConfig queryUpload, @NotNull DateReader dateReader) {
+ Map resolved = new Int2ObjectOpenHashMap<>();
+
+ List unresolvedDate = new ArrayList<>();
+ List unresolvedId = new ArrayList<>();
// extract dates from rows
- final FrontendConfig.UploadConfig uploadConfig = context.getConfig().getFrontend().getQueryUpload();
+ final FrontendConfig.UploadConfig uploadConfig = queryUpload;
final Int2ObjectMap rowDates = readDates(values, format, dateReader, uploadConfig);
@@ -118,7 +155,6 @@ public void resolve(QueryResolveContext context) {
final ColumnConfig reader = uploadConfig.getIdMapper(format.get(idIndex));
- final List unresolved = new ArrayList<>();
// ignore the first row, because this is the header
for (int rowNum = 1; rowNum < values.length; rowNum++) {
@@ -128,31 +164,20 @@ public void resolve(QueryResolveContext context) {
final int resolvedId = mapping.resolve(externalId);
if (resolvedId == -1) {
- unresolved.add(row);
+ unresolvedId.add(row);
continue;
}
if (!rowDates.containsKey(rowNum)) {
- unresolved.add(row);
+ unresolvedDate.add(row);
continue;
}
//read the dates from the row
- valuesResolved.put(resolvedId, rowDates.get(rowNum));
+ resolved.put(resolvedId, rowDates.get(rowNum));
}
- if (!unresolved.isEmpty()) {
- log.warn(
- "Could not resolve {} of the {} rows. Not resolved: {}",
- unresolved.size(),
- values.length - 1,
- unresolved.subList(0, Math.min(unresolved.size(), 10))
- );
- }
-
- if (valuesResolved.isEmpty()) {
- throw new ConqueryError.ExternalResolveEmptyError();
- }
+ return new ResolveStatistic(resolved,unresolvedDate,unresolvedId);
}
diff --git a/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java b/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java
index 1758f69536..cc1f8a4674 100644
--- a/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java
+++ b/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java
@@ -3,13 +3,17 @@
import com.bakdata.conquery.apiv1.*;
import com.bakdata.conquery.apiv1.query.QueryDescription;
+import com.bakdata.conquery.apiv1.query.concept.specific.external.CQExternal;
import com.bakdata.conquery.models.auth.entities.User;
import com.bakdata.conquery.models.auth.permissions.Ability;
import com.bakdata.conquery.models.datasets.Dataset;
import com.bakdata.conquery.models.exceptions.JSONException;
import com.bakdata.conquery.models.execution.ManagedExecution;
+import com.bakdata.conquery.models.identifiable.ids.specific.ManagedExecutionId;
import io.dropwizard.auth.Auth;
import io.dropwizard.jersey.PATCH;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import javax.inject.Inject;
@@ -120,4 +124,19 @@ public void cancel(@Auth User user, @PathParam(QUERY) ManagedExecution> query)
query
);
}
+
+ @RequiredArgsConstructor
+ @Getter
+ public static class ExternalUpload {
+ private final List format;
+ private final String[][] values;
+
+ private final ManagedExecutionId executionId;
+ }
+
+ @POST
+ @Path("/upload/")
+ public Response upload(@Auth User user, ExternalUpload upload) {
+ return processor.uploadEntities(user, dataset, upload);
+ }
}
diff --git a/backend/src/test/resources/tests/endpoints/apiEndpointInfo.json b/backend/src/test/resources/tests/endpoints/apiEndpointInfo.json
index 65a2ebb17e..a55bb6bdf6 100644
--- a/backend/src/test/resources/tests/endpoints/apiEndpointInfo.json
+++ b/backend/src/test/resources/tests/endpoints/apiEndpointInfo.json
@@ -14,6 +14,11 @@
"path": "/datasets/{dataset}/queries",
"clazz": "QueryResource"
},
+ {
+ "method": "POST",
+ "path": "/datasets/{dataset}/queries/upload",
+ "clazz": "QueryResource"
+ },
{
"method": "GET",
"path": "/datasets/{dataset}/queries/{query}",
From 742493325ee1197f79444387b5c0217e5cb69743 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Mon, 26 Jul 2021 14:35:20 +0000
Subject: [PATCH 27/82] Update AutoDoc
---
docs/REST API JSONs.md | 30 ++++++++++++++++++++++--------
1 file changed, 22 insertions(+), 8 deletions(-)
diff --git a/docs/REST API JSONs.md b/docs/REST API JSONs.md
index 310c70624e..884b863b2e 100644
--- a/docs/REST API JSONs.md
+++ b/docs/REST API JSONs.md
@@ -103,7 +103,7 @@ Returns: [ResolvedConceptsResult](#Type-ResolvedConceptsResult)
-### GET datasets/{dataset}/queries [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java#L46)
+### GET datasets/{dataset}/queries [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java#L50)
Details
@@ -117,7 +117,7 @@ Returns: list of [ExecutionStatus](#Type-ExecutionStatus)
-### POST datasets/{dataset}/queries [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java#L55)
+### POST datasets/{dataset}/queries [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java#L59)
Details
@@ -132,7 +132,21 @@ Returns: `Response`
-### GET datasets/{dataset}/queries/{query} [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java#L67)
+### POST datasets/{dataset}/queries/upload/ [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java#L137)
+
+
+Details
+
+Java Type: `com.bakdata.conquery.resources.api.QueryResource`
+
+Method: `upload`
+
+Expects: `ExternalUpload`
+Returns: `Response`
+
+
+
+### GET datasets/{dataset}/queries/{query} [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java#L71)
Details
@@ -146,7 +160,7 @@ Returns: [FullExecutionStatus](#Type-FullExecutionStatus)
-### PATCH datasets/{dataset}/queries/{query} [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java#L80)
+### PATCH datasets/{dataset}/queries/{query} [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java#L84)
Details
@@ -161,7 +175,7 @@ Returns: [FullExecutionStatus](#Type-FullExecutionStatus)
-### DELETE datasets/{dataset}/queries/{query} [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java#L91)
+### DELETE datasets/{dataset}/queries/{query} [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java#L95)
Details
@@ -174,7 +188,7 @@ Returns: `void`
-### POST datasets/{dataset}/queries/{query}/cancel [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java#L110)
+### POST datasets/{dataset}/queries/{query}/cancel [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java#L114)
Details
@@ -187,7 +201,7 @@ Returns: `void`
-### POST datasets/{dataset}/queries/{query}/reexecute [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java#L100)
+### POST datasets/{dataset}/queries/{query}/reexecute [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java#L104)
Details
@@ -495,7 +509,7 @@ Supported Fields:
| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/apiv1/query/CQElement.java#L31-L33) | label | `String` | ? | | Allows the user to define labels. |
-### EXTERNAL [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java#L38-L40)
+### EXTERNAL [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java#L37-L39)
Allows uploading lists of entities.
Details
From d261a24797a4cad8696e9ab8c35fde7dc8f5d542 Mon Sep 17 00:00:00 2001
From: Fabian Kovacs <1553491+awildturtok@users.noreply.github.com>
Date: Tue, 27 Jul 2021 09:36:21 +0200
Subject: [PATCH 28/82] adds missing initialization of Table#getColumns
---
.../conquery/resources/admin/rest/AdminDatasetProcessor.java | 3 +++
1 file changed, 3 insertions(+)
diff --git a/backend/src/main/java/com/bakdata/conquery/resources/admin/rest/AdminDatasetProcessor.java b/backend/src/main/java/com/bakdata/conquery/resources/admin/rest/AdminDatasetProcessor.java
index 391b8af522..6515969224 100644
--- a/backend/src/main/java/com/bakdata/conquery/resources/admin/rest/AdminDatasetProcessor.java
+++ b/backend/src/main/java/com/bakdata/conquery/resources/admin/rest/AdminDatasetProcessor.java
@@ -195,10 +195,13 @@ else if (!table.getDataset().equals(dataset)) {
throw new IllegalArgumentException();
}
+
if (namespace.getStorage().getTable(table.getId()) != null) {
throw new WebApplicationException("Table already exists", Response.Status.CONFLICT);
}
+ table.init();
+
ValidatorHelper.failOnError(log, validator.validate(table));
namespace.getStorage().addTable(table);
From 34d058d1d9e300fa9d33450e717610587549b634 Mon Sep 17 00:00:00 2001
From: Fabian Kovacs <1553491+awildturtok@users.noreply.github.com>
Date: Tue, 27 Jul 2021 09:40:52 +0200
Subject: [PATCH 29/82] add exclude to DictionaryMapping
---
.../bakdata/conquery/models/dictionary/DictionaryMapping.java | 3 +++
1 file changed, 3 insertions(+)
diff --git a/backend/src/main/java/com/bakdata/conquery/models/dictionary/DictionaryMapping.java b/backend/src/main/java/com/bakdata/conquery/models/dictionary/DictionaryMapping.java
index 707c3ac287..00ad342eef 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/dictionary/DictionaryMapping.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/dictionary/DictionaryMapping.java
@@ -22,9 +22,12 @@
public class DictionaryMapping {
private final Dictionary sourceDictionary;
+
private final Dictionary targetDictionary;
+ @ToString.Exclude
private final Int2IntMap source2Target;
+ @ToString.Exclude
private final Int2IntMap target2Source;
private final int numberOfNewIds;
From 1f066650e80e41ae5a89abe23c4f356475410a9c Mon Sep 17 00:00:00 2001
From: Fabian Kovacs <1553491+awildturtok@users.noreply.github.com>
Date: Tue, 27 Jul 2021 09:52:39 +0200
Subject: [PATCH 30/82] undo InternalOnly annos in conf as they will not be
read
---
.../java/com/bakdata/conquery/models/config/ColumnConfig.java | 4 ----
1 file changed, 4 deletions(-)
diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java b/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java
index fc15fe7d5f..3d7772b1a4 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java
@@ -59,18 +59,14 @@ public EntityIdMap.ExternalId read(String value) {
*/
private Map description = Collections.emptyMap();
- @InternalOnly
private String field;
- @InternalOnly
private String pad = null;
- @InternalOnly
private int length = -1;
private boolean resolvable = false;
- @InternalOnly
private boolean fillAnon = false;
}
From ce394c4f33498e57c2bbb21c985c9d17489bed37 Mon Sep 17 00:00:00 2001
From: Fabian Kovacs <1553491+awildturtok@users.noreply.github.com>
Date: Tue, 27 Jul 2021 11:02:57 +0200
Subject: [PATCH 31/82] only create Query, don't run it
---
.../java/com/bakdata/conquery/apiv1/QueryProcessor.java | 5 ++++-
.../bakdata/conquery/models/query/ExecutionManager.java | 9 ---------
.../bakdata/conquery/resources/api/QueryResource.java | 2 +-
3 files changed, 5 insertions(+), 11 deletions(-)
diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/QueryProcessor.java b/backend/src/main/java/com/bakdata/conquery/apiv1/QueryProcessor.java
index db81e07e5e..8e8258fe17 100644
--- a/backend/src/main/java/com/bakdata/conquery/apiv1/QueryProcessor.java
+++ b/backend/src/main/java/com/bakdata/conquery/apiv1/QueryProcessor.java
@@ -387,7 +387,10 @@ public Response uploadEntities(User user, Dataset dataset, QueryResource.Externa
}
final ConceptQuery query = new ConceptQuery(new CQExternal(upload.getFormat(), upload.getValues()));
- final ManagedExecution> execution = postQuery(dataset, query, user);
+
+ // We only create the Query, really no need to execute it as it's only useful for composition.
+ final ManagedExecution> execution =
+ datasetRegistry.get(dataset.getId()).getExecutionManager().createExecution(datasetRegistry, query, user, dataset);
return Response.ok()
.entity(new UploadResponse(
diff --git a/backend/src/main/java/com/bakdata/conquery/models/query/ExecutionManager.java b/backend/src/main/java/com/bakdata/conquery/models/query/ExecutionManager.java
index 6ac7b0735f..c62b789163 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/query/ExecutionManager.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/query/ExecutionManager.java
@@ -95,15 +95,6 @@ public ManagedExecution> createExecution(DatasetRegistry datasets, QueryDescri
return createQuery(datasets, query, UUID.randomUUID(), user, submittedDataset);
}
- /**
- * Send message for query execution to all workers.
- */
- private ManagedExecution> executeQueryInNamespace(ManagedExecution> query) {
- final WorkerMessage executionMessage = query.createExecutionMessage();
-
- namespace.sendToAll(executionMessage);
- return query;
- }
public ManagedExecution> createQuery(DatasetRegistry datasets, QueryDescription query, UUID queryId, User user, Dataset submittedDataset) {
// Transform the submitted query into an initialized execution
diff --git a/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java b/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java
index cc1f8a4674..d5825aa3ca 100644
--- a/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java
+++ b/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java
@@ -135,7 +135,7 @@ public static class ExternalUpload {
}
@POST
- @Path("/upload/")
+ @Path("/upload")
public Response upload(@Auth User user, ExternalUpload upload) {
return processor.uploadEntities(user, dataset, upload);
}
From 4f55967bf179d2cf1c6f31871a4aac601317b5ee Mon Sep 17 00:00:00 2001
From: Fabian Kovacs <1553491+awildturtok@users.noreply.github.com>
Date: Tue, 27 Jul 2021 11:18:42 +0200
Subject: [PATCH 32/82] check for validity of ColumnConfig and locale keys
---
.../conquery/models/config/ColumnConfig.java | 19 ++++++++++++++++++-
.../models/config/FrontendConfig.java | 8 +++++++-
2 files changed, 25 insertions(+), 2 deletions(-)
diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java b/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java
index 3d7772b1a4..a2233799a5 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java
@@ -1,13 +1,18 @@
package com.bakdata.conquery.models.config;
import java.util.Collections;
+import java.util.Locale;
import java.util.Map;
+import java.util.Objects;
import javax.validation.constraints.NotEmpty;
+import c10n.C10N;
import com.bakdata.conquery.io.jackson.InternalOnly;
import com.bakdata.conquery.models.identifiable.mapping.EntityIdMap;
+import com.fasterxml.jackson.annotation.JsonIgnore;
import com.google.common.base.Strings;
+import io.dropwizard.validation.ValidationMethod;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
@@ -51,7 +56,7 @@ public EntityIdMap.ExternalId read(String value) {
/**
* Map of Localized labels.
*/
-
+ @NotEmpty
private Map label = Collections.emptyMap();
/**
@@ -69,4 +74,16 @@ public EntityIdMap.ExternalId read(String value) {
private boolean fillAnon = false;
+ @JsonIgnore
+ @ValidationMethod(message = "Keys must be valid Locales.")
+ public boolean isLabelKeysLocale() {
+ return getLabel().keySet().stream().map(Locale::forLanguageTag).noneMatch(Objects::isNull);
+ }
+
+ @JsonIgnore
+ @ValidationMethod(message = "Keys must be valid Locales.")
+ public boolean isDescriptionKeysLocale() {
+ return getDescription().keySet().stream().map(Locale::forLanguageTag).noneMatch(Objects::isNull);
+ }
+
}
diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java b/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java
index 366d050e39..cfed108cb4 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java
@@ -56,6 +56,7 @@ public class FrontendConfig {
public static class UploadConfig {
@NotEmpty
+ @Valid
private List ids = List.of(
ColumnConfig.builder()
.name("ID")
@@ -94,7 +95,7 @@ public int getIdIndex(List format) {
for (int index = 0; index < format.size(); index++) {
final String current = format.get(index);
- if (ids.stream().map(ColumnConfig::getName).anyMatch(current::equals)) {
+ if (getIdMapper(current) != null) {
return index;
}
}
@@ -103,6 +104,7 @@ public int getIdIndex(List format) {
}
@NotNull
+ @Valid
private ColumnConfig dateStart = ColumnConfig.builder()
.name(DateFormat.START_DATE.name())
.label(Map.of("en", "Begin"))
@@ -110,6 +112,7 @@ public int getIdIndex(List format) {
.build();
@NotNull
+ @Valid
private ColumnConfig dateEnd = ColumnConfig.builder()
.name(DateFormat.END_DATE.name())
.label(Map.of("en", "End"))
@@ -118,6 +121,7 @@ public int getIdIndex(List format) {
@NotNull
+ @Valid
private ColumnConfig dateRange = ColumnConfig.builder()
.name(DateFormat.DATE_RANGE.name())
.label(Map.of("en", "Date Range"))
@@ -126,6 +130,7 @@ public int getIdIndex(List format) {
@NotNull
+ @Valid
private ColumnConfig dateSet = ColumnConfig.builder()
.name(DateFormat.DATE_SET.name())
.label(Map.of("en", "Dateset"))
@@ -134,6 +139,7 @@ public int getIdIndex(List format) {
@NotNull
+ @Valid
private ColumnConfig eventDate = ColumnConfig.builder()
.name(DateFormat.EVENT_DATE.name())
.label(Map.of("en", "Event Date"))
From f620dd63f80fccdb5e98bf2e234c50634143341a Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Tue, 27 Jul 2021 09:20:37 +0000
Subject: [PATCH 33/82] Update AutoDoc
---
docs/Config JSON.md | 10 +++++-----
docs/REST API JSONs.md | 12 ++++++------
2 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/docs/Config JSON.md b/docs/Config JSON.md
index c9248a656f..adb95b4ea6 100644
--- a/docs/Config JSON.md
+++ b/docs/Config JSON.md
@@ -223,7 +223,7 @@ Supported Fields:
| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/ConqueryConfig.java#L68) | storage | `@Valid @NotNull StoreFactory` | | | |
-### Type CurrencyConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L207)
+### Type CurrencyConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L213)
Details
@@ -234,10 +234,10 @@ Supported Fields:
| | Field | Type | Default | Example | Description |
| --- | --- | --- | --- | --- | --- |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L212) | decimalScale | `int` | `2` | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L211) | decimalSeparator | `String` | `","` | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L209) | prefix | `String` | `"€"` | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L210) | thousandSeparator | `String` | `"."` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L218) | decimalScale | `int` | `2` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L217) | decimalSeparator | `String` | `","` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L215) | prefix | `String` | `"€"` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L216) | thousandSeparator | `String` | `"."` | | |
### Type FrontendConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L35)
diff --git a/docs/REST API JSONs.md b/docs/REST API JSONs.md
index 884b863b2e..4862d0891d 100644
--- a/docs/REST API JSONs.md
+++ b/docs/REST API JSONs.md
@@ -132,7 +132,7 @@ Returns: `Response`
-### POST datasets/{dataset}/queries/upload/ [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java#L137)
+### POST datasets/{dataset}/queries/upload [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java#L137)
Details
@@ -755,7 +755,7 @@ Supported Fields:
| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/resources/api/ConceptResource.java#L68) | concepts | list of `String` | `null` | | |
-### Type CurrencyConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L207)
+### Type CurrencyConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L213)
Details
@@ -766,10 +766,10 @@ Supported Fields:
| | Field | Type | Default | Example | Description |
| --- | --- | --- | --- | --- | --- |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L212) | decimalScale | `int` | `2` | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L211) | decimalSeparator | `String` | `","` | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L209) | prefix | `String` | `"€"` | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L210) | thousandSeparator | `String` | `"."` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L218) | decimalScale | `int` | `2` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L217) | decimalSeparator | `String` | `","` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L215) | prefix | `String` | `"€"` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L216) | thousandSeparator | `String` | `"."` | | |
### Type ExecutionStatus [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/apiv1/ExecutionStatus.java#L18)
From 70b5aeaad04591e3dce11d2f85fef31288a621c1 Mon Sep 17 00:00:00 2001
From: Fabian Kovacs <1553491+awildturtok@users.noreply.github.com>
Date: Tue, 27 Jul 2021 11:59:03 +0200
Subject: [PATCH 34/82] use view to reduce API surface for QueryUpload
---
.../java/com/bakdata/conquery/Conquery.java | 10 ++++++++--
.../conquery/models/config/ColumnConfig.java | 3 +++
.../conquery/models/config/FrontendConfig.java | 2 +-
.../conquery/resources/api/ConfigResource.java | 17 ++++++++++++++---
4 files changed, 26 insertions(+), 6 deletions(-)
diff --git a/backend/src/main/java/com/bakdata/conquery/Conquery.java b/backend/src/main/java/com/bakdata/conquery/Conquery.java
index af84bae5d4..4c54818fa9 100644
--- a/backend/src/main/java/com/bakdata/conquery/Conquery.java
+++ b/backend/src/main/java/com/bakdata/conquery/Conquery.java
@@ -12,10 +12,12 @@
import com.bakdata.conquery.commands.RecodeStoreCommand;
import com.bakdata.conquery.commands.ShardNode;
import com.bakdata.conquery.commands.StandaloneCommand;
+import com.bakdata.conquery.io.jackson.InternalOnly;
import com.bakdata.conquery.io.jackson.Jackson;
import com.bakdata.conquery.io.jackson.MutableInjectableValues;
import com.bakdata.conquery.models.config.ConqueryConfig;
import com.bakdata.conquery.util.UrlRewriteBundle;
+import com.fasterxml.jackson.databind.ObjectMapper;
import io.dropwizard.Application;
import io.dropwizard.ConfiguredBundle;
import io.dropwizard.configuration.JsonConfigurationFactory;
@@ -44,7 +46,11 @@ public Conquery() {
@Override
public void initialize(Bootstrap bootstrap) {
- Jackson.configure(bootstrap.getObjectMapper());
+ final ObjectMapper confMapper = bootstrap.getObjectMapper();
+ Jackson.configure(confMapper);
+
+ confMapper.setConfig(confMapper.getDeserializationConfig().withView(InternalOnly.class));
+
// check for java compiler, needed for the class generation
if (ToolProvider.getSystemJavaCompiler() == null) {
throw new IllegalStateException("Conquery requires to be run on either a JDK or a ServerJRE");
@@ -59,7 +65,7 @@ public void initialize(Bootstrap bootstrap) {
bootstrap.addCommand(new StandaloneCommand(this));
bootstrap.addCommand(new RecodeStoreCommand());
- ((MutableInjectableValues)bootstrap.getObjectMapper().getInjectableValues()).add(Validator.class, bootstrap.getValidatorFactory().getValidator());
+ ((MutableInjectableValues) confMapper.getInjectableValues()).add(Validator.class, bootstrap.getValidatorFactory().getValidator());
// do some setup in other classes after initialization but before running a
// command
diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java b/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java
index a2233799a5..6158277ca5 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java
@@ -66,12 +66,15 @@ public EntityIdMap.ExternalId read(String value) {
private String field;
+ @InternalOnly
private String pad = null;
+ @InternalOnly
private int length = -1;
private boolean resolvable = false;
+ @InternalOnly
private boolean fillAnon = false;
@JsonIgnore
diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java b/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java
index cfed108cb4..9406bbdedd 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java
@@ -35,10 +35,10 @@
@ToString
@Getter
@Setter
-@With
@AllArgsConstructor
@NoArgsConstructor
@Slf4j
+@With
public class FrontendConfig {
private String version = VersionInfo.INSTANCE.getProjectVersion();
diff --git a/backend/src/main/java/com/bakdata/conquery/resources/api/ConfigResource.java b/backend/src/main/java/com/bakdata/conquery/resources/api/ConfigResource.java
index a7655e84e3..2c43f41df2 100644
--- a/backend/src/main/java/com/bakdata/conquery/resources/api/ConfigResource.java
+++ b/backend/src/main/java/com/bakdata/conquery/resources/api/ConfigResource.java
@@ -1,10 +1,13 @@
package com.bakdata.conquery.resources.api;
+import java.util.stream.Collectors;
+
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import com.bakdata.conquery.apiv1.AdditionalMediaTypes;
+import com.bakdata.conquery.models.config.ColumnConfig;
import com.bakdata.conquery.models.config.ConqueryConfig;
import com.bakdata.conquery.models.config.FrontendConfig;
import lombok.RequiredArgsConstructor;
@@ -20,8 +23,16 @@ public class ConfigResource {
@GET
@Path("frontend")
public FrontendConfig getFrontendConfig() {
-
-
- return config.getFrontend();
+ // Filter Ids that are not resolvable
+ return config.getFrontend()
+ .withQueryUpload(config.getFrontend()
+ .getQueryUpload()
+ .withIds(config.getFrontend()
+ .getQueryUpload()
+ .getIds()
+ .stream()
+ .filter(ColumnConfig::isResolvable)
+ .collect(Collectors.toList())));
}
+
}
\ No newline at end of file
From 5c6e72f94923b32d9ee04c3bed1da6bc90b4974d Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Tue, 27 Jul 2021 10:01:19 +0000
Subject: [PATCH 35/82] Update AutoDoc
---
docs/REST API JSONs.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/REST API JSONs.md b/docs/REST API JSONs.md
index 4862d0891d..159501ca89 100644
--- a/docs/REST API JSONs.md
+++ b/docs/REST API JSONs.md
@@ -20,7 +20,7 @@ Returns: list of [IdLabel](#Type-IdLabel)
-### GET config/frontend [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/resources/api/ConfigResource.java#L20)
+### GET config/frontend [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/resources/api/ConfigResource.java#L23)
Details
From 0dbdcb2e848e3abc091b20b10c20d4c50b06fd00 Mon Sep 17 00:00:00 2001
From: Fabian Kovacs <1553491+awildturtok@users.noreply.github.com>
Date: Tue, 27 Jul 2021 12:01:47 +0200
Subject: [PATCH 36/82] remove more fields from API
---
.../java/com/bakdata/conquery/models/config/ColumnConfig.java | 2 ++
1 file changed, 2 insertions(+)
diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java b/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java
index 6158277ca5..707d267446 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java
@@ -64,6 +64,7 @@ public EntityIdMap.ExternalId read(String value) {
*/
private Map description = Collections.emptyMap();
+ @InternalOnly
private String field;
@InternalOnly
@@ -72,6 +73,7 @@ public EntityIdMap.ExternalId read(String value) {
@InternalOnly
private int length = -1;
+ @InternalOnly
private boolean resolvable = false;
@InternalOnly
From 12e9e417c752a6ee02c2a1f01835649a0bae5c2b Mon Sep 17 00:00:00 2001
From: Fabian Kovacs <1553491+awildturtok@users.noreply.github.com>
Date: Tue, 27 Jul 2021 15:07:48 +0200
Subject: [PATCH 37/82] use the csv output directly from the endpoint
---
.../concept/specific/external/CQExternal.java | 24 ++--
.../concept/specific/external/DateFormat.java | 53 +++------
.../io/result/csv/ResultCsvProcessor.java | 3 +-
.../models/config/FrontendConfig.java | 6 +-
.../com/bakdata/conquery/util/io/Cloner.java | 32 +++---
.../integration/IntegrationTests.java | 107 +++++++++++-------
.../json/AbstractQueryEngineTest.java | 51 +++++----
.../conquery/util/support/TestConquery.java | 4 +-
8 files changed, 143 insertions(+), 137 deletions(-)
diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java
index c4031c3464..12c4d06913 100644
--- a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java
+++ b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java
@@ -78,19 +78,25 @@ private static Int2ObjectMap readDates(String[][] values, List
//validate structures
- final int[] datePositions = DateFormat.select(dateFormats);
-
- DateFormat dateFormat = datePositions.length > 0 ? dateFormats.get(datePositions[0]) : DateFormat.ALL;
-
for (int row = 1; row < values.length; row++) {
try {
- final CDateSet dates = dateFormat.readDates(datePositions, values[row], dateReader);
+ for (int col = 0; col < dateFormats.size(); col++) {
+ final DateFormat dateFormat = dateFormats.get(col);
- if (dates == null) {
- continue;
- }
+ if(dateFormat == null){
+ continue;
+ }
+
+ CDateSet dates = CDateSet.create();
- out.put(row, dates);
+ dateFormat.readDates(values[row][col], dateReader, dates);
+
+ if (dates.isEmpty()) {
+ continue;
+ }
+
+ out.put(row, dates);
+ }
}
catch (Exception e) {
log.warn("Failed to parse Date from {}", row, e);
diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateFormat.java b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateFormat.java
index d172a177c3..e4c83a7308 100644
--- a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateFormat.java
+++ b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateFormat.java
@@ -1,7 +1,5 @@
package com.bakdata.conquery.apiv1.query.concept.specific.external;
-import java.time.LocalDate;
-import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
@@ -14,68 +12,43 @@
public enum DateFormat {
EVENT_DATE {
@Override
- public CDateSet readDates(int[] formats, String[] row, DateReader dateReader) {
- final int index = formats[0];
-
- return CDateSet.create(Collections.singleton(CDateRange.exactly(dateReader.parseToLocalDate(row[index]))));
+ public void readDates(String value, DateReader dateReader, CDateSet out) {
+ out.add(CDateRange.exactly(dateReader.parseToLocalDate(value)));
}
},
END_DATE {
@Override
- public CDateSet readDates(int[] formats, String[] row, DateReader dateReader) {
-
- if (formats.length == 1) {
- return CDateSet.create(CDateRange.atMost(dateReader.parseToLocalDate(row[0])));
- }
-
- return END_DATE.readDates(formats, row, dateReader);
+ public void readDates(String value, DateReader dateReader, CDateSet out) {
+ out.add(CDateRange.atMost(dateReader.parseToLocalDate(value)));
}
},
START_DATE {
@Override
- public CDateSet readDates(int[] formats, String[] row, DateReader dateReader) {
-
- if (formats.length == 1) {
- return CDateSet.create(CDateRange.atLeast(dateReader.parseToLocalDate(row[0])));
- }
-
- final int startIndex = formats[0];
- final int endIndex = formats[1];
-
- LocalDate start = dateReader.parseToLocalDate(row[startIndex]);
- LocalDate end = dateReader.parseToLocalDate(row[endIndex]);
-
- if (start == null && end == null) {
- return null;
- }
-
- return CDateSet.create(Collections.singleton(CDateRange.of(start, end)));
+ public void readDates(String value, DateReader dateReader, CDateSet out) {
+ out.add(CDateRange.atLeast(dateReader.parseToLocalDate(value)));
}
},
DATE_RANGE {
@Override
- public CDateSet readDates(int[] formats, String[] row, DateReader dateReader) {
- final int index = formats[0];
-
- return CDateSet.create(Collections.singleton(DateRangeParser.parseISORange(row[index], dateReader)));
+ public void readDates(String value, DateReader dateReader, CDateSet out) {
+ out.add(DateRangeParser.parseISORange(value, dateReader));
}
},
DATE_SET {
@Override
- public CDateSet readDates(int[] formats, String[] row, DateReader dateReader) {
- final int index = formats[0];
+ public void readDates(String value, DateReader dateReader, CDateSet out) {
- return CDateSet.parse(row[index], dateReader);
+ out.addAll(CDateSet.parse(value, dateReader));
}
},
ALL {
@Override
- public CDateSet readDates(int[] formats, String[] row, DateReader dateReader) {
- return CDateSet.createFull();
+ public void readDates(String value, DateReader dateReader, CDateSet out) {
+ out.add(CDateRange.all());
}
};
- public abstract CDateSet readDates(int[] formats, String[] row, DateReader dateReader);
+ public abstract void readDates(String value, DateReader dateReader, CDateSet out);
public static int[] select(List dateFormat) {
final List distinct = dateFormat.stream().filter(Objects::nonNull).distinct().sorted().collect(Collectors.toList());
diff --git a/backend/src/main/java/com/bakdata/conquery/io/result/csv/ResultCsvProcessor.java b/backend/src/main/java/com/bakdata/conquery/io/result/csv/ResultCsvProcessor.java
index b6d2b055fa..cac11892ec 100644
--- a/backend/src/main/java/com/bakdata/conquery/io/result/csv/ResultCsvProcessor.java
+++ b/backend/src/main/java/com/bakdata/conquery/io/result/csv/ResultCsvProcessor.java
@@ -18,7 +18,6 @@
import com.bakdata.conquery.models.datasets.Dataset;
import com.bakdata.conquery.models.execution.ManagedExecution;
import com.bakdata.conquery.models.i18n.I18n;
-
import com.bakdata.conquery.models.identifiable.mapping.IdPrinter;
import com.bakdata.conquery.models.query.PrintSettings;
import com.bakdata.conquery.models.query.SingleTableResult;
@@ -63,7 +62,7 @@ public & SingleTableResult> Response getResult(Us
Charset charset = determineCharset(userAgent, queryCharset);
- StreamingOutput out = os -> {
+ StreamingOutput out = os -> {
try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, charset))) {
CsvRenderer renderer = new CsvRenderer(config.getCsv().createWriter(writer), settings);
renderer.toCSV(config.getFrontend().getQueryUpload().getPrintIdFields(), exec.getResultInfo(), exec.streamResults());
diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java b/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java
index 9406bbdedd..fa053e326d 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java
@@ -1,6 +1,7 @@
package com.bakdata.conquery.models.config;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -24,6 +25,7 @@
import com.fasterxml.jackson.annotation.JsonIgnore;
import groovy.transform.ToString;
import io.dropwizard.validation.ValidationMethod;
+import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
@@ -67,6 +69,8 @@ public static class UploadConfig {
);
@JsonIgnore
+ @Setter(AccessLevel.NONE)
+ @Getter(AccessLevel.NONE)
private List idFieldsCached;
/**
@@ -78,7 +82,7 @@ public List getPrintIdFields() {
idFieldsCached = ids.stream()
.map(ColumnConfig::getField)
.filter(Objects::nonNull)
- .collect(Collectors.toList());
+ .collect(Collectors.toUnmodifiableList());
}
return idFieldsCached;
diff --git a/backend/src/main/java/com/bakdata/conquery/util/io/Cloner.java b/backend/src/main/java/com/bakdata/conquery/util/io/Cloner.java
index 7dface2db9..f972e6a516 100644
--- a/backend/src/main/java/com/bakdata/conquery/util/io/Cloner.java
+++ b/backend/src/main/java/com/bakdata/conquery/util/io/Cloner.java
@@ -12,35 +12,37 @@
public class Cloner {
- public static ConqueryConfig clone(ConqueryConfig config, Map , T > injectables) {
+ public static ConqueryConfig clone(ConqueryConfig config, Map, T> injectables, ObjectMapper mapper) {
try {
- ObjectMapper mapper = Jackson.BINARY_MAPPER.copy();
- MutableInjectableValues injectableHolder = ((MutableInjectableValues)Jackson.BINARY_MAPPER.getInjectableValues());
- for(Entry, T> injectable : injectables.entrySet()) {
+
+ MutableInjectableValues injectableHolder = ((MutableInjectableValues) mapper.getInjectableValues());
+ for (Entry, T> injectable : injectables.entrySet()) {
injectableHolder.add(injectable.getKey(), injectable.getValue());
}
ConqueryConfig clone = mapper.readValue(
- Jackson.BINARY_MAPPER.writeValueAsBytes(config),
- ConqueryConfig.class
+ mapper.writeValueAsBytes(config),
+ ConqueryConfig.class
);
clone.setLoggingFactory(config.getLoggingFactory());
return clone;
- } catch (IOException e) {
- throw new IllegalStateException("Failed to clone a conquery config "+config, e);
+ }
+ catch (IOException e) {
+ throw new IllegalStateException("Failed to clone a conquery config " + config, e);
}
}
public static T clone(T element, Injectable injectable, Class valueType) {
try {
return injectable
- .injectInto(Jackson.BINARY_MAPPER)
- .readValue(
- Jackson.BINARY_MAPPER.writeValueAsBytes(element),
- valueType
- );
- } catch (IOException e) {
- throw new IllegalStateException("Failed to clone the CQElement "+element, e);
+ .injectInto(Jackson.BINARY_MAPPER)
+ .readValue(
+ Jackson.BINARY_MAPPER.writeValueAsBytes(element),
+ valueType
+ );
+ }
+ catch (IOException e) {
+ throw new IllegalStateException("Failed to clone the CQElement " + element, e);
}
}
}
diff --git a/backend/src/test/java/com/bakdata/conquery/integration/IntegrationTests.java b/backend/src/test/java/com/bakdata/conquery/integration/IntegrationTests.java
index 99f562ae62..f767152b97 100644
--- a/backend/src/test/java/com/bakdata/conquery/integration/IntegrationTests.java
+++ b/backend/src/test/java/com/bakdata/conquery/integration/IntegrationTests.java
@@ -7,7 +7,13 @@
import java.io.InputStream;
import java.net.URI;
import java.nio.file.Files;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -15,16 +21,16 @@
import com.bakdata.conquery.TestTags;
import com.bakdata.conquery.integration.json.JsonIntegrationTest;
import com.bakdata.conquery.integration.tests.ProgrammaticIntegrationTest;
-import com.bakdata.conquery.integration.tests.RestartTest;
import com.bakdata.conquery.io.cps.CPSTypeIdResolver;
+import com.bakdata.conquery.io.jackson.InternalOnly;
import com.bakdata.conquery.io.jackson.Jackson;
import com.bakdata.conquery.models.config.ConqueryConfig;
import com.bakdata.conquery.util.io.Cloner;
import com.bakdata.conquery.util.support.ConfigOverride;
import com.bakdata.conquery.util.support.TestConquery;
+import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import io.github.classgraph.Resource;
-import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.SneakyThrows;
@@ -39,14 +45,27 @@
@Slf4j
public class IntegrationTests {
- private static final ObjectWriter CONFIG_WRITER = Jackson.MAPPER.writerFor(ConqueryConfig.class);
+ private static final ObjectMapper MAPPER;
+ private static final ObjectWriter CONFIG_WRITER;
+
+ static {
+ final ObjectMapper mapper = Jackson.MAPPER.copy();
+
+ MAPPER = mapper.setConfig(mapper.getDeserializationConfig().withView(InternalOnly.class))
+ .setConfig(mapper.getSerializationConfig().withView(InternalOnly.class));
+
+ CONFIG_WRITER = MAPPER.writerFor(ConqueryConfig.class);
+ }
+
+
private static final Map reusedInstances = new HashMap<>();
-
+
private final String defaultTestRoot;
private final String defaultTestRootPackage;
@Getter
private final File workDir;
- @Getter @RegisterExtension
+ @Getter
+ @RegisterExtension
public static TestConqueryConfig DEFAULT_CONFIG = new TestConqueryConfig();
@SneakyThrows(IOException.class)
@@ -62,10 +81,10 @@ public List jsonTests() {
ResourceTree tree = new ResourceTree(null, null);
tree.addAll(
- CPSTypeIdResolver.SCAN_RESULT
- .getResourcesMatchingPattern(Pattern.compile("^" + testRoot + ".*\\.test\\.json$"))
+ CPSTypeIdResolver.SCAN_RESULT
+ .getResourcesMatchingPattern(Pattern.compile("^" + testRoot + ".*\\.test\\.json$"))
);
-
+
// collect tests from directory
if (tree.getChildren().isEmpty()) {
log.warn("Could not find tests in {}", testRoot);
@@ -77,64 +96,65 @@ public List jsonTests() {
return Collections.singletonList(collectTests(reduced));
}
return reduced.getChildren().values().stream()
- .map(this::collectTests)
- .collect(Collectors.toList());
+ .map(this::collectTests)
+ .collect(Collectors.toList());
}
@SneakyThrows
public Stream programmaticTests() {
List> programmatic = CPSTypeIdResolver
- .SCAN_RESULT
- .getClassesImplementing(ProgrammaticIntegrationTest.class.getName())
- .filter(info -> info.getPackageName().startsWith(defaultTestRootPackage))
- .loadClasses();
+ .SCAN_RESULT
+ .getClassesImplementing(ProgrammaticIntegrationTest.class.getName())
+ .filter(info -> info.getPackageName().startsWith(defaultTestRootPackage))
+ .loadClasses();
return programmatic
- .stream()
- .map(c-> {
- try {
- return c.asSubclass(ProgrammaticIntegrationTest.class).getDeclaredConstructor().newInstance();
- }
- catch(Exception e) {
- throw new RuntimeException(e);
- }
- })
- .map(this::createDynamicProgrammaticTestNode);
+ .stream()
+ .map(c -> {
+ try {
+ return c.asSubclass(ProgrammaticIntegrationTest.class).getDeclaredConstructor().newInstance();
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ })
+ .map(this::createDynamicProgrammaticTestNode);
}
private DynamicTest createDynamicProgrammaticTestNode(ProgrammaticIntegrationTest test) {
TestConquery conquery = getCachedConqueryInstance(workDir, getConfigOverride(test));
+
return DynamicTest.dynamicTest(
test.getClass().getSimpleName(),
//classpath URI
- URI.create("classpath:/"+test.getClass().getName().replace('.', '/')+".java"),
+ URI.create("classpath:/" + test.getClass().getName().replace('.', '/') + ".java"),
new IntegrationTest.Wrapper(test.getClass().getSimpleName(), conquery, test)
);
}
private DynamicNode collectTests(ResourceTree currentDir) {
- if(currentDir.getValue() != null) {
+ if (currentDir.getValue() != null) {
return readTest(currentDir.getValue(), currentDir.getName(), this);
}
List list = new ArrayList<>();
- for(ResourceTree child : currentDir.getChildren().values()) {
+ for (ResourceTree child : currentDir.getChildren().values()) {
list.add(collectTests(child));
}
list.sort(Comparator.comparing(DynamicNode::getDisplayName));
-
+
return dynamicContainer(
- currentDir.getName(),
- URI.create("classpath:/"+currentDir.getFullName()+"/"),
- list.stream()
+ currentDir.getName(),
+ URI.create("classpath:/" + currentDir.getFullName() + "/"),
+ list.stream()
);
}
private static DynamicTest readTest(Resource resource, String name, IntegrationTests integrationTests) {
- try(InputStream in = resource.open()) {
+ try (InputStream in = resource.open()) {
JsonIntegrationTest test = new JsonIntegrationTest(in);
ConqueryConfig conf = getConfigOverride(test);
@@ -148,23 +168,24 @@ private static DynamicTest readTest(Resource resource, String name, IntegrationT
new IntegrationTest.Wrapper(
name,
conquery,
- test)
+ test
+ )
);
}
- catch(Exception e) {
+ catch (Exception e) {
return DynamicTest.dynamicTest(
- name,
- resource.getURI(),
- () -> {
- throw e;
- }
+ name,
+ resource.getURI(),
+ () -> {
+ throw e;
+ }
);
}
}
@NotNull
private static ConqueryConfig getConfigOverride(IntegrationTest test) {
- ConqueryConfig conf = Cloner.clone(DEFAULT_CONFIG, Map.of());
+ ConqueryConfig conf = Cloner.clone(DEFAULT_CONFIG, Map.of(), MAPPER);
test.overrideConfig(conf);
return conf;
}
@@ -173,7 +194,7 @@ private static ConqueryConfig getConfigOverride(IntegrationTest test) {
private static synchronized TestConquery getCachedConqueryInstance(File workDir, ConqueryConfig conf) {
// This should be fast enough and a stable comparison
String confString = CONFIG_WRITER.writeValueAsString(conf);
- if(!reusedInstances.containsKey(confString)){
+ if (!reusedInstances.containsKey(confString)) {
// For the overriden config we must override the ports so there are no clashes
// We do it here so the config "hash" is not influenced by the port settings
TestConquery.configureRandomPorts(conf);
@@ -187,7 +208,7 @@ private static synchronized TestConquery getCachedConqueryInstance(File workDir,
}
@EqualsAndHashCode(callSuper = true)
- public static class TestConqueryConfig extends ConqueryConfig implements Extension, BeforeAllCallback {
+ public static class TestConqueryConfig extends ConqueryConfig implements Extension, BeforeAllCallback {
@Override
public void beforeAll(ExtensionContext context) throws Exception {
diff --git a/backend/src/test/java/com/bakdata/conquery/integration/json/AbstractQueryEngineTest.java b/backend/src/test/java/com/bakdata/conquery/integration/json/AbstractQueryEngineTest.java
index 118536ad7e..1709155450 100644
--- a/backend/src/test/java/com/bakdata/conquery/integration/json/AbstractQueryEngineTest.java
+++ b/backend/src/test/java/com/bakdata/conquery/integration/json/AbstractQueryEngineTest.java
@@ -1,27 +1,32 @@
package com.bakdata.conquery.integration.json;
+import static com.bakdata.conquery.resources.ResourceConstants.DATASET;
+import static com.bakdata.conquery.resources.ResourceConstants.QUERY;
import static org.assertj.core.api.Assertions.assertThat;
import java.io.IOException;
+import java.io.InputStream;
import java.util.List;
import java.util.Locale;
-import java.util.stream.Collectors;
+import java.util.Map;
+import javax.ws.rs.core.Response;
+
+import com.bakdata.conquery.apiv1.AdditionalMediaTypes;
import com.bakdata.conquery.apiv1.query.Query;
import com.bakdata.conquery.integration.common.IntegrationUtils;
import com.bakdata.conquery.integration.common.ResourceFile;
-import com.bakdata.conquery.io.result.CsvLineStreamRenderer;
import com.bakdata.conquery.models.auth.entities.User;
import com.bakdata.conquery.models.config.ConqueryConfig;
import com.bakdata.conquery.models.execution.ExecutionState;
import com.bakdata.conquery.models.identifiable.ids.specific.ManagedExecutionId;
-import com.bakdata.conquery.models.identifiable.mapping.IdPrinter;
import com.bakdata.conquery.models.query.ManagedQuery;
-import com.bakdata.conquery.models.query.PrintSettings;
import com.bakdata.conquery.models.query.resultinfo.ResultInfo;
import com.bakdata.conquery.models.query.results.EntityResult;
import com.bakdata.conquery.models.query.results.MultilineEntityResult;
import com.bakdata.conquery.models.worker.DatasetRegistry;
+import com.bakdata.conquery.resources.api.ResultCsvResource;
+import com.bakdata.conquery.resources.hierarchies.HierarchyHelper;
import com.bakdata.conquery.util.NonPersistentStoreFactory;
import com.bakdata.conquery.util.support.StandaloneSupport;
import com.fasterxml.jackson.annotation.JsonIgnore;
@@ -66,32 +71,28 @@ public void executeTest(StandaloneSupport standaloneSupport) throws IOException
.as("Should have same size as result infos")
.allSatisfy(v -> assertThat(v).hasSameSizeAs(resultInfos));
- IdPrinter idPrinter = config.getFrontend().getQueryUpload().getIdPrinter(testUser, execution, execution.getNamespace());
-
- PrintSettings
- PRINT_SETTINGS =
- new PrintSettings(
- false,
- Locale.ENGLISH,
- namespaces,
- config,
- idPrinter::createId,
- (columnInfo) -> columnInfo.getSelect().getId().toStringWithoutDataset()
- );
-
- CsvLineStreamRenderer renderer = new CsvLineStreamRenderer(config.getCsv().createWriter(), PRINT_SETTINGS);
-
- List actual = renderer.toStream(
- config.getFrontend().getQueryUpload().getPrintIdFields(),
- resultInfos,
- execution.streamResults()
- ).collect(Collectors.toList());
+ // Get the actual response and compare with expected result.
+ final Response csvResponse =
+ standaloneSupport.getClient()
+ .target(HierarchyHelper.hierarchicalPath(standaloneSupport.defaultApiURIBuilder(), ResultCsvResource.class, "getAsCsv")
+ .buildFromMap(
+ Map.of(DATASET, standaloneSupport.getDataset().getName(),
+ QUERY, execution.getId().toString()
+ )
+ ))
+ .request(AdditionalMediaTypes.CSV)
+ .acceptLanguage(Locale.ENGLISH)
+ .get();
+
+ List actual = In.stream(((InputStream) csvResponse.getEntity())).readLines();
ResourceFile expectedCsv = getExpectedCsv();
List expected = In.stream(expectedCsv.stream()).readLines();
- assertThat(actual).as("Results for %s are not as expected.", this).containsExactlyInAnyOrderElementsOf(expected);
+ assertThat(actual).as("Results for %s are not as expected.", this)
+ .containsExactlyInAnyOrderElementsOf(expected);
+
// check that getLastResultCount returns the correct size
if (execution.streamResults().noneMatch(MultilineEntityResult.class::isInstance)) {
assertThat(execution.getLastResultCount()).as("Result count for %s is not as expected.", this).isEqualTo(expected.size() - 1);
diff --git a/backend/src/test/java/com/bakdata/conquery/util/support/TestConquery.java b/backend/src/test/java/com/bakdata/conquery/util/support/TestConquery.java
index e7f54ec527..2ec0325784 100644
--- a/backend/src/test/java/com/bakdata/conquery/util/support/TestConquery.java
+++ b/backend/src/test/java/com/bakdata/conquery/util/support/TestConquery.java
@@ -19,13 +19,13 @@
import com.bakdata.conquery.Conquery;
import com.bakdata.conquery.commands.ShardNode;
import com.bakdata.conquery.commands.StandaloneCommand;
+import com.bakdata.conquery.io.jackson.Jackson;
import com.bakdata.conquery.models.auth.entities.User;
import com.bakdata.conquery.models.config.ConqueryConfig;
import com.bakdata.conquery.models.config.XodusStoreFactory;
import com.bakdata.conquery.models.execution.ExecutionState;
import com.bakdata.conquery.models.execution.ManagedExecution;
import com.bakdata.conquery.models.identifiable.ids.specific.DatasetId;
-import com.bakdata.conquery.models.messages.network.specific.RemoveWorker;
import com.bakdata.conquery.models.worker.DatasetRegistry;
import com.bakdata.conquery.models.worker.Namespace;
import com.bakdata.conquery.util.Wait;
@@ -137,7 +137,7 @@ private synchronized StandaloneSupport createSupport(DatasetId datasetId, String
log.info("Reusing existing folder {} for Support", localTmpDir.getPath());
}
- ConqueryConfig localCfg = Cloner.clone(config, Map.of(Validator.class, standaloneCommand.getManager().getEnvironment().getValidator()));
+ ConqueryConfig localCfg = Cloner.clone(config, Map.of(Validator.class, standaloneCommand.getManager().getEnvironment().getValidator()), Jackson.BINARY_MAPPER.copy());
StandaloneSupport support = new StandaloneSupport(
From 6e362a81ae4bdcfa0da94e12128b395deeabde99 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Tue, 27 Jul 2021 13:10:04 +0000
Subject: [PATCH 38/82] Update AutoDoc
---
docs/Config JSON.md | 18 +++++++++---------
docs/REST API JSONs.md | 18 +++++++++---------
2 files changed, 18 insertions(+), 18 deletions(-)
diff --git a/docs/Config JSON.md b/docs/Config JSON.md
index adb95b4ea6..00b1cc6f43 100644
--- a/docs/Config JSON.md
+++ b/docs/Config JSON.md
@@ -223,7 +223,7 @@ Supported Fields:
| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/ConqueryConfig.java#L68) | storage | `@Valid @NotNull StoreFactory` | | | |
-### Type CurrencyConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L213)
+### Type CurrencyConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L217)
Details
@@ -234,13 +234,13 @@ Supported Fields:
| | Field | Type | Default | Example | Description |
| --- | --- | --- | --- | --- | --- |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L218) | decimalScale | `int` | `2` | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L217) | decimalSeparator | `String` | `","` | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L215) | prefix | `String` | `"€"` | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L216) | thousandSeparator | `String` | `"."` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L222) | decimalScale | `int` | `2` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L221) | decimalSeparator | `String` | `","` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L219) | prefix | `String` | `"€"` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L220) | thousandSeparator | `String` | `"."` | | |
-### Type FrontendConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L35)
+### Type FrontendConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L37)
Details
@@ -251,9 +251,9 @@ Supported Fields:
| | Field | Type | Default | Example | Description |
| --- | --- | --- | --- | --- | --- |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L45) | currency | [CurrencyConfig](#Type-CurrencyConfig) | | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L49) | queryUpload | `UploadConfig` | | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L44) | version | `String` | `"0.0.0-SNAPSHOT"` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L47) | currency | [CurrencyConfig](#Type-CurrencyConfig) | | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L51) | queryUpload | `UploadConfig` | | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L46) | version | `String` | `"0.0.0-SNAPSHOT"` | | |
### Type LocaleConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/LocaleConfig.java#L11)
diff --git a/docs/REST API JSONs.md b/docs/REST API JSONs.md
index 159501ca89..fdf4537bc1 100644
--- a/docs/REST API JSONs.md
+++ b/docs/REST API JSONs.md
@@ -755,7 +755,7 @@ Supported Fields:
| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/resources/api/ConceptResource.java#L68) | concepts | list of `String` | `null` | | |
-### Type CurrencyConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L213)
+### Type CurrencyConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L217)
Details
@@ -766,10 +766,10 @@ Supported Fields:
| | Field | Type | Default | Example | Description |
| --- | --- | --- | --- | --- | --- |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L218) | decimalScale | `int` | `2` | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L217) | decimalSeparator | `String` | `","` | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L215) | prefix | `String` | `"€"` | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L216) | thousandSeparator | `String` | `"."` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L222) | decimalScale | `int` | `2` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L221) | decimalSeparator | `String` | `","` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L219) | prefix | `String` | `"€"` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L220) | thousandSeparator | `String` | `"."` | | |
### Type ExecutionStatus [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/apiv1/ExecutionStatus.java#L18)
@@ -885,7 +885,7 @@ No fields can be set for this type.
-### Type FrontendConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L35)
+### Type FrontendConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L37)
Details
@@ -896,9 +896,9 @@ Supported Fields:
| | Field | Type | Default | Example | Description |
| --- | --- | --- | --- | --- | --- |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L45) | currency | [CurrencyConfig](#Type-CurrencyConfig) | | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L49) | queryUpload | `UploadConfig` | | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L44) | version | `String` | `"0.0.0-SNAPSHOT"` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L47) | currency | [CurrencyConfig](#Type-CurrencyConfig) | | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L51) | queryUpload | `UploadConfig` | | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L46) | version | `String` | `"0.0.0-SNAPSHOT"` | | |
### Type FullExecutionStatus [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/apiv1/FullExecutionStatus.java#L20-L24)
From 1b0fbafaa0f4c145d5a238c4b556584ccdbf6c4e Mon Sep 17 00:00:00 2001
From: Fabian Kovacs <1553491+awildturtok@users.noreply.github.com>
Date: Tue, 27 Jul 2021 15:10:37 +0200
Subject: [PATCH 39/82] cleanup
---
.../concept/specific/external/CQExternal.java | 8 +++----
.../concept/specific/external/DateFormat.java | 21 -------------------
.../conquery/resources/api/QueryResource.java | 13 +++++++++++-
3 files changed, 15 insertions(+), 27 deletions(-)
diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java
index 12c4d06913..6a8bf31859 100644
--- a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java
+++ b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java
@@ -73,7 +73,6 @@ public QPNode createQueryPlan(QueryPlanContext context, ConceptQueryPlan plan) {
private static Int2ObjectMap readDates(String[][] values, List format, DateReader dateReader, FrontendConfig.UploadConfig queryUpload) {
Int2ObjectMap out = new Int2ObjectAVLTreeMap<>();
-
List dateFormats = format.stream().map(queryUpload::resolveDateFormat).collect(Collectors.toList());
//validate structures
@@ -153,13 +152,12 @@ public static ResolveStatistic resolveEntities(@NotEmpty String[][] values, @Not
List unresolvedId = new ArrayList<>();
// extract dates from rows
- final FrontendConfig.UploadConfig uploadConfig = queryUpload;
- final Int2ObjectMap rowDates = readDates(values, format, dateReader, uploadConfig);
+ final Int2ObjectMap rowDates = readDates(values, format, dateReader, queryUpload);
- final int idIndex = uploadConfig.getIdIndex(format);
+ final int idIndex = queryUpload.getIdIndex(format);
- final ColumnConfig reader = uploadConfig.getIdMapper(format.get(idIndex));
+ final ColumnConfig reader = queryUpload.getIdMapper(format.get(idIndex));
// ignore the first row, because this is the header
diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateFormat.java b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateFormat.java
index e4c83a7308..d1c2ed33c1 100644
--- a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateFormat.java
+++ b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateFormat.java
@@ -37,7 +37,6 @@ public void readDates(String value, DateReader dateReader, CDateSet out) {
DATE_SET {
@Override
public void readDates(String value, DateReader dateReader, CDateSet out) {
-
out.addAll(CDateSet.parse(value, dateReader));
}
},
@@ -50,24 +49,4 @@ public void readDates(String value, DateReader dateReader, CDateSet out) {
public abstract void readDates(String value, DateReader dateReader, CDateSet out);
- public static int[] select(List dateFormat) {
- final List distinct = dateFormat.stream().filter(Objects::nonNull).distinct().sorted().collect(Collectors.toList());
-
- // => ALL
- if (distinct.isEmpty()) {
- return new int[0];
- }
-
-
- if (distinct.size() == 1) {
- return new int[]{dateFormat.indexOf(distinct.get(0))};
- }
-
- if (distinct.size() == 2 && distinct.get(0).equals(START_DATE) && distinct.get(1).equals(END_DATE)) {
- return new int[]{dateFormat.indexOf(START_DATE), dateFormat.indexOf(END_DATE)};
- }
-
- throw new IllegalStateException("can only handle 1 or 2 format columns"); //TODO map error
-
- }
}
diff --git a/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java b/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java
index d5825aa3ca..a1f42e0200 100644
--- a/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java
+++ b/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java
@@ -10,8 +10,10 @@
import com.bakdata.conquery.models.exceptions.JSONException;
import com.bakdata.conquery.models.execution.ManagedExecution;
import com.bakdata.conquery.models.identifiable.ids.specific.ManagedExecutionId;
+import com.fasterxml.jackson.annotation.JsonIgnore;
import io.dropwizard.auth.Auth;
import io.dropwizard.jersey.PATCH;
+import io.dropwizard.validation.ValidationMethod;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -24,6 +26,8 @@
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
+
+import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
@@ -132,11 +136,18 @@ public static class ExternalUpload {
private final String[][] values;
private final ManagedExecutionId executionId;
+
+ @JsonIgnore
+ @ValidationMethod(message = "Values and Format are not of same width.")
+ public boolean isAllSameLength() {
+ final int expected = format.size();
+ return Arrays.stream(values).mapToInt(a -> a.length).allMatch(v -> expected == v);
+ }
}
@POST
@Path("/upload")
- public Response upload(@Auth User user, ExternalUpload upload) {
+ public Response upload(@Auth User user, @Valid ExternalUpload upload) {
return processor.uploadEntities(user, dataset, upload);
}
}
From 453ae3ae0a949bf31ecca3016e582791c36b27d3 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Tue, 27 Jul 2021 13:12:43 +0000
Subject: [PATCH 40/82] Update AutoDoc
---
docs/REST API JSONs.md | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/docs/REST API JSONs.md b/docs/REST API JSONs.md
index fdf4537bc1..03b364470b 100644
--- a/docs/REST API JSONs.md
+++ b/docs/REST API JSONs.md
@@ -103,7 +103,7 @@ Returns: [ResolvedConceptsResult](#Type-ResolvedConceptsResult)
-### GET datasets/{dataset}/queries [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java#L50)
+### GET datasets/{dataset}/queries [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java#L54)
Details
@@ -117,7 +117,7 @@ Returns: list of [ExecutionStatus](#Type-ExecutionStatus)
-### POST datasets/{dataset}/queries [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java#L59)
+### POST datasets/{dataset}/queries [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java#L63)
Details
@@ -132,7 +132,7 @@ Returns: `Response`
-### POST datasets/{dataset}/queries/upload [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java#L137)
+### POST datasets/{dataset}/queries/upload [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java#L148)
Details
@@ -141,12 +141,12 @@ Java Type: `com.bakdata.conquery.resources.api.QueryResource`
Method: `upload`
-Expects: `ExternalUpload`
+Expects: `@Valid ExternalUpload`
Returns: `Response`
-### GET datasets/{dataset}/queries/{query} [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java#L71)
+### GET datasets/{dataset}/queries/{query} [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java#L75)
Details
@@ -160,7 +160,7 @@ Returns: [FullExecutionStatus](#Type-FullExecutionStatus)
-### PATCH datasets/{dataset}/queries/{query} [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java#L84)
+### PATCH datasets/{dataset}/queries/{query} [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java#L88)
Details
@@ -175,7 +175,7 @@ Returns: [FullExecutionStatus](#Type-FullExecutionStatus)
-### DELETE datasets/{dataset}/queries/{query} [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java#L95)
+### DELETE datasets/{dataset}/queries/{query} [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java#L99)
Details
@@ -188,7 +188,7 @@ Returns: `void`
-### POST datasets/{dataset}/queries/{query}/cancel [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java#L114)
+### POST datasets/{dataset}/queries/{query}/cancel [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java#L118)
Details
@@ -201,7 +201,7 @@ Returns: `void`
-### POST datasets/{dataset}/queries/{query}/reexecute [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java#L104)
+### POST datasets/{dataset}/queries/{query}/reexecute [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/resources/api/QueryResource.java#L108)
Details
From 8b0d745e4f335318ae7a787a67949134cff0ced9 Mon Sep 17 00:00:00 2001
From: Fabian Kovacs <1553491+awildturtok@users.noreply.github.com>
Date: Tue, 27 Jul 2021 15:20:02 +0200
Subject: [PATCH 41/82] add check for all-Case
---
.../concept/specific/external/CQExternal.java | 22 ++++++++++++++-----
1 file changed, 17 insertions(+), 5 deletions(-)
diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java
index 6a8bf31859..9d7b73ef15 100644
--- a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java
+++ b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java
@@ -4,6 +4,7 @@
import java.util.Arrays;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.stream.Collectors;
import javax.validation.constraints.NotEmpty;
@@ -17,7 +18,6 @@
import com.bakdata.conquery.models.config.FrontendConfig;
import com.bakdata.conquery.models.error.ConqueryError;
import com.bakdata.conquery.models.identifiable.mapping.EntityIdMap;
-
import com.bakdata.conquery.models.query.QueryPlanContext;
import com.bakdata.conquery.models.query.QueryResolveContext;
import com.bakdata.conquery.models.query.queryplan.ConceptQueryPlan;
@@ -75,14 +75,19 @@ private static Int2ObjectMap readDates(String[][] values, List
List dateFormats = format.stream().map(queryUpload::resolveDateFormat).collect(Collectors.toList());
- //validate structures
+ final boolean isAll = dateFormats.stream().allMatch(Objects::isNull);
for (int row = 1; row < values.length; row++) {
try {
+ if (isAll) {
+ out.put(row, CDateSet.createFull());
+ continue;
+ }
+
for (int col = 0; col < dateFormats.size(); col++) {
final DateFormat dateFormat = dateFormats.get(col);
- if(dateFormat == null){
+ if (dateFormat == null) {
continue;
}
@@ -107,7 +112,14 @@ private static Int2ObjectMap readDates(String[][] values, List
@Override
public void resolve(QueryResolveContext context) {
- final ResolveStatistic resolved = resolveEntities(values, format, context.getNamespace().getStorage().getIdMapping(), context.getConfig().getFrontend().getQueryUpload(), context.getConfig().getPreprocessor().getParsers().getDateReader());
+ final ResolveStatistic
+ resolved =
+ resolveEntities(values, format, context.getNamespace().getStorage().getIdMapping(), context.getConfig()
+ .getFrontend()
+ .getQueryUpload(), context.getConfig()
+ .getPreprocessor()
+ .getParsers()
+ .getDateReader());
if (resolved.getResolved().isEmpty()) {
throw new ConqueryError.ExternalResolveEmptyError();
@@ -181,7 +193,7 @@ public static ResolveStatistic resolveEntities(@NotEmpty String[][] values, @Not
resolved.put(resolvedId, rowDates.get(rowNum));
}
- return new ResolveStatistic(resolved,unresolvedDate,unresolvedId);
+ return new ResolveStatistic(resolved, unresolvedDate, unresolvedId);
}
From 5e8970ddcea3c6e652afca725812739cb4503026 Mon Sep 17 00:00:00 2001
From: Fabian Kovacs <1553491+awildturtok@users.noreply.github.com>
Date: Tue, 27 Jul 2021 16:03:13 +0200
Subject: [PATCH 42/82] adds documentation
---
.../conquery/apiv1/QueryProcessor.java | 20 ++++---
.../concept/specific/external/CQExternal.java | 58 ++++++++++---------
.../concept/specific/external/DateFormat.java | 3 +
.../models/config/FrontendConfig.java | 18 ++++--
4 files changed, 60 insertions(+), 39 deletions(-)
diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/QueryProcessor.java b/backend/src/main/java/com/bakdata/conquery/apiv1/QueryProcessor.java
index 8e8258fe17..e82fd97885 100644
--- a/backend/src/main/java/com/bakdata/conquery/apiv1/QueryProcessor.java
+++ b/backend/src/main/java/com/bakdata/conquery/apiv1/QueryProcessor.java
@@ -372,14 +372,19 @@ public static class UploadResponse {
private final List unreadableDate;
}
+ /**
+ * Try to resolve the upload, if successful, create query for the user and return id and statistics for that.
+ */
public Response uploadEntities(User user, Dataset dataset, QueryResource.ExternalUpload upload) {
- final CQExternal.ResolveStatistic statistic = CQExternal.resolveEntities(upload.getValues(), upload.getFormat(),
- datasetRegistry.get(dataset.getId()).getStorage().getIdMapping(),
- config.getFrontend().getQueryUpload(),
- config.getPreprocessor().getParsers().getDateReader()
- );
- // Resolving nothing is a problem and we fail.
+ final CQExternal.ResolveStatistic statistic =
+ CQExternal.resolveEntities(upload.getValues(), upload.getFormat(),
+ datasetRegistry.get(dataset.getId()).getStorage().getIdMapping(),
+ config.getFrontend().getQueryUpload(),
+ config.getPreprocessor().getParsers().getDateReader()
+ );
+
+ // Resolving nothing is a problem thus we fail.
if (statistic.getResolved().isEmpty()) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(new UploadResponse(null, 0, statistic.getUnresolvedId(), statistic.getUnreadableDate()))
@@ -390,7 +395,8 @@ public Response uploadEntities(User user, Dataset dataset, QueryResource.Externa
// We only create the Query, really no need to execute it as it's only useful for composition.
final ManagedExecution> execution =
- datasetRegistry.get(dataset.getId()).getExecutionManager().createExecution(datasetRegistry, query, user, dataset);
+ datasetRegistry.get(dataset.getId()).getExecutionManager()
+ .createExecution(datasetRegistry, query, user, dataset);
return Response.ok()
.entity(new UploadResponse(
diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java
index 9d7b73ef15..e76f6d2390 100644
--- a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java
+++ b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/CQExternal.java
@@ -70,37 +70,43 @@ public QPNode createQueryPlan(QueryPlanContext context, ConceptQueryPlan plan) {
}
+ /**
+ * For each row try and collect all dates.
+ *
+ * @return Row -> Dates
+ */
private static Int2ObjectMap readDates(String[][] values, List format, DateReader dateReader, FrontendConfig.UploadConfig queryUpload) {
Int2ObjectMap out = new Int2ObjectAVLTreeMap<>();
List dateFormats = format.stream().map(queryUpload::resolveDateFormat).collect(Collectors.toList());
- final boolean isAll = dateFormats.stream().allMatch(Objects::isNull);
+ // If no format provided, put all dates into output.
+ if (dateFormats.stream().allMatch(Objects::isNull)) {
+ for (int row = 0; row < values.length; row++) {
+ out.put(row, CDateSet.createFull());
+ }
+ return out;
+ }
for (int row = 1; row < values.length; row++) {
try {
- if (isAll) {
- out.put(row, CDateSet.createFull());
- continue;
- }
+ final CDateSet dates = CDateSet.create();
+ // Collect all specified dates into a single set.
for (int col = 0; col < dateFormats.size(); col++) {
final DateFormat dateFormat = dateFormats.get(col);
if (dateFormat == null) {
continue;
}
-
- CDateSet dates = CDateSet.create();
-
dateFormat.readDates(values[row][col], dateReader, dates);
+ }
- if (dates.isEmpty()) {
- continue;
- }
-
- out.put(row, dates);
+ if (dates.isEmpty()) {
+ continue;
}
+
+ out.put(row, dates);
}
catch (Exception e) {
log.warn("Failed to parse Date from {}", row, e);
@@ -112,14 +118,12 @@ private static Int2ObjectMap readDates(String[][] values, List
@Override
public void resolve(QueryResolveContext context) {
- final ResolveStatistic
- resolved =
- resolveEntities(values, format, context.getNamespace().getStorage().getIdMapping(), context.getConfig()
- .getFrontend()
- .getQueryUpload(), context.getConfig()
- .getPreprocessor()
- .getParsers()
- .getDateReader());
+ final ResolveStatistic resolved =
+ resolveEntities(values, format,
+ context.getNamespace().getStorage().getIdMapping(),
+ context.getConfig().getFrontend().getQueryUpload(),
+ context.getConfig().getPreprocessor().getParsers().getDateReader()
+ );
if (resolved.getResolved().isEmpty()) {
throw new ConqueryError.ExternalResolveEmptyError();
@@ -127,18 +131,16 @@ public void resolve(QueryResolveContext context) {
if (!resolved.getUnreadableDate().isEmpty()) {
log.warn(
- "Could not read dates {} of the {} rows. Not resolved: {}",
+ "Could not read {} dates. Not resolved: {}",
resolved.getUnreadableDate().size(),
- values.length - 1,
resolved.getUnreadableDate().subList(0, Math.min(resolved.getUnreadableDate().size(), 10))
);
}
if (!resolved.getUnresolvedId().isEmpty()) {
log.warn(
- "Could not read dates {} of the {} rows. Not resolved: {}",
+ "Could not resolve {} ids. Not resolved: {}",
resolved.getUnresolvedId().size(),
- values.length - 1,
resolved.getUnresolvedId().subList(0, Math.min(resolved.getUnresolvedId().size(), 10))
);
}
@@ -157,6 +159,9 @@ public static class ResolveStatistic {
}
+ /**
+ * Helper method to try and resolve entities in values using the specified format.
+ */
public static ResolveStatistic resolveEntities(@NotEmpty String[][] values, @NotEmpty List format, EntityIdMap mapping, FrontendConfig.UploadConfig queryUpload, @NotNull DateReader dateReader) {
Map resolved = new Int2ObjectOpenHashMap<>();
@@ -164,14 +169,13 @@ public static ResolveStatistic resolveEntities(@NotEmpty String[][] values, @Not
List unresolvedId = new ArrayList<>();
// extract dates from rows
-
final Int2ObjectMap rowDates = readDates(values, format, dateReader, queryUpload);
+ // TODO allow multiple ids
final int idIndex = queryUpload.getIdIndex(format);
final ColumnConfig reader = queryUpload.getIdMapper(format.get(idIndex));
-
// ignore the first row, because this is the header
for (int rowNum = 1; rowNum < values.length; rowNum++) {
final String[] row = values[rowNum];
diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateFormat.java b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateFormat.java
index d1c2ed33c1..1ce4206ede 100644
--- a/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateFormat.java
+++ b/backend/src/main/java/com/bakdata/conquery/apiv1/query/concept/specific/external/DateFormat.java
@@ -47,6 +47,9 @@ public void readDates(String value, DateReader dateReader, CDateSet out) {
}
};
+ /**
+ * Try and parse value using dateReader, adding result into out set.
+ */
public abstract void readDates(String value, DateReader dateReader, CDateSet out);
}
diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java b/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java
index fa053e326d..8a55a9b8ba 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java
@@ -1,7 +1,6 @@
package com.bakdata.conquery.models.config;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -23,6 +22,7 @@
import com.bakdata.conquery.models.worker.Namespace;
import com.bakdata.conquery.util.VersionInfo;
import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.google.common.base.Functions;
import groovy.transform.ToString;
import io.dropwizard.validation.ValidationMethod;
import lombok.AccessLevel;
@@ -88,11 +88,16 @@ public List getPrintIdFields() {
return idFieldsCached;
}
+ @JsonIgnore
+ private Map idMappers;
+
public ColumnConfig getIdMapper(String name) {
- return ids.stream()
- .filter(mapper -> mapper.getName().equals(name)) //TODO use map
- .findFirst()
- .orElse(null);
+ if (idMappers == null) {
+ idMappers = ids.stream().filter(ColumnConfig::isResolvable)
+ .collect(Collectors.toMap(ColumnConfig::getName, Functions.identity()));
+ }
+
+ return idMappers.get(name);
}
public int getIdIndex(List format) {
@@ -198,6 +203,9 @@ public DateFormat resolveDateFormat(String handle) {
}
+ /**
+ * Try to create a {@link FullIdPrinter} for user if they are allowed. If not allowed to read ids, they will receive ab pseudomized result instead.
+ */
public IdPrinter getIdPrinter(User owner, ManagedExecution> execution, Namespace namespace) {
if (owner.isPermitted(execution.getDataset(), Ability.PRESERVE_ID)) {
From d80b2d1f0428dc60f6d8d81e155ee295fe552e8b Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Tue, 27 Jul 2021 14:04:52 +0000
Subject: [PATCH 43/82] Update AutoDoc
---
docs/Config JSON.md | 10 +++++-----
docs/REST API JSONs.md | 10 +++++-----
2 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/docs/Config JSON.md b/docs/Config JSON.md
index 00b1cc6f43..5ded2f198f 100644
--- a/docs/Config JSON.md
+++ b/docs/Config JSON.md
@@ -223,7 +223,7 @@ Supported Fields:
| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/ConqueryConfig.java#L68) | storage | `@Valid @NotNull StoreFactory` | | | |
-### Type CurrencyConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L217)
+### Type CurrencyConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L225)
Details
@@ -234,10 +234,10 @@ Supported Fields:
| | Field | Type | Default | Example | Description |
| --- | --- | --- | --- | --- | --- |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L222) | decimalScale | `int` | `2` | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L221) | decimalSeparator | `String` | `","` | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L219) | prefix | `String` | `"€"` | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L220) | thousandSeparator | `String` | `"."` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L230) | decimalScale | `int` | `2` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L229) | decimalSeparator | `String` | `","` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L227) | prefix | `String` | `"€"` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L228) | thousandSeparator | `String` | `"."` | | |
### Type FrontendConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L37)
diff --git a/docs/REST API JSONs.md b/docs/REST API JSONs.md
index 03b364470b..3620549724 100644
--- a/docs/REST API JSONs.md
+++ b/docs/REST API JSONs.md
@@ -755,7 +755,7 @@ Supported Fields:
| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/resources/api/ConceptResource.java#L68) | concepts | list of `String` | `null` | | |
-### Type CurrencyConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L217)
+### Type CurrencyConfig [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L225)
Details
@@ -766,10 +766,10 @@ Supported Fields:
| | Field | Type | Default | Example | Description |
| --- | --- | --- | --- | --- | --- |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L222) | decimalScale | `int` | `2` | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L221) | decimalSeparator | `String` | `","` | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L219) | prefix | `String` | `"€"` | | |
-| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L220) | thousandSeparator | `String` | `"."` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L230) | decimalScale | `int` | `2` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L229) | decimalSeparator | `String` | `","` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L227) | prefix | `String` | `"€"` | | |
+| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java#L228) | thousandSeparator | `String` | `"."` | | |
### Type ExecutionStatus [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/apiv1/ExecutionStatus.java#L18)
From 580e5d3e1b27dadb80909f2154af5c96bc3f9534 Mon Sep 17 00:00:00 2001
From: Fabian Kovacs <1553491+awildturtok@users.noreply.github.com>
Date: Wed, 28 Jul 2021 11:55:31 +0200
Subject: [PATCH 44/82] refactor PrimaryDictionary into it's own separate store
#NeedsReimport
---
.../bakdata/conquery/ConqueryConstants.java | 4 +-
.../conquery/io/storage/NamespaceStorage.java | 36 +-
.../io/storage/NamespacedStorage.java | 4 +-
.../conquery/io/storage/StoreInfo.java | 125 +++---
.../xodus/stores/SerializingStore.java | 16 +-
.../conquery/models/config/ColumnConfig.java | 16 +-
.../models/config/FrontendConfig.java | 14 +-
.../conquery/models/config/StoreFactory.java | 2 +
.../models/config/XodusStoreFactory.java | 369 +++++++++---------
.../identifiable/mapping/EntityIdMap.java | 21 +-
.../identifiable/mapping/FullIdPrinter.java | 8 +-
.../conquery/models/jobs/ImportJob.java | 11 +-
.../admin/rest/AdminDatasetProcessor.java | 1 +
.../integration/IntegrationTests.java | 11 +-
.../integration/common/LoadingUtil.java | 8 +-
.../conquery/integration/json/FormTest.java | 6 +-
.../conquery/integration/json/QueryTest.java | 2 +-
.../identifiable/IdMapSerialisationTest.java | 2 +-
.../util/NonPersistentStoreFactory.java | 213 +++++-----
.../conquery/util/support/TestConquery.java | 4 +-
20 files changed, 468 insertions(+), 405 deletions(-)
diff --git a/backend/src/main/java/com/bakdata/conquery/ConqueryConstants.java b/backend/src/main/java/com/bakdata/conquery/ConqueryConstants.java
index cf44882817..c9d6c49611 100644
--- a/backend/src/main/java/com/bakdata/conquery/ConqueryConstants.java
+++ b/backend/src/main/java/com/bakdata/conquery/ConqueryConstants.java
@@ -30,12 +30,14 @@ public class ConqueryConstants {
public static final ResultInfo FEATURE_DATE_RANGE_INFO = new LocalizedDefaultResultInfo((l) -> C10N.get(ResultHeadersC10n.class, l).featureDateRange(), ResultType.DateRangeT.INSTANCE);
public static final ResultInfo OUTCOME_DATE_RANGE_INFO = new LocalizedDefaultResultInfo((l) -> C10N.get(ResultHeadersC10n.class, l).outcomeDateRange(), ResultType.DateRangeT.INSTANCE);
+ public static final String PRIMARY_DICTIONARY = "PRIMARY_DICTIONARY";
+
public static class AuthenticationUtil {
public static final String REALM_NAME = "CONQUERY";
}
public static DictionaryId getPrimaryDictionary(Dataset dataset) {
- return DictionaryId.Parser.INSTANCE.parse(Arrays.asList(dataset.getName(), "primary_dictionary"));
+ return DictionaryId.Parser.INSTANCE.parse(Arrays.asList(dataset.getName(), PRIMARY_DICTIONARY));
}
}
diff --git a/backend/src/main/java/com/bakdata/conquery/io/storage/NamespaceStorage.java b/backend/src/main/java/com/bakdata/conquery/io/storage/NamespaceStorage.java
index c85f6188dc..ee5bd5b426 100644
--- a/backend/src/main/java/com/bakdata/conquery/io/storage/NamespaceStorage.java
+++ b/backend/src/main/java/com/bakdata/conquery/io/storage/NamespaceStorage.java
@@ -5,9 +5,14 @@
import javax.validation.Validator;
+import com.bakdata.conquery.ConqueryConstants;
import com.bakdata.conquery.io.storage.xodus.stores.SingletonStore;
import com.bakdata.conquery.models.datasets.concepts.StructureNode;
import com.bakdata.conquery.models.config.StoreFactory;
+import com.bakdata.conquery.models.dictionary.Dictionary;
+import com.bakdata.conquery.models.dictionary.EncodedDictionary;
+import com.bakdata.conquery.models.dictionary.MapDictionary;
+import com.bakdata.conquery.models.events.stores.specific.string.StringTypeEncoded;
import com.bakdata.conquery.models.identifiable.mapping.EntityIdMap;
import com.bakdata.conquery.models.worker.SingletonNamespaceCollection;
import com.bakdata.conquery.models.worker.WorkerToBucketsMap;
@@ -27,6 +32,8 @@ public class NamespaceStorage extends NamespacedStorage {
protected SingletonStore structure;
protected SingletonStore workerToBuckets;
+ protected SingletonStore primaryDictionary;
+
@Getter
private final boolean registerImports = true;
@@ -36,13 +43,34 @@ public NamespaceStorage(Validator validator, StoreFactory storageFactory, String
idMapping = storageFactory.createIdMappingStore(pathName);
structure = storageFactory.createStructureStore(pathName, new SingletonNamespaceCollection(getCentralRegistry()));
workerToBuckets = storageFactory.createWorkerToBucketsStore(pathName);
-
+ primaryDictionary = storageFactory.createPrimaryDictionaryStore(pathName);
decorateIdMapping(idMapping);
}
+ public EncodedDictionary getPrimaryDictionary() {
+ return new EncodedDictionary(getPrimaryDictionaryRaw(), StringTypeEncoded.Encoding.UTF8);
+ }
+
+ @NonNull
+ public Dictionary getPrimaryDictionaryRaw() {
+ final Dictionary dictionary = primaryDictionary.get();
+
+ if(dictionary == null){
+ log.trace("No prior PrimaryDictionary, creating one");
+ final MapDictionary newPrimary = new MapDictionary(getDataset(), ConqueryConstants.PRIMARY_DICTIONARY);
+
+ primaryDictionary.update(newPrimary);
+
+ return newPrimary;
+ }
+
+ return dictionary;
+ }
+
+
private void decorateIdMapping(SingletonStore idMapping) {
- idMapping.onAdd(mapping -> mapping.setDictionary(getPrimaryDictionary()));
+ idMapping.onAdd(mapping -> mapping.setStorage(this));
}
@@ -84,6 +112,10 @@ public EntityIdMap getIdMapping() {
}
+ public void updatePrimaryDictionary(Dictionary dictionary){
+ primaryDictionary.update(dictionary);
+ }
+
public void updateIdMapping(EntityIdMap idMapping) {
this.idMapping.update(idMapping);
}
diff --git a/backend/src/main/java/com/bakdata/conquery/io/storage/NamespacedStorage.java b/backend/src/main/java/com/bakdata/conquery/io/storage/NamespacedStorage.java
index 0d7221b16f..6158a6791e 100644
--- a/backend/src/main/java/com/bakdata/conquery/io/storage/NamespacedStorage.java
+++ b/backend/src/main/java/com/bakdata/conquery/io/storage/NamespacedStorage.java
@@ -215,9 +215,7 @@ public void removeDictionary(DictionaryId id) {
dictionaries.remove(id);
}
- public EncodedDictionary getPrimaryDictionary() {
- return new EncodedDictionary(dictionaries.get(ConqueryConstants.getPrimaryDictionary(getDataset())), StringTypeEncoded.Encoding.UTF8);
- }
+
public void addImport(Import imp) {
imports.add(imp);
diff --git a/backend/src/main/java/com/bakdata/conquery/io/storage/StoreInfo.java b/backend/src/main/java/com/bakdata/conquery/io/storage/StoreInfo.java
index ea6440b9fa..1a97525fe1 100644
--- a/backend/src/main/java/com/bakdata/conquery/io/storage/StoreInfo.java
+++ b/backend/src/main/java/com/bakdata/conquery/io/storage/StoreInfo.java
@@ -6,12 +6,12 @@
import com.bakdata.conquery.models.auth.entities.Group;
import com.bakdata.conquery.models.auth.entities.Role;
import com.bakdata.conquery.models.auth.entities.User;
-import com.bakdata.conquery.models.datasets.concepts.Concept;
-import com.bakdata.conquery.models.datasets.concepts.StructureNode;
import com.bakdata.conquery.models.datasets.Dataset;
import com.bakdata.conquery.models.datasets.Import;
import com.bakdata.conquery.models.datasets.SecondaryIdDescription;
import com.bakdata.conquery.models.datasets.Table;
+import com.bakdata.conquery.models.datasets.concepts.Concept;
+import com.bakdata.conquery.models.datasets.concepts.StructureNode;
import com.bakdata.conquery.models.dictionary.Dictionary;
import com.bakdata.conquery.models.events.Bucket;
import com.bakdata.conquery.models.events.CBlock;
@@ -49,76 +49,77 @@
*/
@RequiredArgsConstructor
@Getter
-@ToString(of={"name", "keyType", "valueType" })
+@ToString(of = {"name", "keyType", "valueType"})
public enum StoreInfo implements IStoreInfo {
- DATASET(Dataset.class, Boolean.class),
- ID_MAPPING(EntityIdMap.class, Boolean.class),
- NAMESPACES(DatasetRegistry.class, Boolean.class),
- SLAVE(ShardNodeInformation.class, Boolean.class),
- DICTIONARIES(Dictionary.class, DictionaryId.class),
- IMPORTS(Import.class, ImportId.class),
- SECONDARY_IDS(SecondaryIdDescription.class, SecondaryIdDescriptionId.class),
- TABLES(Table.class, TableId.class),
- CONCEPTS(Concept.class, ConceptId.class),
- BUCKETS(Bucket.class, BucketId.class),
- C_BLOCKS(CBlock.class, CBlockId.class),
- WORKER(WorkerInformation.class, Boolean.class),
- EXECUTIONS(ManagedExecution.class, ManagedExecutionId.class),
- AUTH_ROLE(Role.class, RoleId.class),
- AUTH_USER(User.class, UserId.class),
- AUTH_GROUP(Group.class, GroupId.class),
- STRUCTURE(StructureNode[].class, Boolean.class),
- FORM_CONFIG(FormConfig.class, FormConfigId.class),
- WORKER_TO_BUCKETS(WorkerToBucketsMap.class, Boolean.class);
+ DATASET(Dataset.class, Boolean.class),
+ ID_MAPPING(EntityIdMap.class, Boolean.class),
+ NAMESPACES(DatasetRegistry.class, Boolean.class),
+ SLAVE(ShardNodeInformation.class, Boolean.class),
+ DICTIONARIES(Dictionary.class, DictionaryId.class),
+ IMPORTS(Import.class, ImportId.class),
+ SECONDARY_IDS(SecondaryIdDescription.class, SecondaryIdDescriptionId.class),
+ TABLES(Table.class, TableId.class),
+ CONCEPTS(Concept.class, ConceptId.class),
+ BUCKETS(Bucket.class, BucketId.class),
+ C_BLOCKS(CBlock.class, CBlockId.class),
+ WORKER(WorkerInformation.class, Boolean.class),
+ EXECUTIONS(ManagedExecution.class, ManagedExecutionId.class),
+ AUTH_ROLE(Role.class, RoleId.class),
+ AUTH_USER(User.class, UserId.class),
+ AUTH_GROUP(Group.class, GroupId.class),
+ STRUCTURE(StructureNode[].class, Boolean.class),
+ FORM_CONFIG(FormConfig.class, FormConfigId.class),
+ WORKER_TO_BUCKETS(WorkerToBucketsMap.class, Boolean.class),
+ PRIMARY_DICTIONARY(Dictionary.class, Boolean.class);
- private final Class> valueType;
- private final Class> keyType;
+ private final Class> valueType;
+ private final Class> keyType;
- /**
- * Store for identifiable values, with injectors. Store is also cached.
- */
- public > DirectIdentifiableStore identifiable(Store, T> baseStore, CentralRegistry centralRegistry, Injectable... injectables) {
+ /**
+ * Store for identifiable values, with injectors. Store is also cached.
+ */
+ public > DirectIdentifiableStore identifiable(Store, T> baseStore, CentralRegistry centralRegistry, Injectable... injectables) {
- for (Injectable injectable : injectables) {
- baseStore.inject(injectable);
- }
+ for (Injectable injectable : injectables) {
+ baseStore.inject(injectable);
+ }
- baseStore.inject(centralRegistry);
+ baseStore.inject(centralRegistry);
- return new DirectIdentifiableStore<>(centralRegistry, baseStore);
- }
+ return new DirectIdentifiableStore<>(centralRegistry, baseStore);
+ }
- /**
- * Store for identifiable values, without injectors. Store is also cached.
- */
- public > DirectIdentifiableStore identifiable(Store, T> baseStore, CentralRegistry centralRegistry) {
- return identifiable(baseStore, centralRegistry, new SingletonNamespaceCollection(centralRegistry));
- }
+ /**
+ * Store for identifiable values, without injectors. Store is also cached.
+ */
+ public > DirectIdentifiableStore identifiable(Store, T> baseStore, CentralRegistry centralRegistry) {
+ return identifiable(baseStore, centralRegistry, new SingletonNamespaceCollection(centralRegistry));
+ }
- /**
- * General Key-Value store with caching.
- */
- public CachedStore cached(Store baseStore) {
- return new CachedStore<>(baseStore);
- }
+ /**
+ * General Key-Value store with caching.
+ */
+ public CachedStore cached(Store baseStore) {
+ return new CachedStore<>(baseStore);
+ }
- /**
- * Identifiable store, that lazy registers items in the central registry.
- */
- public > IdentifiableCachedStore identifiableCachedStore(Store baseStore, CentralRegistry centralRegistry) {
- return new IdentifiableCachedStore(centralRegistry, baseStore);
- }
+ /**
+ * Identifiable store, that lazy registers items in the central registry.
+ */
+ public > IdentifiableCachedStore identifiableCachedStore(Store baseStore, CentralRegistry centralRegistry) {
+ return new IdentifiableCachedStore(centralRegistry, baseStore);
+ }
- /**
- * Store holding a single value.
- */
- public SingletonStore singleton(Store baseStore, Injectable... injectables) {
- return new SingletonStore<>(baseStore, injectables);
- }
+ /**
+ * Store holding a single value.
+ */
+ public SingletonStore singleton(Store baseStore, Injectable... injectables) {
+ return new SingletonStore<>(baseStore, injectables);
+ }
- @Override
- public String getName() {
- return name();
- }
+ @Override
+ public String getName() {
+ return name();
+ }
}
diff --git a/backend/src/main/java/com/bakdata/conquery/io/storage/xodus/stores/SerializingStore.java b/backend/src/main/java/com/bakdata/conquery/io/storage/xodus/stores/SerializingStore.java
index 2469a5d444..ebc9f4f560 100644
--- a/backend/src/main/java/com/bakdata/conquery/io/storage/xodus/stores/SerializingStore.java
+++ b/backend/src/main/java/com/bakdata/conquery/io/storage/xodus/stores/SerializingStore.java
@@ -114,21 +114,13 @@ public SerializingStore(XodusStoreFactory config, XodusStore store, Validator va
this.objectMapper = objectMapper;
- valueWriter = objectMapper
- .writerFor(valueType)
- .withView(InternalOnly.class);
+ valueWriter = objectMapper.writerFor(valueType);
- valueReader = objectMapper
- .readerFor(valueType)
- .withView(InternalOnly.class);
+ valueReader = objectMapper.readerFor(valueType);
- keyWriter = objectMapper
- .writerFor(storeInfo.getKeyType())
- .withView(InternalOnly.class);
+ keyWriter = objectMapper.writerFor(storeInfo.getKeyType());
- keyReader = objectMapper
- .readerFor(storeInfo.getKeyType())
- .withView(InternalOnly.class);
+ keyReader = objectMapper.readerFor(storeInfo.getKeyType());
removeUnreadablesFromUnderlyingStore = config.isRemoveUnreadableFromStore();
diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java b/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java
index 707d267446..18c70fe764 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/config/ColumnConfig.java
@@ -29,7 +29,6 @@
@Getter
public class ColumnConfig {
-
public EntityIdMap.ExternalId read(String value) {
if (!isResolvable()) {
return null;
@@ -39,13 +38,13 @@ public EntityIdMap.ExternalId read(String value) {
return null;
}
- if (getLength() == -1) {
- return new EntityIdMap.ExternalId(new String[]{getName(), value});
+ if (getLength() == -1 || getPad() == null) {
+ return new EntityIdMap.ExternalId(getName(), value);
}
String padded = StringUtils.leftPad(value, getLength(), getPad());
- return new EntityIdMap.ExternalId(new String[]{getName(), padded});
+ return new EntityIdMap.ExternalId(getName(), padded);
}
@@ -57,11 +56,13 @@ public EntityIdMap.ExternalId read(String value) {
* Map of Localized labels.
*/
@NotEmpty
+ @Builder.Default
private Map label = Collections.emptyMap();
/**
* Map of Localized description.
*/
+ @Builder.Default
private Map description = Collections.emptyMap();
@InternalOnly
@@ -71,12 +72,19 @@ public EntityIdMap.ExternalId read(String value) {
private String pad = null;
@InternalOnly
+ @Builder.Default
private int length = -1;
@InternalOnly
+ @Builder.Default
private boolean resolvable = false;
@InternalOnly
+ @Builder.Default
+ private boolean print = true;
+
+ @InternalOnly
+ @Builder.Default
private boolean fillAnon = false;
@JsonIgnore
diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java b/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java
index 8a55a9b8ba..157f0008aa 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/config/FrontendConfig.java
@@ -80,8 +80,8 @@ public static class UploadConfig {
public List getPrintIdFields() {
if (idFieldsCached == null) {
idFieldsCached = ids.stream()
+ .filter(ColumnConfig::isPrint)
.map(ColumnConfig::getField)
- .filter(Objects::nonNull)
.collect(Collectors.toUnmodifiableList());
}
@@ -89,6 +89,7 @@ public List getPrintIdFields() {
}
@JsonIgnore
+ @Setter(AccessLevel.NONE)
private Map idMappers;
public ColumnConfig getIdMapper(String name) {
@@ -207,17 +208,18 @@ public DateFormat resolveDateFormat(String handle) {
* Try to create a {@link FullIdPrinter} for user if they are allowed. If not allowed to read ids, they will receive ab pseudomized result instead.
*/
public IdPrinter getIdPrinter(User owner, ManagedExecution> execution, Namespace namespace) {
-
- if (owner.isPermitted(execution.getDataset(), Ability.PRESERVE_ID)) {
- return new FullIdPrinter(namespace.getStorage().getPrimaryDictionary(), namespace.getStorage().getIdMapping());
- }
-
final int size = getPrintIdFields().size();
final int pos = IntStream.range(0, getIds().size())
.filter(idx -> getIds().get(idx).isFillAnon())
.findFirst()
.orElseThrow();
+ if (owner.isPermitted(execution.getDataset(), Ability.PRESERVE_ID)) {
+ return new FullIdPrinter(namespace.getStorage().getPrimaryDictionary(), namespace.getStorage().getIdMapping(), size, pos);
+ }
+
+
+
return new AutoIncrementingPseudomizer(size, pos);
}
}
diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/StoreFactory.java b/backend/src/main/java/com/bakdata/conquery/models/config/StoreFactory.java
index 8170c77fdc..0c642243ab 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/config/StoreFactory.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/config/StoreFactory.java
@@ -66,4 +66,6 @@ public interface StoreFactory {
IdentifiableStore createUserStore(CentralRegistry centralRegistry, String pathName);
IdentifiableStore createRoleStore(CentralRegistry centralRegistry, String pathName);
IdentifiableStore createGroupStore(CentralRegistry centralRegistry, String pathName);
+
+ SingletonStore createPrimaryDictionaryStore(String pathName);
}
diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/XodusStoreFactory.java b/backend/src/main/java/com/bakdata/conquery/models/config/XodusStoreFactory.java
index 8d823fdc62..5e9a3b7afa 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/config/XodusStoreFactory.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/config/XodusStoreFactory.java
@@ -24,6 +24,7 @@
import com.bakdata.conquery.commands.ManagerNode;
import com.bakdata.conquery.commands.ShardNode;
import com.bakdata.conquery.io.cps.CPSType;
+import com.bakdata.conquery.io.jackson.InternalOnly;
import com.bakdata.conquery.io.jackson.Jackson;
import com.bakdata.conquery.io.storage.IdentifiableStore;
import com.bakdata.conquery.io.storage.NamespaceStorage;
@@ -40,12 +41,12 @@
import com.bakdata.conquery.models.auth.entities.Group;
import com.bakdata.conquery.models.auth.entities.Role;
import com.bakdata.conquery.models.auth.entities.User;
-import com.bakdata.conquery.models.datasets.concepts.Concept;
-import com.bakdata.conquery.models.datasets.concepts.StructureNode;
import com.bakdata.conquery.models.datasets.Dataset;
import com.bakdata.conquery.models.datasets.Import;
import com.bakdata.conquery.models.datasets.SecondaryIdDescription;
import com.bakdata.conquery.models.datasets.Table;
+import com.bakdata.conquery.models.datasets.concepts.Concept;
+import com.bakdata.conquery.models.datasets.concepts.StructureNode;
import com.bakdata.conquery.models.dictionary.Dictionary;
import com.bakdata.conquery.models.events.Bucket;
import com.bakdata.conquery.models.events.CBlock;
@@ -90,69 +91,73 @@
@CPSType(id = "XODUS", base = StoreFactory.class)
public class XodusStoreFactory implements StoreFactory {
- private Path directory = Path.of("storage");
+ private Path directory = Path.of("storage");
- private boolean validateOnWrite = false;
- @NotNull
- @Valid
- private XodusConfig xodus = new XodusConfig();
+ private boolean validateOnWrite = false;
+ @NotNull
+ @Valid
+ private XodusConfig xodus = new XodusConfig();
- private boolean useWeakDictionaryCaching = true;
- @NotNull
- private Duration weakCacheDuration = Duration.hours(48);
+ private boolean useWeakDictionaryCaching = true;
+ @NotNull
+ private Duration weakCacheDuration = Duration.hours(48);
- @Min(1)
- private int nThreads = Runtime.getRuntime().availableProcessors();
+ @Min(1)
+ private int nThreads = Runtime.getRuntime().availableProcessors();
- /**
- * Flag for the {@link SerializingStore} whether to delete values from the underlying store, that cannot be mapped to an object anymore.
- */
- private boolean removeUnreadableFromStore = false;
+ /**
+ * Flag for the {@link SerializingStore} whether to delete values from the underlying store, that cannot be mapped to an object anymore.
+ */
+ private boolean removeUnreadableFromStore = false;
- /**
- * When set, all values that could not be deserialized from the persistent store, are dump into individual files.
- */
- private Optional unreadableDataDumpDirectory = Optional.empty();
+ /**
+ * When set, all values that could not be deserialized from the persistent store, are dump into individual files.
+ */
+ private Optional unreadableDataDumpDirectory = Optional.empty();
- @JsonIgnore
- private transient Validator validator;
+ @JsonIgnore
+ private transient Validator validator;
- @JsonIgnore
- private transient ObjectMapper objectMapper = Jackson.BINARY_MAPPER.copy();
+ @JsonIgnore
+ private transient ObjectMapper objectMapper = Jackson.BINARY_MAPPER.copy();
- @JsonIgnore
- private BiMap activeEnvironments = HashBiMap.create();
+ @JsonIgnore
+ private BiMap activeEnvironments = HashBiMap.create();
- @JsonIgnore
- private final transient Multimap openStoresInEnv = Multimaps.synchronizedSetMultimap(MultimapBuilder.hashKeys().hashSetValues().build());
+ @JsonIgnore
+ private final transient Multimap
+ openStoresInEnv =
+ Multimaps.synchronizedSetMultimap(MultimapBuilder.hashKeys().hashSetValues().build());
- @Override
- public void init(ManagerNode managerNode) {
- validator = managerNode.getValidator();
- configureMapper(managerNode.getConfig());
- }
+ @Override
+ public void init(ManagerNode managerNode) {
+ validator = managerNode.getValidator();
+ configureMapper(managerNode.getConfig());
+ }
- @Override
- public void init(ShardNode shardNode) {
- validator = shardNode.getValidator();
- configureMapper(shardNode.getConfig());
- }
+ @Override
+ public void init(ShardNode shardNode) {
+ validator = shardNode.getValidator();
+ configureMapper(shardNode.getConfig());
+ }
- private void configureMapper(ConqueryConfig config) {
- config.configureObjectMapper(objectMapper);
- }
+ private void configureMapper(ConqueryConfig config) {
+ config.configureObjectMapper(objectMapper);
+ objectMapper.setConfig(objectMapper.getDeserializationConfig().withView(InternalOnly.class));
+ objectMapper.setConfig(objectMapper.getSerializationConfig().withView(InternalOnly.class));
+ }
- @Override
- @SneakyThrows
- public Collection loadNamespaceStorages() {
+ @Override
+ @SneakyThrows
+ public Collection loadNamespaceStorages() {
return loadNamespacedStores("dataset_", (elements) -> new NamespaceStorage(validator, this, elements));
- }
+ }
- @Override
- @SneakyThrows
- public Collection loadWorkerStorages() {
+ @Override
+ @SneakyThrows
+ public Collection loadWorkerStorages() {
return loadNamespacedStores("worker_", (elements) -> new WorkerStorage(validator, this, elements));
- }
+ }
private Queue loadNamespacedStores(String prefix, Function creator)
@@ -167,7 +172,7 @@ private Queue loadNamespacedStores(String prefi
ExecutorService loaders = Executors.newFixedThreadPool(getNThreads());
- for (File directory : baseDir.listFiles((file, name) -> file.isDirectory() && name.startsWith(prefix))) {
+ for (File directory : baseDir.listFiles((file, name) -> file.isDirectory() && name.startsWith(prefix))) {
final String name = directory.getName();
@@ -209,38 +214,38 @@ private Queue loadNamespacedStores(String prefi
}
private List getRelativePathElements(Path path) {
- ArrayList list = new ArrayList<>();
- Path relative = getDirectory().relativize(path);
- for (int i = 0; i < relative.getNameCount(); i++) {
- list.add(relative.getName(i).toString());
- }
- return list;
- }
-
- private boolean environmentHasStores(File pathName) {
- Environment env = findEnvironment(pathName);
- boolean exists = env.computeInTransaction(t -> env.storeExists(StoreInfo.DATASET.getName(), t));
- env.computeInTransaction(t -> env.getAllStoreNames(t));
- if (!exists) {
- closeEnvironment(env);
- }
- return exists;
- }
-
- @Override
- public SingletonStore createDatasetStore(String pathName) {
- return DATASET.singleton(createStore(findEnvironment(pathName), validator, DATASET));
- }
-
- @Override
- public IdentifiableStore createSecondaryIdDescriptionStore(CentralRegistry centralRegistry, String pathName) {
- return SECONDARY_IDS.identifiable(createStore(findEnvironment(pathName), validator, SECONDARY_IDS), centralRegistry);
- }
-
- @Override
- public IdentifiableStore createTableStore(CentralRegistry centralRegistry, String pathName) {
- return TABLES.identifiable(createStore(findEnvironment(pathName), validator, TABLES), centralRegistry);
- }
+ ArrayList list = new ArrayList<>();
+ Path relative = getDirectory().relativize(path);
+ for (int i = 0; i < relative.getNameCount(); i++) {
+ list.add(relative.getName(i).toString());
+ }
+ return list;
+ }
+
+ private boolean environmentHasStores(File pathName) {
+ Environment env = findEnvironment(pathName);
+ boolean exists = env.computeInTransaction(t -> env.storeExists(StoreInfo.DATASET.getName(), t));
+ env.computeInTransaction(t -> env.getAllStoreNames(t));
+ if (!exists) {
+ closeEnvironment(env);
+ }
+ return exists;
+ }
+
+ @Override
+ public SingletonStore createDatasetStore(String pathName) {
+ return DATASET.singleton(createStore(findEnvironment(pathName), validator, DATASET));
+ }
+
+ @Override
+ public IdentifiableStore createSecondaryIdDescriptionStore(CentralRegistry centralRegistry, String pathName) {
+ return SECONDARY_IDS.identifiable(createStore(findEnvironment(pathName), validator, SECONDARY_IDS), centralRegistry);
+ }
+
+ @Override
+ public IdentifiableStore createTableStore(CentralRegistry centralRegistry, String pathName) {
+ return TABLES.identifiable(createStore(findEnvironment(pathName), validator, TABLES), centralRegistry);
+ }
@Override
public IdentifiableStore createDictionaryStore(CentralRegistry centralRegistry, String pathName) {
@@ -251,7 +256,9 @@ public IdentifiableStore createDictionaryStore(CentralRegistry centr
final BigStore, Dictionary> bigStore;
synchronized (openStoresInEnv) {
- bigStore = new BigStore<>(this, validator, environment, DICTIONARIES, openStoresInEnv.get(environment), this::closeEnvironment, this::removeEnvironment, namespaceCollection.injectInto(objectMapper));
+ bigStore =
+ new BigStore<>(this, validator, environment, DICTIONARIES, openStoresInEnv.get(environment), this::closeEnvironment, this::removeEnvironment, namespaceCollection
+ .injectInto(objectMapper));
}
final Store, Dictionary> result;
@@ -266,30 +273,30 @@ public IdentifiableStore createDictionaryStore(CentralRegistry centr
return DICTIONARIES.identifiableCachedStore(result, centralRegistry);
}
- @Override
- public IdentifiableStore> createConceptStore(CentralRegistry centralRegistry, String pathName) {
- return CONCEPTS.identifiable(createStore(findEnvironment(pathName), validator, CONCEPTS), centralRegistry);
- }
+ @Override
+ public IdentifiableStore> createConceptStore(CentralRegistry centralRegistry, String pathName) {
+ return CONCEPTS.identifiable(createStore(findEnvironment(pathName), validator, CONCEPTS), centralRegistry);
+ }
- @Override
- public IdentifiableStore createImportStore(CentralRegistry centralRegistry, String pathName) {
- return IMPORTS.identifiable(createStore(findEnvironment(pathName), validator, IMPORTS), centralRegistry);
- }
+ @Override
+ public IdentifiableStore createImportStore(CentralRegistry centralRegistry, String pathName) {
+ return IMPORTS.identifiable(createStore(findEnvironment(pathName), validator, IMPORTS), centralRegistry);
+ }
- @Override
- public IdentifiableStore createCBlockStore(CentralRegistry centralRegistry, String pathName) {
- return C_BLOCKS.identifiable(createStore(findEnvironment(pathName), validator, C_BLOCKS), centralRegistry);
- }
+ @Override
+ public IdentifiableStore createCBlockStore(CentralRegistry centralRegistry, String pathName) {
+ return C_BLOCKS.identifiable(createStore(findEnvironment(pathName), validator, C_BLOCKS), centralRegistry);
+ }
- @Override
- public IdentifiableStore createBucketStore(CentralRegistry centralRegistry, String pathName) {
- return BUCKETS.identifiable(createStore(findEnvironment(pathName), validator, BUCKETS), centralRegistry);
- }
+ @Override
+ public IdentifiableStore createBucketStore(CentralRegistry centralRegistry, String pathName) {
+ return BUCKETS.identifiable(createStore(findEnvironment(pathName), validator, BUCKETS), centralRegistry);
+ }
- @Override
- public SingletonStore createWorkerInformationStore(String pathName) {
- return WORKER.singleton(createStore(findEnvironment(pathName), validator, WORKER));
- }
+ @Override
+ public SingletonStore createWorkerInformationStore(String pathName) {
+ return WORKER.singleton(createStore(findEnvironment(pathName), validator, WORKER));
+ }
@Override
public SingletonStore createIdMappingStore(String pathName) {
@@ -303,43 +310,48 @@ public SingletonStore createIdMappingStore(String pathName) {
}
}
- @Override
- public SingletonStore createWorkerToBucketsStore(String pathName) {
- return WORKER_TO_BUCKETS.singleton(createStore(findEnvironment(pathName), validator, WORKER_TO_BUCKETS));
- }
+ @Override
+ public SingletonStore createWorkerToBucketsStore(String pathName) {
+ return WORKER_TO_BUCKETS.singleton(createStore(findEnvironment(pathName), validator, WORKER_TO_BUCKETS));
+ }
+
+ @Override
+ public SingletonStore createStructureStore(String pathName, SingletonNamespaceCollection centralRegistry) {
+ return STRUCTURE.singleton(createStore(findEnvironment(pathName), validator, STRUCTURE), centralRegistry);
+ }
- @Override
- public SingletonStore createStructureStore(String pathName, SingletonNamespaceCollection centralRegistry) {
- return STRUCTURE.singleton(createStore(findEnvironment(pathName), validator, STRUCTURE), centralRegistry);
- }
+ @Override
+ public IdentifiableStore> createExecutionsStore(CentralRegistry centralRegistry, DatasetRegistry datasetRegistry, String pathName) {
+ return EXECUTIONS.identifiable(createStore(findEnvironment(resolveSubDir(pathName, "executions")), validator, EXECUTIONS), centralRegistry, datasetRegistry);
+ }
- @Override
- public IdentifiableStore> createExecutionsStore(CentralRegistry centralRegistry, DatasetRegistry datasetRegistry, String pathName) {
- return EXECUTIONS.identifiable(createStore(findEnvironment(resolveSubDir(pathName, "executions")), validator, EXECUTIONS), centralRegistry, datasetRegistry);
- }
+ @Override
+ public IdentifiableStore createFormConfigStore(CentralRegistry centralRegistry, DatasetRegistry datasetRegistry, String pathName) {
+ return FORM_CONFIG.identifiable(createStore(findEnvironment(resolveSubDir(pathName, "formConfigs")), validator, FORM_CONFIG), centralRegistry, datasetRegistry);
+ }
- @Override
- public IdentifiableStore createFormConfigStore(CentralRegistry centralRegistry, DatasetRegistry datasetRegistry, String pathName) {
- return FORM_CONFIG.identifiable(createStore(findEnvironment(resolveSubDir(pathName, "formConfigs")), validator, FORM_CONFIG), centralRegistry, datasetRegistry);
- }
+ @Override
+ public IdentifiableStore createUserStore(CentralRegistry centralRegistry, String pathName) {
+ return AUTH_USER.identifiable(createStore(findEnvironment(resolveSubDir(pathName, "users")), validator, AUTH_USER), centralRegistry);
+ }
- @Override
- public IdentifiableStore createUserStore(CentralRegistry centralRegistry, String pathName) {
- return AUTH_USER.identifiable(createStore(findEnvironment(resolveSubDir(pathName, "users")), validator, AUTH_USER), centralRegistry);
- }
+ @Override
+ public IdentifiableStore createRoleStore(CentralRegistry centralRegistry, String pathName) {
+ return AUTH_ROLE.identifiable(createStore(findEnvironment(resolveSubDir(pathName, "roles")), validator, AUTH_ROLE), centralRegistry);
+ }
- @Override
- public IdentifiableStore createRoleStore(CentralRegistry centralRegistry, String pathName) {
- return AUTH_ROLE.identifiable(createStore(findEnvironment(resolveSubDir(pathName, "roles")), validator, AUTH_ROLE), centralRegistry);
- }
+ @Override
+ public IdentifiableStore createGroupStore(CentralRegistry centralRegistry, String pathName) {
+ return AUTH_GROUP.identifiable(createStore(findEnvironment(resolveSubDir(pathName, "groups")), validator, AUTH_GROUP), centralRegistry);
+ }
- @Override
- public IdentifiableStore createGroupStore(CentralRegistry centralRegistry, String pathName) {
- return AUTH_GROUP.identifiable(createStore(findEnvironment(resolveSubDir(pathName, "groups")), validator, AUTH_GROUP), centralRegistry);
- }
+ @Override
+ public SingletonStore createPrimaryDictionaryStore(String pathName) {
+ return PRIMARY_DICTIONARY.singleton(createStore(findEnvironment(pathName), validator, PRIMARY_DICTIONARY));
+ }
- private File resolveSubDir(String... subdirs) {
+ private File resolveSubDir(String... subdirs) {
Path current = getDirectory();
for (String dir : subdirs) {
@@ -347,55 +359,56 @@ private File resolveSubDir(String... subdirs) {
}
return current.toFile();
- }
+ }
- /**
- * Returns this.directory if the list is empty.
- */
+ /**
+ * Returns this.directory if the list is empty.
+ */
@NonNull
@JsonIgnore
private File getStorageDir(String pathName) {
return getDirectory().resolve(pathName).toFile();
- }
-
- private Environment findEnvironment(@NonNull File path) {
- synchronized (activeEnvironments) {
- return activeEnvironments.computeIfAbsent(path, (p) -> Environments.newInstance(path, getXodus().createConfig()));
- }
- }
-
- private Environment findEnvironment(String pathName) {
- synchronized (activeEnvironments) {
- File path = getStorageDir(pathName);
- return activeEnvironments.computeIfAbsent(path, (p) -> Environments.newInstance(p, getXodus().createConfig()));
- }
- }
-
- private void closeEnvironment(Environment env) {
- synchronized (activeEnvironments) {
- if (env == null) {
- return;
- }
-
- if(activeEnvironments.remove(activeEnvironments.inverse().get(env)) == null){
- return;
- }
- env.close();
- }
- }
-
- private void removeEnvironment(Environment env) {
- log.info("Deleting Environment[{}]", env.getLocation());
- try {
- FileUtil.deleteRecursive(Path.of(env.getLocation()));
- }catch (IOException e) {
- log.error("Cannot delete directory of removed Environment[{}]", env.getLocation(), log.isDebugEnabled()? e : null);
- }
- }
-
- public Store createStore(Environment environment, Validator validator, StoreInfo storeId) {
- synchronized (openStoresInEnv) {
- return new CachedStore<>(
+ }
+
+ private Environment findEnvironment(@NonNull File path) {
+ synchronized (activeEnvironments) {
+ return activeEnvironments.computeIfAbsent(path, (p) -> Environments.newInstance(path, getXodus().createConfig()));
+ }
+ }
+
+ private Environment findEnvironment(String pathName) {
+ synchronized (activeEnvironments) {
+ File path = getStorageDir(pathName);
+ return activeEnvironments.computeIfAbsent(path, (p) -> Environments.newInstance(p, getXodus().createConfig()));
+ }
+ }
+
+ private void closeEnvironment(Environment env) {
+ synchronized (activeEnvironments) {
+ if (env == null) {
+ return;
+ }
+
+ if (activeEnvironments.remove(activeEnvironments.inverse().get(env)) == null) {
+ return;
+ }
+ env.close();
+ }
+ }
+
+ private void removeEnvironment(Environment env) {
+ log.info("Deleting Environment[{}]", env.getLocation());
+ try {
+ FileUtil.deleteRecursive(Path.of(env.getLocation()));
+ }
+ catch (IOException e) {
+ log.error("Cannot delete directory of removed Environment[{}]", env.getLocation(), log.isDebugEnabled() ? e : null);
+ }
+ }
+
+ public Store createStore(Environment environment, Validator validator, StoreInfo storeId) {
+ synchronized (openStoresInEnv) {
+ return new CachedStore<>(
new SerializingStore<>(
this,
new XodusStore(environment, storeId, openStoresInEnv.get(environment), this::closeEnvironment, this::removeEnvironment),
@@ -403,7 +416,7 @@ public Store createStore(Environment environment, Valid
storeId,
objectMapper
));
- }
- }
+ }
+ }
}
diff --git a/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/EntityIdMap.java b/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/EntityIdMap.java
index 77bcd6363d..6979661322 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/EntityIdMap.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/EntityIdMap.java
@@ -5,8 +5,10 @@
import java.util.List;
import java.util.Map;
+import com.bakdata.conquery.io.storage.NamespaceStorage;
import com.bakdata.conquery.models.config.ColumnConfig;
import com.bakdata.conquery.models.dictionary.EncodedDictionary;
+import com.bakdata.conquery.models.worker.Namespace;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonValue;
@@ -32,7 +34,7 @@ public class EntityIdMap {
@Setter
@JsonIgnore
- private EncodedDictionary dictionary;
+ private NamespaceStorage storage;
/**
* The map from csv entity ids to external entity ids.
@@ -65,12 +67,14 @@ public static EntityIdMap generateIdMapping(CsvParser parser, List
final String otherId = record.getString(columnConfig.getField());
- idParts.add(otherId);
-
if (otherId == null) {
continue;
}
+ if(columnConfig.isPrint()) {
+ idParts.add(otherId);
+ }
+
if (!columnConfig.isResolvable()) {
continue;
}
@@ -144,10 +148,13 @@ public int resolve(ExternalId key) {
String value = external2Internal.get(key);
if (value != null) {
- return dictionary.getId(value);
+ return getStorage().getPrimaryDictionary().getId(value);
}
- return -1;
+ // Maybe we can find them directly in the dictionary?
+ final int id = getStorage().getPrimaryDictionary().getId(key.getId());
+
+ return id;
}
public void addOutputMapping(String csvEntityId, EntityPrintId externalEntityId) {
@@ -171,8 +178,8 @@ public void addInputMapping(String csvEntityId, ExternalId externalEntityId) {
@Data
@RequiredArgsConstructor(onConstructor_ = @JsonCreator)
public static class ExternalId {
- @Getter
- private final String[] parts;
+ private final String type;
+ private final String id;
}
}
diff --git a/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/FullIdPrinter.java b/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/FullIdPrinter.java
index db1c3ba8b5..81711a7fbf 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/FullIdPrinter.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/identifiable/mapping/FullIdPrinter.java
@@ -13,6 +13,9 @@ public class FullIdPrinter implements IdPrinter {
private final EncodedDictionary dictionary;
private final EntityIdMap idMapping;
+ private final int size;
+ private final int idPos;
+
@Override
public EntityPrintId createId(EntityResult entityResult){
@@ -26,7 +29,10 @@ public EntityPrintId createId(EntityResult entityResult){
EntityPrintId externalEntityId = idMapping.toExternal(csvEntityId);
if (externalEntityId == null) {
- return EntityPrintId.from(csvEntityId);
+ final String[] parts = new String[size];
+ parts[idPos] = csvEntityId;
+
+ return EntityPrintId.from(parts);
}
return externalEntityId;
diff --git a/backend/src/main/java/com/bakdata/conquery/models/jobs/ImportJob.java b/backend/src/main/java/com/bakdata/conquery/models/jobs/ImportJob.java
index 4facb3c0ce..1f5f8fea75 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/jobs/ImportJob.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/jobs/ImportJob.java
@@ -420,15 +420,8 @@ private Bucket selectBucket(Map localStarts, Map co.override(this));
+ context.getTestInstance()
+ .filter(ConfigOverride.class::isInstance)
+ .map(ConfigOverride.class::cast)
+ .ifPresent(co -> co.override(this));
}
}
}
diff --git a/backend/src/test/java/com/bakdata/conquery/integration/common/LoadingUtil.java b/backend/src/test/java/com/bakdata/conquery/integration/common/LoadingUtil.java
index 4550f3fd44..964f470b14 100644
--- a/backend/src/test/java/com/bakdata/conquery/integration/common/LoadingUtil.java
+++ b/backend/src/test/java/com/bakdata/conquery/integration/common/LoadingUtil.java
@@ -57,10 +57,6 @@
@UtilityClass
public class LoadingUtil {
- public static void importPreviousQueries(StandaloneSupport support, RequiredData content) throws IOException {
- importPreviousQueries(support, content, support.getTestUser());
- }
-
public static void importPreviousQueries(StandaloneSupport support, RequiredData content, User user) throws IOException {
// Load previous query results if available
int id = 1;
@@ -72,7 +68,9 @@ public static void importPreviousQueries(StandaloneSupport support, RequiredData
ConceptQuery q = new ConceptQuery(new CQExternal(Arrays.asList("ID", "DATE_SET"), data));
- ManagedExecution> managed = support.getNamespace().getExecutionManager().createQuery(support.getNamespace().getNamespaces(),q, queryId, user, support.getNamespace().getDataset());
+ ManagedExecution> managed = support.getNamespace().getExecutionManager()
+ .createQuery(support.getNamespace().getNamespaces(),q, queryId, user, support.getNamespace().getDataset());
+
user.addPermission(support.getMetaStorage(), ExecutionPermission.onInstance(AbilitySets.QUERY_CREATOR, managed.getId()));
if (managed.getState() == ExecutionState.FAILED) {
diff --git a/backend/src/test/java/com/bakdata/conquery/integration/json/FormTest.java b/backend/src/test/java/com/bakdata/conquery/integration/json/FormTest.java
index d35cc0f34b..80f1075c77 100644
--- a/backend/src/test/java/com/bakdata/conquery/integration/json/FormTest.java
+++ b/backend/src/test/java/com/bakdata/conquery/integration/json/FormTest.java
@@ -1,5 +1,6 @@
package com.bakdata.conquery.integration.json;
+import static com.bakdata.conquery.integration.common.LoadingUtil.importIdMapping;
import static com.bakdata.conquery.integration.common.LoadingUtil.importSecondaryIds;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
@@ -93,6 +94,10 @@ public void importRequiredData(StandaloneSupport support) throws Exception {
LoadingUtil.importTableContents(support, content.getTables());
support.waitUntilWorkDone();
+
+ importIdMapping(support, content);
+ support.waitUntilWorkDone();
+
log.info("{} IMPORT TABLE CONTENTS", getLabel());
LoadingUtil.importPreviousQueries(support, content, support.getTestUser());
@@ -112,7 +117,6 @@ public void executeTest(StandaloneSupport support) throws Exception {
.isEmpty();
-
ManagedExecution> managedForm = support.getNamespace().getExecutionManager().runQuery(namespaces, form, support.getTestUser(), support.getDataset(), support.getConfig());
managedForm.awaitDone(10, TimeUnit.MINUTES);
diff --git a/backend/src/test/java/com/bakdata/conquery/integration/json/QueryTest.java b/backend/src/test/java/com/bakdata/conquery/integration/json/QueryTest.java
index f797d3324f..04167c3c6f 100644
--- a/backend/src/test/java/com/bakdata/conquery/integration/json/QueryTest.java
+++ b/backend/src/test/java/com/bakdata/conquery/integration/json/QueryTest.java
@@ -63,7 +63,7 @@ public void importRequiredData(StandaloneSupport support) throws Exception {
importIdMapping(support, content);
support.waitUntilWorkDone();
- importPreviousQueries(support, content);
+ importPreviousQueries(support, content, support.getTestUser());
support.waitUntilWorkDone();
query = IntegrationUtils.parseQuery(support, rawQuery);
diff --git a/backend/src/test/java/com/bakdata/conquery/models/identifiable/IdMapSerialisationTest.java b/backend/src/test/java/com/bakdata/conquery/models/identifiable/IdMapSerialisationTest.java
index a92ce8f261..42f895727c 100644
--- a/backend/src/test/java/com/bakdata/conquery/models/identifiable/IdMapSerialisationTest.java
+++ b/backend/src/test/java/com/bakdata/conquery/models/identifiable/IdMapSerialisationTest.java
@@ -8,7 +8,7 @@ public class IdMapSerialisationTest {
public static EntityIdMap createTestPersistentMap() {
EntityIdMap entityIdMap = new EntityIdMap();
- entityIdMap.addInputMapping("test1", new EntityIdMap.ExternalId(new String[]{"a"}));
+ entityIdMap.addInputMapping("test1", new EntityIdMap.ExternalId("id", "a"));
entityIdMap.addOutputMapping("test2", EntityPrintId.from("c"));
diff --git a/backend/src/test/java/com/bakdata/conquery/util/NonPersistentStoreFactory.java b/backend/src/test/java/com/bakdata/conquery/util/NonPersistentStoreFactory.java
index 4af353f08e..d2f06bee60 100644
--- a/backend/src/test/java/com/bakdata/conquery/util/NonPersistentStoreFactory.java
+++ b/backend/src/test/java/com/bakdata/conquery/util/NonPersistentStoreFactory.java
@@ -14,13 +14,13 @@
import com.bakdata.conquery.models.auth.entities.Group;
import com.bakdata.conquery.models.auth.entities.Role;
import com.bakdata.conquery.models.auth.entities.User;
-import com.bakdata.conquery.models.datasets.concepts.Concept;
-import com.bakdata.conquery.models.datasets.concepts.StructureNode;
import com.bakdata.conquery.models.config.StoreFactory;
import com.bakdata.conquery.models.datasets.Dataset;
import com.bakdata.conquery.models.datasets.Import;
import com.bakdata.conquery.models.datasets.SecondaryIdDescription;
import com.bakdata.conquery.models.datasets.Table;
+import com.bakdata.conquery.models.datasets.concepts.Concept;
+import com.bakdata.conquery.models.datasets.concepts.StructureNode;
import com.bakdata.conquery.models.dictionary.Dictionary;
import com.bakdata.conquery.models.events.Bucket;
import com.bakdata.conquery.models.events.CBlock;
@@ -36,107 +36,110 @@
@CPSType(id = "NON_PERSISTENT", base = StoreFactory.class)
public class NonPersistentStoreFactory implements StoreFactory {
- @Override
- public Collection loadNamespaceStorages() {
-
- return Collections.emptyList();
- }
-
- @Override
- public Collection loadWorkerStorages() {
-
- return Collections.emptyList();
- }
-
- @Override
- public SingletonStore createDatasetStore(String pathName) {
- return DATASET.singleton(new NonPersistentStore());
- }
-
- @Override
- public IdentifiableStore createSecondaryIdDescriptionStore(CentralRegistry centralRegistry, String pathName) {
- return SECONDARY_IDS.identifiable(new NonPersistentStore(), centralRegistry);
- }
-
- @Override
- public IdentifiableStore createTableStore(CentralRegistry centralRegistry, String pathName) {
- return TABLES.identifiable(new NonPersistentStore(), centralRegistry);
- }
-
- @Override
- public IdentifiableStore createDictionaryStore(CentralRegistry centralRegistry, String pathName) {
- return DICTIONARIES.identifiable(new NonPersistentStore(), centralRegistry);
- }
-
- @Override
- public IdentifiableStore> createConceptStore(CentralRegistry centralRegistry, String pathName) {
- return CONCEPTS.identifiable(new NonPersistentStore(), centralRegistry);
- }
-
- @Override
- public IdentifiableStore createImportStore(CentralRegistry centralRegistry, String pathName) {
- return IMPORTS.identifiable(new NonPersistentStore(), centralRegistry);
- }
-
- @Override
- public IdentifiableStore createCBlockStore(CentralRegistry centralRegistry, String pathName) {
- return C_BLOCKS.identifiable(new NonPersistentStore(), centralRegistry);
- }
-
- @Override
- public IdentifiableStore createBucketStore(CentralRegistry centralRegistry, String pathName) {
- return BUCKETS.identifiable(new NonPersistentStore(), centralRegistry);
- }
-
- @Override
- public SingletonStore createWorkerInformationStore(String pathName) {
- return WORKER.singleton(new NonPersistentStore());
- }
-
- @Override
- public SingletonStore createIdMappingStore(String pathName) {
- return ID_MAPPING.singleton(new NonPersistentStore());
- }
-
- @Override
- public SingletonStore createWorkerToBucketsStore(String pathName) {
- return WORKER_TO_BUCKETS.singleton(new NonPersistentStore());
- }
-
- @Override
- public SingletonStore createStructureStore(String pathName, SingletonNamespaceCollection centralRegistry) {
- return STRUCTURE.singleton(new NonPersistentStore(), centralRegistry);
- }
-
- @Override
- public IdentifiableStore> createExecutionsStore(CentralRegistry centralRegistry, DatasetRegistry datasetRegistry, String pathName) {
- return EXECUTIONS.identifiable(new NonPersistentStore(), centralRegistry, datasetRegistry);
- }
-
- @Override
- public IdentifiableStore createFormConfigStore(CentralRegistry centralRegistry, DatasetRegistry datasetRegistry, String pathName) {
- return FORM_CONFIG.identifiable(new NonPersistentStore(), centralRegistry, datasetRegistry);
- }
-
- @Override
- public IdentifiableStore createUserStore(CentralRegistry centralRegistry, String pathName) {
- return AUTH_USER.identifiable(new NonPersistentStore(), centralRegistry);
- }
-
- @Override
- public IdentifiableStore createRoleStore(CentralRegistry centralRegistry, String pathName) {
- return AUTH_ROLE.identifiable(new NonPersistentStore(), centralRegistry);
- }
-
- @Override
- public IdentifiableStore