All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.utils.QueryState Maven / Gradle / Ivy

There is a newer version: 2.5.0
Show newest version
/*
 * Copyright (C) 2024 Fraunhofer Institut IOSB, Fraunhoferstr. 1, D 76131
 * Karlsruhe, Germany.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see .
 */
package de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.utils;

import static de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.QueryBuilder.ALIAS_PREFIX;

import de.fraunhofer.iosb.ilt.frostserver.model.core.Entity;
import de.fraunhofer.iosb.ilt.frostserver.model.core.EntitySet;
import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.EntitySetJooqCurser;
import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.JooqPersistenceManager;
import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.ResultBuilder;
import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.tables.StaMainTable;
import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.utils.PropertyFieldRegistry.ExpressionFactory;
import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.utils.PropertyFieldRegistry.PropertyFields;
import de.fraunhofer.iosb.ilt.frostserver.property.NavigationProperty;
import de.fraunhofer.iosb.ilt.frostserver.property.NavigationPropertyMain.NavigationPropertyEntity;
import de.fraunhofer.iosb.ilt.frostserver.query.Expand;
import de.fraunhofer.iosb.ilt.frostserver.query.Query;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.jooq.Condition;
import org.jooq.Cursor;
import org.jooq.Field;
import org.jooq.Record;
import org.jooq.Table;
import org.jooq.impl.DSL;

/**
 *
 * @author hylke
 * @param  The type of the main table for the query.
 */
public class QueryState> {

    public static final String ALIAS_ROOT = "_ROOT";

    private final JooqPersistenceManager persistenceManager;
    private Set> selectedProperties;
    private Set sqlSelectFields;
    private final T mainTable;
    private final List sqlMainPkFields;
    private Table sqlFrom;
    private Condition sqlWhere = DSL.noCondition();
    private Condition sqlSkipWhere;
    private Utils.SortSelectFields sqlSortFields;

    private boolean distinctRequired = false;
    private boolean isFilter = false;

    private int aliasNr = 0;
    private QueryState parent;
    private Map childStates = new HashMap<>();
    private String staAlias;

    /**
     * The table reference for the main table of the request.
     */
    private final TableRef tableRef;

    public QueryState(T table, QueryState parent, String staAlias) {
        this(parent.getPersistenceManager(), table, null);
        this.parent = parent;
        this.staAlias = staAlias;
    }

    public QueryState(JooqPersistenceManager pm, T table, Set> sqlSelectFields) {
        this.persistenceManager = pm;
        this.selectedProperties = sqlSelectFields;
        sqlFrom = table;
        mainTable = table;
        sqlMainPkFields = table.getPkFields();
        tableRef = new TableRef(table);
        staAlias = ALIAS_ROOT;
    }

    public JooqPersistenceManager getPersistenceManager() {
        return persistenceManager;
    }

    public T getMainTable() {
        return mainTable;
    }

    public TableRef getTableRef() {
        return tableRef;
    }

    public Entity entityFromRecord(Record tuple, DataSize dataSize, Query staQuery) {
        Entity mainEntity = mainTable.entityFromQuery(tuple, this, dataSize)
                .setQuery(staQuery);

        if (staQuery != null) {
            for (Expand expand : staQuery.getExpand()) {
                NavigationProperty expandPath = expand.getPath();
                if (expandPath instanceof NavigationPropertyEntity navPropEntity) {
                    QueryState childState = getChildState(navPropEntity);
                    Entity subEntity = childState.entityFromRecord(tuple, dataSize, expand.getSubQuery());
                    mainEntity.setProperty(navPropEntity, subEntity);
                }
            }
        }

        return mainEntity;
    }

    public EntitySet createSetFromRecords(Cursor tuples, ResultBuilder resultBuilder) {
        return new EntitySetJooqCurser(mainTable.getEntityType(), tuples, this, resultBuilder);
    }

    public QueryState findStateForAlias(String alias) {
        if (staAlias.equalsIgnoreCase(alias)) {
            return this;
        }
        if (parent == null) {
            return this;
        }
        return parent.findStateForAlias(alias);
    }

    public String getNextAlias() {
        if (parent == null) {
            return ALIAS_PREFIX + (++aliasNr);
        }
        return parent.getNextAlias();
    }

    public void addChildState(NavigationPropertyEntity property, QueryState state) {
        childStates.put(property, state);
    }

