* 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

View File

@@ -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

View File

@@ -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

View File

@@ -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());

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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:

View File

@@ -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

View File

@@ -0,0 +1,121 @@
/*
* 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.htmlcheck.dict;
class DictNode
{
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
private static final int[] permute_tab =
{ 7, 21, 12, 9, 1, 13, 18, 10, 5, 25, 23, 11, 16, 3, 6, 14, 24, 4, 8, 2, 15, 20, 19, 22, 17, 26 };
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private boolean terminal = false;
private DictNode[] p = null;
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
DictNode()
{ // do nothing
} // end constructor
/*--------------------------------------------------------------------------------
* Internal functions
*--------------------------------------------------------------------------------
*/
private final int permute(char ltr)
{
if (ltr=='-')
return 0;
else
return permute_tab[ltr - 'a'];
} // end permute
/*--------------------------------------------------------------------------------
* External operations
*--------------------------------------------------------------------------------
*/
final DictNode getRef(char ltr)
{
if (p==null)
return null;
int x = permute(ltr);
if (x<p.length)
return p[x];
else
return null;
} // end getRef
final void setRef(char ltr, DictNode node)
{
int x = permute(ltr);
if ((p==null) || (x>=p.length))
{ // the internal array needs to be expanded
DictNode[] new_p = new DictNode[x+1];
int i;
if (p!=null)
{ // copy the old portion over, set the new portion
System.arraycopy(p,0,new_p,0,p.length);
for (i=p.length; i<x+1; i++)
new_p[i] = null;
} // end if
else
{ // initialize the whole thing
for (i=0; i<x+1; i++)
new_p[i] = null;
} // end else
p = new_p;
} // end if
p[x] = node;
} // end setRef
final boolean isTerminal()
{
return terminal;
} // end isTerminal
final void setTerminal()
{
terminal = true;
} // end setTerminal
} // end class DictNode

View File

@@ -0,0 +1,162 @@
/*
* 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.htmlcheck.dict;
import java.io.*;
import org.apache.log4j.*;
import com.silverwrist.venice.htmlcheck.SpellingDictionary;
public class LazyTreeLexicon implements Runnable, SpellingDictionary
{
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
private static Category logger = Category.getInstance(LazyTreeLexicon.class.getName());
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
TreeLexicon inner_lex = null;
private String[] filenames;
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
public LazyTreeLexicon(String[] filenames)
{
this.filenames = filenames; // save off the file names to be loaded
// spin off the load process into the background
Thread thrd = new Thread(this);
thrd.start();
} // end constructor
/*--------------------------------------------------------------------------------
* Internal functions
*--------------------------------------------------------------------------------
*/
private synchronized TreeLexicon getLex()
{
while (inner_lex==null)
{ // wait for the inner thread to finish creating the lexicon
if (logger.isDebugEnabled())
logger.debug("LazyLexicon: waiting for lex to load...");
try
{ // park the thread here until we know what's up
wait();
} // end try
catch (InterruptedException e)
{ // do nothing
} // end catch
} // end while
return inner_lex;
} // end getLex
/*--------------------------------------------------------------------------------
* Implementations from class Runnable
*--------------------------------------------------------------------------------
*/
public void run()
{
TreeLexicon lex = new TreeLexicon();
if (logger.isDebugEnabled())
logger.debug("LazyTreeLexicon loading " + String.valueOf(filenames.length) + " lexicon(s)");
for (int i=0; i<filenames.length; i++)
{ // load data into the lexicon in turn
if (logger.isDebugEnabled())
logger.debug("LazyTreeLexicon loading file: " + filenames[i]);
try
{ // start reading the file
BufferedReader rdr = new BufferedReader(new FileReader(filenames[i]));
int counter = 0;
String word = rdr.readLine();
while (word!=null)
{ // add each word to the lexicon as we go
lex.addWord(word);
word = rdr.readLine();
if (((++counter % 1000)==0) && logger.isDebugEnabled())
logger.debug("loaded " + String.valueOf(counter) + " words");
} // end while
rdr.close();
if (logger.isDebugEnabled())
logger.debug("finished loading " + filenames[i] + ", " + String.valueOf(counter) + " words loaded");
} // end try
catch (IOException e)
{ // trap it and go on to the next one
logger.error("IOException loading lexfile " + filenames[i] + ": " + e.getMessage());
} // end catch
} // end for
if (logger.isDebugEnabled())
logger.debug("LazyTreeLexicon load complete.");
synchronized (this)
{ // set the lexicon reference and wake up all waiting threads
inner_lex = lex;
notifyAll();
} // end synchronized block
System.gc(); // free any extra crap generated by the lexicon load
if (logger.isDebugEnabled())
logger.debug("LazyTreeLexicon GC complete.");
} // end run
/*--------------------------------------------------------------------------------
* Implementations from interface SpellingDictionary
*--------------------------------------------------------------------------------
*/
public int size()
{
return getLex().size();
} // end size
public boolean checkWord(String word)
{
return getLex().checkWord(word);
} // end checkWord
} // end class LazyTreeLexicon

