New renderer for ObjectLists, which uses a second category system to split the list into sections (Ticket #1310).
git-svn-id: https://svn.libreccm.org/ccm/trunk@2075 8810af33-2d31-482b-a856-94f89814c4dfmaster
parent
4121b7a83d
commit
a4a94953c4
|
|
@ -283,6 +283,7 @@ public class DataCollectionDefinition extends LockableImpl {
|
||||||
getCategorizedObjectPath("id"),
|
getCategorizedObjectPath("id"),
|
||||||
"com.arsdigita.categorization.objectIDsInSubtree");
|
"com.arsdigita.categorization.objectIDsInSubtree");
|
||||||
children.set("categoryID", cat.getID());
|
children.set("categoryID", cat.getID());
|
||||||
|
|
||||||
if (m_excludeIndexObjects) {
|
if (m_excludeIndexObjects) {
|
||||||
Filter moreChildren =
|
Filter moreChildren =
|
||||||
objects.addNotInSubqueryFilter(
|
objects.addNotInSubqueryFilter(
|
||||||
|
|
@ -294,6 +295,7 @@ public class DataCollectionDefinition extends LockableImpl {
|
||||||
objects.addEqualsFilter(
|
objects.addEqualsFilter(
|
||||||
getCategorizedObjectPath("categories.id"),
|
getCategorizedObjectPath("categories.id"),
|
||||||
cat.getID());
|
cat.getID());
|
||||||
|
|
||||||
if (m_excludeIndexObjects) {
|
if (m_excludeIndexObjects) {
|
||||||
Filter moreChildren =
|
Filter moreChildren =
|
||||||
objects.addNotInSubqueryFilter(
|
objects.addNotInSubqueryFilter(
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@
|
||||||
*/
|
*/
|
||||||
package com.arsdigita.navigation;
|
package com.arsdigita.navigation;
|
||||||
|
|
||||||
|
import com.arsdigita.categorization.Categorization;
|
||||||
|
import com.arsdigita.categorization.Category;
|
||||||
import com.arsdigita.cms.dispatcher.SimpleXMLGenerator;
|
import com.arsdigita.cms.dispatcher.SimpleXMLGenerator;
|
||||||
import com.arsdigita.domain.DomainObjectFactory;
|
import com.arsdigita.domain.DomainObjectFactory;
|
||||||
import com.arsdigita.kernel.ACSObject;
|
import com.arsdigita.kernel.ACSObject;
|
||||||
|
|
@ -29,28 +31,22 @@ import com.arsdigita.persistence.PersistenceException;
|
||||||
import com.arsdigita.util.Assert;
|
import com.arsdigita.util.Assert;
|
||||||
import com.arsdigita.util.LockableImpl;
|
import com.arsdigita.util.LockableImpl;
|
||||||
import com.arsdigita.util.StringUtils;
|
import com.arsdigita.util.StringUtils;
|
||||||
import com.arsdigita.xml.Element;
|
|
||||||
|
|
||||||
// Quasimodo: Begin
|
|
||||||
import com.arsdigita.web.URL;
|
|
||||||
import com.arsdigita.web.ParameterMap;
|
import com.arsdigita.web.ParameterMap;
|
||||||
|
import com.arsdigita.web.URL;
|
||||||
import com.arsdigita.web.Web;
|
import com.arsdigita.web.Web;
|
||||||
// Quasimodo: End
|
import com.arsdigita.xml.Element;
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
public class DataCollectionRenderer extends LockableImpl {
|
public class DataCollectionRenderer extends LockableImpl {
|
||||||
|
|
||||||
private static final Logger s_log =
|
private static final Logger s_log = Logger.getLogger(DataCollectionRenderer.class);
|
||||||
Logger.getLogger(DataCollectionRenderer.class);
|
|
||||||
private ArrayList m_attributes = new ArrayList();
|
private ArrayList m_attributes = new ArrayList();
|
||||||
private ArrayList m_properties = new ArrayList();
|
private ArrayList m_properties = new ArrayList();
|
||||||
private int m_pageSize = 20;
|
private int m_pageSize = 20;
|
||||||
|
|
@ -60,8 +56,7 @@ public class DataCollectionRenderer extends LockableImpl {
|
||||||
* <code>true</code>. Defaults to
|
* <code>true</code>. Defaults to
|
||||||
* {@link SimpleXMLGenerator.ADAPTER_CONTEXT}.
|
* {@link SimpleXMLGenerator.ADAPTER_CONTEXT}.
|
||||||
*/
|
*/
|
||||||
private String m_specializeObjectsContext =
|
private String m_specializeObjectsContext = SimpleXMLGenerator.ADAPTER_CONTEXT;
|
||||||
SimpleXMLGenerator.ADAPTER_CONTEXT;
|
|
||||||
private boolean m_wrapAttributes = false;
|
private boolean m_wrapAttributes = false;
|
||||||
private boolean m_navItems = true;
|
private boolean m_navItems = true;
|
||||||
|
|
||||||
|
|
@ -70,31 +65,43 @@ public class DataCollectionRenderer extends LockableImpl {
|
||||||
addAttribute("id");
|
addAttribute("id");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addAttribute(String name) {
|
public void addAttribute(final String name) {
|
||||||
Assert.isUnlocked(this);
|
Assert.isUnlocked(this);
|
||||||
m_attributes.add(name);
|
m_attributes.add(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addProperty(DataCollectionPropertyRenderer pr) {
|
public void addProperty(final DataCollectionPropertyRenderer pr) {
|
||||||
Assert.isUnlocked(this);
|
Assert.isUnlocked(this);
|
||||||
m_properties.add(pr);
|
m_properties.add(pr);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPageSize(int pageSize) {
|
protected int getPageSize() {
|
||||||
|
return m_pageSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPageSize(final int pageSize) {
|
||||||
Assert.isUnlocked(this);
|
Assert.isUnlocked(this);
|
||||||
m_pageSize = pageSize;
|
m_pageSize = pageSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected boolean getNavItems() {
|
||||||
|
return m_navItems;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify whether to include the items for navigation that are within
|
* Specify whether to include the items for navigation that are within
|
||||||
* same category.
|
* same category.
|
||||||
* This flag toggles the generation of nav:item xml elements.
|
* This flag toggles the generation of nav:item xml elements.
|
||||||
*/
|
*/
|
||||||
public void setNavItems(boolean navItems) {
|
public void setNavItems(final boolean navItems) {
|
||||||
m_navItems = navItems;
|
m_navItems = navItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected boolean isSpecializeObjects() {
|
||||||
|
return m_specializeObjects;
|
||||||
|
}
|
||||||
|
|
||||||
public void setSpecializeObjects(boolean specializeObjects) {
|
public void setSpecializeObjects(final boolean specializeObjects) {
|
||||||
Assert.isUnlocked(this);
|
Assert.isUnlocked(this);
|
||||||
m_specializeObjects = specializeObjects;
|
m_specializeObjects = specializeObjects;
|
||||||
}
|
}
|
||||||
|
|
@ -110,11 +117,11 @@ public class DataCollectionRenderer extends LockableImpl {
|
||||||
*
|
*
|
||||||
* @param context The adapter context.
|
* @param context The adapter context.
|
||||||
*/
|
*/
|
||||||
public void setSpecializeObjectsContext(String context) {
|
public void setSpecializeObjectsContext(final String context) {
|
||||||
m_specializeObjectsContext = context;
|
m_specializeObjectsContext = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setWrapAttributes(boolean wrapAttributes) {
|
public void setWrapAttributes(final boolean wrapAttributes) {
|
||||||
Assert.isUnlocked(this);
|
Assert.isUnlocked(this);
|
||||||
m_wrapAttributes = wrapAttributes;
|
m_wrapAttributes = wrapAttributes;
|
||||||
}
|
}
|
||||||
|
|
@ -122,17 +129,22 @@ public class DataCollectionRenderer extends LockableImpl {
|
||||||
public List getAttributes() {
|
public List getAttributes() {
|
||||||
return m_attributes;
|
return m_attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List getProperties() {
|
||||||
|
return m_properties;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param objects
|
* @param objects
|
||||||
* @param pageNumber current page, starting from 1
|
* @param pageNum
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public Element generateXML(DataCollection objects,
|
public Element generateXML(final DataCollection objects, final int pageNum) {
|
||||||
int pageNumber) {
|
|
||||||
Assert.isLocked(this);
|
Assert.isLocked(this);
|
||||||
|
|
||||||
|
int pageNumber = pageNum;
|
||||||
|
|
||||||
// Quasimodo: Begin
|
// Quasimodo: Begin
|
||||||
// If objects is null or empty, do not insert objectList-element
|
// If objects is null or empty, do not insert objectList-element
|
||||||
// but do insert noContent-element and return immediately
|
// but do insert noContent-element and return immediately
|
||||||
|
|
@ -141,19 +153,18 @@ public class DataCollectionRenderer extends LockableImpl {
|
||||||
}
|
}
|
||||||
// Quasimodo: End
|
// Quasimodo: End
|
||||||
|
|
||||||
Element content = Navigation.newElement("objectList");
|
final Element content = Navigation.newElement("objectList");
|
||||||
|
|
||||||
//Return the empty nav:item & nav:paginator tags.
|
//Return the empty nav:item & nav:paginator tags.
|
||||||
// Quasimodo: Why should I??? There is no need for a paginator if there aren't any elements
|
// Quasimodo: Why should I??? There is no need for a paginator if there aren't any elements
|
||||||
if (!m_navItems) {
|
if (!m_navItems) {
|
||||||
Element paginator = Navigation.newElement("paginator");
|
final Element paginator = Navigation.newElement("paginator");
|
||||||
content.addContent(paginator);
|
content.addContent(paginator);
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
long objectCount = objects.size();
|
final long objectCount = objects.size();
|
||||||
int pageCount = (int) Math.ceil((double) objectCount
|
final int pageCount = (int) Math.ceil((double) objectCount / (double) m_pageSize);
|
||||||
/ (double) m_pageSize);
|
|
||||||
|
|
||||||
if (pageNumber < 1) {
|
if (pageNumber < 1) {
|
||||||
pageNumber = 1;
|
pageNumber = 1;
|
||||||
|
|
@ -163,28 +174,27 @@ public class DataCollectionRenderer extends LockableImpl {
|
||||||
pageNumber = (pageCount == 0 ? 1 : pageCount);
|
pageNumber = (pageCount == 0 ? 1 : pageCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
long begin = ((pageNumber - 1) * m_pageSize);
|
final long begin = ((pageNumber - 1) * m_pageSize);
|
||||||
int count = (int) Math.min(m_pageSize, (objectCount - begin));
|
final int count = (int) Math.min(m_pageSize, (objectCount - begin));
|
||||||
long end = begin + count;
|
final long end = begin + count;
|
||||||
|
|
||||||
if (count != 0) {
|
if (count != 0) {
|
||||||
objects.setRange(new Integer((int) begin + 1),
|
objects.setRange((int) begin + 1, (int) end + 1);
|
||||||
new Integer((int) end + 1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Element paginator = Navigation.newElement("paginator");
|
final Element paginator = Navigation.newElement("paginator");
|
||||||
|
|
||||||
// Quasimodo: Begin
|
// Quasimodo: Begin
|
||||||
// Copied from com.arsdigita.search.ui.ResultPane
|
// Copied from com.arsdigita.search.ui.ResultPane
|
||||||
String pageParam = "pageNumber";
|
final String pageParam = "pageNumber";
|
||||||
|
|
||||||
URL url = Web.getContext().getRequestURL();
|
final URL url = Web.getContext().getRequestURL();
|
||||||
ParameterMap map = new ParameterMap();
|
final ParameterMap map = new ParameterMap();
|
||||||
|
|
||||||
if (url.getParameterMap() != null) {
|
if (url.getParameterMap() != null) {
|
||||||
Iterator current = url.getParameterMap().keySet().iterator();
|
final Iterator current = url.getParameterMap().keySet().iterator();
|
||||||
while (current.hasNext()) {
|
while (current.hasNext()) {
|
||||||
String key = (String) current.next();
|
final String key = (String) current.next();
|
||||||
if (key.equals(pageParam)) {
|
if (key.equals(pageParam)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -197,47 +207,48 @@ public class DataCollectionRenderer extends LockableImpl {
|
||||||
toString());
|
toString());
|
||||||
// Quasimodo: End
|
// Quasimodo: End
|
||||||
|
|
||||||
paginator.addAttribute("pageNumber", new Long(pageNumber).toString());
|
paginator.addAttribute("pageNumber", Long.toString(pageNumber));
|
||||||
paginator.addAttribute("pageCount", new Long(pageCount).toString());
|
paginator.addAttribute("pageCount", Long.toString(pageCount));
|
||||||
paginator.addAttribute("pageSize", new Long(m_pageSize).toString());
|
paginator.addAttribute("pageSize", Long.toString(m_pageSize));
|
||||||
paginator.addAttribute("objectBegin", new Long(begin + 1).toString());
|
paginator.addAttribute("objectBegin", Long.toString(begin + 1));
|
||||||
paginator.addAttribute("objectEnd", new Long(end).toString());
|
paginator.addAttribute("objectEnd", Long.toString(end));
|
||||||
paginator.addAttribute("objectCount", new Long(objectCount).toString());
|
paginator.addAttribute("objectCount", Long.toString(objectCount));
|
||||||
|
|
||||||
content.addContent(paginator);
|
content.addContent(paginator);
|
||||||
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
while (objects.next()) {
|
while (objects.next()) {
|
||||||
DataObject dobj = objects.getDataObject();
|
final DataObject dobj = objects.getDataObject();
|
||||||
ACSObject object = null;
|
ACSObject object = null;
|
||||||
if (m_specializeObjects) {
|
if (m_specializeObjects) {
|
||||||
object = (ACSObject) DomainObjectFactory.newInstance(dobj);
|
object = (ACSObject) DomainObjectFactory.newInstance(dobj);
|
||||||
if (object == null) {
|
if (object == null) {
|
||||||
s_log.error(String.format("Failed to specialize object with with id %s. Skiping object.", dobj.getOID().toString()));
|
s_log.error(String.format("Failed to specialize object with with id %s. Skiping object.", dobj.
|
||||||
|
getOID().toString()));
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
s_log.debug("Specializing successful.");
|
s_log.debug("Specializing successful.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Element item = Navigation.newElement(content, "item");
|
final Element item = Navigation.newElement(content, "item");
|
||||||
|
|
||||||
Iterator attributes = m_attributes.iterator();
|
final Iterator attributes = m_attributes.iterator();
|
||||||
while (attributes.hasNext()) {
|
while (attributes.hasNext()) {
|
||||||
String name = (String) attributes.next();
|
final String name = (String) attributes.next();
|
||||||
String[] paths = StringUtils.split(name, '.');
|
final String[] paths = StringUtils.split(name, '.');
|
||||||
outputValue(item, dobj, name, paths, 0);
|
outputValue(item, dobj, name, paths, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator properties = m_properties.iterator();
|
final Iterator properties = m_properties.iterator();
|
||||||
while (properties.hasNext()) {
|
while (properties.hasNext()) {
|
||||||
DataCollectionPropertyRenderer property = (DataCollectionPropertyRenderer) properties.next();
|
final DataCollectionPropertyRenderer property = (DataCollectionPropertyRenderer) properties.next();
|
||||||
property.render(objects, item);
|
property.render(objects, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
Element path = Navigation.newElement(item, "path");
|
final Element path = Navigation.newElement(item, "path");
|
||||||
path.setText(getStableURL(dobj, object));
|
path.setText(getStableURL(dobj, object));
|
||||||
//item.addContent(path);
|
//item.addContent(path);
|
||||||
|
|
||||||
generateItemXML(item, dobj, object, index);
|
generateItemXML(item, dobj, object, index);
|
||||||
|
|
||||||
index++;
|
index++;
|
||||||
|
|
@ -247,22 +258,23 @@ public class DataCollectionRenderer extends LockableImpl {
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getStableURL(DataObject dobj, ACSObject obj) {
|
protected String getStableURL(final DataObject dobj, final ACSObject obj) {
|
||||||
OID oid = new OID((String) dobj.get(ACSObject.OBJECT_TYPE),
|
final OID oid = new OID((String) dobj.get(ACSObject.OBJECT_TYPE), dobj.get(ACSObject.ID));
|
||||||
dobj.get(ACSObject.ID));
|
|
||||||
return Navigation.redirectURL(oid);
|
return Navigation.redirectURL(oid);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void outputValue(final Element item, final Object value,
|
protected void outputValue(final Element item,
|
||||||
final String name,
|
final Object value,
|
||||||
final String[] paths, final int depth) {
|
final String name,
|
||||||
|
final String[] paths,
|
||||||
|
final int depth) {
|
||||||
if (null == value) {
|
if (null == value) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value instanceof DataAssociation) {
|
if (value instanceof DataAssociation) {
|
||||||
DataAssociation assoc = (DataAssociation) value;
|
final DataAssociation assoc = (DataAssociation) value;
|
||||||
DataAssociationCursor cursor = assoc.cursor();
|
final DataAssociationCursor cursor = assoc.cursor();
|
||||||
|
|
||||||
while (cursor.next()) {
|
while (cursor.next()) {
|
||||||
outputValue(item, cursor.getDataObject(), name, paths, depth);
|
outputValue(item, cursor.getDataObject(), name, paths, depth);
|
||||||
|
|
@ -271,40 +283,34 @@ public class DataCollectionRenderer extends LockableImpl {
|
||||||
cursor.close();
|
cursor.close();
|
||||||
} else if (value instanceof DataObject) {
|
} else if (value instanceof DataObject) {
|
||||||
try {
|
try {
|
||||||
Object newValue = ((DataObject) value).get(paths[depth]);
|
final Object newValue = ((DataObject) value).get(paths[depth]);
|
||||||
outputValue(item, newValue, name, paths, depth + 1);
|
outputValue(item, newValue, name, paths, depth + 1);
|
||||||
} catch (PersistenceException ex) {
|
} catch (PersistenceException ex) {
|
||||||
valuePersistenceError(ex, paths, depth);
|
valuePersistenceError(ex, paths, depth);
|
||||||
}
|
}
|
||||||
} else if (depth == paths.length) {
|
} else if (depth == paths.length) {
|
||||||
Element attribute = Navigation.newElement("attribute");
|
final Element attribute = Navigation.newElement("attribute");
|
||||||
attribute.addAttribute("name", name);
|
attribute.addAttribute("name", name);
|
||||||
attribute.setText(value.toString());
|
attribute.setText(value.toString());
|
||||||
|
|
||||||
// Special handling of Date - see ccm-core/src/com/arsdigita/domain/DomainObjectXMLRenderer.java
|
// Special handling of Date - see ccm-core/src/com/arsdigita/domain/DomainObjectXMLRenderer.java
|
||||||
if (value instanceof Date) {
|
if (value instanceof Date) {
|
||||||
Date date = (Date) value;
|
final Date date = (Date) value;
|
||||||
Calendar calDate = Calendar.getInstance();
|
final Calendar calDate = Calendar.getInstance();
|
||||||
calDate.setTime(date);
|
calDate.setTime(date);
|
||||||
attribute.addAttribute("year", Integer.toString(calDate.get(
|
attribute.addAttribute("year", Integer.toString(calDate.get(Calendar.YEAR)));
|
||||||
Calendar.YEAR)));
|
attribute.addAttribute("month", Integer.toString(calDate.get(Calendar.MONTH) + 1));
|
||||||
attribute.addAttribute("month", Integer.toString(calDate.get(
|
attribute.addAttribute("day", Integer.toString(calDate.get(Calendar.DAY_OF_MONTH)));
|
||||||
Calendar.MONTH) + 1));
|
attribute.addAttribute("hour", Integer.toString(calDate.get(Calendar.HOUR_OF_DAY)));
|
||||||
attribute.addAttribute("day", Integer.toString(calDate.get(
|
attribute.addAttribute("minute", Integer.toString(calDate.get(Calendar.MINUTE)));
|
||||||
Calendar.DAY_OF_MONTH)));
|
attribute.addAttribute("second", Integer.toString(calDate.get(Calendar.SECOND)));
|
||||||
attribute.addAttribute("hour", Integer.toString(calDate.get(
|
|
||||||
Calendar.HOUR_OF_DAY)));
|
|
||||||
attribute.addAttribute("minute", Integer.toString(calDate.get(
|
|
||||||
Calendar.MINUTE)));
|
|
||||||
attribute.addAttribute("second", Integer.toString(calDate.get(
|
|
||||||
Calendar.SECOND)));
|
|
||||||
|
|
||||||
// Quasimodo: BEGIN
|
// Quasimodo: BEGIN
|
||||||
// Add attributes for date and time
|
// Add attributes for date and time
|
||||||
Locale negLocale = com.arsdigita.globalization.GlobalizationHelper.getNegotiatedLocale();
|
final Locale negLocale = com.arsdigita.globalization.GlobalizationHelper.getNegotiatedLocale();
|
||||||
DateFormat dateFormatter = DateFormat.getDateInstance(DateFormat.MEDIUM, negLocale);
|
final DateFormat dateFormatter = DateFormat.getDateInstance(DateFormat.MEDIUM, negLocale);
|
||||||
DateFormat longDateFormatter = DateFormat.getDateInstance(DateFormat.LONG, negLocale);
|
final DateFormat longDateFormatter = DateFormat.getDateInstance(DateFormat.LONG, negLocale);
|
||||||
DateFormat timeFormatter = DateFormat.getTimeInstance(DateFormat.SHORT, negLocale);
|
final DateFormat timeFormatter = DateFormat.getTimeInstance(DateFormat.SHORT, negLocale);
|
||||||
attribute.addAttribute("date", dateFormatter.format(date));
|
attribute.addAttribute("date", dateFormatter.format(date));
|
||||||
attribute.addAttribute("longDate", longDateFormatter.format(date));
|
attribute.addAttribute("longDate", longDateFormatter.format(date));
|
||||||
attribute.addAttribute("time", timeFormatter.format(date));
|
attribute.addAttribute("time", timeFormatter.format(date));
|
||||||
|
|
@ -318,9 +324,8 @@ public class DataCollectionRenderer extends LockableImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void valuePersistenceError(PersistenceException ex,
|
private void valuePersistenceError(final PersistenceException exception, final String[] paths, final int depth) {
|
||||||
String[] paths, int depth) {
|
final StringBuffer msg = new StringBuffer(30);
|
||||||
StringBuffer msg = new StringBuffer();
|
|
||||||
msg.append("Attribute ");
|
msg.append("Attribute ");
|
||||||
for (int i = 0; i <= depth; i++) {
|
for (int i = 0; i <= depth; i++) {
|
||||||
msg.append(paths[i]);
|
msg.append(paths[i]);
|
||||||
|
|
@ -330,16 +335,15 @@ public class DataCollectionRenderer extends LockableImpl {
|
||||||
}
|
}
|
||||||
msg.append(" doesn't exist");
|
msg.append(" doesn't exist");
|
||||||
|
|
||||||
if (null == ex) {
|
if (null == exception) {
|
||||||
s_log.warn(msg.toString());
|
s_log.warn(msg.toString());
|
||||||
} else {
|
} else {
|
||||||
s_log.warn(msg.toString(), ex);
|
s_log.warn(msg.toString(), exception);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void generateItemXML(Element item,
|
protected void generateItemXML(final Element item, final DataObject dobj, final ACSObject obj, final int index) {
|
||||||
DataObject dobj,
|
|
||||||
ACSObject obj,
|
|
||||||
int index) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
package com.arsdigita.navigation.cms;
|
||||||
|
|
||||||
|
import com.arsdigita.categorization.Category;
|
||||||
|
import com.arsdigita.london.terms.Domain;
|
||||||
|
import com.arsdigita.navigation.NavigationModel;
|
||||||
|
import com.arsdigita.persistence.DataCollection;
|
||||||
|
import com.arsdigita.persistence.Filter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An extension to the {@link CMSDataCollectionDefinition}. With this definition it is possible to filter an object
|
||||||
|
* list using a second category system/terms domain. This class is designed to be used together with the
|
||||||
|
* {@link CategorisedDataCollectionRenderer} which displays the objects in a list with several sections.
|
||||||
|
*
|
||||||
|
* @author Jens Pelzetter <jens@jp-digital.de>
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class CategorisedDataCollectionDefinition extends CMSDataCollectionDefinition{
|
||||||
|
|
||||||
|
private String termDomain;
|
||||||
|
|
||||||
|
public String getTermDomain() {
|
||||||
|
return termDomain;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTermDomain(final String termDomain) {
|
||||||
|
this.termDomain = termDomain;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void applyFilters(final DataCollection objects, final NavigationModel model) {
|
||||||
|
super.applyFilters(objects, model);
|
||||||
|
|
||||||
|
final Domain domain = Domain.retrieve(termDomain);
|
||||||
|
final Category rootCat = domain.getModel();
|
||||||
|
|
||||||
|
//final FilterFactory filterFactory = objects.getFilterFactory();
|
||||||
|
final Filter filter = objects.addInSubqueryFilter(getCategorizedObjectPath("id"), "com.arsdigita.categorization.objectIDsInSubtree");
|
||||||
|
filter.set("categoryID", rootCat.getID());
|
||||||
|
|
||||||
|
objects.addOrder("parent.categories.link.sortKey");
|
||||||
|
objects.addOrder("title desc");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,266 @@
|
||||||
|
package com.arsdigita.navigation.cms;
|
||||||
|
|
||||||
|
import com.arsdigita.categorization.Category;
|
||||||
|
import com.arsdigita.cms.ContentPage;
|
||||||
|
import com.arsdigita.cms.contenttypes.GenericPerson;
|
||||||
|
import com.arsdigita.domain.DomainCollection;
|
||||||
|
import com.arsdigita.domain.DomainObjectFactory;
|
||||||
|
import com.arsdigita.globalization.GlobalizationHelper;
|
||||||
|
import com.arsdigita.kernel.ACSObject;
|
||||||
|
import com.arsdigita.london.terms.Domain;
|
||||||
|
import com.arsdigita.london.terms.Term;
|
||||||
|
import com.arsdigita.navigation.DataCollectionPropertyRenderer;
|
||||||
|
import com.arsdigita.navigation.Navigation;
|
||||||
|
import com.arsdigita.persistence.DataAssociationCursor;
|
||||||
|
import com.arsdigita.persistence.DataCollection;
|
||||||
|
import com.arsdigita.persistence.DataObject;
|
||||||
|
import com.arsdigita.util.Assert;
|
||||||
|
import com.arsdigita.util.StringUtils;
|
||||||
|
import com.arsdigita.web.ParameterMap;
|
||||||
|
import com.arsdigita.web.URL;
|
||||||
|
import com.arsdigita.web.Web;
|
||||||
|
import com.arsdigita.xml.Element;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* An extended {@code DataCollectionRenderer} which displays a object list split into several sections. The sections
|
||||||
|
* are created using a second category system/term domain set using the {@link #setTermDomain(java.lang.String)}
|
||||||
|
* method in the JSP template. This renderer is designed to be used together with the
|
||||||
|
* {@link CategorisedDataCollectionRenderer}. To use them, a special JSP template is required. More specificly a JSP
|
||||||
|
* template using these two class would look like this (only relevant parts shown):
|
||||||
|
* </p>
|
||||||
|
* <pre>
|
||||||
|
* ...
|
||||||
|
* <define:component name="itemList"
|
||||||
|
* classname="com.arsdigita.navigation.ui.object.SimpleObjectList"/>
|
||||||
|
* <jsp:scriptlet>
|
||||||
|
* CategorisedDataCollectionDefinition definition = new CategorisedDataCollectionDefinition();
|
||||||
|
* CategorisedDataCollectionRenderer renderer = new CategorisedDataCollectionRenderer();
|
||||||
|
*
|
||||||
|
* definition.setObjectType("com.arsdigita.cms.contenttypes.GenericPerson");
|
||||||
|
* definition.setDescendCategories(false);
|
||||||
|
* definition.setTermDomain("memberTypes");
|
||||||
|
*
|
||||||
|
* renderer.setTermDomain("memberTypes");
|
||||||
|
*
|
||||||
|
* ((com.arsdigita.navigation.ui.object.SimpleObjectList) itemList).setDefinition(definition);
|
||||||
|
* ((com.arsdigita.navigation.ui.object.SimpleObjectList) itemList).setRenderer(renderer);
|
||||||
|
*
|
||||||
|
* ...
|
||||||
|
* </jsp:scriplet>
|
||||||
|
* </pre>
|
||||||
|
* <p>
|
||||||
|
* This example will create a list of objects of the type {@link GenericPerson}, split into sections definied by the
|
||||||
|
* terms domain identified by the key {@code memberTypes}. Only the root terms of the domain are used for creating the
|
||||||
|
* sections.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author Jens Pelzetter <jens@jp-digital.de>
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class CategorisedDataCollectionRenderer extends CMSDataCollectionRenderer {
|
||||||
|
|
||||||
|
private static final Logger s_log = Logger.getLogger(CategorisedDataCollectionRenderer.class);
|
||||||
|
private String termDomain;
|
||||||
|
|
||||||
|
public CategorisedDataCollectionRenderer() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTermDomain() {
|
||||||
|
return termDomain;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTermDomain(final String termDomain) {
|
||||||
|
this.termDomain = termDomain;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Element generateXML(final DataCollection objects, int pageNum) {
|
||||||
|
Assert.isLocked(this);
|
||||||
|
|
||||||
|
int pageNumber = pageNum;
|
||||||
|
|
||||||
|
// Quasimodo: Begin
|
||||||
|
// If objects is null or empty, do not insert objectList-element
|
||||||
|
// but do insert noContent-element and return immediately
|
||||||
|
if (objects == null || objects.isEmpty()) {
|
||||||
|
return Navigation.newElement("noContent");
|
||||||
|
}
|
||||||
|
// Quasimodo: End
|
||||||
|
|
||||||
|
final Element content = Navigation.newElement("objectList");
|
||||||
|
|
||||||
|
//Return the empty nav:item & nav:paginator tags.
|
||||||
|
// Quasimodo: Why should I??? There is no need for a paginator if there aren't any elements
|
||||||
|
if (!getNavItems()) {
|
||||||
|
final Element paginator = Navigation.newElement("paginator");
|
||||||
|
content.addContent(paginator);
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
final long objectCount = objects.size();
|
||||||
|
final int pageCount = (int) Math.ceil((double) objectCount / (double) getPageSize());
|
||||||
|
|
||||||
|
if (pageNumber < 1) {
|
||||||
|
pageNumber = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pageNumber > pageCount) {
|
||||||
|
pageNumber = (pageCount == 0 ? 1 : pageCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
final long begin = ((pageNumber - 1) * getPageSize());
|
||||||
|
final int count = (int) Math.min(getPageSize(), (objectCount - begin));
|
||||||
|
final long end = begin + count;
|
||||||
|
|
||||||
|
if (count != 0) {
|
||||||
|
objects.setRange((int) begin + 1, (int) end + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Element paginator = Navigation.newElement("paginator");
|
||||||
|
|
||||||
|
// Quasimodo: Begin
|
||||||
|
// Copied from com.arsdigita.search.ui.ResultPane
|
||||||
|
final String pageParam = "pageNumber";
|
||||||
|
|
||||||
|
final URL url = Web.getContext().getRequestURL();
|
||||||
|
final ParameterMap map = new ParameterMap();
|
||||||
|
|
||||||
|
if (url.getParameterMap() != null) {
|
||||||
|
final Iterator current = url.getParameterMap().keySet().iterator();
|
||||||
|
while (current.hasNext()) {
|
||||||
|
final String key = (String) current.next();
|
||||||
|
if (key.equals(pageParam)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
map.setParameterValues(key, url.getParameterValues(key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
paginator.addAttribute("pageParam", pageParam);
|
||||||
|
paginator.addAttribute("baseURL", URL.there(url.getPathInfo(), map).
|
||||||
|
toString());
|
||||||
|
// Quasimodo: End
|
||||||
|
|
||||||
|
paginator.addAttribute("pageNumber", Long.toString(pageNumber));
|
||||||
|
paginator.addAttribute("pageCount", Long.toString(pageCount));
|
||||||
|
paginator.addAttribute("pageSize", Long.toString(getPageSize()));
|
||||||
|
paginator.addAttribute("objectBegin", Long.toString(begin + 1));
|
||||||
|
paginator.addAttribute("objectEnd", Long.toString(end));
|
||||||
|
paginator.addAttribute("objectCount", Long.toString(objectCount));
|
||||||
|
|
||||||
|
content.addContent(paginator);
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
final Domain domain = Domain.retrieve(termDomain);
|
||||||
|
Category currentCat = null;
|
||||||
|
final Map<String, Element> sections = new HashMap<String, Element>();
|
||||||
|
Element currentSection = null;
|
||||||
|
while (objects.next()) {
|
||||||
|
final DataObject dobj = objects.getDataObject();
|
||||||
|
ACSObject object = null;
|
||||||
|
//if (m_specializeObjects) {
|
||||||
|
object = (ACSObject) DomainObjectFactory.newInstance(dobj);
|
||||||
|
if (object == null) {
|
||||||
|
s_log.error(String.format("Failed to specialize object with with id %s. Skiping object.", dobj.
|
||||||
|
getOID().toString()));
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
s_log.debug("Specializing successful.");
|
||||||
|
}
|
||||||
|
//}
|
||||||
|
|
||||||
|
// Get the content bundle to retrieve the terms/categories. This is necessary because the bundle is
|
||||||
|
// object which is categorised not the item itself.
|
||||||
|
final ACSObject categorisedObj;
|
||||||
|
if (object instanceof ContentPage) {
|
||||||
|
final ContentPage item = (ContentPage) object;
|
||||||
|
categorisedObj = item.getContentBundle();
|
||||||
|
} else {
|
||||||
|
categorisedObj = object;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the term from the term domain used to separate the list which are associated the current object.
|
||||||
|
final DomainCollection terms = domain.getDirectTerms(categorisedObj);
|
||||||
|
if (terms.next()) {
|
||||||
|
//Get the category
|
||||||
|
final Category cat = ((Term) terms.getDomainObject()).getModel();
|
||||||
|
// If a new section starts create a new section element. Ordering has to be done the theme using the
|
||||||
|
// sortKey attribute added to the section
|
||||||
|
if (currentCat == null) {
|
||||||
|
currentCat = cat;
|
||||||
|
final Element section = Navigation.newElement(content, "section");
|
||||||
|
section.addAttribute("id", cat.getID().toString());
|
||||||
|
section.addAttribute("url", cat.getURL());
|
||||||
|
section.addAttribute("title", cat.getName(GlobalizationHelper.getNegotiatedLocale().getLanguage()));
|
||||||
|
final DataAssociationCursor childCats = domain.getModel().getRelatedCategories(Category.CHILD);
|
||||||
|
childCats.addEqualsFilter("id", cat.getID());
|
||||||
|
if (childCats.next()) {
|
||||||
|
section.addAttribute("sortKey", childCats.get("link.sortKey").toString());
|
||||||
|
}
|
||||||
|
childCats.close();
|
||||||
|
currentSection = section;
|
||||||
|
sections.put(cat.getURL(), section);
|
||||||
|
} else if (!cat.getID().equals(currentCat.getID())) {
|
||||||
|
currentCat = cat;
|
||||||
|
//If the section has been already created use the existing element.
|
||||||
|
if (sections.containsKey(cat.getURL())) {
|
||||||
|
currentSection = sections.get(cat.getURL());
|
||||||
|
} else {
|
||||||
|
final Element section = Navigation.newElement(content, "section");
|
||||||
|
section.addAttribute("id", cat.getID().toString());
|
||||||
|
section.addAttribute("url", cat.getURL());
|
||||||
|
section.addAttribute("title", cat.getName(GlobalizationHelper.getNegotiatedLocale().
|
||||||
|
getLanguage()));
|
||||||
|
final DataAssociationCursor childCats = domain.getModel().getRelatedCategories(Category.CHILD);
|
||||||
|
childCats.addEqualsFilter("id", cat.getID());
|
||||||
|
if (childCats.next()) {
|
||||||
|
section.addAttribute("sortKey", childCats.get("link.sortKey").toString());
|
||||||
|
}
|
||||||
|
childCats.close();
|
||||||
|
currentSection = section;
|
||||||
|
sections.put(cat.getURL(), section);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
terms.close();
|
||||||
|
|
||||||
|
final Element item;
|
||||||
|
if (currentSection == null) {
|
||||||
|
item = Navigation.newElement(content, "item");
|
||||||
|
} else {
|
||||||
|
item = Navigation.newElement(currentSection, "item");
|
||||||
|
}
|
||||||
|
|
||||||
|
final Iterator attributes = getAttributes().iterator();
|
||||||
|
while (attributes.hasNext()) {
|
||||||
|
final String name = (String) attributes.next();
|
||||||
|
final String[] paths = StringUtils.split(name, '.');
|
||||||
|
outputValue(item, dobj, name, paths, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Iterator properties = getProperties().iterator();
|
||||||
|
while (properties.hasNext()) {
|
||||||
|
final DataCollectionPropertyRenderer property = (DataCollectionPropertyRenderer) properties.next();
|
||||||
|
property.render(objects, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Element path = Navigation.newElement(item, "path");
|
||||||
|
path.setText(getStableURL(dobj, object));
|
||||||
|
//item.addContent(path);
|
||||||
|
|
||||||
|
generateItemXML(item, dobj, object, index);
|
||||||
|
|
||||||
|
index++;
|
||||||
|
//content.addContent(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -69,7 +69,7 @@ public abstract class AbstractObjectList
|
||||||
* @return the object list or null
|
* @return the object list or null
|
||||||
*/
|
*/
|
||||||
protected DataCollection getObjects(HttpServletRequest request,
|
protected DataCollection getObjects(HttpServletRequest request,
|
||||||
HttpServletResponse response) {
|
HttpServletResponse response) {
|
||||||
|
|
||||||
// Stop here, if the set object type is invalid a.k.a. not installed
|
// Stop here, if the set object type is invalid a.k.a. not installed
|
||||||
if (m_definition.hasInvalidObjectType()) {
|
if (m_definition.hasInvalidObjectType()) {
|
||||||
|
|
@ -92,7 +92,7 @@ public abstract class AbstractObjectList
|
||||||
}
|
}
|
||||||
|
|
||||||
public Element generateObjectListXML(HttpServletRequest request,
|
public Element generateObjectListXML(HttpServletRequest request,
|
||||||
HttpServletResponse response) {
|
HttpServletResponse response) {
|
||||||
Assert.isLocked(this);
|
Assert.isLocked(this);
|
||||||
|
|
||||||
String pageNumberValue = request.getParameter("pageNumber");
|
String pageNumberValue = request.getParameter("pageNumber");
|
||||||
|
|
@ -116,17 +116,22 @@ public abstract class AbstractObjectList
|
||||||
if (Kernel.getConfig().languageIndependentItems()) {
|
if (Kernel.getConfig().languageIndependentItems()) {
|
||||||
FilterFactory ff = objects.getFilterFactory();
|
FilterFactory ff = objects.getFilterFactory();
|
||||||
Filter filter = ff.or().
|
Filter filter = ff.or().
|
||||||
addFilter(ff.equals("language", com.arsdigita.globalization.GlobalizationHelper.getNegotiatedLocale().getLanguage())).
|
addFilter(ff.equals("language", com.arsdigita.globalization.GlobalizationHelper.
|
||||||
addFilter(ff.and().
|
getNegotiatedLocale().getLanguage())).
|
||||||
addFilter(ff.equals("language", GlobalizationHelper.LANG_INDEPENDENT)).
|
addFilter(
|
||||||
addFilter(ff.notIn("parent", "com.arsdigita.navigation.getParentIDsOfMatchedItems").set("language", com.arsdigita.globalization.GlobalizationHelper.getNegotiatedLocale().getLanguage())));
|
ff.and().
|
||||||
|
addFilter(ff.equals("language", GlobalizationHelper.LANG_INDEPENDENT)).
|
||||||
|
addFilter(ff.notIn("parent", "com.arsdigita.navigation.getParentIDsOfMatchedItems").set(
|
||||||
|
"language", com.arsdigita.globalization.GlobalizationHelper.getNegotiatedLocale().getLanguage())));
|
||||||
objects.addFilter(filter);
|
objects.addFilter(filter);
|
||||||
} else {
|
} else {
|
||||||
objects.addEqualsFilter("language", com.arsdigita.globalization.GlobalizationHelper.getNegotiatedLocale().getLanguage());
|
objects.addEqualsFilter("language", com.arsdigita.globalization.GlobalizationHelper.
|
||||||
|
getNegotiatedLocale().getLanguage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Quasimodo: End
|
// Quasimodo: End
|
||||||
|
|
||||||
return m_renderer.generateXML(objects, pageNumber.intValue());
|
return m_renderer.generateXML(objects, pageNumber.intValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue