. Dashboards impl checkpoint

- configurable JSP layouts
  - configurable "dashlets" (JSP snipets)
  - page config (de)serialisation per user

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@3346 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Kevin Roast
2006-07-18 17:35:11 +00:00
parent 2c74374ce2
commit 02790a7b4a
2 changed files with 675 additions and 0 deletions

View File

@@ -0,0 +1,392 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* 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.alfresco.web.bean.dashboard;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import javax.faces.context.FacesContext;
import org.alfresco.config.ConfigService;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.repository.PreferencesService;
import org.alfresco.web.config.DashboardsConfigElement;
import org.alfresco.web.config.DashboardsConfigElement.DashletDefinition;
import org.alfresco.web.config.DashboardsConfigElement.LayoutDefinition;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Bean that manages the Dashboard framework.
*
* @author Kevin Roast
*/
public final class DashboardManager
{
private static Log logger = LogFactory.getLog(DashboardManager.class);
private static final String PREF_DASHBOARD = "dashboard";
private static final String LAYOUT_DEFAULT = "default";
private static final String DASHLET_DEFAULT = "getting-started";
private static final String JSP_DUMMY = "/jsp/dashboards/dummy.jsp";
private PageConfig pageConfig = null;
private DashletRenderingList renderingList = null;
private DashletTitleList titleList = null;
/**
* @return The layout JSP page for the current My Alfresco dashboard page
*/
public String getLayoutPage()
{
String layout = null;
Page page = getPageConfig().getCurrentPage();
if (page != null)
{
layout = page.getLayoutDefinition().JSPPage;
}
return layout;
}
/**
* Helper to init the dashboard for display
*/
public void initDashboard()
{
this.renderingList = null;
}
/**
* @return JSF List getter to return which dashlets are available for rendering
*/
public List getDashletAvailable()
{
if (this.renderingList == null)
{
this.renderingList = new DashletRenderingList(getPageConfig());
}
return this.renderingList;
}
/**
* @return JSF List getter to return dashlet title strings
*/
public List getDashletTitle()
{
if (this.titleList == null)
{
this.titleList = new DashletTitleList(getPageConfig());
}
return this.titleList;
}
/**
* Return the JSP for the specified dashlet index
*
* @param index Zero based index from the left most column working top-bottom then left-right
*
* @return JSP page for the dashlet or a blank dummy page if not found
*/
public String getDashletPage(int index)
{
String page = JSP_DUMMY;
DashletDefinition def = getDashletDefinitionByIndex(getPageConfig(), index);
if (def != null)
{
page = def.JSPPage;
}
return page;
}
/**
* Helper to get the DashDefinition as the zero based index, working from the left most column
* top-bottom then working left-right.
*
* @param index Zero based index from the left most column working top-bottom then left-right
*
* @return DashletDefinition if found or null if no dashlet at the specified index
*/
private static DashletDefinition getDashletDefinitionByIndex(PageConfig config, int index)
{
DashletDefinition def = null;
LayoutDefinition layoutDef = config.getCurrentPage().getLayoutDefinition();
List<Column> columns = config.getCurrentPage().getColumns();
int columnCount = columns.size();
int selectedColumn = index / layoutDef.ColumnLength;
if (selectedColumn < columnCount)
{
List<DashletDefinition> dashlets = columns.get(selectedColumn).getDashlets();
if (index % layoutDef.ColumnLength < dashlets.size())
{
def = dashlets.get(index % layoutDef.ColumnLength);
}
}
if (logger.isDebugEnabled())
logger.debug("Searching for dashlet at index: " + index +
" and found " + (def != null ? def.JSPPage : null));
return def;
}
/**
* @return the PageConfig for the current My Alfresco dashboard page
*/
private PageConfig getPageConfig()
{
if (this.pageConfig == null)
{
PageConfig pageConfig;
DashboardsConfigElement config = getDashboardConfig();
// read the config for this user from the Preferences
String xml = (String)PreferencesService.getPreferences().getValue(PREF_DASHBOARD);
if (xml != null && xml.length() != 0)
{
if (logger.isDebugEnabled())
logger.debug("PageConfig found: " + xml);
// process the XML config and convert into a PageConfig object
pageConfig = new PageConfig();
pageConfig.fromXML(config, xml);
}
else
{
if (logger.isDebugEnabled())
logger.debug("No PageConfig found, creating default instance.");
// create default config for the first access for a user
pageConfig = new PageConfig();
LayoutDefinition layout = config.getLayoutDefinition(LAYOUT_DEFAULT);
if (layout != null)
{
Page page = new Page("default", layout);
Column defaultColumn = new Column();
DashletDefinition dashlet = config.getDashletDefinition(DASHLET_DEFAULT);
if (dashlet != null)
{
defaultColumn.addDashlet(dashlet);
page.addColumn(defaultColumn);
pageConfig.addPage(page);
}
}
// persist the config for this user
//PreferencesService.getPreferences().setValue(PREF_DASHBOARD, pageConfig.toXML());
}
this.pageConfig = pageConfig;
}
return this.pageConfig;
}
/**
* @return The externally configured WebClient config element for the Dashboards
*/
private static DashboardsConfigElement getDashboardConfig()
{
ConfigService service = Application.getConfigService(FacesContext.getCurrentInstance());
DashboardsConfigElement config = (DashboardsConfigElement)service.getConfig("Dashboards").getConfigElement(
DashboardsConfigElement.CONFIG_ELEMENT_ID);
return config;
}
/**
* Dashlet rendering list.
*
* Returns true from the get() method if the specified dashlet is available for rendering.
*/
private static class DashletRenderingList extends JSFHelperList
{
PageConfig config;
public DashletRenderingList(PageConfig config)
{
this.config = config;
}
/**
* @see java.util.List#get(int)
*/
public Object get(int index)
{
return getDashletDefinitionByIndex(config, index) != null;
}
}
/**
* Dashlet title list.
*
* Returns the title string from the get() method if the specified dashlet is available.
*/
private static class DashletTitleList extends JSFHelperList
{
PageConfig config;
public DashletTitleList(PageConfig config)
{
this.config = config;
}
/**
* @see java.util.List#get(int)
*/
public Object get(int index)
{
String result = "";
DashletDefinition def = getDashletDefinitionByIndex(config, index);
if (def != null)
{
if (def.LabelId != null)
{
result = Application.getMessage(FacesContext.getCurrentInstance(), def.LabelId);
}
else if (def.Label != null)
{
result = def.Label;
}
}
return result;
}
}
/**
* Helper class that implements a dummy List contract for use by JSF List getter methods
*/
private static abstract class JSFHelperList implements List
{
//
// Satisfy List interface contract
//
public void add(int arg0, Object arg1)
{
}
public boolean add(Object arg0)
{
return false;
}
public boolean addAll(Collection arg0)
{
return false;
}
public boolean addAll(int arg0, Collection arg1)
{
return false;
}
public void clear()
{
}
public boolean contains(Object arg0)
{
return false;
}
public boolean containsAll(Collection arg0)
{
return false;
}
public int indexOf(Object arg0)
{
return 0;
}
public boolean isEmpty()
{
return false;
}
public Iterator iterator()
{
return null;
}
public int lastIndexOf(Object arg0)
{
return 0;
}
public ListIterator listIterator()
{
return null;
}
public ListIterator listIterator(int arg0)
{
return null;
}
public Object remove(int arg0)
{
return null;
}
public boolean remove(Object arg0)
{
return false;
}
public boolean removeAll(Collection arg0)
{
return false;
}
public boolean retainAll(Collection arg0)
{
return false;
}
public Object set(int arg0, Object arg1)
{
return null;
}
public int size()
{
return 0;
}
public List subList(int arg0, int arg1)
{
return null;
}
public Object[] toArray()
{
return null;
}
public Object[] toArray(Object[] arg0)
{
return null;
}
}
}

