/** * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.brixcms.plugin.prototype; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.wicket.markup.html.panel.Panel; import org.apache.wicket.model.IModel; import org.apache.wicket.model.ResourceModel; import org.apache.wicket.util.lang.Objects; import org.brixcms.Brix; import org.brixcms.Path; import org.brixcms.Plugin; import org.brixcms.auth.Action; import org.brixcms.jcr.JcrUtil; import org.brixcms.jcr.JcrUtil.ParentLimiter; import org.brixcms.jcr.JcrUtil.TargetRootNodeProvider; import org.brixcms.jcr.api.JcrNode; import org.brixcms.jcr.api.JcrSession; import org.brixcms.plugin.prototype.auth.AccessPrototypePluginAction; import org.brixcms.plugin.site.SitePlugin; import org.brixcms.plugin.site.page.global.GlobalContainerNode; import org.brixcms.web.tab.AbstractWorkspaceTab; import org.brixcms.web.tab.IBrixTab; import org.brixcms.workspace.Workspace; public class PrototypePlugin implements Plugin { private static final String ID = PrototypePlugin.class.getName(); private static final String WORKSPACE_TYPE = "brix:prototype"; private static final String WORKSPACE_ATTRIBUTE_PROTOTYPE_NAME = "brix:prototype-name"; private final Brix brix; public static PrototypePlugin get() { return get(Brix.get()); } public static PrototypePlugin get(Brix brix) { return (PrototypePlugin) brix.getPlugin(ID); } public PrototypePlugin(Brix brix) { this.brix = brix; } public String getId() { return ID; } public String getUserVisibleName(Workspace workspace, boolean isFrontend) { return "Prototype " + getPrototypeName(workspace); } public List<Workspace> getWorkspaces(Workspace currentWorkspace, boolean isFrontend) { if (isFrontend) { Map<String, String> attributes = new HashMap<String, String>(); attributes.put(Brix.WORKSPACE_ATTRIBUTE_TYPE, WORKSPACE_TYPE); return brix.getWorkspaceManager().getWorkspacesFiltered(attributes); } else { return null; } } public void initWorkspace(Workspace workspace, JcrSession workspaceSession) { } public boolean isPluginWorkspace(Workspace workspace) { return isPrototypeWorkspace(workspace); } public List<IBrixTab> newTabs(IModel<Workspace> workspaceModel) { IBrixTab tabs[] = new IBrixTab[]{new Tab(new ResourceModel("prototypes", "Prototypes"), workspaceModel)}; return Arrays.asList(tabs); } public void createPrototype(Workspace originalWorkspace, String prototypeName) { Workspace workspace = brix.getWorkspaceManager().createWorkspace(); workspace.setAttribute(Brix.WORKSPACE_ATTRIBUTE_TYPE, WORKSPACE_TYPE); setPrototypeName(workspace, prototypeName); JcrSession originalSession = brix.getCurrentSession(originalWorkspace.getId()); JcrSession destSession = brix.getCurrentSession(workspace.getId()); brix.clone(originalSession, destSession); } public void setPrototypeName(Workspace workspace, String name) { workspace.setAttribute(WORKSPACE_ATTRIBUTE_PROTOTYPE_NAME, name); } public void createPrototype(List<JcrNode> nodes, String prototypeName) { if (nodes.isEmpty()) { throw new IllegalStateException("Node list can not be empty."); } Workspace workspace = brix.getWorkspaceManager().createWorkspace(); workspace.setAttribute(Brix.WORKSPACE_ATTRIBUTE_TYPE, WORKSPACE_TYPE); setPrototypeName(workspace, prototypeName); JcrSession destSession = brix.getCurrentSession(workspace.getId()); JcrUtil.cloneNodes(nodes, destSession.getRootNode()); destSession.save(); } public String getPrototypeName(Workspace workspace) { return workspace.getAttribute(WORKSPACE_ATTRIBUTE_PROTOTYPE_NAME); } public List<Workspace> getPrototypes() { Map<String, String> attributes = new HashMap<String, String>(); attributes.put(Brix.WORKSPACE_ATTRIBUTE_TYPE, WORKSPACE_TYPE); return brix.getWorkspaceManager().getWorkspacesFiltered(attributes); } public boolean isPrototypeWorkspace(Workspace workspace) { return WORKSPACE_TYPE.equals(workspace.getAttribute(Brix.WORKSPACE_ATTRIBUTE_TYPE)); } public boolean prototypeExists(String protypeName) { Map<String, String> attributes = new HashMap<String, String>(); attributes.put(Brix.WORKSPACE_ATTRIBUTE_TYPE, WORKSPACE_TYPE); attributes.put(WORKSPACE_ATTRIBUTE_PROTOTYPE_NAME, protypeName); return !brix.getWorkspaceManager().getWorkspacesFiltered(attributes).isEmpty(); } public void restoreNodes(List<JcrNode> nodes, final JcrNode targetRootNode) { if (nodes.isEmpty()) { throw new IllegalStateException("List 'nodes' must contain at least one node."); } ParentLimiter limiter = null; // targetRootNode is only applicable for regular Site nodes (not even // global container) final String siteRoot = SitePlugin.get().getSiteRootPath(); if (targetRootNode.getDepth() > 0) { final String commonParent = getCommonParentPath(nodes); limiter = new ParentLimiter() { public boolean isFinalParent(JcrNode node, JcrNode parent) { if (node.getPath().startsWith(siteRoot) && node instanceof GlobalContainerNode == false) { return parent.getPath().equals(commonParent); } else { return parent.getDepth() == 0; } } }; } TargetRootNodeProvider provider = new TargetRootNodeProvider() { public JcrNode getTargetRootNode(JcrNode node) { if (node.getPath().startsWith(siteRoot) && node instanceof GlobalContainerNode == false) { return targetRootNode; } else { return targetRootNode.getSession().getRootNode(); } } }; JcrUtil.cloneNodes(nodes, provider, limiter); targetRootNode.getSession().save(); } private String getCommonParentPath(List<JcrNode> nodes) { Path current = null; String sitePath = SitePlugin.get().getSiteRootPath(); for (JcrNode node : nodes) { if (node.getPath().startsWith(sitePath) && node instanceof GlobalContainerNode == false) { if (current == null) { current = new Path(node.getPath()).parent(); } else { Path another = new Path(node.getPath()).parent(); Path common = Path.ROOT; Iterator<String> i1 = current.iterator(); Iterator<String> i2 = another.iterator(); while (i1.hasNext() && i2.hasNext()) { String s1 = i1.next(); String s2 = i2.next(); if (Objects.equal(s1, s2)) { common = common.append(new Path(s1)); } else { break; } } current = common; } } } if (current == null) { current = Path.ROOT; } return current.toString(); } static class Tab extends AbstractWorkspaceTab { public Tab(IModel<String> title, IModel<Workspace> workspaceModel) { super(title, workspaceModel, 50); } @Override public Panel newPanel(String panelId, IModel<Workspace> workspaceModel) { return new ManagePrototypesPanel(panelId, workspaceModel); } @Override public boolean isVisible() { final Action action = new AccessPrototypePluginAction(getWorkspaceModel().getObject()); return Brix.get().getAuthorizationStrategy().isActionAuthorized(action); } } }