com.qcadoo.model.internal.search.SearchQueryImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.qcadoo.model.internal.search.SearchQueryImpl.java

Source

/**
 * ***************************************************************************
 * Copyright (c) 2010 Qcadoo Limited
 * Project: Qcadoo Framework
 * Version: 1.4
 *
 * This file is part of Qcadoo.
 *
 * Qcadoo is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 * ***************************************************************************
 */
package com.qcadoo.model.internal.search;

import com.qcadoo.model.api.DataDefinition;
import com.qcadoo.model.api.Entity;
import com.qcadoo.model.api.search.SearchQueryBuilder;
import com.qcadoo.model.api.search.SearchResult;
import com.qcadoo.model.internal.api.DataAccessService;
import com.qcadoo.model.internal.api.InternalDataDefinition;
import org.hibernate.Query;
import org.hibernate.classic.Session;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class SearchQueryImpl implements SearchQuery {

    private final Pattern pattern = Pattern.compile("#([a-zA-Z0-9]+)_([a-zA-Z0-9]+)");

    private final Map<String, String> strings = new HashMap<String, String>();

    private final Map<String, Boolean> booleans = new HashMap<String, Boolean>();

    private final Map<String, Byte> bytes = new HashMap<String, Byte>();

    private final Map<String, Short> shorts = new HashMap<String, Short>();

    private final Map<String, Integer> integers = new HashMap<String, Integer>();

    private final Map<String, Long> longs = new HashMap<String, Long>();

    private final Map<String, Float> floats = new HashMap<String, Float>();

    private final Map<String, Double> doubles = new HashMap<String, Double>();

    private final Map<String, BigDecimal> bigDecimals = new HashMap<String, BigDecimal>();

    private final Map<String, Date> dates = new HashMap<String, Date>();

    private final Map<String, Date> times = new HashMap<String, Date>();

    private final Map<String, Date> timestamps = new HashMap<String, Date>();

    private final Map<String, Object> parameters = new HashMap<String, Object>();

    private final Map<String, Collection<? extends Object>> parameterLists = new HashMap<String, Collection<? extends Object>>();

    private final Map<String, Object> entities = new HashMap<String, Object>();

    private final DataAccessService dataAccessService;

    private final InternalDataDefinition sourceDataDefinition;

    private final String queryString;

    private InternalDataDefinition mainDataDefinition = null;

    private int maxResults;

    private int firstResult;

    private boolean cacheable = false;

    public SearchQueryImpl(final InternalDataDefinition dataDefinition, final DataAccessService dataAccessService,
            final String queryString) {
        this.sourceDataDefinition = dataDefinition;
        this.dataAccessService = dataAccessService;
        this.queryString = prepareDataDefinitions(prepareQuery(queryString));
    }

    private String prepareDataDefinitions(final String queryString) {
        boolean hasSelectSection = !queryString.startsWith("from");

        Matcher matcher = pattern.matcher(queryString);

        String newQueryString = queryString;

        while (matcher.find()) {
            InternalDataDefinition dataDefinition = dataAccessService.getDataDefinition(matcher.group(1),
                    matcher.group(2));

            newQueryString = newQueryString.replaceAll(
                    "#" + dataDefinition.getPluginIdentifier() + "_" + dataDefinition.getName(),
                    dataDefinition.getFullyQualifiedClassName());

            if (!hasSelectSection && mainDataDefinition == null) {
                mainDataDefinition = dataDefinition;
            }
        }

        return newQueryString;
    }

    private String prepareQuery(final String queryString) {
        if (!StringUtils.hasText(queryString)) {
            return "from #" + sourceDataDefinition.getPluginIdentifier() + "_" + sourceDataDefinition.getName();
        }
        if (queryString.trim().startsWith("where")) {
            return "from #" + sourceDataDefinition.getPluginIdentifier() + "_" + sourceDataDefinition.getName()
                    + " " + queryString.trim();
        }
        return queryString.trim();
    }

    @Override
    public DataDefinition getDataDefinition() {
        return mainDataDefinition;
    }

    @Override
    public SearchResult list() {
        return dataAccessService.find(this);
    }

    @Override
    public Entity uniqueResult() {
        SearchResult results = list();

        if (results.getEntities().isEmpty()) {
            return null;
        } else if (results.getEntities().size() == 1) {
            return results.getEntities().get(0);
        } else {
            throw new IllegalStateException(
                    "Too many results, expected one, found " + results.getEntities().size());
        }
    }

    public SearchQueryBuilder setCacheable(final boolean cacheable) {
        this.cacheable = cacheable;
        return this;
    }

    @Override
    public void addCacheable(Query query) {
        query.setCacheable(cacheable);
    }

    @Override
    public SearchQueryBuilder setMaxResults(final int maxResults) {
        this.maxResults = maxResults;
        return this;
    }

    @Override
    public SearchQueryBuilder setFirstResult(final int firstResult) {
        this.firstResult = firstResult;
        return this;
    }

    @Override
    public SearchQueryBuilder setString(final String name, final String val) {
        strings.put(name, val);
        return this;
    }

    @Override
    public SearchQueryBuilder setBoolean(final String name, final boolean val) {
        booleans.put(name, val);
        return this;
    }

    @Override
    public SearchQueryBuilder setByte(final String name, final byte val) {
        bytes.put(name, val);
        return this;
    }

    @Override
    public SearchQueryBuilder setShort(final String name, final short val) {
        shorts.put(name, val);
        return this;
    }

    @Override
    public SearchQueryBuilder setInteger(final String name, final int val) {
        integers.put(name, val);
        return this;
    }

    @Override
    public SearchQueryBuilder setLong(final String name, final long val) {
        longs.put(name, val);
        return this;
    }

    @Override
    public SearchQueryBuilder setFloat(final String name, final float val) {
        floats.put(name, val);
        return this;
    }

    @Override
    public SearchQueryBuilder setDouble(final String name, final double val) {
        doubles.put(name, val);
        return this;
    }

    @Override
    public SearchQueryBuilder setBigDecimal(final String name, final BigDecimal number) {
        bigDecimals.put(name, number);
        return this;
    }

    @Override
    public SearchQueryBuilder setDate(final String name, final Date date) {
        dates.put(name, date);
        return this;
    }

    @Override
    public SearchQueryBuilder setTime(final String name, final Date date) {
        times.put(name, date);
        return this;
    }

    @Override
    public SearchQueryBuilder setTimestamp(final String name, final Date date) {
        timestamps.put(name, date);
        return this;
    }

    @Override
    public SearchQueryBuilder setEntity(final String name, final Entity entity) {
        Object databaseEntity = null;

        if (entity != null) {
            databaseEntity = dataAccessService.convertToDatabaseEntity(entity);
        }

        if (databaseEntity == null) {
            parameters.put(name, null);
        } else {
            entities.put(name, databaseEntity);
        }

        return this;
    }

    @Override
    public SearchQueryBuilder setEntity(final String name, final String pluginIdentifier, final String modelName,
            final long entityId) {
        return setEntity(name,
                dataAccessService.get(dataAccessService.getDataDefinition(pluginIdentifier, modelName), entityId));
    }

    @Override
    public SearchQueryBuilder setParameter(final String name, final Object val) {
        parameters.put(name, val);
        return this;
    }

    @Override
    public SearchQueryBuilder setParameterList(final String name, final Collection<? extends Object> values) {
        parameterLists.put(name, values);
        return this;
    }

    @Override
    public Query createQuery(final Session session) {
        return session.createQuery(queryString);
    }

    @Override
    public void addParameters(final Query query) {
        for (Map.Entry<String, String> parameter : strings.entrySet()) {
            query.setString(parameter.getKey(), parameter.getValue());
        }
        for (Map.Entry<String, Boolean> parameter : booleans.entrySet()) {
            query.setBoolean(parameter.getKey(), parameter.getValue());
        }
        for (Map.Entry<String, Byte> parameter : bytes.entrySet()) {
            query.setByte(parameter.getKey(), parameter.getValue());
        }
        for (Map.Entry<String, Short> parameter : shorts.entrySet()) {
            query.setShort(parameter.getKey(), parameter.getValue());
        }
        for (Map.Entry<String, Integer> parameter : integers.entrySet()) {
            query.setInteger(parameter.getKey(), parameter.getValue());
        }
        for (Map.Entry<String, Long> parameter : longs.entrySet()) {
            query.setLong(parameter.getKey(), parameter.getValue());
        }
        for (Map.Entry<String, Float> parameter : floats.entrySet()) {
            query.setFloat(parameter.getKey(), parameter.getValue());
        }
        for (Map.Entry<String, Double> parameter : doubles.entrySet()) {
            query.setDouble(parameter.getKey(), parameter.getValue());
        }
        for (Map.Entry<String, BigDecimal> parameter : bigDecimals.entrySet()) {
            query.setBigDecimal(parameter.getKey(), parameter.getValue());
        }
        for (Map.Entry<String, Date> parameter : dates.entrySet()) {
            query.setDate(parameter.getKey(), parameter.getValue());
        }
        for (Map.Entry<String, Date> parameter : times.entrySet()) {
            query.setTime(parameter.getKey(), parameter.getValue());
        }
        for (Map.Entry<String, Date> parameter : timestamps.entrySet()) {
            query.setTimestamp(parameter.getKey(), parameter.getValue());
        }
        for (Map.Entry<String, Object> parameter : parameters.entrySet()) {
            query.setParameter(parameter.getKey(), parameter.getValue());
        }
        for (Map.Entry<String, Collection<? extends Object>> parametersList : parameterLists.entrySet()) {
            query.setParameterList(parametersList.getKey(), parametersList.getValue());
        }
        for (Map.Entry<String, Object> parameter : entities.entrySet()) {
            query.setEntity(parameter.getKey(), parameter.getValue());
        }
    }

    @Override
    public void addFirstAndMaxResults(final Query query) {
        if (firstResult > 0) {
            query.setFirstResult(firstResult);
        }
        if (maxResults > 0) {
            query.setMaxResults(maxResults);
        }
    }

    @Override
    public boolean hasFirstAndMaxResults() {
        return firstResult > 0 || maxResults > 0;
    }

}