/*
 * 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 java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.persistence.FlushModeType;
import javax.persistence.LockModeType;
import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;
import javax.persistence.Parameter;
import javax.persistence.ParameterMode;
import javax.persistence.StoredProcedureQuery;
import javax.persistence.TemporalType;

import org.apache.openjpa.kernel.DelegatingResultList;
import org.apache.openjpa.kernel.QueryResultCallback;
import org.apache.openjpa.lib.rop.ResultList;
import org.apache.openjpa.lib.rop.ResultObjectProvider;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.meta.MultiQueryMetaData;
import org.apache.openjpa.util.RuntimeExceptionTranslator;
import org.apache.openjpa.util.UserException;

/**
 * Implements Store Procedure based query for JPA facade.
 * <br>
 * A {@link StoredProcedureQuery stored procedure query} differs from other query types because it may return
 * more than one result set, apart from an optional update count, whereas the traditional query processing in OpenJPA
 * via the abstractions of {@link ResultObjectProvider} and {@link org.apache.openjpa.jdbc.sql.Result}
 * assumed that a query will return its
 * result in a single list.
 * <br>
 * This query resorts to a callback mechanism, where the execution of the query returns not a result, but a
 * {@link QueryResultCallback callback object} that can be used to callback to OpenJPA kernel to get a series of
 * results via the traditional result processing pathway.
 *
 * @author Pinaki Poddar
 * @author Romain Manni-Bucau
 */
// TODO: add lock
public class StoredProcedureQueryImpl implements StoredProcedureQuery {
    private static final Localizer _loc = Localizer.forPackage(QueryImpl.class);

    private final String _name;
    private final QueryImpl<?> _delegate;
    private final MultiQueryMetaData _meta;
    private QueryResultCallback _callback;
    private boolean _declaredParams; // mainly a flag for now (null or not)

    /**
     * Construct a query for executing a Stored Procedure.
     *  @param procedureName name of the database stored procedure.
     * @param meta
     * @param delegate      the delegate which manages bind parameters on behalf of this
     */
    public StoredProcedureQueryImpl(String procedureName, MultiQueryMetaData meta, QueryImpl<?> delegate) {
        _name = procedureName;
        if (!isValidProcedureName(procedureName)) {
            throw new RuntimeException(procedureName + " is not a valid procedure name");
        }
        _meta = meta;
        _delegate = delegate;
        _delegate.compile();
    }

    /**
     * Gets the facade delegate that manages bind parameters on behalf of this receiver.
     *
     * @return
     */
    public OpenJPAQuery<?> getDelegate() {
        return _delegate;
    }

    /**
     * Gets the kernel delegate that is handles actual execution on behalf of this receiver.
     *
     * @return
     */
    public org.apache.openjpa.kernel.Query getExecutableQuery() {
        return _delegate.getDelegate();
    }

    private void buildParametersIfNeeded() {
        if (!_declaredParams) {
            for (MultiQueryMetaData.Parameter entry : _meta.getParameters()) {
                final Object key;
                final Parameter<?> param;
                if (entry.getName() == null) {
                    key = entry.getPosition();
                    param = new ParameterImpl(entry.getPosition(), entry.getType());
                } else {
                    key = entry.getName();
                    param = new ParameterImpl(entry.getName(), entry.getType());
                }
                _delegate.declareParameter(key, param);
            }
            _declaredParams = true;
        }
    }

    /**
     * Executes this receiver by delegation to the underlying executable query.
     * <br>
     * This method is multi-call safe. The underlying executable query is executed
     * <em>only</em> for the first invocation. Subsequent
     */
    @Override
    public boolean execute() {
        if (_callback == null) {
            _callback = (QueryResultCallback) getExecutableQuery().execute(_delegate.getParameterValues());
        }
        return _callback.getExecutionResult();
    }

    @Override
    public List getResultList() {
        execute();
        try {
            Object list = _callback.callback();
            RuntimeExceptionTranslator trans = PersistenceExceptions
                    .getRollbackTranslator(_delegate.getEntityManager());
            return new DelegatingResultList((ResultList) list, trans);
        } catch (Exception ex) {
            throw new javax.persistence.PersistenceException(ex);
        }
    }

    @Override
    public Object getSingleResult() {
        execute();
        try {
            ResultList result = (ResultList) _callback.callback();
            if (result == null || result.isEmpty())
                throw new NoResultException(_loc.get("no-result", _name)
                        .getMessage());
            if (result.size() > 1)
                throw new NonUniqueResultException(_loc.get("non-unique-result",
                        _name, result.size()).getMessage());
            RuntimeExceptionTranslator trans = PersistenceExceptions
                    .getRollbackTranslator(_delegate.getEntityManager());
            return new DelegatingResultList(result, trans).iterator().next();
        } catch (Exception ex) {
            throw new javax.persistence.PersistenceException(ex);
        }
    }

    @Override
    public boolean hasMoreResults() {
        return _callback != null && _callback.hasMoreResults();
    }

    @Override
    public int getUpdateCount() {
        assertExecuted();
        return _callback.getUpdateCount();
    }

    @Override
    public int executeUpdate() {
        execute();
        return _callback.getUpdateCount();
    }

    @Override
    public <T> Parameter<T> getParameter(String name, Class<T> type) {
        // TODO JPA 2.1 Method
        return _delegate.getParameter(name, type);
    }

    @Override
    public <T> Parameter<T> getParameter(int position, Class<T> type) {
        // TODO JPA 2.1 Method
        return _delegate.getParameter(position, type);
    }

    @Override
    public boolean isBound(Parameter<?> param) {
        // TODO JPA 2.1 Method
        return _delegate.isBound(param);
    }

