001: /**
002: * Copyright (C) 2001 Yasna.com. All rights reserved.
003: *
004: * ===================================================================
005: * The Apache Software License, Version 1.1
006: *
007: * Redistribution and use in source and binary forms, with or without
008: * modification, are permitted provided that the following conditions
009: * are met:
010: *
011: * 1. Redistributions of source code must retain the above copyright
012: * notice, this list of conditions and the following disclaimer.
013: *
014: * 2. Redistributions in binary form must reproduce the above copyright
015: * notice, this list of conditions and the following disclaimer in
016: * the documentation and/or other materials provided with the
017: * distribution.
018: *
019: * 3. The end-user documentation included with the redistribution,
020: * if any, must include the following acknowledgment:
021: * "This product includes software developed by
022: * Yasna.com (http://www.yasna.com)."
023: * Alternately, this acknowledgment may appear in the software itself,
024: * if and wherever such third-party acknowledgments normally appear.
025: *
026: * 4. The names "Yazd" and "Yasna.com" must not be used to
027: * endorse or promote products derived from this software without
028: * prior written permission. For written permission, please
029: * contact yazd@yasna.com.
030: *
031: * 5. Products derived from this software may not be called "Yazd",
032: * nor may "Yazd" appear in their name, without prior written
033: * permission of Yasna.com.
034: *
035: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
036: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
037: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
038: * DISCLAIMED. IN NO EVENT SHALL YASNA.COM OR
039: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
040: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
041: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
042: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
043: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
044: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
045: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
046: * SUCH DAMAGE.
047: * ====================================================================
048: *
049: * This software consists of voluntary contributions made by many
050: * individuals on behalf of Yasna.com. For more information
051: * on Yasna.com, please see <http://www.yasna.com>.
052: */
053:
054: /**
055: * Copyright (C) 2000 CoolServlets.com. All rights reserved.
056: *
057: * ===================================================================
058: * The Apache Software License, Version 1.1
059: *
060: * Redistribution and use in source and binary forms, with or without
061: * modification, are permitted provided that the following conditions
062: * are met:
063: *
064: * 1. Redistributions of source code must retain the above copyright
065: * notice, this list of conditions and the following disclaimer.
066: *
067: * 2. Redistributions in binary form must reproduce the above copyright
068: * notice, this list of conditions and the following disclaimer in
069: * the documentation and/or other materials provided with the
070: * distribution.
071: *
072: * 3. The end-user documentation included with the redistribution,
073: * if any, must include the following acknowledgment:
074: * "This product includes software developed by
075: * CoolServlets.com (http://www.coolservlets.com)."
076: * Alternately, this acknowledgment may appear in the software itself,
077: * if and wherever such third-party acknowledgments normally appear.
078: *
079: * 4. The names "Jive" and "CoolServlets.com" must not be used to
080: * endorse or promote products derived from this software without
081: * prior written permission. For written permission, please
082: * contact webmaster@coolservlets.com.
083: *
084: * 5. Products derived from this software may not be called "Jive",
085: * nor may "Jive" appear in their name, without prior written
086: * permission of CoolServlets.com.
087: *
088: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
089: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
090: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
091: * DISCLAIMED. IN NO EVENT SHALL COOLSERVLETS.COM OR
092: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
093: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
094: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
095: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
096: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
097: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
098: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
099: * SUCH DAMAGE.
100: * ====================================================================
101: *
102: * This software consists of voluntary contributions made by many
103: * individuals on behalf of CoolServlets.com. For more information
104: * on CoolServlets.com, please see <http://www.coolservlets.com>.
105: */package com.Yasna.forum.database;
106:
107: import java.sql.*;
108:
109: import com.Yasna.forum.*;
110: import com.Yasna.util.*;
111:
112: /**
113: * Database implementation of the TreeWalker interface. This class is relatively
114: * inefficient compared to how it will eventually be implemented. However,
115: * a schema change is needed before that optimization is needed (represent
116: * tree structure directly in schema).
117: */
118: public class DbTreeWalker implements TreeWalker {
119:
120: /** DATABASE QUERIES **/
121: private static final String GET_CHILD = "SELECT yazdMessageTree.childID, yazdMessage.creationDate FROM "
122: + "yazdMessageTree, yazdMessage WHERE "
123: + "yazdMessageTree.childID=yazdMessage.messageID AND "
124: + "yazdMessageTree.parentID=? ORDER BY yazdMessage.creationDate";
125: private static final String CHILD_COUNT = "SELECT count(*) FROM yazdMessageTree WHERE parentID=?";
126: private static final String INDEX_OF_CHILD = "SELECT yazdMessageTree.childID, yazdMessage.creationDate "
127: + "FROM yazdMessageTree, yazdMessage WHERE yazdMessageTree.childID=yazdMessage.messageID "
128: + "AND yazdMessageTree.parentID=? ORDER BY yazdMessage.creationDate";
129:
130: private DbForumThread thread;
131: private DbForumFactory factory;
132:
133: public DbTreeWalker(DbForumThread thread, DbForumFactory factory) {
134: this .thread = thread;
135: this .factory = factory;
136: }
137:
138: /**
139: * Returns the root of the tree. Returns null only if the tree has no nodes.
140: *
141: * @returns the root of the tree
142: */
143: public ForumMessage getRoot() {
144: return thread.getRootMessage();
145: }
146:
147: /**
148: * Returns the child of parent at index index in the parent's child array.
149: * This should not return null if index is a valid index for parent (that
150: * is index >= 0 && index < getChildCount(parent)).
151: *
152: * @param parent the parent message.
153: * @param index the index of the child.
154: * @returns the child of parent at index.
155: */
156: public ForumMessage getChild(ForumMessage parent, int index) {
157: ForumMessage message = null;
158: Connection con = null;
159: PreparedStatement pstmt = null;
160: try {
161: con = DbConnectionManager.getConnection();
162: pstmt = con.prepareStatement(GET_CHILD);
163: pstmt.setInt(1, parent.getID());
164: ResultSet rs = pstmt.executeQuery();
165: while (rs.next() && index > 0) {
166: index--;
167: }
168: if (index == 0) {
169: int messageID = rs.getInt(1);
170: message = thread.getMessage(messageID);
171: }
172: } catch (Exception e) {
173: System.err.println("Error in DbMessageTreeWalker:getChild("
174: + index + ")-" + e);
175: e.printStackTrace();
176: } finally {
177: try {
178: pstmt.close();
179: } catch (Exception e) {
180: e.printStackTrace();
181: }
182: try {
183: con.close();
184: } catch (Exception e) {
185: e.printStackTrace();
186: }
187: }
188: return message;
189: }
190:
191: /**
192: * Returns the number of children of parent. Returns 0 if the node is a
193: * leaf or if it has no children.
194: *
195: * @param parent a node in the tree, obtained from this data source.
196: * @returns the number of children of the node parent.
197: */
198: public int getChildCount(ForumMessage parent) {
199: int childCount = 0;
200: Connection con = null;
201: PreparedStatement pstmt = null;
202: try {
203: con = DbConnectionManager.getConnection();
204: pstmt = con.prepareStatement(CHILD_COUNT);
205: pstmt.setInt(1, parent.getID());
206: ResultSet rs = pstmt.executeQuery();
207: rs.next();
208: childCount = rs.getInt(1);
209: } catch (Exception e) {
210: System.err.println("Error in DbTreeWalker:getChildCount()-"
211: + e);
212: e.printStackTrace();
213: } finally {
214: try {
215: pstmt.close();
216: } catch (Exception e) {
217: e.printStackTrace();
218: }
219: try {
220: con.close();
221: } catch (Exception e) {
222: e.printStackTrace();
223: }
224: }
225: return childCount;
226: }
227:
228: /**
229: * Returns the total number of recursive children of a parent. Returns 0
230: * if there are no children. This method is not intended to aid in
231: * navigation of a Thread but is included as an added utility.
232: */
233: public int getRecursiveChildCount(ForumMessage parent) {
234: int numChildren = 0;
235: int num = getChildCount(parent);
236: numChildren += num;
237: for (int i = 0; i < num; i++) {
238: ForumMessage child = getChild(parent, i);
239: if (child != null) {
240: numChildren += getRecursiveChildCount(child);
241: }
242: }
243: return numChildren;
244: }
245:
246: /**
247: * Returns the index of child in parent.
248: */
249: public int getIndexOfChild(ForumMessage parent, ForumMessage child) {
250: int index = 0;
251: Connection con = null;
252: PreparedStatement pstmt = null;
253: ResultSet rs = null;
254: try {
255: con = DbConnectionManager.getConnection();
256: pstmt = con.prepareStatement(INDEX_OF_CHILD);
257: pstmt.setInt(1, parent.getID());
258: rs = pstmt.executeQuery();
259: while (rs.next()) {
260: if (rs.getInt(1) == child.getID()) {
261: break;
262: }
263: index++;
264: }
265: } catch (Exception e) {
266: System.err
267: .println("Error in DbTreeWalker:getIndexOfChild()-"
268: + e);
269: } finally {
270: try {
271: pstmt.close();
272: } catch (Exception e) {
273: e.printStackTrace();
274: }
275: try {
276: con.close();
277: } catch (Exception e) {
278: e.printStackTrace();
279: }
280: }
281: return index;
282: }
283:
284: /**
285: * Returns true if node is a leaf. A node is a leaf when it has no children
286: * messages.
287: *
288: * @param node a node in the tree, obtained from this data source
289: * @returns true if node is a leaf
290: */
291: public boolean isLeaf(ForumMessage node) {
292: return (getChildCount(node) == 0);
293: }
294: }
|