ExtraXMLGenerator für GenericOrganizationalUnit und einige Tabs für diesen.

git-svn-id: https://svn.libreccm.org/ccm/trunk@1186 8810af33-2d31-482b-a856-94f89814c4df
master
jensp 2011-10-21 18:20:36 +00:00
parent ac9142335e
commit 070b43f9fd
7 changed files with 618 additions and 1 deletions

View File

@ -21,6 +21,8 @@ package com.arsdigita.cms.contenttypes;
import com.arsdigita.cms.ContentBundle;
import com.arsdigita.cms.ContentPage;
import com.arsdigita.cms.ExtraXMLGenerator;
import com.arsdigita.cms.contenttypes.ui.GenericOrgaUnitExtraXmlGenerator;
import com.arsdigita.cms.contenttypes.ui.GenericOrganizationalUnitSubordinateOrgaUnitAddForm;
import com.arsdigita.cms.contenttypes.ui.GenericOrganizationalUnitSubordinateOrgaUnitsTable;
import com.arsdigita.cms.ui.authoring.AuthoringKitWizard;
@ -30,6 +32,7 @@ import com.arsdigita.persistence.DataObject;
import com.arsdigita.persistence.OID;
import com.arsdigita.util.Assert;
import java.math.BigDecimal;
import java.util.List;
import org.apache.log4j.Logger;
/**
@ -77,7 +80,7 @@ public class GenericOrganizationalUnit extends ContentPage {
public GenericOrganizationalUnit(final String type) {
super(type);
}
public String getAddendum() {
return (String) get(ADDENDUM);
}

View File

@ -0,0 +1,79 @@
package com.arsdigita.cms.contenttypes.ui;
import com.arsdigita.bebop.PageState;
import com.arsdigita.cms.ContentItem;
import com.arsdigita.cms.contenttypes.GenericContact;
import com.arsdigita.cms.contenttypes.GenericOrganizationalUnit;
import com.arsdigita.cms.contenttypes.GenericOrganizationalUnitContactCollection;
import com.arsdigita.cms.dispatcher.SimpleXMLGenerator;
import com.arsdigita.xml.Element;
/**
*
* @author Jens Pelzetter
* @version $Id$
*/
public class GenericOrgaUnitContactsTab implements GenericOrgaUnitTab {
@Override
public boolean hasData(final GenericOrganizationalUnit orgaunit) {
return !getData(orgaunit).isEmpty();
}
@Override
public void generateXml(final GenericOrganizationalUnit orgaunit,
final Element parent,
final PageState state) {
final GenericOrganizationalUnitContactCollection contacts = getData(orgaunit,
state);
Element contactsElem = parent.newChildElement("contacts");
while (contacts.next()) {
GenericContact contact;
contact = contacts.getContact();
generateGenericContactXML(contact,
contactsElem,
state,
Integer.toString(
contacts.getContactOrder()),
true);
}
}
protected void generateGenericContactXML(final GenericContact contact,
final Element parent,
final PageState state,
final String order,
final boolean withPerson) {
ContactXmlLGenerator generator = new ContactXmlLGenerator(contact);
generator.generateXML(state, parent, order);
}
protected GenericOrganizationalUnitContactCollection getData(
final GenericOrganizationalUnit orgaunit,
final PageState state) {
return getData(orgaunit);
}
protected GenericOrganizationalUnitContactCollection getData(
final GenericOrganizationalUnit orgaunit) {
return orgaunit.getContacts();
}
private class ContactXmlLGenerator extends SimpleXMLGenerator {
private GenericContact contact;
public ContactXmlLGenerator(final GenericContact contact) {
super();
this.contact = contact;
}
@Override
protected ContentItem getContentItem(PageState state) {
return contact;
}
}
}

View File

