/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.openjpa.persistence;

import static org.apache.openjpa.kernel.QueryLanguages.LANG_PREPARED_SQL;

import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.locks.ReentrantLock;

import javax.persistence.FlushModeType;
import javax.persistence.LockModeType;
import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;
import javax.persistence.Query;
import javax.persistence.TypedQuery;

import org.apache.openjpa.conf.Compatibility;
import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.kernel.Broker;
import org.apache.openjpa.kernel.DelegatingQuery;
import org.apache.openjpa.kernel.DelegatingResultList;
import org.apache.openjpa.kernel.DistinctResultList;
import org.apache.openjpa.kernel.FetchConfiguration;
import org.apache.openjpa.kernel.PreparedQuery;
import org.apache.openjpa.kernel.PreparedQueryCache;
import org.apache.openjpa.kernel.QueryHints;
import org.apache.openjpa.kernel.QueryLanguages;
import org.apache.openjpa.kernel.QueryOperations;
import org.apache.openjpa.kernel.QueryStatistics;
import org.apache.openjpa.kernel.exps.AggregateListener;
import org.apache.openjpa.kernel.exps.FilterListener;
import org.apache.openjpa.kernel.jpql.JPQLParser;
import org.apache.openjpa.lib.log.Log;
import org.apache.openjpa.lib.rop.ResultList;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.lib.util.OrderedMap;
import org.apache.openjpa.meta.QueryMetaData;
import org.apache.openjpa.persistence.criteria.OpenJPACriteriaBuilder;
import org.apache.openjpa.util.ImplHelper;
import org.apache.openjpa.util.RuntimeExceptionTranslator;
import org.apache.openjpa.util.UserException;


/**
 * Implementation of {@link Query} interface.
 *
 * @author Marc Prud'hommeaux
 * @author Abe White
 */
public class QueryImpl<X> extends AbstractQuery<X> implements Serializable {
    private static final long serialVersionUID = 1L;
    private static final Localizer _loc = Localizer.forPackage(QueryImpl.class);
	private transient FetchPlan _fetch;

	private String _id;
    private transient ReentrantLock _lock = null;
	private HintHandler _hintHandler;
    private DelegatingQuery _query;
	/**
	 * Constructor; supply factory exception translator and delegate.
	 *
	 * @param em  The EntityManager which created this query
	 * @param ret Exception translator for this query
	 * @param query The underlying "kernel" query.
	 */
    public QueryImpl(EntityManagerImpl em, RuntimeExceptionTranslator ret, org.apache.openjpa.kernel.Query query,
        QueryMetaData qmd) {
        super(qmd, em);
        _query = new DelegatingQuery(query, ret);
        _lock = new ReentrantLock();
        if(query.getLanguage() == QueryLanguages.LANG_SQL) {
            _convertPositionalParams = false;
        }
        else {
            Compatibility compat  = query.getStoreContext().getConfiguration().getCompatibilityInstance();
            _convertPositionalParams = compat.getConvertPositionalParametersToNamed();
        }

    }

	/**
	 * Constructor; supply factory and delegate.
	 *
	 * @deprecated
	 */
    @Deprecated
    public QueryImpl(EntityManagerImpl em, RuntimeExceptionTranslator ret, org.apache.openjpa.kernel.Query query) {
        this(em, ret, query, null);
    }

    /**
     * Constructor; supply factory and delegate.
     *
     * @deprecated
     */
    @Deprecated
    public QueryImpl(EntityManagerImpl em, org.apache.openjpa.kernel.Query query) {
        this(em, null, query, null);
    }

	/**
	 * Delegate.
	 */
	public org.apache.openjpa.kernel.Query getDelegate() {
		return _query.getDelegate();
	}

	@Override
    public OpenJPAEntityManager getEntityManager() {
		return _em;
	}

	@Override
    public String getLanguage() {
		return _query.getLanguage();
	}

	@Override
    public QueryOperationType getOperation() {
        return QueryOperationType.fromKernelConstant(_query.getOperation());
	}