    @Override
    public <T> T getParameterValue(Parameter<T> param) {
        // TODO JPA 2.1 Method
        return _delegate.getParameterValue(param);
    }

    @Override
    public <T> T unwrap(Class<T> cls) {
        // TODO JPA 2.1 Method
        return _delegate.unwrap(cls);
    }

    @Override
    public <T> StoredProcedureQuery setParameter(Parameter<T> param, T value) {
        buildParametersIfNeeded();
        _delegate.setParameter(param, value);
        return this;
    }

    @Override
    public StoredProcedureQuery setParameter(Parameter<Calendar> param, Calendar cal, TemporalType temporalType) {
        buildParametersIfNeeded();
        _delegate.setParameter(param, cal, temporalType);
        return this;
    }

    @Override
    public StoredProcedureQuery setParameter(Parameter<Date> param, Date value, TemporalType temporalType) {
        buildParametersIfNeeded();
        _delegate.setParameter(param, value, temporalType);
        return this;
    }

    @Override
    public StoredProcedureQuery registerStoredProcedureParameter(int position, Class type, ParameterMode mode) {
        buildParametersIfNeeded();
        ParameterImpl param = new ParameterImpl(position, type);
        _delegate.declareParameter(position, param);
        return this;
    }

    @Override
    public StoredProcedureQuery registerStoredProcedureParameter(String name, Class type, ParameterMode mode) {
        buildParametersIfNeeded();
        ParameterImpl param = new ParameterImpl(name, type);
        _delegate.declareParameter(name, param);
        return this;
    }

    @Override
    public Object getOutputParameterValue(int position) {
        return _callback == null ? null : _callback.getOut(position);
    }

    @Override
    public Object getOutputParameterValue(String parameterName) {
        return _callback == null ? null : _callback.getOut(parameterName);
    }

    @Override
    public javax.persistence.Query setMaxResults(int maxResult) {
        // TODO JPA 2.1 Method
        return _delegate.setMaxResults(maxResult);
    }

    @Override
    public int getMaxResults() {
        // TODO JPA 2.1 Method
        return _delegate.getMaxResults();
    }

    @Override
    public javax.persistence.Query setFirstResult(int startPosition) {
        // TODO JPA 2.1 Method
        return _delegate.setFirstResult(startPosition);
    }

    @Override
    public int getFirstResult() {
        // TODO JPA 2.1 Method
        return _delegate.getFirstResult();
    }

    @Override
    public Map<String, Object> getHints() {
        // TODO JPA 2.1 Method
        return _delegate.getHints();
    }

    @Override
    public Set<Parameter<?>> getParameters() {
        buildParametersIfNeeded();
        return _delegate.getParameters();
    }

    @Override
    public Parameter<?> getParameter(String name) {
        buildParametersIfNeeded();
        return _delegate.getParameter(name);
    }

    @Override
    public Parameter<?> getParameter(int position) {
        buildParametersIfNeeded();
        return _delegate.getParameter(position);
    }

    @Override
    public Object getParameterValue(String name) {
        buildParametersIfNeeded();
        return _delegate.getParameterValue(name);
    }

    @Override
    public Object getParameterValue(int position) {
        buildParametersIfNeeded();
        return _delegate.getParameter(position);
    }

    @Override
    public FlushModeType getFlushMode() {
        // TODO JPA 2.1 Method
        return _delegate.getFlushMode();
    }

    @Override
    public javax.persistence.Query setLockMode(LockModeType lockMode) {
        // TODO JPA 2.1 Method
        return _delegate.setLockMode(lockMode);
    }

    @Override
    public LockModeType getLockMode() {
        // TODO JPA 2.1 Method
        return _delegate.getLockMode();
    }

    @Override
    public StoredProcedureQuery setHint(String hintName, Object value) {
        _delegate.setHint(hintName, value);
        return this;
    }

    @Override
    public StoredProcedureQuery setParameter(String name, Object value) {
        buildParametersIfNeeded();
        _delegate.setParameter(name, value);
        return this;
    }

    @Override
    public StoredProcedureQuery setParameter(String name, Calendar cal, TemporalType temporalType) {
        buildParametersIfNeeded();
        _delegate.setParameter(name, cal, temporalType);
        return this;
    }

    @Override
    public StoredProcedureQuery setParameter(String name, Date date, TemporalType temporalType) {
        buildParametersIfNeeded();
        _delegate.setParameter(name, date, temporalType);
        return this;
    }

    @Override
    public StoredProcedureQuery setParameter(int position, Object value) {
        buildParametersIfNeeded();
        _delegate.setParameter(position, value);
        return this;
    }

    @Override
    public StoredProcedureQuery setParameter(int position, Calendar value, TemporalType temporalType) {
        buildParametersIfNeeded();
        _delegate.setParameter(position, value, temporalType);
        return this;
    }

    @Override
    public StoredProcedureQuery setParameter(int position, Date value, TemporalType temporalType) {
        buildParametersIfNeeded();
        _delegate.setParameter(position, value, temporalType);
        return this;
    }

    @Override
    public StoredProcedureQuery setFlushMode(FlushModeType flushMode) {
        // TODO JPA 2.1 Method
        _delegate.setFlushMode(flushMode);
        return this;
    }

    /**
     * Asserts that user has executed this query.
     */
    void assertExecuted() {
        if (_callback == null) {
            throw new UserException(this + " has not been executed");
        }
    }

    boolean isValidProcedureName(String s) {
        if (s == null || s.trim().length() == 0) {
            return false;
        }
        for (int i = 0; i < s.length(); i++) {
            char ch = s.charAt(i);
            if (ch == '#' || ch == '$' || Character.isJavaIdentifierPart(ch))
                continue;
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return _name;
    }
}
