The admin form of a PortalWorkspace now shows a mapped category system without a restart (issue #1899).

git-svn-id: https://svn.libreccm.org/ccm/trunk@2708 8810af33-2d31-482b-a856-94f89814c4df
master
jensp 2014-06-17 14:35:54 +00:00
parent bacea5257f
commit da6df35eff
2 changed files with 121 additions and 34 deletions

View File

@ -22,12 +22,14 @@ import org.apache.log4j.Logger;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.RequestLocal;
import com.arsdigita.bebop.SimpleContainer;
import com.arsdigita.bebop.Tree;
import com.arsdigita.bebop.event.ActionEvent;
import com.arsdigita.bebop.event.ActionListener;
import com.arsdigita.bebop.tree.TreeModel;
import com.arsdigita.bebop.tree.TreeModelBuilder;
import com.arsdigita.bebop.tree.TreeNode;
import com.arsdigita.categorization.Category;
import com.arsdigita.categorization.CategoryTreeModelLite;
import com.arsdigita.domain.DomainObjectFactory;
@ -41,6 +43,7 @@ import com.arsdigita.util.Assert;
import com.arsdigita.util.LockableImpl;
import com.arsdigita.web.Application;
import com.arsdigita.web.Web;
import java.util.Iterator;
/**
* CategoryComponent.
@ -49,8 +52,7 @@ import com.arsdigita.web.Web;
*/
public class CategoryComponent extends SimpleContainer {
private static final Logger s_log = Logger
.getLogger(CategoryComponent.class);
private static final Logger s_log = Logger.getLogger(CategoryComponent.class);
private ACSObjectSelectionModel m_catModel;
private CategoryTree m_tree;
private ApplicationSelectionModel m_appModel;
@ -63,26 +65,19 @@ public class CategoryComponent extends SimpleContainer {
* @param appModel
*/
public CategoryComponent(ApplicationSelectionModel appModel) {
// this model means that the server needs a restart
// if you want to map a category to this personal portal
// AND vice versa - if you remove a domain mapping you need to
// restart the server otherwise you will get an exception next time
// this Component is viewed.
if (m_root != null) {
setNamespace(WorkspacePage.PORTAL_XML_NS);
setTag("portal:categoryPanel");
setNamespace(WorkspacePage.PORTAL_XML_NS);
setTag("portal:categoryPanel");
m_appModel = appModel;
m_appModel = appModel;
m_catModel = new ACSObjectSelectionModel("category");
m_tree = new CategoryTree(m_catModel);
m_catModel = new ACSObjectSelectionModel("category");
m_tree = new CategoryTree(m_catModel);
add(m_tree);
add(new CategoryTable(appModel, m_catModel));
add(m_tree);
add(new CategoryTable(appModel, m_catModel));
m_error = new Label("");
add(m_error);
}
m_error = new Label("");
add(m_error);
}
/**
@ -115,11 +110,11 @@ public class CategoryComponent extends SimpleContainer {
s_log.debug("action performed");
if (m_catModel.isSelected(state)) {
Category category = (Category) m_catModel
.getSelectedObject(state);
.getSelectedObject(state);
// Make sure that other workspaces aren't already categorized
DataCollection workspaces = SessionManager.getSession()
.retrieve(Workspace.BASE_DATA_OBJECT_TYPE);
.retrieve(Workspace.BASE_DATA_OBJECT_TYPE);
Filter f = workspaces.addInSubqueryFilter("id",
"com.arsdigita.categorization.immediateChildObjectIDs");
@ -129,16 +124,16 @@ public class CategoryComponent extends SimpleContainer {
s_log.debug("About to categorize");
Workspace workspace = (Workspace) m_appModel
.getSelectedObject(state);
.getSelectedObject(state);
category.addChild(workspace);
category.save();
} else {
// print an error
while (workspaces.next()) {
Workspace wk = (Workspace) DomainObjectFactory
.newInstance(workspaces.getDataObject());
.newInstance(workspaces.getDataObject());
m_error.setLabel(
"This category already has a workspace "
"This category already has a workspace "
+ wk.getTitle(), state);
}
}
@ -150,23 +145,115 @@ public class CategoryComponent extends SimpleContainer {
/**
* A TreeModelBuilder that loads the tree from the current category
*/
private static class SectionTreeModelBuilder extends LockableImpl implements
TreeModelBuilder {
private static class SectionTreeModelBuilder extends LockableImpl implements TreeModelBuilder {
/**
* A RequestLocal wrapper for the model. It is necessary to wrap the model into a
* {@link RequestLocal} wrapper because the contents of the model may change. Before this
* was introduced the system had be restarted if a new category system was mapped to
* a PortalWorkspace.
*/
final RequestLocal treeModel = new TreeModelRequestLocal();
public SectionTreeModelBuilder() {
super();
}
@Override
public TreeModel makeModel(Tree t, PageState s) {
return (TreeModel) treeModel.get(s);
}
}
/**
* The RequestLocal used by the {@link SectionTreeModelBuilder}.
*/
private static class TreeModelRequestLocal extends RequestLocal {
public TreeModelRequestLocal() {
//Nothing
}
/**
* Provides the initial value for this {@code {RequestLocal}. If a category system
* is mapped to the current PortalWorkspace (the current Application instance), the method
* returns a {@link CategoryTreeModelLite} instance. The {link CategoryTreeModelLite} is
* created using the root category of the mapped category system.
* If there is no mapping the method returns an instance of {@link EmptyTreeModel}.
*
* @param state
* @return
*/
@Override
protected Object initialValue(final PageState state) {
Application app = Web.getWebContext().getApplication();
Category root = null;
while (app != null && root == null) {
root = Category.getRootForObject(app);
app = (Application) app.getParentResource();
}
Assert.exists(root, Category.class);
return new CategoryTreeModelLite(root);
if (root == null) {
return new EmptyTreeModel();
} else {
Assert.exists(root, Category.class);
return new CategoryTreeModelLite(root);
}
}
}
/**
* A simple helper class representing an empty tree.
*/
private static class EmptyTreeModel implements TreeModel {
public EmptyTreeModel() {
//Nothing
}
@Override
public TreeNode getRoot(final PageState data) {
return new EmptyTreeRootNode();
}
@Override
public boolean hasChildren(final TreeNode node,
final PageState state) {
return false;
}
@Override
public Iterator getChildren(final TreeNode node,
final PageState data) {
return null;
}
}
/**
* The root node of an empty tree.
*/
private static class EmptyTreeRootNode implements TreeNode {
public EmptyTreeRootNode() {
//Nothing
}
@Override
public Object getKey() {
return "empty";
}
@Override
public Object getElement() {
return "";
}
}
}

View File

@ -9,7 +9,7 @@
name="ScientificCMS"
prettyName="Scientific CMS"
version="2.3.0"
release="devel-SNAPSHOT-r2691"
release="devel-SNAPSHOT-r2707"
webxml="sci-web.xml"
portletxml="sci-portlet.xml"
webapp="libreccm"