	@Override
    public FetchPlan getFetchPlan() {
		_em.assertNotCloseInvoked();
		_query.assertNotSerialized();
		_query.lock();
		try {
			if (_fetch == null)
                _fetch = ((EntityManagerFactoryImpl) _em
                        .getEntityManagerFactory()).toFetchPlan(_query
                        .getBroker(), _query.getFetchConfiguration());
			return _fetch;
		} finally {
			_query.unlock();
		}
	}

	@Override
    public String getQueryString() {
		String result = _query.getQueryString();
		return result != null ? result : _id;
	}

	@Override
    public boolean getIgnoreChanges() {
		return _query.getIgnoreChanges();
	}

	@Override
    public OpenJPAQuery<X> setIgnoreChanges(boolean ignore) {
		_em.assertNotCloseInvoked();
		_query.setIgnoreChanges(ignore);
		return this;
	}

	@Override
    public OpenJPAQuery<X> addFilterListener(FilterListener listener) {
		_em.assertNotCloseInvoked();
		_query.addFilterListener(listener);
		return this;
	}

	@Override
    public OpenJPAQuery<X> removeFilterListener(FilterListener listener) {
		_em.assertNotCloseInvoked();
		_query.removeFilterListener(listener);
		return this;
	}

	@Override
    public OpenJPAQuery<X> addAggregateListener(AggregateListener listener) {
		_em.assertNotCloseInvoked();
		_query.addAggregateListener(listener);
		return this;
	}

    @Override
    public OpenJPAQuery<X> removeAggregateListener(AggregateListener listener) {
		_em.assertNotCloseInvoked();
		_query.removeAggregateListener(listener);
		return this;
	}

	@Override
    public Collection<?> getCandidateCollection() {
		return _query.getCandidateCollection();
	}

	@Override
    public OpenJPAQuery<X> setCandidateCollection(Collection coll) {
		_em.assertNotCloseInvoked();
		_query.setCandidateCollection(coll);
		return this;
	}

	@Override
    public Class getResultClass() {
		Class res = _query.getResultType();
		if (res != null)
			return res;
		return _query.getCandidateType();
	}

	@Override
    public OpenJPAQuery<X> setResultClass(Class cls) {
		_em.assertNotCloseInvoked();
		if (ImplHelper.isManagedType(_em.getConfiguration(), cls))
			_query.setCandidateType(cls, true);
		else
			_query.setResultType(cls);
		return this;
	}

	@Override
    public boolean hasSubclasses() {
		return _query.hasSubclasses();
	}

	@Override
    public OpenJPAQuery<X> setSubclasses(boolean subs) {
		_em.assertNotCloseInvoked();
		Class<?> cls = _query.getCandidateType();
        _query.setCandidateExtent(_query.getBroker().newExtent(cls, subs));
		return this;
	}

	@Override
    public int getFirstResult() {
		return asInt(_query.getStartRange());
	}

	@Override
    public OpenJPAQuery<X> setFirstResult(int startPosition) {
		_em.assertNotCloseInvoked();
		long end;
		if (_query.getEndRange() == Long.MAX_VALUE)
			end = Long.MAX_VALUE;
		else
			end = startPosition
                    + (_query.getEndRange() - _query.getStartRange());
		_query.setRange(startPosition, end);
		return this;
	}

	@Override
    public int getMaxResults() {
		return asInt(_query.getEndRange() - _query.getStartRange());
	}

	@Override
    public OpenJPAQuery<X> setMaxResults(int max) {
		_em.assertNotCloseInvoked();
		long start = _query.getStartRange();
		if (max == Integer.MAX_VALUE)
			_query.setRange(start, Long.MAX_VALUE);
		else
			_query.setRange(start, start + max);
		return this;
	}

	@Override
    public OpenJPAQuery<X> compile() {
		_em.assertNotCloseInvoked();
		_query.compile();
		return this;
	}

