jive论坛消息的threaded显示模式解析
2006-11-20 22:22
447 查看
jive主题的消息有两种显示方式:flat和threaded,具体可以在jive_config.xml中配置,配置的选项是skin.default.threadmode。
当我们使用flat模式的时候,所有的消息将会在主题的根消息下面以时间顺序并且没有缩进地排列显示出来,这种分页显示方式与主题的分页显示方式是类似的。但是,这里的另一种实现方式,即缩进方式,它所有的消息是显示在它自己的父消息(非主题的根消息)之下,并且没有使用分页显示,这种显示方式就是threaded方式,在threaded方式中使用到了一个重要的类TreeWalker。
来看下面的代码(threadMode1.jsp)
TreeWalker treeWalker = thread.treeWalker();
ForumMessage rootMessage = thread.getRootMessage();
Iterator messages = treeWalker.recursiveChildren(rootMessage);
这段代码是使用treeWalker获得以rootMessage为树根的所有消息,注意,返回的是一个Iterator,可想而知,在下面的消息显示中,无非是枚举messages里的内容。
下面重点来看一下treeWalker的recursiveChilderen,它是如何递归返回消息的。
首先我们看TreeWalkerProxy里的recursiveChildren.是这样的
public Iterator recursiveChildren(ForumMessage parent) {
return new IteratorProxy(JiveGlobals.MESSAGE,
treeWalker.recursiveChildren(parent), authorization, permissions);
}
它其实是对treeWalker返回的迭代器的一层proxy封装,(这里的treeWalker应该是DbTreeWalder的实例了。再往里看到DbtreeWalker中的方法:
public Iterator recursiveChildren(ForumMessage parent) {
long [] messages = tree.getRecursiveChildren(parent.getID());
return new DatabaseObjectIterator(JiveGlobals.MESSAGE, messages,
parent.getForumThread());
}
现在到了关键的地方了,tree.getRecursiveChildren(parent.getID()),这个方法直接返回以rootMessage的ID为根的所有的子消息ID号了,前面讲到过DatabaseObjectIterator只是对这些消息ID的一个迭代器封装而已。
稍微解释一下:
tree是二叉树的一个不完全实现,类为LongTree,可以看到系统中有这样一段说明,
* 1
* |-- 3
* |-- |--4
* |-- |--6
* |-- 5
*
* array index: 0 | 1 | 2 | 3 | 4
*
* key: 1 | 3 | 4 | 5 | 6
* leftChild: 1 | 2 |-1 |-1 |-1
* rightSiblings -1 | 3 | 4 |-1 |-1
即系统中使用三个成员数组来描述上面的树,而对于一个主题来说,就存在这样的一棵树,这棵树tree是在treewalker初始化的时候完成的,即:
public DbTreeWalker(DbForumThread thread, DbForumFactory factory) {
......
ForumMessage root = thread.getRootMessage();
int numMessages = thread.getMessageCount(IGNORE_MODERATION_FILTER);
//初始化tree,这时只包含一个根
tree = new LongTree(root.getID(), numMessages);
Connection con = null;
PreparedStatement pstmt = null;
try {
con = ConnectionManager.getConnection();
pstmt = con.prepareStatement(GET_MESSAGES);
pstmt.setLong(1, thread.getID());
ResultSet rs = pstmt.executeQuery();
while(rs.next()) {
//枚举出数据库中的每个message并加入到数中,由于枚举时按时间升序,所以这个message的parent的id肯定已经在数上了。
long messageID = rs.getLong(1);
long parentMessageID = rs.getLong(2);
tree.addChild(parentMessageID, messageID);
}
}
......
}
树在初始化已经形成,现在还是来看核心的部分吧
tree.getRecursiveChildren(parent.getID()),
public long[] getRecursiveChildren(long parentKey) {
//找到根节点的id:startIndex
char startIndex = findKey(parentKey, (char)1);
//初始化返回的数组,数组的index即是树节点的index。数组的value将是tree的节点的key值,即message的ID值。
long [] depthKeys = new long[nextIndex-1];
int cursor = 0;
//得到根节点的左子数
char siblingIndex = leftChildren[startIndex];
while (siblingIndex != 0) {
//填充根节点的左子数,即把所有左子数上的节点的key都赋给depthKey.(这是递归)
cursor = fillDepthKeys(siblingIndex, depthKeys, cursor);
//得到根节点的右子数,继而所有右子数上的节点的key都赋给depthKey
siblingIndex = rightSiblings[siblingIndex];
}
long [] dKeys = new long[cursor];
for (int i=0; i<cursor; i++) {
dKeys[i] = depthKeys[i];
}
return dKeys;
}
这段代码,以深度优先算法返回了数的key。
当我们使用flat模式的时候,所有的消息将会在主题的根消息下面以时间顺序并且没有缩进地排列显示出来,这种分页显示方式与主题的分页显示方式是类似的。但是,这里的另一种实现方式,即缩进方式,它所有的消息是显示在它自己的父消息(非主题的根消息)之下,并且没有使用分页显示,这种显示方式就是threaded方式,在threaded方式中使用到了一个重要的类TreeWalker。
来看下面的代码(threadMode1.jsp)
TreeWalker treeWalker = thread.treeWalker();
ForumMessage rootMessage = thread.getRootMessage();
Iterator messages = treeWalker.recursiveChildren(rootMessage);
这段代码是使用treeWalker获得以rootMessage为树根的所有消息,注意,返回的是一个Iterator,可想而知,在下面的消息显示中,无非是枚举messages里的内容。
下面重点来看一下treeWalker的recursiveChilderen,它是如何递归返回消息的。
首先我们看TreeWalkerProxy里的recursiveChildren.是这样的
public Iterator recursiveChildren(ForumMessage parent) {
return new IteratorProxy(JiveGlobals.MESSAGE,
treeWalker.recursiveChildren(parent), authorization, permissions);
}
它其实是对treeWalker返回的迭代器的一层proxy封装,(这里的treeWalker应该是DbTreeWalder的实例了。再往里看到DbtreeWalker中的方法:
public Iterator recursiveChildren(ForumMessage parent) {
long [] messages = tree.getRecursiveChildren(parent.getID());
return new DatabaseObjectIterator(JiveGlobals.MESSAGE, messages,
parent.getForumThread());
}
现在到了关键的地方了,tree.getRecursiveChildren(parent.getID()),这个方法直接返回以rootMessage的ID为根的所有的子消息ID号了,前面讲到过DatabaseObjectIterator只是对这些消息ID的一个迭代器封装而已。
稍微解释一下:
tree是二叉树的一个不完全实现,类为LongTree,可以看到系统中有这样一段说明,
* 1
* |-- 3
* |-- |--4
* |-- |--6
* |-- 5
*
* array index: 0 | 1 | 2 | 3 | 4
*
* key: 1 | 3 | 4 | 5 | 6
* leftChild: 1 | 2 |-1 |-1 |-1
* rightSiblings -1 | 3 | 4 |-1 |-1
即系统中使用三个成员数组来描述上面的树,而对于一个主题来说,就存在这样的一棵树,这棵树tree是在treewalker初始化的时候完成的,即:
public DbTreeWalker(DbForumThread thread, DbForumFactory factory) {
......
ForumMessage root = thread.getRootMessage();
int numMessages = thread.getMessageCount(IGNORE_MODERATION_FILTER);
//初始化tree,这时只包含一个根
tree = new LongTree(root.getID(), numMessages);
Connection con = null;
PreparedStatement pstmt = null;
try {
con = ConnectionManager.getConnection();
pstmt = con.prepareStatement(GET_MESSAGES);
pstmt.setLong(1, thread.getID());
ResultSet rs = pstmt.executeQuery();
while(rs.next()) {
//枚举出数据库中的每个message并加入到数中,由于枚举时按时间升序,所以这个message的parent的id肯定已经在数上了。
long messageID = rs.getLong(1);
long parentMessageID = rs.getLong(2);
tree.addChild(parentMessageID, messageID);
}
}
......
}
树在初始化已经形成,现在还是来看核心的部分吧
tree.getRecursiveChildren(parent.getID()),
public long[] getRecursiveChildren(long parentKey) {
//找到根节点的id:startIndex
char startIndex = findKey(parentKey, (char)1);
//初始化返回的数组,数组的index即是树节点的index。数组的value将是tree的节点的key值,即message的ID值。
long [] depthKeys = new long[nextIndex-1];
int cursor = 0;
//得到根节点的左子数
char siblingIndex = leftChildren[startIndex];
while (siblingIndex != 0) {
//填充根节点的左子数,即把所有左子数上的节点的key都赋给depthKey.(这是递归)
cursor = fillDepthKeys(siblingIndex, depthKeys, cursor);
//得到根节点的右子数,继而所有右子数上的节点的key都赋给depthKey
siblingIndex = rightSiblings[siblingIndex];
}
long [] dKeys = new long[cursor];
for (int i=0; i<cursor; i++) {
dKeys[i] = depthKeys[i];
}
return dKeys;
}
这段代码,以深度优先算法返回了数的key。
相关文章推荐
- 若要调试此模块,请将其项目生成配置更改为“调试”模式。若要取消显示此消息,请禁用"启动时若没有用户代码则发出警告"调试器选项。
- 解析 ViewTreeObserver 源码,体会观察者模式、Android消息传递(上)
- 若要调试此模块,请将其项目生成配置更改为“调试”模式。若要取消显示此消息,请禁用“启动时若没有用户代码则发出警告”调试器选项。
- 解析 ViewTreeObserver 源码,体会观察者模式、Android消息传递(下)
- 解析XML,将数据显示在treeview上,使用简单工厂模式
- 若要调试此模块,请将其项目生成配置更改为“调试”模式。若要取消显示此消息,请禁用“启动时若没有用户代码则发出警告”调试器选项。
- 若要调试此模块,请将其项目生成配置更改为“调试”模式。若要取消显示此消息,请禁用“启动时若没有用户代码则发出警告”调试器选项。
- 若要调试此模块,请将其项目生成配置更改为“调试”模式。若要取消显示此消息,请禁用“启动时若没有用户代码则发出警告”调试器选项
- discuz论坛不登录状态(游客浏览)模式下,门户页面显示keyword关键词,description描述
- 若要调试此模块,请将其项目生成配置更改为“调试”模式。若要取消显示此消息,请禁用“启动时若没有用户代码则发出警告”调试器选项
- MVVM模式解析和在WPF中的实现(六) 用依赖注入的方式配置ViewModel并注册消息
- IOS 推送 通知栏消息模式 显示demo字段,如何让demo字段变为应用名
- 模仿短信模式的显示消息数目的xml布局 和 cmd查看手机短信步骤
- Excel 中的自动筛选状态栏显示“Filter Mode”(“筛选”模式)消息
- 20170223-问题001,增强中的E消息 显示为 S模式消息,
- MFC模式对话框与非模式对话框 消息处理顺序 与非模式对话框的焦点问题、显示、关闭以及交互问题
- LTE Initial Attach 的过程以及相关消息的具体解析 (二)
- 23种设计模式全解析
- 消息模式
- 有html代码的变量显示字符串而不是html解析显示