/*  PAT: Persistent Applications Toolkit (patsystem.sf.net)
 *  Copyright (C) 2004, 2005  Tomasz Nazar, nthx at irc dot pl
 *
 *  This library 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 2 of the License, or (at your option) any later version.
 *
 *  This library 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 library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *  Full version of the license is /docs/LICENSE.txt
 */
package org.nthx.pat;

import org.apache.log4j.Logger;


/** Helper class for converting from real objects to fake ones ({@link ObjectForStream
 *  ObjectForStream}) and vice versa.
 *
 *  @version $Id: CommandGenerationHelper.java 3725 2005-06-09 23:57:03Z nthx $
 *  @author nthx@users.sourceforge.net
 */
public class CommandGenerationHelper
{
    private static Logger log = Logger.getLogger("pat");

    public static ObjectForStream[] targetAndBos2FakeOIDs(Object target,
                                                          Object[] bos)
    {
        if (null == bos) bos = new Object[]{};
        
        ObjectForStream[] objectsForStream = new ObjectForStream[bos.length + 1];

        //log("Translating[target]: " + target + " Class: " + target.getClass().getName());
        //if (null == target) log.error("Target is 'null' - static method");
        if (target instanceof Identifiable)
            writeBo2StreamTable(target, objectsForStream, 0);
        else
            writeObject2StreamTable(target, objectsForStream, 0);

        for (int i = 0; i < bos.length; i++)
        {
            Object bo = bos[i];
            //log("Translating[bo]: " + bo + " Class: " + bo.getClass().getName());
            if (bo instanceof Identifiable)
                writeBo2StreamTable(bo, objectsForStream, i + 1);
            else
                writeObject2StreamTable(bo, objectsForStream, i + 1);
        }
        return objectsForStream;
    }

    private static void writeObject2StreamTable(Object bo, ObjectForStream[] objectsForStream, int index)
    {
        objectsForStream[index] = new ObjectForStream();
        objectsForStream[index].objectOrOID = bo;
        objectsForStream[index].isBo = false;
    }

    private static void writeBo2StreamTable(Object object, ObjectForStream[] objectsForStream, int index)
    {
        objectsForStream[index] = new ObjectForStream();
        objectsForStream[index].objectOrOID = ((Identifiable)object).getOID();
        objectsForStream[index].isBo = true;
    }

    public static Object[] fakeBOs2targetAndBos(IdentityMap system,
                                                ObjectForStream[] targetAndBosFromStream,
                                                String where,
                                                Class[] parameterTypes)
    {
        Object[] result = new Object[targetAndBosFromStream.length];

        for (int i = 0; i < targetAndBosFromStream.length; i++)
        {
            ObjectForStream objectFromStream = targetAndBosFromStream[i];
            if (objectFromStream.isBo)
            {
                result[i] = system.getObject((Long)objectFromStream.objectOrOID);
                if (null == result[i])
                    throw new IllegalStateException(
                                    where + " -> "
                                    + parameterTypes[i-1]
                                    + " ("+i+") should exist: "
                                    + objectFromStream.objectOrOID
                                    + "\nIt indicates lack of @@pat.transaction on"
                                    + " some transacted method."
                    );
            }
            else
                result[i] = objectFromStream.objectOrOID;
        }
        return result;
    }


    public static void assertNotNullAnyOfParams(Object target, String command, Object[] params)
    {
        if (null == target) throw new IllegalStateException("Target for GenericCommand is NULL");
        if (null == command) throw new IllegalStateException("Command for GenericCommand is NULL");
        if (null == params) throw new IllegalStateException("Params for GenericCommand are NULL");

        for (int i = 0; i < params.length; i++)
        {
            Object param = params[i];
            if (null == param)
            {
                log.error("Params' param(" + i + ") "
                    + "for GenericCommand  is null."
                    + "\nMethod is: " + command
                    + "\nTarget is: " + target);
                log.debug("You've probably found a bug in PAT"
                        + "..plz provide logs to nthx@users.sourceforge.net");
                System.exit(1);
            }
        }
    }


    private static void log(String msg){
        log.debug(msg);
    }

    public static void showParamsForStream(ObjectForStream[] targetAndArgsForStream)
    {
        StringBuffer sb = new StringBuffer();
        sb.append("CGH: Wrote params:");
        for (int i = 0; i < targetAndArgsForStream.length; i++)
        {
            ObjectForStream param = targetAndArgsForStream[i];
            sb.append("\nParam[" + i + "]->");
            sb.append(" " + param.objectOrOID);
            sb.append(", " + param.isBo + "], ");
            if (null != param.objectOrOID)
            {
                sb.append("class: " + param.objectOrOID.getClass().getName());
            }
        }
        log.debug(sb.toString());
    }
}