Kategorienfilter arbeitet jetzt korrekt (durchsucht nur die ausgewählte Kategorie)

git-svn-id: https://svn.libreccm.org/ccm/trunk@2448 8810af33-2d31-482b-a856-94f89814c4df
master
jensp 2013-11-22 09:22:30 +00:00
parent 818b0785cf
commit 7f79f1da6a
7 changed files with 258 additions and 289 deletions

View File

@ -25,5 +25,5 @@ com.arsdigita.cms.contenttypes.generic_contact.address.hide_country.format=[bool
com.arsdigita.cms.contenttypes.generic_contact.contact_entry_keys.title=Select available contact entry types
com.arsdigita.cms.contenttypes.generic_contact.contact_entry_keys.purpose=Select available contact entry types and define display order
com.arsdigita.cms.contenttypes.generic_contact.contact_entry_keys.example=contact_type,office_hours,phone_office,phone_private,phone_mobile,email,fax,im,www
com.arsdigita.cms.contenttypes.generic_contact.contact_entry_keys.example=contacttype,visitingHours,phoneOffice,phonePrivate,phoneMobile,email,fax,im,www
com.arsdigita.cms.contenttypes.generic_contact.contact_entry_keys.format=[string]

View File

@ -34,8 +34,9 @@ import java.math.BigDecimal;
import javax.servlet.http.HttpServletRequest;
/**
* An extension of {@link ItemSearch} for use in a popup search window. The display of results is altered so that
* selecting a result closes the window & passes the id of the selected item back to the opener.
* An extension of {@link ItemSearch} for use in a popup search window. The display of results is
* altered so that selecting a result closes the window & passes the id of the selected item back
* to the opener.
*
* @author Stanislav Freidin (sfreidin@arsdigita.com)
* @version $Id: ItemSearchPopup.java 1397 2006-11-29 14:10:38Z sskracic $

View File

@ -18,7 +18,6 @@
*/
package com.arsdigita.bebop.form;
import java.util.Collections;
import java.util.Iterator;
import java.util.TooManyListenersException;
@ -48,22 +47,20 @@ import com.arsdigita.util.Assert;
import com.arsdigita.xml.Element;
/**
* <p>A class representing a widget in the graphical representation of
* a form.</p>
* <p>
* A class representing a widget in the graphical representation of a form.</p>
*
* <p>A widget may correspond to a standard HTML form element, or to a
* more specific element or set of elements, such as a date widget
* that allows input of month, day and year (and possibly time as
* <p>
* A widget may correspond to a standard HTML form element, or to a more specific element or set of
* elements, such as a date widget that allows input of month, day and year (and possibly time as
* well).</p>
*
* <p>This class and its subclasses provide methods to set all element
* attributes except for <code>VALUE</code>, which is typically
* dependent on the request. At the time of a request, a widget
* object merges a dynamically specified value or set of values with
* its own set of persistent attributes to render the final HTML for
* the widget. Other dynamic attributes may be associated with the
* form component via a <code>WidgetPeer</code> associated with the
* widget.</p>
* <p>
* This class and its subclasses provide methods to set all element attributes except for
* <code>VALUE</code>, which is typically dependent on the request. At the time of a request, a
* widget object merges a dynamically specified value or set of values with its own set of
* persistent attributes to render the final HTML for the widget. Other dynamic attributes may be
* associated with the form component via a <code>WidgetPeer</code> associated with the widget.</p>
*
* @author Karl Goldstein
* @author Uday Mathur
@ -80,7 +77,9 @@ public abstract class Widget extends BlockStylable implements Cloneable,
private ParameterListener m_forwardParameter = null;
private PrintListener m_printListener;
private Form m_form;
/** The optional (localized) label (or title) of this widget. */
/**
* The optional (localized) label (or title) of this widget.
*/
private GlobalizedMessage m_label;
private ValidationGuard m_guard = null;
@ -101,8 +100,7 @@ public abstract class Widget extends BlockStylable implements Cloneable,
public abstract boolean isCompound();
/**
* Returns a string naming the type of this widget. Must be implemented by
* subclasses
* Returns a string naming the type of this widget. Must be implemented by subclasses
*/
protected abstract String getType();
@ -111,14 +109,15 @@ public abstract class Widget extends BlockStylable implements Cloneable,
*
*/
protected Widget(String name) {
this( new StringParameter(name) );
this(new StringParameter(name));
}
/**
* Constructs a new widget.
*
* <p>Each new widget is associated with a ParameterModel describing
* the data object(s) submitted from the widget.
* <p>
* Each new widget is associated with a ParameterModel describing the data object(s) submitted
* from the widget.
*/
protected Widget(ParameterModel model) {
Assert.exists(model, ParameterModel.class);
@ -130,8 +129,7 @@ public abstract class Widget extends BlockStylable implements Cloneable,
return new ParameterListener() {
public void validate(ParameterEvent evt)
throws FormProcessException {
fireValidation(new ParameterEvent
(Widget.this, evt.getParameterData()));
fireValidation(new ParameterEvent(Widget.this, evt.getParameterData()));
}
};
}
@ -151,14 +149,14 @@ public abstract class Widget extends BlockStylable implements Cloneable,
PageState ps = evt.getPageState();
if ((!validateInvisible() && !ps.isVisibleOnPage(this)) ||
((m_guard != null) && m_guard.shouldValidate(ps))) {
if ((!validateInvisible() && !ps.isVisibleOnPage(this)) || ((m_guard != null) && m_guard.
shouldValidate(ps))) {
return;
}
for (Iterator it =
m_listeners.getListenerIterator(ParameterListener.class);
it.hasNext(); ) {
for (Iterator it
= m_listeners.getListenerIterator(ParameterListener.class);
it.hasNext();) {
((ParameterListener) it.next()).validate(evt);
}
}
@ -193,74 +191,67 @@ public abstract class Widget extends BlockStylable implements Cloneable,
}
/**
* Adds a print listener for this widget. Only one print listener can be
* set for a widget, since the <code>PrintListener</code> is expected to
* modify the target of the <code>PrintEvent</code>.
* Adds a print listener for this widget. Only one print listener can be set for a widget, since
* the <code>PrintListener</code> is expected to modify the target of the
* <code>PrintEvent</code>.
*
* @param listener the print listener
* @throws IlegalArgumentException <code>listener</code> is null
* @throws TooManyListenersException a print listener has previously been
* added
* @throws TooManyListenersException a print listener has previously been added
* @pre listener != null
*/
public void addPrintListener(PrintListener listener)
throws TooManyListenersException, IllegalArgumentException
{
if ( listener == null ) {
throws TooManyListenersException, IllegalArgumentException {
if (listener == null) {
throw new IllegalArgumentException("Argument listener can not be null");
}
if ( m_printListener != null ) {
if (m_printListener != null) {
throw new TooManyListenersException();
}
m_printListener = listener;
}
/**
* Set the print listener for this widget. Since there can only
* be one print listener for a widget, this lets you just set it
* and avoid writing a try/catch block for
* "TooManyListenersException". Any existing listener will be
* overwritten.
* Set the print listener for this widget. Since there can only be one print listener for a
* widget, this lets you just set it and avoid writing a try/catch block for
* "TooManyListenersException". Any existing listener will be overwritten.
*
* @param listener the print listener
* @throws IlegalArgumentException <code>listener</code> is null
* @pre listener != null */
* @pre listener != null
*/
public void setPrintListener(PrintListener listener)
throws IllegalArgumentException
{
if ( listener == null ) {
throws IllegalArgumentException {
if (listener == null) {
throw new IllegalArgumentException("Argument listener can not be null");
}
m_printListener = listener;
}
/**
* Remove a previously added print listener. If <code>listener</code> is
* not the listener that has been added with {@link #addPrintListener
* Remove a previously added print listener. If <code>listener</code> is not the listener that
* has been added with {@link #addPrintListener
* addPrintListener}, an IllegalArgumentException will be thrown.
* @param listener the listener that had been added with
* <code>addPrintListener</code>
* @throws IllegalArgumentException <code>listener</code> is not the
* currently registered print listener or is <code>null</code>.
*
* @param listener the listener that had been added with <code>addPrintListener</code>
* @throws IllegalArgumentException <code>listener</code> is not the currently registered print
* listener or is <code>null</code>.
* @pre listener != null
*/
public void removePrintListener(PrintListener listener)
throws IllegalArgumentException
{
if ( listener == null ) {
throws IllegalArgumentException {
if (listener == null) {
throw new IllegalArgumentException("listener can not be null");
}
if ( listener != m_printListener ) {
if (listener != m_printListener) {
throw new IllegalArgumentException("listener is not registered with this widget");
}
m_printListener = null;
}
/**
* Registers the ParameterModel of this Widget with the containing Form. This method is
* used by the Bebop framework and should not be used by application developers.
* Registers the ParameterModel of this Widget with the containing Form. This method is used by
* the Bebop framework and should not be used by application developers.
*/
public void register(Form form, FormModel model) {
model.addFormParam(getParameterModel());
@ -269,9 +260,8 @@ public abstract class Widget extends BlockStylable implements Cloneable,
}
/**
* Sets the Form Object for this Widget. This method will throw an
* exception if the _form pointer is already set. To explicity
* change the m_form pointer the developer must first call
* Sets the Form Object for this Widget. This method will throw an exception if the _form
* pointer is already set. To explicity change the m_form pointer the developer must first call
* setForm(null)
*
* @param form The <code>Form</code> Object for this Widget
@ -279,86 +269,76 @@ public abstract class Widget extends BlockStylable implements Cloneable,
*/
public void setForm(final Form form) {
if (m_form != null && form != null) {
throw new IllegalStateException("Form "+form.getName()+" already set for "+getName());
throw new IllegalStateException("Form " + form.getName() + " already set for "
+ getName());
}
m_form = form;
}
/**
* Gets the Form Object for this Widget. Throws an exception if
* the Widget doesn't belong to a form.
* Gets the Form Object for this Widget. Throws an exception if the Widget doesn't belong to a
* form.
*
* @return the {@link Form} Object for this Widget.
* @post return != null
*/
public Form getForm() throws RuntimeException {
if (m_form == null) {
throw new RuntimeException
("Widget " + this + " (" + getName() + ") " +
"isn't associated with any Form");
throw new RuntimeException("Widget " + this + " (" + getName() + ") "
+ "isn't associated with any Form");
}
return m_form;
}
/**
* Sets the <tt>ONFOCUS</tt> attribute for the HTML tags that compose
* this element.
* Sets the <tt>ONFOCUS</tt> attribute for the HTML tags that compose this element.
*/
public void setOnFocus(String javascriptCode) {
setAttribute(ON_FOCUS,javascriptCode);
setAttribute(ON_FOCUS, javascriptCode);
}
/**
* Sets the <tt>ONBLUR</tt> attribute for the HTML tags that compose
* this element.
* Sets the <tt>ONBLUR</tt> attribute for the HTML tags that compose this element.
*/
public void setOnBlur(String javascriptCode) {
setAttribute(ON_BLUR,javascriptCode);
setAttribute(ON_BLUR, javascriptCode);
}
/**
* Sets the <tt>ONSELECT</tt> attribute for the HTML tags that compose
* this element.
* Sets the <tt>ONSELECT</tt> attribute for the HTML tags that compose this element.
*/
public void setOnSelect(String javascriptCode) {
setAttribute(ON_SELECT,javascriptCode);
setAttribute(ON_SELECT, javascriptCode);
}
/**
* Sets the <tt>ONCHANGE</tt> attribute for the HTML tags that compose
* this element.
* Sets the <tt>ONCHANGE</tt> attribute for the HTML tags that compose this element.
*/
public void setOnChange(String javascriptCode) {
setAttribute(ON_CHANGE,javascriptCode);
setAttribute(ON_CHANGE, javascriptCode);
}
/**
* Sets the <tt>ON_KEY_UP</tt> attribute for the HTML tags that compose
* this element.
**/
* Sets the <tt>ON_KEY_UP</tt> attribute for the HTML tags that compose this element.
*
*/
public void setOnKeyUp(String javascriptCode) {
setAttribute(ON_KEY_UP, javascriptCode);
}
/**
* Sets the default value in the parameter model for this element. This
* is a static property and this method should not be invoked at request time
* (not even in a PrintListener).
* Sets the default value in the parameter model for this element. This is a static property and
* this method should not be invoked at request time (not even in a PrintListener).
*/
public void setDefaultValue(Object value) {
m_parameterModel.setDefaultValue(value);
}
/**
* Marks this widget as readonly, which has the effect of
* preventing the user from modifying the widget's contents.
* This method can only be called on unlocked widgets.
* Marks this widget as readonly, which has the effect of preventing the user from modifying the
* widget's contents. This method can only be called on unlocked widgets.
*/
public void setReadOnly() {
Assert.isUnlocked(this);
@ -366,10 +346,9 @@ public abstract class Widget extends BlockStylable implements Cloneable,
}
/**
* Marks this widget as disabled, which has the effect of preventing the
* widget's value being submitted with the form, and will typically cause
* the widget to be 'grayed out' on the form. This method can only be
* called on unlocked widgets.
* Marks this widget as disabled, which has the effect of preventing the widget's value being
* submitted with the form, and will typically cause the widget to be 'grayed out' on the form.
* This method can only be called on unlocked widgets.
*/
public void setDisabled() {
Assert.isUnlocked(this);
@ -378,8 +357,9 @@ public abstract class Widget extends BlockStylable implements Cloneable,
/**
* Sets a popup hint for the widget.
* @deprecated refactor to use a GlobalizedMessage instead and use
* setHint(GlobalizedMessage hint)
*
* @deprecated refactor to use a GlobalizedMessage instead and use setHint(GlobalizedMessage
* hint)
*/
public void setHint(String hint) {
Assert.isUnlocked(this);
@ -391,7 +371,7 @@ public abstract class Widget extends BlockStylable implements Cloneable,
*/
public void setHint(GlobalizedMessage hint) {
Assert.isUnlocked(this);
setAttribute("hint", (String)hint.localize() );
setAttribute("hint", (String) hint.localize());
}
/**
@ -408,13 +388,12 @@ public abstract class Widget extends BlockStylable implements Cloneable,
return m_label;
}
/**
* Gets the default value in the parameter model for this element.
*/
public String getDefaultValue() {
Object o = m_parameterModel.getDefaultValue();
if (o==null) {
if (o == null) {
return null;
}
return o.toString();
@ -425,29 +404,28 @@ public abstract class Widget extends BlockStylable implements Cloneable,
}
/**
* The "pass in" property determines whether the value for this
* parameter is generally passed in from the outside. If this property
* is <code>true</code>, the model always tries to get the parameter
* value from the request, no matter whether the request is the initial
* request or a submission of the form to which the widget belongs.
* The "pass in" property determines whether the value for this parameter is generally passed in
* from the outside. If this property is <code>true</code>, the model always tries to get the
* parameter value from the request, no matter whether the request is the initial request or a
* submission of the form to which the widget belongs.
*
* <p> If this property is <code>false</code>, the parameter value is
* only read from the request if it is a submission of the form
* containing the widget.
* <p>
* If this property is <code>false</code>, the parameter value is only read from the request if
* it is a submission of the form containing the widget.
*
* <p> By default, this property is <code>false</code>.
* <p>
* By default, this property is <code>false</code>.
*
* @return <code>true</code> if an attempt should always be made to
* retrieve the parameter value from the request.
* @return <code>true</code> if an attempt should always be made to retrieve the parameter value
* from the request.
*/
public final boolean isPassIn() {
return getParameterModel().isPassIn();
}
/**
* Set whether this parameter should be treated as a "pass in"
* parameter. This is a static property of the ParameterModel
* and this method should not be invoked at request-time.
* Set whether this parameter should be treated as a "pass in" parameter. This is a static
* property of the ParameterModel and this method should not be invoked at request-time.
*
* @see #isPassIn
* @param v <code>true</code> if this parameter is a pass in parameter.
@ -458,9 +436,8 @@ public abstract class Widget extends BlockStylable implements Cloneable,
}
/**
* The ParameterModel is normally set via the constructors. This method is only
* rarely needed. Please note that the previous ParameterModel and all its
* listeners will be lost.
* The ParameterModel is normally set via the constructors. This method is only rarely needed.
* Please note that the previous ParameterModel and all its listeners will be lost.
*/
public final void setParameterModel(ParameterModel parameterModel) {
Assert.isUnlocked(this);
@ -468,11 +445,10 @@ public abstract class Widget extends BlockStylable implements Cloneable,
}
/**
* Allows access to underlying parameterModel. The ParameterModel contains
* static (request-independent) properties of a Widget such as its name,
* default value and its listeners. The ParameterModel can not be modified
* once Page.lock() has been invoked (not even in a PrintListener). This is done
* after the Page has been built, normally at server startup.
* Allows access to underlying parameterModel. The ParameterModel contains static
* (request-independent) properties of a Widget such as its name, default value and its
* listeners. The ParameterModel can not be modified once Page.lock() has been invoked (not even
* in a PrintListener). This is done after the Page has been built, normally at server startup.
*/
public final ParameterModel getParameterModel() {
return m_parameterModel;
@ -480,23 +456,23 @@ public abstract class Widget extends BlockStylable implements Cloneable,
/**
* <p>
* This method creates the DOM for the widget. The method is called
* by the Bebop framework and should not be invoked by application
* developers.
* This method creates the DOM for the widget. The method is called by the Bebop framework and
* should not be invoked by application developers.
* </p>
*
* <p>
* The method first fires the print event allowing application developers to set
* certain properties of the Widget at request time in a PrintListener.
* The methods generateWidget and
* The method first fires the print event allowing application developers to set certain
* properties of the Widget at request time in a PrintListener. The methods generateWidget and
* generateErrors will then be invoked to generate either of the following
* </p>
*
* <p><code>&lt;bebop:formErrors message=...>
* <p>
* <code>&lt;bebop:formErrors message=...>
* &lt;/bebop:formErrors></code>
* </p>
*
* <p><code>&lt;bebop:formWidget name=... type=... value=... [onXXX=...]>
* <p>
* <code>&lt;bebop:formWidget name=... type=... value=... [onXXX=...]>
* &lt;/bebop:formWidget></code>
* </p>
*
@ -513,13 +489,13 @@ public abstract class Widget extends BlockStylable implements Cloneable,
protected Widget firePrintEvent(PageState state) {
Widget w = this;
if ( m_printListener != null ) {
if (m_printListener != null) {
try {
w = (Widget) this.clone();
w.setForm(m_form);
m_printListener.prepare(new PrintEvent(this, state, w));
} catch ( CloneNotSupportedException e ) {
} catch (CloneNotSupportedException e) {
// FIXME: Failing silently here isn't so great
// It probably indicates a serious programming error
w = this;
@ -528,34 +504,39 @@ public abstract class Widget extends BlockStylable implements Cloneable,
return w;
}
/** The XML tag.
* @return The tag to be used for the top level DOM element
* generated for this type of Widget. */
protected String getElementTag()
{
/**
* The XML tag.
*
* @return The tag to be used for the top level DOM element generated for this type of Widget.
*/
protected String getElementTag() {
return BEBOP_FORMWIDGET;
}
/**
* Generates the DOM for the given widget.
* <p>Generates DOM fragment:
* <p><code>&lt;bebop:formWidget name=... type=... value=... [onXXX=...]>
* &lt;/bebop:formWidget></code> */
protected void generateWidget ( PageState state, Element parent ) {
* <p>
* Generates DOM fragment:
* <p>
* <code>&lt;bebop:formWidget name=... type=... value=... [onXXX=...]>
* &lt;/bebop:formWidget></code>
*/
protected void generateWidget(PageState state, Element parent) {
Element widget = parent.newChildElement(getElementTag(), BEBOP_XML_NS);
widget.addAttribute("type", getType());
widget.addAttribute("name", getName());
if (m_label != null)
if (m_label != null) {
widget.addAttribute("label",
(String)m_label.localize(state.getRequest()));
(String) m_label.localize(state.getRequest()));
}
exportAttributes(widget);
String value = null;
ParameterData p = getParameterData(state);
if ( p != null ) {
if (p != null) {
value = p.marshal();
}
if ( value == null ) {
if (value == null) {
value = "";
}
widget.addAttribute("value", value);
@ -563,28 +544,28 @@ public abstract class Widget extends BlockStylable implements Cloneable,
/**
* Generates the XML for the given widget
* <p>Generates XML fragment:
* <p><code>&lt;bebop:formErrors message=... id=name>
* <p>
* Generates XML fragment:
* <p>
* <code>&lt;bebop:formErrors message=... id=name>
* &lt;/bebop:formErrors></code>
*/
protected void generateErrors (PageState state, Element parent) {
protected void generateErrors(PageState state, Element parent) {
Iterator i = getErrors(state);
while (i.hasNext()) {
Element errors = parent.newChildElement(BEBOP_FORMERRORS, BEBOP_XML_NS);
errors.addAttribute("message",
(String) ((GlobalizedMessage)
i.next()).localize(state.getRequest())
(String) ((GlobalizedMessage) i.next()).localize(state.getRequest())
);
errors.addAttribute("id", getName());
}
}
/**
* Get the value associated with this widget in the request described by
* <code>ps</code>. The type of the returned object depends on the
* <code>ParameterModel</code> underlying this widget. This method is
* typically called in a FormProcessListener to access the value that was
* Get the value associated with this widget in the request described by <code>ps</code>. The
* type of the returned object depends on the <code>ParameterModel</code> underlying this
* widget. This method is typically called in a FormProcessListener to access the value that was
* submitted for a Widget in the Form.
*
* @param ps describes the request currently being processed
@ -604,22 +585,20 @@ public abstract class Widget extends BlockStylable implements Cloneable,
} else {
data = p.getValue();
}
return (data==null) ? getDefaultValue() : data;
return (data == null) ? getDefaultValue() : data;
}
/**
* Set the value of the parameter associated with this widget to a new
* value. The exact type of <code>value</code> depends on the
* <code>ParameterModel</code> underlying the widget. This method is
* typically called in a FormInitListener to initialize the value of
* a Widget in the Form at request time.
* Set the value of the parameter associated with this widget to a new value. The exact type of
* <code>value</code> depends on the <code>ParameterModel</code> underlying the widget. This
* method is typically called in a FormInitListener to initialize the value of a Widget in the
* Form at request time.
*
* @pre ps != null
* @post value == getValue(ps)
*
* @throws IllegalStateExeption the form to which the widget belongs has
* not been processed yet.
* @throws IllegalStateExeption the form to which the widget belongs has not been processed yet.
*/
public void setValue(PageState ps, Object value)
throws IllegalStateException {
@ -632,12 +611,12 @@ public abstract class Widget extends BlockStylable implements Cloneable,
if (session != null && session.getAttribute(getName()) != null) {
session.setAttribute(getName(), value);
}
if (p!=null) {
if (p != null) {
p.setValue(value);
} else {
throw new IllegalStateException("Cannot set value for widget '" +
getName() + "': corresponding form '"
throw new IllegalStateException("Cannot set value for widget '" + getName()
+ "': corresponding form '"
+ getForm().getName()
+ "' has not been processed yet.");
}
@ -646,7 +625,7 @@ public abstract class Widget extends BlockStylable implements Cloneable,
protected Iterator getErrors(PageState ps) {
Assert.exists(ps, "PageState");
FormData f = getForm().getFormData(ps);
if (f!=null) {
if (f != null) {
return f.getErrors(getName());
}
return Collections.EMPTY_LIST.iterator();
@ -666,11 +645,10 @@ public abstract class Widget extends BlockStylable implements Cloneable,
}
/**
* Respond to an incoming request by calling <code>respond</code> on the
* form to which the widget belongs. This method is called
* by the Bebop framework and should not be invoked by application
* developers. It is somewhat questionable that
* this method should ever be called, rather than having {@link
* Respond to an incoming request by calling <code>respond</code> on the form to which the
* widget belongs. This method is called by the Bebop framework and should not be invoked by
* application developers. It is somewhat questionable that this method should ever be called,
* rather than having {@link
* Form#respond Form.respond()} called directly.
*
* @pre state != null
@ -688,8 +666,8 @@ public abstract class Widget extends BlockStylable implements Cloneable,
}
/**
* Specify a Widget.ValidationGuard implementation to use to determine if
* this widget should run its validation listeners.
* Specify a Widget.ValidationGuard implementation to use to determine if this widget should run
* its validation listeners.
*
* @param guard the Widget.ValidationGuard.
*/
@ -699,10 +677,11 @@ public abstract class Widget extends BlockStylable implements Cloneable,
}
/**
* Inner interface used to determine if the validation listeners should be
* run for this widget or not.
* Inner interface used to determine if the validation listeners should be run for this widget
* or not.
*/
public interface ValidationGuard {
boolean shouldValidate(PageState ps);
}

View File

@ -3,9 +3,7 @@ package com.arsdigita.navigation.ui.object;
import com.arsdigita.categorization.Category;
import com.arsdigita.categorization.CategoryCollection;
import com.arsdigita.domain.DomainObjectFactory;
import com.arsdigita.persistence.CompoundFilter;
import com.arsdigita.persistence.DataCollection;
import com.arsdigita.persistence.FilterFactory;
import com.arsdigita.persistence.SessionManager;
import com.arsdigita.xml.Element;
import java.util.ArrayList;
@ -59,28 +57,32 @@ public class CategoryFilter {
public void applyFilter(final DataCollection objects) {
if (!values.isEmpty()) {
final FilterFactory filterFactory = objects.getFilterFactory();
final CompoundFilter compoundFilter = filterFactory.and();
//final FilterFactory filterFactory = objects.getFilterFactory();
//final CompoundFilter compoundFilter = filterFactory.and();
final List<String> categoryIds = new ArrayList<String>();
for (String value : values) {
if (multiple) {
//When using multiple search we assume text input for now
if (catNameToCatId.containsKey(value)) {
final com.arsdigita.persistence.Filter filter = filterFactory.in(
"parent.id", "com.arsdigita.categorization.objectIDsInSubtree");
//filter.set("categoryID", value);
filter.set("categoryID", catNameToCatId.get(value));
compoundFilter.addFilter(filter);
// final com.arsdigita.persistence.Filter filter = filterFactory.in(
// "parent.id", "com.arsdigita.categorization.objectIDsInSubtree");
// filter.set("categoryID", catNameToCatId.get(value));
// compoundFilter.addFilter(filter);
categoryIds.add(catNameToCatId.get(value));
}
} else {
//Otherwise, we assume that we get the ID of a single category
final com.arsdigita.persistence.Filter filter = filterFactory.in(
"parent.id", "com.arsdigita.categorization.objectIDsInSubtree");
filter.set("categoryID", value);
compoundFilter.addFilter(filter);
// final com.arsdigita.persistence.Filter filter = filterFactory.in(
// "parent.id", "com.arsdigita.categorization.objectIDsInSubtree");
// filter.set("categoryID", value);
// compoundFilter.addFilter(filter);
categoryIds.add(value);
}
}
objects.addFilter(compoundFilter);
final com.arsdigita.persistence.Filter filter = objects.addInSubqueryFilter("parent.id", "com.arsdigita.categorization.objectIDsInMultipleSubtrees");
filter.set("categoryIDs", categoryIds);
//objects.addFilter(compoundFilter);
}
}
@ -180,6 +182,7 @@ public class CategoryFilter {
}
public void setValue(final String value) {
values.clear();
if ((value != null) && !value.isEmpty()) {
final String[] tokens = value.split(separator);
for (String token : tokens) {
@ -187,5 +190,4 @@ public class CategoryFilter {
}
}
}
}

View File

@ -12,31 +12,28 @@ import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
/**
* <p> An object list variant which can be filtered and sorted by the visitor of
* the website. The available filters and sort options are added in a JSP
* template. There are three kinds of filters yet: </p> <dl>
* <dt><code>TextFilter</code></dt> <dd>This filter filters the object list
* using a user provided string, which is put into the
* <p> An object list variant which can be filtered and sorted by the visitor of the website. The
* available filters and sort options are added in a JSP template. There are three kinds of filters
* yet: </p> <dl>
* <dt><code>TextFilter</code></dt> <dd>This filter filters the object list using a user provided
* string, which is put into the
* <code>WHERE</code> clause with
* <code>LIKE</code> operator. You might use this filter to allow the visitor to
* filter an object list for items with a specific name.</dd>
* <dt><code>SelectFilter</code></dt> <dd>This filter traverses through the
* objects displayed by the list and determines all distinct values of a
* property. The visitor can choose one of this values, and the displayed list
* will only contain items which where the property has the selected value.</dd>
* <dt><code>CompareFilter</code></dt> <dd>This filter also provides selectable
* options. But these options can be configured by the developer in the
* template.</dd> </dl> <p> If there is more than one filter, the values of all
* filters are combined using
* <code>AND</code>. </p> <p> This object list class was developed for
* displaying list of items from the Sci modules (SciPublications and
* SciOrganization). For example, we use this list to provide lists of
* publications which be filtered for publications from a specific year, for a
* specific author and for a specific title. The list can be sorted by the
* titles of the publications, the years of the publications and the (surnames
* of the) authors of the publications. </p> <p> As an example how to use this
* object list in a JSP template here are the relevant parts from the template
* for the publication list: </p>
* <code>LIKE</code> operator. You might use this filter to allow the visitor to filter an object
* list for items with a specific name.</dd>
* <dt><code>SelectFilter</code></dt> <dd>This filter traverses through the objects displayed by the
* list and determines all distinct values of a property. The visitor can choose one of this values,
* and the displayed list will only contain items which where the property has the selected
* value.</dd>
* <dt><code>CompareFilter</code></dt> <dd>This filter also provides selectable options. But these
* options can be configured by the developer in the template.</dd> </dl> <p> If there is more than
* one filter, the values of all filters are combined using
* <code>AND</code>. </p> <p> This object list class was developed for displaying list of items from
* the Sci modules (SciPublications and SciOrganization). For example, we use this list to provide
* lists of publications which be filtered for publications from a specific year, for a specific
* author and for a specific title. The list can be sorted by the titles of the publications, the
* years of the publications and the (surnames of the) authors of the publications. </p> <p> As an
* example how to use this object list in a JSP template here are the relevant parts from the
* template for the publication list: </p>
* <pre>
* {@code
* ...
@ -44,34 +41,26 @@ import org.apache.log4j.Logger;
* classname="com.arsdigita.navigation.ui.object.CustomizableObjectList"/>
* ...
* <jsp:scriptlet>
* CustomizableObjectList objList = (CustomizableObjectList) itemList;
* objList.setDefinition(new CMSDataCollectionDefinition());
* objList.setRenderer(new CMSDataCollectionRenderer());
* CustomizableObjectList objList = (CustomizableObjectList) itemList; objList.setDefinition(new
* CMSDataCollectionDefinition()); objList.setRenderer(new CMSDataCollectionRenderer());
* objList.getDefinition().setObjectType("com.arsdigita.cms.contenttypes.Publication");
* objList.getDefinition().setDescendCategories(false);
* objList.addTextFilter("title", "title");
* objList.addTextFilter("authors.surname", "author");
* objList.addSelectFilter("yearOfPublication", "year", true, true, true, true);
* objList.addSortField("title", "title asc");
* objList.addSortField("yearAsc", "yearOfPublication asc");
* objList.addSortField("yearDesc", "yearOfPublication desc");
* objList.addSortField("authors", "authors.surname asc, authors.givenname asc");
* objList.getDefinition().setDescendCategories(false); objList.addTextFilter("title", "title");
* objList.addTextFilter("authors.surname", "author"); objList.addSelectFilter("yearOfPublication",
* "year", true, true, true, true); objList.addSortField("title", "title asc");
* objList.addSortField("yearAsc", "yearOfPublication asc"); objList.addSortField("yearDesc",
* "yearOfPublication desc"); objList.addSortField("authors", "authors.surname asc,
* authors.givenname asc");
* objList.getDefinition().addOrder(objList.getOrder(request.getParameter("sort")));
*
* objList.getRenderer().setPageSize(20);
* objList.getRenderer().setSpecializeObjects(true);
* objList.getRenderer().setPageSize(20); objList.getRenderer().setSpecializeObjects(true);
*
* </jsp:scriptlet>
* ...
* }
* ... }
* </pre> <p> You may notice the line
* <code>objList.getDefinition().addOrder(objList.getOrder(request.getParameter("sort")));</code>.
* This line may looks a bit weird to you. The reason is that it is not possible
* to access the
* <code>DataCollectionDefinition</code> from the methods in this class. If you
* try call the
* <code>addOrder()</code> from within this class you will cause an locking
* error. </p>
* This line may looks a bit weird to you. The reason is that it is not possible to access the
* <code>DataCollectionDefinition</code> from the methods in this class. If you try call the
* <code>addOrder()</code> from within this class you will cause an locking error. </p>
*
* @author Jens Pelzetter
* @version $Id$
@ -85,16 +74,16 @@ public class CustomizableObjectList extends ComplexObjectList {
private static final Logger logger = Logger.getLogger(
CustomizableObjectList.class);
/**
* The filters for the list. We use an {@link LinkedHashMap} here to
* preserve the insertation order.
* The filters for the list. We use an {@link LinkedHashMap} here to preserve the insertation
* order.
*
*/
private final Map<String, Filter> filters =
new LinkedHashMap<String, Filter>();
private CategoryFilter categoryFilter;
/**
* The available sort fields. We use an {@link LinkedHashMap} here to
* preserve the insertation order.
* The available sort fields. We use an {@link LinkedHashMap} here to preserve the insertation
* order.
*
*/
private final Map<String, String> sortFields =
@ -123,12 +112,11 @@ public class CustomizableObjectList extends ComplexObjectList {
* @param allOptionIsDefault Is the all option the default?
* @param propertyIsNumeric Is the property to filter numeric?
* @return The new filter. Options can be added to the filter by calling the
* {@link CompareFilter#addOption(java.lang.String, java.lang.String)} or
* the
* {@link CompareFilter#addOption(java.lang.String, java.lang.String)} or the
* {@link CompareFilter#addOption(java.lang.String, com.arsdigita.navigation.ui.object.CompareFilter.Operators, java.lang.String)}
* method.
* @see CompareFilter#CompareFilter(java.lang.String, java.lang.String,
* boolean, boolean, boolean)
* @see CompareFilter#CompareFilter(java.lang.String, java.lang.String, boolean, boolean,
* boolean)
*
*/
public CompareFilter addCompareFilter(final String property,
@ -158,8 +146,8 @@ public class CustomizableObjectList extends ComplexObjectList {
* @param allOptionIsDefault Is the all option the default.
* @param propertyIsNumeric Is the property numeric?
* @see SelectFilter#SelectFilter(java.lang.String, java.lang.String,
* com.arsdigita.navigation.ui.object.CustomizableObjectList, boolean,
* boolean, boolean, boolean)
* com.arsdigita.navigation.ui.object.CustomizableObjectList, boolean, boolean, boolean,
* boolean)
*/
public void addSelectFilter(final String property,
final String label,
@ -212,9 +200,8 @@ public class CustomizableObjectList extends ComplexObjectList {
/**
* This overwritten version of the
* <code>getObjects</code> method evaluates the parameters in HTTP request
* for the filters and creates an appropriate SQL filter and sets this
* filter.
* <code>getObjects</code> method evaluates the parameters in HTTP request for the filters and
* creates an appropriate SQL filter and sets this filter.
*
* @param request
* @param response
@ -281,10 +268,9 @@ public class CustomizableObjectList extends ComplexObjectList {
/**
* <p> Generates the XML for the list. The root element for the list is
* <code>customizableObjectList</code>. The available filters are put into a
* <code>filters</code> element. </p> <p> The available sort fields are put
* into a
* <code>sortFields</code> element. This element has also an attribute
* indicating the current selected sort field. </p>
* <code>filters</code> element. </p> <p> The available sort fields are put into a
* <code>sortFields</code> element. This element has also an attribute indicating the current
* selected sort field. </p>
*
* @param request
* @param response
@ -331,7 +317,9 @@ public class CustomizableObjectList extends ComplexObjectList {
if (categoryFilter != null) {
final String value = Globalization.decodeParameter(request, categoryFilter.getLabel());
if ((value != null) && !value.isEmpty()) {
if ((value == null) || value.isEmpty()) {
categoryFilter.setValue("");
} else {
categoryFilter.setValue(value);
}
}
@ -372,5 +360,4 @@ public class CustomizableObjectList extends ComplexObjectList {
return content;
}
}