View File

@@ -0,0 +1,283 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* 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.alfresco.web.bean.dashboard;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.web.config.DashboardsConfigElement;
import org.alfresco.web.config.DashboardsConfigElement.DashletDefinition;
import org.alfresco.web.config.DashboardsConfigElement.LayoutDefinition;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
/**
* Describes the config for the Pages in a user Dashboard.
* Multiple Pages are supported.
*
* @author Kevin Roast
*/
final class PageConfig
{
private static Log logger = LogFactory.getLog(DashboardManager.class);
private static final String ELEMENT_DASHBOARD = "dashboard";
private static final String ELEMENT_PAGE = "page";
private static final String ELEMENT_COLUMN = "column";
private static final String ELEMENT_DASHLET = "dashlet";
private static final String ATTR_ID = "id";
private static final String ATTR_LAYOUTID = "layout-id";
private static final String ATTR_REFID = "idref";
private List<Page> pages = new ArrayList<Page>(4);
private int currentPageIndex = 0;
public Page getCurrentPage()
{
if (currentPageIndex < pages.size())
{
return pages.get(currentPageIndex);
}
else
{
return null;
}
}
public void addPage(Page page)
{
pages.add(page);
}
public Page getPage(String pageId)
{
Page foundPage = null;
for (Page page : pages)
{
if (page.getId().equals(pageId))
{
foundPage = page;
break;
}
}
return foundPage;
}
/**
* Convert this config to an XML definition which can be serialized.
* Example:
* <code>
* <?xml version="1.0"?>
* <dashboard>
* <page id="main" layout-id="narrow-left-2column">
* <column>
* <dashlet idref="clock" />
* <dashlet idref="random-joke" />
* </column>
* <column>
* <dashlet idref="getting-started" />
* <dashlet idref="task-list" />
* <dashlet idref="my-checkedout-docs" />
* <dashlet idref="my-documents" />
* </column>
* </page>
* </dashboard>
* </code>
*
* @return XML for this config
*/
public String toXML()
{
try
{
Document doc = DocumentHelper.createDocument();
Element root = doc.addElement(ELEMENT_DASHBOARD);
for (Page page : pages)
{
Element pageElement = root.addElement(ELEMENT_PAGE);
pageElement.addAttribute(ATTR_ID, page.getId());
pageElement.addAttribute(ATTR_LAYOUTID, page.getLayoutDefinition().Id);
for (Column column : page.getColumns())
{
Element columnElement = pageElement.addElement(ELEMENT_COLUMN);
for (DashletDefinition dashletDef : column.getDashlets())
{
columnElement.addElement(ELEMENT_DASHLET).addAttribute(ATTR_REFID, dashletDef.Id);
}
}
}
StringWriter out = new StringWriter(512);
XMLWriter writer = new XMLWriter(OutputFormat.createPrettyPrint());
writer.setWriter(out);
writer.write(doc);
return out.toString();
}
catch (Throwable err)
{
throw new AlfrescoRuntimeException("Unable to serialize Dashboard PageConfig to XML: " + err.getMessage(), err);
}
}
@Override
public String toString()
{
return toXML();
}
/**
* Deserialise this PageConfig instance from the specified XML stream.
*
* @param xml
*/
public void fromXML(DashboardsConfigElement config, String xml)
{
try
{
SAXReader reader = new SAXReader();
Document document = reader.read(new StringReader(xml));
Element rootElement = document.getRootElement();
// walk the pages found in xml
Iterator itrPages = rootElement.elementIterator(ELEMENT_PAGE);
while (itrPages.hasNext())
{
Element pageElement = (Element)itrPages.next();
String layoutId = pageElement.attributeValue(ATTR_LAYOUTID);
LayoutDefinition layoutDef = config.getLayoutDefinition(layoutId);
if (layoutDef != null)
{
// found the layout now build the page and read the columns
Page page = new Page(pageElement.attributeValue(ATTR_ID), layoutDef);
Iterator itrColumns = pageElement.elementIterator(ELEMENT_COLUMN);
while (itrColumns.hasNext())
{
Column column = new Column();
// read and resolve the dashlet definitions for this column
Element columnElement = (Element)itrColumns.next();
Iterator itrDashlets = columnElement.elementIterator(ELEMENT_DASHLET);
while (itrDashlets.hasNext())
{
String dashletId = ((Element)itrDashlets.next()).attributeValue(ATTR_REFID);
DashletDefinition dashletDef = config.getDashletDefinition(dashletId);
if (dashletDef != null)
{
column.addDashlet(dashletDef);
}
else if (logger.isWarnEnabled())
{
logger.warn("Failed to resolve Dashboard Dashlet Definition ID: " + dashletId);
}
}
// add the column of dashlets to the page
page.addColumn(column);
}
// add the page to this config instance
this.addPage(page);
}
else if (logger.isWarnEnabled())
{
logger.warn("Failed to resolve Dashboard Layout Definition ID: " + layoutId);
}
}
}
catch (DocumentException docErr)
{
// if we cannot parse, then we simply revert to default
}
}
}
/**
* Simple class to represent a Page in a Dashboard.
* Each Page has a Layout associated with it, and a number of Column definitions.
*/
final class Page
{
private String id;
private LayoutDefinition layoutDef;
private List<Column> columns = new ArrayList<Column>(4);
public Page(String id, LayoutDefinition layout)
{
if (id == null || id.length() == 0)
{
throw new IllegalArgumentException("ID for a Dashboard Page is mandatory.");
}
if (layout == null)
{
throw new IllegalArgumentException("Layout for a Dashboard Page is mandatory.");
}
this.id = id;
this.layoutDef = layout;
}
public String getId()
{
return this.id;
}
public LayoutDefinition getLayoutDefinition()
{
return this.layoutDef;
}
public void addColumn(Column column)
{
this.columns.add(column);
}
public List<Column> getColumns()
{
return this.columns;
}
}
/**
* Simple class representing a single Column in a dashboard Page.
* Each column contains a list of Dashlet definitions.
*/
final class Column
{
private List<DashletDefinition> dashlets = new ArrayList<DashletDefinition>(4);
public void addDashlet(DashletDefinition dashlet)
{
dashlets.add(dashlet);
}
public List<DashletDefinition> getDashlets()
{
return this.dashlets;
}
}