001: package auction.model;
002:
003: import java.io.Serializable;
004: import java.util.*;
005:
006: /**
007: * The CaveatEmptor Category can have child categories and each has items.
008: * <p>
009: * Categories can be nested, this is expressed as a bidirectional one-to-many
010: * relationship that references parent and child categories.
011: * <p>
012: * Each Category can have many items (and an item can be in many categories). This
013: * is a many-to-many relationship. There are four strategies how you can map it.
014: * <p>
015: * First, the collection <tt>items</tt> is a true many-to-many association, with
016: * collections on both sides. There are no additional columns in the underlying
017: * many-to-many join table.
018: * <p>
019: * Second, the collection <tt>categorizedItems</tt> is a one-to-many association
020: * to an entity class <tt>CategorizedItem</tt> that represents the link. The
021: * <tt>Item</tt> class has the same collection mapped, to make it bidirectional.
022: * This intermediate class represents additional columns on the many-to-many
023: * join table, such as the user who added the item to the category, and the date
024: * of the addition.
025: * <p>
026: * Third, the collection <tt>categorizedItemComponents</tt> is a collection of
027: * value typed elements, of value type <tt>CategorizedItemComponent</tt>. This
028: * simplifies management of the link (no intermediate entity class) but allows
029: * only unidirectional navigation. The <tt>Item</tt> class does not know anything
030: * about this collection or the components - no shared references.
031: * <p>
032: * Finally, the map <tt>itemsAndUser</tt> represents the many-to-many association
033: * with a ternary relationship using a hash map. This map has item objects as keys,
034: * and user objects as values. The underlying many-to-many join table has three
035: * columns, <tt>CATEGORY_ID</tt>, <tt>ITEM_ID</tt>, and <tt>ADDED_BY_USER_ID</tt>.
036: * This strategy allows you to map an additional column (the user foreign key) of
037: * a many-to-many join table without writing an intermediate entity or component
038: * class.
039: *
040: * @see Item
041: * @see CategorizedItem
042: * @see CategorizedItemComponent
043: * @author Christian Bauer
044: */
045: public class Category implements Serializable, Comparable {
046:
047: private Long id = null;
048: private int version = 0;
049:
050: private String name;
051: private List<Category> childCategories = new ArrayList<Category>(); // A bag with SQL ORDER BY
052: private Category parentCategory;
053:
054: private List<Book> books = new ArrayList<Book>();
055:
056: private Date created = new Date();
057:
058: /**
059: * No-arg constructor for JavaBean tools
060: */
061: public Category() {
062: }
063:
064: /**
065: * Full constructor
066: */
067: public Category(String name, List<Category> childCategories,
068: Category parentCategory, List<Book> books) {
069: this .name = name;
070: this .childCategories = childCategories;
071: this .parentCategory = parentCategory;
072: this .books = books;
073: }
074:
075: /**
076: * Simple constructors
077: */
078: public Category(String name) {
079: this .name = name;
080: }
081:
082: public Category(String name, Category parentCategory) {
083: this .name = name;
084: this .parentCategory = parentCategory;
085: }
086:
087: // ********************** Accessor Methods ********************** //
088:
089: public Long getId() {
090: return id;
091: }
092:
093: public void setId(long id) {
094: this .id = id;
095: }
096:
097: public int getVersion() {
098: return version;
099: }
100:
101: public String getName() {
102: return name;
103: }
104:
105: public void setName(String name) {
106: this .name = name;
107: }
108:
109: public List getChildCategories() {
110: return childCategories;
111: }
112:
113: public void addChildCategory(Category childCategory) {
114: if (childCategory == null)
115: throw new IllegalArgumentException("Null child category!");
116: if (childCategory.getParentCategory() != null)
117: childCategory.getParentCategory().getChildCategories()
118: .remove(childCategory);
119: childCategory.setParentCategory(this );
120: childCategories.add(childCategory);
121: }
122:
123: public void removeChildCategory(Category childCategory) {
124: if (childCategory == null)
125: throw new IllegalArgumentException("Null child category!");
126: childCategory.setParentCategory(null);
127: childCategories.remove(childCategory);
128: }
129:
130: public String getFullName() {
131: String name = getName();
132: Category category = getParentCategory();
133: while (category != null) {
134: name = (category.getName() + " -> " + name);
135: category = category.getParentCategory();
136: }
137: return name;
138: }
139:
140: public Category getParentCategory() {
141: return parentCategory;
142: }
143:
144: private void setParentCategory(Category parentCategory) {
145: this .parentCategory = parentCategory;
146: }
147:
148: // Regular many-to-many
149: public List<Book> getBooks() {
150: return books;
151: }
152:
153: public void addBook(Book book) {
154: if (book == null)
155: throw new IllegalArgumentException("Null book");
156: books.add(book);
157: book.getCategories().add(this );
158: }
159:
160: public void removeBook(Book book) {
161: if (book == null)
162: throw new IllegalArgumentException("Null book");
163: books.remove(book);
164: book.getCategories().remove(this );
165: }
166:
167: public Date getCreated() {
168: return created;
169: }
170:
171: // ********************** Common Methods ********************** //
172:
173: public boolean equals(Object o) {
174: if (this == o)
175: return true;
176: if (o == null || getClass() != o.getClass())
177: return false;
178:
179: final Category category = (Category) o;
180:
181: if (!created.equals(category.created))
182: return false;
183: if (!name.equals(category.name))
184: return false;
185: return !(parentCategory != null ? !parentCategory
186: .equals(category.parentCategory)
187: : category.parentCategory != null);
188:
189: }
190:
191: public int hashCode() {
192: int result;
193: result = name.hashCode();
194: result = 29
195: * result
196: + (parentCategory != null ? parentCategory.hashCode()
197: : 0);
198: result = 29 * result + created.hashCode();
199: return result;
200: }
201:
202: public int compareTo(Object o) {
203: if (o instanceof Category) {
204: return this .getName().compareTo(((Category) o).getName());
205: }
206: return 0;
207: }
208:
209: public String toString() {
210: return "(" + getId() + ") Name: '" + getName();
211: }
212:
213: // ********************** Business Methods ********************** //
214:
215: }
|