/*
* Copyright (C) 2005-2010 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco 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 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Alfresco. If not, see .
*/
package org.alfresco.web.bean.dashboard;
import java.io.Serializable;
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
*/
public final class PageConfig implements Serializable
{
private static final long serialVersionUID = 5464324390924278215L;
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 pages = new ArrayList(4);
private Page currentPage = null;
/**
* Default constructor
*/
public PageConfig()
{
}
/**
* Copy constructor
*
* @param copy PageConfig to copy
*/
public PageConfig(PageConfig copy)
{
this.pages = new ArrayList(copy.pages.size());
for (Page page : copy.pages)
{
// invoke the copy constructor on each Page
// which in turn calls the copy constructor of child classes
this.pages.add(new Page(page));
}
}
/**
* @return The current page in the config
*/
public Page getCurrentPage()
{
if (this.currentPage == null)
{
if (this.pages.size() != 0)
{
this.currentPage = pages.get(0);
}
}
return this.currentPage;
}
/**
* Set the current Page for the cnfig
*
* @param pageId ID of the page to set as current
*/
public void setCurrentPage(String pageId)
{
for (Page page : pages)
{
if (page.getId().equals(pageId))
{
this.currentPage = page;
break;
}
}
}
/**
* Add a new Page to the list
*
* @param page Page to add
*/
public void addPage(Page page)
{
pages.add(page);
}
/**
* Get a Page with the specified page Id
*
* @param pageId Of the page to return
*
* @return Page or null if not found
*/
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:
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
* @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 implements Serializable
{
private static final long serialVersionUID = 8023042580316126423L;
private String id;
private LayoutDefinition layoutDef;
private List columns = new ArrayList(4);
/**
* Constructor
*
* @param id
* @param layout
*/
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;
}
/**
* Copy Constructor
*
* @param copy Page to build a copy from
*/
public Page(Page copy)
{
this.id = copy.id;
this.layoutDef = copy.layoutDef;
for (Column column : copy.columns)
{
Column cloneColumn = new Column(column);
addColumn(cloneColumn);
}
}
public String getId()
{
return this.id;
}
public LayoutDefinition getLayoutDefinition()
{
return this.layoutDef;
}
public void setLayoutDefinition(LayoutDefinition layout)
{
if (layout == null)
{
throw new IllegalArgumentException("Layout for a Dashboard Page is mandatory.");
}
// correct column collection based on new layout definition
while (this.columns.size() < layout.Columns)
{
addColumn(new Column());
}
if (this.columns.size() > layout.Columns)
{
this.columns = this.columns.subList(0, layout.Columns);
}
this.layoutDef = layout;
}
public void addColumn(Column column)
{
this.columns.add(column);
}
public List 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 implements Serializable
{
private static final long serialVersionUID = 6462844390234508010L;
private List dashlets = new ArrayList(4);
/**
* Default constructor
*/
public Column()
{
}
/**
* Copy constructor
*
* @param copy Column to copy
*/
public Column(Column copy)
{
this.dashlets = new ArrayList(copy.dashlets.size());
this.dashlets.addAll(copy.dashlets);
}
public void addDashlet(DashletDefinition dashlet)
{
dashlets.add(dashlet);
}
public List getDashlets()
{
return this.dashlets;
}
public void trimDashlets(int max)
{
if (max >= 0)
{
int maxTrim = Math.min(this.dashlets.size(), max);
this.dashlets = this.dashlets.subList(0, maxTrim);
}
}
}