/*
 * Copyright 2006-2007 Queplix Corp.
 *
 * Licensed under the Queplix Public License, Version 1.1.1 (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.queplix.com/solutions/commercial-open-source/queplix-public-license/
 *
 * 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 com.queplix.core.modules.jeo.ejb;

import com.queplix.core.error.GenericSystemException;
import com.queplix.core.integrator.security.LogonSession;
import com.queplix.core.jxb.entity.Entity;
import com.queplix.core.modules.eql.EQLERes;
import com.queplix.core.modules.eql.EQLReqMetaData;
import com.queplix.core.modules.eql.EQLRes;
import com.queplix.core.modules.eql.EQLResRecord;
import com.queplix.core.modules.eql.ejb.AbstractEQLSupportedEJB;
import com.queplix.core.modules.eql.ejb.EQLManagerLocal;
import com.queplix.core.modules.eql.error.EQLException;
import com.queplix.core.modules.eql.parser.EQLIntPreparedStatement;
import com.queplix.core.modules.jeo.JEObjectHandler;

import java.util.ArrayList;
import java.util.List;

/**
 * <p>Java Entity Object Manager session EJB</p>
 * <p>Manages creation of Entity Object Handlers</p>
 *
 * @author Baranov Andrey [ALB]
 * @version $Revision: 1.2 $ $Date: 2006/06/04 00:15:09 $
 */

public class JEOManagerEJB
        extends AbstractEQLSupportedEJB {

    // ----------------------------------------------------------------- public methods

    /**
     * Initialize bean
     */
    public void ejbCreate() {
        INFO("JEOManagerEJB create - " + hashCode());
    }

    /**
     * Build JE object on EQL response
     *
     * @param ls           LogonSession object
     * @param eqlRes       EQLERes response
     * @param eqlResRecord EQL response record
     * @param hndClazz     JE object handler class
     * @return JE object handler
     */
    public JEObjectHandler getJEO(LogonSession ls,
                                  EQLERes eqlRes,
                                  EQLResRecord eqlResRecord,
                                  Class hndClazz) {

        JEObjectHandler handler = getObjectHandler(hndClazz);
        handler.init(ls, eqlRes, eqlResRecord);
        return handler;
    }

    /**
     * Create new JE object
     *
     * @param ls       LogonSession object
     * @param hndClazz JE object handler class
     * @return JE object handler
     * @throws EQLException
     */
    public JEObjectHandler create(LogonSession ls, Class hndClazz)
            throws EQLException {

        JEObjectHandler handler = getObjectHandler(hndClazz);

        Entity entity = getEntityViewConfigManager().getEntityViewConfig(
                handler.getEntityName());
        EQLERes eqlRes = getEQLManager().selectNew(ls, entity);

        handler.init(ls, eqlRes, eqlRes.getRecord(0));
        return handler;
    }

    /**
     * Find JE objects
     *
     * @param ls       LogonSession object
     * @param hndClazz JE object handler class
     * @param eqlQuery EQL query
     * @return collection of JE objects or null
     * @throws EQLException
     */
    public List select(LogonSession ls,
                       Class hndClazz,
                       String eqlQuery)
            throws EQLException {

        return select(ls, hndClazz, null, eqlQuery);
    }

    /**
     * Find JE objects
     *
     * @param ls       LogonSession object
     * @param hndClazz JE object handler class
     * @param eqlPs    EQLIntPreparedStatement object
     * @param eqlQuery EQL query
     * @return collection of JE objects or null
     * @throws EQLException
     */
    public List select(LogonSession ls,
                       Class hndClazz,
                       EQLIntPreparedStatement eqlPs,
                       String eqlQuery)
            throws EQLException {

        // Don't load datasets by default!
        return select(ls, hndClazz, eqlPs, eqlQuery, false);
    }

    /**
     * Find JE objects
     *
     * @param ls           LogonSession object
     * @param hndClazz     JE object handler class
     * @param eqlPs        EQLIntPreparedStatement object
     * @param eqlQuery     EQL query
     * @param loadDatasets whether system should load datasets or not
     * @return collection of JE objects or null
     * @throws EQLException
     */
    public List select(LogonSession ls,
                       Class hndClazz,
                       EQLIntPreparedStatement eqlPs,
                       String eqlQuery,
                       boolean loadDatasets)
            throws EQLException {

        List ret = new ArrayList();

        // create eql meta if necessary
        EQLReqMetaData meta = null;

        if(!loadDatasets) {
            // .. add all datasets in lazy loading set
            meta = new EQLReqMetaData();
            meta.setIgnoreAllDatasets(true);
        }

        // do select
        EQLRes eqlRes = getEQLManager().select(ls, eqlQuery, eqlPs, meta);

        // check result
        if(!(eqlRes instanceof EQLERes)) {
            throw new IllegalStateException("Invalid EQL query: " + eqlQuery);
        }

        // create handlers
        int size = eqlRes.size();
        for(int i = 0; i < size; i++) {
            EQLResRecord eqlResRecord = eqlRes.getRecord(i);
            JEObjectHandler handler = getObjectHandler(hndClazz);
            handler.init(ls, (EQLERes) eqlRes, eqlResRecord);
            ret.add(handler);
        }

        return (ret.size() == 0) ? null:ret;
    }

    /**
     * Update JE object
     *
     * @param hnd JEO handler
     * @throws EQLException
     */
    public int commit(JEObjectHandler hnd)
            throws EQLException {

        // check is exist
        hnd.checkIsExist();
        EQLManagerLocal eqlMng = getEQLManager();
        eqlMng.update(hnd.getLogonSession(), hnd.getEQLRes(),
                hnd.getEqlResRecord());
        return eqlMng.getAffectedRowsCounter();
    }

    // ----------------------------------------------------------------- private methods

    /**
     * Get object handler
     *
     * @param hndClazz handler class
     * @return handler
     */
    private JEObjectHandler getObjectHandler(Class hndClazz) {
        try {
            return (JEObjectHandler) hndClazz.newInstance();
        } catch (IllegalAccessException ex) {
            throw new GenericSystemException(ex);
        } catch (InstantiationException ex) {
            throw new GenericSystemException(ex);
        }
    }
}
