* landed code for viewing topics in a conference, and for adding a topic

(first workout of HTML Checker code)
* modified the dictionary implementation to use a trie system rather than
  a set of HashSets, and also started using a new, much smaller dictionary
* general bugfixes and cleanup on other items as needed
This commit is contained in:
Eric J. Bowersox
2001-02-06 04:50:04 +00:00
parent 650691c8d2
commit 8bcc80ddd7
39 changed files with 47278 additions and 264907 deletions
@@ -109,4 +109,7 @@ public interface ConferenceContext
public abstract TopicContext getTopic(short number) throws DataException, AccessError;
public abstract TopicContext addTopic(String title, String zp_pseud, String zp_text)
throws DataException, AccessError;
} // end interface ConferenceContext
@@ -18,6 +18,7 @@
package com.silverwrist.venice.core.impl;
import java.sql.*;
import java.util.Date;
public interface ConferenceBackend extends SIGBackend
{
@@ -27,6 +28,8 @@ public interface ConferenceBackend extends SIGBackend
public abstract void touchRead(Connection conn) throws SQLException;
public abstract void touchPost(Connection conn, java.util.Date post_date) throws SQLException;
public abstract String realConfAlias();
} // end interface ConferenceBackend
@@ -52,7 +52,7 @@ class ConferenceCoreData implements ConferenceData
private int nuke_level; // access level required to delete topics/scribble/nuke posts
private int change_level; // access level required to modify conference profile
private int delete_level; // access level required to delete conference
private int top_topic; // the highest topic number in the conference
private short top_topic; // the highest topic number in the conference
private String name; // the name of the conference
private String description; // the conference's description
private String cached_alias = null; // the cached alias (for getAnAlias)
@@ -142,7 +142,7 @@ class ConferenceCoreData implements ConferenceData
nuke_level = rs.getInt("nuke_lvl");
change_level = rs.getInt("change_lvl");
delete_level = rs.getInt("delete_lvl");
top_topic = rs.getInt("top_topic");
top_topic = rs.getShort("top_topic");
name = rs.getString("name");
description = rs.getString("descr");
// "icon_url" and "color" fields are skipped
@@ -817,6 +817,121 @@ class ConferenceCoreData implements ConferenceData
} // end getAnAlias
public ReturnTopicInfo createNewTopic(SIGBackend sig, String title, String pseud, String body,
int body_lines) throws DataException
{
Connection conn = null; // database connection
AuditRecord ar = null; // audit record
short new_topic_num; // sequential number of the new topic
int new_topic_id; // ID of the new topic
java.util.Date creation; // creation date for new topic
try
{ // get a database connection
conn = datapool.getConnection();
Statement stmt = conn.createStatement();
// lock the tables we need to use so we can update them
stmt.executeUpdate("LOCK TABLES confs WRITE, topics WRITE, posts WRITE, postdata WRITE;");
try
{ // determine the data for the initial topic
new_topic_num = (short)(top_topic + 1);
// add the topic row to the database
StringBuffer sql = new StringBuffer("INSERT INTO topics (confid, num, creator_uid, createdate, "
+ "lastupdate, name) VALUES (");
sql.append(confid).append(", ").append(new_topic_num).append(", ").append(sig.realUID()).append(", '");
creation = new java.util.Date();
String now_str = SQLUtil.encodeDate(creation);
sql.append(now_str).append("', '").append(now_str).append("', '").append(title).append("');");
if (logger.isDebugEnabled())
logger.debug("SQL: " + sql.toString());
stmt.executeUpdate(sql.toString());
// get the topic ID we just inserted
ResultSet rs = stmt.executeQuery("SELECT LAST_INSERT_ID();");
if (!(rs.next()))
throw new InternalStateError("createNewTopic() could not get back inserted Topic ID");
new_topic_id = rs.getInt(1);
// insert the "header" for the "zero post" in the topic
sql.setLength(0);
sql.append("INSERT INTO posts (topicid, num, linecount, creator_uid, posted, pseud) VALUES (");
sql.append(new_topic_id).append(", 0, ").append(body_lines).append(", ").append(sig.realUID());
sql.append(", '").append(now_str).append("', '").append(pseud).append("');");
if (logger.isDebugEnabled())
logger.debug("SQL: " + sql.toString());
stmt.executeUpdate(sql.toString());
// get the ID of the zero post
rs = stmt.executeQuery("SELECT LAST_INSERT_ID();");
if (!(rs.next()))
throw new InternalStateError("createNewTopic() could not get back inserted zero post ID");
long zero_post_id = rs.getLong(1);
// insert the post data
sql.setLength(0);
sql.append("INSERT INTO postdata (postid, data) VALUES (").append(zero_post_id).append(", '");
sql.append(body).append("');");
stmt.executeUpdate(sql.toString());
// touch the "conference" entry to reflect the update
sql.setLength(0);
sql.append("UPDATE confs SET lastupdate = '").append(now_str).append("', top_topic = ");
sql.append(new_topic_num).append(" WHERE confid = ").append(confid).append(';');
if (logger.isDebugEnabled())
logger.debug("SQL: " + sql.toString());
stmt.executeUpdate(sql.toString());
// touch the local variables, too
top_topic = new_topic_num;
last_update = creation;
// create an audit record indicating we were successful
ar = new AuditRecord(AuditRecord.CREATE_TOPIC,sig.realUID(),sig.userRemoteAddress(),sig.realSIGID(),
"confid=" + String.valueOf(confid),"num=" + String.valueOf(new_topic_num),
"title=" + title);
} // end try
finally
{ // we need to unlock the tables before we go
Statement ulk_stmt = conn.createStatement();
ulk_stmt.executeUpdate("UNLOCK TABLES;");
} // end finally
} // end try
catch (SQLException e)
{ // database error - this is a DataException
logger.error("DB error creating topic: " + e.getMessage(),e);
throw new DataException("unable to create topic: " + e.getMessage(),e);
} // end catch
finally
{ // make sure the connection is released before we go
try
{ // save off the audit record before we go, though
if ((ar!=null) && (conn!=null))
ar.store(conn);
} // end try
catch (SQLException e)
{ // we couldn't store the audit record!
logger.error("DB error saving audit record: " + e.getMessage(),e);
} // end catch
if (conn!=null)
datapool.releaseConnection(conn);
} // end finally
// we have three pieces of data to return, so we need a temporary object
return new ReturnTopicInfo(new_topic_id,new_topic_num,creation);
} // end createNewTopic
/*--------------------------------------------------------------------------------
* External static operations (usable only from within package)
*--------------------------------------------------------------------------------
@@ -865,14 +980,14 @@ class ConferenceCoreData implements ConferenceData
// insert the record into the conferences table!
sql.setLength(0);
sql.append("INSERT INTO confs (createdate, read_lvl, post_lvl, create_lvl, hide_lvl, nuke_lvl, "
+ "change_lvl, delete_lvl, top_topic, name, descr) VALUES ('");
+ "change_lvl, delete_lvl, name, descr) VALUES ('");
created = new java.util.Date();
sql.append(SQLUtil.encodeDate(created)).append("', ").append(DefaultLevels.newConferenceRead(pvt));
sql.append(", ").append(DefaultLevels.newConferencePost(pvt)).append(", ");
sql.append(DefaultLevels.newConferenceCreate(pvt)).append(", ");
sql.append(DefaultLevels.newConferenceHide()).append(", ").append(DefaultLevels.newConferenceNuke());
sql.append(", ").append(DefaultLevels.newConferenceChange()).append(", ");
sql.append(DefaultLevels.newConferenceDelete()).append(", 0, '").append(SQLUtil.encodeString(name));
sql.append(DefaultLevels.newConferenceDelete()).append(", '").append(SQLUtil.encodeString(name));
sql.append("', '").append(SQLUtil.encodeString(description)).append("');");
if (logger.isDebugEnabled())
logger.debug("SQL: " + sql.toString());
@@ -76,4 +76,7 @@ public interface ConferenceData extends ReferencedData
public abstract String getAnAlias() throws DataException;
public abstract ReturnTopicInfo createNewTopic(SIGBackend sig, String title, String pseud, String body,
int body_lines) throws DataException;
} // end interface ConferenceData
@@ -88,4 +88,7 @@ public interface ConferenceSIGContext extends ReferencedData
public abstract String getAnAlias() throws DataException;
public abstract ReturnTopicInfo createNewTopic(SIGBackend sig, String title, String pseud, String body,
int body_lines) throws DataException;
} // end interface ConferenceSIGContext
@@ -611,4 +611,11 @@ class ConferenceSIGContextImpl implements ConferenceSIGContext
} // end getAnAlias
public ReturnTopicInfo createNewTopic(SIGBackend sig, String title, String pseud, String body,
int body_lines) throws DataException
{
return getConferenceData().createNewTopic(sig,title,pseud,body,body_lines);
} // end createNewTopic
} // end class ConferenceSIGContextImpl
@@ -21,6 +21,7 @@ import java.sql.*;
import java.util.*;
import org.apache.log4j.*;
import com.silverwrist.venice.db.*;
import com.silverwrist.venice.htmlcheck.*;
import com.silverwrist.venice.security.DefaultLevels;
import com.silverwrist.venice.core.*;
@@ -810,6 +811,79 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
} // end getTopic
public TopicContext addTopic(String title, String zp_pseud, String zp_text)
throws DataException, AccessError
{
if (!(getConferenceData().canCreateTopic(level)))
{ // not allowed to create a topic - bail out
logger.error("user not permitted to create new topic");
throw new AccessError("You are not permitted to create a topic in this conference.");
} // end if
// preprocess the three arguments through HTML checkers
HTMLChecker title_ch = engine.createCheckerObject(engine.HTMLC_POST_PSEUD);
HTMLChecker zp_pseud_ch = engine.createCheckerObject(engine.HTMLC_POST_PSEUD);
HTMLChecker zp_text_ch = engine.createCheckerObject(engine.HTMLC_POST_BODY);
try
{ // run all three arguments through the HTML checker
title_ch.append(title);
title_ch.finish();
zp_pseud_ch.append(zp_pseud);
zp_pseud_ch.finish();
zp_text_ch.append(zp_text);
zp_text_ch.finish();
} // end try
catch (AlreadyFinishedException e)
{ // this isn't right...
throw new InternalStateError("HTMLChecker erroneously throwing AlreadyFinishedException",e);
} // end catch
// Create the actual topic in the database.
String real_title;
ReturnTopicInfo new_topic_inf;
try
{ // call down to create the new topic!
real_title = title_ch.getValue();
new_topic_inf = getConferenceData().createNewTopic(sig,real_title,zp_pseud_ch.getValue(),
zp_text_ch.getValue(),zp_text_ch.getLines());
} // end try
catch (NotYetFinishedException e)
{ // this isn't right either!
throw new InternalStateError("HTMLChecker erroneously throwing NotYetFinishedException",e);
} // end catch
// now we need to reset our last post date
Connection conn = null;
try
{ // get a connection and feed it to the touchPost function
conn = datapool.getConnection();
touchPost(conn,new_topic_inf.getCreateDate());
} // end try
catch (SQLException e)
{ // this becomes a DataException
logger.error("DB error updating user information: " + e.getMessage(),e);
throw new DataException("unable to update user information: " + e.getMessage(),e);
} // end catch
finally
{ // make sure we release the connection before we go
if (conn!=null)
datapool.releaseConnection(conn);
} // end finally
// create the topic context to return to the user
return new TopicUserContextImpl(engine,this,datapool,new_topic_inf,real_title);
} // end addTopic
/*--------------------------------------------------------------------------------
* Implementations from interface UserBackend
*--------------------------------------------------------------------------------
@@ -929,6 +1003,34 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
} // end touchRead
public void touchPost(Connection conn, java.util.Date post_date) throws SQLException
{
Statement stmt = conn.createStatement();
StringBuffer sql = new StringBuffer();
if (settings_loaded)
{ // generate an update statement
sql.append("UPDATE confsettings SET last_post = '").append(SQLUtil.encodeDate(post_date));
sql.append("' WHERE confid = ").append(confid).append(" AND uid = ").append(sig.realUID()).append(';');
} // end if
else
{ // need to insert a confsettings row
sql.append("INSERT INTO confsettings (confid, uid, default_pseud, last_read) VALUES (").append(confid);
sql.append(", ").append(sig.realUID()).append(", '").append(SQLUtil.encodeString(pseud)).append("', '");
sql.append(SQLUtil.encodeDate(post_date)).append("');");
} // end else
// execute the statement
stmt.executeUpdate(sql.toString());
// save off the values to our local fields
last_post = post_date;
settings_loaded = true;
} // end touchRead
public String realConfAlias()
{
try
@@ -0,0 +1,69 @@
/*
* The contents of this file are subject to the Mozilla Public License Version 1.1
* (the "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at <http://www.mozilla.org/MPL/>.
*
* Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
* language governing rights and limitations under the License.
*
* The Original Code is the Venice Web Community System.
*
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.venice.core.impl;
import java.util.Date;
public class ReturnTopicInfo
{
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private int topic_id;
private short topic_num;
private Date create_date;
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
public ReturnTopicInfo(int topic_id, short topic_num, Date create_date)
{
this.topic_id = topic_id;
this.topic_num = topic_num;
this.create_date = create_date;
} // end constructor
/*--------------------------------------------------------------------------------
* External operations
*--------------------------------------------------------------------------------
*/
public int getTopicID()
{
return topic_id;
} // end getTopicID
public short getTopicNum()
{
return topic_num;
} // end getTopicNum
public Date getCreateDate()
{
return create_date;
} // end getCreateDate
} // end class ReturnTopicInfo
@@ -79,7 +79,27 @@ class TopicUserContextImpl implements TopicContext
this.hidden = hidden;
this.unread = unread;
} // end TopicUserContextImpl
} // end constructor
TopicUserContextImpl(EngineBackend engine, ConferenceBackend conf, DataPool datapool, ReturnTopicInfo inf,
String name)
{
this.engine = engine;
this.conf = conf;
this.datapool = datapool;
this.topicid = inf.getTopicID();
this.topicnum = inf.getTopicNum();
this.creator_uid = conf.realUID();
this.top_message = 0;
this.frozen = false;
this.archived = false;
this.created = inf.getCreateDate();
this.lastupdate = inf.getCreateDate();
this.name = name;
this.hidden = false;
this.unread = 1;
} // end constructor
/*--------------------------------------------------------------------------------
* Internal functions
@@ -553,23 +573,24 @@ class TopicUserContextImpl implements TopicContext
break;
case ConferenceContext.DISPLAY_NEW:
where_clause = "hidden = 0 AND unread > 0"; // only non-hidden topics w/unread messages
// only non-hidden topics w/unread messages
where_clause = "IFNULL(s.hidden,0) = 0 AND t.top_message > IFNULL(s.last_message,-1)";
break;
case ConferenceContext.DISPLAY_ACTIVE:
where_clause = "t.archived = 0 AND hidden = 0"; // only non-hidden, non-archived topics
where_clause = "t.archived = 0 AND IFNULL(s.hidden,0) = 0"; // only non-hidden, non-archived topics
break;
case ConferenceContext.DISPLAY_ALL:
where_clause = "t.archived = 0 AND hidden = 0"; // only non-hidden, non-archived topics
where_clause = "t.archived = 0 AND IFNULL(s.hidden,0) = 0"; // only non-hidden, non-archived topics
break;
case ConferenceContext.DISPLAY_HIDDEN:
where_clause = "hidden = 1"; // only hidden topics
where_clause = "IFNULL(s.hidden,0) = 1"; // only hidden topics
break;
case ConferenceContext.DISPLAY_ARCHIVED:
where_clause = "t.archived = 1 AND hidden = 0"; // only non-hidden, archived topics
where_clause = "t.archived = 1 AND IFNULL(s.hidden,0) = 0"; // only non-hidden, archived topics
break;
default:
@@ -435,7 +435,7 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
String[] dictfiles = new String[dictionary_tmp.size()];
for (int i=0; i<dictionary_tmp.size(); i++)
dictfiles[i] = (String)(dictionary_tmp.get(i));
LazyLexicon lex = new LazyLexicon(dictfiles);
LazyTreeLexicon lex = new LazyTreeLexicon(dictfiles);
spell_rewriter.addDictionary(lex);
html_configs = new HTMLCheckerConfig[4]; // create the array