@ -0,0 +1,215 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.arsdigita.cms.contenttypes.ui;
import com.arsdigita.bebop.Page;
import com.arsdigita.bebop.PageState;
import com.arsdigita.cms.ContentItem;
import com.arsdigita.cms.ContentPage;
import com.arsdigita.cms.ExtraXMLGenerator;
import com.arsdigita.cms.contenttypes.GenericOrganizationalUnit;
import com.arsdigita.xml.Element;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.Map;
import org.apache.log4j.Logger;
/**
* <p>
* Base class for {@link ExtraXMLGenerator}s for sub classes of
* {@link GenericOrganizationalUnit}. The only method which has to be
* overwritten is {@link #getTabConfig()}. This method will return the tabs
* (instances of implementations of {@link GenericOrgaUnitTab}). The
* {@link #generateXML(com.arsdigita.cms.ContentItem, com.arsdigita.xml.Element, com.arsdigita.bebop.PageState)}
* method delegates the XML creation to this objects.
* </p>
* <p>
* {@link GenericOrganizationalUnit} does not include this generator.
* The subclasses of {@link GenericOrganizationalUnit} are responsible for
* integrating the subclasses of this class by overwriting the
* {@link ContentPage#getExtraXMLGenerators()}.
* </p>
*
* @author Jens Pelzetter
* @version $Id$
*/
public abstract class GenericOrgaUnitExtraXmlGenerator
implements ExtraXMLGenerator {
private final static Logger logger =
Logger.getLogger(
GenericOrgaUnitExtraXmlGenerator.class);
private final static String SELECTED_TAB_PARAM = "selectedTab";
private String showOnly;
public void generateXML(final ContentItem item,
final Element element,
final PageState state) {
final long start = System.currentTimeMillis();
if (!(item instanceof GenericOrganizationalUnit)) {
throw new IllegalArgumentException(
"This ExtraXMLGenerator supports "
+ "only instances of GenericOrganizationalUnit only.");
}
final Element orgaUnitTabsElem = element.newChildElement("orgaUnitTabs");
final Element availableTabsElem = orgaUnitTabsElem.newChildElement(
"availableTabs");
final GenericOrganizationalUnit orgaunit =
(GenericOrganizationalUnit) item;
final Map<String, GenericOrgaUnitTab> tabs =
processTabConfig(getTabConfig());
String selected = state.getRequest().getParameter(
SELECTED_TAB_PARAM);
if (showOnly != null && !showOnly.isEmpty()) {
selected = showOnly;
}
if ((selected == null) || selected.isEmpty()) {
selected = new ArrayList<String>(tabs.keySet()).get(0);
}
final long availableStart = System.currentTimeMillis();
if ((showOnly == null) || showOnly.isEmpty()) {
for (Map.Entry<String, GenericOrgaUnitTab> entry : tabs.entrySet()) {
if (entry.getValue().hasData(orgaunit)) {
createAvailableTabElem(availableTabsElem,
entry.getKey(),
selected);
}
}
}
logger.debug(String.format("Created available tabs XML for "
+ "GenericOrganizationalUnit '%s' in %d ms.",
orgaunit.getName(),
System.currentTimeMillis() - availableStart));
if (tabs.containsKey(selected) && tabs.get(selected).hasData(orgaunit)) {
final GenericOrgaUnitTab selectedTab = tabs.get(selected);
final Element selectedTabElem = orgaUnitTabsElem.newChildElement(
"selectedTab");
selectedTab.generateXml(orgaunit, selectedTabElem, state);
} else {
orgaUnitTabsElem.newChildElement("selectedTabNotAvailable");
}
logger.debug(String.format("Generated XML for GenericOrganizationalUnit "
+ "'%s' in %d ms",
orgaunit.getName(),
System.currentTimeMillis() - start));
}
/**
* Can be used from a JSP template for Navigation to show only a specific
* tab in category.
*
* @param showOnly
*/
public void setShowOnly(final String showOnly) {
this.showOnly = showOnly;
}
private void createAvailableTabElem(final Element parent,
final String key,
final String selected) {
final Element availableTabElem = parent.newChildElement("availableTab");
availableTabElem.addAttribute("label", key);
if (key.equals(selected)) {
availableTabElem.addAttribute("selected", "true");
} else {
availableTabElem.addAttribute("selected", "false");
}
}
/**
* <p>
* This method should return a string containing all tabs to use. The string
* must have to following format:
* </p>
* <p>
* <code>
* tabName:fullyQualifedClassName;...
* </code>
* </p>
* <p>
* Example:
* </p>
* <p>
* <code>
* foo:com.arsdigita.cms.contenttypes.ui.FooTab;bar:com.arsdigita.cms.contenttypes.BarTab;fooBar:com.arsdigita.cms.contenttypes.ui.FooBarTab
* </code>
* </p>
*
* @return
*/
public abstract String getTabConfig();
private Map<String, GenericOrgaUnitTab> processTabConfig(
final String tabConfig) {
final long start = System.currentTimeMillis();
final String[] tokens = tabConfig.split(";");
final Map<String, GenericOrgaUnitTab> tabs =
new LinkedHashMap<String, GenericOrgaUnitTab>();
for (String token : tokens) {
processTabConfigToken(tabs, token);
}
logger.debug(String.format("Processed tab config in %d ms",
System.currentTimeMillis() - start));
return tabs;
}
@SuppressWarnings("unchecked")
private void processTabConfigToken(
final Map<String, GenericOrgaUnitTab> tabs,
final String tabConfigToken) {
final String[] tokens = tabConfigToken.split(":");
if (tokens.length != 2) {
throw new IllegalArgumentException(String.format(
"Invalid tab configuration token. Found more or less than"
+ "two tokens in string '%s'.",
tabConfigToken));
}
final String tabName = tokens[0];
final String tabClassName = tokens[1];
final GenericOrgaUnitTab tab = createTabInstance(tabClassName);
tabs.put(tabName, tab);
}
@SuppressWarnings("unchecked")
private GenericOrgaUnitTab createTabInstance(final String tabClassName) {
final GenericOrgaUnitTab tab;
try {
tab = (GenericOrgaUnitTab) Class.forName(tabClassName).
newInstance();
} catch (ClassNotFoundException ex) {
throw new IllegalArgumentException(String.format(
"Can't find tab class '%s'.",
tabClassName),
ex);
} catch (InstantiationException ex) {
throw new IllegalArgumentException(String.format(
"Can't instantiate tab class '%s'.",
tabClassName),
ex);
} catch (IllegalAccessException ex) {
throw new IllegalArgumentException(String.format(
"Can't instantiate tab class '%s'.",
tabClassName),
ex);
}
return tab;
}
public void addGlobalStateParams(final Page page) {
//Nothing yet
}
}

