Implemented partial support for conference hotlists ("Add To Hotlist"
button, Conferences sidebox).
This commit is contained in:
		
							parent
							
								
									bda25d9aa2
								
							
						
					
					
						commit
						7b7e6be996
					
				
							
								
								
									
										16
									
								
								TODO
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								TODO
									
									
									
									
									
								
							@ -12,6 +12,16 @@ Lots!
 | 
			
		||||
- There's no system admin functionality AT ALL.  We need to have this stuff
 | 
			
		||||
  before we go live.  (It plugs into the Administrative SIG features.)
 | 
			
		||||
 | 
			
		||||
- Unimplemented functions on the Top page:
 | 
			
		||||
  Manage SIG list (SIG sidebox)
 | 
			
		||||
  Manage Conference Hotlist (Conference sidebox)
 | 
			
		||||
  Customize Sideboxes
 | 
			
		||||
 | 
			
		||||
- The plan for the "main" part of the Top page is to let a sysadmin put
 | 
			
		||||
  notices there by "publishing" selected conference messages to the front page.
 | 
			
		||||
  We may include a welcome message up top to be displayed if the user's not
 | 
			
		||||
  logged in.
 | 
			
		||||
 | 
			
		||||
- Implement quick e-mail from the user profile display (engine support and
 | 
			
		||||
  UI).
 | 
			
		||||
 | 
			
		||||
@ -23,14 +33,12 @@ Lots!
 | 
			
		||||
 | 
			
		||||
- Slippage during posting is still untested.
 | 
			
		||||
 | 
			
		||||
- Functions still to do on conferencing "topics" page:
 | 
			
		||||
  Add Conference To Hotlist
 | 
			
		||||
 | 
			
		||||
- We need a "manage" button at conference list level so we can use that to
 | 
			
		||||
  manage the ordering of conferences.  This operation should be accessible
 | 
			
		||||
  only to users with "create" privilege on the SIG.
 | 
			
		||||
 | 
			
		||||
- Implement conference hotlist for users.
 | 
			
		||||
- Conference hotlist is now partially implemented, but we need some more work
 | 
			
		||||
  at engine level.
 | 
			
		||||
 | 
			
		||||