	private Object execute() {
        if (!isNative() && _query.getOperation() != QueryOperations.OP_SELECT)
            throw new InvalidStateException(_loc.get("not-select-query", getQueryString()), null, null, false);
		try {
		    lock();
            Map params = getParameterValues();
            boolean registered = preExecute(params);
            Object result = _query.execute(params);
            if (registered) {
                postExecute(result);
            }
            return result;
		} catch (LockTimeoutException e) {
		    throw new QueryTimeoutException(e.getMessage(), new Throwable[]{e}, this);
		} finally {
		    unlock();
		}
	}

	@Override
    public List getResultList() {
		_em.assertNotCloseInvoked();
		boolean queryFetchPlanUsed = pushQueryFetchPlan();
		try {
		    Object ob = execute();
		    if (ob instanceof List) {
			    List ret = (List) ob;
			    if (ret instanceof ResultList) {
			        RuntimeExceptionTranslator trans = PersistenceExceptions.getRollbackTranslator(_em);
			        if (_query.isDistinct()) {
			            return new DistinctResultList((ResultList) ret, trans);
			        } else {
			            return new DelegatingResultList((ResultList) ret, trans);
			        }
			    } else {
				    return ret;
			    }
		    }
		    return Collections.singletonList(ob);
		} finally {
			popQueryFetchPlan(queryFetchPlanUsed);
		}
	}

	/**
	 * Execute a query that returns a single result.
	 */
	@Override
    public X getSingleResult() {
		_em.assertNotCloseInvoked();
        setHint(QueryHints.HINT_RESULT_COUNT, 1); // for DB2 optimization
		boolean queryFetchPlanUsed = pushQueryFetchPlan();
		try {
		    List result = getResultList();
		    if (result == null || result.isEmpty())
                throw new NoResultException(_loc.get("no-result", getQueryString())
                        .getMessage());
		    if (result.size() > 1)
                throw new NonUniqueResultException(_loc.get("non-unique-result",
                        getQueryString(), result.size()).getMessage());
		    try {
		        return (X)result.get(0);
		    } catch (Exception e) {
                throw new NoResultException(_loc.get("no-result", getQueryString())
                    .getMessage());
		    }
		} finally {
			popQueryFetchPlan(queryFetchPlanUsed);
		}
	}

	private boolean pushQueryFetchPlan() {
		boolean fcPushed = false;
		if (_hintHandler != null) {
			FetchConfiguration fc = _fetch == null ? null : ((FetchPlanImpl)_fetch).getDelegate();
			_em.pushFetchPlan(fc);
			return true;
		}
		if (_fetch != null && _hintHandler != null) {
			switch (_fetch.getReadLockMode()) {
			case PESSIMISTIC_READ:
			case PESSIMISTIC_WRITE:
			case PESSIMISTIC_FORCE_INCREMENT:
				// push query fetch plan to em if pessisimistic lock and any
				// hints are set
				_em.pushFetchPlan(((FetchPlanImpl)_fetch).getDelegate());
				fcPushed = true;
			}
		}
		return fcPushed;
	}

	private void popQueryFetchPlan(boolean queryFetchPlanUsed) {
		if (queryFetchPlanUsed) {
			_em.popFetchPlan();
		}
	}

	@Override
    public int executeUpdate() {
		_em.assertNotCloseInvoked();
        Map<?,?> paramValues = getParameterValues();
		if (_query.getOperation() == QueryOperations.OP_DELETE) {
		   return asInt(paramValues.isEmpty() ? _query.deleteAll() : _query.deleteAll(paramValues));
		}
		if (_query.getOperation() == QueryOperations.OP_UPDATE) {
	       return asInt(paramValues.isEmpty() ? _query.updateAll() : _query.updateAll(paramValues));
		}
        throw new InvalidStateException(_loc.get("not-update-delete-query", getQueryString()), null, null, false);
	}

	/**
	 * Cast the specified long down to an int, first checking for overflow.
	 */
	private static int asInt(long l) {
		if (l > Integer.MAX_VALUE)
			return Integer.MAX_VALUE;
        if (l < Integer.MIN_VALUE) // unlikely, but we might as well check
			return Integer.MIN_VALUE;
		return (int) l;
	}

	@Override
    public FlushModeType getFlushMode() {
		return EntityManagerImpl.fromFlushBeforeQueries(_query
                .getFetchConfiguration().getFlushBeforeQueries());
	}