View File

@ -0,0 +1,144 @@
package com.arsdigita.cms.contenttypes.ui;
import com.arsdigita.bebop.PageState;
import com.arsdigita.domain.DomainCollection;
import com.arsdigita.web.ParameterMap;
import com.arsdigita.web.URL;
import com.arsdigita.web.Web;
import com.arsdigita.xml.Element;
import java.util.Iterator;
import java.util.Map;
/**
* Helper class for generating a paginator in lists generated by
* {@link GenericOrgaUnitTab}s.
*
* @param <T>
* @author Jens Pelzetter
* @version $Id$
*/
public class GenericOrgaUnitPaginator<T extends DomainCollection> {
private final static String PAGE_NUMBER = "pageNumber";
private final long pageSize;
private final long pageCount;
private final long begin;
private final long count;
private final long end;
private final long pageNumber;
public GenericOrgaUnitPaginator(final T collection,
final PageState state,
final long pageSize) {
this.pageSize = pageSize;
final long pageNum = getPageNumber(state);
pageCount = getPageCount(collection.size());
begin = getPaginatorBegin(pageNum);
count = getPaginatorCount(begin, collection.size());
end = getPaginatorEnd(begin, count);
pageNumber = normalizePageNumber(pageCount, pageNum);
}
public void setRange(final T collection) {
collection.setRange((int) begin + 1, (int) end + 1);
}
public void generateXml(final Element parent) {
final Element paginatorElem = parent.newChildElement(
"nav:paginator",
"http://ccm.redhat.com/london/navigation");
final URL requestUrl = Web.getContext().getRequestURL();
final ParameterMap parameters = new ParameterMap();
if (requestUrl.getParameterMap() != null) {
Iterator<?> current =
requestUrl.getParameterMap().keySet().iterator();
while (current.hasNext()) {
final String key = (String) current.next();
if (PAGE_NUMBER.equals(key)) {
continue;
} else {
parameters.setParameter(key, requestUrl.getParameterValues(
key));
}
}
}
paginatorElem.addAttribute("pageParam", "pageNumber");
paginatorElem.addAttribute("baseURL", URL.there(requestUrl.getPathInfo(),
parameters).toString());
paginatorElem.addAttribute("pageNumber", Long.toString(pageNumber));
paginatorElem.addAttribute("pageCount", Long.toString(pageCount));
paginatorElem.addAttribute("pageSize", Long.toString(pageSize));
paginatorElem.addAttribute("objectBegin", Long.toString(begin + 1));
paginatorElem.addAttribute("objectEnd", Long.toString(end + 1));
paginatorElem.addAttribute("objectCount", Long.toString(count));
}
private long getPageNumber(final PageState state) {
long num = 1;
if (state == null) {
return num;
}
final String value = state.getRequest().getParameter(PAGE_NUMBER);
if (value != null) {
try {
num = Integer.parseInt(value);
} catch (NumberFormatException ex) {
num = 1;
}
}
return num;
}
private long normalizePageNumber(final long pageCount,
final long pageNumber) {
long num = pageNumber;
if (num < 1) {
num = 1;
}
if (num > pageCount) {
if (pageCount == 0) {
num = 1;
} else {
num = pageCount;
}
}
return num;
}
private long getPageCount(final long objectCount) {
final double dObjectCount = (double) objectCount;
final double dPageSize = (double) pageSize;
final double dResult = Math.ceil(dObjectCount / pageSize);
final long result = (long) dResult;
return result;
}
private long getPaginatorBegin(final long pageNumber) {
return (pageNumber - 1) * pageSize;
}
private long getPaginatorCount(final long begin, final long objectCount) {
return Math.min(pageSize, (objectCount - begin));
}
private long getPaginatorEnd(final long begin, final long count) {
long paginatorEnd = begin + count;
if (paginatorEnd < 0) {
paginatorEnd = 0;
}
return paginatorEnd;
}
}

