| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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.apache.cocoon.portal.impl; |
| |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.apache.avalon.framework.activity.Disposable; |
| import org.apache.avalon.framework.component.Component; |
| import org.apache.avalon.framework.configuration.Configurable; |
| import org.apache.avalon.framework.configuration.Configuration; |
| import org.apache.avalon.framework.context.Context; |
| import org.apache.avalon.framework.context.ContextException; |
| import org.apache.avalon.framework.context.Contextualizable; |
| import org.apache.avalon.framework.logger.AbstractLogEnabled; |
| import org.apache.avalon.framework.service.ServiceException; |
| import org.apache.avalon.framework.service.ServiceManager; |
| import org.apache.avalon.framework.service.Serviceable; |
| import org.apache.avalon.framework.thread.ThreadSafe; |
| import org.apache.cocoon.components.ContextHelper; |
| import org.apache.cocoon.environment.ObjectModelHelper; |
| import org.apache.cocoon.environment.Request; |
| import org.apache.cocoon.portal.PortalService; |
| import org.apache.cocoon.portal.event.impl.ChangeAspectDataEvent; |
| import org.apache.cocoon.portal.layout.CompositeLayout; |
| import org.apache.cocoon.portal.layout.Item; |
| import org.apache.cocoon.portal.layout.Layout; |
| import org.apache.cocoon.portal.layout.NamedItem; |
| |
| /** |
| * Manages the various activities required for page labels. |
| * |
| * The name of the request parameter used to identify the page labelmay be configured |
| * here by declaring |
| * <br><parameter-name><i>request-parm-name</i></parameter-name><br> |
| * in the configuration for this component. The default request parameter name is |
| * 'pageLabel'. |
| * @author Ralph Goers |
| * |
| * @version CVS $Id$ |
| */ |
| public class PageLabelManager |
| extends AbstractLogEnabled |
| implements ThreadSafe, Serviceable, Configurable, Contextualizable, Component, Disposable { |
| |
| public static final String ROLE = PageLabelManager.class.getName(); |
| |
| /** The service manager */ |
| protected ServiceManager manager; |
| /** The portal service */ |
| protected PortalService portalService; |
| /** The cocoon context */ |
| protected Context context; |
| protected String aspectName = null; |
| private String requestParameterName; |
| |
| /** boolean to determine if page label should use directory structure */ |
| private boolean useUrlPath; |
| private boolean nonStickyTabs; |
| private boolean marshallEvents; |
| |
| protected static final String LABEL_ARRAY = PageLabelManager.class.getName() + "A"; |
| protected static final String LABEL_MAP = "page-labels"; |
| protected static final String EVENT_MAP = PageLabelManager.class.getName() + "E"; |
| private static final String DEFAULT_REQUEST_PARAMETER_NAME = "pageLabel"; |
| |
| /** |
| * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager) |
| */ |
| public void service(ServiceManager manager) throws ServiceException { |
| this.manager = manager; |
| this.portalService = (PortalService) this.manager.lookup(PortalService.ROLE); |
| } |
| |
| /** |
| * @see org.apache.avalon.framework.activity.Disposable#dispose() |
| */ |
| public void dispose() { |
| if (this.manager != null) { |
| this.manager.release(this.portalService); |
| this.manager = null; |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see org.apache.avalon.framework.configuration.Configurable#configure(org.apache.avalon.framework.configuration.Configuration) |
| */ |
| public void configure(Configuration config) { |
| this.requestParameterName = |
| config.getChild("parameterName").getValue(DEFAULT_REQUEST_PARAMETER_NAME); |
| this.aspectName = config.getChild("aspectName").getValue("tab"); |
| this.nonStickyTabs = |
| Boolean.valueOf(config.getChild("nonStickyTabs").getValue("false")).booleanValue(); |
| this.marshallEvents = |
| Boolean.valueOf(config.getChild("marshallEvents").getValue("false")).booleanValue(); |
| this.useUrlPath = |
| Boolean.valueOf(config.getChild("urlPath").getValue("false")).booleanValue(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.apache.avalon.framework.context.Contextualizable#contextualize(org.apache.avalon.framework.context.Context) |
| */ |
| public void contextualize(Context context) throws ContextException { |
| this.context = context; |
| } |
| |
| /** |
| * Return the current page label. |
| * @return The current page label. |
| */ |
| public String getCurrentLabel() { |
| String[] labels = getLabels(); |
| |
| return labels[0]; |
| } |
| |
| /** |
| * Return the page label from the previous request. |
| * @return The previous page label. |
| */ |
| public String getPreviousLabel() { |
| String[] labels = getLabels(); |
| |
| return labels[1]; |
| } |
| |
| /** |
| * Sets the current page label. |
| * @return The current page label. |
| */ |
| public String setCurrentLabel() { |
| final Request request = |
| ObjectModelHelper.getRequest(ContextHelper.getObjectModel(this.context)); |
| String value; |
| if (this.useUrlPath) { |
| value = request.getSitemapURI(); |
| if (!isLabel(value)) { |
| value = null; |
| } |
| } else { |
| value = request.getParameter(this.requestParameterName); |
| } |
| |
| String[] labels = getLabels(); |
| |
| if (value != null) { |
| labels[1] = labels[0]; |
| labels[0] = value; |
| } |
| return labels[0]; |
| } |
| |
| /** |
| * Returns whether directory structure should be used |
| * @return A boolean specifying if directory structure should be used. |
| */ |
| public boolean isUrlPath() { |
| return this.useUrlPath; |
| } |
| |
| /** |
| * Returns the request parameter being used to identify the page label. |
| * @return A String containing the request parameter name used for page labels. |
| */ |
| public String getRequestParameterName() { |
| return this.requestParameterName; |
| } |
| |
| /** |
| * Return the Map that contains events for all the page labels. |
| * @return The Map to use for converting events to and from urls. |
| */ |
| public Map getPageEventMap() { |
| Map map = (Map) portalService.getAttribute(EVENT_MAP); |
| if (null == map) { |
| map = new HashMap(); |
| portalService.setAttribute(EVENT_MAP, map); |
| } |
| |
| return map; |
| } |
| |
| protected Map getLabelMap() { |
| final Layout rootLayout = portalService.getComponentManager().getProfileManager().getPortalLayout(null, null); |
| Map map = (Map) rootLayout.getAspectData(LABEL_MAP); |
| if (null == map) { |
| map = this.initializeLabels(); |
| rootLayout.setAspectData(LABEL_MAP, map); |
| } |
| return map; |
| } |
| |
| /** |
| * Retrieve the events associated with the specified page label. |
| * |
| * @param pageLabel The label to retrieve the events for. |
| * @return A List containing all the events associated with the page label in the order they |
| * should occur. |
| */ |
| public List getPageLabelEvents(String pageLabel) { |
| final Map labelMap = this.getLabelMap(); |
| List list = (List) labelMap.get(pageLabel); |
| |
| if (list == null) { |
| list = new ArrayList(); |
| labelMap.put(pageLabel, list); |
| } |
| |
| return list; |
| } |
| |
| public boolean isLabel(String pageLabel) { |
| final Map labelMap = this.getLabelMap(); |
| |
| return labelMap.containsKey(pageLabel); |
| } |
| |
| /** |
| * Returns true if events are not to be exposed as request parameters |
| */ |
| public boolean isMarshallEvents() { |
| return this.marshallEvents; |
| } |
| |
| /** |
| * Return the array containing the current and previous labels. |
| */ |
| private String[] getLabels() { |
| String[] labels = (String[]) portalService.getAttribute(LABEL_ARRAY); |
| if (null == labels) { |
| labels = new String[2]; |
| labels[0] = getRoot(); |
| portalService.setAttribute(LABEL_ARRAY, labels); |
| } |
| return labels; |
| } |
| |
| /** |
| * Create the page label event map and return it. |
| * |
| * @param service The portal service |
| * @return The page label map. |
| */ |
| private Map initializeLabels() { |
| final Map map = new HashMap(); |
| |
| final Layout portalLayout = |
| portalService.getComponentManager().getProfileManager().getPortalLayout(null, null); |
| |
| if (portalLayout instanceof CompositeLayout) { |
| this.populate((CompositeLayout) portalLayout, map, "", new ArrayList()); |
| } |
| |
| return map; |
| } |
| |
| private String getRoot() { |
| final Layout portalLayout = |
| portalService.getComponentManager().getProfileManager().getPortalLayout(null, null); |
| |
| if (portalLayout instanceof CompositeLayout) { |
| return getRoot((CompositeLayout)portalLayout, new StringBuffer("")); |
| } |
| return ""; |
| } |
| |
| private String getRoot(CompositeLayout layout, StringBuffer root) { |
| for (int j=0; j < layout.getSize(); j++) { |
| Item tab = layout.getItem(j); |
| if (tab instanceof NamedItem) { |
| if (root.length() > 0) { |
| root.append("."); |
| } |
| root.append(((NamedItem)tab).getName()); |
| Layout child = tab.getLayout(); |
| if (child != null && child instanceof CompositeLayout) { |
| getRoot((CompositeLayout)child, root); |
| } |
| break; |
| } |
| } |
| return root.toString(); |
| } |
| |
| |
| /** |
| * Populate the event map |
| * |
| * @param layout |
| * @param map |
| * @param name |
| * @param parentEvents |
| */ |
| private List populate(CompositeLayout layout, Map map, String name, List parentEvents) { |
| List lhList = null; |
| for (int j = 0; j < layout.getSize(); j++) { |
| Item tab = layout.getItem(j); |
| ChangeAspectDataEvent event = |
| new ChangeAspectDataEvent(layout, this.aspectName, new Integer(j)); |
| StringBuffer label = new StringBuffer(name); |
| if (label.length() > 0) { |
| label.append("."); |
| } |
| label.append((tab instanceof NamedItem) ? ((NamedItem) tab).getName() : |
| Integer.toString(j)); |
| List events = new ArrayList(parentEvents); |
| events.add(event); |
| Layout child = tab.getLayout(); |
| List allEvents = null; |
| if (child != null && child instanceof CompositeLayout) { |
| allEvents = populate((CompositeLayout) child, map, label.toString(), events); |
| } |
| if (this.nonStickyTabs) { |
| // With non-sticky tabs the non-leaf nodes always display |
| // the left-most child tabs |
| if (lhList == null) { |
| if (allEvents != null) { |
| lhList = allEvents; |
| } else { |
| lhList = events; |
| } |
| } |
| if (allEvents != null) { |
| map.put(label.toString(), allEvents); |
| } else { |
| map.put(label.toString(), events); |
| } |
| } else { |
| map.put(label.toString(), events); |
| } |
| } |
| return lhList; |
| } |
| } |