diff --git a/.github/workflows/test_build_backend_image.yml b/.github/workflows/test_build_backend_image.yml new file mode 100644 index 0000000000..d7991ae1e5 --- /dev/null +++ b/.github/workflows/test_build_backend_image.yml @@ -0,0 +1,45 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +name: Test building backend image + +on: + pull_request: + types: [opened, reopened, synchronize] + branches: + - develop + - master + paths: + - 'backend/**' + - 'executable/**' + - 'Dockerfile' + - 'pom.xml' + - 'lombok.config' + - 'scripts/**' + - '.github/workflows/test_build_backend_image.yml' + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }}-backend + +jobs: + test-build-image: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + with: + # Fetch all tags + fetch-depth: 0 + + - name: Build docker image + uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc + with: + context: . + push: false diff --git a/.github/workflows/test_build_frontend_image.yml b/.github/workflows/test_build_frontend_image.yml new file mode 100644 index 0000000000..53f901f2f5 --- /dev/null +++ b/.github/workflows/test_build_frontend_image.yml @@ -0,0 +1,40 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +name: Test building frontend image + +on: + pull_request: + types: [opened, reopened, synchronize] + branches: + - develop + - master + paths: + - 'frontend/*' + - 'scripts/*' + - '.github/workflows/test_build_frontend_image.yml' +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }}-frontend + +jobs: + test-build-image: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + with: + # Fetch all tags + fetch-depth: 0 + + - name: Build docker image + uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc + with: + context: ./frontend + push: false diff --git a/.restyled.yaml b/.restyled.yaml deleted file mode 100644 index 8c27fc9961..0000000000 --- a/.restyled.yaml +++ /dev/null @@ -1,19 +0,0 @@ -enabled: false -#auto: false -#pull_requests: true -#comments: true -request_review: author -labels: ["code-style"] - -restylers: - # - astyle: - # include: - # - "**/*.java" - # arguments: - # - --style=java - # - --indent=force-tab=4 - # - --lineend=linux - # - --indent-after-parens - # - --break-closing-braces - # - --break-one-line-headers - # - --add-braces \ No newline at end of file diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/FilterTemplate.java b/backend/src/main/java/com/bakdata/conquery/apiv1/FilterTemplate.java index 6a05f227f8..03cda498ba 100644 --- a/backend/src/main/java/com/bakdata/conquery/apiv1/FilterTemplate.java +++ b/backend/src/main/java/com/bakdata/conquery/apiv1/FilterTemplate.java @@ -1,7 +1,6 @@ package com.bakdata.conquery.apiv1; import java.net.URI; -import java.util.List; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; @@ -91,12 +90,12 @@ public boolean isSearchDisabled() { return false; } - public List> getSearches(IndexConfig config, NamespaceStorage storage) { + public TrieSearch createTrieSearch(IndexConfig config, NamespaceStorage storage) { final URI resolvedURI = FileUtil.getResolvedUri(config.getBaseUrl(), getFilePath()); log.trace("Resolved filter template reference url for search '{}': {}", this.getId(), resolvedURI); - FrontendValueIndex search = indexService.getIndex(new FrontendValueIndexKey( + final FrontendValueIndex search = indexService.getIndex(new FrontendValueIndexKey( resolvedURI, columnValue, value, @@ -105,7 +104,7 @@ public List> getSearches(IndexConfig config, Namespace config.getSearchSplitChars() )); - return List.of(search); + return search; } @Override diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/MetaDataPatch.java b/backend/src/main/java/com/bakdata/conquery/apiv1/MetaDataPatch.java index a78b011c8b..b96c367d9c 100644 --- a/backend/src/main/java/com/bakdata/conquery/apiv1/MetaDataPatch.java +++ b/backend/src/main/java/com/bakdata/conquery/apiv1/MetaDataPatch.java @@ -47,13 +47,7 @@ public class MetaDataPatch implements Taggable, Labelable, ShareInformation { * @param Type of the instance that is patched */ public , INST extends Taggable & Shareable & Labelable & Identifiable & Owned & Authorized> void applyTo(INST instance, MetaStorage storage, Subject subject) { - buildChain( - QueryUtils.getNoOpEntryPoint(), - storage, - subject, - instance - ) - .accept(this); + buildChain(QueryUtils.getNoOpEntryPoint(), storage, subject, instance).accept(this); } protected , INST extends Taggable & Shareable & Labelable & Identifiable & Owned & Authorized> Consumer buildChain(Consumer patchConsumerChain, MetaStorage storage, Subject subject, INST instance) { diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/forms/ExternalForm.java b/backend/src/main/java/com/bakdata/conquery/apiv1/forms/ExternalForm.java index 0a8a8e6908..cc5fc0cc8b 100644 --- a/backend/src/main/java/com/bakdata/conquery/apiv1/forms/ExternalForm.java +++ b/backend/src/main/java/com/bakdata/conquery/apiv1/forms/ExternalForm.java @@ -26,9 +26,9 @@ import com.bakdata.conquery.models.identifiable.ids.specific.ManagedExecutionId; import com.bakdata.conquery.models.query.QueryResolveContext; import com.bakdata.conquery.models.query.Visitable; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonValue; import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.BeanProperty; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; @@ -37,13 +37,16 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.deser.ContextualDeserializer; import com.fasterxml.jackson.databind.node.ObjectNode; +import com.fasterxml.jackson.databind.node.TextNode; import com.google.common.base.Strings; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.RequiredArgsConstructor; import lombok.Setter; +import lombok.ToString; import lombok.extern.slf4j.Slf4j; +import org.jetbrains.annotations.Nullable; @Getter @Setter @@ -51,17 +54,27 @@ @JsonDeserialize(using = Deserializer.class) @RequiredArgsConstructor @Slf4j +@ToString public class ExternalForm extends Form implements SubTyped { @JsonValue + @ToString.Exclude private final ObjectNode node; - private final String subType; + public JsonNode getExternalApiPayload() { + return ((ObjectNode) node.deepCopy() + .without("values")) + .set("type", new TextNode(subType)); + + } + + @Nullable @Override - public String getFormType() { - return CPSTypeIdResolver.createSubTyped(this.getClass().getAnnotation(CPSType.class).id(), getSubType()); + @JsonIgnore + public JsonNode getValues() { + return node.get("values"); } @Override @@ -72,41 +85,52 @@ public String getLocalizedTypeLabel() { } // Form had no specific title set. Try localized lookup in FormConfig - Locale preferredLocale = I18n.LOCALE.get(); - FormType frontendConfig = FormScanner.FRONTEND_FORM_CONFIGS.get(this.getFormType()); + final Locale preferredLocale = I18n.LOCALE.get(); + final FormType frontendConfig = FormScanner.FRONTEND_FORM_CONFIGS.get(getFormType()); if (frontendConfig == null) { return getSubType(); } - JsonNode titleObj = frontendConfig.getRawConfig().path("title"); + final JsonNode titleObj = frontendConfig.getRawConfig().path("title"); if (!titleObj.isObject()) { log.trace("Expected \"title\" member to be of type Object in {}", frontendConfig); return getSubType(); } - List localesFound = new ArrayList<>(); + final List localesFound = new ArrayList<>(); titleObj.fieldNames().forEachRemaining((lang) -> localesFound.add(new Locale(lang))); + if (localesFound.isEmpty()) { log.trace("Could not extract a locale from the provided FrontendConfig: {}", frontendConfig); return getSubType(); } + Locale chosenLocale = Locale.lookup(Locale.LanguageRange.parse(preferredLocale.getLanguage()), localesFound); + if (chosenLocale == null) { chosenLocale = localesFound.get(0); log.trace("Locale lookup did not return a matching locale. Using the first title encountered: {}", chosenLocale); } - JsonNode title = titleObj.path(chosenLocale.getLanguage()); + + final JsonNode title = titleObj.path(chosenLocale.getLanguage()); + if (!title.isTextual()) { log.trace("Expected a textual node for the localized title. Was: {}", title.getNodeType()); return getSubType(); } - String ret = title.asText(); + + final String ret = title.asText(); log.trace("Extracted localized title. Was: \"{}\"", ret); return ret.isBlank() ? getSubType() : ret; } + @Override + public String getFormType() { + return CPSTypeIdResolver.createSubTyped(getClass().getAnnotation(CPSType.class).id(), getSubType()); + } + @Override public ManagedExecution toManagedExecution(User user, Dataset submittedDataset, MetaStorage storage) { return new ExternalExecution(this, user, submittedDataset, storage); @@ -142,22 +166,25 @@ public static class Deserializer extends JsonDeserializer implemen private String subTypeId; @Override - public ExternalForm deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { + public ExternalForm deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { if (Strings.isNullOrEmpty(subTypeId)) { throw new IllegalStateException("This class needs subtype information for deserialization."); } - ObjectNode tree = p.readValueAsTree(); + + final ObjectNode tree = p.readValueAsTree(); return new ExternalForm(tree, subTypeId); } @Override public JsonDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException { // This is only called once per typeId@SubTypeId - String subTypeId = (String) ctxt.getAttribute(CPSTypeIdResolver.ATTRIBUTE_SUB_TYPE); + final String subTypeId = (String) ctxt.getAttribute(CPSTypeIdResolver.ATTRIBUTE_SUB_TYPE); + if (Strings.isNullOrEmpty(subTypeId)) { throw new IllegalStateException("This class needs subtype information for deserialization."); } + return new Deserializer(subTypeId); } diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/forms/Form.java b/backend/src/main/java/com/bakdata/conquery/apiv1/forms/Form.java index 451c39d333..11bcd5f3e6 100644 --- a/backend/src/main/java/com/bakdata/conquery/apiv1/forms/Form.java +++ b/backend/src/main/java/com/bakdata/conquery/apiv1/forms/Form.java @@ -15,9 +15,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.google.common.collect.ClassToInstanceMap; import lombok.EqualsAndHashCode; -import lombok.Getter; import lombok.NonNull; -import lombok.Setter; /** * API representation of a form query. @@ -25,15 +23,13 @@ @EqualsAndHashCode public abstract class Form implements QueryDescription { + /** * Raw form config (basically the raw format of this form), that is used by the backend at the moment to * create a {@link com.bakdata.conquery.models.forms.configs.FormConfig} upon start of this form (see {@link ManagedForm#start()}). */ @Nullable - @Getter - @Setter - @EqualsAndHashCode.Exclude - private JsonNode values; + public abstract JsonNode getValues(); @JsonIgnore public String getFormType() { diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/AbsoluteMode.java b/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/AbsoluteMode.java index c71dbd788c..2f58701d2e 100644 --- a/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/AbsoluteMode.java +++ b/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/AbsoluteMode.java @@ -46,12 +46,8 @@ public Query createSpecializedQuery() { List resolutionsAndAlignments = ExportForm.getResolutionAlignmentMap(getForm().getResolvedResolutions(), getAlignmentHint()); - return new AbsoluteFormQuery( - getForm().getPrerequisite(), - dateRange, - resolvedFeatures, - resolutionsAndAlignments - ); + Query prerequisite = getForm().getPrerequisite(); + return new AbsoluteFormQuery(prerequisite, dateRange, resolvedFeatures, resolutionsAndAlignments); } @Override diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/ExportForm.java b/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/ExportForm.java index 381e4bf70d..63f37f96b8 100644 --- a/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/ExportForm.java +++ b/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/ExportForm.java @@ -1,11 +1,13 @@ package com.bakdata.conquery.apiv1.forms.export_form; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.Consumer; import java.util.stream.Collectors; +import javax.annotation.Nullable; import javax.validation.Valid; import javax.validation.ValidationException; import javax.validation.constraints.NotEmpty; @@ -16,6 +18,8 @@ import com.bakdata.conquery.apiv1.forms.Form; import com.bakdata.conquery.apiv1.forms.InternalForm; import com.bakdata.conquery.apiv1.query.CQElement; +import com.bakdata.conquery.apiv1.query.CQYes; +import com.bakdata.conquery.apiv1.query.ConceptQuery; import com.bakdata.conquery.apiv1.query.Query; import com.bakdata.conquery.apiv1.query.QueryDescription; import com.bakdata.conquery.internationalization.ExportFormC10n; @@ -37,20 +41,29 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonManagedReference; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.JsonNode; import com.google.common.collect.ImmutableList; import lombok.AccessLevel; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.Setter; +import lombok.ToString; @Getter @Setter @CPSType(id = "EXPORT_FORM", base = QueryDescription.class) @EqualsAndHashCode(callSuper = true) +@ToString public class ExportForm extends Form implements InternalForm { - @NotNull + @Getter + @Setter + @EqualsAndHashCode.Exclude + private JsonNode values; + + + @Nullable @JsonProperty("queryGroup") private ManagedExecutionId queryGroupId; @@ -97,19 +110,28 @@ public Map createSubQueries() { @Override public Set collectRequiredQueries() { + if (queryGroupId == null) { + return Collections.emptySet(); + } + return Set.of(queryGroupId); } @Override public void resolve(QueryResolveContext context) { - queryGroup = (ManagedQuery) context.getStorage().getExecution(queryGroupId); + if(queryGroupId != null) { + queryGroup = (ManagedQuery) context.getStorage().getExecution(queryGroupId); + prerequisite = queryGroup.getQuery(); + } + else { + prerequisite = new ConceptQuery(new CQYes()); + } // Apply defaults to user concept ExportForm.DefaultSelectSettable.enable(features); timeMode.resolve(context); - prerequisite = queryGroup.getQuery(); List resolutionsFlat = resolution.stream() .flatMap(ResolutionShortNames::correspondingResolutions) diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/FullExportForm.java b/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/FullExportForm.java index 3bfc39a382..f457c1a04f 100644 --- a/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/FullExportForm.java +++ b/backend/src/main/java/com/bakdata/conquery/apiv1/forms/export_form/FullExportForm.java @@ -1,6 +1,7 @@ package com.bakdata.conquery.apiv1.forms.export_form; import java.time.LocalDate; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; @@ -9,12 +10,13 @@ import javax.annotation.Nullable; import javax.validation.Valid; import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; import c10n.C10N; import com.bakdata.conquery.ConqueryConstants; import com.bakdata.conquery.apiv1.forms.Form; import com.bakdata.conquery.apiv1.forms.InternalForm; +import com.bakdata.conquery.apiv1.query.CQYes; +import com.bakdata.conquery.apiv1.query.ConceptQuery; import com.bakdata.conquery.apiv1.query.Query; import com.bakdata.conquery.apiv1.query.QueryDescription; import com.bakdata.conquery.apiv1.query.TableExportQuery; @@ -33,16 +35,27 @@ import com.bakdata.conquery.models.query.Visitable; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.JsonNode; import com.google.common.collect.ImmutableList; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; +import lombok.ToString; @Getter @Setter +@ToString @CPSType(id = "FULL_EXPORT_FORM", base = QueryDescription.class) public class FullExportForm extends Form implements InternalForm { - @NotNull + @Nullable + @Getter + @Setter + @EqualsAndHashCode.Exclude + private JsonNode values; + + + @Nullable @JsonProperty("queryGroup") private ManagedExecutionId queryGroupId; @@ -68,7 +81,16 @@ public Map createSubQueries() { // Forms are sent as an array of standard queries containing AND/OR of CQConcepts, we ignore everything and just convert the CQConcepts into CQUnfiltered for export. - final TableExportQuery exportQuery = new TableExportQuery(queryGroup.getQuery()); + final Query query; + + if (queryGroupId != null) { + query = queryGroup.getQuery(); + } + else { + query = new ConceptQuery(new CQYes()); + } + + final TableExportQuery exportQuery = new TableExportQuery(query); exportQuery.setDateRange(getDateRange()); exportQuery.setTables(tables); @@ -83,12 +105,18 @@ public Map createSubQueries() { @Override public Set collectRequiredQueries() { + if (queryGroupId == null) { + return Collections.emptySet(); + } + return Set.of(queryGroupId); } @Override public void resolve(QueryResolveContext context) { - queryGroup = (ManagedQuery) context.getStorage().getExecution(queryGroupId); + if (queryGroupId != null) { + queryGroup = (ManagedQuery) context.getStorage().getExecution(queryGroupId); + } } @Override diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/frontend/FrontendNode.java b/backend/src/main/java/com/bakdata/conquery/apiv1/frontend/FrontendNode.java index 318e0bc9c0..6eeace5595 100644 --- a/backend/src/main/java/com/bakdata/conquery/apiv1/frontend/FrontendNode.java +++ b/backend/src/main/java/com/bakdata/conquery/apiv1/frontend/FrontendNode.java @@ -32,4 +32,5 @@ public class FrontendNode { private boolean codeListResolvable; private List selects; private long matchingEntities; + private boolean excludeFromTimeAggregation; } diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/query/CQYes.java b/backend/src/main/java/com/bakdata/conquery/apiv1/query/CQYes.java new file mode 100644 index 0000000000..0031abe6bc --- /dev/null +++ b/backend/src/main/java/com/bakdata/conquery/apiv1/query/CQYes.java @@ -0,0 +1,38 @@ +package com.bakdata.conquery.apiv1.query; + +import java.util.Collections; +import java.util.List; + +import com.bakdata.conquery.io.cps.CPSType; +import com.bakdata.conquery.models.query.QueryExecutionContext; +import com.bakdata.conquery.models.query.QueryPlanContext; +import com.bakdata.conquery.models.query.QueryResolveContext; +import com.bakdata.conquery.models.query.RequiredEntities; +import com.bakdata.conquery.models.query.queryplan.ConceptQueryPlan; +import com.bakdata.conquery.models.query.queryplan.QPNode; +import com.bakdata.conquery.models.query.queryplan.specific.Yes; +import com.bakdata.conquery.models.query.resultinfo.ResultInfo; + +@CPSType(id = "YES", base = CQElement.class) +public class CQYes extends CQElement { + + @Override + public void resolve(QueryResolveContext context) { + + } + + @Override + public QPNode createQueryPlan(QueryPlanContext context, ConceptQueryPlan plan) { + return new Yes(context.getDataset().getAllIdsTable()); + } + + @Override + public List getResultInfos() { + return Collections.emptyList(); + } + + @Override + public RequiredEntities collectRequiredEntities(QueryExecutionContext context) { + return new RequiredEntities(context.getBucketManager().getEntities().keySet()); + } +} diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/query/TableExportQuery.java b/backend/src/main/java/com/bakdata/conquery/apiv1/query/TableExportQuery.java index 6fc57971a6..8ab94340d9 100644 --- a/backend/src/main/java/com/bakdata/conquery/apiv1/query/TableExportQuery.java +++ b/backend/src/main/java/com/bakdata/conquery/apiv1/query/TableExportQuery.java @@ -311,7 +311,12 @@ public static String printValue(Concept concept, Object rawValue, PrintSettings return node.getId().toStringWithoutDataset(); } - return node.getName(); + if (node.getDescription() == null) { + return node.getName(); + } + + return node.getName() + " - " + node.getDescription(); + } @Override diff --git a/backend/src/main/java/com/bakdata/conquery/io/external/form/ExternalFormBackendApi.java b/backend/src/main/java/com/bakdata/conquery/io/external/form/ExternalFormBackendApi.java index d62be767e6..42e3fe35bd 100644 --- a/backend/src/main/java/com/bakdata/conquery/io/external/form/ExternalFormBackendApi.java +++ b/backend/src/main/java/com/bakdata/conquery/io/external/form/ExternalFormBackendApi.java @@ -21,6 +21,7 @@ import com.bakdata.conquery.models.datasets.Dataset; import com.codahale.metrics.health.HealthCheck; import com.fasterxml.jackson.databind.node.ObjectNode; +import io.dropwizard.health.check.http.HttpHealthCheck; import lombok.extern.slf4j.Slf4j; @Slf4j @@ -96,7 +97,8 @@ public ExternalTaskState postForm(ExternalForm form, User originalUser, User ser .header(HTTP_HEADER_CQ_AUTHENTICATION, serviceUserToken) .header(HTTP_HEADER_CQ_AUTHENTICATION_ORIGINAL, originalUserToken); - return request.post(Entity.entity(form, MediaType.APPLICATION_JSON_TYPE), ExternalTaskState.class); + ExternalTaskState post = request.post(Entity.entity(form.getExternalApiPayload(), MediaType.APPLICATION_JSON_TYPE), ExternalTaskState.class); + return post; } public ExternalTaskState getFormState(UUID externalId) { @@ -113,14 +115,10 @@ public Response getResult(final URI resultURL) { } - public HealthCheck.Result checkHealth() { - log.trace("Checking health from: {}", getHealthTarget); - try { - getHealthTarget.request(MediaType.APPLICATION_JSON_TYPE).get(Void.class); - return HealthCheck.Result.healthy(); - } - catch (Exception e) { - return HealthCheck.Result.unhealthy(e.getMessage()); - } + public HealthCheck createHealthCheck() { + return new HttpHealthCheck( + getHealthTarget.getUri().toString(), client + ); } + } diff --git a/backend/src/main/java/com/bakdata/conquery/io/external/form/ExternalFormBackendHealthCheck.java b/backend/src/main/java/com/bakdata/conquery/io/external/form/ExternalFormBackendHealthCheck.java deleted file mode 100644 index c0d87ea4cd..0000000000 --- a/backend/src/main/java/com/bakdata/conquery/io/external/form/ExternalFormBackendHealthCheck.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.bakdata.conquery.io.external.form; - -import com.codahale.metrics.health.HealthCheck; -import lombok.RequiredArgsConstructor; - -@RequiredArgsConstructor -public class ExternalFormBackendHealthCheck extends HealthCheck { - - private final ExternalFormBackendApi externalApi; - - @Override - protected Result check() throws Exception { - return externalApi.checkHealth(); - } -} diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/FormBackendConfig.java b/backend/src/main/java/com/bakdata/conquery/models/config/FormBackendConfig.java index da0e4f9ae9..d592a8f691 100644 --- a/backend/src/main/java/com/bakdata/conquery/models/config/FormBackendConfig.java +++ b/backend/src/main/java/com/bakdata/conquery/models/config/FormBackendConfig.java @@ -17,7 +17,6 @@ import com.bakdata.conquery.io.cps.CPSType; import com.bakdata.conquery.io.cps.CPSTypeIdResolver; import com.bakdata.conquery.io.external.form.ExternalFormBackendApi; -import com.bakdata.conquery.io.external.form.ExternalFormBackendHealthCheck; import com.bakdata.conquery.io.external.form.ExternalFormMixin; import com.bakdata.conquery.models.auth.entities.User; import com.bakdata.conquery.models.auth.permissions.Ability; @@ -94,7 +93,9 @@ public void initialize(ManagerNode managerNode) { client.register(new JacksonMessageBodyProvider(om)); // Register health check - managerNode.getEnvironment().healthChecks().register(getId(), new ExternalFormBackendHealthCheck(createApi())); + final ExternalFormBackendApi externalApi = createApi(); + + managerNode.getEnvironment().healthChecks().register(getId(), externalApi.createHealthCheck()); // Register form configuration provider managerNode.getFormScanner().registerFrontendFormConfigProvider(this::registerFormConfigs); @@ -121,11 +122,11 @@ public boolean supportsFormType(String formType) { * @param formConfigs Collection to add received form configs to. */ private void registerFormConfigs(ImmutableCollection.Builder formConfigs) { - Set supportedFormTypes = new HashSet<>(); + final Set supportedFormTypes = new HashSet<>(); for (ObjectNode formConfig : createApi().getFormConfigs()) { final String subType = formConfig.get("type").asText(); - String formType = createSubTypedId(subType); + final String formType = createSubTypedId(subType); // Override type with our subtype formConfig.set("type", new TextNode(formType)); @@ -155,7 +156,7 @@ public User createServiceUser(User originalUser, Dataset dataset) { // the actual user and download permissions. final User serviceUser = - managerNode.getAuthController().flatCopyUser(originalUser, String.format("%s_%s", this.getClass().getSimpleName().toLowerCase(), getId())); + managerNode.getAuthController().flatCopyUser(originalUser, String.format("%s_%s", getClass().getSimpleName().toLowerCase(), getId())); // The user is able to read the dataset, ensure that the service user can download results serviceUser.addPermission(dataset.createPermission(Ability.DOWNLOAD.asSet())); diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/IndexConfig.java b/backend/src/main/java/com/bakdata/conquery/models/config/IndexConfig.java index 9fc7a17102..c027587ff4 100644 --- a/backend/src/main/java/com/bakdata/conquery/models/config/IndexConfig.java +++ b/backend/src/main/java/com/bakdata/conquery/models/config/IndexConfig.java @@ -5,6 +5,7 @@ import javax.annotation.Nullable; import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; import com.bakdata.conquery.models.index.IndexKey; import com.fasterxml.jackson.annotation.JsonIgnore; @@ -30,6 +31,9 @@ public class IndexConfig { @Nullable private String searchSplitChars = "(),;.:\"'/"; + @NotNull + private String emptyLabel = "No Value"; + @JsonIgnore @ValidationMethod(message = "Specified baseUrl is not valid") public boolean isValidUrl() { diff --git a/backend/src/main/java/com/bakdata/conquery/models/datasets/Column.java b/backend/src/main/java/com/bakdata/conquery/models/datasets/Column.java index 1819a3f59c..f7303d091b 100644 --- a/backend/src/main/java/com/bakdata/conquery/models/datasets/Column.java +++ b/backend/src/main/java/com/bakdata/conquery/models/datasets/Column.java @@ -1,6 +1,5 @@ package com.bakdata.conquery.models.datasets; -import java.util.List; import java.util.Map; import javax.annotation.Nullable; @@ -151,7 +150,7 @@ private String computeDefaultDictionaryName(String importName) { @Override - public List> getSearches(IndexConfig config, NamespaceStorage storage) { + public TrieSearch createTrieSearch(IndexConfig config, NamespaceStorage storage) { final int suffixLength = isGenerateSuffixes() ? config.getSearchSuffixLength() : Integer.MAX_VALUE; @@ -168,12 +167,8 @@ public List> getSearches(IndexConfig config, Namespace .onClose(() -> log.debug("DONE processing values for {}", getId())) .forEach(feValue -> search.addItem(feValue, FilterSearch.extractKeywords(feValue))); - return List.of(search); - } - @Override - public List> getSearchReferences() { - return List.of(this); - } + return search; + } } diff --git a/backend/src/main/java/com/bakdata/conquery/models/datasets/concepts/Concept.java b/backend/src/main/java/com/bakdata/conquery/models/datasets/concepts/Concept.java index e18fcd195c..d4c51d7c3e 100644 --- a/backend/src/main/java/com/bakdata/conquery/models/datasets/concepts/Concept.java +++ b/backend/src/main/java/com/bakdata/conquery/models/datasets/concepts/Concept.java @@ -40,7 +40,7 @@ */ @JsonTypeInfo(use = JsonTypeInfo.Id.CUSTOM, property = "type") @CPSBase -@ToString(of = {"connectors"}) +@ToString(of = "connectors") @Getter @Setter @EqualsAndHashCode(callSuper = true) @@ -49,7 +49,9 @@ public abstract class Concept extends ConceptElemen /** * Display Concept for users. */ - private boolean hidden = false; + private boolean hidden; + + private boolean defaultExcludeFromTimeAggregation = false; @JsonManagedReference @Valid @@ -59,10 +61,7 @@ public abstract class Concept extends ConceptElemen private Dataset dataset; public List