View File

@ -0,0 +1,153 @@
package com.arsdigita.cms.contenttypes.ui;
import com.arsdigita.bebop.PageState;
import com.arsdigita.cms.ContentItem;
import com.arsdigita.cms.contenttypes.GenericOrganizationalUnit;
import com.arsdigita.cms.contenttypes.GenericOrganizationalUnitSubordinateCollection;
import com.arsdigita.cms.dispatcher.SimpleXMLGenerator;
import com.arsdigita.xml.Element;
import org.apache.log4j.Logger;
/**
*
* @author Jens Pelzetter
* @version $Id$
*/
public abstract class GenericOrgaUnitSubordinateTab
implements GenericOrgaUnitTab {
private final static Logger logger =
Logger.getLogger(
GenericOrgaUnitSubordinateTab.class);
@Override
public boolean hasData(final GenericOrganizationalUnit orgaunit) {
return !getData(orgaunit).isEmpty();
}
@Override
public void generateXml(final GenericOrganizationalUnit orgaunit,
final Element parent,
final PageState state) {
final long start = System.currentTimeMillis();
final GenericOrganizationalUnitSubordinateCollection subOrgaUnits =
getData(orgaunit,
state);
processFilters(subOrgaUnits, state);
final Element subOrgaUnitsElem =
parent.newChildElement(getXmlElementName());
if (getPageSize() != 0) {
final GenericOrgaUnitPaginator<GenericOrganizationalUnitSubordinateCollection> paginator =
new GenericOrgaUnitPaginator<GenericOrganizationalUnitSubordinateCollection>(
subOrgaUnits, state, getPageSize());
paginator.setRange(subOrgaUnits);
paginator.generateXml(subOrgaUnitsElem);
}
while (subOrgaUnits.next()) {
generateSubOrgaUnitXml(subOrgaUnits.getGenericOrganizationalUnit(),
parent,
state);
}
logger.debug(String.format("XML for subordinate organizational units of "
+ "organizational unit '%s' with assoctype '%s' generated in"
+ "%d ms",
orgaunit.getName(),
getAssocType(),
System.currentTimeMillis() - start));
}
private void generateSubOrgaUnitXml(
final GenericOrganizationalUnit orgaunit,
final Element parent,
final PageState state) {
final SubordinateXmlLGenerator generator = new SubordinateXmlLGenerator(
orgaunit);
generator.generateXML(state, parent, "");
}
protected GenericOrganizationalUnitSubordinateCollection getData(
final GenericOrganizationalUnit orgaunit,
final PageState state) {
return getData(orgaunit);
}
protected GenericOrganizationalUnitSubordinateCollection getData(
final GenericOrganizationalUnit orgaunit) {
final GenericOrganizationalUnitSubordinateCollection subOrgaUnits =
orgaunit.
getSubordinateOrgaUnits();
subOrgaUnits.addFilter(
String.format("%s = '%s'",
GenericOrganizationalUnitSubordinateCollection.LINK_ASSOCTYPE,
getAssocType()));
return subOrgaUnits;
}
protected abstract String getXmlElementName();
/**
* The collection of subordinate organization units is filtered for
* the value of the {@code assocType} property returned by this method.
* If you don't want to filter for an assocType simply return '{@code %}'.
*
* @return
*/
protected abstract String getAssocType();
/**
* Page size for the paginator. If you want to disable the paginator,
* return 0.
*
* @return
*/
protected abstract int getPageSize();
/**
* Overwrite to create filters for the list.
*
* @param orgaunit
* @param subOrgaUnits
* @param element
* @param state
*/
protected void generateFiltersXml(
final GenericOrganizationalUnit orgaunit,
final GenericOrganizationalUnitSubordinateCollection subOrgaUnits,
final Element element,
final PageState state) {
//Nothing now
}
/**
* If you have filters for the list of subordinate organizational units,
* overwrite this method to process them.
*
* @param subOrgaUnits
* @param state
*/
protected void processFilters(
final GenericOrganizationalUnitSubordinateCollection subOrgaUnits,
final PageState state) {
//Nothing now
}
private class SubordinateXmlLGenerator extends SimpleXMLGenerator {
private final GenericOrganizationalUnit orgaunit;
public SubordinateXmlLGenerator(final GenericOrganizationalUnit orgaunit) {
super();
this.orgaunit = orgaunit;
}
@Override
protected ContentItem getContentItem(final PageState state) {
return orgaunit;
}
}
}

View File

@ -0,0 +1,20 @@
package com.arsdigita.cms.contenttypes.ui;
import com.arsdigita.bebop.PageState;
import com.arsdigita.cms.contenttypes.GenericOrganizationalUnit;
import com.arsdigita.xml.Element;
/**
*
* @author Jens Pelzetter
* @version $Id$
*/
public interface GenericOrgaUnitTab {
boolean hasData(GenericOrganizationalUnit orgaunit);
void generateXml(GenericOrganizationalUnit orgaunit,
Element parent,
PageState state);
}

View File

@ -37,7 +37,10 @@ import org.apache.log4j.Logger;
/**
*
* @author Jens Pelzetter
*
* @deprecated Replaced with {@link GenericOrgaUnitExtraXmlGenerator}.
*/
@Deprecated
public class GenericOrganizationalUnitPanel extends CompoundContentItemPanel {
private final static Logger logger =