/* * JBoss, Home of Professional Open Source * * Distributable under LGPL license. * See terms of license at gnu.org. */ package org.jboss.seam.wiki.plugin.basic; import org.hibernate.Query; import org.hibernate.Session; 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.wiki.core.dao.WikiNodeDAO; import org.jboss.seam.wiki.core.wikitext.engine.WikiLinkResolver; import org.jboss.seam.wiki.core.model.WikiDirectory; import org.jboss.seam.wiki.core.model.WikiDocument; import org.jboss.seam.wiki.core.model.WikiNode; import org.jboss.seam.wiki.core.model.WikiTreeNode; import org.jboss.seam.wiki.core.plugin.WikiPluginMacro; import org.jboss.seam.wiki.preferences.Preferences; import org.richfaces.component.UITree; import javax.persistence.EntityManager; import java.io.Serializable; import java.util.*; /** * @author Christian Bauer */ @Name("dirTocQuery") @Scope(ScopeType.CONVERSATION) public class DirTocQuery implements Serializable { public static final String MACRO_ATTR_TOCTREE = "dirTocTree"; @In EntityManager restrictedEntityManager; @In Integer currentAccessLevel; @In WikiDirectory currentDirectory; public List<WikiTreeNode<WikiDirectory>> getToc(WikiPluginMacro macro) { // We cache the result in the macro, so that when the getter is called over and over during rendering, we have it if (macro.getAttributes().get(MACRO_ATTR_TOCTREE) == null) { DirTocPreferences prefs = Preferences.instance().get(DirTocPreferences.class, macro); if (prefs.getRootDocumentLink() != null) { Long id = ((WikiLinkResolver)Component.getInstance("wikiLinkResolver")) .resolveWikiDirectoryId(currentDirectory.getAreaNumber(), prefs.getRootDocumentLink()); WikiDirectory foundDir = WikiNodeDAO.instance().findWikiDirectory(id); if (foundDir != null) currentDirectory = foundDir; } // Query the directory tree List<WikiTreeNode<WikiDirectory>> tree = WikiNodeDAO.instance().findWikiDirectoryTree(currentDirectory, WikiNode.SortableProperty.createdOn, true); Set<Long> directoryIds = new HashSet<Long>(); for (WikiTreeNode<WikiDirectory> treeNode : tree) { if (currentDirectory.getId().equals(treeNode.getNode().getId()) && (prefs.getShowRootDocuments() != null && prefs.getShowRootDocuments())) { directoryIds.add(treeNode.getNode().getId()); } else if (!currentDirectory.getId().equals(treeNode.getNode().getId())){ directoryIds.add(treeNode.getNode().getId()); } } if (directoryIds.size() == 0) return null; // Early exit // Now query the documents for the directories in the tree StringBuilder queryString = new StringBuilder(); queryString.append("select d from WikiDocument d "); // TODO: Rewrite this query to use a subselect nested set query, this has limits queryString.append("where d.parent.id in (:directories) "); if (prefs.getWithHeaderMacro() != null) queryString.append("and d.headerMacrosString like :headerMacro").append(" "); queryString.append("order by d.createdOn asc"); Query query = getSession().createQuery(queryString.toString()); query.setParameterList("directories", directoryIds); if (prefs.getWithHeaderMacro() != null) query.setParameter("headerMacro", "%"+prefs.getWithHeaderMacro()+"%"); query.setComment("retrieving documents for toc directory tree"); List<WikiDocument> flatDocs = query.list(); // Now attach the documents as payloads to the directories in the tree for (WikiDocument flatDoc : flatDocs) { Long directoryId = flatDoc.getParent().getId(); for (WikiTreeNode<WikiDirectory> treeNode : tree) { if (treeNode.getNode().getId().equals(directoryId)) { if (treeNode.getPayload() == null) treeNode.setPayload(new ArrayList()); ((Collection)treeNode.getPayload()).add(flatDoc); } } } macro.getAttributes().put(MACRO_ATTR_TOCTREE, tree); } return (List<WikiTreeNode<WikiDirectory>>)macro.getAttributes().get(MACRO_ATTR_TOCTREE); } public boolean expandTocTree(UITree tree) { return true; // Expand all nodes by default; } private Session getSession() { return ((Session)((org.jboss.seam.persistence.EntityManagerProxy) restrictedEntityManager).getDelegate()); } }