[jboss-cvs] jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action ...
Christian Bauer
christian at hibernate.org
Tue Dec 18 23:29:26 EST 2007
User: cbauer
Date: 07/12/18 23:29:26
Modified: examples/wiki/src/main/org/jboss/seam/wiki/core/action
WikiIdentity.java UserHome.java Authenticator.java
Breadcrumb.java CommentHome.java Help.java
DirectoryHome.java AdminHome.java
WikiRequestResolver.java Menu.java NodeHome.java
DocumentHome.java
Added: examples/wiki/src/main/org/jboss/seam/wiki/core/action
DocumentHistory.java TagQuery.java
CommentQuery.java UploadHome.java
Removed: examples/wiki/src/main/org/jboss/seam/wiki/core/action
NodeHistory.java FileHome.java TagHome.java
Log:
Major rewrite of the most of the application
Revision Changes Path
1.12 +51 -37 jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/WikiIdentity.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: WikiIdentity.java
===================================================================
RCS file: /cvsroot/jboss/jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/WikiIdentity.java,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -b -r1.11 -r1.12
--- WikiIdentity.java 9 Nov 2007 15:08:26 -0000 1.11
+++ WikiIdentity.java 19 Dec 2007 04:29:25 -0000 1.12
@@ -6,23 +6,23 @@
*/
package org.jboss.seam.wiki.core.action;
+import org.jboss.seam.Component;
import static org.jboss.seam.ScopeType.SESSION;
+import org.jboss.seam.annotations.AutoCreate;
+import org.jboss.seam.annotations.Install;
import static org.jboss.seam.annotations.Install.APPLICATION;
-
-import org.jboss.seam.security.Identity;
-import org.jboss.seam.security.AuthorizationException;
-import org.jboss.seam.annotations.*;
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.intercept.BypassInterceptors;
-import org.jboss.seam.wiki.core.model.User;
-import org.jboss.seam.wiki.core.model.Node;
-import org.jboss.seam.wiki.core.dao.UserRoleAccessFactory;
-import org.jboss.seam.wiki.core.action.prefs.WikiPreferences;
-import org.jboss.seam.Component;
import org.jboss.seam.core.Events;
-
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletResponse;
-import javax.faces.context.FacesContext;
+import org.jboss.seam.security.AuthorizationException;
+import org.jboss.seam.security.Identity;
+import org.jboss.seam.wiki.core.action.prefs.WikiPreferences;
+import org.jboss.seam.wiki.core.dao.UserRoleAccessFactory;
+import org.jboss.seam.wiki.core.model.User;
+import org.jboss.seam.wiki.core.model.WikiNode;
+import org.jboss.seam.wiki.core.model.Role;
+import org.jboss.seam.wiki.core.model.WikiDocument;
/**
* Need this until Drools fixes bugs and becomes usable/debuggable.
@@ -60,16 +60,16 @@
}
if ("Node".equals(name) && "create".equals(action)) {
- return checkCreateAccess( (Node)args[0]);
+ return checkCreateAccess( (WikiNode)args[0]);
} else
if ("Node".equals(name) && "edit".equals(action)) {
- return checkEditAccess((Node)args[0]);
+ return checkEditAccess((WikiNode)args[0]);
} else
if ("Node".equals(name) && "read".equals(action)) {
- return checkReadAccess((Node)args[0]);
+ return checkReadAccess((WikiNode)args[0]);
} else
if ("Node".equals(name) && "changeAccessLevel".equals(action)) {
- return checkRaiseAccessLevel((Node)args[0]);
+ return checkRaiseAccessLevel((WikiNode)args[0]);
} else
if ("User".equals(name) && "edit".equals(action)) {
return checkEditUser((User)args[0]);
@@ -81,13 +81,16 @@
return checkEditUserRoles((User)args[0]);
} else
if ("Node".equals(name) && "editMenu".equals(action)) {
- return checkEditMenu((Node)args[0]);
+ return checkEditMenu((WikiNode)args[0]);
} else
if ("User".equals(name) && "isAdmin".equals(action)) {
return checkIsAdmin((User)args[0]);
} else
+ if ("Comment".equals(name) && "create".equals(action)) {
+ return checkCommentCreate((WikiDocument)args[0]);
+ } else
if ("Comment".equals(name) && "delete".equals(action)) {
- return checkCommentDelete((Node)args[0]);
+ return checkCommentDelete((WikiNode)args[0]);
}
@@ -98,9 +101,9 @@
User either needs to have the access level of the parent directory
or the user is the creator of the parent directory
*/
- private boolean checkCreateAccess(Node directory) {
+ private boolean checkCreateAccess(WikiNode directory) {
//if (directory.getId().equals(wikiPrefs.getMemberAreaId())) return false; // Member home dir is immutable
- if (directory.getWriteAccessLevel() == UserRoleAccessFactory.GUESTROLE_ACCESSLEVEL) return true;
+ if (directory.getWriteAccessLevel() == Role.GUESTROLE_ACCESSLEVEL) return true;
int dirWriteAccessLevel = directory.getWriteAccessLevel();
User dirCreator = directory.getCreatedBy();
if (
@@ -116,8 +119,8 @@
/*
User either needs to have the access level of the edited node or has to be the creator
*/
- private boolean checkReadAccess(Node node) {
- if (node.getReadAccessLevel() == UserRoleAccessFactory.GUESTROLE_ACCESSLEVEL) return true;
+ private boolean checkReadAccess(WikiNode node) {
+ if (node.getReadAccessLevel() == Role.GUESTROLE_ACCESSLEVEL) return true;
int nodeReadAccessLevel = node.getReadAccessLevel();
User nodeCreator = node.getCreatedBy();
@@ -131,10 +134,12 @@
}
/*
- User either needs to have the access level of the edited node or has to be the creator
+ User either needs to have the access level of the edited node or has to be the creator,
+ if the node is write protected, he needs to be admin.
*/
- private boolean checkEditAccess(Node node) {
- if (node.getWriteAccessLevel() == UserRoleAccessFactory.GUESTROLE_ACCESSLEVEL) return true;
+ private boolean checkEditAccess(WikiNode node) {
+ if (node.isWriteProtected() && currentAccessLevel != Role.ADMINROLE_ACCESSLEVEL) return false;
+ if (node.getWriteAccessLevel() == Role.GUESTROLE_ACCESSLEVEL) return true;
int nodeWriteAccessLevel = node.getWriteAccessLevel();
User nodeCreator = node.getCreatedBy();
@@ -151,7 +156,7 @@
User can't persist or update a node and assign a higher access level than
he has, unless he is the creator
*/
- private boolean checkRaiseAccessLevel(Node node) {
+ private boolean checkRaiseAccessLevel(WikiNode node) {
//if (node.getId() != null && node.getId().equals(wikiPrefs.getMemberAreaId())) return false; // Member home dir is immutable
int desiredWriteAccessLevel = node.getWriteAccessLevel();
int desiredReadAccessLevel = node.getReadAccessLevel();
@@ -175,14 +180,14 @@
Only admins can change roles of a user
*/
private boolean checkEditUserRoles(User currentUser) {
- return currentAccessLevel == UserRoleAccessFactory.ADMINROLE_ACCESSLEVEL;
+ return currentAccessLevel == Role.ADMINROLE_ACCESSLEVEL;
}
/*
Only admins can edit users, or the user himself
*/
private boolean checkEditUser(User user) {
- if (currentAccessLevel == UserRoleAccessFactory.ADMINROLE_ACCESSLEVEL) return true;
+ if (currentAccessLevel == Role.ADMINROLE_ACCESSLEVEL) return true;
if (currentUser.getId().equals(user.getId())) return true;
return false;
}
@@ -197,15 +202,15 @@
if (user.getId().equals(adminUser.getId())) return false;
if (user.getId().equals(guestUser.getId())) return false;
- if (currentAccessLevel == UserRoleAccessFactory.ADMINROLE_ACCESSLEVEL) return true;
+ if (currentAccessLevel == Role.ADMINROLE_ACCESSLEVEL) return true;
return false;
}
/*
Admins can edit all menus, owners can edit their own.
*/
- private boolean checkEditMenu(Node node) {
- if (currentAccessLevel == UserRoleAccessFactory.ADMINROLE_ACCESSLEVEL) return true;
+ private boolean checkEditMenu(WikiNode node) {
+ if (currentAccessLevel == Role.ADMINROLE_ACCESSLEVEL) return true;
if (node.getCreatedBy().getId().equals(currentUser.getId())) return true;
return false;
}
@@ -214,16 +219,25 @@
Only admins are admins
*/
private boolean checkIsAdmin(User user) {
- if (currentAccessLevel == UserRoleAccessFactory.ADMINROLE_ACCESSLEVEL) return true;
+ if (currentAccessLevel == Role.ADMINROLE_ACCESSLEVEL) return true;
return false;
}
/*
- Only admins or document creator can delete comments
+ Only admins or enabled documents allow comments, if you can read the document.
*/
- private boolean checkCommentDelete(Node node) {
- if (currentAccessLevel == UserRoleAccessFactory.ADMINROLE_ACCESSLEVEL) return true;
- if (node.getCreatedBy().getId().equals(currentUser.getId())) return true;
+ private boolean checkCommentCreate(WikiDocument doc) {
+ if (currentAccessLevel == Role.ADMINROLE_ACCESSLEVEL) return true;
+ if (doc.getReadAccessLevel() <= currentAccessLevel &&
+ doc.isEnableComments() && doc.isEnableCommentForm()) return true;
+ return false;
+ }
+
+ /*
+ Only admins can delete comments.
+ */
+ private boolean checkCommentDelete(WikiNode node) {
+ if (currentAccessLevel == Role.ADMINROLE_ACCESSLEVEL) return true;
return false;
}
1.18 +52 -35 jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/UserHome.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: UserHome.java
===================================================================
RCS file: /cvsroot/jboss/jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/UserHome.java,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -b -r1.17 -r1.18
--- UserHome.java 12 Oct 2007 16:31:25 -0000 1.17
+++ UserHome.java 19 Dec 2007 04:29:25 -0000 1.18
@@ -24,7 +24,10 @@
import org.jboss.seam.wiki.core.dao.UserDAO;
import org.jboss.seam.wiki.core.model.Role;
import org.jboss.seam.wiki.core.model.User;
-import org.jboss.seam.wiki.core.ui.FileMetaMap;
+import org.jboss.seam.wiki.core.model.WikiUpload;
+import org.jboss.seam.wiki.core.model.WikiUploadImage;
+import org.jboss.seam.wiki.core.upload.UploadType;
+import org.jboss.seam.wiki.core.upload.Uploader;
import org.jboss.seam.wiki.preferences.PreferenceComponent;
import org.jboss.seam.wiki.preferences.PreferenceVisibility;
import org.jboss.seam.wiki.util.Hash;
@@ -64,9 +67,6 @@
@In(create = true)
private Renderer renderer;
- @In
- Map<String, FileMetaMap.FileMetaInfo> fileMetaMap;
-
@DataModel
private List<PreferenceComponent> userPreferenceComponents;
PreferenceEditor preferenceEditor;
@@ -76,9 +76,15 @@
private String passwordControl;
private List<Role> roles;
private org.jboss.seam.wiki.core.model.Role defaultRole;
- private String portraitContentType;
- // TODO: This should really use an InputStream and directly stream into the BLOB without consuming server memory
- private byte[] portraitImageData;
+ private Uploader uploader;
+
+ public Uploader getUploader() {
+ return uploader;
+ }
+
+ public void setUploader(Uploader uploader) {
+ this.uploader = uploader;
+ }
public void init() {
if (isManaged()) {
@@ -88,6 +94,8 @@
if (roles == null) roles = getInstance().getRoles();
if (oldUsername == null) oldUsername = getInstance().getUsername();
+ uploader = (Uploader)Component.getInstance("uploader");
+
} else {
UserManagementPreferences userMgmtPrefs =
(UserManagementPreferences) Component.getInstance("userManagementPreferences");
@@ -159,9 +167,26 @@
@Restrict("#{s:hasPermission('User', 'edit', userHome.instance)}")
public String update() {
- // Validate
- if (!isUniqueUsername())
- return null;
+ if (uploader.hasData()) {
+ uploader.uploadNewInstance();
+ if (WikiUploadImage.class.isAssignableFrom(uploader.getUpload().getClass())) {
+ WikiUploadImage portrait = (WikiUploadImage)uploader.getUpload();
+ getLog().debug("updating portrait file data/type");
+ getInstance().getProfile().setImageContentType(portrait.getContentType());
+ getInstance().getProfile().setImage(
+ WikiUtil.resizeImage(portrait.getData(), portrait.getContentType(), 80) // TODO: Make size configurable?
+ );
+
+ } else {
+ facesMessages.addFromResourceBundleOrDefault(
+ FacesMessage.SEVERITY_ERROR,
+ "lacewiki.msg.userHome.WrongPortraitImageType",
+ "The file type '{0}' is not supported, the portrait was not updated.",
+ uploader.getUpload().getContentType()
+ );
+ }
+ }
+ uploader.reset();
User adminUser = (User)Component.getInstance("adminUser");
User guestUser = (User)Component.getInstance("guestUser");
@@ -201,26 +226,11 @@
}
// User changed his username
- if (!getInstance().getUsername().equals(oldUsername)) loginCredentialsModified = true;
-
- // Profile image upload
- if (portraitImageData != null && portraitImageData.length > 0) {
+ if (!getInstance().getUsername().equals(oldUsername)) {
+ loginCredentialsModified = true;
- if (fileMetaMap.get(portraitContentType) != null &&
- fileMetaMap.get(portraitContentType).image) {
- getLog().debug("updating portrait file data/type");
- getInstance().getProfile().setImageContentType(portraitContentType);
- getInstance().getProfile().setImage(
- WikiUtil.resizeImage(portraitImageData, portraitContentType, 80)
- );
- } else {
- facesMessages.addFromResourceBundleOrDefault(
- FacesMessage.SEVERITY_ERROR,
- "lacewiki.msg.WrongPortraitImageType",
- "The file type '{0}' is not supported, the portrait was not updated.",
- portraitContentType
- );
- }
+ // Validate
+ if (!isUniqueUsername()) return null;
}
if (Identity.instance().hasPermission("User", "isAdmin", Component.getInstance("currentUser"))) {
@@ -259,6 +269,19 @@
return super.remove();
}
+ @Restrict("#{s:hasPermission('User', 'edit', userHome.instance)}")
+ public void removePortrait() {
+ getInstance().getProfile().setImage(null);
+ getInstance().getProfile().setImageContentType(null);
+
+ facesMessages.addFromResourceBundleOrDefault(
+ FacesMessage.SEVERITY_INFO,
+ "lacewiki.msg.userHome.PortraitRemoved",
+ "The portrait has been removed, save to make changes permanent."
+ );
+ }
+
+
/* -------------------------- Messages ------------------------------ */
protected void createdMessage() {
@@ -294,12 +317,6 @@
public String getPasswordControl() { return passwordControl; }
public void setPasswordControl(String passwordControl) { this.passwordControl = passwordControl; }
- public String getPortraitContentType() { return portraitContentType; }
- public void setPortraitContentType(String portraitContentType) { this.portraitContentType = portraitContentType; }
-
- public byte[] getPortraitImageData() { return portraitImageData; }
- public void setPortraitImageData(byte[] portraitImageData) { this.portraitImageData = portraitImageData; }
-
public List<Role> getRoles() { return roles; }
@Restrict("#{s:hasPermission('User', 'editRoles', currentUser)}")
public void setRoles(List<Role> roles) { this.roles = roles; }
1.11 +20 -18 jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/Authenticator.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: Authenticator.java
===================================================================
RCS file: /cvsroot/jboss/jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/Authenticator.java,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -b -r1.10 -r1.11
--- Authenticator.java 13 Nov 2007 07:58:09 -0000 1.10
+++ Authenticator.java 19 Dec 2007 04:29:25 -0000 1.11
@@ -8,16 +8,15 @@
import org.jboss.seam.annotations.*;
import org.jboss.seam.wiki.core.dao.UserDAO;
-import org.jboss.seam.wiki.core.dao.NodeDAO;
-import org.jboss.seam.wiki.core.dao.UserRoleAccessFactory;
+import org.jboss.seam.wiki.core.dao.WikiNodeDAO;
import org.jboss.seam.wiki.core.model.*;
import org.jboss.seam.wiki.core.model.Role;
import org.jboss.seam.wiki.core.action.prefs.UserManagementPreferences;
+import org.jboss.seam.wiki.core.engine.MacroWikiTextRenderer;
import org.jboss.seam.wiki.util.WikiUtil;
import org.jboss.seam.wiki.util.Hash;
import org.jboss.seam.ScopeType;
import org.jboss.seam.Component;
-import org.jboss.seam.persistence.PersistenceProvider;
import org.jboss.seam.log.Log;
import org.jboss.seam.util.Base64;
import org.jboss.seam.core.Events;
@@ -85,7 +84,7 @@
}
private User getUserForCredentials(String username, String password) {
- if (org.jboss.seam.wiki.core.dao.UserRoleAccessFactory.GUEST_USERNAME.equals(username)) return null;
+ if (User.GUEST_USERNAME.equals(username)) return null;
User user = userDAO.findUser(username, true, true);
if (user == null || password == null || !user.getPasswordHash().equalsIgnoreCase(hashUtil.hash(password))) {
log.info("Invalid authentication credentials for user: " + username);
@@ -131,19 +130,18 @@
public void createHomeDirectory(User user) {
- NodeDAO nodeDAO = (NodeDAO)Component.getInstance("nodeDAO");
+ WikiNodeDAO nodeDAO = (WikiNodeDAO)Component.getInstance("wikiNodeDAO");
// Create home directory
- Directory memberArea = (Directory)Component.getInstance("memberArea");
+ WikiDirectory memberArea = (WikiDirectory)Component.getInstance("memberArea");
- Directory homeDirectory = new Directory(user.getUsername());
+ WikiDirectory homeDirectory = new WikiDirectory(user.getUsername());
homeDirectory.setWikiname(WikiUtil.convertToWikiName(homeDirectory.getName()));
homeDirectory.setAreaNumber(memberArea.getAreaNumber());
homeDirectory.setCreatedBy(user);
- homeDirectory.setWriteAccessLevel(UserRoleAccessFactory.ADMINROLE_ACCESSLEVEL);
- homeDirectory.setReadAccessLevel(UserRoleAccessFactory.GUESTROLE_ACCESSLEVEL);
- homeDirectory.setMenuItem(true);
- memberArea.addChild(homeDirectory);
+ homeDirectory.setWriteAccessLevel(Role.ADMINROLE_ACCESSLEVEL);
+ homeDirectory.setReadAccessLevel(Role.GUESTROLE_ACCESSLEVEL);
+ homeDirectory.setParent(memberArea);
user.setMemberHome(homeDirectory);
// Create feed for home directory
@@ -156,19 +154,23 @@
nodeDAO.makePersistent(homeDirectory);
// Create home page
- Document homePage = new Document("Home of " + user.getUsername());
+ WikiDocument homePage = new WikiDocument();
+ homePage.setName("Home of " + user.getUsername());
homePage.setWikiname(WikiUtil.convertToWikiName(homePage.getName()));
homePage.setCreatedBy(user);
homePage.setAreaNumber(homeDirectory.getAreaNumber());
homePage.setContent(
((UserManagementPreferences)Component.getInstance("userManagementPreferences")).getHomepageDefaultContent()
);
- homePage.setWriteAccessLevel(UserRoleAccessFactory.ADMINROLE_ACCESSLEVEL);
- homePage.setReadAccessLevel(UserRoleAccessFactory.GUESTROLE_ACCESSLEVEL);
- homePage.setMenuItem(true);
- homePage.setMacros(WikiUtil.findMacros(homePage, homeDirectory, homePage.getContent()));
- homeDirectory.addChild(homePage);
- homeDirectory.setDefaultDocument(homePage);
+ homePage.setWriteAccessLevel(Role.ADMINROLE_ACCESSLEVEL);
+ homePage.setReadAccessLevel(Role.GUESTROLE_ACCESSLEVEL);
+
+ MacroWikiTextRenderer renderer = MacroWikiTextRenderer.renderMacros(homeDirectory.getAreaNumber(), homePage.getContent());
+ homePage.setContentMacros(renderer.getMacros());
+ homePage.setContentMacrosString(renderer.getMacrosString());
+
+ homePage.setParent(homeDirectory);
+ homeDirectory.setDefaultFile(homePage);
nodeDAO.makePersistent(homePage);
}
1.3 +23 -12 jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/Breadcrumb.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: Breadcrumb.java
===================================================================
RCS file: /cvsroot/jboss/jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/Breadcrumb.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- Breadcrumb.java 3 Sep 2007 10:36:34 -0000 1.2
+++ Breadcrumb.java 19 Dec 2007 04:29:25 -0000 1.3
@@ -1,42 +1,53 @@
package org.jboss.seam.wiki.core.action;
-import org.jboss.seam.annotations.*;
-import org.jboss.seam.ScopeType;
import org.jboss.seam.Component;
+import org.jboss.seam.ScopeType;
+import org.jboss.seam.annotations.*;
+import org.jboss.seam.log.Log;
import org.jboss.seam.security.Identity;
-import org.jboss.seam.wiki.core.model.Node;
-import org.jboss.seam.wiki.core.model.Directory;
+import org.jboss.seam.wiki.core.model.WikiDirectory;
+import org.jboss.seam.wiki.core.model.WikiNode;
import java.io.Serializable;
-import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.List;
@Name("breadcrumbFactory")
- at Scope(ScopeType.PAGE)
+ at Scope(ScopeType.CONVERSATION)
public class Breadcrumb implements Serializable {
+ @Logger
+ Log log;
+
@In(required = false)
- Node currentLocation;
+ WikiNode currentLocation;
@Factory(value = "breadcrumb", autoCreate = true)
- public List<Node> unwrap() {
+ public List<WikiNode> unwrap() {
// TODO: Maybe a nested set query would be more efficient?
- List<Node> currentPath = new ArrayList<Node>();
+ log.debug("breadcrumb starting at current location: " + currentLocation);
+ List<WikiNode> currentPath = new ArrayList<WikiNode>();
if (currentLocation == null) return currentPath;
addToPath(currentPath, currentLocation);
Collections.reverse(currentPath);
return currentPath;
}
- protected void addToPath(List<Node> path, Node currentLocation) {
+ protected void addToPath(List<WikiNode> path, WikiNode currentLocation) {
if (Identity.instance().hasPermission("Node", "read", currentLocation) &&
- currentLocation.getId() != null &&
- !currentLocation.getId().equals( ((Directory) Component.getInstance("wikiRoot")).getId() ) )
+ currentLocation.getId() != null && !isRootWikiNode(currentLocation) ) {
+ log.debug("adding to breadcrumb: " + currentLocation);
path.add(currentLocation);
+
+ }
if (currentLocation.getParent() != null ) {
addToPath(path, currentLocation.getParent());
}
}
+ private boolean isRootWikiNode(WikiNode node) {
+ return (node.isInstance(WikiDirectory.class) && node.getId().equals(((WikiDirectory) Component.getInstance("wikiRoot")).getId()));
+ }
+
}
1.14 +223 -88 jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/CommentHome.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: CommentHome.java
===================================================================
RCS file: /cvsroot/jboss/jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/CommentHome.java,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -b -r1.13 -r1.14
--- CommentHome.java 20 Nov 2007 08:05:12 -0000 1.13
+++ CommentHome.java 19 Dec 2007 04:29:25 -0000 1.14
@@ -6,149 +6,284 @@
*/
package org.jboss.seam.wiki.core.action;
-import org.jboss.seam.annotations.*;
import org.jboss.seam.ScopeType;
-import org.jboss.seam.international.Messages;
-import org.jboss.seam.security.Identity;
+import org.jboss.seam.Component;
import org.jboss.seam.security.AuthorizationException;
+import org.jboss.seam.security.Identity;
+import org.jboss.seam.core.Events;
+import org.jboss.seam.core.Conversation;
+import org.jboss.seam.international.Messages;
+import org.jboss.seam.annotations.*;
+import org.jboss.seam.annotations.web.RequestParameter;
+import org.jboss.seam.wiki.core.feeds.FeedDAO;
+import org.jboss.seam.wiki.core.feeds.FeedEntryManager;
import org.jboss.seam.wiki.core.model.*;
-import org.jboss.seam.wiki.core.dao.FeedDAO;
+import org.jboss.seam.wiki.core.action.prefs.CommentsPreferences;
import org.jboss.seam.wiki.util.WikiUtil;
-import javax.persistence.EntityManager;
-import java.io.Serializable;
-import java.util.List;
-import java.util.ArrayList;
+import static javax.faces.application.FacesMessage.SEVERITY_INFO;
+import java.util.Date;
@Name("commentHome")
- at Scope(ScopeType.PAGE)
-public class CommentHome implements Serializable {
+ at Scope(ScopeType.CONVERSATION)
+public class CommentHome extends NodeHome<WikiComment, WikiNode>{
- @In
- FeedDAO feedDAO;
+ public static final String REPLY_PREFIX = "Re: ";
- @In
- protected EntityManager restrictedEntityManager;
+ /* -------------------------- Context Wiring ------------------------------ */
@In
- protected Document currentDocument;
+ protected DocumentHome documentHome;
@In
- protected User currentUser;
+ protected FeedDAO feedDAO;
@In
- protected User guestUser;
+ protected CommentsPreferences commentsPreferences;
- @In("#{commentsPreferences.properties['listAscending']}")
- protected boolean listCommentsAscending;
+ /* -------------------------- Internal State ------------------------------ */
- protected Comment comment;
- protected List<Comment> comments;
+ @RequestParameter
+ private Long parentCommentId;
+ private boolean showForm = false;
- @Create
- public void initialize() {
- refreshComments();
+ /* -------------------------- Basic Overrides ------------------------------ */
+
+ @Override
+ protected boolean isPageRootController() {
+ return false;
}
- @Observer(value = {"PersistenceContext.filterReset", "PreferenceComponent.refresh.commentsPreferences"}, create = false)
- public void refreshComments() {
+ public Class<WikiComment> getEntityClass() {
+ return WikiComment.class;
+ }
- comments = new ArrayList<Comment>();
+ @Override
+ public void create() {
+ super.create();
+ setParentNodeId(documentHome.getInstance().getId());
+ }
- //noinspection unchecked
- comments = restrictedEntityManager
- .createQuery("select c from Comment c left join fetch c.fromUser u left join fetch u.profile fetch all properties where c.document is :doc" +
- " order by c.createdOn " + (listCommentsAscending ? "asc" : "desc") )
- .setParameter("doc", currentDocument)
- .setHint("org.hibernate.cacheable", true)
- .getResultList();
+ @Override
+ public WikiComment findInstance() {
+ return getWikiNodeDAO().findWikiComment((Long)getId());
+ }
- createComment(); // Stay inside the same persistence context
+ @Override
+ protected WikiNode findParentNode(Long parentNodeId) {
+ return getEntityManager().find(WikiNode.class, parentNodeId);
}
- public void createComment() {
+ @Override
+ public WikiComment afterNodeCreated(WikiComment comment) {
+ comment = super.afterNodeCreated(comment);
- User user = restrictedEntityManager.find(User.class, currentUser.getId());
+ comment.setAreaNumber(documentHome.getInstance().getAreaNumber());
+ comment.setDerivedName(documentHome.getInstance());
+ comment.setWikiname(comment.getName());
+ comment.setCreatedBy(getCurrentUser());
- comment = new Comment();
- if (!user.getId().equals(guestUser.getId())) {
- comment.setFromUserName(user.getFullname());
- comment.setFromUserEmail(user.getEmail());
- // Profile website overrides member home website
- comment.setFromUserHomepage(
- user.getProfile() != null && user.getProfile().getWebsite() != null
- ? user.getProfile().getWebsite()
- : user.getMemberHome() != null ? WikiUtil.renderHomeURL(user) : null);
+ // TODO: This means that when a user is deleted, his name will still be preserved. However, it's an old name.
+ if (comment.isOwnedByRegularUser()) {
+ comment.setFromUserName(getCurrentUser().getFullname());
}
// Default to title of document as subject
- comment.setSubject(currentDocument.getName());
+ comment.setSubject(documentHome.getInstance().getName());
// Default to help text
- comment.setText(Messages.instance().get("lacewiki.msg.commentForm.EditThisTextPreviewUpdatesAutomatically"));
+ comment.setContent(Messages.instance().get("lacewiki.msg.wikiTextEditor.EditThisTextPreviewUpdatesAutomatically"));
+
+ return comment;
}
- public void persist() {
+ protected void checkPersistPermissions() {
+ getLog().trace("checking comment persist permissions");
+ if (!Identity.instance().hasPermission("Comment", "create", documentHome.getInstance()) ) {
+ throw new AuthorizationException("You don't have permission for this operation");
+ }
+ }
+
+ /* -------------------------- Custom CUD ------------------------------ */
+
+ @Override
+ public String persist() {
+ String outcome = super.persist();
+ if (outcome != null) {
+
+ if (documentHome.getInstance().isEnableCommentsOnFeeds()) {
+ FeedEntry feedEntry =
+ ((FeedEntryManager) Component.getInstance(getFeedEntryManagerName())).createFeedEntry(getInstance());
+ feedDAO.createFeedEntry(documentHome.getParentNode(), documentHome.getInstance(), feedEntry, false);
+
+ getEntityManager().flush();
+ }
+
+ Events.instance().raiseEvent("Comment.persisted");
+ endConversation();
+ }
+ return null; // Prevent navigation
+ }
+
+ /* -------------------------- Messages ------------------------------ */
+
+ @Override
+ protected void createdMessage() {
+ getFacesMessages().addFromResourceBundleOrDefault(
+ SEVERITY_INFO,
+ "lacewiki.msg.Comment.Persist",
+ "Comment '{0}' has been saved.",
+ getInstance().getSubject()
+ );
+ }
- Document doc = restrictedEntityManager.find(Document.class, currentDocument.getId());
- comment.setDocument(doc);
- doc.getComments().add(comment);
+ @Override
+ protected void updatedMessage() {
+ getFacesMessages().addFromResourceBundleOrDefault(
+ SEVERITY_INFO,
+ "lacewiki.msg.Comment.Update",
+ "Comment '{0}' has been updated.",
+ getInstance().getSubject()
+ );
+ }
- // Null out the property so that the @Email validator doesn't fall over it...
- // I hate JSF and its "let's set an empty string" behavior
- comment.setFromUserEmail(
- comment.getFromUserEmail()!=null && comment.getFromUserEmail().length()>0
- ? comment.getFromUserEmail()
- : null
+ @Override
+ protected void deletedMessage() {
+ getFacesMessages().addFromResourceBundleOrDefault(
+ SEVERITY_INFO,
+ "lacewiki.msg.Comment.Delete",
+ "Comment '{0}' has been deleted.",
+ getInstance().getSubject()
);
+ }
- restrictedEntityManager.persist(comment);
+ /* -------------------------- Internal Methods ------------------------------ */
- pushOnFeeds(doc, null);
+ protected void endConversation() {
+ showForm = false;
+ Conversation.instance().end();
+ getEntityManager().clear(); // Need to force re-read in the topic list refresh
+ Events.instance().raiseEvent("Comment.commentListRefresh");
+ }
- refreshComments();
- createComment();
+ protected String getFeedEntryManagerName() {
+ return "wikiCommentFeedEntryManager";
}
- public void remove(Long commentId) {
+ protected void setReplySubject(WikiComment parentComment) {
+ if (!parentComment.getSubject().equals(documentHome.getInstance().getName())) {
+ if (parentComment.getSubject().startsWith(REPLY_PREFIX)) {
+ getInstance().setSubject(parentComment.getSubject());
+ } else {
+ getInstance().setSubject(REPLY_PREFIX + parentComment.getSubject());
+ }
+ }
+ }
- Comment foundCommment = restrictedEntityManager.find(Comment.class, commentId);
- if (foundCommment != null) {
- if (!Identity.instance().hasPermission("Comment", "delete", foundCommment.getDocument()) ) {
- throw new AuthorizationException("You don't have permission for this operation");
+ protected void setQuotedContent(WikiComment parentComment) {
+ getInstance().setContent(quote(
+ parentComment.getContent(),
+ parentComment.getCreatedOn(),
+ parentComment.isOwnedByRegularUser() ? parentComment.getCreatedBy().getFullname() : parentComment.getFromUserName()
+ ));
+ }
+
+ protected String quote(String text, Date date, String authorName) {
+ StringBuilder quoted = new StringBuilder();
+ quoted.append("<blockquote>").append("\n");
+ quoted.append("_").append(authorName);
+ 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");
+ quoted.append(Messages.instance().get("lacewiki.msg.wikiTextEditor.EditThisTextPreviewUpdatesAutomatically"));
+ return quoted.toString();
}
- restrictedEntityManager.remove(foundCommment);
+ /* -------------------------- Public Features ------------------------------ */
- Document doc = restrictedEntityManager.find(Document.class, currentDocument.getId());
- feedDAO.removeFeedEntry(doc, foundCommment);
+ public boolean isShowForm() {
+ return showForm;
}
- refreshComments();
- createComment();
+ public void setShowForm(boolean showForm) {
+ this.showForm = showForm;
}
- protected void pushOnFeeds(Document document, String title) {
+ @Begin(flushMode = FlushModeType.MANUAL, join = true)
+ public String newComment() {
+ setEdit(true);
+ showForm = true;
+ return "redirectToDocument";
+ }
+
+ @Begin(flushMode = FlushModeType.MANUAL, join = true)
+ public String replyTo() {
+ if (parentCommentId == null || parentCommentId.equals(0l))
+ throw new IllegalStateException("Missing parentCommentId request parameter");
+
+ if (commentsPreferences.getThreadedComments()) {
+ // Override parent from @Create
+ setParentNodeId(parentCommentId);
+ }
+ getLog().debug("reply to comment id: " + parentCommentId);
+ newComment();
- String feedEntryTitle =
- title == null
- ? Messages.instance().get("lacewiki.label.comment.FeedEntryTitlePrefix") + " " + comment.getSubject()
- : title;
- if (currentDocument.getEnableComments() && document.getEnableCommentsOnFeeds()) {
- feedDAO.createFeedEntry(document, comment, false, feedEntryTitle);
+ if (commentsPreferences.getThreadedComments()) {
+ getInstance(); // Init
+ setReplySubject((WikiComment)getParentNode());
+ } else {
+ setReplySubject(getWikiNodeDAO().findWikiComment(parentCommentId));
}
+ return "redirectToDocument";
}
- public Comment getComment() {
- return comment;
+ @Begin(flushMode = FlushModeType.MANUAL, join = true)
+ public String quote() {
+ replyTo();
+
+ if (commentsPreferences.getThreadedComments()) {
+ setQuotedContent((WikiComment)getParentNode());
+ } else {
+ setQuotedContent(getWikiNodeDAO().findWikiComment(parentCommentId));
+ }
+ return "redirectToDocument";
+ }
+
+ public void cancel() {
+ endConversation();
+ }
+
+ public void remove(Long commentId) {
+ setNodeId(commentId);
+ setEdit(true);
+ if (isManaged()) {
+
+ // Additional permission required besides NodeHome.remove()
+ if (!Identity.instance().hasPermission("Comment", "delete", getInstance().getParent()) ) {
+ throw new AuthorizationException("You don't have permission for this operation");
}
- public void setComment(Comment comment) {
- this.comment = comment;
+ // Remove feed entry before removing comment
+ feedDAO.removeFeedEntry(
+ feedDAO.findFeeds(getInstance()),
+ feedDAO.findFeedEntry(getInstance())
+ );
+
+ remove();
+ getEntityManager().clear();
+ Events.instance().raiseEvent("Comment.commentListRefresh");
+ }
}
- public List<Comment> getComments() {
- return comments;
+ @RequestParameter("showCommentForm")
+ public void showCommentForm(Boolean requestParam) {
+ if (requestParam != null && requestParam && !showForm) {
+ getLog().debug("request parameter sets comment form visible, starts conversation");
+ Conversation.instance().begin(true, false);
+ Conversation.instance().changeFlushMode(FlushModeType.MANUAL);
+ newComment();
+ }
}
}
1.4 +63 -49 jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/Help.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: Help.java
===================================================================
RCS file: /cvsroot/jboss/jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/Help.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- Help.java 9 Nov 2007 15:08:26 -0000 1.3
+++ Help.java 19 Dec 2007 04:29:25 -0000 1.4
@@ -1,81 +1,95 @@
package org.jboss.seam.wiki.core.action;
-import org.jboss.seam.annotations.Name;
-import org.jboss.seam.annotations.Scope;
-import org.jboss.seam.annotations.In;
-import org.jboss.seam.annotations.Logger;
import org.jboss.seam.ScopeType;
-import org.jboss.seam.log.Log;
+import org.jboss.seam.annotations.*;
import org.jboss.seam.framework.EntityNotFoundException;
-import org.jboss.seam.wiki.core.model.Document;
-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.log.Log;
import org.jboss.seam.wiki.core.action.prefs.WikiPreferences;
-import org.jboss.seam.wiki.core.nestedset.NestedSetNodeWrapper;
+import org.jboss.seam.wiki.core.dao.WikiNodeDAO;
+import org.jboss.seam.wiki.core.model.WikiDirectory;
+import org.jboss.seam.wiki.core.model.WikiDocument;
+import org.jboss.seam.wiki.core.nestedset.query.NestedSetNodeWrapper;
import org.jboss.seam.wiki.util.WikiUtil;
import java.io.Serializable;
@Name("help")
- at Scope(ScopeType.PAGE)
+ at Scope(ScopeType.SESSION)
public class Help implements Serializable {
@Logger
Log log;
@In
- NodeDAO nodeDAO;
+ WikiNodeDAO wikiNodeDAO;
@In
WikiPreferences wikiPreferences;
- NestedSetNodeWrapper<Node> root;
+ NestedSetNodeWrapper<WikiDirectory> root;
- public NestedSetNodeWrapper<Node> getRoot() {
- // If this is the first time or if the preferences changed... (re)load the help document tree
- if (root == null || !root.getWrappedNode().getName().equals(wikiPreferences.getHelpArea()) ) {
- Directory helpAreaRoot = nodeDAO.findArea(WikiUtil.convertToWikiName(wikiPreferences.getHelpArea()));
- if (helpAreaRoot != null) {
+ public NestedSetNodeWrapper<WikiDirectory> getRoot() {
+ if (root == null) refreshRoot();
+ return root;
+ }
+
+ // TODO: Find event that triggers help document updates... difficult
+ //@Observer(value = "Nodes.menuStructureModified", create = false)
+ public void refreshRoot() {
log.debug("Loading help documents tree");
- root = nodeDAO.findMenuItems(helpAreaRoot, 99l, 1l, false);
+ WikiDirectory helpAreaRoot = wikiNodeDAO.findArea(WikiUtil.convertToWikiName(wikiPreferences.getHelpArea()));
+ if (helpAreaRoot != null) {
+ root = wikiNodeDAO.findWikiDirectoryTree(helpAreaRoot, 99l, 1l, false);
} else {
- throw new EntityNotFoundException("Help Area: '" + wikiPreferences.getHelpArea() + "'", Directory.class);
+ throw new EntityNotFoundException("Help Area: '" + wikiPreferences.getHelpArea() + "'", WikiDirectory.class);
}
}
- return root;
- }
- Document selectedDocument;
- Directory selectedDirectory;
- public Document getSelectedDocument() { return selectedDocument; }
- public Directory getSelectedDirectory() { return selectedDirectory; }
-
- NestedSetNodeWrapper<Node> selectedNode;
- public NestedSetNodeWrapper<Node> getSelectedNode() { return selectedNode; }
- public void setSelectedNode(NestedSetNodeWrapper<Node> selectedNode) {
+ // Needed for the tree dropdown
+ NestedSetNodeWrapper<WikiDirectory> selectedNode;
+ public NestedSetNodeWrapper<WikiDirectory> getSelectedNode() {
+ return selectedNode;
+ }
+ public void setSelectedNode(NestedSetNodeWrapper<WikiDirectory> selectedNode) {
this.selectedNode = selectedNode;
+ setSelectedDirectory(selectedNode.getWrappedNode());
+ setSelectedDocument(null);
+ }
+ WikiDocument selectedDocument;
+ WikiDirectory selectedDirectory;
- selectedDirectory = null;
- selectedDocument = null;
- if (selectedNode != null) {
- if (WikiUtil.isDirectory( selectedNode.getWrappedNode() )) {
- selectedDirectory = (Directory)selectedNode.getWrappedNode();
- } else if (WikiUtil.isDocument( selectedNode.getWrappedNode() ) ) {
- selectedDocument = (Document)selectedNode.getWrappedNode();
- selectedDirectory = selectedNode.getWrappedNode().getParent();
+ public WikiDocument getSelectedDocument() {
+ return selectedDocument;
}
- } else {
- selectedDirectory = (Directory)root.getWrappedNode();
+
+ public void setSelectedDocument(WikiDocument selectedDocument) {
+ this.selectedDocument = selectedDocument;
}
+
+ public WikiDirectory getSelectedDirectory() {
+ return selectedDirectory;
}
- public void selectDocumentByName(String documentName) {
- Node foundNode = nodeDAO.findDocumentInArea(root.getWrappedNode().getAreaNumber(), WikiUtil.convertToWikiName(documentName));
- if (foundNode == null)
- throw new EntityNotFoundException("Help document: "+documentName, Document.class);
+ public void setSelectedDirectory(WikiDirectory selectedDirectory) {
+ this.selectedDirectory = selectedDirectory;
+ }
- setSelectedNode(new NestedSetNodeWrapper(foundNode));
+ public void selectDocumentByName(String documentName) {
+ log.debug("Searching for help document with wiki name in area: " + getRoot().getWrappedNode().getAreaNumber() + ", " + WikiUtil.convertToWikiName(documentName));
+ WikiDocument helpDoc =
+ wikiNodeDAO.findWikiDocumentInArea(
+ getRoot().getWrappedNode().getAreaNumber(),
+ WikiUtil.convertToWikiName(documentName)
+ );
+ if (helpDoc == null)
+ throw new EntityNotFoundException("Help document: "+documentName, WikiDocument.class);
+
+ log.debug("Found help document: " + helpDoc);
+ // TODO: Avoid cast
+ setSelectedNode(new NestedSetNodeWrapper<WikiDirectory>( (WikiDirectory)helpDoc.getParent()) );
+ setSelectedDocument(helpDoc);
+ // TODO: Avoid cast
+ setSelectedDirectory( (WikiDirectory)helpDoc.getParent() );
}
}
1.22 +172 -86 jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/DirectoryHome.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: DirectoryHome.java
===================================================================
RCS file: /cvsroot/jboss/jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/DirectoryHome.java,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -b -r1.21 -r1.22
--- DirectoryHome.java 9 Nov 2007 15:08:26 -0000 1.21
+++ DirectoryHome.java 19 Dec 2007 04:29:25 -0000 1.22
@@ -6,60 +6,100 @@
*/
package org.jboss.seam.wiki.core.action;
-import static javax.faces.application.FacesMessage.SEVERITY_INFO;
-
-import org.jboss.seam.annotations.*;
+import org.jboss.seam.ScopeType;
+import org.jboss.seam.annotations.In;
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.Observer;
+import org.jboss.seam.annotations.web.RequestParameter;
import org.jboss.seam.annotations.security.Restrict;
-import org.jboss.seam.ScopeType;
-import org.jboss.seam.wiki.core.model.*;
-import org.jboss.seam.wiki.core.dao.WikiTreeNodeAdapter;
-import org.jboss.seam.wiki.core.dao.FeedDAO;
+import org.jboss.seam.security.Identity;
+import org.jboss.seam.wiki.core.feeds.FeedDAO;
+import org.jboss.seam.wiki.core.model.WikiDirectory;
+import org.jboss.seam.wiki.core.model.WikiDocument;
+import org.jboss.seam.wiki.core.model.WikiMenuItem;
+import org.jboss.seam.wiki.core.model.WikiNode;
import org.jboss.seam.wiki.util.WikiUtil;
-import org.richfaces.model.TreeNode;
import javax.faces.application.FacesMessage;
+import static javax.faces.application.FacesMessage.SEVERITY_INFO;
import java.util.*;
@Name("directoryHome")
@Scope(ScopeType.CONVERSATION)
-public class DirectoryHome extends NodeHome<Directory> {
+public class DirectoryHome extends NodeHome<WikiDirectory, WikiDirectory> {
+
/* -------------------------- Context Wiring ------------------------------ */
@In
- FeedDAO feedDAO;
+ protected FeedDAO feedDAO;
- /* -------------------------- Request Wiring ------------------------------ */
- @Observer("DirectoryHome.init")
- public String init() {
- String result = super.init();
- if (result != null) return result;
+ /* -------------------------- Internal State ------------------------------ */
- // Fill the datamodel for outjection
- refreshChildNodes();
+ // TODO: Move page size into preferences
+ private Pager pager = new Pager(15l);
+ private boolean hasFeed;
+ private List<WikiNode> childNodes = new ArrayList<WikiNode>();
+ private List<WikiDocument> childDocuments = new ArrayList<WikiDocument>();
+ private List<WikiMenuItem> menuItems = new ArrayList<WikiMenuItem>();
+ private SortedSet<WikiDirectory> alreadyUsedMenuItems = new TreeSet<WikiDirectory>();
+ private SortedSet<WikiDirectory> availableMenuItems = new TreeSet<WikiDirectory>();
+ private WikiDirectory selectedChildDirectory;
- // Feed checkbox
- hasFeed = getInstance().getFeed()!=null;
+ /* -------------------------- Basic Overrides ------------------------------ */
- return null;
+ @Override
+ public Class<WikiDirectory> getEntityClass() {
+ return WikiDirectory.class;
}
- /* -------------------------- Internal State ------------------------------ */
+ @Override
+ public WikiDirectory findInstance() {
+ return getWikiNodeDAO().findWikiDirectory((Long)getId());
+ }
- private List<Document> childDocuments = new ArrayList<Document>();
- public List<Document> getChildDocuments() { return childDocuments; }
+ @Override
+ protected WikiDirectory findParentNode(Long parentNodeId) {
+ return getEntityManager().find(WikiDirectory.class, parentNodeId);
+ }
+
+ @Override
+ public WikiDirectory afterNodeFound(WikiDirectory dir) {
+ super.afterNodeFound(dir);
+
+ refreshChildNodes(dir);
+ return dir;
+ }
+
+ @Override
+ public WikiDirectory beforeNodeEditFound(WikiDirectory dir) {
+ dir = super.beforeNodeEditFound(dir);
+
+ hasFeed = dir.getFeed()!=null;
+
+ childDocuments = getWikiNodeDAO().findWikiDocuments(dir);
+
+ menuItems = getWikiNodeDAO().findMenuItems(dir);
+ alreadyUsedMenuItems = new TreeSet<WikiDirectory>();
+ for (WikiMenuItem menuItem : menuItems) {
+ alreadyUsedMenuItems.add(menuItem.getDirectory());
+ }
+ refreshAvailableMenuItems(dir);
+
+ return dir;
+ }
/* -------------------------- Custom CUD ------------------------------ */
@Override
public String persist() {
- if (getParentDirectory().getParent() != null) {
+ if (getParentNode().getParent() != null) {
// This is a subdirectory in an area
- getInstance().setAreaNumber(getParentDirectory().getAreaNumber());
+ getInstance().setAreaNumber(getParentNode().getAreaNumber());
return super.persist();
} else {
// This is a logical area in the wiki root
@@ -78,30 +118,28 @@
}
}
+ @Override
protected boolean beforePersist() {
createOrRemoveFeed();
return super.preparePersist();
}
+ @Override
protected boolean beforeUpdate() {
createOrRemoveFeed();
+ updateMenuItems();
return super.beforeUpdate();
}
+ @Override
protected boolean prepareRemove() {
if (getInstance().getParent() == null) return false; // Veto wiki root delete
return true;
}
- protected boolean beforeRemove() {
- // Remove all children (nested, recursively, udpates the second-level cache)
- getNodeDAO().removeChildren(getInstance());
-
- return true;
- }
-
/* -------------------------- Messages ------------------------------ */
+ @Override
protected void createdMessage() {
getFacesMessages().addFromResourceBundleOrDefault(
SEVERITY_INFO,
@@ -111,6 +149,7 @@
);
}
+ @Override
protected void updatedMessage() {
getFacesMessages().addFromResourceBundleOrDefault(
SEVERITY_INFO,
@@ -120,6 +159,7 @@
);
}
+ @Override
protected void deletedMessage() {
getFacesMessages().addFromResourceBundleOrDefault(
SEVERITY_INFO,
@@ -129,12 +169,57 @@
);
}
+ protected void feedCreatedMessage() {
+ getFacesMessages().addFromResourceBundleOrDefault(
+ FacesMessage.SEVERITY_INFO,
+ "lacewiki.msg.Feed.Create",
+ "Created syndication feed for this directory");
+ }
+
+ protected void feedRemovedMessage() {
+ getFacesMessages().addFromResourceBundleOrDefault(
+ FacesMessage.SEVERITY_INFO,
+ "lacewiki.msg.Feed.Remove",
+ "Removed syndication feed of this directory");
+ }
+
/* -------------------------- Internal Methods ------------------------------ */
- private void refreshChildNodes() {
- childDocuments.clear();
- for (Node childNode : getInstance().getChildren()) {
- if (childNode instanceof Document) childDocuments.add((Document)childNode);
+ private void refreshChildNodes(WikiDirectory dir) {
+ pager.setNumOfRecords(getWikiNodeDAO().findChildrenCount(dir));
+ if (pager.getNumOfRecords() > 0) {
+ childNodes = getWikiNodeDAO().findChildren(dir, "createdOn", false, pager.getNextRecord(), pager.getPageSize());
+ }
+ }
+
+ private void refreshAvailableMenuItems(WikiDirectory dir) {
+ availableMenuItems = new TreeSet();
+ availableMenuItems.addAll(getWikiNodeDAO().findChildWikiDirectories(dir));
+ availableMenuItems.removeAll(alreadyUsedMenuItems);
+ }
+
+ private void updateMenuItems() {
+ if ( Identity.instance().hasPermission("Node", "editMenu", getInstance()) ) {
+ // No point in doing that if the user couldn't have edited anything
+
+ // Compare the edited list of menu items to the persistent menu items and insert/remove accordingly
+ List<WikiMenuItem> persistentMenuItems = getWikiNodeDAO().findMenuItems(getInstance());
+ for (WikiMenuItem persistentMenuItem : persistentMenuItems) {
+ if (menuItems.contains(persistentMenuItem)) {
+ persistentMenuItem.setDisplayPosition(menuItems.indexOf(persistentMenuItem));
+ getLog().debug("Updated menu: " + persistentMenuItem);
+ } else {
+ getEntityManager().remove(persistentMenuItem);
+ getLog().debug("Removed menu: " + persistentMenuItem);
+ }
+ }
+ for (WikiMenuItem menuItem : menuItems) {
+ if (!persistentMenuItems.contains(menuItem)) {
+ menuItem.setDisplayPosition(menuItems.indexOf(menuItem));
+ getEntityManager().persist(menuItem);
+ getLog().debug("Inserted menu: " + menuItem);
+ }
+ }
}
}
@@ -142,20 +227,12 @@
if (hasFeed && getInstance().getFeed() == null) {
// Does not have a feed but user wants one, create it
feedDAO.createFeed(getInstance());
-
- getFacesMessages().addFromResourceBundleOrDefault(
- FacesMessage.SEVERITY_INFO,
- "lacewiki.msg.Feed.Create",
- "Created syndication feed for this directory");
+ feedCreatedMessage();
} else if (!hasFeed && getInstance().getFeed() != null) {
// Does have feed but user doesn't want it anymore... delete it
feedDAO.removeFeed(getInstance());
-
- getFacesMessages().addFromResourceBundleOrDefault(
- FacesMessage.SEVERITY_INFO,
- "lacewiki.msg.Feed.Remove",
- "Removed syndication feed of this directory");
+ feedRemovedMessage();
} else if (getInstance().getFeed() != null) {
// Does have a feed and user still wants it, update the feed
@@ -165,42 +242,34 @@
/* -------------------------- Public Features ------------------------------ */
- @In(required=false)
- @Out(required = false, scope=ScopeType.PAGE)
- WikiTreeNodeAdapter directoryTree;
-
- public TreeNode getTree() {
- if (directoryTree == null) {
- directoryTree = new WikiTreeNodeAdapter(getInstance(), getNodeDAO().getComparatorDisplayPosition(), 2l);
- directoryTree.loadChildren();
- }
- return directoryTree;
- /*
- TreeNode root = new TreeNodeImpl();
- TreeNode bar = new TreeNodeImpl();
- TreeNode baz = new TreeNodeImpl();
- TreeNode faz = new TreeNodeImpl();
- root.setData("Foo");
- bar.setData("bar");
- baz.setData("baz");
- faz.setData("faz");
- root.addChild("1", bar);
- root.addChild("2", baz);
- root.addChild("3", faz);
- return root;
- */
+ @Observer(value = "PersistenceContext.filterReset", create = false)
+ public void refreshChildNodes() {
+ if (isManaged()) refreshChildNodes(getInstance());
}
- private boolean hasFeed;
-
- public boolean isHasFeed() {
- return hasFeed;
+ @RequestParameter
+ public void setPage(Integer page) {
+ pager.setPage(page);
}
- public void setHasFeed(boolean hasFeed) {
- this.hasFeed = hasFeed;
+ public Pager getPager() {
+ return pager;
}
+ public List<WikiNode> getChildNodes() { return childNodes; }
+
+ public List<WikiDocument> getChildDocuments() { return childDocuments; }
+
+ public List<WikiMenuItem> getMenuItems() { return menuItems; }
+
+ public WikiDirectory getSelectedChildDirectory() { return selectedChildDirectory; }
+ public void setSelectedChildDirectory(WikiDirectory selectedChildDirectory) { this.selectedChildDirectory = (WikiDirectory)selectedChildDirectory; }
+
+ public SortedSet<WikiDirectory> getAvailableMenuItems() { return availableMenuItems; }
+
+ public boolean isHasFeed() { return hasFeed; }
+ public void setHasFeed(boolean hasFeed) { this.hasFeed = hasFeed; }
+
public void resetFeed() {
if (getInstance().getFeed() != null) {
getLog().debug("resetting feed of directory");
@@ -214,19 +283,36 @@
}
@Restrict("#{s:hasPermission('Node', 'editMenu', directoryHome.instance)}")
- public void moveNode(int currentPosition, int newPosition) {
-
- if (currentPosition != newPosition) {
-
- // Shift and refresh displayed list
- WikiUtil.shiftListElement(getInstance().getChildren(), currentPosition, newPosition);
+ public void removeMenuItem(Long menuItemId) {
+ Iterator<WikiMenuItem> it = menuItems.iterator();
+ while (it.hasNext()) {
+ WikiMenuItem wikiMenuItem = it.next();
+ if (wikiMenuItem.getDirectoryId().equals(menuItemId)) {
+ getLog().debug("Removing menu item: " + menuItemId);
+ it.remove();
+ alreadyUsedMenuItems.remove(wikiMenuItem.getDirectory());
+ refreshAvailableMenuItems(getInstance());
+ }
+ }
+ }
- // Required update, this is only refreshed on database load
- for (Node node : getInstance().getChildren()) {
- node.setDisplayPosition( getInstance().getChildren().indexOf(node) );
+ @Restrict("#{s:hasPermission('Node', 'editMenu', directoryHome.instance)}")
+ public void addMenuItem() {
+ if (selectedChildDirectory != null) {
+ getLog().debug("Adding menu item: " + selectedChildDirectory);
+ WikiMenuItem newMenuItem = new WikiMenuItem(selectedChildDirectory);
+ menuItems.add(newMenuItem);
+ alreadyUsedMenuItems.add(selectedChildDirectory);
+ refreshAvailableMenuItems(getInstance());
}
+ }
+
+ @Restrict("#{s:hasPermission('Node', 'editMenu', directoryHome.instance)}")
+ public void moveMenuItem(int currentPosition, int newPosition) {
- refreshChildNodes();
+ if (currentPosition != newPosition) {
+ // Shift and refresh displayed list
+ WikiUtil.shiftListElement(menuItems, currentPosition, newPosition);
}
}
1.13 +1 -0 jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/AdminHome.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: AdminHome.java
===================================================================
RCS file: /cvsroot/jboss/jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/AdminHome.java,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -b -r1.12 -r1.13
--- AdminHome.java 12 Oct 2007 16:31:25 -0000 1.12
+++ AdminHome.java 19 Dec 2007 04:29:25 -0000 1.13
@@ -18,6 +18,7 @@
import org.jboss.seam.contexts.Contexts;
import org.jboss.seam.faces.FacesMessages;
import org.jboss.seam.core.Validators;
+import org.jboss.seam.core.Events;
import org.jboss.seam.log.Log;
import org.jboss.seam.security.AuthorizationException;
import org.jboss.seam.security.Identity;
1.4 +53 -48 jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/WikiRequestResolver.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: WikiRequestResolver.java
===================================================================
RCS file: /cvsroot/jboss/jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/WikiRequestResolver.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- WikiRequestResolver.java 12 Oct 2007 16:31:25 -0000 1.3
+++ WikiRequestResolver.java 19 Dec 2007 04:29:25 -0000 1.4
@@ -6,17 +6,14 @@
*/
package org.jboss.seam.wiki.core.action;
-import org.jboss.seam.annotations.*;
-import org.jboss.seam.log.Log;
-import org.jboss.seam.ScopeType;
import org.jboss.seam.Component;
+import org.jboss.seam.ScopeType;
+import org.jboss.seam.annotations.*;
import org.jboss.seam.faces.FacesMessages;
-import org.jboss.seam.wiki.core.dao.NodeDAO;
-import org.jboss.seam.wiki.core.model.Document;
-import org.jboss.seam.wiki.core.model.Directory;
-import org.jboss.seam.wiki.core.model.Node;
+import org.jboss.seam.log.Log;
+import org.jboss.seam.wiki.core.dao.WikiNodeDAO;
+import org.jboss.seam.wiki.core.model.*;
import org.jboss.seam.wiki.core.search.WikiSearch;
-import org.jboss.seam.wiki.util.WikiUtil;
import javax.faces.application.FacesMessage;
@@ -33,13 +30,16 @@
* </pre>
* <p>
* 'Foo' is a WikiName of a directory with a parentless parent (ROOT), we call this a logical area.
- * 'Bar' is a WikiName of a node in that logical area, unique within that area subtree.
+ * 'Bar' is a WikiName of a node in that logical area, unique within that area subtree. A node can either
+ * be a document or a directory, so we don't know what 'Bar' is until we searched for it by its unique
+ * name inside the area.
* </p>
* <p>
* We _never_ have URLs like <tt>http://host/Foo/Baz/Bar</tt> because 'Baz' would be a subdirectory
* we don't need. An area name and a node name is enough, the node name is unique within
* a subtree. We also never have <tt>http://host/Bar</tt>, a node name alone is not enough to
- * identify a node, we also need the area name.
+ * identify a node, we also need the area name. Of course, <tt>http://host/Foo</tt> is enough, then
+ * we look for a default document of that area.
* </p>
*<p>
* If the given parameters can't be resolved, the following prodecure applies:
@@ -70,13 +70,10 @@
static Log log;
@In
- protected org.jboss.seam.faces.Redirect redirect;
-
- @In
private FacesMessages facesMessages;
@In
- protected NodeDAO nodeDAO;
+ protected WikiNodeDAO wikiNodeDAO;
protected Long nodeId;
public Long getNodeId() { return nodeId; }
@@ -95,63 +92,62 @@
public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; }
- protected Document currentDocument = null;
- public Document getCurrentDocument() { return currentDocument; }
-
- protected Directory currentDirectory = null;
- public Directory getCurrentDirectory() { return currentDirectory; }
+ protected WikiDocument currentDocument = null;
+ protected WikiDirectory currentDirectory = null;
public String resolve() {
+ log.debug("resolving wiki request, node id: " + getNodeId() + " area name: " + getAreaName() + " node name: " + getNodeName());
// Queue a message if requested (for message passing across session invalidations and conversations)
if (message != null) {
+ log.debug("wiki request contained message: " + message);
facesMessages.addFromResourceBundle(
FacesMessage.SEVERITY_INFO,
message
);
}
- // Have we been called with a nodeId request parameter, could be document or directory
+ // Have we been called with a nodeId request parameter, must be a document
if (nodeId != null) {
log.debug("trying to resolve node id: " + nodeId);
// Try to find a document
- currentDocument = nodeDAO.findDocument(nodeId);
-
- // Document not found, see if it is a directory
- if (currentDocument == null) {
- currentDirectory = nodeDAO.findDirectory(nodeId);
-
- // Try to get a default document of that directory
- currentDocument = nodeDAO.findDefaultDocument(currentDirectory);
-
- } else {
+ currentDocument = wikiNodeDAO.findWikiDocument(nodeId);
+ if (currentDocument != null) {
// Document found, take its directory
- currentDirectory = currentDocument.getParent();
+ // TODO: Avoid cast
+ currentDirectory = (WikiDirectory)currentDocument.getParent();
+ } else {
+ // Let's check if the id was a directory
+ currentDirectory = wikiNodeDAO.findWikiDirectory(nodeId);
+
}
// Have we been called with an areaName and nodeName request parameter
} else if (areaName != null && nodeName != null) {
log.debug("trying to resolve area name: " + areaName + " and node name: " + nodeName);
- // Try to find the area
- Directory area = nodeDAO.findArea(areaName);
+ // Try to find the area/directory
+ WikiDirectory area = wikiNodeDAO.findArea(areaName);
if (area != null) {
- Node node = nodeDAO.findNodeInArea(area.getAreaNumber(), nodeName);
- if (WikiUtil.isDirectory(node)) {
- currentDirectory = (Directory)node;
- currentDocument = nodeDAO.findDefaultDocument(currentDirectory);
+
+ // Try to find the document
+ WikiDocument doc = wikiNodeDAO.findWikiDocumentInArea(area.getAreaNumber(), nodeName);
+ if (doc != null) {
+ // Found it, let's use that
+ currentDocument = doc;
+ // TODO: Avoid cast
+ currentDirectory = (WikiDirectory)currentDocument.getParent();
} else {
- currentDocument = (Document)node;
- currentDirectory = currentDocument != null ? currentDocument.getParent() : area;
+ // Didn't find a document for the node name, let's see if it's a directory
+ currentDirectory = wikiNodeDAO.findWikiDirectoryInArea(area.getAreaNumber(), nodeName);
}
}
// Or have we been called just with an areaName request parameter
} else if (areaName != null) {
log.debug("trying to resolve area name: " + areaName);
- currentDirectory = nodeDAO.findArea(areaName);
- currentDocument = nodeDAO.findDefaultDocument(currentDirectory);
+ currentDirectory = wikiNodeDAO.findArea(areaName);
}
log.debug("resolved directory: " + currentDirectory + " and document: " + currentDocument);
@@ -172,23 +168,32 @@
} else {
log.debug("falling back to wiki start document");
// Fall back to default document
- currentDocument = (Document)Component.getInstance("wikiStart");
- currentDirectory = currentDocument.getParent();
+ currentDocument = (WikiDocument)Component.getInstance("wikiStart");
+ // TODO: Avoid cast
+ currentDirectory = (WikiDirectory)currentDocument.getParent();
}
}
+ // Last attempt, in case nothing worked try the default document if we have a directory
+ if (currentDirectory != null && currentDocument == null) {
+ // We have a directory, let's see if it has a default file and if that is a document we can use
+ // TODO: Default can be a file, not only a document, currently the UI only allows you to set documents,
+ // so narrow the Hibernate proxy down to a document with a special DAO method and a NO_PROXY mapping
+ currentDocument = wikiNodeDAO.findDefaultDocument(currentDirectory);
+ }
+
if (currentDocument != null) {
- nodeId = currentDocument.getId();
DocumentHome documentHome = (DocumentHome)Component.getInstance("documentHome");
- documentHome.setId(nodeId);
+ documentHome.setNodeId(currentDocument.getId());
documentHome.setInstance(currentDocument);
+ documentHome.afterNodeFound(currentDocument);
log.debug("displaying document: " + currentDocument);
return "docDisplay";
} else {
- nodeId = currentDirectory.getId();
DirectoryHome directoryHome = (DirectoryHome)Component.getInstance("directoryHome");
- directoryHome.setId(nodeId);
+ directoryHome.setNodeId(currentDirectory.getId());
directoryHome.setInstance(currentDirectory);
+ directoryHome.afterNodeFound(currentDirectory);
log.debug("displaying directory: " + currentDirectory);
return "dirDisplay";
}
1.13 +11 -12 jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/Menu.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: Menu.java
===================================================================
RCS file: /cvsroot/jboss/jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/Menu.java,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -b -r1.12 -r1.13
--- Menu.java 9 Nov 2007 15:08:26 -0000 1.12
+++ Menu.java 19 Dec 2007 04:29:25 -0000 1.13
@@ -7,13 +7,12 @@
package org.jboss.seam.wiki.core.action;
import org.jboss.seam.ScopeType;
-import org.jboss.seam.log.Log;
import org.jboss.seam.annotations.*;
+import org.jboss.seam.log.Log;
import org.jboss.seam.wiki.core.action.prefs.WikiPreferences;
-import org.jboss.seam.wiki.core.dao.NodeDAO;
-import org.jboss.seam.wiki.core.model.Directory;
-import org.jboss.seam.wiki.core.model.Node;
-import org.jboss.seam.wiki.core.nestedset.NestedSetNodeWrapper;
+import org.jboss.seam.wiki.core.dao.WikiNodeDAO;
+import org.jboss.seam.wiki.core.model.WikiDirectory;
+import org.jboss.seam.wiki.core.nestedset.query.NestedSetNodeWrapper;
import java.io.Serializable;
@@ -23,33 +22,33 @@
* @author Christian Bauer
*/
@Name("menu")
- at Scope(ScopeType.PAGE)
+ at Scope(ScopeType.SESSION)
public class Menu implements Serializable {
@Logger
Log log;
@In
- Directory wikiRoot;
+ WikiDirectory wikiRoot;
@In
- NodeDAO nodeDAO;
+ WikiNodeDAO wikiNodeDAO;
@In
WikiPreferences wikiPreferences;
- NestedSetNodeWrapper<Node> root;
- public NestedSetNodeWrapper<Node> getRoot() {
+ NestedSetNodeWrapper<WikiDirectory> root;
+ public NestedSetNodeWrapper<WikiDirectory> getRoot() {
if (root == null) {
refreshRoot();
}
return root;
}
- @Observer(value = "Nodes.menuStructureModified", create = false)
+ @Observer(value = { "Nodes.menuStructureModified", "PersistenceContext.filterReset" }, create = false)
public void refreshRoot() {
log.debug("Loading menu items tree");
- root = nodeDAO.findMenuItems(
+ root = wikiNodeDAO.findMenuItemTree(
wikiRoot,
wikiPreferences.getMainMenuDepth(),
wikiPreferences.getMainMenuLevels(),
1.30 +151 -121 jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/NodeHome.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: NodeHome.java
===================================================================
RCS file: /cvsroot/jboss/jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/NodeHome.java,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -b -r1.29 -r1.30
--- NodeHome.java 20 Nov 2007 08:05:12 -0000 1.29
+++ NodeHome.java 19 Dec 2007 04:29:25 -0000 1.30
@@ -6,26 +6,20 @@
*/
package org.jboss.seam.wiki.core.action;
-import static javax.faces.application.FacesMessage.SEVERITY_ERROR;
-
-import org.jboss.seam.framework.EntityHome;
-import org.jboss.seam.wiki.core.dao.NodeDAO;
-import org.jboss.seam.wiki.core.dao.UserDAO;
-import org.jboss.seam.wiki.core.dao.UserRoleAccessFactory;
-import org.jboss.seam.wiki.core.model.User;
-import org.jboss.seam.wiki.core.model.Directory;
-import org.jboss.seam.wiki.core.model.Node;
-import org.jboss.seam.wiki.core.model.Role;
-import org.jboss.seam.wiki.util.WikiUtil;
-import org.jboss.seam.wiki.preferences.PreferenceProvider;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.security.Restrict;
-import org.jboss.seam.Component;
-import org.jboss.seam.core.Events;
import org.jboss.seam.contexts.Contexts;
+import org.jboss.seam.core.Events;
+import org.jboss.seam.framework.EntityHome;
import org.jboss.seam.security.AuthorizationException;
import org.jboss.seam.security.Identity;
+import org.jboss.seam.wiki.core.dao.TagDAO;
+import org.jboss.seam.wiki.core.dao.UserDAO;
+import org.jboss.seam.wiki.core.dao.WikiNodeDAO;
+import org.jboss.seam.wiki.core.model.*;
+import org.jboss.seam.wiki.util.WikiUtil;
+import static javax.faces.application.FacesMessage.SEVERITY_ERROR;
import java.util.Date;
import java.util.List;
@@ -34,131 +28,157 @@
*
* @author Christian Bauer
*/
-public abstract class NodeHome<N extends Node> extends EntityHome<N> {
+public abstract class NodeHome<N extends WikiNode, P extends WikiNode> extends EntityHome<N> {
/* -------------------------- Context Wiring ------------------------------ */
@In
- private NodeDAO nodeDAO;
+ private WikiNodeDAO wikiNodeDAO;
@In
private UserDAO userDAO;
@In
+ private TagDAO tagDAO;
+ @In
+ private WikiDirectory wikiRoot;
+ @In
protected User currentUser;
@In
protected List<Role.AccessLevel> accessLevelsList;
- protected NodeDAO getNodeDAO() { return nodeDAO; }
- protected UserDAO getUserDAO() { return userDAO; }
- protected User getCurrentUser() { return currentUser; }
+ public WikiNodeDAO getWikiNodeDAO() { return wikiNodeDAO; }
+ public UserDAO getUserDAO() { return userDAO; }
+ public TagDAO getTagDAO() { return tagDAO; }
+ public WikiDirectory getWikiRoot() { return wikiRoot; }
+ public User getCurrentUser() { return currentUser; }
public List<Role.AccessLevel> getAccessLevelsList() { return accessLevelsList; }
/* -------------------------- Request Wiring ------------------------------ */
- private Long parentDirectoryId;
- public Long getParentDirectoryId() {
- return parentDirectoryId;
+ private Long parentNodeId;
+
+ public Long getParentNodeId() {
+ return parentNodeId;
}
- public void setParentDirectoryId(Long parentDirectoryId) {
- this.parentDirectoryId = parentDirectoryId;
+ public void setParentNodeId(Long parentNodeId) {
+ this.parentNodeId = parentNodeId;
}
- private Directory parentDirectory;
- public Directory getParentDirectory() {
- return parentDirectory;
+ private P parentNode;
+ public P getParentNode() {
+ return parentNode;
}
- public void setParentDirectory(Directory parentDirectory) {
- this.parentDirectory = parentDirectory;
+ public void setParentNode(P parentNode) {
+ this.parentNode = parentNode;
}
public void setNodeId(Long o) {
super.setId(o);
}
-
public Long getNodeId() {
return (Long)super.getId();
}
- public String init() {
-
- getLog().debug("initializing node home");
-
- // Load the parent instance
- if (!isIdDefined() && parentDirectoryId == null) {
- return "missingParameters";
- }
-
- if (!isIdDefined()) {
- getLog().debug("no instance identifier, getting parent directory with id: " + parentDirectoryId);
- parentDirectory = loadParentDirectory(parentDirectoryId);
- } else {
- getLog().debug("using parent of instance: " + getInstance());
- parentDirectory = getInstance().getParent();
- if (parentDirectory != null) // Wiki Root doesn't have a parent
- parentDirectoryId = parentDirectory.getId();
- }
-
- getLog().debug("initalized with parent directory: " + parentDirectory);
+ /* -------------------------- Additional States ------------------------------ */
- // Outjects current node or parent directory, e.g. for breadcrumb rendering
- // TODO: This clashes if several subclasses of NodeHome run on the same page, e.g. DocumentHome + ForumHome
- Contexts.getPageContext().set("currentLocation", !isManaged() ? getParentDirectory() : getInstance());
+ private boolean edit = false;
- return null;
- }
+ public boolean isEdit() { return edit; }
+ public void setEdit(boolean edit) { this.edit = edit; }
/* -------------------------- Basic Overrides ------------------------------ */
-
@Override
protected String getPersistenceContextName() {
return "restrictedEntityManager";
}
- // Access level filtered DAO for retrieval by identifier
@Override
public N find() {
- //noinspection unchecked
- N result = (N)nodeDAO.findNode((Long)getId());
- if (result==null) {
+ getLog().debug("finding an existing instance with id: " + getId());
+ N foundNode = findInstance();
+ if (foundNode == null) {
handleNotFound();
- } else {
+ return null;
+ }
+ getLog().debug("found instance: " + foundNode);
+ return isEdit() ? beforeNodeEditFound(afterNodeFound(foundNode)) : afterNodeFound(foundNode);
+ }
+
+ @Override
+ protected N createInstance() {
+ getLog().debug("creating a new instance");
+ N newNode = super.createInstance();
+ getLog().debug("created new instance: " + newNode);
+ return isEdit() ? beforeNodeEditNew(afterNodeCreated(newNode)) : afterNodeCreated(newNode);
+ }
+
+ /* -------------------------- Basic Subclass Callbacks ------------------------------ */
+
+ public N afterNodeCreated(N node) {
+
+ outjectCurrentLocation(node);
+
+ return node;
+ }
+
+ public N beforeNodeEditNew(N node) {
+
+ if (parentNodeId == null)
+ throw new IllegalStateException("Missing parentNodeId parameter");
+
+ getLog().debug("loading parent node with id: " + parentNodeId);
+ parentNode = findParentNode(parentNodeId);
+ if (parentNode == null)
+ throw new IllegalStateException("Could not find parent node with id: " + parentNodeId);
+ getLog().debug("initalized with parent node: " + parentNode);
+
+ // Default to same access permissions as parent node
+ node.setWriteAccessLevel(parentNode.getWriteAccessLevel());
+ node.setReadAccessLevel(parentNode.getReadAccessLevel());
writeAccessLevel = getAccessLevelsList().get(
accessLevelsList.indexOf(
- new Role.AccessLevel(result.getWriteAccessLevel())
+ new Role.AccessLevel(parentNode.getWriteAccessLevel())
)
);
readAccessLevel = getAccessLevelsList().get(
accessLevelsList.indexOf(
- new Role.AccessLevel(result.getReadAccessLevel())
+ new Role.AccessLevel(parentNode.getReadAccessLevel())
)
);
+
+ return node;
}
- return result;
+
+ public N afterNodeFound(N node) {
+
+ getLog().debug("using parent of instance: " + node.getParent());
+ if (node.getParent() != null) { // Wiki Root doesn't have a parent
+ parentNode = (P)node.getParent();
+ parentNodeId = parentNode.getId();
}
- @Override
- protected N createInstance() {
- N node = super.createInstance();
- if (parentDirectory == null) {
- throw new IllegalStateException("Call the init() method before you use NodeHome");
- }
- // Set default permissions for new nodes - default to same access as parent directory
- node.setWriteAccessLevel(parentDirectory.getWriteAccessLevel());
- node.setReadAccessLevel(parentDirectory.getReadAccessLevel());
+ outjectCurrentLocation(node);
+
+ return node;
+ }
+
+ public N beforeNodeEditFound(N node) {
+
writeAccessLevel = getAccessLevelsList().get(
accessLevelsList.indexOf(
- new Role.AccessLevel(parentDirectory.getWriteAccessLevel())
+ new Role.AccessLevel(node.getWriteAccessLevel())
)
);
readAccessLevel = getAccessLevelsList().get(
accessLevelsList.indexOf(
- new Role.AccessLevel(parentDirectory.getReadAccessLevel())
+ new Role.AccessLevel(node.getReadAccessLevel())
)
);
return node;
}
+
/* -------------------------- Custom CUD ------------------------------ */
@Override
@@ -167,12 +187,8 @@
if (!preparePersist()) return null;
- // Link the node with its parent directory
- getLog().trace("linking new node with its parent directory");
- parentDirectory.addChild(getInstance());
-
- // Last modified metadata
- setLastModifiedMetadata();
+ getLog().trace("linking new node with its parent node: " + getParentNode());
+ getInstance().setParent(getParentNode());
// Wiki name conversion
setWikiName();
@@ -222,21 +238,16 @@
return outcome;
}
+
+ // TODO: Doesn't handle recursive deletion (only db cascading), so 2nd level cache and lucene index out of sync!
@Override
public String remove() {
checkRemovePermissions();
if (!prepareRemove()) return null;
- // Unlink the node from its directory
- getInstance().getParent().removeChild(getInstance());
-
if (!beforeRemove()) return null;
- // Delete preferences of this node
- PreferenceProvider provider = (PreferenceProvider) Component.getInstance("preferenceProvider");
- provider.deleteInstancePreferences(getInstance());
-
String outcome = super.remove();
if (outcome != null) {
Events.instance().raiseEvent("Nodes.menuStructureModified");
@@ -244,12 +255,38 @@
return outcome;
}
+ /* -------------------------- Internal (Subclass) Methods ------------------------------ */
+
+ public abstract Class<N> getEntityClass();
+
+ protected abstract N findInstance();
+
+ protected abstract P findParentNode(Long parentNodeId);
+
+ protected void outjectCurrentLocation(WikiNode node) {
+ if (isPageRootController()) {
+ // Outjects current node or parent directory, e.g. for breadcrumb rendering
+ Contexts.getPageContext().set("currentLocation", node);
+ }
+ }
+
+ protected void setWikiName() {
+ getLog().trace("setting wiki name of node");
+ getInstance().setWikiname(WikiUtil.convertToWikiName(getInstance().getName()));
+ }
+
+ protected void setLastModifiedMetadata() {
+ getLog().trace("setting last modified metadata");
+ getInstance().setLastModifiedBy(currentUser);
+ getInstance().setLastModifiedOn(new Date());
+ }
+
protected boolean isValidModel() {
getLog().trace("validating model");
- if (getParentDirectory() == null) return true; // Special case, editing the wiki root
+ if (getParentNode() == null) return true; // Special case, editing the wiki root
// Unique wiki name
- if (nodeDAO.isUniqueWikiname(getInstance())) {
+ if (getWikiNodeDAO().isUniqueWikiname(getParentNode().getAreaNumber(), getInstance())) {
return true;
} else {
getFacesMessages().addToControlFromResourceBundleOrDefault(
@@ -263,22 +300,9 @@
}
- /* -------------------------- Internal Methods ------------------------------ */
-
- protected void setWikiName() {
- getLog().trace("setting wiki name of node");
- getInstance().setWikiname(WikiUtil.convertToWikiName(getInstance().getName()));
- }
-
- protected void setLastModifiedMetadata() {
- getLog().trace("setting last modified metadata");
- getInstance().setLastModifiedBy(currentUser);
- getInstance().setLastModifiedOn(new Date());
- }
-
protected void checkPersistPermissions() {
getLog().trace("checking persist permissions");
- if (!Identity.instance().hasPermission("Node", "create", getParentDirectory()) )
+ if (!Identity.instance().hasPermission("Node", "create", getParentNode()) )
throw new AuthorizationException("You don't have permission for this operation");
if (!Identity.instance().hasPermission("Node", "changeAccessLevel", getInstance()))
throw new AuthorizationException("You don't have permission for this operation");
@@ -298,11 +322,9 @@
throw new AuthorizationException("You don't have permission for this operation");
}
- protected Directory loadParentDirectory(Long parentDirectoryId) {
- return nodeDAO.findDirectory(parentDirectoryId);
- }
+ /* -------------------------- Optional Subclass Callbacks ------------------------------ */
- /* -------------------------- Subclass Callbacks ------------------------------ */
+ protected boolean isPageRootController() { return true; }
/**
* Called before the superclass does its preparation;
@@ -345,7 +367,7 @@
* @param oldParent the previous parent directory
* @param newParent the new parent directory
*/
- protected void afterNodeMoved(Directory oldParent, Directory newParent) {}
+ protected void afterNodeMoved(WikiDirectory oldParent, WikiDirectory newParent) {}
/* -------------------------- Public Features ------------------------------ */
@@ -356,20 +378,20 @@
Iterator pathIterator = rowkey.iterator();
Long dirId = null;
while (pathIterator.hasNext()) dirId = (Long)pathIterator.next();
- parentDirectory = nodeDAO.findDirectory(dirId);
+ parentNode = nodeDAO.findDirectory(dirId);
Directory oldParentDirectory = (Directory)getInstance().getParent();
// Move node to different directory
- if (parentDirectory.getId() != oldParentDirectory.getId()) {
+ if (parentNode.getId() != oldParentDirectory.getId()) {
// Null out default document of old parent
removeAsDefaultDocument(oldParentDirectory);
// Attach to new parent
- getInstance().setParent(parentDirectory); // TODO: Disconnects from old parent?
- getInstance().setAreaNumber(parentDirectory.getAreaNumber());
+ getInstance().setParent(parentNode); // TODO: Disconnects from old parent?
+ getInstance().setAreaNumber(parentNode.getAreaNumber());
- afterNodeMoved(oldParentDirectory, parentDirectory);
+ afterNodeMoved(oldParentDirectory, parentNode);
}
}
*/
@@ -393,7 +415,7 @@
}
this.writeAccessLevel = writeAccessLevel;
getInstance().setWriteAccessLevel(
- writeAccessLevel != null ? writeAccessLevel.getAccessLevel() : UserRoleAccessFactory.ADMINROLE_ACCESSLEVEL
+ writeAccessLevel != null ? writeAccessLevel.getAccessLevel() : Role.ADMINROLE_ACCESSLEVEL
);
}
@@ -407,8 +429,16 @@
}
this.readAccessLevel = readAccessLevel;
getInstance().setReadAccessLevel(
- readAccessLevel != null ? readAccessLevel.getAccessLevel() : UserRoleAccessFactory.ADMINROLE_ACCESSLEVEL
+ readAccessLevel != null ? readAccessLevel.getAccessLevel() : Role.ADMINROLE_ACCESSLEVEL
);
}
+ private List<DisplayTagCount> popularTags;
+
+ public List<DisplayTagCount> getPopularTags() {
+ // Load 6 most popular tags
+ if (popularTags == null) popularTags = tagDAO.findTagCounts(getWikiRoot(), null, 6);
+ return popularTags;
+ }
+
}
1.38 +242 -105 jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/DocumentHome.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: DocumentHome.java
===================================================================
RCS file: /cvsroot/jboss/jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/DocumentHome.java,v
retrieving revision 1.37
retrieving revision 1.38
diff -u -b -r1.37 -r1.38
--- DocumentHome.java 13 Nov 2007 07:58:09 -0000 1.37
+++ DocumentHome.java 19 Dec 2007 04:29:25 -0000 1.38
@@ -6,149 +6,201 @@
*/
package org.jboss.seam.wiki.core.action;
-import static javax.faces.application.FacesMessage.SEVERITY_INFO;
-
-import org.jboss.seam.annotations.*;
-import org.jboss.seam.wiki.core.model.*;
-import org.jboss.seam.wiki.core.engine.*;
-import org.jboss.seam.wiki.core.dao.FeedDAO;
-import org.jboss.seam.wiki.core.dao.UserRoleAccessFactory;
-import org.jboss.seam.wiki.core.dao.TagDAO;
-import org.jboss.seam.wiki.core.action.prefs.DocumentEditorPreferences;
-import org.jboss.seam.wiki.core.action.prefs.CommentsPreferences;
-import org.jboss.seam.wiki.core.action.prefs.WikiPreferences;
-import org.jboss.seam.wiki.util.WikiUtil;
import org.jboss.seam.Component;
import org.jboss.seam.ScopeType;
-import org.jboss.seam.log.Log;
+import org.jboss.seam.annotations.In;
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.annotations.Scope;
import org.jboss.seam.contexts.Contexts;
+import org.jboss.seam.wiki.core.action.prefs.CommentsPreferences;
+import org.jboss.seam.wiki.core.action.prefs.DocumentEditorPreferences;
+import org.jboss.seam.wiki.core.action.prefs.WikiPreferences;
+import org.jboss.seam.wiki.core.feeds.FeedDAO;
+import org.jboss.seam.wiki.core.feeds.FeedEntryManager;
+import org.jboss.seam.wiki.core.engine.WikiLinkResolver;
+import org.jboss.seam.wiki.core.engine.MacroWikiTextRenderer;
+import org.jboss.seam.wiki.core.model.WikiDirectory;
+import org.jboss.seam.wiki.core.model.WikiDocument;
+import org.jboss.seam.wiki.core.model.WikiFile;
+import org.jboss.seam.wiki.core.model.FeedEntry;
+import org.jboss.seam.wiki.preferences.PreferenceProvider;
-import java.util.List;
-import java.util.Date;
-import java.util.Calendar;
-import java.util.GregorianCalendar;
+import static javax.faces.application.FacesMessage.SEVERITY_INFO;
+import java.util.*;
@Name("documentHome")
@Scope(ScopeType.CONVERSATION)
-public class DocumentHome extends NodeHome<Document> {
-
- @Logger
- static Log log;
+public class DocumentHome extends NodeHome<WikiDocument, WikiDirectory> {
/* -------------------------- Context Wiring ------------------------------ */
- @In
- private Directory wikiRoot;
@In(required = false)
- private Node selectedHistoricalNode;
+ private DocumentHistory documentHistory;
@In
private FeedDAO feedDAO;
- @In
- private TagDAO tagDAO;
- /* -------------------------- Request Wiring ------------------------------ */
+ /* -------------------------- Internal State ------------------------------ */
+
+ private WikiDocument historicalCopy;
+ private Boolean minorRevision;
+ private String formContent;
+ private String tagString;
+ Set<WikiFile> linkTargets;
+ private boolean enabledPreview = false;
+ private boolean pushOnFeeds = false;
+ private boolean pushOnSiteFeed = false;
+ private boolean isOnSiteFeed = false;
+ private List<WikiFile> historicalFiles;
+ private Long numOfHistoricalFiles = 0l;
- @Observer("DocumentHome.init")
- public String init() {
- String result = super.init();
- if (result != null) return result;
+ /* -------------------------- Basic Overrides ------------------------------ */
- // Rollback to historical revision?
- if (selectedHistoricalNode != null) {
- getLog().debug("rolling back to revision: " + selectedHistoricalNode.getRevision());
- getInstance().rollback(selectedHistoricalNode);
+ @Override
+ public Class<WikiDocument> getEntityClass() {
+ return WikiDocument.class;
}
- // Make a copy
- if (historicalCopy == null) {
- historicalCopy = new Document(getInstance(), true);
+ @Override
+ public WikiDocument findInstance() {
+ return getWikiNodeDAO().findWikiDocument((Long)getId());
}
- // Wiki text parser and plugins need this
- log.debug("setting current document: " + getInstance());
- Contexts.getPageContext().set("currentDocument", getInstance());
- log.debug("setting current directory: " + getParentDirectory());
- Contexts.getPageContext().set("currentDirectory", getParentDirectory());
+ @Override
+ protected WikiDirectory findParentNode(Long parentNodeId) {
+ return getEntityManager().find(WikiDirectory.class, parentNodeId);
+ }
+
+ @Override
+ public WikiDocument afterNodeCreated(WikiDocument doc) {
+ doc = super.afterNodeCreated(doc);
- return null;
+ outjectDocumentAndDirectory(doc, getParentNode());
+ return doc;
}
- /* -------------------------- Internal State ------------------------------ */
+ @Override
+ public WikiDocument beforeNodeEditNew(WikiDocument doc) {
+ doc = super.beforeNodeEditNew(doc);
- private Document historicalCopy;
- private Boolean minorRevision;
- private String formContent;
- private boolean enabledPreview = false;
- private boolean pushOnFeeds = false;
- private boolean pushOnSiteFeed = false;
- private List<Node> historicalNodes;
- private Long numOfHistoricalNodes;
+ doc.setEnableComments( ((CommentsPreferences)Component.getInstance("commentsPreferences")).getEnableByDefault() );
- /* -------------------------- Basic Overrides ------------------------------ */
+ return doc;
+ }
+ @Override
+ public WikiDocument afterNodeFound(WikiDocument doc) {
+ doc = super.afterNodeFound(doc);
- /* -------------------------- Custom CUD ------------------------------ */
+ findHistoricalFiles(doc);
+ syncMacros(doc.getAreaNumber(), doc);
+ outjectDocumentAndDirectory(doc, getParentNode());
+
+ return doc;
+ }
+
+ @Override
+ public WikiDocument beforeNodeEditFound(WikiDocument doc) {
+ doc = super.beforeNodeEditFound(doc);
+
+ // Rollback to historical revision?
+ if (documentHistory != null && documentHistory.getSelectedHistoricalFile() != null) {
+ getLog().debug("rolling back to revision: " + documentHistory.getSelectedHistoricalFile().getRevision());
+ // TODO: Avoid cast, make history polymorphic
+ doc.rollback((WikiDocument)documentHistory.getSelectedHistoricalFile());
+ }
- protected Document createInstance() {
- Document newDoc = super.createInstance();
- newDoc.setEnableComments( ((CommentsPreferences)Component.getInstance("commentsPreferences")).getEnableByDefault() );
- return newDoc;
+ isOnSiteFeed = feedDAO.isOnSiteFeed(doc);
+ tagString = doc.getTagsCommaSeparated();
+
+ return doc;
}
+ /* -------------------------- Custom CUD ------------------------------ */
+
+ @Override
protected boolean beforePersist() {
// Sync document content
- syncFormToInstance(getParentDirectory());
+ syncFormContentToInstance(getParentNode());
+ syncLinks();
+ syncTags();
// Set createdOn date _now_
getInstance().setCreatedOn(new Date());
// Make a copy
- historicalCopy = new Document(getInstance(), true);
+ historicalCopy = new WikiDocument();
+ historicalCopy.flatCopy(getInstance(), true);
return true;
}
+ @Override
public String persist() {
String outcome = super.persist();
// Create feed entries (needs identifiers assigned, so we run after persist())
if (outcome != null && isPushOnFeeds()) {
- feedDAO.createFeedEntry(getInstance(), isPushOnSiteFeed());
+ getLog().debug("creating feed entries on parent dirs - and on site feed: " + isPushOnSiteFeed());
+ isOnSiteFeed = isPushOnSiteFeed();
+
+ FeedEntry feedEntry =
+ ((FeedEntryManager)Component.getInstance(getFeedEntryManagerName())).createFeedEntry(getInstance());
+ feedDAO.createFeedEntry(getParentNode(), getInstance(), feedEntry, isPushOnSiteFeed());
+
getEntityManager().flush();
- pushOnFeeds = false;
- pushOnSiteFeed = false;
+ setPushOnFeeds(false);
+ setPushOnSiteFeed(false);
}
return outcome;
}
+ @Override
protected boolean beforeUpdate() {
// Sync document content
- syncFormToInstance(getParentDirectory());
+ syncFormContentToInstance(getParentNode());
+ syncLinks();
+ syncTags();
// Update feed entries
- if (getInstance().getReadAccessLevel() == UserRoleAccessFactory.GUESTROLE_ACCESSLEVEL && isPushOnFeeds()) {
- feedDAO.updateFeedEntry(getInstance(), isPushOnSiteFeed());
- pushOnFeeds = false;
- pushOnSiteFeed = false;
+ if (isPushOnFeeds()) {
+ isOnSiteFeed = isPushOnSiteFeed();
+
+ FeedEntry feedEntry = feedDAO.findFeedEntry(getInstance());
+ if (feedEntry == null) {
+ getLog().debug("creating feed entries on parent dirs - and on site feed: " + isPushOnSiteFeed());
+ feedEntry = ((FeedEntryManager)Component.getInstance(getFeedEntryManagerName())).createFeedEntry(getInstance());
+ feedDAO.createFeedEntry(getParentNode(), getInstance(), feedEntry, isPushOnSiteFeed());
+ } else {
+ getLog().debug("updating feed entries on parent dirs - and on site feed: " + isPushOnSiteFeed());
+ ((FeedEntryManager)Component.getInstance(getFeedEntryManagerName())).updateFeedEntry(feedEntry, getInstance());
+ feedDAO.updateFeedEntry(getParentNode(), getInstance(), feedEntry, isPushOnSiteFeed());
+ }
+
+ setPushOnFeeds(false);
+ setPushOnSiteFeed(false);
}
// Feeds should not be removed by a maintenance thread: If there
// is no activity on the site, feeds shouldn't be empty but show the last updates.
WikiPreferences wikiPrefs = (WikiPreferences) Component.getInstance("wikiPreferences");
Calendar oldestDate = GregorianCalendar.getInstance();
- oldestDate.roll(Calendar.DAY_OF_YEAR, -wikiPrefs.getPurgeFeedEntriesAfterDays().intValue());
+ oldestDate.add(Calendar.DAY_OF_YEAR, -wikiPrefs.getPurgeFeedEntriesAfterDays().intValue());
feedDAO.purgeOldFeedEntries(oldestDate.getTime());
// Write history log and prepare a new copy for further modification
if (!isMinorRevision()) {
-
+ if (historicalCopy == null)
+ throw new IllegalStateException("Call getFormContent() once to create a historical revision");
+ getLog().debug("storing the historical copy as a new revision");
historicalCopy.setId(getInstance().getId());
- getNodeDAO().persistHistoricalNode(historicalCopy);
+ historicalCopy.setLastModifiedBy(getCurrentUser());
+ getWikiNodeDAO().persistHistoricalFile(historicalCopy);
getInstance().incrementRevision();
// New historical copy in conversation
- historicalCopy = new Document(getInstance(), true);
+ historicalCopy = new WikiDocument();
+ historicalCopy.flatCopy(getInstance(), true);
// Reset form
setMinorRevision(
@@ -160,23 +212,42 @@
return true;
}
+ @Override
protected boolean prepareRemove() {
// Remove feed entry before removing document
- feedDAO.removeFeedEntries(getInstance());
+ feedDAO.removeFeedEntry(
+ feedDAO.findFeeds(getInstance()),
+ feedDAO.findFeedEntry(getInstance())
+ );
return super.prepareRemove();
}
- protected void afterNodeMoved(Directory oldParent, Directory newParent) {
+ @Override
+ protected boolean beforeRemove() {
+
+ // Delete preferences of this node
+ PreferenceProvider provider = (PreferenceProvider) Component.getInstance("preferenceProvider");
+ provider.deleteInstancePreferences(getInstance());
+
+
+ return super.beforeRemove();
+ }
+
+ /* TODO: Implement node moving
+ @Override
+ protected void afterNodeMoved(WikiDirectory oldParent, WikiDirectory newParent) {
// Update view
- syncFormToInstance(oldParent); // Resolve existing links in old directory
- syncInstanceToForm(newParent); // Now update the form, effectively re-rendering the links
+ syncFormContentToInstance(oldParent); // Resolve existing links in old directory
+ syncInstanceToFormContent(newParent); // Now update the form, effectively re-rendering the links
Contexts.getConversationContext().set("currentDirectory", newParent);
}
+ */
/* -------------------------- Messages ------------------------------ */
+ @Override
protected void createdMessage() {
getFacesMessages().addFromResourceBundleOrDefault(
SEVERITY_INFO,
@@ -186,6 +257,7 @@
);
}
+ @Override
protected void updatedMessage() {
getFacesMessages().addFromResourceBundleOrDefault(
SEVERITY_INFO,
@@ -195,6 +267,7 @@
);
}
+ @Override
protected void deletedMessage() {
getFacesMessages().addFromResourceBundleOrDefault(
SEVERITY_INFO,
@@ -206,31 +279,94 @@
/* -------------------------- Internal Methods ------------------------------ */
+ protected void findHistoricalFiles(WikiDocument doc) {
+ getLog().debug("Finding number of historical files for: " + doc);
+ numOfHistoricalFiles= getWikiNodeDAO().findNumberOfHistoricalFiles(doc);
+ if (isHistoricalFilesPresent()) {
+ historicalFiles = getWikiNodeDAO().findHistoricalFiles(doc);
+ }
+ }
- private void syncFormToInstance(Directory dir) {
+ // Wiki text parser and plugins need this
+ protected void outjectDocumentAndDirectory(WikiDocument doc, WikiDirectory dir) {
+ if (isPageRootController()) {
+ if (doc != null) {
+ getLog().debug("setting current document: " + doc);
+ Contexts.getPageContext().set("currentDocument", doc);
+ }
+ if (dir != null) {
+ getLog().debug("setting current directory: " + dir);
+ Contexts.getPageContext().set("currentDirectory", dir);
+ }
+ }
+ }
+
+ private void syncLinks() {
+ if (linkTargets != null) getInstance().setOutgoingLinks(linkTargets);
+ }
+
+ private void syncTags() {
+ getInstance().setTagsCommaSeparated(tagString);
+ }
+
+ private void syncMacros(Long areaNumber, WikiDocument doc) {
+ if (doc.getHeader() != null) {
+ MacroWikiTextRenderer renderer = MacroWikiTextRenderer.renderMacros(areaNumber, doc.getHeader());
+ doc.setHeaderMacros(renderer.getMacros());
+ doc.setHeaderMacrosString(renderer.getMacrosString());
+ }
+ if (doc.getContent() != null) {
+ MacroWikiTextRenderer renderer = MacroWikiTextRenderer.renderMacros(areaNumber, doc.getContent());
+ doc.setContentMacros(renderer.getMacros());
+ doc.setContentMacrosString(renderer.getMacrosString());
+ }
+ if (doc.getFooter() != null) {
+ MacroWikiTextRenderer renderer = MacroWikiTextRenderer.renderMacros(areaNumber, doc.getFooter());
+ doc.setFooterMacros(renderer.getMacros());
+ doc.setFooterMacrosString(renderer.getMacrosString());
+ }
+ }
+
+ private void syncFormContentToInstance(WikiDirectory dir) {
+ if (formContent != null) {
+ getLog().debug("sync form content to instance");
WikiLinkResolver wikiLinkResolver = (WikiLinkResolver)Component.getInstance("wikiLinkResolver");
+ linkTargets = new HashSet<WikiFile>();
getInstance().setContent(
- wikiLinkResolver.convertToWikiProtocol(dir.getAreaNumber(), formContent)
+ wikiLinkResolver.convertToWikiProtocol(linkTargets, dir.getAreaNumber(), formContent)
);
- getInstance().setMacros( WikiUtil.findMacros(getInstance(), getParentDirectory(), formContent) );
+ syncMacros(dir.getAreaNumber(), getInstance());
+ }
}
- private void syncInstanceToForm(Directory dir) {
+ private void syncInstanceToFormContent(WikiDirectory dir) {
+ getLog().debug("sync instance to form");
WikiLinkResolver wikiLinkResolver = (WikiLinkResolver)Component.getInstance("wikiLinkResolver");
formContent = wikiLinkResolver.convertFromWikiProtocol(dir.getAreaNumber(), getInstance().getContent());
+ if (historicalCopy == null) {
+ getLog().debug("making a history copy of the document");
+ historicalCopy = new WikiDocument();
+ historicalCopy.flatCopy(getInstance(), true);
+ }
+ }
+
+ protected String getFeedEntryManagerName() {
+ return "wikiDocumentFeedEntryManager";
}
/* -------------------------- Public Features ------------------------------ */
public String getFormContent() {
// Load the document content and resolve links
- if (formContent == null) syncInstanceToForm(getParentDirectory());
+ if (formContent == null) syncInstanceToFormContent(getParentNode());
return formContent;
}
public void setFormContent(String formContent) {
this.formContent = formContent;
- if (formContent != null) syncFormToInstance(getParentDirectory());
+ if (formContent != null) {
+ syncFormContentToInstance(getParentNode());
+ }
}
public boolean isMinorRevision() {
@@ -248,11 +384,11 @@
public void setEnabledPreview(boolean enabledPreview) {
this.enabledPreview = enabledPreview;
- syncFormToInstance(getParentDirectory());
+ syncFormContentToInstance(getParentNode());
}
- public boolean isSiteFeedEntryPresent() {
- return feedDAO.isOnSiteFeed(getInstance());
+ public boolean isOnSiteFeed() {
+ return isOnSiteFeed;
}
public boolean isPushOnFeeds() {
@@ -278,26 +414,27 @@
// TODO: Move this into WikiTextEditor.java
public boolean isShowPluginPrefs() {
Boolean showPluginPrefs = (Boolean)Contexts.getPageContext().get("showPluginPreferences");
- return showPluginPrefs != null ? showPluginPrefs : false;
+ return showPluginPrefs != null && showPluginPrefs;
}
- public boolean isHistoricalNodesPresent() {
- if (numOfHistoricalNodes == null) {
- getLog().debug("Finding number of historical nodes for: " + getInstance());
- numOfHistoricalNodes = getNodeDAO().findNumberOfHistoricalNodes(getInstance());
+ public boolean isHistoricalFilesPresent() {
+ return numOfHistoricalFiles != null && numOfHistoricalFiles> 0;
}
- return numOfHistoricalNodes != null && numOfHistoricalNodes > 0;
+
+ public List<WikiFile> getHistoricalFiles() {
+ return historicalFiles;
+ }
+
+ public String getTagString() {
+ return tagString;
}
- public List<Node> getHistoricalNodes() {
- if (historicalNodes == null)
- historicalNodes = getNodeDAO().findHistoricalNodes(getInstance());
- return historicalNodes;
+ public void setTagString(String tagString) {
+ this.tagString = tagString;
}
- public List<TagDAO.TagCount> getPopularTags() {
- List list = tagDAO.findTagsAggregatedSorted(wikiRoot, null, 0);
- return list;
+ public boolean isTagInTagString(String tag) {
+ return tag != null && getTagString() != null && getTagString().contains(tag);
}
}
1.1 date: 2007/12/19 04:29:25; author: cbauer; state: Exp;jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/DocumentHistory.java
Index: DocumentHistory.java
===================================================================
package org.jboss.seam.wiki.core.action;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.*;
import org.jboss.seam.annotations.datamodel.DataModel;
import org.jboss.seam.annotations.datamodel.DataModelSelection;
import org.jboss.seam.annotations.security.Restrict;
import org.jboss.seam.contexts.Contexts;
import org.jboss.seam.faces.FacesMessages;
import org.jboss.seam.log.Log;
import org.jboss.seam.security.AuthorizationException;
import org.jboss.seam.security.Identity;
import org.jboss.seam.wiki.core.dao.WikiNodeDAO;
import org.jboss.seam.wiki.core.model.WikiDocument;
import org.jboss.seam.wiki.core.model.WikiFile;
import org.jboss.seam.wiki.util.Diff;
import org.jboss.seam.wiki.util.WikiUtil;
import javax.faces.application.FacesMessage;
import java.io.Serializable;
import java.util.List;
/**
* Diff for historical WikiDocuments.
*
* TODO: Needs to be generalized to support other WikiFiles, should be easy, except for polymorphic diff() UI, probably
* hierarchy of WikiFileDiff actions and some page fragments. Maybe move diff() algorithm into each WikiFile subclass.
*
* @author Christian Bauer
*/
@Name("documentHistory")
@Scope(ScopeType.CONVERSATION)
@AutoCreate
public class DocumentHistory implements Serializable {
private boolean isInitialized = false;
@Logger
Log log;
@In
WikiNodeDAO wikiNodeDAO;
@In
private FacesMessages facesMessages;
@DataModel
private List<WikiFile> historicalFileList;
public List<WikiFile> getHistoricalFileList() { return historicalFileList; }
public void setHistoricalFileList(List<WikiFile> historicalFileList) { this.historicalFileList = historicalFileList; }
@DataModelSelection
private WikiFile selectedHistoricalFile;
public WikiFile getSelectedHistoricalFile() { return selectedHistoricalFile; }
public void setSelectedHistoricalFile(WikiFile selectedHistoricalFile) {
log.debug("selecting historical file id: " + selectedHistoricalFile.getHistoricalFileId());
this.selectedHistoricalFile = selectedHistoricalFile;
}
Long fileId;
public Long getFileId() { return fileId; }
public void setFileId(Long fileId) { this.fileId = fileId; }
Long historicalFileId;
public Long getHistoricalFileId() { return historicalFileId; }
public void setHistoricalFileId(Long historicalFileId) { this.historicalFileId = historicalFileId; }
private WikiFile currentFile;
public WikiFile getCurrentFile() { return currentFile; }
private WikiFile displayedHistoricalFile;
public WikiFile getDisplayedHistoricalFile() { return displayedHistoricalFile; }
private String diffResult;
public String getDiffResult() { return diffResult; }
@Factory("historicalFileList")
public void initializeHistoricalFileList() {
if (historicalFileList == null) {
log.debug("initializing list of historical files for file:" + getCurrentFile());
historicalFileList = wikiNodeDAO.findHistoricalFiles(getCurrentFile());
}
}
public String init() {
if (!isInitialized) {
if (fileId == null) return "missingParameter";
log.debug("initializing document history with file id: " + getFileId());
if (currentFile == null) {
log.debug("loading current file: " + getFileId());
currentFile = wikiNodeDAO.findWikiDocument(getFileId());
if (!Identity.instance().hasPermission("Node", "read", currentFile) ) {
throw new AuthorizationException("You don't have permission for this operation");
}
}
initializeHistoricalFileList();
}
isInitialized = true;
return null;
}
public void displayHistoricalRevision() {
log.debug("displaying historical file id: " + selectedHistoricalFile.getHistoricalFileId());
displayedHistoricalFile = selectedHistoricalFile;
diffResult = null;
facesMessages.addFromResourceBundleOrDefault(
FacesMessage.SEVERITY_INFO,
"lacewiki.msg.DiffOldVersionDisplayed",
"Showing historical revision {0}",
selectedHistoricalFile.getRevision()
);
}
public void diff() {
init(); // TODO: Why doesn't Seam execute my page action but instead s:link action="diff" in a fake RENDER RESPONSE?!?
displayedHistoricalFile = null;
if (historicalFileId == null) return;
selectedHistoricalFile = wikiNodeDAO.findHistoricalFile(getCurrentFile().getHistoricalEntityName(), historicalFileId);
if (selectedHistoricalFile == null) {
facesMessages.addFromResourceBundleOrDefault(
FacesMessage.SEVERITY_ERROR,
"lacewiki.msg.HistoricalNodeNotFound",
"Couldn't find historical node: {0}",
historicalFileId
);
return;
}
String[] a = ((WikiDocument)selectedHistoricalFile).getContent().split("\n");
String[] b = ((WikiDocument)currentFile).getContent().split("\n");
StringBuilder result = new StringBuilder();
List<Diff.Difference> differences = new Diff(a, b).diff();
for (Diff.Difference diff : differences) {
int delStart = diff.getDeletedStart();
int delEnd = diff.getDeletedEnd();
int addStart = diff.getAddedStart();
int addEnd = diff.getAddedEnd();
String type = delEnd != Diff.NONE && addEnd != Diff.NONE ? "changed" : (delEnd == Diff.NONE ? "added" : "deleted");
// Info line
result.append("<div class=\"diffInfo\">");
result.append("From ");
result.append(delStart == delEnd || delEnd == Diff.NONE ? "line" : "lines");
result.append(" ");
result.append(delStart);
if (delEnd != Diff.NONE && delStart != delEnd) {
result.append(" to ").append(delEnd);
}
result.append(" ").append(type).append(" to ");
result.append(addStart == addEnd || addEnd == Diff.NONE ? "line" : "lines");
result.append(" ");
result.append(addStart);
if (addEnd != Diff.NONE && addStart != addEnd) {
result.append(" to ").append(addEnd);
}
result.append(":");
result.append("</div>\n");
if (delEnd != Diff.NONE) {
result.append("<div class=\"diffDeleted\">");
for (int lnum = delStart; lnum <= delEnd; ++lnum) {
result.append( WikiUtil.escapeHtml(a[lnum], false) ).append("<br/>");
}
result.append("</div>");
if (addEnd != Diff.NONE) {
//result.append("----------------------------").append("\n");
}
}
if (addEnd != Diff.NONE) {
result.append("<div class=\"diffAdded\">");
for (int lnum = addStart; lnum <= addEnd; ++lnum) {
result.append( WikiUtil.escapeHtml(b[lnum], false) ).append("<br/>");
}
result.append("</div>");
}
}
diffResult = result.toString();
facesMessages.addFromResourceBundleOrDefault(
FacesMessage.SEVERITY_INFO,
"lacewiki.msg.DiffCreated",
"Comparing current revision with historical revision {0}",
selectedHistoricalFile.getRevision()
);
}
@Restrict("#{s:hasPermission('Node', 'edit', documentHistory.currentFile)}")
public String rollback() {
facesMessages.addFromResourceBundleOrDefault(
FacesMessage.SEVERITY_INFO,
"lacewiki.msg.RollingBackDocument",
"Rolling document back to revision {0}",
selectedHistoricalFile.getRevision()
);
return "rollback";
}
@Restrict("#{s:hasPermission('User', 'isAdmin', currentUser)}")
public String purgeHistory() {
wikiNodeDAO.removeHistoricalFiles(getCurrentFile());
return "purgedHistory";
}
}
1.1 date: 2007/12/19 04:29:25; author: cbauer; state: Exp;jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/TagQuery.java
Index: TagQuery.java
===================================================================
package org.jboss.seam.wiki.core.action;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.wiki.core.dao.TagDAO;
import org.jboss.seam.wiki.core.model.WikiDirectory;
import org.jboss.seam.wiki.core.model.WikiFile;
import java.io.Serializable;
import java.util.List;
@Name("tagQuery")
@Scope(ScopeType.CONVERSATION)
public class TagQuery implements Serializable {
@In
TagDAO tagDAO;
@In
WikiDirectory wikiRoot;
private String tag;
public String getTag() { return tag; }
public void setTag(String tag) { this.tag = tag; }
private List<WikiFile> taggedFiles;
public List<WikiFile> getTaggedFiles() {
if (taggedFiles == null) {
loadTaggedFiles();
}
return taggedFiles;
}
public void loadTaggedFiles() {
taggedFiles = tagDAO.findWikFiles(wikiRoot, null, tag);
}
}
1.1 date: 2007/12/19 04:29:25; author: cbauer; state: Exp;jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/CommentQuery.java
Index: CommentQuery.java
===================================================================
package org.jboss.seam.wiki.core.action;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Observer;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.wiki.core.dao.WikiNodeDAO;
import org.jboss.seam.wiki.core.model.WikiComment;
import org.jboss.seam.wiki.core.model.WikiDocument;
import org.jboss.seam.wiki.core.action.prefs.CommentsPreferences;
import java.io.Serializable;
import java.util.List;
import java.util.ArrayList;
@Name("commentQuery")
@Scope(ScopeType.CONVERSATION)
public class CommentQuery implements Serializable {
@In
WikiNodeDAO wikiNodeDAO;
@In
protected DocumentHome documentHome;
@In
protected CommentsPreferences commentsPreferences;
protected List<WikiComment> comments;
public List<WikiComment> getComments() {
if (comments == null) loadComments();
return comments;
}
@Observer(value = {
"PersistenceContext.filterReset",
"PreferenceComponent.refresh.commentsPreferences",
"Comment.commentListRefresh"
}, create = false)
public void loadComments() {
// Don't do the expensive query if the simple query doesn't return children
if (wikiNodeDAO.findChildrenCount(documentHome.getInstance()) == 0) {
comments = new ArrayList<WikiComment>();
return;
}
if (commentsPreferences.getThreadedComments() != null && commentsPreferences.getThreadedComments()) {
comments = wikiNodeDAO.findWikiCommentsThreaded(documentHome.getInstance());
} else {
comments = wikiNodeDAO.findWikiCommentsFlat(documentHome.getInstance(), commentsPreferences.getListAscending());
}
}
}
1.1 date: 2007/12/19 04:29:25; author: cbauer; state: Exp;jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/action/UploadHome.java
Index: UploadHome.java
===================================================================
package org.jboss.seam.wiki.core.action;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.wiki.core.model.WikiUpload;
import org.jboss.seam.wiki.core.model.WikiDirectory;
import org.jboss.seam.wiki.core.upload.UploadType;
import org.jboss.seam.wiki.core.upload.UploadTypes;
import org.jboss.seam.wiki.core.upload.Uploader;
import org.jboss.seam.wiki.core.upload.editor.UploadEditor;
import javax.faces.application.FacesMessage;
import java.util.Date;
import java.util.Map;
@Name("uploadHome")
@Scope(ScopeType.CONVERSATION)
public class UploadHome extends NodeHome<WikiUpload, WikiDirectory> {
/* -------------------------- Context Wiring ------------------------------ */
@In(required = false)
Uploader uploader;
@In
Map<String, UploadType> uploadTypes;
/* -------------------------- Internal State ------------------------------ */
protected UploadEditor uploadEditor;
private String tagString;
/* -------------------------- Basic Overrides ------------------------------ */
@Override
public Class<WikiUpload> getEntityClass() {
return WikiUpload.class;
}
@Override
public WikiUpload findInstance() {
return getWikiNodeDAO().findWikiUpload((Long)getId());
}
@Override
protected WikiDirectory findParentNode(Long parentNodeId) {
return getEntityManager().find(WikiDirectory.class, parentNodeId);
}
@Override
public WikiUpload afterNodeCreated(WikiUpload ignoredNode) {
if (uploader == null || uploader.getUpload() == null) {
throw new RuntimeException("No uploader found for create");
}
getLog().debug("initializing with new uploaded file: " + uploader.getFilename());
WikiUpload upload = uploader.getUpload();
upload = super.afterNodeCreated(upload);
initUploadEditor(upload);
return upload;
}
@Override
public WikiUpload afterNodeFound(WikiUpload upload) {
upload = super.afterNodeFound(upload);
getLog().debug("initializing with existing upload '" + upload + "' and content type: " + upload.getContentType());
tagString = upload.getTagsCommaSeparated();
initUploadEditor(upload);
return upload;
}
/* -------------------------- Custom CUD ------------------------------ */
@Override
protected boolean preparePersist() {
return uploadEditor.preparePersist();
}
@Override
protected boolean beforePersist() {
// Set createdOn date _now_
getInstance().setCreatedOn(new Date());
// Tags
getInstance().setTagsCommaSeparated(tagString);
return uploadEditor.beforePersist();
}
@Override
protected boolean beforeUpdate() {
// Tags
getInstance().setTagsCommaSeparated(tagString);
return uploadEditor.beforeUpdate();
}
@Override
protected boolean beforeRemove() {
return uploadEditor.beforeRemove();
}
/* -------------------------- Internal Methods ------------------------------ */
private void initUploadEditor(WikiUpload instance) {
if (uploader != null && uploader.getUpload() != null) {
uploadEditor = uploader.getUploadHandler().createEditor(uploader.getUpload());
} else {
UploadType uploadType = uploadTypes.get(instance.getContentType());
if (uploadType == null) {
getLog().debug("couldn't find upload handler for content type, using generic handler and editor");
uploadType = uploadTypes.get(UploadTypes.GENERIC_UPLOAD_TYPE);
}
uploadEditor = uploadType.getUploadHandler().createEditor(instance);
}
}
/* -------------------------- Messages ------------------------------ */
@Override
protected void createdMessage() {
getFacesMessages().addFromResourceBundleOrDefault(
FacesMessage.SEVERITY_INFO,
"lacewiki.msg.Upload.Persist",
"File '{0}' has been saved.",
getInstance().getName()
);
}
@Override
protected void updatedMessage() {
getFacesMessages().addFromResourceBundleOrDefault(
FacesMessage.SEVERITY_INFO,
"lacewiki.msg.Upload.Update",
"File '{0}' has been updated.",
getInstance().getName()
);
}
@Override
protected void deletedMessage() {
getFacesMessages().addFromResourceBundleOrDefault(
FacesMessage.SEVERITY_INFO,
"lacewiki.msg.Upload.Delete",
"File '{0}' has been deleted.",
getInstance().getName()
);
}
protected void uploadUpdatedMessage() {
getFacesMessages().addFromResourceBundleOrDefault(
FacesMessage.SEVERITY_INFO,
"lacewiki.msg.uploadEdit.UpdateUpload",
"File '{0}' has been uploaded.",
uploader.getFilename()
);
}
/* -------------------------- Public Features ------------------------------ */
public UploadEditor getUploadEditor() {
if (uploadEditor == null) initUploadEditor(getInstance());
return uploadEditor;
}
public void uploadUpdateInstance() {
if (uploader.uploadUpdateInstance(getInstance(), true) != null) {
uploadUpdatedMessage();
}
}
public String getTagString() {
return tagString;
}
public void setTagString(String tagString) {
this.tagString = tagString;
}
public boolean isTagInTagString(String tag) {
return tag != null && getTagString() != null && getTagString().contains(tag);
}
}
More information about the jboss-cvs-commits
mailing list