/* * JBoss, Home of Professional Open Source * * Distributable under LGPL license. * See terms of license at gnu.org. */ package org.jboss.seam.wiki.core.action; import org.jboss.seam.Component; 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.security.Restrict; import org.jboss.seam.international.Messages; import org.jboss.seam.international.StatusMessages; 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 static org.jboss.seam.international.StatusMessage.Severity.INFO; import java.util.*; /** * Directory editor functionality. * * @author Christian Bauer */ @Name("directoryHome") @Scope(ScopeType.CONVERSATION) public class DirectoryHome extends NodeHome<WikiDirectory, WikiDirectory> { /* -------------------------- Context Wiring ------------------------------ */ @In protected FeedDAO feedDAO; /* -------------------------- Internal State ------------------------------ */ private boolean hasFeed; 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; /* -------------------------- Basic Overrides ------------------------------ */ @Override public Class<WikiDirectory> getEntityClass() { return WikiDirectory.class; } @Override public WikiDirectory findInstance() { return getWikiNodeDAO().findWikiDirectory((Long)getId()); } @Override protected WikiDirectory findParentNode(Long parentNodeId) { return getEntityManager().find(WikiDirectory.class, parentNodeId); } @Override public WikiDirectory beforeNodeEditFound(WikiDirectory dir) { dir = super.beforeNodeEditFound(dir); hasFeed = dir.getFeed()!=null; childDocuments = getWikiNodeDAO().findWikiDocuments(dir, WikiNode.SortableProperty.name, true); menuItems = getWikiNodeDAO().findMenuItems(dir); alreadyUsedMenuItems = new TreeSet<WikiDirectory>(); for (WikiMenuItem menuItem : menuItems) { alreadyUsedMenuItems.add(menuItem.getDirectory()); } refreshAvailableMenuItems(dir); return dir; } @Override protected boolean requiresMessageId() { return false; } /* -------------------------- Custom CUD ------------------------------ */ @Override public String persist() { if (getParentNode().getParent() != null) { // This is a subdirectory in an area getInstance().setAreaNumber(getParentNode().getAreaNumber()); return super.persist(); } else { // This is a logical area in the wiki root // Satisfy NOT NULL constraint getInstance().setAreaNumber(Long.MAX_VALUE); // Do the persist() first, we need the identifier after this String outcome = super.persist(); getInstance().setAreaNumber(getInstance().getId()); // And flush() again... getEntityManager().flush(); return outcome; } } @Override protected boolean beforePersist() { createOrRemoveFeed(); return super.preparePersist(); } @Override protected boolean beforeUpdate() { createOrRemoveFeed(); updateMenuItems(); return super.beforeUpdate(); } protected NodeRemover getNodeRemover() { return (NodeRemover)Component.getInstance(DirectoryNodeRemover.class); } /* -------------------------- Messages ------------------------------ */ @Override protected void createdMessage() { StatusMessages.instance().addFromResourceBundleOrDefault( INFO, "lacewiki.msg.Directory.Persist", "Directory '{0}' has been saved.", getInstance().getName() ); } @Override protected void updatedMessage() { StatusMessages.instance().addFromResourceBundleOrDefault( INFO, "lacewiki.msg.Directory.Update", "Directory '{0}' has been updated.", getInstance().getName() ); } @Override protected void deletedMessage() { StatusMessages.instance().addFromResourceBundleOrDefault( INFO, "lacewiki.msg.Directory.Delete", "Directory '{0}' has been deleted.", getInstance().getName() ); } protected void feedCreatedMessage() { StatusMessages.instance().addFromResourceBundleOrDefault( INFO, "lacewiki.msg.Feed.Create", "Created syndication feed for this directory"); } protected void feedRemovedMessage() { StatusMessages.instance().addFromResourceBundleOrDefault( INFO, "lacewiki.msg.Feed.Remove", "Removed syndication feed of this directory"); } protected String getEditorWorkspaceDescription(boolean create) { if (create) { return Messages.instance().get("lacewiki.label.dirEdit.CreateDirectory"); } else { return Messages.instance().get("lacewiki.label.dirEdit.EditDirectory") + ":" + getInstance().getName(); } } /* -------------------------- Internal Methods ------------------------------ */ private void refreshAvailableMenuItems(WikiDirectory dir) { if (availableMenuItems == null) availableMenuItems = new TreeSet(); availableMenuItems.clear(); 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); } } } } public void createOrRemoveFeed() { if (hasFeed && getInstance().getFeed() == null) { // Does not have a feed but user wants one, create it feedDAO.createFeed(getInstance()); feedCreatedMessage(); } else if (!hasFeed && getInstance().getFeed() != null) { // Does have feed but user doesn't want it anymore... delete it feedDAO.removeFeed(getInstance()); feedRemovedMessage(); } else if (getInstance().getFeed() != null) { // Does have a feed and user still wants it, update the feed feedDAO.updateFeed(getInstance()); } } /* -------------------------- Public Features ------------------------------ */ public List<WikiDocument> getChildDocuments() { return childDocuments; } public List<WikiMenuItem> getMenuItems() { return menuItems; } public WikiDirectory getSelectedChildDirectory() { return selectedChildDirectory; } public void setSelectedChildDirectory(WikiDirectory selectedChildDirectory) { this.selectedChildDirectory = 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"); getInstance().getFeed().getFeedEntries().clear(); getInstance().getFeed().setPublishedDate(new Date()); StatusMessages.instance().addFromResourceBundleOrDefault( INFO, "lacewiki.msg.Feed.Reset", "Queued removal of all feed entries from the syndication feed of this directory, please update to finalize"); } } @Restrict("#{s:hasPermission('Node', 'editMenu', directoryHome.instance)}") 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()); } } } @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) { if (currentPosition != newPosition) { // Shift and refresh displayed list WikiUtil.shiftListElement(menuItems, currentPosition, newPosition); } } }