- Not everybody likes purple.  Provide a way to change the default colors.
 | 
			
		||||
  Probably via entries in render-config.xml.  Of course, if we go to a
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								doc/tag_new.png
									
									
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								doc/tag_new.png
									
									
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 685 B  | 
@ -1325,6 +1325,8 @@ INSERT INTO contacts (contactid, given_name, family_name, locality, region, pcod
 | 
			
		||||
# new users.
 | 
			
		||||
INSERT INTO sideboxes (uid, boxid, sequence, param)
 | 
			
		||||
    VALUES (1, 1, 100, NULL), (1, 2, 200, NULL);
 | 
			
		||||
INSERT INTO confhotlist (uid, sequence, sigid, confid)
 | 
			
		||||
    VALUES (1, 100, 2, 2);
 | 
			
		||||
 | 
			
		||||
# Add the 'Administrator' user to the users table.
 | 
			
		||||
# (UID = 2, CONTACTID = 2)
 | 
			
		||||
@ -1337,6 +1339,8 @@ INSERT INTO contacts (contactid, given_name, family_name, locality, region, pcod
 | 
			
		||||
# Create the default view for Administrator.
 | 
			
		||||
INSERT INTO sideboxes (uid, boxid, sequence, param)
 | 
			
		||||
    VALUES (2, 1, 100, NULL), (2, 2, 200, NULL);
 | 
			
		||||
INSERT INTO confhotlist (uid, sequence, sigid, confid)
 | 
			
		||||
    VALUES (2, 100, 2, 2);
 | 
			
		||||
 | 
			
		||||
# Add the administration SIG to the SIGs table.
 | 
			
		||||
# (SIGID = 1, CONTACTID = 3)
 | 
			
		||||
@ -1432,6 +1436,8 @@ INSERT INTO contacts (contactid, given_name, family_name, locality, region, pcod
 | 
			
		||||
    VALUES (5, 'Test', 'User', 'Denver', 'CO', '80231', 'US', 'testuser@example.com', 3);
 | 
			
		||||
INSERT INTO sideboxes (uid, boxid, sequence, param)
 | 
			
		||||
    VALUES (3, 1, 100, NULL), (3, 2, 200, NULL);
 | 
			
		||||
INSERT INTO confhotlist (uid, sequence, sigid, confid)
 | 
			
		||||
    VALUES (3, 100, 2, 2);
 | 
			
		||||
INSERT INTO sigmember (sigid, uid, granted_lvl, locked)
 | 
			
		||||
    VALUES (2, 3, 6500, 1);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -141,4 +141,12 @@ public interface ConferenceContext
 | 
			
		||||
 | 
			
		||||
  public abstract boolean canDeleteConference();
 | 
			
		||||
 | 
			
		||||
  public abstract boolean isInHotlist();
 | 
			
		||||
 | 
			
		||||
  public abstract void addToHotlist() throws DataException;
 | 
			
		||||
 | 
			
		||||
  public abstract boolean canAddToHotlist();
 | 
			
		||||
 | 
			
		||||
  public abstract SIGContext getEnclosingSIG();
 | 
			
		||||
 | 
			
		||||
} // end interface ConferenceContext
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										26
									
								
								src/com/silverwrist/venice/core/ConferenceHotlistEntry.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/com/silverwrist/venice/core/ConferenceHotlistEntry.java
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,26 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.core;
 | 
			
		||||
 | 
			
		||||
public interface ConferenceHotlistEntry
 | 
			
		||||
{
 | 
			
		||||
  public abstract ConferenceContext getConference();
 | 
			
		||||
 | 
			
		||||
  public abstract int getSequence();
 | 
			
		||||
 | 
			
		||||
} // end interface ConferenceHotlistEntry
 | 
			
		||||
@ -87,4 +87,6 @@ public interface UserContext extends SearchMode
 | 
			
		||||
 | 
			
		||||
  public abstract List getSideBoxList() throws DataException;
 | 
			
		||||
 | 
			
		||||
  public abstract List getConferenceHotlist() throws DataException;
 | 
			
		||||
 | 
			
		||||
} // end interface UserContext
 | 
			
		||||
 | 
			
		||||
@ -116,6 +116,37 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
 | 
			
		||||
 | 
			
		||||
  } // end class FixSeenHelper
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Static class used to return hot list entries
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  static class MyHotlist implements ConferenceHotlistEntry
 | 
			
		||||
  {
 | 
			
		||||
    private ConferenceContext conf;
 | 
			
		||||
    private int seq;
 | 
			
		||||
 | 
			
		||||
    MyHotlist(ConferenceContext conf, int seq)
 | 
			
		||||
    {
 | 
			
		||||
      this.conf = conf;
 | 
			
		||||
      this.seq = seq;
 | 
			
		||||
 | 
			
		||||
    } // end constructor
 | 
			
		||||
 | 
			
		||||
    public ConferenceContext getConference()
 | 
			
		||||
    {
 | 
			
		||||
      return conf;
 | 
			
		||||
 | 
			
		||||
    } // end getConference
 | 
			
		||||
 | 
			
		||||
    public int getSequence()
 | 
			
		||||
    {
 | 
			
		||||
      return seq;
 | 
			
		||||
 | 
			
		||||
    } // end getSequence
 | 
			
		||||
 | 
			
		||||
  } // end class MyHotlist
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Static data members
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
@ -515,8 +546,7 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
 | 
			
		||||
    if (post>create)
 | 
			
		||||
    { // Post level should be no greater than Create
 | 
			
		||||
      if (logger.isDebugEnabled())
 | 
			
		||||
	logger.debug("Post level (" + String.valueOf(post) + ") was greater than create level ("
 | 
			
		||||
		     + String.valueOf(create) + "), correcting");
 | 
			
		||||
	logger.debug("Post level (" + post + ") was greater than create level (" + create + "), correcting");
 | 
			
		||||
      post = create;
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
@ -524,8 +554,7 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
 | 
			
		||||
    if (read>post)
 | 
			
		||||
    { // Read level should be no greater than Post
 | 
			
		||||
      if (logger.isDebugEnabled())
 | 
			
		||||
	logger.debug("Read level (" + String.valueOf(read) + ") was greater than post level ("
 | 
			
		||||
		     + String.valueOf(post) + "), correcting");
 | 
			
		||||
	logger.debug("Read level (" + read + ") was greater than post level (" + post + "), correcting");
 | 
			
		||||
      read = post;
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
@ -533,8 +562,8 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
 | 
			
		||||
    if (change>delete)
 | 
			
		||||
    { // Change level should be no greater than Delete
 | 
			
		||||
      if (logger.isDebugEnabled())
 | 
			
		||||
	logger.debug("Change level (" + String.valueOf(change) + ") was greater than delete level ("
 | 
			
		||||
		     + String.valueOf(delete) + "), correcting");
 | 
			
		||||
	logger.debug("Change level (" + change + ") was greater than delete level (" + delete
 | 
			
		||||
		     + "), correcting");
 | 
			
		||||
      change = delete;
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
@ -542,8 +571,7 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
 | 
			
		||||
    if (nuke>delete)
 | 
			
		||||
    { // Nuke level should be no greater than Delete
 | 
			
		||||
      if (logger.isDebugEnabled())
 | 
			
		||||
	logger.debug("Nuke level (" + String.valueOf(nuke) + ") was greater than delete level ("
 | 
			
		||||
		     + String.valueOf(delete) + "), correcting");
 | 
			
		||||
	logger.debug("Nuke level (" + nuke + ") was greater than delete level (" + delete + "), correcting");
 | 
			
		||||
      nuke = delete;
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
@ -551,8 +579,7 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
 | 
			
		||||
    if (hide>nuke)
 | 
			
		||||
    { // Hide level should be no greater than Nuke
 | 
			
		||||
      if (logger.isDebugEnabled())
 | 
			
		||||
	logger.debug("Hide level (" + String.valueOf(hide) + ") was greater than nuke level ("
 | 
			
		||||
		     + String.valueOf(nuke) + "), correcting");
 | 
			
		||||
	logger.debug("Hide level (" + hide + ") was greater than nuke level (" + nuke + "), correcting");
 | 
			
		||||
      hide = nuke;
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
@ -791,7 +818,7 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
 | 
			
		||||
 | 
			
		||||
  public boolean anyUnread()
 | 
			
		||||
  {
 | 
			
		||||
    if (deleted)
 | 
			
		||||
    if (deleted || sig.userIsAnonymous())
 | 
			
		||||
      return false;
 | 
			
		||||
    Connection conn = null;      // pooled database connection
 | 
			
		||||
 | 
			
		||||
@ -1228,6 +1255,110 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
 | 
			
		||||
 | 
			
		||||
  } // end canDeleteConference
 | 
			
		||||
 | 
			
		||||
  public boolean isInHotlist()
 | 
			
		||||
  {
 | 
			
		||||
    Connection conn = null;
 | 
			
		||||
 | 
			
		||||
    try
 | 
			
		||||
    { // retrieve a connection from the datapool
 | 
			
		||||
      conn = datapool.getConnection();
 | 
			
		||||
      Statement stmt = conn.createStatement();
 | 
			
		||||
 | 
			
		||||
      // do a quickie query
 | 
			
		||||
      StringBuffer sql = new StringBuffer("SELECT sequence FROM confhotlist WHERE uid = ");
 | 
			
		||||
      sql.append(sig.realUID()).append(" AND sigid = ").append(sig.realSIGID()).append(" AND confid = ");
 | 
			
		||||
      sql.append(confid).append(';');
 | 
			
		||||
      ResultSet rs = stmt.executeQuery(sql.toString());
 | 
			
		||||
      return rs.next();
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (SQLException e)
 | 
			
		||||
    { // this becomes a DataException
 | 
			
		||||
      logger.error("DB error checking hotlist: " + e.getMessage(),e);
 | 
			
		||||
      return false;
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
    finally
 | 
			
		||||
    { // make sure we release the connection before we go
 | 
			
		||||
      if (conn!=null)
 | 
			
		||||
	datapool.releaseConnection(conn);
 | 
			
		||||
 | 
			
		||||
    } // end finally
 | 
			
		||||
 | 
			
		||||
  } // end isInHotlist
 | 
			
		||||
 | 
			
		||||
  public void addToHotlist() throws DataException
 | 
			
		||||
  {
 | 
			
		||||
    Connection conn = null;
 | 
			
		||||
 | 
			
		||||
    try
 | 
			
		||||
    { // retrieve a connection from the datapool
 | 
			
		||||
      conn = datapool.getConnection();
 | 
			
		||||
      Statement stmt = conn.createStatement();
 | 
			
		||||
 | 
			
		||||
      stmt.executeUpdate("LOCK TABLES confhotlist WRITE;");
 | 
			
		||||
      try
 | 
			
		||||
      { // do a quickie query to see if we're already in the hotlist
 | 
			
		||||
	StringBuffer sql = new StringBuffer("SELECT sequence FROM confhotlist WHERE uid = ");
 | 
			
		||||
	sql.append(sig.realUID()).append(" AND sigid = ").append(sig.realSIGID()).append(" AND confid = ");
 | 
			
		||||
	sql.append(confid).append(';');
 | 
			
		||||
	ResultSet rs = stmt.executeQuery(sql.toString());
 | 
			
		||||
	if (rs.next())
 | 
			
		||||
	  return;  // already in hotlist - this is a no-op
 | 
			
		||||
 | 
			
		||||
	// find a sequence number for the new entry
 | 
			
		||||
	sql.setLength(0);
 | 
			
		||||
	sql.append("SELECT MAX(sequence) FROM confhotlist WHERE uid = ").append(sig.realUID()).append(';');
 | 
			
		||||
	rs = stmt.executeQuery(sql.toString());
 | 
			
		||||
	if (!(rs.next()))
 | 
			
		||||
	  throw new InternalStateError("bogus query result on addToHotlist");
 | 
			
		||||
	int new_sequence = rs.getInt(1) + 100;
 | 
			
		||||
 | 
			
		||||
	// add the new record
 | 
			
		||||
	sql.setLength(0);
 | 
			
		||||
	sql.append("INSERT INTO confhotlist (uid, sequence, sigid, confid) VALUES (").append(sig.realUID());
 | 
			
		||||
	sql.append(", ").append(new_sequence).append(", ").append(sig.realSIGID()).append(", ");
 | 
			
		||||
	sql.append(confid).append(");");
 | 
			
		||||
	stmt.executeUpdate(sql.toString());
 | 
			
		||||
 | 
			
		||||
      } // end try
 | 
			
		||||
      finally
 | 
			
		||||
      { // make sure the table is unlocked before we go
 | 
			
		||||
	Statement ulk_stmt = conn.createStatement();
 | 
			
		||||
	ulk_stmt.executeUpdate("UNLOCK TABLES;");
 | 
			
		||||
 | 
			
		||||
      } // end finally
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (SQLException e)
 | 
			
		||||
    { // this becomes a DataException
 | 
			
		||||
      logger.error("DB error adding to hotlist: " + e.getMessage(),e);
 | 
			
		||||
      throw new DataException("error adding to hotlist: " + e.getMessage(),e);
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
    finally
 | 
			
		||||
    { // make sure we release the connection before we go
 | 
			
		||||
      if (conn!=null)
 | 
			
		||||
	datapool.releaseConnection(conn);
 | 
			
		||||
 | 
			
		||||
    } // end finally
 | 
			
		||||
 | 
			
		||||
  } // end addToHotList
 | 
			
		||||
 | 
			
		||||
  public boolean canAddToHotlist()
 | 
			
		||||
  {
 | 
			
		||||
    if (sig.userIsAnonymous())
 | 
			
		||||
      return false;
 | 
			
		||||
    return !(isInHotlist());
 | 
			
		||||
 | 
			
		||||
  } // end canAddToHotlist
 | 
			
		||||
 | 
			
		||||
  public SIGContext getEnclosingSIG()
 | 
			
		||||
  {
 | 
			
		||||
    return sig.selfSIG();
 | 
			
		||||
 | 
			
		||||
  } // end getEnclosingSIG
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Implementations from interface UserBackend
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
@ -1268,6 +1399,12 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  public SIGContext selfSIG()
 | 
			
		||||
  {
 | 
			
		||||
    return sig.selfSIG();
 | 
			
		||||
 | 
			
		||||
  } // end selfsig;
 | 
			
		||||
 | 
			
		||||
  public int realSIGID()
 | 
			
		||||
  {
 | 
			
		||||
    return sig.realSIGID();
 | 
			
		||||
@ -1468,8 +1605,7 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
 | 
			
		||||
  static List getSIGConferences(EngineBackend engine, SIGBackend sig, DataPool datapool) throws DataException
 | 
			
		||||
  {
 | 
			
		||||
    if (logger.isDebugEnabled())
 | 
			
		||||
      logger.debug("getSIGConferences for SIG # " + String.valueOf(sig.realSIGID()) + ", user #"
 | 
			
		||||
		   + String.valueOf(sig.realUID()));
 | 
			
		||||
      logger.debug("getSIGConferences for SIG # " + sig.realSIGID() + ", user #" + sig.realUID());
 | 
			
		||||
    Vector rc = new Vector();    // return from this function
 | 
			
		||||
    Connection conn = null;      // pooled database connection
 | 
			
		||||
 | 
			
		||||
@ -1529,8 +1665,7 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
 | 
			
		||||
					 int confid) throws DataException
 | 
			
		||||
  {
 | 
			
		||||
    if (logger.isDebugEnabled())
 | 
			
		||||
      logger.debug("getConference(#" + String.valueOf(confid) + ") for SIG # "
 | 
			
		||||
		   + String.valueOf(sig.realSIGID()) + ", user #" + String.valueOf(sig.realUID()));
 | 
			
		||||
      logger.debug("getConference(#" + confid + ") for SIG # " + sig.realSIGID() + ", user #" + sig.realUID());
 | 
			
		||||
 | 
			
		||||
    Connection conn = null;      // pooled database connection
 | 
			
		||||
 | 
			
		||||
@ -1553,8 +1688,7 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
 | 
			
		||||
      // Run that monster query!
 | 
			
		||||
      ResultSet rs = stmt.executeQuery(sql.toString());
 | 
			
		||||
      if (!(rs.next()))
 | 
			
		||||
	throw new DataException("conference ID#" + String.valueOf(confid) + " not found in SIG#"
 | 
			
		||||
				+ String.valueOf(sig.realSIGID()));
 | 
			
		||||
	throw new DataException("conference ID#" + confid + " not found in SIG#" + sig.realSIGID());
 | 
			
		||||
 | 
			
		||||
      // pass back the new object
 | 
			
		||||
      return new ConferenceUserContextImpl(engine,sig,datapool,confid,rs.getString(2),
 | 
			
		||||
@ -1581,8 +1715,8 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
 | 
			
		||||
					 String alias) throws DataException
 | 
			
		||||
  {
 | 
			
		||||
    if (logger.isDebugEnabled())
 | 
			
		||||
      logger.debug("getConference(\"" + alias + "\") for SIG # " + String.valueOf(sig.realSIGID())
 | 
			
		||||
		   + ", user #" + String.valueOf(sig.realUID()));
 | 
			
		||||
      logger.debug("getConference(\"" + alias + "\") for SIG # " + sig.realSIGID() + ", user #"
 | 
			
		||||
		   + sig.realUID());
 | 
			
		||||
 | 
			
		||||
    Connection conn = null;      // pooled database connection
 | 
			
		||||
 | 
			
		||||
@ -1607,8 +1741,7 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
 | 
			
		||||
      // Run that monster query!
 | 
			
		||||
      ResultSet rs = stmt.executeQuery(sql.toString());
 | 
			
		||||
      if (!(rs.next()))
 | 
			
		||||
	throw new DataException("conference \"" + alias + "\" not found in SIG#"
 | 
			
		||||
				+ String.valueOf(sig.realSIGID()));
 | 
			
		||||
	throw new DataException("conference \"" + alias + "\" not found in SIG#" + sig.realSIGID());
 | 
			
		||||
 | 
			
		||||
      // pass back the new object
 | 
			
		||||
      return new ConferenceUserContextImpl(engine,sig,datapool,rs.getInt(1),rs.getString(3),rs.getString(4),
 | 
			
		||||
@ -1630,4 +1763,77 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
 | 
			
		||||
 | 
			
		||||
  } // end getConference
 | 
			
		||||
 | 
			
		||||
  static List getUserHotlist(EngineBackend engine, UserBackend user, DataPool datapool) throws DataException
 | 
			
		||||
  {
 | 
			
		||||
    if (logger.isDebugEnabled())
 | 
			
		||||
      logger.debug("getUserHotlist for user #" + user.realUID());
 | 
			
		||||
 | 
			
		||||
    Connection conn = null;      // pooled database connection
 | 
			
		||||
    Vector rc = new Vector();    // return from this function
 | 
			
		||||
 | 
			
		||||
    try
 | 
			
		||||
    { // get a database connection
 | 
			
		||||
      conn = datapool.getConnection();
 | 
			
		||||
      Statement stmt = conn.createStatement();
 | 
			
		||||
 | 
			
		||||
      // Build a monster query!  We pull the SIGID and ConfID entries from the confhotlist table,
 | 
			
		||||
      // but we need to pull in "confs" and "confmember" (left joined) to get enough data to create
 | 
			
		||||
      // a ConferenceUserContextImpl object.
 | 
			
		||||
      StringBuffer sql =
 | 
			
		||||
	new StringBuffer("SELECT h.sigid, h.confid, c.name, c.descr, c.createdate, s.granted_lvl, "
 | 
			
		||||
			 + "f.granted_lvl, h.sequence FROM confhotlist h, sigtoconf s, confs c "
 | 
			
		||||
			 + "LEFT JOIN confmember f ON h.confid = f.confid AND h.uid = f.uid "
 | 
			
		||||
			 + "WHERE h.confid = s.confid AND c.confid = h.confid AND h.uid = ");
 | 
			
		||||
      sql.append(user.realUID()).append(" ORDER BY h.sequence ASC;");
 | 
			
		||||
      if (logger.isDebugEnabled())
 | 
			
		||||
	logger.debug("SQL: " + sql.toString());
 | 
			
		||||
 | 
			
		||||
      // Run that puppy!
 | 
			
		||||
      ResultSet rs = stmt.executeQuery(sql.toString());
 | 
			
		||||
 | 
			
		||||
      // Create some temporary data structures to assist us in building the return list.
 | 
			
		||||
      HashMap sig_backend_cache = new HashMap();
 | 
			
		||||
 | 
			
		||||
      while (rs.next())
 | 
			
		||||
      { // retrieve the sigid from the resultset first
 | 
			
		||||
	Integer sigid = new Integer(rs.getInt(1));
 | 
			
		||||
 | 
			
		||||
	// we need a SIG backend for our conference, so make sure we have one
 | 
			
		||||
	SIGBackend sig = (SIGBackend)(sig_backend_cache.get(sigid));
 | 
			
		||||
	if (sig==null)
 | 
			
		||||
	{ // get it and make sure it's in the cache for next time
 | 
			
		||||
	  sig = SIGUserContextImpl.getSIGBackend(engine,user,datapool,conn,sigid.intValue());
 | 
			
		||||
	  sig_backend_cache.put(sigid,sig);
 | 
			
		||||
 | 
			
		||||
	} // end if
 | 
			
		||||
 | 
			
		||||
	// make the new ConferenceContext
 | 
			
		||||
	ConferenceContext conf =
 | 
			
		||||
	    new ConferenceUserContextImpl(engine,sig,datapool,rs.getInt(2),rs.getString(3),rs.getString(4),
 | 
			
		||||
					  SQLUtil.getFullDateTime(rs,5),rs.getInt(6),rs.getInt(7),conn);
 | 
			
		||||
 | 
			
		||||
	// and create the actual return value
 | 
			
		||||
	ConferenceHotlistEntry hle = new MyHotlist(conf,rs.getInt(8));
 | 
			
		||||
	rc.add(hle);
 | 
			
		||||
 | 
			
		||||
      } // end while
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (SQLException e)
 | 
			
		||||
    { // turn SQLException into data exception
 | 
			
		||||
      logger.error("DB error reading hotlist entries: " + e.getMessage(),e);
 | 
			
		||||
      throw new DataException("unable to retrieve hotlist information: " + e.getMessage(),e);
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
    finally
 | 
			
		||||
    { // make sure we release the connection before we go
 | 
			
		||||
      if (conn!=null)
 | 
			
		||||
	datapool.releaseConnection(conn);
 | 
			
		||||
 | 
			
		||||
    } // end finally
 | 
			
		||||
 | 
			
		||||
    return new ReadOnlyVector(rc);
 | 
			
		||||
 | 
			
		||||
  } // end getUserHotlist
 | 
			
		||||
 | 
			
		||||
} // end class ConferenceUserContextImpl
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
@ -18,9 +18,12 @@
 | 
			
		||||
package com.silverwrist.venice.core.impl;
 | 
			
		||||
 | 
			
		||||
import com.silverwrist.venice.core.DataException;
 | 
			
		||||
import com.silverwrist.venice.core.SIGContext;
 | 
			
		||||
 | 
			
		||||
public interface SIGBackend extends UserBackend
 | 
			
		||||
{
 | 
			
		||||
  public abstract SIGContext selfSIG();
 | 
			
		||||
 | 
			
		||||
  public abstract int realSIGID();
 | 
			
		||||
 | 
			
		||||
  public abstract boolean userHideHiddenConferences();
 | 
			
		||||
 | 
			
		||||
@ -229,6 +229,38 @@ class SIGUserContextImpl implements SIGContext, SIGBackend
 | 
			
		||||
 | 
			
		||||
  } // end testConferenceAccess
 | 
			
		||||
 | 
			
		||||
  private static SIGUserContextImpl getSIGPrivate(EngineBackend engine, UserBackend user, DataPool datapool,
 | 
			
		||||
						  Connection conn, int sigid) throws DataException
 | 
			
		||||
  {
 | 
			
		||||
    try
 | 
			
		||||
    { // create the query to find the SIG in the table
 | 
			
		||||
      Statement stmt = conn.createStatement();
 | 
			
		||||
      StringBuffer sql = new StringBuffer("SELECT signame, alias FROM sigs WHERE sigid = ");
 | 
			
		||||
      sql.append(sigid).append(';');
 | 
			
		||||
      ResultSet rs = stmt.executeQuery(sql.toString());
 | 
			
		||||
      if (!(rs.next()))
 | 
			
		||||
      { // the SIG entry was not found
 | 
			
		||||
	logger.error("SIG " + String.valueOf(sigid) + " not found in database");
 | 
			
		||||
	throw new DataException("SIG #" + String.valueOf(sigid) + " was not found in the database.");
 | 
			
		||||
 | 
			
		||||
      } // end if
 | 
			
		||||
 | 
			
		||||
      // initialize the object and check membership info
 | 
			
		||||
      SIGUserContextImpl sc = new SIGUserContextImpl(engine,user,datapool,sigid,rs.getString("signame"),
 | 
			
		||||
						     rs.getString("alias"));
 | 
			
		||||
      sc.checkMembership(conn);
 | 
			
		||||
      return sc;
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (SQLException e)
 | 
			
		||||
    { // turn SQLException into data exception
 | 
			
		||||
      logger.error("DB error reading SIG entry: " + e.getMessage(),e);
 | 
			
		||||
      throw new DataException("unable to retrieve SIG information: " + e.getMessage(),e);
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
 | 
			
		||||
  } // end getSIGPrivate
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Implementations from class SIGContext
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
@ -1132,6 +1164,12 @@ class SIGUserContextImpl implements SIGContext, SIGBackend
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  public SIGContext selfSIG()
 | 
			
		||||
  {
 | 
			
		||||
    return this;
 | 
			
		||||
 | 
			
		||||
  } // end selfsig;
 | 
			
		||||
 | 
			
		||||
  public int realSIGID()
 | 
			
		||||
  {
 | 
			
		||||
    return sigid;
 | 
			
		||||
@ -1248,23 +1286,8 @@ class SIGUserContextImpl implements SIGContext, SIGBackend
 | 
			
		||||
    { // get a database connection
 | 
			
		||||
      conn = datapool.getConnection();
 | 
			
		||||
 | 
			
		||||
      // create the query to find the SIG in the table
 | 
			
		||||
      Statement stmt = conn.createStatement();
 | 
			
		||||
      StringBuffer sql = new StringBuffer("SELECT signame, alias FROM sigs WHERE sigid = ");
 | 
			
		||||
      sql.append(sigid).append(';');
 | 
			
		||||
      ResultSet rs = stmt.executeQuery(sql.toString());
 | 
			
		||||
      if (!(rs.next()))
 | 
			
		||||
      { // the SIG entry was not found
 | 
			
		||||
	logger.error("SIG " + String.valueOf(sigid) + " not found in database");
 | 
			
		||||
	throw new DataException("SIG #" + String.valueOf(sigid) + " was not found in the database.");
 | 
			
		||||
 | 
			
		||||
      } // end if
 | 
			
		||||
 | 
			
		||||
      // initialize the object and check membership info
 | 
			
		||||
      SIGUserContextImpl sc = new SIGUserContextImpl(engine,user,datapool,sigid,rs.getString("signame"),
 | 
			
		||||
						     rs.getString("alias"));
 | 
			
		||||
      sc.checkMembership(conn);
 | 
			
		||||
      return sc;
 | 
			
		||||
      // return the SIG we want
 | 
			
		||||
      return getSIGPrivate(engine,user,datapool,conn,sigid);
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (SQLException e)
 | 
			
		||||
@ -1325,6 +1348,13 @@ class SIGUserContextImpl implements SIGContext, SIGBackend
 | 
			
		||||
 | 
			
		||||
  } // end getSIGContext
 | 
			
		||||
 | 
			
		||||
  static SIGBackend getSIGBackend(EngineBackend engine, UserBackend user, DataPool datapool, Connection conn,
 | 
			
		||||
				  int sigid) throws DataException
 | 
			
		||||
  {
 | 
			
		||||
    return getSIGPrivate(engine,user,datapool,conn,sigid);
 | 
			
		||||
 | 
			
		||||
  } // end getSIGBackend
 | 
			
		||||
 | 
			
		||||
  static List searchForSIGs(EngineBackend engine, UserBackend user, DataPool datapool, int field,
 | 
			
		||||
			    int mode, String term, int offset, int count) throws DataException
 | 
			
		||||
  {
 | 
			
		||||
 | 
			
		||||
@ -862,6 +862,12 @@ class UserContextImpl implements UserContext, UserBackend
 | 
			
		||||
 | 
			
		||||
  } // end getSideBoxList
 | 
			
		||||
 | 
			
		||||
  public List getConferenceHotlist() throws DataException
 | 
			
		||||
  {
 | 
			
		||||
    return ConferenceUserContextImpl.getUserHotlist(engine,this,datapool);
 | 
			
		||||
 | 
			
		||||
  } // end getConferenceHotlist
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Implementations from interface UserBackend
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
@ -874,7 +874,8 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
 | 
			
		||||
    { // look to see if the user name is already present
 | 
			
		||||
      conn = datapool.getConnection();
 | 
			
		||||
      Statement stmt = conn.createStatement();
 | 
			
		||||
      stmt.executeUpdate("LOCK TABLES users WRITE, userprefs WRITE, sigmember WRITE, sideboxes WRITE;");
 | 
			
		||||
      stmt.executeUpdate("LOCK TABLES users WRITE, userprefs WRITE, sigmember WRITE, sideboxes WRITE, "
 | 
			
		||||
			 + "confhotlist WRITE;");
 | 
			
		||||
      try
 | 
			
		||||
      { // make sure the user name isn't there already
 | 
			
		||||
	ResultSet rs = stmt.executeQuery("SELECT uid FROM users WHERE username = '" + encode_username + "';");
 | 
			
		||||
@ -967,6 +968,31 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
 | 
			
		||||
	if (logger.isDebugEnabled())
 | 
			
		||||
	  logger.debug("...loaded default sidebox config");
 | 
			
		||||
 | 
			
		||||
	// get the hotlist configuration for this user
 | 
			
		||||
	rs = stmt.executeQuery("SELECT confhotlist.sequence, confhotlist.sigid, confhotlist.confid FROM "
 | 
			
		||||
		             + "confhotlist, users WHERE confhotlist.uid = users.uid AND users.is_anon = 1;");
 | 
			
		||||
	sql.setLength(0);
 | 
			
		||||
	while (rs.next())
 | 
			
		||||
	{ // set up to insert into the confhotlist table
 | 
			
		||||
	  if (sql.length()==0)
 | 
			
		||||
	    sql.append("INSERT INTO confhotlist (uid, sequence, sigid, confid) VALUES ");
 | 
			
		||||
	  else
 | 
			
		||||
	    sql.append(", ");
 | 
			
		||||
	  sql.append('(').append(new_uid).append(", ").append(rs.getInt(1)).append(", ").append(rs.getInt(2));
 | 
			
		||||
	  sql.append(", ").append(rs.getInt(3)).append(')');
 | 
			
		||||
 | 
			
		||||
	} // end while
 | 
			
		||||
 | 
			
		||||
	if (sql.length()>0)
 | 
			
		||||
	{ // execute the big update
 | 
			
		||||
	  sql.append(';');
 | 
			
		||||
	  stmt.executeUpdate(sql.toString());
 | 
			
		||||
 | 
			
		||||
	} // end if
 | 
			
		||||
 | 
			
		||||
	if (logger.isDebugEnabled())
 | 
			
		||||
	  logger.debug("...loaded default hotlist config");
 | 
			
		||||
 | 
			
		||||
      } // end try
 | 
			
		||||
      finally
 | 
			
		||||
      { // make sure the tables get unlocked before we go
 | 
			
		||||
 | 
			
		||||
@ -326,6 +326,28 @@ public class ConfOperations extends VeniceServlet
 | 
			
		||||
 | 
			
		||||
    } // end if ("M" command)
 | 
			
		||||
 | 
			
		||||
    if (cmd.equals("H"))
 | 
			
		||||
    { // "H" = "Add Conference To Hotlist" (requires conference parameter)
 | 
			
		||||
      ConferenceContext conf = getConferenceParameter(request,sig,true,on_error);
 | 
			
		||||
      on_error = "confdisp?sig=" + sig.getSIGID() + "&conf=" + conf.getConfID();
 | 
			
		||||
 | 
			
		||||
      try
 | 
			
		||||
      { // add to the hotlist
 | 
			
		||||
	conf.addToHotlist();
 | 
			
		||||
 | 
			
		||||
	// and trap back to the conference display
 | 
			
		||||
	throw new RedirectResult(on_error);
 | 
			
		||||
 | 
			
		||||
      } // end try
 | 
			
		||||
      catch (DataException de)
 | 
			
		||||
      { // something wrong in the database
 | 
			
		||||
	return new ErrorBox("Database Error","Database error adding to hotlist: " + de.getMessage(),
 | 
			
		||||
			    on_error);
 | 
			
		||||
 | 
			
		||||
      } // end catch
 | 
			
		||||
 | 
			
		||||
    } // end if ("H" command)
 | 
			
		||||
 | 
			
		||||
    if (cmd.equals("DEL"))
 | 
			
		||||
    { // "DEL" = "Delete Conference (requires conference parameter)
 | 
			
		||||
      ConferenceContext conf = getConferenceParameter(request,sig,true,on_error);
 | 
			
		||||
 | 
			
		||||
@ -19,6 +19,7 @@ package com.silverwrist.venice.servlets.format;
 | 
			
		||||
 | 
			
		||||
import java.io.*;
 | 
			
		||||
import java.util.*;
 | 
			
		||||
import com.silverwrist.util.StringUtil;
 | 
			
		||||
import com.silverwrist.venice.core.*;
 | 
			
		||||
 | 
			
		||||
public class SideBoxConferences implements ContentRender
 | 
			
		||||
@ -29,15 +30,17 @@ public class SideBoxConferences implements ContentRender
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  private UserContext uc;
 | 
			
		||||
  private List hotlist;
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Constructor
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  public SideBoxConferences(UserContext uc, String parameter)
 | 
			
		||||
  public SideBoxConferences(UserContext uc, String parameter) throws DataException
 | 
			
		||||
  {
 | 
			
		||||
    this.uc = uc;
 | 
			
		||||
    this.hotlist = uc.getConferenceHotlist();
 | 
			
		||||
 | 
			
		||||
  } // end constructor
 | 
			
		||||
 | 
			
		||||
@ -62,14 +65,34 @@ public class SideBoxConferences implements ContentRender
 | 
			
		||||
 | 
			
		||||
  public void renderHere(Writer out, RenderData rdat) throws IOException
 | 
			
		||||
  {
 | 
			
		||||
    /* BEGIN TEMP */
 | 
			
		||||
    out.write("<FONT FACE=\"Arial, Helvetica\" SIZE=2><UL>\n");
 | 
			
		||||
    out.write("<LI>BOFH (Benevolent Dictators)</LI>\n");
 | 
			
		||||
    out.write("<LI>Playground (Electric Minds)</LI>\n");
 | 
			
		||||
    out.write("<LI>Commons (Electric Minds)</LI>\n");
 | 
			
		||||
    out.write("<LI>Top Ten Lists (Pamela's Lounge)</LI>\n");
 | 
			
		||||
    out.write("</UL></FONT>\n");
 | 
			
		||||
    /* END TEMP */
 | 
			
		||||
    out.write(rdat.getStdFontTag(null,2) + "\n");
 | 
			
		||||
    if (hotlist.size()>0)
 | 
			
		||||
    { // display the list of conferences
 | 
			
		||||
      out.write("<TABLE ALIGN=CENTER BORDER=0 CELLPADDING=0 CELLSPACING=2>\n");
 | 
			
		||||
      Iterator it = hotlist.iterator();
 | 
			
		||||
      while (it.hasNext())
 | 
			
		||||
      { // display the names of the conferences and SIGs one by one
 | 
			
		||||
	ConferenceHotlistEntry hle = (ConferenceHotlistEntry)(it.next());
 | 
			
		||||
	ConferenceContext conf = hle.getConference();
 | 
			
		||||
	String href = "confdisp?sig=" + conf.getEnclosingSIG().getSIGID() + "&conf=" + conf.getConfID();
 | 
			
		||||
	out.write("<TR VALIGN=MIDDLE>\n<TD ALIGN=CENTER WIDTH=14><IMG SRC=\""
 | 
			
		||||
		  + rdat.getFullImagePath("purple-ball.gif")
 | 
			
		||||
		  + "\" ALT=\"*\" WIDTH=14 HEIGHT=14 BORDER=0></TD>\n");
 | 
			
		||||
	out.write("<TD ALIGN=LEFT>\n" + rdat.getStdFontTag(null,2) + "<B><A HREF=\""
 | 
			
		||||
		  + rdat.getEncodedServletPath(href) + "\">" + StringUtil.encodeHTML(conf.getName())
 | 
			
		||||
		  + "</A></B> (" + StringUtil.encodeHTML(conf.getEnclosingSIG().getName()) + ")</FONT>\n");
 | 
			
		||||
	if (conf.anyUnread())
 | 
			
		||||
	  out.write(" <IMG SRC=\"" + rdat.getFullImagePath("tag_new.gif")
 | 
			
		||||
		    + "\" ALT=\"New!\" BORDER=0 WIDTH=40 HEIGHT=20>\n");
 | 
			
		||||
	out.write("</TD>\n</TR>\n");
 | 
			
		||||
 | 
			
		||||
      } // end while
 | 
			
		||||
 | 
			
		||||
      out.write("</TABLE>\n");
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
    else
 | 
			
		||||
      out.write(rdat.getStdFontTag(null,2) + "<EM>You have no conferences in your hotlist.</EM></FONT>\n");
 | 
			
		||||
 | 
			
		||||
    // write the link at the end
 | 
			
		||||
    out.write("<P>" + rdat.getStdFontTag(null,1) + "<B>[ <A HREF=\"" + rdat.getEncodedServletPath("TODO")
 | 
			
		||||
 | 
			
		||||
@ -154,7 +154,7 @@ public class TopicListing implements JSPRender
 | 
			
		||||
 | 
			
		||||
  public boolean canAddToHotlist()
 | 
			
		||||
  {
 | 
			
		||||
    return false;  // TODO: fix this
 | 
			
		||||
    return conf.canAddToHotlist();
 | 
			
		||||
 | 
			
		||||
  } // end canAddToHotlist
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -44,12 +44,13 @@
 | 
			
		||||
       SRC="<%= rdat.getFullImagePath("bn_read_new.gif") %>" ALT="Read New" WIDTH=80 HEIGHT=24
 | 
			
		||||
       BORDER=0></A> 
 | 
			
		||||
    <% } // end if %>
 | 
			
		||||
    <A HREF="<%= "confops?" + data.getLocator() + "&cmd=Q" %>"><IMG
 | 
			
		||||
    <A HREF="<%= rdat.getEncodedServletPath("confops?" + data.getLocator() + "&cmd=Q") %>"><IMG
 | 
			
		||||
       SRC="<%= rdat.getFullImagePath("bn_manage.gif") %>" ALT="Manage" WIDTH=80 HEIGHT=24
 | 
			
		||||
       BORDER=0></A> 
 | 
			
		||||
    <% if (data.canAddToHotlist()) { %>
 | 
			
		||||
      <A HREF="TODO"><IMG SRC="<%= rdat.getFullImagePath("bn_add_to_hotlist.gif") %>"
 | 
			
		||||
       ALT="Add to HotList" WIDTH=80 HEIGHT=24 BORDER=0></A> 
 | 
			
		||||
      <A HREF="<%= rdat.getEncodedServletPath("confops?" + data.getLocator() + "&cmd=H") %>"><IMG
 | 
			
		||||
         SRC="<%= rdat.getFullImagePath("bn_add_to_hotlist.gif") %>" ALT="Add to HotList" WIDTH=80
 | 
			
		||||
	 HEIGHT=24 BORDER=0></A> 
 | 
			
		||||
    <% } // end if %>
 | 
			
		||||
  </DIV>
 | 
			
		||||
  <% if (data.anyTopics()) { %>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								web/images/tag_new.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								web/images/tag_new.gif
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 335 B  | 
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user