package br.unicamp.ic.lsd.mercurius.persistence.entities;

import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;

import org.hibernate.search.annotations.Analyze;
import org.hibernate.search.annotations.Analyzer;
import org.hibernate.search.annotations.Field;
import org.hibernate.search.annotations.Index;
import org.hibernate.search.annotations.Store;

import br.unicamp.ic.lsd.mercurius.datatype.Category;
import br.unicamp.ic.lsd.mercurius.datatype.Product;

import com.google.common.base.Objects;

@Entity(name = "Category")
@Table(name = "category")
public class CategoryImpl implements Category {

	private static final long serialVersionUID = -8661054284413152214L;

	protected CategoryImpl() {
		super();
	}

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column(name = "category_id")
	private Integer id;

	@Field(index = Index.YES, analyze = Analyze.YES, store = Store.NO)
	@Analyzer(definition = "productalyzer")
	@Column(name = "category_name", nullable = false)
	private String name;

	@Field(index = Index.YES, analyze = Analyze.YES, store = Store.NO)
	@Analyzer(definition = "productalyzer")
	@Column(name = "description")
	private String description;

	@ManyToOne(targetEntity = CategoryImpl.class)
	@JoinColumn(name = "parent_id")
	private Category parent;

	@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, targetEntity = CategoryImpl.class)
	private List<Category> children;

	@ManyToMany(cascade = { CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH },
			targetEntity = ProductImpl.class)
	@JoinTable(name = "product_to_category", joinColumns = @JoinColumn(name = "category_id",
			referencedColumnName = "category_id"), inverseJoinColumns = @JoinColumn(name = "product_id",
			referencedColumnName = "product_id"))
	private List<Product> products;

	@Override
	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	@Override
	public String getName() {
		return name;
	}

	@Override
	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String getDescription() {
		return description;
	}

	@Override
	public void setDescription(String description) {
		this.description = description;
	}

	@Override
	public Category getParent() {
		return parent;
	}

	@Override
	public void setParent(Category parent) {
		this.parent = parent;
	}

	@Override
	public List<Category> getChildren() {
		return children;
	}

	public void setChildren(List<Category> children) {
		this.children = children;
	}

	@Override
	public List<Product> getProducts() {
		return products;
	}

	public void setProducts(List<Product> products) {
		this.products = products;
	}

	@Override
	public int hashCode() {
		return Objects.hashCode(id);
	}

	@Override
	public boolean equals(Object obj) {
		if (obj instanceof CategoryImpl) {
			CategoryImpl category = (CategoryImpl) obj;
			return Objects.equal(category.getId(), id);
		}
		return false;
	}

	@Override
	public String toString() {
		StringBuilder builder = new StringBuilder();
		builder.append("CategoryImpl [id=");
		builder.append(id);
		builder.append(", name=");
		builder.append(name);
		builder.append(", description=");
		builder.append(description);
		builder.append(", parent=");
		builder.append(parent);
		builder.append(", children=");
		builder.append(children);
		builder.append(", products=");
		builder.append(products);
		builder.append("]");
		return builder.toString();
	}

}

@@ -605,16 +605,69 @@
 alyzer;%0A
+import org.hibernate.search.annotations.ContainedIn;%0A
 import o
@@ -1856,24 +1856,38 @@
  children;%0A%0A
+%09@ContainedIn%0A
 %09@ManyToMany

index association