[jboss-cvs] jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/plugin/forum ...

Christian Bauer christian at hibernate.org
Tue Dec 18 23:29:25 EST 2007


  User: cbauer  
  Date: 07/12/18 23:29:25

  Modified:    examples/wiki/src/main/org/jboss/seam/wiki/plugin/forum               
                        ForumDAO.java ForumQueries.hbm.xml ForumQuery.java
                        ForumHome.java TopicHome.java ForumTopic.java
                        ReplyHome.java ForumListHome.java ForumInfo.java
  Added:       examples/wiki/src/main/org/jboss/seam/wiki/plugin/forum               
                        ForumTopicReadManager.java TopicInfo.java
                        ForumTopicFeedEntryManager.java
                        ForumReplyFeedEntryManager.java
  Removed:     examples/wiki/src/main/org/jboss/seam/wiki/plugin/forum               
                        ForumCookie.java ForumSearchSupport.java
  Log:
  Major rewrite of the most of the application
  
  Revision  Changes    Path
  1.2       +132 -38   jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/plugin/forum/ForumDAO.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: ForumDAO.java
  ===================================================================
  RCS file: /cvsroot/jboss/jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/plugin/forum/ForumDAO.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -b -r1.1 -r1.2
  --- ForumDAO.java	9 Nov 2007 15:00:28 -0000	1.1
  +++ ForumDAO.java	19 Dec 2007 04:29:25 -0000	1.2
  @@ -3,17 +3,16 @@
   import org.jboss.seam.annotations.Name;
   import org.jboss.seam.annotations.In;
   import org.jboss.seam.annotations.AutoCreate;
  -import org.jboss.seam.wiki.core.model.Directory;
  -import org.jboss.seam.wiki.core.model.Comment;
  +import org.jboss.seam.wiki.core.model.WikiDirectory;
  +import org.jboss.seam.wiki.core.model.WikiDocument;
  +import org.jboss.seam.wiki.core.model.WikiComment;
  +import org.jboss.seam.wiki.core.model.WikiMenuItem;
   import org.hibernate.Session;
   import org.hibernate.ScrollableResults;
   import org.hibernate.transform.ResultTransformer;
   
   import javax.persistence.EntityManager;
  -import java.util.List;
  -import java.util.Map;
  -import java.util.HashMap;
  -import java.util.Date;
  +import java.util.*;
   
   @Name("forumDAO")
   @AutoCreate
  @@ -25,24 +24,23 @@
       @In
       EntityManager restrictedEntityManager;
   
  -    public List<Directory> findForums(Directory forumDirectory) {
  -        return getSession(true).getNamedQuery("forums")
  -                .setParameter("parentDir", forumDirectory)
  +    public List<WikiMenuItem> findForumsMenuItems(WikiDirectory forumsDirectory) {
  +        return getSession(true).getNamedQuery("forumsMenuItems")
  +                .setParameter("parentDir", forumsDirectory)
                   .list();
       }
       
  -    public Map<Long, ForumInfo> findForumInfo(Directory forumDirectory) {
  -        final Map<Long, ForumInfo> forumInfoMap = new HashMap<Long, ForumInfo>();
  +    public Map<Long, ForumInfo> findForums(WikiDirectory forumsDirectory) {
  +        final Map<Long, ForumInfo> forumInfoMap = new LinkedHashMap<Long, ForumInfo>();
   
  -        // Append thread and posting count
  -        getSession(true).getNamedQuery("forumTopicPostCount")
  -            .setParameter("parentDir", forumDirectory)
  +        getSession(true).getNamedQuery("forums")
  +            .setParameter("parentDir", forumsDirectory)
               .setResultTransformer(
                   new ResultTransformer() {
                       public Object transformTuple(Object[] result, String[] strings) {
                           forumInfoMap.put(
                               (Long) result[0],
  -                            new ForumInfo( (Long)result[1], (Long)result[2])
  +                            new ForumInfo( (WikiDirectory)result[1])
                           );
                           return null;
                       }
  @@ -51,14 +49,51 @@
               )
               .list();
   
  -        // Append last topic Document
  +        // Find topic count (topics are just wiki documents in the forum directories)
  +        getSession(true).getNamedQuery("forumTopicCount")
  +            .setParameter("parentDir", forumsDirectory)
  +            .setResultTransformer(
  +                new ResultTransformer() {
  +                    public Object transformTuple(Object[] result, String[] strings) {
  +                        if (forumInfoMap.containsKey((Long)result[0])) {
  +                            ForumInfo info = forumInfoMap.get( (Long)result[0] );
  +                            info.setTotalNumOfTopics((Long)result[1]);
  +                            info.setTotalNumOfPosts(info.getTotalNumOfTopics());
  +                        }
  +                        return null;
  +                    }
  +                    public List transformList(List list) { return list; }
  +                }
  +            )
  +            .list();
  +
  +        // Add reply count to topic count to get total num of posts
  +        getSession(true).getNamedQuery("forumReplyCount")
  +            .setParameter("parentDir", forumsDirectory)
  +            .setResultTransformer(
  +                new ResultTransformer() {
  +                    public Object transformTuple(Object[] result, String[] strings) {
  +                        if (forumInfoMap.containsKey((Long)result[0])) {
  +                            ForumInfo info = forumInfoMap.get( (Long)result[0] );
  +                            info.setTotalNumOfPosts(
  +                                info.getTotalNumOfPosts() + (Long)result[1]
  +                            );
  +                        }
  +                        return null;
  +                    }
  +                    public List transformList(List list) { return list; }
  +                }
  +            )
  +            .list();
  +
  +        // Append last topic WikiDocument
           getSession(true).getNamedQuery("forumLastTopic")
  -            .setParameter("parentDir", forumDirectory)
  +            .setParameter("parentDir", forumsDirectory)
               .setResultTransformer(
                   new ResultTransformer() {
                       public Object transformTuple(Object[] result, String[] strings) {
                           if (forumInfoMap.containsKey((Long)result[0]))
  -                            forumInfoMap.get( (Long)result[0] ).setLastTopic( (ForumTopic)result[1] );
  +                            forumInfoMap.get( (Long)result[0] ).setLastTopic( (WikiDocument)result[1] );
                           return null;
                       }
                       public List transformList(List list) { return list; }
  @@ -66,16 +101,14 @@
               )
               .list();
   
  -        // Append last reply Comment
  -        getSession(true).getNamedQuery("forumLastComment")
  -            .setParameter("nsLeft", forumDirectory.getNsLeft())
  -            .setParameter("nsRight", forumDirectory.getNsRight())
  -            .setParameter("nsThread", forumDirectory.getNsThread())
  +        // Append last reply WikiComment
  +        getSession(true).getNamedQuery("forumLastReply")
  +                .setParameter("parentDir", forumsDirectory)
               .setResultTransformer(
                   new ResultTransformer() {
                       public Object transformTuple(Object[] result, String[] strings) {
                           if (forumInfoMap.containsKey((Long)result[0]))
  -                            forumInfoMap.get( (Long)result[0] ).setLastComment( (Comment)result[1] );
  +                            forumInfoMap.get( (Long)result[0] ).setLastComment( (WikiComment)result[1] );
                           return null;
                       }
                       public List transformList(List list) { return list; }
  @@ -86,7 +119,50 @@
           return forumInfoMap;
       }
   
  -    public Long findTopicCount(Directory forum) {
  +    public Map<Long, Long> findUnreadTopicAndParentIds(WikiDirectory forumsDir, Date lastLoginDate) {
  +        return findUnreadTopicAndParentIds("forumUnreadTopics", "forumUnreadReplies", forumsDir, lastLoginDate);
  +    }
  +
  +    public Map<Long, Long> findUnreadTopicAndParentIdsInForum(WikiDirectory forum, Date lastLoginDate) {
  +        return findUnreadTopicAndParentIds("forumUnreadTopicsInForum", "forumUnreadRepliesInForum", forum, lastLoginDate);
  +    }
  +
  +    private Map<Long, Long> findUnreadTopicAndParentIds(String unreadTopicsQuery, String unreadRepliesQuery,
  +                                                        WikiDirectory directory, Date lastLoginDate) {
  +        final Map<Long, Long> unreadTopics = new HashMap<Long, Long>();
  +
  +        getSession(true).getNamedQuery(unreadTopicsQuery)
  +            .setParameter("parentDir", directory)
  +            .setParameter("lastLoginDate", lastLoginDate)
  +            .setResultTransformer(
  +                new ResultTransformer() {
  +                    public Object transformTuple(Object[] objects, String[] strings) {
  +                        unreadTopics.put((Long)objects[0], (Long)objects[1]);
  +                        return null;
  +                    }
  +                    public List transformList(List list) { return list;}
  +                }
  +            )
  +            .list();
  +
  +        getSession(true).getNamedQuery(unreadRepliesQuery)
  +            .setParameter("parentDir", directory)
  +            .setParameter("lastLoginDate", lastLoginDate)
  +            .setResultTransformer(
  +                new ResultTransformer() {
  +                    public Object transformTuple(Object[] objects, String[] strings) {
  +                        unreadTopics.put((Long)objects[0], (Long)objects[1]);
  +                        return null;
  +                    }
  +                    public List transformList(List list) { return list;}
  +                }
  +            )
  +            .list();
  +
  +        return unreadTopics;
  +    }
  +
  +    public Long findTopicCount(WikiDirectory forum) {
           ScrollableResults cursor =
               getSession(true).getNamedQuery("forumTopics")
                   .setParameter("forum", forum)
  @@ -98,26 +174,44 @@
           return count;
       }
      
  -    public List<ForumTopic> findTopics(Directory forum, long firstResult, long maxResults) {
  -        return getSession(true).getNamedQuery("forumTopics")
  +    public Map<Long, TopicInfo> findTopics(WikiDirectory forum, long firstResult, long maxResults) {
  +        final Map<Long, TopicInfo> topicInfoMap = new LinkedHashMap<Long, TopicInfo>();
  +
  +        getSession(true).getNamedQuery("forumTopics")
               .setParameter("forum", forum)
  +            .setFirstResult(new Long(firstResult).intValue())
  +            .setMaxResults(new Long(maxResults).intValue())
               .setResultTransformer(
                   new ResultTransformer() {
                       public Object transformTuple(Object[] result, String[] strings) {
  -                        return ForumTopic.fromArray(result);
  +                        topicInfoMap.put(
  +                            (Long) result[0],
  +                            new TopicInfo( (WikiDocument)result[1], (Integer)result[2])
  +                        );
  +                        return null;
                       }
                       public List transformList(List list) { return list; }
                   }
               )
  -            .setFirstResult(new Long(firstResult).intValue())
  -            .setMaxResults(new Long(maxResults).intValue())
               .list();
  +        getSession(true).getNamedQuery("forumTopicsReplies")
  +            .setParameterList("topicIds", topicInfoMap.keySet())
  +            .setResultTransformer(
  +                new ResultTransformer() {
  +                    public Object transformTuple(Object[] result, String[] strings) {
  +                        if (topicInfoMap.containsKey((Long)result[0])) {
  +                            TopicInfo info = topicInfoMap.get( (Long)result[0] );
  +                            info.setNumOfReplies((Long)result[1]);
  +                            info.setLastComment((WikiComment)result[2]);
       }
  -
  -    public List<ForumTopic> findUnreadTopics(Date lastLoginDate) {
  -        return getSession(true).getNamedQuery("forumUnreadTopics")
  -                .setParameter("lastLoginDate", lastLoginDate)
  +                        return null;
  +                    }
  +                    public List transformList(List list) { return list; }
  +                }
  +            )
                   .list();
  +
  +        return topicInfoMap;
       }
   
       private Session getSession(boolean restricted) {
  
  
  
  1.2       +128 -54   jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/plugin/forum/ForumQueries.hbm.xml
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: ForumQueries.hbm.xml
  ===================================================================
  RCS file: /cvsroot/jboss/jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/plugin/forum/ForumQueries.hbm.xml,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -b -r1.1 -r1.2
  --- ForumQueries.hbm.xml	9 Nov 2007 15:00:28 -0000	1.1
  +++ ForumQueries.hbm.xml	19 Dec 2007 04:29:25 -0000	1.2
  @@ -6,98 +6,172 @@
   <hibernate-mapping>
   
       <query name="forums">
  +        select d.id, d
  +        from
  +            WikiDirectory d fetch all properties,
  +            WikiMenuItem m
  +        where
  +            d = m.directory
  +            and d.parent = :parentDir
  +        order by m.displayPosition asc
  +    </query>
  +
  +    <query name="forumsMenuItems">
  +        select m
  +        from
  +            WikiMenuItem m
  +        where
  +            m.directory.parent = :parentDir
  +        order by m.displayPosition asc
  +    </query>
  +
  +    <query name="forumTopicCount">
           select
  -            f
  +            f.id, count(distinct t)
           from
  -            Directory f left join fetch f.feed
  +            WikiDirectory f, WikiDocument t
           where
               f.parent = :parentDir
  -        order by f.displayPosition asc
  +            and t.parent = f
  +            and (t.headerMacrosString like '%forumPosting%' or t.headerMacrosString like '%forumStickyPosting%')
  +        group
  +            by f.id
       </query>
   
  -    <query name="forumTopicPostCount">
  +    <query name="forumReplyCount">
           select
  -            f.id, count(distinct child), count(distinct child) + count(distinct comment)
  +            f.id, count(distinct c)
           from
  -            Directory f
  -                left outer join f.children as child
  -                left outer join child.comments as comment
  +            WikiDirectory f, WikiDocument t, WikiComment c
           where
               f.parent = :parentDir
  -            and child != f.defaultDocument
  +            and t.parent = f
  +            and (t.headerMacrosString like '%forumPosting%' or t.headerMacrosString like '%forumStickyPosting%')
  +            and c.nodeInfo.nsThread in (select c2.nodeInfo.nsThread from WikiComment c2 where c2.parent = t)
           group
               by f.id
       </query>
   
       <query name="forumLastTopic">
           select
  -            f.id, lt
  +            f.id, t
           from
  -            Directory f left outer join f.children as lt left join fetch lt.createdBy u join fetch u.profile
  +            WikiDirectory f, WikiDocument t left join fetch t.parent left join fetch t.createdBy u left join fetch u.profile
           where
               f.parent = :parentDir
  -            and lt != f.defaultDocument
  -            and lt.displayPosition = (select max(n.displayPosition) from Node n where n.parent = f)
  +            and t.parent = f
  +            and (t.headerMacrosString like '%forumPosting%' or t.headerMacrosString like '%forumStickyPosting%')
  +            and t.createdOn = (select max(t2.createdOn) from WikiDocument t2 where t2 = t)
       </query>
   
  -    <!-- This only uses the timestamp of all comments to identify the last comment - is that enough? -->
  -    <query name="forumLastComment"><![CDATA[
  +    <query name="forumLastReply">
           select
               f.id, c
           from
  -            Comment c left join fetch c.fromUser u join fetch u.profile, Document d, Directory f join fetch c.document
  +            WikiDirectory f, WikiDocument t, WikiComment c left join fetch c.parent left join fetch c.createdBy u left join fetch u.profile
  +        where
  +            f.parent = :parentDir
  +            and t.parent = f
  +            and (t.headerMacrosString like '%forumPosting%' or t.headerMacrosString like '%forumStickyPosting%')
  +            and c.nodeInfo.nsThread in (select c2 from WikiComment c2 where c2.parent = t)
  +            and c.createdOn = (
  +                select max(c3.createdOn) from WikiDirectory f2, WikiDocument t2, WikiComment c3
  +                where f2.parent = :parentDir and t2.parent = f2
  +                and (t2.headerMacrosString like '%forumPosting%' or t2.headerMacrosString like '%forumStickyPosting%')
  +                and c3.nodeInfo.nsThread in (select c4.nodeInfo.nsThread from WikiComment c4 where c4.parent = t2)
  +            )
  +    </query>
  +
  +    <query name="forumUnreadTopics"><![CDATA[
  +        select
  +            distinct t.id, t.parent.id
  +        from
  +            WikiDirectory f, WikiDocument t
           where
  -            c.createdOn =
  -                (select max(com.createdOn) from Document doc, Comment com where
  -                doc.nsLeft > :nsLeft and doc.nsRight < :nsRight and doc.nsThread = :nsThread
  -                and com.document = doc)
  -            and c.document = d
  -            and d.parent = f
  +            f.parent = :parentDir
  +            and t.parent = f
  +            and (t.headerMacrosString like '%forumPosting%' or t.headerMacrosString like '%forumStickyPosting%')
  +            and t.createdOn > :lastLoginDate
       ]]></query>
   
  -    <!-- Somewhat ugly workarounds for the missing case...when support in HQL select clause -->
  -    <query name="forumTopics"><![CDATA[
  +    <query name="forumUnreadReplies"><![CDATA[
           select
  -            t,
  -            count(c),
  -            locate('forumStickyPosting', t.macros, 1),
  -            c2
  +            distinct t.id, t.parent.id
           from
  -            Directory f,
  -            ForumTopic t
  -                join fetch t.createdBy u join fetch u.profile up
  -                left outer join t.comments c
  -                left outer join t.comments c2 left join fetch c2.fromUser u2 left join fetch u2.profile u2p
  +            WikiDirectory f, WikiDocument t, WikiComment c
           where
  -            f = :forum
  +            f.parent = :parentDir
               and t.parent = f
  -            and t != f.defaultDocument
  -            and (c2.createdOn = (select max(com.createdOn) from Comment com where com.document = t) or c2 is null)
  -            group by t.id, t.class, t.version, t.nsLeft, t.nsRight, t.nsThread, t.parent,
  -                     t.areaNumber, t.createdBy, t.createdOn, t.lastModifiedBy, t.lastModifiedOn, t.menuItem, t.name, t.displayPosition,
  -                     t.readAccessLevel, t.revision, t.wikiname, t.writeAccessLevel, t.tags,
  -                     t.enableComments, t.enableCommentForm, t.enableCommentsOnFeeds, t.nameAsTitle, t.macros,
  -                     locate('forumStickyPosting', t.macros, 1),
  +            and (t.headerMacrosString like '%forumPosting%' or t.headerMacrosString like '%forumStickyPosting%')
  +            and c.nodeInfo.nsThread in (select c2.nodeInfo.nsThread from WikiComment c2 where c2.parent = t)
  +            and c.createdOn > :lastLoginDate
  +    ]]></query>
   
  -                     c2.id, c2.version, c2.document, c2.subject, c2.fromUser, c2.fromUserName, c2.fromUserEmail, c2.fromUserHomepage, c2.text, c2.useWikiText, c2.createdOn,
  +    <query name="forumUnreadTopicsInForum"><![CDATA[
  +        select
  +            distinct t.id, t.parent.id
  +        from
  +            WikiDocument t
  +        where
  +            t.parent = :parentDir
  +            and (t.headerMacrosString like '%forumPosting%' or t.headerMacrosString like '%forumStickyPosting%')
  +            and t.createdOn > :lastLoginDate
  +    ]]></query>
   
  -                     u.id, u.version, u.firstname, u.lastname, u.username, u.passwordHash, u.email, u.activated, u.activationCode, u.createdOn, u.lastLoginOn, u.memberHome, u.profile,
  -                     up.id, up.version, up.createdOn, up.bio, up.website, up.location, up.occupation, up.signature, up.imageContentType,
  +    <query name="forumUnreadRepliesInForum"><![CDATA[
  +        select
  +            distinct t.id, t.parent.id
  +        from
  +            WikiDocument t, WikiComment c
  +        where
  +            t.parent = :parentDir
  +            and (t.headerMacrosString like '%forumPosting%' or t.headerMacrosString like '%forumStickyPosting%')
  +            and c.nodeInfo.nsThread in (select c2.nodeInfo.nsThread from WikiComment c2 where c2.parent = t)
  +            and c.createdOn > :lastLoginDate
  +    ]]></query>
   
  -                     u2.id, u2.version, u2.firstname, u2.lastname, u2.username, u2.passwordHash, u2.email, u2.activated, u2.activationCode, u2.createdOn, u.lastLoginOn, u2.memberHome, u2.profile,
  -                     u2p.id, u2p.version, u2p.createdOn, u2p.bio, u2p.website, u2p.location, u2p.occupation, u2p.signature, u2p.imageContentType
   
  -            order by case locate('forumStickyPosting', t.macros, 1) when '0' then '0' else '1' end desc, t.createdOn desc, c2.createdOn desc
  +    <!-- Somewhat ugly workarounds for the missing case...when support in HQL select clause -->
  +    <query name="forumTopics"><![CDATA[
  +        select
  +            t.id,
  +            t,
  +            locate('forumStickyPosting', t.headerMacrosString, 1)
  +        from
  +            WikiDirectory f,
  +            WikiDocument t join fetch t.createdBy u join fetch u.profile up
  +        where
  +            f = :forum
  +            and t.parent = f
  +            and (t.headerMacrosString like '%forumPosting%' or t.headerMacrosString like '%forumStickyPosting%')
  +            order by case locate('forumStickyPosting', t.headerMacrosString, 1) when '0' then '0' else '1' end desc, t.createdOn desc
       ]]></query>
   
  -    <query name="forumUnreadTopics"><![CDATA[
  +    <query name="forumTopicsReplies"><![CDATA[
           select
  -            distinct t
  -        from ForumTopic t left join fetch t.parent left outer join t.comments c
  -            where
  -                t.createdOn > :lastLoginDate
  -                or
  -                c.createdOn > :lastLoginDate
  +            t.id,
  +            count(c),
  +            c2
  +        from
  +            WikiDocument t,
  +            WikiComment c,
  +            WikiComment c2 join fetch c2.createdBy u join fetch u.profile up
  +        where
  +            t.id in (:topicIds)
  +            and c.nodeInfo.nsThread in (select c3.nodeInfo.nsThread from WikiComment c3 where c3.parent = t)
  +            and c2.createdOn =
  +                (select max(c4.createdOn) from WikiComment c4 where c4.nodeInfo.nsThread in
  +                    (select c5.nodeInfo.nsThread from WikiComment c5 where c5.parent = t) )
  +        group by
  +            t.id,
  +
  +            c2.id, c2.nodeInfo.nsLeft, c2.nodeInfo.nsRight, c2.nodeInfo.nsThread,
  +            c2.version, c2.parent,
  +            c2.areaNumber, c2.name, c2.wikiname, c2.createdBy, c2.createdOn, c2.lastModifiedBy, c2.lastModifiedOn, c2.readAccessLevel, c2.writeAccessLevel, c2.writeProtected,
  +            c2.subject, c2.fromUserName, c2.fromUserEmail, c2.fromUserHomepage, c2.useWikiText,
  +
  +            u.id, u.version, u.firstname, u.lastname, u.username, u.passwordHash, u.email, u.activated, u.activationCode, u.createdOn, u.lastLoginOn, u.memberHome, u.profile,
  +            up.id, up.version, up.createdOn, up.bio, up.website, up.location, up.occupation, up.signature, up.imageContentType
   
       ]]></query>
   
  
  
  
  1.3       +55 -47    jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/plugin/forum/ForumQuery.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: ForumQuery.java
  ===================================================================
  RCS file: /cvsroot/jboss/jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/plugin/forum/ForumQuery.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -b -r1.2 -r1.3
  --- ForumQuery.java	20 Nov 2007 08:05:09 -0000	1.2
  +++ ForumQuery.java	19 Dec 2007 04:29:25 -0000	1.3
  @@ -1,25 +1,26 @@
   package org.jboss.seam.wiki.plugin.forum;
   
  -import org.jboss.seam.wiki.core.model.Directory;
  +import org.jboss.seam.wiki.core.model.WikiDirectory;
   import org.jboss.seam.wiki.core.model.User;
  +import org.jboss.seam.wiki.core.model.WikiDocument;
   import org.jboss.seam.wiki.core.action.Pager;
  -import org.jboss.seam.annotations.Name;
  -import org.jboss.seam.annotations.Scope;
  -import org.jboss.seam.annotations.In;
  +import org.jboss.seam.annotations.*;
   import org.jboss.seam.annotations.Observer;
   import org.jboss.seam.annotations.web.RequestParameter;
   import org.jboss.seam.ScopeType;
   import org.jboss.seam.Component;
  +import org.jboss.seam.log.Log;
   
  -import java.util.List;
  -import java.util.Map;
  -import java.util.ArrayList;
  +import java.util.*;
   import java.io.Serializable;
   
   @Name("forumQuery")
   @Scope(ScopeType.CONVERSATION)
   public class ForumQuery implements Serializable {
   
  +    @Logger
  +    Log log;
  +
       private Pager pager;
   
       @In
  @@ -36,7 +37,7 @@
       }
   
       @In
  -    Directory currentDirectory;
  +    WikiDirectory currentDirectory;
   
       @In
       User currentUser;
  @@ -49,72 +50,79 @@
   
       /* ####################### FORUMS ########################## */
   
  -    List<Directory> forums;
  -    public List<Directory> getForums() {
  +    List<ForumInfo> forums;
  +    public List<ForumInfo> getForums() {
           if (forums == null) loadForums();
           return forums;
       }
   
  -    Map<Long, ForumInfo> forumInfo;
  -    public Map<Long, ForumInfo> getForumInfo() {
  -        return forumInfo;
  -    }
   
       @Observer(value = {"Forum.forumListRefresh", "PersistenceContext.filterReset"}, create = false)
       public void loadForums() {
   
  -        forums = forumDAO.findForums(currentDirectory);
  -        forumInfo = forumDAO.findForumInfo(currentDirectory);
  +        Map<Long, ForumInfo> forumInfo = forumDAO.findForums(currentDirectory);
   
           // Find unread postings
  -        User adminUser = (User)Component.getInstance("adminUser");
  -        User guestUser = (User)Component.getInstance("guestUser");
  -        if ( !(currentUser.getId().equals(guestUser.getId())) &&
  -             !(currentUser.getId().equals(adminUser.getId())) ) {
  -            List<ForumTopic> unreadTopics = forumDAO.findUnreadTopics(currentUser.getPreviousLastLoginOn());
  -            ForumCookie forumCookie = (ForumCookie)Component.getInstance("forumCookie");
  -            for (ForumTopic unreadTopic : unreadTopics) {
  -                if (forumInfo.containsKey(unreadTopic.getParent().getId()) &&
  -                    !forumCookie.getCookieValues().containsKey(unreadTopic.getId().toString())) {
  -                    forumInfo.get(unreadTopic.getParent().getId()).setUnreadPostings(true);
  +        if (!currentUser.isAdmin() && !currentUser.isGuest()) {
  +            log.debug("finding unread topics since: " + currentUser.getPreviousLastLoginOn());
  +
  +            Map<Long,Long> unreadTopicsWithParent =
  +                    forumDAO.findUnreadTopicAndParentIds(currentDirectory, currentUser.getPreviousLastLoginOn());
  +
  +            ForumTopicReadManager forumTopicReadManager = (ForumTopicReadManager)Component.getInstance("forumTopicReadManager");
  +
  +            for (Map.Entry<Long, Long> unreadTopicAndParent: unreadTopicsWithParent.entrySet()) {
  +                if (forumInfo.containsKey(unreadTopicAndParent.getValue()) &&
  +                    !forumTopicReadManager.isTopicIdRead(unreadTopicAndParent.getValue(), unreadTopicAndParent.getKey()) ) {
  +                    forumInfo.get(unreadTopicAndParent.getValue()).setUnreadPostings(true);
                   }
               }
           }
  +        forums = new ArrayList<ForumInfo>();
  +        forums.addAll(forumInfo.values());
       }
   
       /* ####################### TOPICS ########################## */
   
  -    private List<ForumTopic> topics;
  +    private List<TopicInfo> topics;
   
  -    public List<ForumTopic> getTopics() {
  +    public List<TopicInfo> getTopics() {
           if (topics == null) loadTopics();
           return topics;
       }
   
  -    @Observer(value = {"Forum.topicPersisted", "PersistenceContext.filterReset"}, create = false)
  +    @Observer(value = {"Forum.topicListRefresh", "PersistenceContext.filterReset"}, create = false)
       public void loadTopics() {
           pager.setNumOfRecords( forumDAO.findTopicCount(currentDirectory) );
  -        topics = pager.getNumOfRecords() > 0
  -            ? forumDAO.findTopics(currentDirectory, pager.getNextRecord(), pager.getPageSize())
  -            : new ArrayList<ForumTopic>();
   
  -        User adminUser = (User)Component.getInstance("adminUser");
  -        User guestUser = (User)Component.getInstance("guestUser");
  -        // Find unread postings
  -        if ( !(currentUser.getId().equals(guestUser.getId())) &&
  -             !(currentUser.getId().equals(adminUser.getId())) ) {
  -            List<ForumTopic> unreadTopics = forumDAO.findUnreadTopics(currentUser.getPreviousLastLoginOn());
  -            ForumCookie forumCookie = (ForumCookie)Component.getInstance("forumCookie");
  -            // TODO: This is nested interation but it's difficult to make this more efficient
  -            for (ForumTopic topic : topics) {
  -                for (ForumTopic unreadTopic : unreadTopics) {
  -                    if (unreadTopic.getId().equals(topic.getId())&&
  -                        !forumCookie.getCookieValues().containsKey(topic.getId().toString())) {
  -                        topic.setUnread(true);
  -                    }
  +        if (pager.getNumOfRecords() == 0) {
  +            topics = Collections.emptyList();
  +            return;
                   }
  +
  +        Map<Long, TopicInfo> topicInfo = forumDAO.findTopics(currentDirectory, pager.getNextRecord(), pager.getPageSize());
  +
  +        if (!currentUser.isAdmin() && !currentUser.isGuest()) {
  +            log.debug("finding unread topics since: " + currentUser.getPreviousLastLoginOn());
  +
  +            Map<Long,Long> unreadTopicsWithParent =
  +                    forumDAO.findUnreadTopicAndParentIdsInForum(currentDirectory, currentUser.getPreviousLastLoginOn());
  +
  +            ForumTopicReadManager forumTopicReadManager = (ForumTopicReadManager)Component.getInstance("forumTopicReadManager");
  +
  +            for (Map.Entry<Long, TopicInfo> topicInfoEntry: topicInfo.entrySet()) {
  +                topicInfoEntry.getValue().setUnread(
  +                    unreadTopicsWithParent.containsKey(topicInfoEntry.getKey()) &&
  +                    !forumTopicReadManager.isTopicIdRead(
  +                        unreadTopicsWithParent.get(topicInfoEntry.getKey()),
  +                        topicInfoEntry.getKey()
  +                    )
  +                );
               }
           }
  +
  +        topics = new ArrayList<TopicInfo>();
  +        topics.addAll(topicInfo.values());
       }
   
   }
  
  
  
  1.2       +89 -120   jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/plugin/forum/ForumHome.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: ForumHome.java
  ===================================================================
  RCS file: /cvsroot/jboss/jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/plugin/forum/ForumHome.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -b -r1.1 -r1.2
  --- ForumHome.java	9 Nov 2007 15:00:28 -0000	1.1
  +++ ForumHome.java	19 Dec 2007 04:29:25 -0000	1.2
  @@ -1,78 +1,104 @@
   package org.jboss.seam.wiki.plugin.forum;
   
  -import static javax.faces.application.FacesMessage.SEVERITY_INFO;
  -import javax.faces.application.FacesMessage;
  -
  -import org.jboss.seam.annotations.*;
   import org.jboss.seam.ScopeType;
  +import org.jboss.seam.international.Messages;
  +import org.jboss.seam.annotations.*;
   import org.jboss.seam.core.Conversation;
   import org.jboss.seam.core.Events;
  -import org.jboss.seam.wiki.core.model.Directory;
  -import org.jboss.seam.wiki.core.model.Document;
  -import org.jboss.seam.wiki.core.action.NodeHome;
  -import org.jboss.seam.wiki.core.dao.FeedDAO;
  +import org.jboss.seam.wiki.core.model.*;
  +import org.jboss.seam.wiki.core.action.DirectoryHome;
   import org.jboss.seam.wiki.util.WikiUtil;
   
  -import java.util.Date;
  +import javax.faces.application.FacesMessage;
  +import static javax.faces.application.FacesMessage.SEVERITY_INFO;
  +import java.util.List;
   
   @Name("forumHome")
   @Scope(ScopeType.CONVERSATION)
  - at AutoCreate
  -public class ForumHome extends NodeHome<Directory> {
  +public class ForumHome extends DirectoryHome {
   
       @In
  -    Directory currentDirectory;
  +    ForumDAO forumDAO;
   
       @In
  -    FeedDAO feedDAO;
  +    WikiDirectory currentDirectory;
   
       private boolean showForm = false;
  -    private boolean hasFeed = true;
   
       /* -------------------------- Basic Overrides ------------------------------ */
   
  -    protected Directory createInstance() {
  -        Directory forum = super.createInstance();
  -        forum.setName("New Forum");
  -        hasFeed = true;
  -        return forum;
  +    @Override
  +    protected boolean isPageRootController() {
  +        return false;
       }
   
  -    public Directory find() {
  -        Directory forum = super.find();
  -        hasFeed = forum.getFeed()!=null;
  -        return forum;
  +    @Override
  +    public Class<WikiDirectory> getEntityClass() {
  +        return WikiDirectory.class;
       }
   
  +    @Override
       public void create() {
           super.create();
  -        setParentDirectoryId(currentDirectory.getId());
  -        init();
  +        setParentNodeId(currentDirectory.getId());
       }
   
  -    protected boolean beforePersist() {
  -        createOrRemoveFeed();
  -        return super.beforePersist();
  +    @Override
  +    public WikiDirectory afterNodeCreated(WikiDirectory node) {
  +        node.setWriteProtected(true); // Only allow admins to edit it
  +        setHasFeed(true); // New forum always has a feed
  +        return super.afterNodeCreated(node);
       }
   
  +    @Override
       public String persist() {
           // This is _always_ a subdirectory in an area
  -        getInstance().setAreaNumber(getParentDirectory().getAreaNumber());
  +        getInstance().setAreaNumber(getParentNode().getAreaNumber());
   
           String outcome = super.persist();
           if (outcome != null) {
   
  +            // Create a mandatory menu item
  +            List<WikiMenuItem> menuItems = forumDAO.findForumsMenuItems(getParentNode());
  +            WikiMenuItem newMenuItem = new WikiMenuItem(getInstance());
  +            menuItems.add(newMenuItem);
  +            for (WikiMenuItem menuItem : menuItems) {
  +                menuItem.setDisplayPosition(menuItems.indexOf(menuItem));
  +            }
  +            getEntityManager().persist(newMenuItem);
  +
               // Default document is topic list
  -            Document topicList = createDefaultDocument();
  -            topicList.setAreaNumber(getInstance().getAreaNumber());
  -            topicList.setName(getInstance().getName() + " Forum");
  -            topicList.setWikiname(WikiUtil.convertToWikiName(topicList.getName()));
  -            topicList.setCreatedBy(getCurrentUser());
  -            topicList.setLastModifiedBy(getCurrentUser());
  -            topicList.setLastModifiedOn(new Date());
  +            WikiDocumentDefaults topicListDefaults =
  +                new WikiDocumentDefaults() {
  +                    public String getDefaultName() {
  +                        return getInstance().getName() + " " + Messages.instance().get("forum.label.Forum");
  +                    }
  +                    public String[] getDefaultHeaderMacros() {
  +                        return new String[] {"clearBackground", "hideControls", "hideComments", "hideTags", "hideCreatorHistory"};
  +                    }
  +                    public String[] getDefaultContentMacros() {
  +                        return new String[] {"forumTopics"};
  +                    }
  +                    public String getDefaultContent() {
  +                        return "";
  +                    }
  +                    public void setDefaults(WikiDocument document) {
  +                        document.setAreaNumber(getInstance().getAreaNumber());
  +                        document.setWikiname(WikiUtil.convertToWikiName(document.getName()));
  +                        document.setNameAsTitle(true);
  +                        document.setReadAccessLevel(getInstance().getReadAccessLevel());
  +                        document.setWriteAccessLevel(org.jboss.seam.wiki.core.model.Role.ADMINROLE_ACCESSLEVEL);
  +                        document.setEnableComments(false);
  +                        document.setEnableCommentForm(false);
  +                        document.setEnableCommentsOnFeeds(false);
  +                        document.setCreatedBy(getCurrentUser());
  +                    }
  +                };
  +
  +            WikiDocument topicList = new WikiDocument(topicListDefaults);
   
  -            getInstance().addChild(topicList);
  -            getInstance().setDefaultDocument(topicList);
  +            topicList.setParent(getInstance());
  +            getInstance().setDefaultFile(topicList);
   
               getEntityManager().persist(topicList);
               getEntityManager().flush();
  @@ -82,32 +108,23 @@
           return null; // Prevent navigation
       }
   
  -    protected boolean beforeUpdate() {
  -        createOrRemoveFeed();
  -        return super.beforeUpdate();
  -    }
  -
  +    @Override
       public String update() {
           String outcome = super.update();
           if (outcome != null) endConversation();
           return null; // Prevent navigation
       }
   
  -    protected boolean beforeRemove() {
  -        // Remove all children (nested, recursively, udpates the second-level cache)
  -        getNodeDAO().removeChildren(getInstance());
  -
  -        return true;
  -    }
  -
  +    @Override
       public String remove() {
           String outcome = super.remove();
           if (outcome != null) endConversation();
           return null; // Prevent navigation
       }
   
  -    /* -------------------------- Messages ------------------------------ */
  +/* -------------------------- Messages ------------------------------ */
   
  +    @Override
       protected void createdMessage() {
           getFacesMessages().addFromResourceBundleOrDefault(
                   SEVERITY_INFO,
  @@ -117,6 +134,7 @@
           );
       }
   
  +    @Override
       protected void updatedMessage() {
           getFacesMessages().addFromResourceBundleOrDefault(
                   SEVERITY_INFO,
  @@ -126,6 +144,7 @@
           );
       }
   
  +    @Override
       protected void deletedMessage() {
           getFacesMessages().addFromResourceBundleOrDefault(
                   SEVERITY_INFO,
  @@ -135,60 +154,29 @@
           );
       }
       
  -    /* -------------------------- Internal Methods ------------------------------ */
  -
  -    private void endConversation() {
  -        showForm = false;
  -        Conversation.instance().end();
  -        getEntityManager().clear(); // Need to force re-read in the forum list refresh
  -        Events.instance().raiseEvent("Forum.forumListRefresh");
  -    }
  -
  -    private Document createDefaultDocument() {
  -        Document doc = new Document();
  -        doc.setNameAsTitle(true);
  -        doc.setReadAccessLevel(getInstance().getReadAccessLevel());
  -        doc.setWriteAccessLevel(getInstance().getWriteAccessLevel());
  -        doc.setEnableComments(false);
  -        doc.setEnableCommentForm(false);
  -
  -        String[] defaultMacros = {"clearBackground", "hideControls", "hideComments", "hideTags", "hideCreatorHistory", "forumTopics"};
  -
  -        StringBuilder contentWithMacros = new StringBuilder();
  -        StringBuilder macros = new StringBuilder();
  -        for (String s : defaultMacros) {
  -            contentWithMacros.append("[<=").append(s).append("]\n");
  -            macros.append(s).append(" ");
  -        }
  -        doc.setContent(contentWithMacros.toString());
  -        doc.setMacros(macros.substring(0, macros.length()-1));
  -
  -        return doc;
  -    }
  -
  -    public void createOrRemoveFeed() {
  -        if (hasFeed && getInstance().getFeed() == null) {
  -            // Does not have a feed but user wants one, create it
  -            feedDAO.createFeed(getInstance());
  -
  +    @Override
  +    protected void feedCreatedMessage() {
               getFacesMessages().addFromResourceBundleOrDefault(
                   FacesMessage.SEVERITY_INFO,
                   "forum.msg.Feed.Create",
                   "Created syndication feed for this forum");
  +    }
   
  -        } else if (!hasFeed && getInstance().getFeed() != null) {
  -            // Does have feed but user doesn't want it anymore... delete it
  -            feedDAO.removeFeed(getInstance());
  -
  +    @Override
  +    protected void feedRemovedMessage() {
               getFacesMessages().addFromResourceBundleOrDefault(
                   FacesMessage.SEVERITY_INFO,
                   "forum.msg.Feed.Remove",
                   "Removed syndication feed of this forum");
  -
  -        } else if (getInstance().getFeed() != null) {
  -            // Does have a feed and user still wants it, update the feed
  -            feedDAO.updateFeed(getInstance());
           }
  +
  +    /* -------------------------- Internal Methods ------------------------------ */
  +
  +    private void endConversation() {
  +        showForm = false;
  +        Conversation.instance().end();
  +        getEntityManager().clear(); // Need to force re-read in the forum list refresh
  +        Events.instance().raiseEvent("Forum.forumListRefresh");
       }
   
       /* -------------------------- Public Features ------------------------------ */
  @@ -201,24 +189,17 @@
           this.showForm = showForm;
       }
   
  -    public boolean isHasFeed() {
  -        return hasFeed;
  -    }
  -
  -    public void setHasFeed(boolean hasFeed) {
  -        this.hasFeed = hasFeed;
  -    }
   
  -    @Begin(flushMode = FlushModeType.MANUAL)
  +    @Begin(flushMode = FlushModeType.MANUAL, join = true)
       public void newForum() {
  -        init();
  +        setEdit(true);
           showForm = true;
       }
   
  -    @Begin(flushMode = FlushModeType.MANUAL)
  +    @Begin(flushMode = FlushModeType.MANUAL, join = true)
       public void edit(Long forumId) {
           setId(forumId);
  -        init();
  +        setEdit(true);
           showForm = true;
       }
   
  @@ -226,16 +207,4 @@
           endConversation();
       }
   
  -    public void resetFeed() {
  -        if (getInstance().getFeed() != null) {
  -            getLog().debug("resetting feed of directory");
  -            getInstance().getFeed().getFeedEntries().clear();
  -            getInstance().getFeed().setPublishedDate(new Date());
  -            getFacesMessages().addFromResourceBundleOrDefault(
  -                FacesMessage.SEVERITY_INFO,
  -                "forum.msg.Feed.Reset",
  -                "Queued removal of all feed entries from the syndication feed of this directory, please update to finalize");
  -        }
  -    }
  -
   }
  
  
  
  1.3       +114 -79   jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/plugin/forum/TopicHome.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: TopicHome.java
  ===================================================================
  RCS file: /cvsroot/jboss/jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/plugin/forum/TopicHome.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -b -r1.2 -r1.3
  --- TopicHome.java	20 Nov 2007 08:05:10 -0000	1.2
  +++ TopicHome.java	19 Dec 2007 04:29:25 -0000	1.3
  @@ -1,68 +1,110 @@
   package org.jboss.seam.wiki.plugin.forum;
   
  -import org.jboss.seam.Component;
   import org.jboss.seam.ScopeType;
   import org.jboss.seam.annotations.*;
  -import org.jboss.seam.wiki.core.action.NodeHome;
  -import org.jboss.seam.wiki.core.engine.WikiLinkResolver;
  -import org.jboss.seam.wiki.core.model.Directory;
  -import org.jboss.seam.wiki.core.model.User;
  -import org.jboss.seam.wiki.core.dao.FeedDAO;
  +import org.jboss.seam.annotations.web.RequestParameter;
  +import org.jboss.seam.core.Conversation;
  +import org.jboss.seam.core.Events;
  +import org.jboss.seam.international.Messages;
  +import org.jboss.seam.wiki.core.action.DocumentHome;
  +import org.jboss.seam.wiki.core.model.WikiDirectory;
  +import org.jboss.seam.wiki.core.model.WikiDocument;
  +import org.jboss.seam.wiki.core.model.WikiDocumentDefaults;
   
   import static javax.faces.application.FacesMessage.SEVERITY_INFO;
  -import java.util.Date;
   
   @Name("topicHome")
   @Scope(ScopeType.CONVERSATION)
  -public class TopicHome extends NodeHome<ForumTopic> {
  +public class TopicHome extends DocumentHome {
   
       @In
  -    Directory currentDirectory;
  -
  -    @In
  -    private FeedDAO feedDAO;
  +    WikiDirectory currentDirectory;
   
       private boolean showForm = false;
  -    private String formContent;
  -    private User user;
  +    private boolean sticky = false;
   
       /* -------------------------- Basic Overrides ------------------------------ */
   
  +    @Override
  +    protected boolean isPageRootController() {
  +        return false;
  +    }
  +
  +    @Override
  +    public Class<WikiDocument> getEntityClass() {
  +        return WikiDocument.class;
  +    }
  +
  +    @Override
       public void create() {
           super.create();
  -        super.setParentDirectory(currentDirectory);
  +        setParentNodeId(currentDirectory.getId());
       }
   
  -    protected boolean beforePersist() {
  -        // Sync topic content
  -        syncFormToInstance(getParentDirectory());
  +    @Override
  +    public WikiDocument afterNodeCreated(WikiDocument doc) {
  +        WikiDocument newTopic = super.afterNodeCreated(doc);
   
  -        // Macros
  -        getInstance().setDefaultMacros();
  -
  -        // Set createdOn date _now_
  -        getInstance().setCreatedOn(new Date());
  +        WikiDocumentDefaults newTopicDefaults =
  +                new WikiDocumentDefaults() {
  +                    public String getDefaultName() {
  +                        return Messages.instance().get("forum.label.NewTopic");
  +                    }
  +                    public String[] getDefaultHeaderMacros() {
  +                        return new String[] { "clearBackground", "hideControls", "hideComments",
  +                                              "hideTags", "hideCreatorHistory", "disableContentMacros", "forumPosting" };
  +                    }
  +                    public String getDefaultContent() {
  +                        return Messages.instance().get("lacewiki.msg.wikiTextEditor.EditThisTextPreviewUpdatesAutomatically");
  +                    }
   
  -        return true;
  +                    public String[] getDefaultFooterMacros() {
  +                        return new String[] { "forumReplies" };
  +                    }
  +                    public void setDefaults(WikiDocument newTopic) {
  +                        newTopic.setNameAsTitle(false);
  +                        newTopic.setEnableComments(true);
  +                        newTopic.setEnableCommentForm(true);
  +                        newTopic.setEnableCommentsOnFeeds(true);
       }
  +                };
  +        newTopic.setDefaults(newTopicDefaults);
   
  -    /* -------------------------- Internal Methods ------------------------------ */
  +        setPushOnFeeds(true);
   
  +        return newTopic;
  +    }
   
  -    private void syncFormToInstance(Directory dir) {
  -        WikiLinkResolver wikiLinkResolver = (WikiLinkResolver) Component.getInstance("wikiLinkResolver");
  -        getInstance().setContentWithoutMacros(
  -            wikiLinkResolver.convertToWikiProtocol(dir.getAreaNumber(), formContent)
  +    @Override
  +    protected boolean beforePersist() {
  +        if (isSticky())
  +            getInstance().setHeader(
  +                getInstance().getHeader().replaceAll("forumPosting", "forumStickyPosting")
           );
  +        return super.beforePersist();
  +    }
  +
  +    @Override
  +    public String persist() {
  +        String outcome = super.persist();
  +        if (outcome != null) {
  +            endConversation();
  +        }
  +        return null; // Prevent navigation
       }
   
  -    private void syncInstanceToForm(Directory dir) {
  -        WikiLinkResolver wikiLinkResolver = (WikiLinkResolver)Component.getInstance("wikiLinkResolver");
  -        formContent = wikiLinkResolver.convertFromWikiProtocol(dir.getAreaNumber(), getInstance().getContentWithoutMacros());
  +    @Override
  +    public String update() {
  +        String outcome = super.update();
  +        if (outcome != null) endConversation();
  +        return null; // Prevent navigation
       }
   
  -    protected User getCurrentUser() {
  -        return user; // Return user from this persistence context
  +    @Override
  +    public String remove() {
  +        String outcome = super.remove();
  +        if (outcome != null) endConversation();
  +        return null; // Prevent navigation
       }
   
       /* -------------------------- Messages ------------------------------ */
  @@ -70,7 +112,7 @@
       protected void createdMessage() {
           getFacesMessages().addFromResourceBundleOrDefault(
                   SEVERITY_INFO,
  -                "lacewiki.msg.Topic.Persist",
  +                "forum.msg.Topic.Persist",
                   "Topic '{0}' has been saved.",
                   getInstance().getName()
           );
  @@ -79,7 +121,7 @@
       protected void updatedMessage() {
           getFacesMessages().addFromResourceBundleOrDefault(
                   SEVERITY_INFO,
  -                "lacewiki.msg.Topic.Update",
  +                "forum.msg.Topic.Update",
                   "Topic '{0}' has been updated.",
                   getInstance().getName()
           );
  @@ -88,50 +130,26 @@
       protected void deletedMessage() {
           getFacesMessages().addFromResourceBundleOrDefault(
                   SEVERITY_INFO,
  -                "lacewiki.msg.Topic.Delete",
  +                "forum.msg.Topic.Delete",
                   "Topic '{0}' has been deleted.",
                   getInstance().getName()
           );
       }
   
  -    /* -------------------------- Public Features ------------------------------ */
  -
  -    @Begin(flushMode = FlushModeType.MANUAL)
  -    public void newTopic() {
  -
  -        showForm = true;
  -
  -        // Start with a fresh instance
  -        setInstance(createInstance());
  -
  -        // Get a fresh parent directory instance into the current persistence context
  -        setParentDirectory(loadParentDirectory(getParentDirectory().getId()));
  -
  -        // Get a fresh user instance into the current persistence context
  -        user = getUserDAO().findUser(currentUser.getId());
  -
  -    }
  +    /* -------------------------- Internal Methods ------------------------------ */
   
  -    @End
  -    public void cancel() {
  +    private void endConversation() {
           showForm = false;
  +        Conversation.instance().end();
  +        getEntityManager().clear(); // Need to force re-read in the topic list refresh
  +        Events.instance().raiseEvent("Forum.topicListRefresh");
       }
   
  -    @End
  -    @RaiseEvent("Forum.topicPersisted")
  -    public String persist() {
  -        String outcome = super.persist();
  -        showForm = outcome == null; // Keep showing the form if there was a validation error
  -
  -        // Create feed entries (needs identifiers assigned, so we run after persist())
  -        if (outcome != null) {
  -            String feedEntryTitle = "[" + getParentDirectory().getName() + "] " + getInstance().getName();
  -            feedDAO.createFeedEntry(getInstance(), false, feedEntryTitle);
  -            getEntityManager().flush();
  +    protected String getFeedEntryManagerName() {
  +        return "forumTopicFeedEntryManager";
           }
   
  -        return outcome;
  -    }
  +    /* -------------------------- Public Features ------------------------------ */
   
       public boolean isShowForm() {
           return showForm;
  @@ -141,15 +159,32 @@
           this.showForm = showForm;
       }
   
  -    public String getFormContent() {
  -        // Load the topic content and resolve links
  -        if (formContent == null) syncInstanceToForm(getParentDirectory());
  -        return formContent;
  +    public boolean isSticky() {
  +        return sticky;
  +    }
  +
  +    public void setSticky(boolean sticky) {
  +        this.sticky = sticky;
  +    }
  +
  +    @Begin(flushMode = FlushModeType.MANUAL, join = true)
  +    public void newTopic() {
  +        setEdit(true);
  +        showForm = true;
  +    }
  +
  +    public void cancel() {
  +        endConversation();
       }
   
  -    public void setFormContent(String formContent) {
  -        this.formContent = formContent;
  -        if (formContent != null) syncFormToInstance(getParentDirectory());
  +    @RequestParameter("showTopicForm")
  +    public void showTopicForm(Boolean requestParam) {
  +        if (requestParam != null && requestParam && !showForm) {
  +            getLog().debug("request parameter sets topic form visible, starts conversation");
  +            Conversation.instance().begin(true, false);
  +            Conversation.instance().changeFlushMode(FlushModeType.MANUAL);
  +            newTopic();
  +        }
       }
   
   }
  
  
  
  1.2       +6 -6      jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/plugin/forum/ForumTopic.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: ForumTopic.java
  ===================================================================
  RCS file: /cvsroot/jboss/jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/plugin/forum/ForumTopic.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -b -r1.1 -r1.2
  --- ForumTopic.java	9 Nov 2007 15:00:28 -0000	1.1
  +++ ForumTopic.java	19 Dec 2007 04:29:25 -0000	1.2
  @@ -1,7 +1,5 @@
   package org.jboss.seam.wiki.plugin.forum;
   
  -import org.jboss.seam.wiki.core.model.Document;
  -import org.jboss.seam.wiki.core.model.Comment;
   import org.jboss.seam.wiki.core.search.annotations.Searchable;
   import org.jboss.seam.wiki.util.WikiUtil;
   
  @@ -22,12 +20,14 @@
    *
    * @author Christian Bauer
    */
  +/*
   @Entity
   @DiscriminatorValue("FORUMTOPIC")
   @org.hibernate.search.annotations.Indexed
   @Searchable(description = "Forum Topics")
  -public class ForumTopic extends Document {
  -
  +*/
  +public class ForumTopic {
  +/*
       @Transient
       protected final String[] MACROS_BEFORE_CONTENT =
               {"clearBackground", "forumPosting"};
  @@ -132,5 +132,5 @@
   
           return iconName.toString();
       }
  -
  +*/
   }
  
  
  
  1.3       +73 -94    jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/plugin/forum/ReplyHome.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: ReplyHome.java
  ===================================================================
  RCS file: /cvsroot/jboss/jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/plugin/forum/ReplyHome.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -b -r1.2 -r1.3
  --- ReplyHome.java	20 Nov 2007 08:05:10 -0000	1.2
  +++ ReplyHome.java	19 Dec 2007 04:29:25 -0000	1.3
  @@ -1,123 +1,102 @@
   package org.jboss.seam.wiki.plugin.forum;
   
  -import org.jboss.seam.wiki.core.action.CommentHome;
  -import org.jboss.seam.wiki.core.model.Comment;
  -import org.jboss.seam.wiki.core.model.Document;
  -import org.jboss.seam.wiki.core.model.User;
  -import org.jboss.seam.wiki.util.WikiUtil;
  -import org.jboss.seam.annotations.*;
  -import org.jboss.seam.ScopeType;
   import org.jboss.seam.Component;
  -import org.jboss.seam.international.Messages;
  +import org.jboss.seam.ScopeType;
  +import org.jboss.seam.security.Identity;
  +import org.jboss.seam.security.AuthorizationException;
  +import org.jboss.seam.annotations.Begin;
  +import org.jboss.seam.annotations.FlushModeType;
  +import org.jboss.seam.annotations.Name;
  +import org.jboss.seam.annotations.Scope;
  +import org.jboss.seam.wiki.core.action.CommentHome;
   
  -import java.util.Date;
  +import static javax.faces.application.FacesMessage.SEVERITY_INFO;
   
   @Name("replyHome")
   @Scope(ScopeType.CONVERSATION)
   public class ReplyHome extends CommentHome {
   
  +    @Override
  +    public void create() {
  +        super.create();
   
  -    @Create
  -    public void initialize() {
  -        super.initialize();
  -
  -        // Add this document to the "read" list in the forum cookie
  -        // TODO: At some point, this adds up to the 4 kb cookie value limit, maybe we should only store unread ids?
  -        ForumCookie forumCookie = (ForumCookie) Component.getInstance("forumCookie");
  -        forumCookie.addCookieValue(currentDocument.getId().toString(), "r");
  +        if (!getCurrentUser().isAdmin() && !getCurrentUser().isGuest()) {
  +            getLog().debug("### adding to read topics, forum id: "
  +                            + documentHome.getParentNode().getId() + " topic id: " + documentHome.getInstance().getId());
  +            ForumTopicReadManager forumTopicReadManager = (ForumTopicReadManager)Component.getInstance("forumTopicReadManager");
  +            forumTopicReadManager.addTopicId(documentHome.getParentNode().getId(), documentHome.getInstance().getId());
       }
  -
  -    private boolean showForm = false;
  -
  -    public boolean isShowForm() {
  -        return showForm;
       }
   
  -    public void setShowForm(boolean showForm) {
  -        this.showForm = showForm;
  -    }
  +    @Begin(flushMode = FlushModeType.MANUAL, join = true)
  +    public String replyToDocument() {
   
  -    public void createComment() {
  -        comment = new Comment();
  -        comment.setFromUser(currentUser);
  -    }
  +        getLog().debug("reply to document id: " + getParentNodeId());
  +        newComment();
  +        setEdit(true);
   
  -    public void createComment(Comment replyTo, boolean quote) {
  -        createComment();
  -        comment.setSubject(replyTo.getSubject());
  -        if (quote) comment.setText(quote(replyTo.getText(), replyTo.getCreatedOn(), replyTo.getFromUser()));
  -    }
  +        getInstance().setSubject(REPLY_PREFIX + getParentNode().getName());
   
  -    public void createComment(ForumTopic replyTo, boolean quote) {
  -        createComment();
  -        comment.setSubject(replyTo.getName());
  -        if (quote) comment.setText(quote(replyTo.getContentWithoutMacros(), replyTo.getCreatedOn(), replyTo.getCreatedBy()));
  +        return "redirectToDocument";
       }
   
  -    @Begin(flushMode = FlushModeType.MANUAL)
  -    public void newReplyToComment(Long commentId, boolean quote) {
  -        showForm = true;
  -
  -        // Take content from other comment
  -        Comment foundCommment = restrictedEntityManager.find(Comment.class, commentId);
  -        createComment(foundCommment, quote);
  -    }
  +    @Begin(flushMode = FlushModeType.MANUAL, join = true)
  +    public String quoteDocument() {
  +        replyToDocument();
   
  -    @Begin(flushMode = FlushModeType.MANUAL)
  -    public void newReplyToTopic(Long topicId, boolean quote) {
  -        showForm = true;
  +        getInstance().setContent(quote(
  +            documentHome.getInstance().getContent(),
  +            documentHome.getInstance().getCreatedOn(),
  +            documentHome.getInstance().getCreatedBy().getFullname()
  +        ));
   
  -        // Take content from topic
  -        ForumTopic topic = restrictedEntityManager.find(ForumTopic.class, topicId);
  -        createComment(topic, quote);
  +        return "redirectToDocument";
       }
   
  -    @End
  -    public void cancel() {
  -        showForm = false;
  +    /* Forum replies require write permissions on the forum directory */
  +    public boolean hasReplyPermission() {
  +        Integer currentAccessLevel = (Integer)Component.getInstance("currentAccessLevel");
  +        return Identity.instance().hasPermission("Comment", "create", documentHome.getInstance())
  +                && (documentHome.getParentNode().getWriteAccessLevel() <= currentAccessLevel);
       }
   
  -    @End
  -    @RaiseEvent("Forum.replyPersisted")
  -    public void persist() {
  -        Document doc = restrictedEntityManager.find(Document.class, currentDocument.getId());
  -        comment.setDocument(doc);
  -        // TODO: Break this, for performance reasons... doc.getComments().add(comment);
  -
  -        restrictedEntityManager.persist(comment);
  -
  -        StringBuilder feedEntryTitle = new StringBuilder();
  -        if (doc.getName().equals(comment.getSubject())) {
  -            feedEntryTitle.append("[").append(doc.getParent().getName()).append("] ");
  -            feedEntryTitle.append( Messages.instance().get("forum.label.reply.FeedEntryTitlePrefix") );
  -            feedEntryTitle.append(" ").append(comment.getSubject());
  -        } else {
  -            feedEntryTitle.append("[").append(doc.getParent().getName()).append("] ");
  -            feedEntryTitle.append("(");
  -            feedEntryTitle.append( Messages.instance().get("forum.label.reply.FeedEntryTitlePrefix") );
  -            feedEntryTitle.append(" ").append(WikiUtil.truncateString(doc.getName(), 20, "...")).append(") ");
  -            feedEntryTitle.append(comment.getSubject());
  +    protected void checkPersistPermissions() {
  +        if (!hasReplyPermission()) {
  +            throw new AuthorizationException("You don't have permission for this operation");
  +        }
           }
   
  -        pushOnFeeds(doc, feedEntryTitle.toString());
  +    protected String getFeedEntryManagerName() {
  +        return "forumReplyFeedEntryManager";
  +    }
   
  -        restrictedEntityManager.flush();
  -        restrictedEntityManager.clear();
  +    /* -------------------------- Messages ------------------------------ */
   
  -        refreshComments();
  +    protected void createdMessage() {
  +        getFacesMessages().addFromResourceBundleOrDefault(
  +                SEVERITY_INFO,
  +                "forum.msg.Reply.Persist",
  +                "Reply '{0}' has been saved.",
  +                getInstance().getSubject()
  +        );
  +    }
   
  -        showForm = false;
  +    protected void updatedMessage() {
  +        getFacesMessages().addFromResourceBundleOrDefault(
  +                SEVERITY_INFO,
  +                "forum.msg.Reply.Update",
  +                "Reply '{0}' has been updated.",
  +                getInstance().getSubject()
  +        );
       }
   
  -    private String quote(String text, Date date, User author) {
  -        StringBuilder quoted = new StringBuilder();
  -        quoted.append("<blockquote>").append("\n");
  -        quoted.append("_").append(author.getFullname());
  -        quoted.append(" ").append(Messages.instance().get("forum.label.WroteOn")).append(" ");
  -        quoted.append(WikiUtil.formatDate(date)).append(":").append("_").append("<br/>\n");
  -        quoted.append(text);
  -        quoted.append("\n").append("</blockquote>").append("\n\n");
  -        return quoted.toString();
  +    protected void deletedMessage() {
  +        getFacesMessages().addFromResourceBundleOrDefault(
  +                SEVERITY_INFO,
  +                "forum.msg.Reply.Delete",
  +                "Reply '{0}' has been deleted.",
  +                getInstance().getSubject()
  +        );
       }
   
   }
  
  
  
  1.2       +0 -27     jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/plugin/forum/ForumListHome.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: ForumListHome.java
  ===================================================================
  RCS file: /cvsroot/jboss/jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/plugin/forum/ForumListHome.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -b -r1.1 -r1.2
  --- ForumListHome.java	9 Nov 2007 15:00:28 -0000	1.1
  +++ ForumListHome.java	19 Dec 2007 04:29:25 -0000	1.2
  @@ -1,14 +1,7 @@
   package org.jboss.seam.wiki.plugin.forum;
   
   import org.jboss.seam.annotations.*;
  -import org.jboss.seam.annotations.security.Restrict;
   import org.jboss.seam.ScopeType;
  -import org.jboss.seam.Component;
  -import org.jboss.seam.contexts.Contexts;
  -import org.jboss.seam.wiki.core.model.Directory;
  -import org.jboss.seam.wiki.core.model.Node;
  -import org.jboss.seam.wiki.core.dao.NodeDAO;
  -import org.jboss.seam.wiki.util.WikiUtil;
   
   import javax.persistence.EntityManager;
   import java.io.Serializable;
  @@ -20,9 +13,6 @@
       @In
       EntityManager restrictedEntityManager;
   
  -    @In
  -    ForumHome forumHome;
  -
       private boolean managed;
   
       public boolean isManaged() {
  @@ -37,21 +27,4 @@
           managed = true;
       }
   
  -    @Restrict("#{s:hasPermission('Node', 'editMenu', currentDirectory)}")
  -    @RaiseEvent("Forum.forumListRefresh")
  -    public void moveNode(int currentPosition, int newPosition) {
  -        Directory forumDirectory = (Directory)Component.getInstance("currentDirectory");
  -        forumDirectory = restrictedEntityManager.find(Directory.class, forumDirectory.getId());
  -        if (currentPosition != newPosition) {
  -            // Shift and refresh displayed list
  -            WikiUtil.shiftListElement(forumDirectory.getChildren(), currentPosition, newPosition);
  -
  -            // Required update, this is only refreshed on database load
  -            for (Node node : forumDirectory.getChildren()) {
  -                node.setDisplayPosition(forumDirectory.getChildren().indexOf(node));
  -            }
  -        }
  -        Contexts.getPageContext().set("currentDirectory", forumDirectory);
  -    }
  -
   }
  
  
  
  1.2       +23 -10    jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/plugin/forum/ForumInfo.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: ForumInfo.java
  ===================================================================
  RCS file: /cvsroot/jboss/jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/plugin/forum/ForumInfo.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -b -r1.1 -r1.2
  --- ForumInfo.java	9 Nov 2007 15:00:28 -0000	1.1
  +++ ForumInfo.java	19 Dec 2007 04:29:25 -0000	1.2
  @@ -1,18 +1,24 @@
   package org.jboss.seam.wiki.plugin.forum;
   
  -import org.jboss.seam.wiki.core.model.Comment;
  +import org.jboss.seam.wiki.core.model.WikiComment;
  +import org.jboss.seam.wiki.core.model.WikiDocument;
  +import org.jboss.seam.wiki.core.model.WikiDirectory;
   
   public class ForumInfo {
   
  +    private WikiDirectory forum;
       private boolean unreadPostings = false;
       private long totalNumOfTopics;
       private long totalNumOfPosts;
  -    private ForumTopic lastTopic;
  -    private Comment lastComment;
  +    private WikiDocument lastTopic;
  +    private WikiComment lastComment;
   
  -    public ForumInfo(long totalNumOfTopics, long totalNumOfPosts) {
  -        this.totalNumOfTopics = totalNumOfTopics;
  -        this.totalNumOfPosts = totalNumOfPosts;
  +    public ForumInfo(WikiDirectory forum) {
  +        this.forum = forum;
  +    }
  +
  +    public WikiDirectory getForum() {
  +        return forum;
       }
   
       public boolean isUnreadPostings() {
  @@ -39,19 +45,19 @@
           this.totalNumOfPosts = totalNumOfPosts;
       }
   
  -    public ForumTopic getLastTopic() {
  +    public WikiDocument getLastTopic() {
           return lastTopic;
       }
   
  -    public void setLastTopic(ForumTopic lastTopic) {
  +    public void setLastTopic(WikiDocument lastTopic) {
           this.lastTopic = lastTopic;
       }
   
  -    public Comment getLastComment() {
  +    public WikiComment getLastComment() {
           return lastComment;
       }
   
  -    public void setLastComment(Comment lastComment) {
  +    public void setLastComment(WikiComment lastComment) {
           this.lastComment = lastComment;
       }
   
  @@ -62,4 +68,11 @@
           return false;
       }
   
  +    public String toString() {
  +        return "ForumInfo(" + getForum().getId() +
  +                ") topics: " + getTotalNumOfTopics() +
  +                ", posts: " + getTotalNumOfPosts() +
  +                ", last topic: " + getLastTopic() +
  +                ", last comment: " + getLastComment();
  +    }
   }
  
  
  
  1.1      date: 2007/12/19 04:29:25;  author: cbauer;  state: Exp;jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/plugin/forum/ForumTopicReadManager.java
  
  Index: ForumTopicReadManager.java
  ===================================================================
  package org.jboss.seam.wiki.plugin.forum;
  
  import org.jboss.seam.annotations.Name;
  import org.jboss.seam.annotations.Scope;
  import org.jboss.seam.annotations.AutoCreate;
  import org.jboss.seam.ScopeType;
  
  import java.io.Serializable;
  import java.util.Map;
  import java.util.Set;
  import java.util.HashMap;
  import java.util.HashSet;
  
  @Name("forumTopicReadManager")
  @Scope(ScopeType.SESSION)
  @AutoCreate
  public class ForumTopicReadManager implements Serializable {
  
      Map<Long, Set<Long>> readTopics = new HashMap<Long, Set<Long>>();
  
      public Map<Long, Set<Long>> getReadTopics() {
          return readTopics;
      }
  
      public void addTopicId(Long forumId, Long topicId) {
          if (readTopics.get(forumId) == null) {
              readTopics.put(forumId, new HashSet<Long>());
          }
          readTopics.get(forumId).add(topicId);
      }
  
      public void removeTopicId(Long forumId, Long topicId) {
          if (readTopics.get(forumId) != null) {
              readTopics.get(forumId).remove(topicId);
          }
      }
  
      public boolean isTopicIdRead(Long forumId, Long topicId) {
          return readTopics.get(forumId) != null && readTopics.get(forumId).contains(topicId);
      }
  
  }
  
  
  
  1.1      date: 2007/12/19 04:29:25;  author: cbauer;  state: Exp;jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/plugin/forum/TopicInfo.java
  
  Index: TopicInfo.java
  ===================================================================
  package org.jboss.seam.wiki.plugin.forum;
  
  import org.jboss.seam.wiki.core.model.WikiDocument;
  import org.jboss.seam.wiki.core.model.WikiComment;
  
  public class TopicInfo {
  
      private WikiDocument topic;
      private boolean unread;
      private boolean sticky;
      private long numOfReplies;
      private WikiComment lastComment;
  
      public TopicInfo(WikiDocument topic, Integer sticky) {
          this.topic = topic;
          this.sticky = sticky != 0;
      }
  
      public WikiDocument getTopic() {
          return topic;
      }
  
      public boolean isUnread() {
          return unread;
      }
  
      public void setUnread(boolean unread) {
          this.unread = unread;
      }
  
      public boolean isSticky() {
          return sticky;
      }
  
      public void setSticky(boolean sticky) {
          this.sticky = sticky;
      }
  
      public long getNumOfReplies() {
          return numOfReplies;
      }
  
      public void setNumOfReplies(long numOfReplies) {
          this.numOfReplies = numOfReplies;
      }
  
      public WikiComment getLastComment() {
          return lastComment;
      }
  
      public void setLastComment(WikiComment lastComment) {
          this.lastComment = lastComment;
      }
  
      public String getIconName() {
          StringBuilder iconName = new StringBuilder();
          iconName.append("posting");
          if (isSticky()) {
              iconName.append("_sticky");
          } else if (!topic.isEnableCommentForm()) {
              iconName.append("_locked");
          }
          if (isUnread()) iconName.append("_unread");
  
          return iconName.toString();
      }
  
  
      public String toString() {
          return "TopicInfo(" + getTopic().getId() +
                  ") replies: " + getNumOfReplies() +
                  ", unread: " + isUnread() +
                  ", sticky: " + isSticky() +
                  ", last comment: " + getLastComment();
      }
  
  }
  
  
  
  1.1      date: 2007/12/19 04:29:25;  author: cbauer;  state: Exp;jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/plugin/forum/ForumTopicFeedEntryManager.java
  
  Index: ForumTopicFeedEntryManager.java
  ===================================================================
  package org.jboss.seam.wiki.plugin.forum;
  
  import org.jboss.seam.wiki.core.feeds.WikiDocumentFeedEntryManager;
  import org.jboss.seam.wiki.core.model.WikiDocument;
  import org.jboss.seam.annotations.Name;
  
  @Name("forumTopicFeedEntryManager")
  public class ForumTopicFeedEntryManager extends WikiDocumentFeedEntryManager {
  
      public String getFeedEntryTitle(WikiDocument document) {
          return "[" + document.getParent().getName() + "] " + document.getName();
      }
  }
  
  
  
  1.1      date: 2007/12/19 04:29:25;  author: cbauer;  state: Exp;jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/plugin/forum/ForumReplyFeedEntryManager.java
  
  Index: ForumReplyFeedEntryManager.java
  ===================================================================
  package org.jboss.seam.wiki.plugin.forum;
  
  import org.jboss.seam.annotations.Name;
  import org.jboss.seam.wiki.core.feeds.WikiCommentFeedEntryManager;
  import org.jboss.seam.wiki.core.model.WikiComment;
  
  @Name("forumReplyFeedEntryManager")
  public class ForumReplyFeedEntryManager extends WikiCommentFeedEntryManager {
  
      public String getFeedEntryTitle(WikiComment comment) {
          return "[" + comment.getParentDocument().getParent().getName() + "] " + comment.getSubject();
      }
  
  }
  
  
  



More information about the jboss-cvs-commits mailing list