View File

@@ -20,10 +20,18 @@ package com.silverwrist.venice.htmlcheck.dict;
import java.io.*;
import java.util.*;
import java.util.zip.*;
import org.apache.log4j.*;
import com.silverwrist.venice.htmlcheck.ModSpellingDictionary;
public class Lexicon implements ModSpellingDictionary, Serializable
{
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
private static Category logger = Category.getInstance(Lexicon.class.getName());
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
@@ -152,17 +160,24 @@ public class Lexicon implements ModSpellingDictionary, Serializable
public synchronized void readFile(String filename) throws IOException
{
if (logger.isDebugEnabled())
logger.debug("Lexicon.readFile loading " + filename);
BufferedReader rdr = new BufferedReader(new FileReader(filename));
int counter = 0;
String word = rdr.readLine();
while (word!=null)
{ // add each word to the lexicon as we go
addWord(word);
word = rdr.readLine();
if (((++counter % 1000)==0) && logger.isDebugEnabled())
logger.debug("loaded " + String.valueOf(counter) + " words");
} // end while
rdr.close();
if (logger.isDebugEnabled())
logger.debug("finished loading " + filename + ", " + String.valueOf(counter) + " words loaded");
} // end readFile
@@ -184,7 +199,7 @@ public class Lexicon implements ModSpellingDictionary, Serializable
real_stm = new ObjectInputStream(stm);
try
{ // attempt to read the LExicon object
{ // attempt to read the Lexicon object
Object tmp = real_stm.readObject();
if (tmp instanceof Lexicon)
return (Lexicon)tmp;

View File

@@ -0,0 +1,120 @@
/*
* 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.htmlcheck.dict;
import com.silverwrist.venice.htmlcheck.ModSpellingDictionary;
public class TreeLexicon implements ModSpellingDictionary
{
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private DictNode root; // root node of the trie that contains our data
private int count; // number of words in the lexicon
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
public TreeLexicon()
{
root = new DictNode();
count = 0;
} // end constructor
/*--------------------------------------------------------------------------------
* Implementations from interface SpellingDictionary
*--------------------------------------------------------------------------------
*/
public synchronized int size()
{
return count;
} // end size
public synchronized boolean checkWord(String word)
{
String real_word = word.toLowerCase();
DictNode cur = root;
for (int i=0; i<real_word.length(); i++)
{ // loop through the characters and move down the trie
char ch = real_word.charAt(i);
if (((ch<'a') || (ch>'z')) && (ch!='-'))
return false;
cur = cur.getRef(ch);
if (cur==null)
return false;
} // end for
return cur.isTerminal();
} // end checkWord
/*--------------------------------------------------------------------------------
* Implementations from interface ModSpellingDictionary
*--------------------------------------------------------------------------------
*/
public synchronized void addWord(String word)
{
String real_word = word.toLowerCase();
DictNode cur = root;
for (int i=0; i<real_word.length(); i++)
{ // move through the word - bail out if bogus chars
char ch = real_word.charAt(i);
if (((ch<'a') || (ch>'z')) && (ch!='-'))
return;
// advance down through trie
DictNode next = cur.getRef(ch);
if (next==null)
{ // strike out into a new DictNode
next = new DictNode();
cur.setRef(ch,next);
} // end if
cur = next;
} // end for
cur.setTerminal();
count++;
} // end addWord
public void delWord(String word)
{ // not implemented for this lexicon type
} // end delWord
public synchronized void clear()
{
root = new DictNode();
count = 0;
} // end clear
} // end class TreeLexicon

View File

@@ -154,7 +154,7 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic
{ // get each rewriter, and wrap it if it has a name
Rewriter r = (Rewriter)(it.next());
String name = r.getName();
if (r!=null)
if (name!=null)
{ // wrap it in a CountingRewriter and hash it...
CountingRewriter cr = new CountingRewriter(r);
counters.put(name,cr);

View File

@@ -213,6 +213,8 @@ public class ConfDisplay extends VeniceServlet
{ // all commands require a SIG parameter
sig = getSIGParameter(request,user);
changeMenuSIG(request,sig);
if (logger.isDebugEnabled())
logger.debug("found SIG #" + String.valueOf(sig.getSIGID()));
} // end try
catch (DataException de)
@@ -222,11 +224,13 @@ public class ConfDisplay extends VeniceServlet
} // end catch
if (content!=null)
if (content==null)
{ // we got the SIG parameter OK
try
{ // all commands require a conference parameter
conf = getConferenceParameter(request,sig);
if (logger.isDebugEnabled())
logger.debug("found conf #" + String.valueOf(conf.getConfID()));
} // end try
catch (DataException de)
@@ -238,11 +242,19 @@ public class ConfDisplay extends VeniceServlet
} // end if
if (content!=null)
if (content==null)
{ // we got the conference parameter OK
try
{ // there's an optional topic parameter
topic = getTopicParameter(request,conf);
if (logger.isDebugEnabled())
{ // do a little debugging output
if (topic!=null)
logger.debug("found topic #" + String.valueOf(topic.getTopicID()));
else
logger.debug("no topic specified");
} // end if
} // end try
catch (DataException de)
@@ -268,26 +280,30 @@ public class ConfDisplay extends VeniceServlet
} // end catch
if (content!=null)
if (content==null)
{ // OK, let's handle the display now
if (topic!=null)
{ // we're handling messages within a single topic
if (logger.isDebugEnabled())
logger.debug("MODE: display messages in topic");
// TODO: handle this somehow
} // end if
else
{ // we're displaying the conference's topic list
if (logger.isDebugEnabled())
logger.debug("MODE: display topics in conference");
TopicSortHolder opts = TopicSortHolder.retrieve(request.getSession(true));
try
{ // get any changes to view or sort options
getViewSortDefaults(request,conf.getConfID(),opts);
// get the topic list in the desired order!
List topic_list = conf.getTopicList(opts.getViewOption(conf.getConfID()),
opts.getSortOption(conf.getConfID()));
// TODO: create the "next topic" list to use for "read next"
// TODO: create the page view
// create the topic list
content = new TopicListing(request,sig,conf,opts.getViewOption(conf.getConfID()),
opts.getSortOption(conf.getConfID()));
page_title = "Topics in " + conf.getName();
} // end try
catch (ValidationException ve)

View File

@@ -7,7 +7,7 @@
* 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 Original Code is the Venice Web Communities 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
@@ -65,6 +65,32 @@ public class ConfOperations extends VeniceServlet
} // end getSIGParameter
private static ConferenceContext getConferenceParameter(ServletRequest request, SIGContext sig)
throws ValidationException, DataException, AccessError
{
String str = request.getParameter("conf");
if (str==null)
{ // no conference parameter - bail out now!
logger.error("Conference parameter not specified!");
throw new ValidationException("No conference specified.");
} // end if
try
{ // turn the string into a ConfID, and thence to a ConferenceContext
int confid = Integer.parseInt(str);
return sig.getConferenceContext(confid);
} // end try
catch (NumberFormatException nfe)
{ // error in Integer.parseInt
logger.error("Cannot convert conference parameter '" + str + "'!");
throw new ValidationException("Invalid conference parameter.");
} // end catch
} // end getConferenceParameter
private CreateConferenceDialog makeCreateConferenceDialog() throws ServletException
{
final String desired_name = "CreateConferenceDialog";
@@ -82,6 +108,28 @@ public class ConfOperations extends VeniceServlet
} // end makeCreateConferenceDialog
private static boolean validateNewTopic(ServletRequest request) throws ValidationException
{
boolean is_title_null, is_zp_null;
String foo = request.getParameter("title");
if (foo==null)
throw new ValidationException("Title parameter was not specified.");
is_title_null = (foo.length()==0);
foo = request.getParameter("pseud");
if (foo==null)
throw new ValidationException("Pseud parameter was not specified.");
foo = request.getParameter("pb");
if (foo==null)
throw new ValidationException("Body text was not specified.");
is_zp_null = (foo.length()==0);
return is_title_null || is_zp_null;
} // end validateNewTopic
/*--------------------------------------------------------------------------------
* Overrides from class HttpServlet
*--------------------------------------------------------------------------------
@@ -147,6 +195,42 @@ public class ConfOperations extends VeniceServlet
} // end else
} // end if
else if (cmd.equals("T"))
{ // "T" = "Create topic" (requires conference parameter)
try
{ // start by getting the conference parameter
ConferenceContext conf = getConferenceParameter(request,sig);
// create the New Topic form
NewTopicForm ntf = new NewTopicForm(sig,conf);
ntf.setupNewRequest();
content = ntf;
page_title = "Create New Topic";
} // end try
catch (ValidationException ve)
{ // we can't get the conference parameter
page_title = "Error";
content = new ErrorBox(null,ve.getMessage(),
"sigprofile?sig=" + String.valueOf(sig.getSIGID()));
} // end catch
catch (AccessError ae)
{ // we have some sort of access problem
page_title = "Access Error";
content = new ErrorBox(page_title,ae.getMessage(),
"sigprofile?sig=" + String.valueOf(sig.getSIGID()));
} // end catch
catch (DataException de)
{ // some sort of error in the database
page_title = "Database Error";
content = new ErrorBox(page_title,"Database error finding conference: " + de.getMessage(),
"sigprofile?sig=" + String.valueOf(sig.getSIGID()));
} // end catch
} // end else
else
{ // any unrecognized command jumps us to "conference list"
try
@@ -239,9 +323,9 @@ public class ConfOperations extends VeniceServlet
{ // attempt to create the conference!
ConferenceContext conf = dlg.doDialog(sig);
// success! go back to the conference list
// TODO: want to jump to the conference's "topic list" page if possible
rdat.redirectTo(location);
// success! go to the conference's topic list
rdat.redirectTo("confdisp?sig=" + String.valueOf(sig.getSIGID()) + "&conf="
+ String.valueOf(conf.getConfID()));
return;
} // end try
@@ -284,7 +368,136 @@ public class ConfOperations extends VeniceServlet
} // end else
} // end if
} // end if ("C" command)
else if (cmd.equals("T"))
{ // "T" command = Create New Topic (requires conference parameter)
ConferenceContext conf = null;
try
{ // start by getting the conference parameter
conf = getConferenceParameter(request,sig);
} // end try
catch (ValidationException ve)
{ // we can't get the conference parameter
page_title = "Error";
content = new ErrorBox(null,ve.getMessage(),location);
} // end catch
catch (AccessError ae)
{ // we have some sort of access problem
page_title = "Access Error";
content = new ErrorBox(page_title,ae.getMessage(),location);
} // end catch
catch (DataException de)
{ // some sort of error in the database
page_title = "Database Error";
content = new ErrorBox(page_title,"Database error finding conference: " + de.getMessage(),location);
} // end catch
if (content==null)
{ // determine what to do based on the button pressed
String on_error = "confdisp?sig=" + String.valueOf(sig.getSIGID()) + "&conf="
+ String.valueOf(conf.getConfID());
if (isImageButtonClicked(request,"cancel"))
{ // the user chickened out - go back to the conference display
rdat.redirectTo(on_error);
return;
} // end if
if (isImageButtonClicked(request,"preview"))
{ // generate a preview and redisplay the form
NewTopicForm ntf = new NewTopicForm(sig,conf);
try
{ // do a preview generation
ntf.generatePreview(getVeniceEngine(),request);
if (ntf.isNullRequest())
{ // no title or text specified - this is a "204 No Content" return
rdat.nullResponse();
return;
} // end if
content = ntf;
page_title = "Preview New Topic";
} // end try
catch (ValidationException ve)
{ // something messed up in the preview generation
page_title = "Error";
content = new ErrorBox(null,ve.getMessage(),on_error);
} // end catch
} // end if ("preview" button clicked)
else if (isImageButtonClicked(request,"post"))
{ // OK, let's do a post request!
try
{ // first validate that we've got all the parameters
if (validateNewTopic(request))
{ // this is a null request - send a null response
rdat.nullResponse();
return;
} // end if
// add the new topic!
TopicContext topic = conf.addTopic(request.getParameter("title"),request.getParameter("pseud"),
request.getParameter("pb"));
final String yes = "Y";
if (yes.equals(request.getParameter("attach")))
{ // we need to upload an attachment for this post
// TODO: jump somewhere to upload an attachment
rdat.redirectTo(on_error);
return;
} // end if
else
{ // the post is complete, we need only jump to the topic
// TODO: jump straight to the new topic
rdat.redirectTo(on_error);
return;
} // end else
} // end try
catch (ValidationException ve)
{ // the validation of parameters failed
page_title = "Error";
content = new ErrorBox(null,ve.getMessage(),on_error);
} // end catch
catch (DataException de)
{ // display a database error
page_title = "Database Error";
content = new ErrorBox(page_title,"Database error adding topic: " + de.getMessage(),on_error);
} // end catch
catch (AccessError ae)
{ // some sort of access problem
page_title = "Access Error";
content = new ErrorBox(page_title,ae.getMessage(),on_error);
} // end catch
} // end else if
else
{ // we don't know what button was pressed
page_title = "Internal Error";
logger.error("no known button click on ConfOperations.doPost, cmd=T");
content = new ErrorBox(page_title,"Unknown command button pressed",on_error);
} // end else
} // end if (we got the conference parameter OK)
} // end else if ("T" command)
else
{ // unrecognized command!
page_title = "Internal Error";

View File

@@ -48,6 +48,7 @@ public class Variables
public static final String LOGIN_COOKIE = "VeniceLogin";
private static Category logger = Category.getInstance(Variables.class.getName());
private static Integer engine_gate = new Integer(0);
/*--------------------------------------------------------------------------------
* External static operations
@@ -56,32 +57,36 @@ public class Variables
public static VeniceEngine getVeniceEngine(ServletContext ctxt) throws ServletException
{
Object foo = ctxt.getAttribute(ENGINE_ATTRIBUTE);
if (foo!=null)
return (VeniceEngine)foo;
synchronized(engine_gate)
{ // we must synchronize efforts to access the engine
Object foo = ctxt.getAttribute(ENGINE_ATTRIBUTE);
if (foo!=null)
return (VeniceEngine)foo;
String cfgfile = ctxt.getInitParameter(ENGINE_INIT_PARAM); // get the config file name
logger.info("Initializing Venice engine using config file: " + cfgfile);
String cfgfile = ctxt.getInitParameter(ENGINE_INIT_PARAM); // get the config file name
logger.info("Initializing Venice engine using config file: " + cfgfile);
try
{ // extract the configuration file name and create the engine
VeniceEngine engine = Startup.createEngine(cfgfile);
ctxt.setAttribute(ENGINE_ATTRIBUTE,engine);
return engine;
try
{ // extract the configuration file name and create the engine
VeniceEngine engine = Startup.createEngine(cfgfile);
ctxt.setAttribute(ENGINE_ATTRIBUTE,engine);
return engine;
} // end try
catch (ConfigException e)
{ // configuration failed! post an error message
logger.fatal("Engine configuration failed: " + e.getMessage(),e);
throw new ServletException("Venice engine configuration failed: " + e.getMessage(),e);
} // end try
catch (ConfigException e)
{ // configuration failed! post an error message
logger.fatal("Engine configuration failed: " + e.getMessage(),e);
throw new ServletException("Venice engine configuration failed: " + e.getMessage(),e);
} // end catch
catch (DataException e2)
{ // configuration failed! post an error message
logger.fatal("Engine data load failed: " + e2.getMessage(),e2);
throw new ServletException("Venice engine data load failed: " + e2.getMessage(),e2);
} // end catch
catch (DataException e2)
{ // configuration failed! post an error message
logger.fatal("Engine data load failed: " + e2.getMessage(),e2);
throw new ServletException("Venice engine data load failed: " + e2.getMessage(),e2);
} // end catch
} // end catch
} // end synchronized block
} // end getVeniceEngine

View File

@@ -7,7 +7,7 @@
* 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 Original Code is the Venice Web Communities 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

View File

@@ -0,0 +1,224 @@
/*
* 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 Communities 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.servlets.format;
import java.util.*;
import javax.servlet.*;
import com.silverwrist.venice.ValidationException;
import com.silverwrist.venice.htmlcheck.*;
import com.silverwrist.venice.core.*;
public class NewTopicForm implements JSPRender
{
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
// Attribute name for request attribute
protected static final String ATTR_NAME = "com.silverwrist.venice.content.NewTopicForm";
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private SIGContext sig; // the SIG we're in
private ConferenceContext conf; // the conference being created in
private String topic_name; // the initial topic name
private String pseud; // the pseud to display
private boolean attach; // is there an attachment?
private String post_box; // stuff from the post box
private String preview = null; // the preview & spellchuck data
private int num_errors = 0; // the number of spelling errors we get
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
public NewTopicForm(SIGContext sig, ConferenceContext conf)
{
this.sig = sig;
this.conf = conf;
} // end constrcutor
/*--------------------------------------------------------------------------------
* External static functions
*--------------------------------------------------------------------------------
*/
public static NewTopicForm retrieve(ServletRequest request)
{
return (NewTopicForm)(request.getAttribute(ATTR_NAME));
} // end retrieve
/*--------------------------------------------------------------------------------
* Implementations from interface JSPRender
*--------------------------------------------------------------------------------
*/
public void store(ServletRequest request)
{
request.setAttribute(ATTR_NAME,this);
} // end store
public String getTargetJSPName()
{
return "newtopic.jsp";
} // end getTargetJSPName
/*--------------------------------------------------------------------------------
* External operations
*--------------------------------------------------------------------------------
*/
public void setupNewRequest()
{
topic_name = "";
pseud = conf.getDefaultPseud();
attach = false;
post_box = "";
} // end setupNewRequest
public void generatePreview(VeniceEngine engine, ServletRequest request) throws ValidationException
{
HTMLChecker check;
try
{ // run the data through the HTML Checker
check = engine.getEscapingChecker();
// sanitize the "title" parameter
String foo = request.getParameter("title");
if (foo==null)
throw new ValidationException("Title parameter was not specified.");
check.append(foo);
check.finish();
topic_name = check.getValue();
check.reset();
// sanitize the "pseud" parameter
foo = request.getParameter("pseud");
if (foo==null)
throw new ValidationException("Pseud parameter was not specified.");
check.append(foo);
check.finish();
pseud = check.getValue();
check.reset();
// sanitize the body text itself
foo = request.getParameter("pb");
if (foo==null)
throw new ValidationException("Body text was not specified.");
check.append(foo);
check.finish();
post_box = check.getValue();
// generate the body text preview
check = engine.getPreviewChecker();
check.append(foo);
check.finish();
preview = check.getValue();
num_errors = check.getCounter("spelling");
} // end try
catch (HTMLCheckerException e)
{ // make sure we catch the HTML Checker exceptions
throw new InternalStateError("spurious HTMLCheckerException in generatePreview",e);
} // end catch
// set the "attach" flag to save the checkbox state
final String yes = "Y";
attach = yes.equals(request.getParameter("attach"));
} // end generatePreview
public int getSIGID()
{
return sig.getSIGID();
} // end getSIGID
public int getConfID()
{
return conf.getConfID();
} // end getConfID
public String getConfName()
{
return conf.getName();
} // end getConfName
public String getTopicName()
{
return topic_name;
} // end getTopicName
public String getPseud()
{
return pseud;
} // end getPseud
public boolean getAttachCheck()
{
return attach;
} // end getAttachCheck
public String getPostBoxData()
{
return post_box;
} // end getPostBoxData
public boolean isPreview()
{
return (preview!=null);
} // end isPreview
public String getPreviewData()
{
return preview;
} // end getPreviewData
public int getNumSpellingErrors()
{
return num_errors;
} // end getNumSpellingErrors
public boolean isNullRequest()
{
return ((topic_name.length()==0) || (post_box.length()==0));
} // end isNullRequest
} // end class NewTopicForm

View File

@@ -293,4 +293,10 @@ public class RenderData
} // end getActivityString
public void nullResponse()
{
response.setStatus(response.SC_NO_CONTENT);
} // end nullResponse
} // end class RenderData

View File

@@ -0,0 +1,163 @@
/*
* 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 Communities 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.servlets.format;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import com.silverwrist.venice.core.*;
public class TopicListing implements JSPRender
{
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
// Attribute name for request attribute
protected static final String ATTR_NAME = "com.silverwrist.venice.content.TopicListing";
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private SIGContext sig; // the SIG we're in
private ConferenceContext conf; // the conference being listed
private int view_opt; // the view option used
private int sort_opt; // the sort option used
private List topic_list; // the topic list
private TopicVisitOrder visit_order; // indicates order in which topics are visited
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
public TopicListing(HttpServletRequest request, SIGContext sig, ConferenceContext conf, int view_opt,
int sort_opt) throws DataException, AccessError
{
this.sig = sig;
this.conf = conf;
this.view_opt = view_opt;
this.sort_opt = sort_opt;
this.topic_list = conf.getTopicList(view_opt,sort_opt);
this.visit_order = TopicVisitOrder.initialize(request.getSession(true),conf.getConfID(),this.topic_list);
} // end constructor
/*--------------------------------------------------------------------------------
* External static functions
*--------------------------------------------------------------------------------
*/
public static TopicListing retrieve(ServletRequest request)
{
return (TopicListing)(request.getAttribute(ATTR_NAME));
} // end retrieve
/*--------------------------------------------------------------------------------
* Implementations from interface JSPRender
*--------------------------------------------------------------------------------
*/
public void store(ServletRequest request)
{
request.setAttribute(ATTR_NAME,this);
} // end store
public String getTargetJSPName()
{
return "topics.jsp";
} // end getTargetJSPName
/*--------------------------------------------------------------------------------
* External operations
*--------------------------------------------------------------------------------
*/
public int getSIGID()
{
return sig.getSIGID();
} // end getSIGID
public int getConfID()
{
return conf.getConfID();
} // end getConfID
public String getConfName()
{
return conf.getName();
} // end getConfName
public boolean canDoReadNew()
{
return visit_order.isNext();
} // end canDoReadNew
public boolean canCreateTopic()
{
return conf.canCreateTopic();
} // end canCreateTopic
public boolean canAddToHotlist()
{
return false; // TODO: fix this
} // end canAddToHotlist
public boolean anyTopics()
{
return (topic_list.size()>0);
} // end anyTopics
public int getViewOption()
{
return view_opt;
} // end getViewOption
public boolean isView(int value)
{
return (view_opt==value);
} // end isSort
public boolean isSort(int value)
{
return (sort_opt==value);
} // end isSort
public Iterator getTopicIterator()
{
return topic_list.iterator();
} // end getTopicIterator
} // end class TopicListing

