From: <mb...@re...> - 2005-02-07 22:46:18
|
Author: mbooth Date: 2005-02-07 23:45:34 +0100 (Mon, 07 Feb 2005) New Revision: 201 Added: ccm-ldn-portal/trunk/pdl/com/arsdigita/london/portal/Portal.ora.pdl ccm-ldn-portal/trunk/pdl/com/arsdigita/london/portal/Portal.pg.pdl ccm-ldn-portal/trunk/src/com/arsdigita/london/portal/StatefulPersistentPortal.java ccm-ldn-portal/trunk/src/com/arsdigita/london/portal/StatefulPersistentPortalModelBuilder.java ccm-ldn-portal/trunk/src/com/arsdigita/london/portal/StatefulPortlet.java ccm-ldn-portal/trunk/src/com/arsdigita/london/portal/StatefulPortletRenderer.java Modified: ccm-ldn-portal/trunk/src/com/arsdigita/london/portal/ui/PersistentPortal.java Log: Add support for stateful portlets from west sussex Added: ccm-ldn-portal/trunk/pdl/com/arsdigita/london/portal/Portal.ora.pdl =================================================================== --- ccm-ldn-portal/trunk/pdl/com/arsdigita/london/portal/Portal.ora.pdl 2005-02-04 23:24:20 UTC (rev 200) +++ ccm-ldn-portal/trunk/pdl/com/arsdigita/london/portal/Portal.ora.pdl 2005-02-07 22:45:34 UTC (rev 201) @@ -0,0 +1,19 @@ +model com.arsdigita.london.portal; + +query MaxPortletInstances { + Integer maxCount; + do { + select nvl(max(count (*)), 0) count + from applications a, + portlets b + where a.application_type_id = :portletType + and b.portlet_id = a.application_id + group by b.portal_id + + } map { + maxCount = count; + } +} + + + Added: ccm-ldn-portal/trunk/pdl/com/arsdigita/london/portal/Portal.pg.pdl =================================================================== --- ccm-ldn-portal/trunk/pdl/com/arsdigita/london/portal/Portal.pg.pdl 2005-02-04 23:24:20 UTC (rev 200) +++ ccm-ldn-portal/trunk/pdl/com/arsdigita/london/portal/Portal.pg.pdl 2005-02-07 22:45:34 UTC (rev 201) @@ -0,0 +1,19 @@ +model com.arsdigita.london.portal; + +query MaxPortletInstances { + Integer maxCount; + do { + select coalesce(max(count (*)), 0) count + from applications a, + portlets b + where a.application_type_id = :portletType + and b.portlet_id = a.application_id + group by b.portal_id + + } map { + maxCount = count; + } +} + + + Added: ccm-ldn-portal/trunk/src/com/arsdigita/london/portal/StatefulPersistentPortal.java =================================================================== --- ccm-ldn-portal/trunk/src/com/arsdigita/london/portal/StatefulPersistentPortal.java 2005-02-04 23:24:20 UTC (rev 200) +++ ccm-ldn-portal/trunk/src/com/arsdigita/london/portal/StatefulPersistentPortal.java 2005-02-07 22:45:34 UTC (rev 201) @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2001 ArsDigita Corporation. All Rights Reserved. + * + * The contents of this file are subject to the ArsDigita Public + * License (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.arsdigita.com/ADPL.txt + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + */ + +package com.arsdigita.london.portal; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.apache.log4j.Logger; + +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.ParameterSingleSelectionModel; +import com.arsdigita.bebop.SimpleContainer; +import com.arsdigita.bebop.SingleSelectionModel; +import com.arsdigita.bebop.parameters.IntegerParameter; +import com.arsdigita.bebop.portal.Portal; +import com.arsdigita.london.portal.ui.PortalSelectionModel; +import com.arsdigita.london.portal.ui.PortletSelectionModel; +import com.arsdigita.london.portal.ui.PortletTypeSelectionModel; +import com.arsdigita.london.portal.ui.WorkspaceSelectionModel; +import com.arsdigita.persistence.DataQuery; +import com.arsdigita.persistence.SessionManager; +import com.arsdigita.persistence.metadata.ObjectType; +import com.arsdigita.portal.Portlet; +import com.arsdigita.portal.PortletType; +import com.arsdigita.portal.PortletTypeCollection; +import com.arsdigita.xml.Element; + +public class StatefulPersistentPortal extends SimpleContainer { + + private static final Logger s_log = + Logger.getLogger(StatefulPersistentPortal.class); + + private WorkspaceSelectionModel m_workspace; + private PortalSelectionModel m_portal; + private PortletTypeSelectionModel m_portletType; + private PortletSelectionModel m_portlet; + + // static to enable access from Page and PersistantPortal, and also, page is dirty if any instance of Portal exceeds + // current max number of stateful portlets + //public static boolean pageDirty = false; + + + private int m_columns; + // make life easier - if no state allowed in edit mode then this class can get rid of all the editor/adder stuff + // need to make sure that default state of stateful portlets is reasonable + // added cg + + /** + * maps portlet type to list of empty renderers + */ + private HashMap m_stateful; + /** + * static map of portlet types to the number of renderers that is contained by any Portal + */ + public static HashMap portletTypeCount; + private Portal m_portalDisplay; + + private SingleSelectionModel m_column; + + public StatefulPersistentPortal(PortalSelectionModel portal) { + this(portal, "portal", 1); + } + + public StatefulPersistentPortal( + PortalSelectionModel portal, + int ncolumns) { + this(portal, "portal", ncolumns); + } + + public StatefulPersistentPortal(PortalSelectionModel portal, String name) { + this(portal, name, 1); + } + + public StatefulPersistentPortal( + PortalSelectionModel portal, + String name, + int columns) { + s_log.debug("IN constructor" + name + " " + columns); + m_portal = portal; + + m_column = + new ParameterSingleSelectionModel(new IntegerParameter("column")); + + // retrieve empty renderers for any stateful portlets and add them to the component hierarchy + + PortletTypeCollection types = PortletType.retrieveAllPortletTypes(); + m_stateful = new HashMap(); + // refresh the type counts if we are recreating the page + portletTypeCount = new HashMap(); + + while (types.next()) { + + PortletType type = types.getPortletType(); + s_log.debug("checking portlet type " + type.getDescription()); + Portlet portlet = Portlet.createPortlet(type, null); + if (portlet instanceof StatefulPortlet) { + StatefulPortlet statefulPortlet = (StatefulPortlet) portlet; + DataQuery findMaxInstances = SessionManager.getSession().retrieveQuery("com.arsdigita.london.portal.MaxPortletInstances"); + findMaxInstances.setParameter("portletType", type.getID()); + int requiredRenderers = 0; + while (findMaxInstances.next()){ + requiredRenderers = ((Integer)findMaxInstances.get("maxCount")).intValue(); + } + s_log.debug("stateful portlet - I am going to instantiate " + requiredRenderers + " renderers"); + List renderers = new ArrayList(); + for (int i = 0; i < requiredRenderers; i++) { + StatefulPortletRenderer renderer = + (StatefulPortletRenderer) statefulPortlet + .getEmptyPortletRenderer(); + renderers.add(renderer); + + // and add it to the page + add(renderer); + s_log.debug("renderer added to page"); + } + + portletTypeCount.put(type.getResourceObjectType(), new Integer(requiredRenderers)); + m_stateful.put(type.getResourceObjectType(), renderers); + + } + } + m_portalDisplay = + new Portal( + new StatefulPersistentPortalModelBuilder(portal, m_stateful)); + + add(m_portalDisplay); + + } + + /*public void register(Page page) { + super.register(page); + + if (m_portlet != null) { + page.addComponentStateParam(this, m_portlet.getStateParameter()); + } + if (m_portletType != null) { + page.addComponentStateParam( + this, + m_portletType.getStateParameter()); + } + + page.addComponentStateParam(this, m_column.getStateParameter()); + } + */ + public void generateXML(PageState state, Element parent) { + // generateXML overridden to prevent generateXML being invoked + // on renderers that are only added to the component model here + // so that they are registered on the page + s_log.debug("start - generateXML"); + m_portalDisplay.generateXML(state, parent); + s_log.debug("FINISH - generateXML"); + } + + public static Integer getCurrentPortletRendererInstances (String portletType) { + + + return (Integer) portletTypeCount + .get(portletType); + } + +} Added: ccm-ldn-portal/trunk/src/com/arsdigita/london/portal/StatefulPersistentPortalModelBuilder.java =================================================================== --- ccm-ldn-portal/trunk/src/com/arsdigita/london/portal/StatefulPersistentPortalModelBuilder.java 2005-02-04 23:24:20 UTC (rev 200) +++ ccm-ldn-portal/trunk/src/com/arsdigita/london/portal/StatefulPersistentPortalModelBuilder.java 2005-02-07 22:45:34 UTC (rev 201) @@ -0,0 +1,129 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package com.arsdigita.london.portal; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; + +import org.apache.log4j.Logger; + +import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.portal.PortalModel; +import com.arsdigita.bebop.portal.PortalModelBuilder; +import com.arsdigita.bebop.portal.PortletRenderer; +import com.arsdigita.london.portal.ui.PortalSelectionModel; +import com.arsdigita.london.portal.ui.SimplePortlet; +import com.arsdigita.portal.Portal; +import com.arsdigita.portal.PortletCollection; +import com.arsdigita.util.LockableImpl; + +/** + * @author cgyg9330 + * + * portal model builder that should only be applied to portal in browse mode, as it does not allow for editing. + * portal in browse mode should have a com.arsdigita.london.portal.ui.PersistentPortalModelBuilder. + * + * For stateless portlets, this builder creates a renderer with a reference to its portlet data object. For stateful portlets + * the builder retrieves one of the empty renderers registered to the page and puts the portlet data object in + * a requestlocal. + */ +public class StatefulPersistentPortalModelBuilder + extends LockableImpl + implements PortalModelBuilder { + + private Logger s_log = Logger.getLogger(StatefulPersistentPortalModelBuilder.class); + + /** + * hashmap that maps portlet types to a list of empty renderers that have been registered on the page + */ + private HashMap statefulCollections; + private PortalSelectionModel portalModel; + + public StatefulPersistentPortalModelBuilder( + PortalSelectionModel portal, + HashMap stateful) { + this.portalModel = portal; + this.statefulCollections = stateful; + + } + + public PortalModel buildModel(PageState state) { + // aim of this method is to get hold of a list of renderers for this particular portal + // and use them to make a PortalModel + s_log.debug("START - buildModel"); + List portletRenderers = new ArrayList(); + + HashMap statefulIterators = new HashMap(); + + + // get iterators for all the renderer lists (this means that each instance of the portlet has it's own renderer) + // getting iterators in the buildmodel method means that each time model is built, we start at the beginning of the list + Iterator it = statefulCollections.keySet().iterator(); + while (it.hasNext()) { + String resourceType = (String)it.next(); + Iterator renderersIterator = ((List)statefulCollections.get(resourceType)).iterator(); + statefulIterators.put(resourceType, renderersIterator); + } + Portal portal = portalModel.getSelectedPortal(state); + PortletCollection portlets = portal.getPortlets(); + while (portlets.next()) { + com.arsdigita.portal.Portlet portlet = portlets.getPortlet(); + s_log.debug("portlet " + portlet.getPortletType().getDescription() + " " + portlet.getTitle()); + if (portlet instanceof StatefulPortlet) { + StatefulPortletRenderer statefulRenderer = (StatefulPortletRenderer)((Iterator) statefulIterators.get( + portlet.getPortletType().getResourceObjectType())).next(); + + statefulRenderer.setPortlet(portlet, state); + portletRenderers.add(statefulRenderer); + s_log.debug("stateful renderer added to model"); + } else { + PortletRenderer renderer = portlet.getPortletRenderer(); + portletRenderers.add(renderer); + s_log.debug("stateless renderer added to model"); + } + + + + } + s_log.debug("FINISH - buildModel " + portal.getTitle()); + return new StatefulPersistentPortalModel( + portletRenderers.iterator(), + portal.getTitle()); + + } + private class StatefulPersistentPortalModel implements PortalModel { + + private Iterator portlets; + private String title; + + public StatefulPersistentPortalModel(Iterator portlets, String title) { + this.portlets = portlets; + this.title = title; + } + + public Iterator getPortletRenderers() { + return portlets; + } + + public String getTitle() { + return title; + } + } +} Added: ccm-ldn-portal/trunk/src/com/arsdigita/london/portal/StatefulPortlet.java =================================================================== --- ccm-ldn-portal/trunk/src/com/arsdigita/london/portal/StatefulPortlet.java 2005-02-04 23:24:20 UTC (rev 200) +++ ccm-ldn-portal/trunk/src/com/arsdigita/london/portal/StatefulPortlet.java 2005-02-07 22:45:34 UTC (rev 201) @@ -0,0 +1,58 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package com.arsdigita.london.portal; + +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.portal.AbstractPortletRenderer; +import com.arsdigita.london.portal.ui.PortalConstants; +import com.arsdigita.persistence.DataObject; +import com.arsdigita.portal.Portlet; +import com.arsdigita.xml.Element; + +/** + * @author cgyg9330 + * + * In order to register stateful components with the page, this class provides a method declaration + * for retreiving a portletrenderer that is not tied to any particular portlet. This is neccessary + * because components need to be added to the page before the PortalModelBuilder retrieves the portlets + * for a specific portal. + */ +public abstract class StatefulPortlet extends Portlet { + + protected StatefulPortlet(DataObject dataObject) { + super(dataObject); + } + + public abstract StatefulPortletRenderer getEmptyPortletRenderer(); + + /** + * + * stateful portlets cannot be displayed when the portal is in customise mode, as + * the portletrenderer is contained within a SimplePortlet which is not stateful + * + */ + protected final AbstractPortletRenderer doGetPortletRenderer() { + return new AbstractPortletRenderer() { + protected void generateBodyXML(PageState state, Element document) { + document.newChildElement( + "portlet:stateful-portlet-in-edit", + PortalConstants.PORTLET_XML_NS); + } + }; + + } +} Added: ccm-ldn-portal/trunk/src/com/arsdigita/london/portal/StatefulPortletRenderer.java =================================================================== --- ccm-ldn-portal/trunk/src/com/arsdigita/london/portal/StatefulPortletRenderer.java 2005-02-04 23:24:20 UTC (rev 200) +++ ccm-ldn-portal/trunk/src/com/arsdigita/london/portal/StatefulPortletRenderer.java 2005-02-07 22:45:34 UTC (rev 201) @@ -0,0 +1,56 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package com.arsdigita.london.portal; + + +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.RequestLocal; +import com.arsdigita.bebop.portal.AbstractPortletRenderer; +import com.arsdigita.portal.Portlet; + +/** + * @author chris gilbert + * + * Renderer that stores reference to portlet data object in a request local. + * When the page is built, enough StatefulPortletRenderers are added to the page as might + * be needed by any one portal. Hence all portals share the same stateful portlets and so + * portlet data object cannot be stored as an instane variable. + * + * StatefulPortletModelBuilder sets value of requestlocal when the portlet model is built. + */ +public abstract class StatefulPortletRenderer extends AbstractPortletRenderer { + + /** + * holds the portlet data object for a particular request + */ + protected RequestLocal portlet = new RequestLocal(); + + + public void setPortlet(Portlet portlet, PageState state) { + setTitle(portlet.getTitle()); + setCellNumber(portlet.getCellNumber()); + setSortKey(portlet.getSortKey()); + setProfile(portlet.getProfile()); + this.portlet.set(state, portlet); + } + + + + + + +} Modified: ccm-ldn-portal/trunk/src/com/arsdigita/london/portal/ui/PersistentPortal.java =================================================================== --- ccm-ldn-portal/trunk/src/com/arsdigita/london/portal/ui/PersistentPortal.java 2005-02-04 23:24:20 UTC (rev 200) +++ ccm-ldn-portal/trunk/src/com/arsdigita/london/portal/ui/PersistentPortal.java 2005-02-07 22:45:34 UTC (rev 201) @@ -15,6 +15,11 @@ package com.arsdigita.london.portal.ui; +import com.arsdigita.london.portal.StatefulPersistentPortal; +import com.arsdigita.london.portal.StatefulPortlet; +import com.arsdigita.london.portal.Workspace; +import com.arsdigita.london.portal.WorkspacePage; + import com.arsdigita.bebop.ParameterSingleSelectionModel; import com.arsdigita.bebop.SingleSelectionModel; import com.arsdigita.bebop.FormProcessException; @@ -23,25 +28,20 @@ import com.arsdigita.bebop.Page; import com.arsdigita.bebop.Component; import com.arsdigita.bebop.RequestLocal; - import com.arsdigita.bebop.event.ChangeListener; import com.arsdigita.bebop.event.ChangeEvent; import com.arsdigita.bebop.event.FormProcessListener; import com.arsdigita.bebop.event.FormSectionEvent; import com.arsdigita.bebop.event.ActionEvent; import com.arsdigita.bebop.event.ActionListener; - +import com.arsdigita.bebop.jsp.DefinePage; import com.arsdigita.bebop.parameters.IntegerParameter; import com.arsdigita.bebop.parameters.BooleanParameter; import com.arsdigita.bebop.parameters.BigDecimalParameter; - import com.arsdigita.bebop.portal.PortletRenderer; import com.arsdigita.bebop.portal.PortalModel; import com.arsdigita.bebop.portal.PortalModelBuilder; -import com.arsdigita.london.portal.Workspace; -import com.arsdigita.london.portal.WorkspacePage; - import com.arsdigita.portal.PortletType; import com.arsdigita.portal.Portlet; import com.arsdigita.portal.PortletCollection; @@ -53,16 +53,17 @@ import com.arsdigita.kernel.ACSObject; import com.arsdigita.kernel.ui.ResourceConfigComponent; -import com.arsdigita.web.ApplicationType; - import com.arsdigita.dispatcher.AccessDeniedException; +import com.arsdigita.dispatcher.DispatcherHelper; import com.arsdigita.domain.DataObjectNotFoundException; - +import com.arsdigita.persistence.DataQuery; +import com.arsdigita.persistence.SessionManager; import com.arsdigita.util.Assert; import com.arsdigita.util.UncheckedWrapperException; +import com.arsdigita.web.ApplicationType; +import com.arsdigita.xml.Element; import com.arsdigita.london.util.ui.parameters.DomainObjectParameter; -import com.arsdigita.xml.Element; import java.math.BigDecimal; import java.lang.RuntimeException; @@ -266,6 +267,45 @@ column.intValue()); portal.save(); } + // added cg - mark page as dirty if max existing + // stateful portlet count is exceeded so page is + // rebuilt with correct number of renderers + if (resource instanceof StatefulPortlet) { + s_log.debug("Stateful portlet added"); + // check if the maximum number of stateful + // portlets has increased + PortletType portletType = + ((Portlet) resource).getPortletType(); + DataQuery findMaxInstances = + SessionManager.getSession().retrieveQuery( + "com.arsdigita.london.portal.portal.MaxPortletInstances"); + findMaxInstances.setParameter( + "portletType", + portletType.getID()); + int maxCount = 0; + while (findMaxInstances.next()) { + maxCount = + ((Integer) findMaxInstances + .get("maxCount")) + .intValue(); + } + String key = portletType.getResourceObjectType(); + + Integer previousMaxValue = StatefulPersistentPortal.getCurrentPortletRendererInstances(key); + int previousMax = previousMaxValue == null ? 0 : previousMaxValue.intValue(); + + s_log.debug( + portletType + + ": previous count = " + + previousMax + + " | new max = " + + maxCount); + if (maxCount > previousMax) { + + DefinePage.setPageAsDirty(DispatcherHelper.getCurrentResourcePath( + state.getRequest())); + } + } m_portletType.clearSelection(e.getPageState()); state.setValue(m_parentApp, null); m_parentResource.set(state, null); |