/*
 * Copyright (c) 2004 Your Corporation. All Rights Reserved.
 */
package org.skife.gear.service.ojb;

import org.apache.ojb.broker.Identity;
import org.apache.ojb.broker.PersistenceBroker;
import org.apache.ojb.broker.query.Criteria;
import org.apache.ojb.broker.query.QueryFactory;
import org.skife.gear.ServiceException;
import org.skife.gear.Student;
import org.skife.gear.service.StudentDAO;
import org.skife.gear.service.Tx;
import org.skife.gear.service.TxRunner;

import java.util.Collection;
import java.util.Collections;
import java.util.List;

public class StudentDAOImpl implements StudentDAO
{
    private final TxRunner runner;

    public StudentDAOImpl(final TxRunner runner)
    {
        this.runner = runner;
    }

    public void insert(final Student student) throws ServiceException
    {
        try
        {
            runner.execute(new Tx()
            {
                public Object execute(final PersistenceBroker broker)
                {
                    broker.store(student);
                    return null;
                }
            });
        }
        catch (Exception e)
        {
            throw new ServiceException("Unable To Register Student", e);
        }
    }

    public Student findStudentById(final Integer id) throws ServiceException
    {
        try
        {
            return (Student) runner.execute(new Tx()
            {
                public Object execute(PersistenceBroker broker)
                {
                    final Identity identity = new Identity(Student.class,
                                                           Student.class,
                                                           new Object[]{id});
                    return broker.getObjectByIdentity(identity);
                }
            });
        }
        catch (Exception e)
        {
            throw new ServiceException("Unable to find student", e);
        }
    }

    public Student findStudentById(String id) throws ServiceException
    {
        return this.findStudentById(new Integer(id));
    }

    public List getAllStudents() throws ServiceException
    {
        try
        {
            return (List) runner.execute(new Tx()
            {
                public Object execute(PersistenceBroker broker)
                {
                    return broker.getCollectionByQuery(QueryFactory.newQuery(Student.class, (Criteria) null));
                }
            });
        }
        catch (Exception e)
        {
            throw new ServiceException("Unable to retrieve students", e);
        }
    }

    public void update(final Student s) throws ServiceException
    {
        try
        {
            final Tx tx = new Tx()
            {
                public Object execute(PersistenceBroker broker)
                {
                    broker.store(s);
                    return null;
                }
            };
            runner.execute(tx);
        }
        catch (Exception e)
        {
            throw new ServiceException("Unable to save student", e);
        }
    }

    public List findStudentsWithIdsIn(final Collection ids) throws ServiceException
    {
        if (ids.size() == 0) return Collections.EMPTY_LIST;
        try
        {
            return (List) runner.execute(new Tx()
            {
                public Object execute(PersistenceBroker broker)
                {
                    final Criteria criteria = new Criteria();
                    criteria.addIn("id", ids);
                    return broker.getCollectionByQuery(QueryFactory.newQuery(Student.class, criteria));
                }
            });
        }
        catch (Exception e)
        {
            throw new ServiceException("Unable to retrieve students", e);
        }
    }

    public void delete(final Student student) throws ServiceException
    {
        if (student.getEquipment().size() > 0)
        {
            throw new ServiceException("Unable to delete student with checked out equipment!");
        }
        try
        {
            runner.execute(new Tx()
            {
                public Object execute(final PersistenceBroker broker)
                {
                    broker.delete(student);
                    return null;
                }
            });
        }
        catch (Exception e)
        {
            throw new ServiceException("Unable to delete student", e);
        }
    }
}