	@Override
    public OpenJPAQuery<X> setFlushMode(FlushModeType flushMode) {
		_em.assertNotCloseInvoked();
		_query.getFetchConfiguration().setFlushBeforeQueries(
                EntityManagerImpl.toFlushBeforeQueries(flushMode));
		return this;
	}

	/**
	 * Asserts that this query is a JPQL or Criteria Query.
	 */
	void assertJPQLOrCriteriaQuery() {
        String language = getLanguage();
        if (JPQLParser.LANG_JPQL.equals(language)
         || QueryLanguages.LANG_PREPARED_SQL.equals(language)
         || OpenJPACriteriaBuilder.LANG_CRITERIA.equals(language)) {
            return;
        } else {
            throw new IllegalStateException(_loc.get("not-jpql-or-criteria-query").getMessage());
        }
	}

	@Override
    public OpenJPAQuery<X> closeAll() {
		_query.closeAll();
		return this;
	}

	@Override
    public String[] getDataStoreActions(Map params) {
		return _query.getDataStoreActions(params);
	}

    @Override
    public LockModeType getLockMode() {
        assertJPQLOrCriteriaQuery();
        return getFetchPlan().getReadLockMode();
    }

    /**
     * Sets lock mode on the given query.
     * If the target query has been prepared and cached, then ignores the cached version.
     * @see #ignorePreparedQuery()
     */
    @Override
    public TypedQuery<X> setLockMode(LockModeType lockMode) {
        String language = getLanguage();
        if (QueryLanguages.LANG_PREPARED_SQL.equals(language)) {
            ignorePreparedQuery();
        }
        assertJPQLOrCriteriaQuery();
       getFetchPlan().setReadLockMode(lockMode);
       return this;
    }

	@Override
    public int hashCode() {
        return (_query == null) ? 0 : _query.hashCode();
	}

	@Override
    public boolean equals(Object other) {
		if (other == this)
			return true;
        if ((other == null) || (other.getClass() != this.getClass()))
            return false;
        if (_query == null)
            return false;
		return _query.equals(((QueryImpl) other)._query);
	}

	/**
	 * Get all the active hints and their values.
	 *
	 */
    //TODO: JPA 2.0 Hints that are not set to FetchConfiguration
    @Override
    public Map<String, Object> getHints() {
        if (_hintHandler == null)
            return Collections.emptyMap();
        return _hintHandler.getHints();
    }

    @Override
    public OpenJPAQuery<X> setHint(String key, Object value) {
        _em.assertNotCloseInvoked();
        if (_hintHandler == null) {
            _hintHandler = new HintHandler(this);
        }
        _hintHandler.setHint(key, value);
        return this;
    }

    @Override
    public Set<String> getSupportedHints() {
        if (_hintHandler == null) {
            _hintHandler = new HintHandler(this);
        }
        return _hintHandler.getSupportedHints();
    }

    /**
     * Unwraps this receiver to an instance of the given class, if possible.
     *
     * @exception if the given class is null, generic <code>Object.class</code> or a class
     * that is not wrapped by this receiver.
     *
     * @since 2.0.0
     */
    @Override
    public <T> T unwrap(Class<T> cls) {
        Object[] delegates = new Object[]{_query.getInnermostDelegate(), _query.getDelegate(), _query, this};
        for (Object o : delegates) {
            if (cls != null && cls != Object.class && cls.isInstance(o))
                return (T)o;
        }
        // Set this transaction to rollback only (as per spec) here because the raised exception
        // does not go through normal exception translation pathways
        RuntimeException ex = new PersistenceException(_loc.get("unwrap-query-invalid", cls).toString(), null,
                this, false);
        if (_em.isActive())
            _em.setRollbackOnly(ex);
        throw ex;
    }


    // =======================================================================
    // Prepared Query Cache related methods
    // =======================================================================

