Source code: com/RuntimeCollective/sitemap/bean/ImageCategory.java
1 /* $Header: /home/CVS/rjp/src/com/RuntimeCollective/sitemap/bean/ImageCategory.java,v 1.7 2003/09/30 15:12:59 joe Exp $
2 * $Revision: 1.7 $
3 * $Date: 2003/09/30 15:12:59 $
4 *
5 * ====================================================================
6 *
7 * Josephine : http://www.runtime-collective.com/josephine/index.html
8 *
9 * Copyright (C) 2003 Runtime Collective
10 *
11 * This product includes software developed by the
12 * Apache Software Foundation (http://www.apache.org/).
13 *
14 * This library is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU Lesser General Public
16 * License as published by the Free Software Foundation; either
17 * version 2.1 of the License, or (at your option) any later version.
18 *
19 * This library is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * Lesser General Public License for more details.
23 *
24 * You should have received a copy of the GNU Lesser General Public
25 * License along with this library; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 *
28 */
29
30 package com.RuntimeCollective.sitemap.bean;
31
32 import com.RuntimeCollective.webapps.RuntimeDataSource;
33 import com.RuntimeCollective.webapps.RuntimeParameters;
34 import com.RuntimeCollective.webapps.bean.EntityBean;
35 import com.RuntimeCollective.webapps.BeanComparator;
36
37 import com.RuntimeCollective.content.bean.Image;
38
39 import java.sql.SQLException;
40 import java.util.Iterator;
41 import java.util.Vector;
42 import java.util.HashSet;
43 import java.util.Collection;
44 import java.util.Collections;
45 import java.util.List;
46 import java.util.Comparator;
47 import java.util.ArrayList;
48
49 /**
50 * The ImageCategory class is used to group Images, for
51 * use in an image library.
52 *
53 * @author Joe Holmberg
54 * @version $Id: ImageCategory.java,v 1.7 2003/09/30 15:12:59 joe Exp $
55 */
56 public class ImageCategory implements EntityBean {
57
58 // ---Inherited from EntityBean---------------------------
59
60 /** The name of the database table for this bean type. */
61 public static final String DATABASE_TABLE = "sitemap_imagecategory";
62
63 /** This ImageCategory's id */
64 protected int id;
65
66 /** Set the unique id of this ImageCategory.
67 * @param an int value for the id
68 */
69 public void setId(int id) {
70 this.id = id;
71 }
72
73 /** Get the unique id of this ImageCategory.
74 * @return the int value of the id
75 */
76 public int getId() {
77 return this.id;
78 }
79
80 /** Save this ImageCategory to the database.
81 * @exception SQLException is thrown if the object couldn't be saved properly to the database.
82 */
83 public void save() throws SQLException {
84
85 // Save the ImageCategory's basic attributes
86 RuntimeDataSource.save( id, DATABASE_TABLE, new String[] { "title" }, new Object[] { this.Title } );
87 }
88
89 /** Delete this ImageCategory from the database.
90 * This will delete the ImageCategory's attributes.
91 * The Images contained in this category will <b>NOT</b> be deleted.
92 *
93 * @exception SQLException is thrown if the object couldn't be deleted properly from the database.
94 */
95 public void delete() throws SQLException {
96
97 String[] updates;
98
99 updates = new String[] { "delete from "+DATABASE_TABLE+" where id = "+this.id };
100 RuntimeDataSource.update( updates);
101 }
102
103
104 //---Specific to ImageCategory ---------------------
105
106 /** How many results per page to display */
107 public static final int RESULTS_PER_PAGE = 20;
108
109 /** The title of the ImageCategory */
110 protected String Title;
111
112 /** Set the title
113 * @param title the image's title
114 */
115 public void setTitle(String title) {
116 this.Title = title;
117 }
118
119 /** Get the title
120 * @return A String which can be used as the title of this object.
121 */
122 public String getTitle() {
123 return this.Title;
124 }
125
126
127 /** Internal representation of Images in this ImageCategory */
128 protected HashSet Images;
129
130
131 /**
132 * Return all Images that belong to this ImageCategory, unsorted
133 */
134 public Collection getImages() {
135 return Images;
136 }
137
138 /**
139 * Return all Images that belong to this ImageCategory,
140 * sorted by the given Comparator
141 */
142 public List getImages(Comparator comp) {
143 List imageList = new ArrayList(Images);
144 Collections.sort(imageList, comp);
145 return imageList;
146 }
147
148 /**
149 * Return all Images that belong to this ImageCategory,
150 * sorted by last modified date (newest first)
151 */
152 public List getImagesByDate() {
153 return getImages(new BeanComparator("lastModifiedDate"));
154 }
155
156 /** Return the number of Images belonging to this ImageCategory */
157 public int getNumberOfImages() {
158 return Images.size();
159 }
160
161 /**
162 * Get <code>number</code> of images, sorted by date, starting
163 * from <code>startPos</code> (inclusive).
164 *
165 * @param startPos the offset position to start fetching images from
166 * @param number the number of images to fetch (if there are less, return as many as there are)
167 * @return a subset of all images in this category
168 */
169 public List getImageSubset(int startPos, int number) {
170 List byDate = getImagesByDate();
171 int endPos = startPos + number;
172 if (endPos > byDate.size()) {
173 endPos = byDate.size();
174 }
175 RuntimeParameters.logDebug(this, "startPos: "+startPos+", number="+number);
176 return byDate.subList(startPos, endPos);
177 }
178
179 /**
180 * Return RESULTS_PER_PAGE number of results.
181 *
182 * @param pageNumber return results page <code>pageNumber</code> (starts at 1)
183 * @return RESULTS_PER_PAGE images
184 */
185 public List getImagesByPage(int pageNumber) {
186 if (pageNumber > getLastPageNumber()) {
187 return new ArrayList();
188 }
189 List byDate = getImagesByDate();
190 int startPos = (pageNumber-1) * RESULTS_PER_PAGE;
191 return getImageSubset(startPos, RESULTS_PER_PAGE);
192 }
193
194 /**
195 * Return the maximum page number
196 */
197 public int getLastPageNumber() {
198 int lastPageNumber = (int)(Math.ceil(Images.size() / (double)RESULTS_PER_PAGE));
199 return lastPageNumber;
200 }
201
202
203 /**
204 * Add an Image to this ImageCategory.
205 * <p>
206 * This method will inform the Image of its new ImageCategory (by calling <b>setImageCategory</b> on it),
207 * then save the image.
208 * <p>
209 * (It also makes sure the image knows it uses the image library)
210 *
211 * @param image the Image to add to this ImageCategory
212 * @return true if the Image did not already belong to this ImageCategory
213 */
214 public boolean addImage(Image image) {
215 // Tell the image about its new category
216 image.setUseImageLibrary(true);
217 image.setImageCategory(this);
218 RuntimeParameters.getStore().save(image);
219
220 // Update our record of which images we have
221 return reallyAddImage(image);
222 }
223
224 /**
225 * Remove an Image from this ImageCategory, if it's in this ImageCategory.
226 * <p>
227 * This method will inform the image that it no longer belongs to this ImageCategory,
228 * then save it.
229 * <p>
230 * <b>Note:</b> The image is <b>not</b> told that it does not use the image library any more.
231 *
232 * @param image the Image to remove from this ImageCategory
233 * @return whether the Image was part of this ImageCategory
234 */
235 public boolean removeImage(Image image) {
236 // Tell the image it has no category
237 image.setImageCategory(null);
238 RuntimeParameters.getStore().save(image);
239
240 // Update our record of which images we have
241 return reallyRemoveImage(image);
242 }
243
244 /**
245 * Update the internal representation of which Images
246 * are part of this category
247 */
248 private synchronized boolean reallyAddImage(Image image) {
249 return Images.add(image);
250 }
251
252
253 /**
254 * Update the internal representation of which Images
255 * are part of this category
256 */
257 private synchronized boolean reallyRemoveImage(Image image) {
258 return Images.remove(image);
259 }
260
261
262 /** Construct a new blank ImageCategory, giving it a new unique ID.
263 * @exception SQLException is thrown if a new ID cannot be created.
264 */
265 public ImageCategory() throws SQLException {
266 setId(RuntimeDataSource.nextId());
267 this.setTitle("New category");
268 this.Images = new HashSet();
269 }
270
271 /** Get a ImageCategory from the database, given an id.
272 * @param id ID of the ImageCategory.
273 * @exception SQLException is thrown if no such ImageCategory exists.
274 */
275 public ImageCategory(int id) throws SQLException {
276
277 setId(id);
278
279 Object[] result = RuntimeDataSource.queryRow("select cil.title from "+DATABASE_TABLE+" cil where cil.id = "+id);
280 if (result.length != 1) {
281 throw new SQLException("Cannot load ImageCategory "+id+" : "+result.length+" fields found in "+DATABASE_TABLE+" instead of 1.");
282 }
283 if (result[0] != null)
284 setTitle((String) result[0]);
285
286 // load the Images that belong to this ImageCategory
287 this.Images = new HashSet();
288 Object[][] rows = RuntimeDataSource.queryRows("select id from "+Image.DATABASE_TABLE+" where imagecategory_id = "+id);
289
290 int contentId;
291
292 for (int i=0; i<rows.length; i++) {
293 contentId = Integer.parseInt(rows[i][0].toString());
294 RuntimeParameters.logDebug(this, "Adding an Image: "+contentId);
295 Image image = null;
296 try {
297 image = (Image)RuntimeParameters.getStore().get("com.RuntimeCollective.content.bean.Image", contentId);
298 reallyAddImage(image);
299 } catch (RuntimeException e) {
300 RuntimeParameters.logError(this, "FAILED to get an image: "+contentId+": "+e);
301 e.printStackTrace(System.out);
302 }
303 }
304
305 }
306
307 }
308