package auction.model; import java.io.Serializable; import java.util.*; /** * The CaveatEmptor Category can have child categories and each has items. *

* Categories can be nested, this is expressed as a bidirectional one-to-many * relationship that references parent and child categories. *

* Each Category can have many items (and an item can be in many categories). This * is a many-to-many relationship. There are four strategies how you can map it. *

* First, the collection items is a true many-to-many association, with * collections on both sides. There are no additional columns in the underlying * many-to-many join table. *

* Second, the collection categorizedItems is a one-to-many association * to an entity class CategorizedItem that represents the link. The * Item class has the same collection mapped, to make it bidirectional. * This intermediate class represents additional columns on the many-to-many * join table, such as the user who added the item to the category, and the date * of the addition. *

* Third, the collection categorizedItemComponents is a collection of * value typed elements, of value type CategorizedItemComponent. This * simplifies management of the link (no intermediate entity class) but allows * only unidirectional navigation. The Item class does not know anything * about this collection or the components - no shared references. *

* Finally, the map itemsAndUser represents the many-to-many association * with a ternary relationship using a hash map. This map has item objects as keys, * and user objects as values. The underlying many-to-many join table has three * columns, CATEGORY_ID, ITEM_ID, and ADDED_BY_USER_ID. * This strategy allows you to map an additional column (the user foreign key) of * a many-to-many join table without writing an intermediate entity or component * class. * * @see Item * @see CategorizedItem * @see CategorizedItemComponent * @author Christian Bauer */ public class Category implements Serializable, Comparable { private Long id = null; private int version = 0; private String name; private List childCategories = new ArrayList(); // A bag with SQL ORDER BY private Category parentCategory; private List items = new ArrayList(); private Set categorizedItems = new HashSet(); private Set categorizedItemComponents = new HashSet(); private Map itemsAndUser = new HashMap(); private Date created = new Date(); /** * No-arg constructor for JavaBean tools */ public Category() {} /** * Full constructor */ public Category(String name, List childCategories, Category parentCategory, List items, Set categorizedItems, Set categorizedItemComponents, Map itemsAndUser) { this.name = name; this.childCategories = childCategories; this.parentCategory = parentCategory; this.items = items; this.categorizedItems = categorizedItems; this.categorizedItemComponents = categorizedItemComponents; this.itemsAndUser = itemsAndUser; } /** * Simple constructors */ public Category(String name) { this.name = name; } public Category(String name, Category parentCategory) { this.name = name; this.parentCategory = parentCategory; } // ********************** Accessor Methods ********************** // public Long getId() { return id; } public int getVersion() { return version; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List getChildCategories() { return childCategories; } public void addChildCategory(Category childCategory) { if (childCategory == null) throw new IllegalArgumentException("Null child category!"); if (childCategory.getParentCategory() != null) childCategory.getParentCategory().getChildCategories().remove(childCategory); childCategory.setParentCategory(parentCategory); childCategories.add(childCategory); } public void removeChildCategory(Category childCategory) { if (childCategory == null) throw new IllegalArgumentException("Null child category!"); childCategory.setParentCategory(null); childCategories.remove(childCategory); } public Category getParentCategory() { return parentCategory; } private void setParentCategory(Category parentCategory) { this.parentCategory = parentCategory; } // Regular many-to-many public List getItems() { return items; } public void addItem(Item item) { if (item == null) throw new IllegalArgumentException("Null item!"); items.add(item); item.getCategories().add(this); } public void removeItem(Item item) { if (item == null) throw new IllegalArgumentException("Null item!"); items.remove(item); item.getCategories().remove(this); } // Many-to-many with additional columns on join table, intermediate entity class // To create a link, instantiate a CategorizedItem with the right constructor // To remove a link, use getCategorizedItems().remove() public Set getCategorizedItems() { return categorizedItems; } // Many-to-many with additional columns on join table, intermediate component class public Set getCategorizedItemComponents() { return categorizedItemComponents; } // Many-to-many with additional columns on join table, ternary hash map representation public Map getItemsAndUser() { return itemsAndUser; } public Date getCreated() { return created; } // ********************** Common Methods ********************** // public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; final Category category = (Category) o; if (!created.equals(category.created)) return false; if (!name.equals(category.name)) return false; return !(parentCategory != null ? !parentCategory.equals(category.parentCategory) : category.parentCategory != null); } public int hashCode() { int result; result = name.hashCode(); result = 29 * result + (parentCategory != null ? parentCategory.hashCode() : 0); result = 29 * result + created.hashCode(); return result; } public int compareTo(Object o) { if (o instanceof Category) { return this.getName().compareTo( ((Category)o).getName() ); } return 0; } public String toString() { return "(" + getId() + ") Name: '" + getName(); } // ********************** Business Methods ********************** // }