    /**
     * Invoked before a query is executed.
     * If this receiver is cached as a {@linkplain PreparedQuery prepared query}
     * then re-parameterizes the given user parameters. The given map is cleared
     * and re-parameterized values are filled in.
     *
     * @param params user supplied parameter key-values. Always supply a
     * non-null map even if the user has not specified any parameter, because
     * the same map will to be populated by re-parameterization.
     *
     * @return true if this invocation caused the query being registered in the
     * cache.
     */
    private boolean preExecute(Map params) {

        PreparedQueryCache cache = _em.getPreparedQueryCache();
        if (cache == null) {
            return false;
        }
        FetchConfiguration fetch = _query.getFetchConfiguration();
        if (fetch.getReadLockLevel() != 0) {
            if (cache.get(_id) != null) {
                ignorePreparedQuery();
            }
            return false;
        }

        // Determine if the query has NULL parameters.  If so, then do not use a PreparedQuery from the cache
        for (Object val : params.values()) {
            if (val == null) {
                ignorePreparedQuery();
                return false;
            }
        }

        Boolean registered = cache.register(_id, _query, fetch);
        boolean alreadyCached = (registered == null);
        String lang = _query.getLanguage();
        QueryStatistics<String> stats = cache.getStatistics();
        if (alreadyCached && LANG_PREPARED_SQL.equals(lang)) {
            //This value is expected to be non-null as it was just registered
            PreparedQuery pq = _em.getPreparedQuery(_id);
            if (pq.isInitialized()) {
                try {
                    Map rep = pq.reparametrize(params, _em.getBroker());
                    params.clear();
                    params.putAll(rep);
                } catch (UserException ue) {
                    invalidatePreparedQuery();
                    Log log = _em.getConfiguration().getLog(OpenJPAConfiguration.LOG_RUNTIME);
                    if (log.isWarnEnabled())
                        log.warn(ue.getMessage());
                    return false;
                }
            }
            stats.recordExecution(pq.getOriginalQuery());
        } else {
            stats.recordExecution(getQueryString());
        }
        return registered == Boolean.TRUE;
    }

    /**
     * Initialize the registered Prepared Query from the given opaque object.
     *
     * @param result an opaque object representing execution result of a query
     *
     * @return true if the prepared query can be initialized.
     */
    private boolean postExecute(Object result) {
        PreparedQueryCache cache = _em.getPreparedQueryCache();
        if (cache == null) {
            return false;
        }
        return cache.initialize(_id, result) != null;
    }

    /**
     * Remove this query from PreparedQueryCache.
     */
    boolean invalidatePreparedQuery() {
        PreparedQueryCache cache = _em.getPreparedQueryCache();
        if (cache == null)
            return false;
        ignorePreparedQuery();
        return cache.invalidate(_id);
    }

    /**
     * Ignores this query from PreparedQueryCache by recreating the original
     * query if it has been cached.
     */
    void ignorePreparedQuery() {
        PreparedQuery cached = _em.getPreparedQuery(_id);
        if (cached == null)
            return;
        Broker broker = _em.getBroker();
        // Critical assumption: Only JPQL queries are cached and more
        // importantly, the identifier of the prepared query is the original
        // JPQL String
        String JPQL = JPQLParser.LANG_JPQL;
        String jpql = _id;

        org.apache.openjpa.kernel.Query newQuery = broker.newQuery(JPQL, jpql);
        newQuery.getFetchConfiguration().copy(_query.getFetchConfiguration());
        newQuery.compile();
        _query = new DelegatingQuery(newQuery, _em.getExceptionTranslator());
    }

    // package protected
    QueryImpl setId(String id) {
        _id = id;
        return this;
    }
    // ================ End of Prepared Query related methods =====================

    @Override
    protected void lock() {
        if (_lock != null)
            _lock.lock();
    }

    @Override
    protected void unlock() {
        if (_lock != null)
            _lock.unlock();
    }

    @Override
    protected void assertOpen() {
        _query.assertOpen();
    }

    @Override
    public OrderedMap<Object, Class<?>> getParamTypes() {
        return _query.getOrderedParameterTypes();
    }

    @Override
    public String toString() {
        String result = _query.getQueryString();
        return result != null ? result : _id;
    }
}
