package org.brixcms.plugin.content;
import java.text.Normalizer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.ResourceModel;
import org.apache.wicket.util.lang.Args;
import org.apache.wicket.util.string.Strings;
import org.brixcms.Brix;
import org.brixcms.auth.Action;
import org.brixcms.auth.Action.Context;
import org.brixcms.jcr.JcrNodeWrapperFactory;
import org.brixcms.jcr.api.JcrNode;
import org.brixcms.jcr.api.JcrNodeIterator;
import org.brixcms.jcr.api.JcrSession;
import org.brixcms.jcr.wrapper.BrixNode;
import org.brixcms.plugin.content.auth.PostNodeAction;
import org.brixcms.plugin.content.auth.PostNodeAction.Type;
import org.brixcms.plugin.content.blog.post.PostNode;
import org.brixcms.plugin.content.blog.post.PostNodePlugin;
import org.brixcms.plugin.content.blog.post.PostNodeTreeRenderer;
import org.brixcms.plugin.content.blog.post.admin.editor.SimplePostEditorFactory;
import org.brixcms.plugin.content.blog.post.admin.editor.TinymcePostEditorFactory;
import org.brixcms.plugin.content.blog.post.comment.CommentNode;
import org.brixcms.plugin.content.blog.tile.BlogTile;
import org.brixcms.plugin.content.blog.tile.archive.BlogArchiveTile;
import org.brixcms.plugin.content.breadcrumb.BreadcrumbTile;
import org.brixcms.plugin.content.folder.FolderNode;
import org.brixcms.plugin.content.folder.FolderNodePlugin;
import org.brixcms.plugin.content.resource.admin.ResourceNodePlugin;
import org.brixcms.plugin.hierarchical.HierarchicalNodePlugin;
import org.brixcms.plugin.hierarchical.HierarchicalPluginLocator;
import org.brixcms.plugin.hierarchical.admin.NodeEditorPlugin;
import org.brixcms.plugin.site.ManageNodeTabFactory;
import org.brixcms.plugin.site.NodeTreeRenderer;
import org.brixcms.plugin.site.page.tile.Tile;
import org.brixcms.registry.ExtensionPoint;
import org.brixcms.registry.ExtensionPointRegistry;
import org.brixcms.workspace.Workspace;
/**
*
* @author dan.simko@gmail.com
*/
// TODO add doc
public class ContentPlugin extends HierarchicalNodePlugin {
public static final String WORKSPACE_ATTRIBUTE_STATE = "brix:content-state";
public static final String WORKSPACE_ATTRIBUTE_NAME = "brix:content-name";
private static final String ID = ContentPlugin.class.getName();
private static final String WORKSPACE_TYPE = "brix:content";
private static final String CONTETNT_NODE_NAME = Brix.NS_PREFIX + "content";
private final Brix brix;
public ContentPlugin(Brix brix) {
super(brix);
this.brix = brix;
initializeExtensionPoints(brix);
ExtensionPointRegistry registry = brix.getConfig().getRegistry();
registry.register(JcrNodeWrapperFactory.POINT, ContentRootNode.FACTORY);
registry.register(JcrNodeWrapperFactory.POINT, FolderNode.FACTORY);
registry.register(JcrNodeWrapperFactory.POINT, PostNode.FACTORY);
registry.register(JcrNodeWrapperFactory.POINT, CommentNode.FACTORY);
registerNodePlugin(new FolderNodePlugin(this));
registerNodePlugin(new PostNodePlugin(this));
registerNodePlugin(new ResourceNodePlugin(this));
registry.register(SimplePostEditorFactory.POINT, new SimplePostEditorFactory());
registry.register(TinymcePostEditorFactory.POINT, new TinymcePostEditorFactory());
registry.register(NodeTreeRenderer.POINT, new PostNodeTreeRenderer());
registry.register(Tile.POINT, new BlogTile());
registry.register(Tile.POINT, new BlogArchiveTile());
registry.register(Tile.POINT, new BreadcrumbTile());
}
@Override
public void initWorkspace(Workspace workspace, JcrSession workspaceSession) {
if (isContentWorkspace(workspace)) {
JcrNode root;
if (workspaceSession.itemExists(brix.getRootPath())) {
root = (JcrNode) workspaceSession.getItem(getBrix().getRootPath());
} else {
root = workspaceSession.getRootNode().addNode(Brix.ROOT_NODE_NAME, "nt:folder");
}
if (!root.isNodeType(BrixNode.JCR_TYPE_BRIX_NODE)) {
root.addMixin(BrixNode.JCR_TYPE_BRIX_NODE);
}
if (!root.hasNode(CONTETNT_NODE_NAME)) {
JcrNode content = root.addNode(CONTETNT_NODE_NAME, "nt:folder");
content.addMixin(BrixNode.JCR_TYPE_BRIX_NODE);
JcrNodeIterator nodes = root.getNodes();
while (nodes.hasNext()) {
BrixNode node = (BrixNode) nodes.nextNode();
if (node.isSame(content) == false) {
JcrSession session = root.getSession();
session.move(node.getPath(), content.getPath() + "/" + node.getName());
}
}
}
}
}
@Override
public List<Workspace> getWorkspaces(Workspace currentWorkspace, boolean isFrontend) {
if (isFrontend) {
return Collections.emptyList();
}
Map<String, String> attributes = new HashMap<String, String>();
attributes.put(Brix.WORKSPACE_ATTRIBUTE_TYPE, WORKSPACE_TYPE);
List<Workspace> workspaces = new ArrayList<Workspace>(brix.getWorkspaceManager().getWorkspacesFiltered(attributes));
Collections.sort(workspaces, new Comparator<Workspace>() {
@Override
public int compare(Workspace o1, Workspace o2) {
String n1 = getWorkspaceName(o1);
String n2 = getWorkspaceName(o2);
int r = n1.compareTo(n2);
if (r == 0) {
String s1 = getWorkspaceState(o1);
String s2 = getWorkspaceState(o2);
if (s1 != null && s2 != null) {
return s1.compareTo(s2);
} else {
return 0;
}
} else {
return r;
}
}
});
return workspaces;
}
@Override
public boolean isPluginWorkspace(Workspace workspace) {
return isContentWorkspace(workspace);
}
@Override
public String getUserVisibleName(Workspace workspace, boolean isFrontend) {
String name = "Content - " + getWorkspaceName(workspace);
String state = getWorkspaceState(workspace);
if (!Strings.isEmpty(state)) {
name = name + " - " + state;
}
return name;
}
public boolean isContentWorkspace(Workspace workspace) {
return WORKSPACE_TYPE.equals(workspace.getAttribute(Brix.WORKSPACE_ATTRIBUTE_TYPE));
}
private static final ExtensionPoint<NodeEditorPlugin> NEP_POINT = new ExtensionPoint<NodeEditorPlugin>() {
@Override
public Multiplicity getMultiplicity() {
return Multiplicity.COLLECTION;
}
@Override
public String getUuid() {
return ContentPlugin.class.getName() + ":NodeEditorPluginExtensionPoint";
}
};
private static final ExtensionPoint<ManageNodeTabFactory> MNTF_POINT = new ExtensionPoint<ManageNodeTabFactory>() {
@Override
public Multiplicity getMultiplicity() {
return Multiplicity.COLLECTION;
}
@Override
public String getUuid() {
return ContentPlugin.class.getName() + ":ManageNodeTabFactoryExtensionPoint";
}
};
@Override
protected ExtensionPoint<? extends NodeEditorPlugin> getNodeEditorPluginExtensionPoint() {
return NEP_POINT;
}
@Override
protected ExtensionPoint<ManageNodeTabFactory> getManageNodeTabFactoryExtensionPoint() {
return MNTF_POINT;
}
public static ContentPlugin get(Brix brix) {
return (ContentPlugin) brix.getPlugin(ID);
}
public static ContentPlugin get() {
return get(Brix.get());
}
@Override
protected HierarchicalPluginLocator getPluginLocator() {
return new ContentPluginLocator();
}
@Override
protected IModel<String> getTabName() {
return new ResourceModel("content-plugin.pluginName");
}
@Override
public String getId() {
return ID;
}
public boolean contentExists(String name, String state) {
return getContentWorkspace(name, state) != null;
}
public Workspace getContentWorkspace(String name, String state) {
Map<String, String> attributes = new HashMap<String, String>();
attributes.put(Brix.WORKSPACE_ATTRIBUTE_TYPE, WORKSPACE_TYPE);
attributes.put(WORKSPACE_ATTRIBUTE_NAME, name);
if (state != null) {
attributes.put(WORKSPACE_ATTRIBUTE_STATE, state);
}
List<Workspace> res = brix.getWorkspaceManager().getWorkspacesFiltered(attributes);
return res.isEmpty() ? null : res.get(0);
}
public Workspace createContent(String name, String state) {
Workspace workspace = brix.getWorkspaceManager().createWorkspace();
workspace.setAttribute(Brix.WORKSPACE_ATTRIBUTE_TYPE, WORKSPACE_TYPE);
setWorkspaceName(workspace, name);
setWorkspaceState(workspace, state);
return workspace;
}
public void setWorkspaceName(Workspace workspace, String name) {
workspace.setAttribute(WORKSPACE_ATTRIBUTE_NAME, name);
}
public void setWorkspaceState(Workspace workspace, String state) {
workspace.setAttribute(WORKSPACE_ATTRIBUTE_STATE, state);
}
public String getWorkspaceName(Workspace workspace) {
return workspace.getAttribute(WORKSPACE_ATTRIBUTE_NAME);
}
public String getWorkspaceState(Workspace workspace) {
return workspace.getAttribute(WORKSPACE_ATTRIBUTE_STATE);
}
@Override
protected String getRootNodeName() {
return CONTETNT_NODE_NAME;
}
public boolean canViewPostNode(PostNode node, Context context) {
Action action = new PostNodeAction(context, Type.VIEW, node);
return brix.getAuthorizationStrategy().isActionAuthorized(action);
}
public static String normalizeValue(final String value, int maxLength) {
if (value != null) {
String normalized = Normalizer.normalize(value, Normalizer.Form.NFKD).replaceAll("[^\\p{ASCII}]+", "");
normalized = normalized.replaceAll("[^a-zA-Z0-9]", "-");
normalized = normalized.replaceAll("-+", "-");
if (normalized.length() > maxLength) {
normalized = normalized.substring(0, maxLength);
}
normalized = normalized.toLowerCase();
return normalized;
}
return null;
}
@Override
protected int getTabPriority() {
return 1000;
}
public void registerNodePlugin(NodeEditorPlugin plugin) {
Args.notNull(plugin, "plugin");
brix.getConfig().getRegistry().register(NEP_POINT, plugin);
}
public void registerManageNodeTabFactory(ManageNodeTabFactory factory) {
Args.notNull(factory, "factory");
brix.getConfig().getRegistry().register(MNTF_POINT, factory);
}
}