    public QueryState getChildState(NavigationPropertyEntity property) {
        return childStates.get(property);
    }

    public boolean isSqlSortFieldsSet() {
        if (sqlSortFields == null) {
            return false;
        }
        return !sqlSortFields.getSqlSortFields().isEmpty();
    }

    public Utils.SortSelectFields getSqlSortFields() {
        if (sqlSortFields == null) {
            sqlSortFields = new Utils.SortSelectFields();
        }
        return sqlSortFields;
    }

    /**
     * @return the selectedProperties
     */
    public Set getSqlSelectFields() {
        if (sqlSelectFields == null) {
            sqlSelectFields = propertiesToFields(mainTable, selectedProperties);
            for (QueryState childState : childStates.values()) {
                sqlSelectFields.addAll(childState.getSqlSelectFields());
            }
        }
        return sqlSelectFields;
    }

    public Set> getSelectedProperties() {
        return selectedProperties;
    }

    /**
     * @param sqlSelectFields the selectedProperties to set
     */
    public void setSelectedProperties(Set> sqlSelectFields) {
        this.selectedProperties = sqlSelectFields;
        this.sqlSelectFields = null;
    }

    /**
     * @return the sqlMainIdField
     */
    public List getSqlMainIdFields() {
        return sqlMainPkFields;
    }

    /**
     * @return the sqlFrom
     */
    public Table getSqlFrom() {
        return sqlFrom;
    }

    /**
     * @param sqlFrom the sqlFrom to set
     */
    public void setSqlFrom(Table sqlFrom) {
        this.sqlFrom = sqlFrom;
    }

    /**
     * Get the SQL Where clause, including skipFilter conditions.
     *
     * @return the sql where clause with skipFilter.
     */
    public Condition getFullSqlWhere() {
        if (sqlSkipWhere == null) {
            return sqlWhere;
        }
        return sqlWhere.and(sqlSkipWhere);
    }

    /**
     * Get the SQL Where clause, excluding skipFilter conditions.
     *
     * @return the sql where clause without skipFilter.
     */
    public Condition getSqlWhere() {
        return sqlWhere;
    }

    /**
     * Set the SQL Where clause, excluding skipFilter conditions.
     *
     * @param sqlWhere the sql where clause without skipFilter.
     */
    public void setSqlWhere(Condition sqlWhere) {
        this.sqlWhere = sqlWhere;
    }

    /**
     * Get the SQL Where clause, for the skipFilter conditions.
     *
     * @return the sql where clause for the skipFilter.
     */
    public Condition getSqlSkipWhere() {
        return sqlSkipWhere == null ? DSL.noCondition() : sqlSkipWhere;
    }

    /**
     * Set the SQL Where clause, for the skipFilter conditions.
     *
     * @param sqlSkipWhere the sql where clause for the skipFilter.
     */
    public void setSqlSkipWhere(Condition sqlSkipWhere) {
        this.sqlSkipWhere = sqlSkipWhere;
    }

    /**
     * @param sqlSortFields the sqlSortFields to set
     */
    public void setSqlSortFields(Utils.SortSelectFields sqlSortFields) {
        this.sqlSortFields = sqlSortFields;
    }

    /**
     * @return the distinctRequired
     */
    public boolean isDistinctRequired() {
        return distinctRequired;
    }

    /**
     * @param distinctRequired the distinctRequired to set
     */
    public void setDistinctRequired(boolean distinctRequired) {
        this.distinctRequired = distinctRequired;
    }

    /**
     * @return Flag indicating the query is a filter query.
     */
    public boolean isFilter() {
        return isFilter;
    }

    /**
     * @param isFilter Flag indicating the query is a filter query.
     */
    public void setFilter(boolean isFilter) {
        this.isFilter = isFilter;
    }

    /**
     * Convert a set of PropertyFields to a set of Fields for the given Table.
     *
     * @param  The table class.
     * @param table The table to generate the Fields for.
     * @param properties The properties to generate the Fields for.
     * @return a set of Fields.
     */
    public static > Set propertiesToFields(StaMainTable table, Set> properties) {
        Set fields = new HashSet<>();
        for (PropertyFields sp : properties) {
            for (ExpressionFactory f : sp.fields.values()) {
                fields.add(f.get(table));
            }
        }
        return fields;
    }

}