View File

@@ -0,0 +1,172 @@
/*
* 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 Communities 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.servlets.format;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import com.silverwrist.venice.core.*;
public class TopicVisitOrder
{
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
protected static final String ATTRIBUTE = "conf.display.topic.visitorder";
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private int confid;
private short[] topics;
private boolean[] unread;
private int ndx_next;
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
protected TopicVisitOrder(int confid, List topiclist)
{
this.confid = confid;
this.topics = new short[topiclist.size()];
this.unread = new boolean[topiclist.size()];
ndx_next = -1;
for (int i=0; i<topiclist.size(); i++)
{ // fill in topic numbers and unread states
TopicContext t = (TopicContext)(topiclist.get(i));
topics[i] = t.getTopicNumber();
unread[i] = (t.getUnreadMessages()>0);
if (unread[i] && (ndx_next<0))
ndx_next = i;
} // end for
} // end constructor
private int moveNext()
{
int i = ndx_next;
do
{ // move forward to next "unread" topic
if (unread[i])
break;
if (++i==unread.length)
i = 0;
} while (i!=ndx_next); // end do
return i;
} // end moveNext
/*--------------------------------------------------------------------------------
* External static functions
*--------------------------------------------------------------------------------
*/
public static TopicVisitOrder initialize(HttpSession session, int confid, List topic_list)
{
TopicVisitOrder tvo = new TopicVisitOrder(confid,topic_list);
session.setAttribute(ATTRIBUTE,tvo);
return tvo;
} // end initialize
public static TopicVisitOrder retrieve(HttpSession session, int confid)
{
TopicVisitOrder tvo = (TopicVisitOrder)(session.getAttribute(ATTRIBUTE));
if (tvo!=null)
{ // make sure the conference is OK
if (tvo.confid!=confid)
{ // wrong conference - remove this
session.removeAttribute(ATTRIBUTE);
tvo = null;
} // end if
} // end if
return tvo;
} // end retrieve
/*--------------------------------------------------------------------------------
* External operations
*--------------------------------------------------------------------------------
*/
public short getNext()
{
if (ndx_next<0)
return -1;
else if (unread[ndx_next])
return topics[ndx_next];
else
return -1;
} // end getNext
public boolean isNext()
{
if (ndx_next>=0)
return unread[ndx_next];
else
return false;
} // end isNext
public void visit(short topnum)
{
if (ndx_next<0)
return;
if (topics[ndx_next]!=topnum)
{ // go searching for the matching topic number
for (int i=0; i<topics.length; i++)
{ // simple linear search - can't be tricky because the topic numbers might be
// in any order
if (topnum==topics[i])
{ // plant ourselves right there
unread[i] = false;
ndx_next = i;
break;
} // end if
} // end for
} // end if
else
unread[ndx_next] = false;
// move the "next" pointer
ndx_next = moveNext();
} // end visit
} // end class TopicVisitOrder