/******************************************************************
  NOTE: Source files best viewed with a tabstop of 4.
 
 Copyright 2000-2006 by BEA Systems Inc.
 
 THE SOURCE CODE HEREIN (THE "CODE") IS SUBJECT TO THE TERMS AND
 CONDITIONS OF THE LICENSE AGREEMENT ACCOMPANYING THE BEA SYSTEMS INC.
 KODO SOFTWARE (THE "LICENSE AGREEMENT"). WITHOUT SUPERSEDING OR
 LIMITING THE APPLICATION OF THE LICENSE AGREEMENT, THE CODE IS
 SUPPLIED "AS IS" WITHOUT WARRANTY OF ANY KIND, AND YOU ACKNOWLEDGE
 THAT (EXCEPT AS OTHERWISE PROHIBITED BY LAW) BEA SYSTEMS INC. SHALL
 HAVE NO LIABILITY WHATSOEVER IN RELATION TO ANY USE OF THE CODE.
 
 LICENSEE MAY NOT REDISTRIBUTE, TRANSFER, SUBLICENSE OR SELL THE CODE OR
 EXPLOIT THE CODE IN ANY OTHER MANNER THAN AS EXPRESSLY ALLOWED IN THE
 LICENSE AGREEMENT. THIS LICENSE DOES NOT ENTITLE LICENSEE TO RECEIVE
 FROM BEA SYSTEMS INC. DOCUMENTATION, TECHNICAL SUPPORT, TELEPHONE
 ASSISTANCE, OR ENHANCEMENTS OR UPDATES TO THE CODE.
 ******************************************************************/
 

package tutorial.persistence;


import java.util.*;
import javax.persistence.*;


@Entity(name="Rabbit")
public class Rabbit
	extends Animal
{
	// the resale price of a rabbit
	public static final float RESALE_PRICE = 3.0f;

	@Basic @Column(name="GENDER")
	private boolean isFemale = false;

	@Basic @Column(name="EXPIRED")
	private boolean isDead = false;

	private Set<Rabbit> children = new HashSet<Rabbit> ();
	private Set<Rabbit> parents = new HashSet<Rabbit> ();

	// some rabbit names; used by breedHelper () to name new rabbits
	private static final String[] maleRabbitNames =
	{
		"Bugs",
		"Peter",
		"Roger",
		"Buttons",
		"John",
		"Ed",
		"Elvis",
	};
	private static final String[] femaleRabbitNames =
	{
		"Babs",
		"Fluffy",
		"Cottontail",
		"Daisie",
		"Poofy",
		"Flower",
		"Britney",
	};


	public Rabbit (String name, boolean isFemale)
	{
		super (name, RESALE_PRICE);
		this.isFemale = isFemale;
	}

	
	public Rabbit (String name, Rabbit mother, Rabbit father, boolean isFemale)
	{
		super (name, RESALE_PRICE);
		parents.add (mother);
		parents.add (father);
		this.isFemale = isFemale;
	}


	/**
	 * 	Return <code>true</code> if this rabbit is female; else 
	 *	<code>false</code>.
	 */
	public boolean isFemale ()
	{
		return isFemale;
	}


	/**
	 *	Designate that this rabbit is dead.
	 */
	public void kill ()
	{
		isDead = true;
	}


	/**
	 *	Adds <code>child</code> to this rabbit's children collection.
	 *	Performs no validation.
	 */
	public void addChild (Rabbit child)
	{
		children.add (child);
	}


	public String toString (boolean detailed)
	{
		StringBuffer buf = new StringBuffer (512);
		buf.append ("Rabbit ").append (getName ());
		buf.append (" (").append ((isFemale) ? "female" : "male").append (")");

		if (detailed)
		{
			buf.append (" sells for ").append (getPrice ());
			buf.append (" dollars.\n\tparents: ").append (parents);
			buf.append ("\n\tchildren: ").append (children);
		}
		else
			buf.append ("; has " + children.size () + " children.");

		return buf.toString ();
	}


	public static void main (String[] args) 
	{
		// create some new rabbits
		try
		{
			if (args.length == 2 && args[0].equals ("breed"))
			{
				int iters = Integer.parseInt (args[1]);
				EntityManagerFactory emf = Persistence.
					createEntityManagerFactory (null);
				EntityManager em = emf.createEntityManager ();
				breed (em, iters);
				em.close ();
				emf.close ();
				return;
			}
		}
		catch (NumberFormatException e)
		{
		}

		// if we get here, something went wrong
		System.out.println ("Usage:");
		System.out.println ("\tjava tutorial.persistence.Rabbit breed "
			+ "'iterations'");
	}


	/**
	 *	Find two random compatible rabbits in the database, toss them
	 *	in a dark room for a little while, and repeat <code>iterations</code> 
	 *	times.
	 */
	public static void breed (EntityManager em, int iterations)
	{
		em.getTransaction ().begin ();
		while (iterations > 0)
		{
			breedHelper (em);
			iterations--;
		}
		em.getTransaction ().commit ();
	}
	

	private static void breedHelper (EntityManager em)
	{
		Random random = new Random ();

		// find a female rabbit
		Query femaleQuery = em.createQuery ("select r from Rabbit r"
			+ " where r.isFemale = true and r.isDead = false");

		List females = femaleQuery.getResultList ();
		if (females.isEmpty ())
			throw new RuntimeException ("No females in db. Please create one.");
		Rabbit female = (Rabbit) females.get (random.nextInt (females.size ()));

		// find a male rabbit
		Query maleQuery = em.createQuery ("select r from Rabbit r"
			+ " where r.isFemale = false and r.isDead = false");
		List males = maleQuery.getResultList ();
		if (males.isEmpty ())
			throw new RuntimeException ("No males in db. Please create one.");
		Rabbit male = (Rabbit) males.get (random.nextInt (males.size ()));

		// breed the two
		for (int count = random.nextInt (3) + 1; count > 0; count--)
		{
			boolean isFemale = random.nextBoolean ();
			String[] names;
			if (isFemale)
				names = femaleRabbitNames;
			else
				names = maleRabbitNames;
			String name = names[random.nextInt (names.length)];
			Rabbit kid = new Rabbit (name, female, male, isFemale);
			female.addChild (kid);
			male.addChild (kid);
			em.persist (kid);
			System.out.println ("New rabbit born: " + kid);
		}
	}
}
