diff --git a/ccm-cms/src/com/arsdigita/cms/CMSResources.properties b/ccm-cms/src/com/arsdigita/cms/CMSResources.properties index 83b8d7277..43f784851 100755 --- a/ccm-cms/src/com/arsdigita/cms/CMSResources.properties +++ b/ccm-cms/src/com/arsdigita/cms/CMSResources.properties @@ -1068,3 +1068,5 @@ cms.ui.move.category=Move category "{0}" to cms.ui.category.move=Move category cms.ui.category.cantmoved=This category can't be moved cms.ui.authoring.error_conflicts_with_this_url=There are conflicts with this URL. Specifically, there is at least one item in the same category as this item with the name (url) of +cms.ui.search.help=To search for content items, please enter at least 3 letters into the search field. You can narrow the result by using additional parameters. +cms.ui.search.no_results=Sorry. Not content items found which match your search. diff --git a/ccm-cms/src/com/arsdigita/cms/CMSResources_de.properties b/ccm-cms/src/com/arsdigita/cms/CMSResources_de.properties index d2f8e3412..5b1d7c3e4 100755 --- a/ccm-cms/src/com/arsdigita/cms/CMSResources_de.properties +++ b/ccm-cms/src/com/arsdigita/cms/CMSResources_de.properties @@ -1062,3 +1062,5 @@ cms.ui.move.category=Verschiebe Kategorie "{0}" nach cms.ui.category.move=Kategorie verschieben cms.ui.category.cantmoved=Diese Kategorie kann nicht verschoben werden cms.ui.authoring.error_conflicts_with_this_url=Es gibt Konflikte mit dieser URL. Insbesondere gibt es mindestens ein Dokument in der gleichen Kategorie wie dieser mit dem Namen (URL) +cms.ui.search.help=Geben sie mindestens drei Buchstaben ein, um nach Content Items zu suchen. Sie k\u00f6nnen das Ergebnis mit weiteren Parametern einschr\u00e4nken. +cms.ui.search.no_results=Es wurden keine Content Items gefunden, die Ihren Suchparametern entsprechen diff --git a/ccm-cms/src/com/arsdigita/cms/CMSResources_en_GB.properties b/ccm-cms/src/com/arsdigita/cms/CMSResources_en_GB.properties index 331817989..e5d4d0d05 100755 --- a/ccm-cms/src/com/arsdigita/cms/CMSResources_en_GB.properties +++ b/ccm-cms/src/com/arsdigita/cms/CMSResources_en_GB.properties @@ -116,3 +116,5 @@ cms.ui.move.category=Move category "{0}" to cms.ui.category.move=Move category cms.ui.category.cantmoved=This category can't be moved cms.ui.authoring.error_conflicts_with_this_url=There are conflicts with this URL. Specifically, there is at least one item in the same category as this item with the name (url) of +cms.ui.search.help= +cms.ui.search.no_results= diff --git a/ccm-cms/src/com/arsdigita/cms/CMSResources_fr.properties b/ccm-cms/src/com/arsdigita/cms/CMSResources_fr.properties index 9eae1f3b7..011adb877 100755 --- a/ccm-cms/src/com/arsdigita/cms/CMSResources_fr.properties +++ b/ccm-cms/src/com/arsdigita/cms/CMSResources_fr.properties @@ -590,3 +590,5 @@ cms.ui.move.category=Move category "{0}" to cms.ui.category.move=Move category cms.ui.category.cantmoved=This category can't be moved cms.ui.authoring.error_conflicts_with_this_url=There are conflicts with this URL. Specifically, there is atleast one item in the same category as this item with the name (url) of +cms.ui.search.help= +cms.ui.search.no_results= diff --git a/ccm-cms/src/com/arsdigita/cms/ui/ItemSearchPopup.java b/ccm-cms/src/com/arsdigita/cms/ui/ItemSearchPopup.java index 95bf11e1d..c60bcb163 100755 --- a/ccm-cms/src/com/arsdigita/cms/ui/ItemSearchPopup.java +++ b/ccm-cms/src/com/arsdigita/cms/ui/ItemSearchPopup.java @@ -22,6 +22,7 @@ import com.arsdigita.bebop.Component; import com.arsdigita.bebop.Page; import com.arsdigita.bebop.PageState; import com.arsdigita.bebop.parameters.StringParameter; +import com.arsdigita.cms.util.GlobalizationUtil; import com.arsdigita.persistence.OID; import com.arsdigita.xml.Element; @@ -105,6 +106,8 @@ public class ItemSearchPopup extends ItemSearch { public PopupResultsPane(QueryGenerator generator) { super(generator); setRelativeURLs(true); + setSearchHelpMsg(GlobalizationUtil.globalize("cms.ui.search.help")); + setNoResultsMsg(GlobalizationUtil.globalize("cms.ui.search.no_results")); } @Override diff --git a/ccm-cms/src/com/arsdigita/cms/ui/ItemSearchSection.java b/ccm-cms/src/com/arsdigita/cms/ui/ItemSearchSection.java index 6e86516a3..7dbe1c6e1 100755 --- a/ccm-cms/src/com/arsdigita/cms/ui/ItemSearchSection.java +++ b/ccm-cms/src/com/arsdigita/cms/ui/ItemSearchSection.java @@ -29,8 +29,10 @@ import com.arsdigita.bebop.PageState; import com.arsdigita.bebop.event.FormProcessListener; import com.arsdigita.bebop.event.FormSectionEvent; import com.arsdigita.bebop.parameters.BigDecimalParameter; +import com.arsdigita.cms.ContentItem; import com.arsdigita.cms.ContentType; import com.arsdigita.cms.ui.search.ItemQueryComponent; +import com.arsdigita.cms.util.GlobalizationUtil; import com.arsdigita.search.ui.ResultsPane; import com.arsdigita.search.ui.QueryGenerator; @@ -139,6 +141,8 @@ public class ItemSearchSection extends FormSection protected Component createResultsPane(QueryGenerator generator) { ResultsPane pane = new ResultsPane(generator); pane.setRelativeURLs(true); + pane.setSearchHelpMsg(GlobalizationUtil.globalize("cms.ui.search.help")); + pane.setNoResultsMsg(GlobalizationUtil.globalize("cms.ui.search.no_results")); return pane; } diff --git a/ccm-cms/src/com/arsdigita/cms/ui/ItemSearchSectionInline.java b/ccm-cms/src/com/arsdigita/cms/ui/ItemSearchSectionInline.java index cd58cf0e2..85197b28a 100755 --- a/ccm-cms/src/com/arsdigita/cms/ui/ItemSearchSectionInline.java +++ b/ccm-cms/src/com/arsdigita/cms/ui/ItemSearchSectionInline.java @@ -27,6 +27,7 @@ import com.arsdigita.toolbox.ui.OIDParameter; import com.arsdigita.persistence.OID; import com.arsdigita.cms.ContentItem; import com.arsdigita.cms.ContentType; +import com.arsdigita.cms.util.GlobalizationUtil; import com.arsdigita.domain.DomainObjectFactory; import com.arsdigita.globalization.GlobalizedMessage; import com.arsdigita.xml.Element; @@ -154,6 +155,8 @@ public class ItemSearchSectionInline extends ItemSearchSection { public InlineResultsPane(QueryGenerator query) { super(query); setRelativeURLs(true); + setSearchHelpMsg(GlobalizationUtil.globalize("cms.ui.search.help")); + setNoResultsMsg(GlobalizationUtil.globalize("cms.ui.search.no_results")); } @Override diff --git a/ccm-cms/src/com/arsdigita/cms/ui/authoring/BasicItemForm.java b/ccm-cms/src/com/arsdigita/cms/ui/authoring/BasicItemForm.java index d93f9c532..e8d5786cf 100755 --- a/ccm-cms/src/com/arsdigita/cms/ui/authoring/BasicItemForm.java +++ b/ccm-cms/src/com/arsdigita/cms/ui/authoring/BasicItemForm.java @@ -51,16 +51,16 @@ import java.util.ArrayList; import java.util.Collection; /** - * A form for editing subclasses of ContentItem. This is just a convenience - * class. + * A form for editing subclasses of ContentItem. This is just a convenience class. * * @author Stanislav Freidin (stas@arsdigita.com) * @version $Revision: #13 $ $DateTime: 2004/08/17 23:15:09 $ - **/ + * + */ public abstract class BasicItemForm extends FormSection - implements FormInitListener, - FormProcessListener, - FormValidationListener { + implements FormInitListener, + FormProcessListener, + FormValidationListener { private static final Logger s_log = Logger.getLogger(BasicItemForm.class); private final ItemSelectionModel m_itemModel; @@ -73,14 +73,14 @@ public abstract class BasicItemForm extends FormSection /** * Construct a new BasicItemForm with 2 ColumnPanels and add basic content. - * - * The left Panel is used for Labels, the right Panel for values. - * - * * - * @param formName the name of this form - * @param itemModel The {@link ItemSelectionModel} which will - * be responsible for loading the current item + * The left Panel is used for Labels, the right Panel for values. + * + * + * + * @param formName the name of this form + * @param itemModel The {@link ItemSelectionModel} which will be responsible for loading the + * current item */ public BasicItemForm(String formName, ItemSelectionModel itemModel) { super(new ColumnPanel(2)); @@ -108,23 +108,22 @@ public abstract class BasicItemForm extends FormSection addProcessListener(this); addValidationListener(this); } - + /** - * Construct a new BasicItemForm with a specified number of ColumnPanels - * and without any content + * Construct a new BasicItemForm with a specified number of ColumnPanels and without any content * - * @param formName the name of this form + * @param formName the name of this form * @param columnPanel the columnpanel of the form - * @param itemModel The {@link ItemSelectionModel} which will - * be responsible for loading the current item + * @param itemModel The {@link ItemSelectionModel} which will be responsible for loading the + * current item */ public BasicItemForm(String formName, ColumnPanel columnPanel, ItemSelectionModel itemModel) { super(columnPanel); - - m_widgetSection = new FormSection(new ColumnPanel(columnPanel.getNumCols(), - true)); + + m_widgetSection = new FormSection(new ColumnPanel(columnPanel.getNumCols(), + true)); super.add(m_widgetSection, ColumnPanel.INSERT); m_itemModel = itemModel; } @@ -137,30 +136,28 @@ public abstract class BasicItemForm extends FormSection super.add(m_saveCancelSection, ColumnPanel.FULL_WIDTH | ColumnPanel.LEFT); } - /** - * Currently, to insert javascript code the Label Widget is "abused". + * Currently, to insert javascript code the Label Widget is "abused". */ private Label m_script = new Label( "", false); /** - * Add basic widgets to the form. - * - * Widgets added are 'title' and 'name (url)' which are part of any content - * item. - * Child classes will override this method to perform all their widget-adding - * needs but may use super() to add the basic widgets. + * Add basic widgets to the form. + * + * Widgets added are 'title' and 'name (url)' which are part of any content item. Child classes + * will override this method to perform all their widget-adding needs but may use super() to add + * the basic widgets. */ protected void addWidgets() { //add(new FormErrorDisplay(this), ColumnPanel.FULL_WIDTH | ColumnPanel.LEFT); - + //add(new Label("id")); final Hidden id = new Hidden(CONTENT_ITEM_ID); - //final TextField id = new TextField(CONTENT_ITEM_ID); + //final TextField id = new TextField(CONTENT_ITEM_ID); add(id); - + // JavaScript auto-name generation is off by default. // It is turned on under the following circumstances // @@ -172,7 +169,6 @@ public abstract class BasicItemForm extends FormSection // created you don't want to subsequently change it since // it breaks URLs & potentially overwrites the user's // customizations. - // For some content types it is maybe useful to change the label of the // title field to something different than 'title'. // This can nowbe done by overwriting the getTitleLabel() method. @@ -184,8 +180,8 @@ public abstract class BasicItemForm extends FormSection + " defaulting = true; this.form." + NAME + ".value = urlize(this.value); }"); titleWidget.setOnKeyUp( - "if (defaulting) { this.form." + NAME - + ".value = urlize(this.value) }"); + "if (defaulting) { this.form." + NAME + + ".value = urlize(this.value) }"); titleWidget.setLabel(getTitleLabel()); titleWidget.setHint(getTitleHint()); add(titleWidget); @@ -200,10 +196,10 @@ public abstract class BasicItemForm extends FormSection nameWidget.setMaxLength(190); nameWidget.setOnFocus("defaulting = false"); nameWidget.setOnBlur( - "if (this.value == '') " - + "{ defaulting = true; this.value = urlize(this.form." + TITLE - + ".value) } " + " else { this.value = urlize(this.value); }"); - nameWidget.addValidationListener(new NotNullValidationListener()); + "if (this.value == '') " + + "{ defaulting = true; this.value = urlize(this.form." + TITLE + + ".value) } " + " else { this.value = urlize(this.value); }"); + nameWidget.addValidationListener(new NotNullValidationListener()); nameWidget.setHint(getNameHint()); add(nameWidget); @@ -230,43 +226,46 @@ public abstract class BasicItemForm extends FormSection } /** - * Perform form initialization. Children should override this - * this method to pre-fill the widgets with data, instantiate - * the content item, etc. + * Perform form initialization. Children should override this this method to pre-fill the + * widgets with data, instantiate the content item, etc. + * * @param e + * * @throws FormProcessException */ public abstract void init(FormSectionEvent e) throws FormProcessException; /** - * Process the form. Children should override this method to save - * the user's changes to the database. + * Process the form. Children should override this method to save the user's changes to the + * database. + * * @param e + * * @throws FormProcessException */ public abstract void process(FormSectionEvent e) throws FormProcessException; /** - * Validate the form. Children should override this method to provide - * custom form validation. - * @param e + * Validate the form. Children should override this method to provide custom form validation. + * + * @param e */ public void validate(FormSectionEvent e) throws FormProcessException { // do nothing } - + /** - * Ensure that the name of an item is unique within a folder. A "New - * item" form should call this method in the validation listener. + * Ensure that the name of an item is unique within a folder. A "New item" form should call this + * method in the validation listener. * * @param parent the folder in which to check - * @param event the {@link FormSectionEvent} which was passed to the - * validation listener - * @throws FormProcessException if the folder already contains an item - * with the name the user provided on the input form. + * @param event the {@link FormSectionEvent} which was passed to the validation listener + * + * @throws FormProcessException if the folder already contains an item with the name the user + * provided on the input form. */ public void validateNameUniqueness(Folder parent, FormSectionEvent event) - throws FormProcessException { + throws FormProcessException { FormData data = event.getFormData(); String newName = (String) data.get(NAME); @@ -275,15 +274,16 @@ public abstract class BasicItemForm extends FormSection } /** - * + * * @param parent * @param event * @param newName - * @throws FormProcessException + * + * @throws FormProcessException */ public void validateNameUniqueness(Folder parent, FormSectionEvent event, String newName) - throws FormProcessException { + throws FormProcessException { if (newName != null) { final String query = "com.arsdigita.cms.validateUniqueItemName"; DataQuery dq = SessionManager.getSession().retrieveQuery(query); @@ -300,20 +300,24 @@ public abstract class BasicItemForm extends FormSection ContentItem item = null; if (getItemSelectionModel() != null) { item = (ContentItem) getItemSelectionModel(). - getSelectedObject(event.getPageState()); + getSelectedObject(event.getPageState()); } if (item == null) { // this means it is a creation form +// throw new FormProcessException( +// "An item with this name already exists"); throw new FormProcessException( - "An item with this name already exists"); + "cms.ui.authoring.an_item_with_this_name_already_exists"); } Collection list = getAllVersionIDs(item); while (dq.next()) { itemID = (BigDecimal) dq.get("itemID"); if (!list.contains(itemID)) { dq.close(); +// throw new FormProcessException( +// "An item with this name already exists"); throw new FormProcessException( - "An item with this name already exists"); + "cms.ui.authoring.an_item_with_this_name_already_exists"); } } } @@ -321,19 +325,18 @@ public abstract class BasicItemForm extends FormSection } /** - * Ensure that the name of an item is unique within a category. This - * should only be called from the validation listener of an "edit" form. + * Ensure that the name of an item is unique within a category. This should only be called from + * the validation listener of an "edit" form. * - * @param event the {@link FormSectionEvent} which was passed to the - * validation listener - * @param id The id of the item that is being checked. This must no - * be null. - * @throws FormProcessException if the folder already contains an item - * with the name the user provided on the input form. + * @param event the {@link FormSectionEvent} which was passed to the validation listener + * @param id The id of the item that is being checked. This must no be null. + * + * @throws FormProcessException if the folder already contains an item with the name the user + * provided on the input form. */ public void validateNameUniquenessWithinCategory(FormSectionEvent event, BigDecimal id) - throws FormProcessException { + throws FormProcessException { if (id == null) { s_log.warn("Trying to validation the name uniqueness without " + " a valid item is invalid. This method should only " @@ -349,9 +352,8 @@ public abstract class BasicItemForm extends FormSection if (url == null) { return; } - DataQuery query = - SessionManager.getSession().retrieveQuery( - "com.arsdigita.categorization.getAllItemURLsForCategoryFromItem"); + DataQuery query = SessionManager.getSession().retrieveQuery( + "com.arsdigita.categorization.getAllItemURLsForCategoryFromItem"); query.setParameter("itemID", id); query.addEqualsFilter("lower(url)", url.toLowerCase()); if (query.size() > 0) { @@ -359,9 +361,8 @@ public abstract class BasicItemForm extends FormSection // pending or live version of the same item BigDecimal itemID = null; - ContentItem item = - (ContentItem) getItemSelectionModel().getSelectedObject(event. - getPageState()); + ContentItem item = (ContentItem) getItemSelectionModel().getSelectedObject(event. + getPageState()); Collection list = getAllVersionIDs(item); try { while (query.next()) { @@ -369,7 +370,7 @@ public abstract class BasicItemForm extends FormSection if (!list.contains(itemID)) { StringBuffer buffer = new StringBuffer((String) GlobalizationUtil .globalize("cms.ui.authoring.error_conflicts_with_this_url") - .localize() ); + .localize()); buffer.append(url); throw new FormProcessException(buffer.toString()); } @@ -402,75 +403,74 @@ public abstract class BasicItemForm extends FormSection * Adds a component to this container. * * @param pc the component to add to this BasicPageForm - * */ + * + */ @Override public void add(Component pc) { m_widgetSection.add(pc); } /** - * Adds a component with the specified layout constraints to this - * container. Layout constraints are defined in each layout container as - * static ints. Use a bitwise OR to specify multiple constraints. + * Adds a component with the specified layout constraints to this container. Layout constraints + * are defined in each layout container as static ints. Use a bitwise OR to specify multiple + * constraints. * - * @param pc the component to add to this container + * @param pc the component to add to this container * - * @param constraints layout constraints (a - * bitwise OR of static ints in the particular layout) - * */ + * @param constraints layout constraints (a bitwise OR of static ints in the particular layout) + * + */ @Override public void add(Component pc, int constraints) { m_widgetSection.add(pc, constraints); } /** - * jensp, 2011-01-28 - * This method can be overridden to change the label of the title field. - * To change to label of the title field can be useful for some - * content types. For example, for an organization the label "Title" for - * the field is may confusing for the normal user. For such a content type, - * the label would be changed to something like "Name of the organization". + * jensp, 2011-01-28 This method can be overridden to change the label of the title field. To + * change to label of the title field can be useful for some content types. For example, for an + * organization the label "Title" for the field is may confusing for the normal user. For such a + * content type, the label would be changed to something like "Name of the organization". * * @return (Content for the) Label for the title field as string */ protected GlobalizedMessage getTitleLabel() { - return GlobalizationUtil.globalize("cms.contenttypes.ui.title"); + return GlobalizationUtil.globalize("cms.contenttypes.ui.title"); } /** - * Provides the text for the user hint providing some detailed information - * how to use this widget. - * + * Provides the text for the user hint providing some detailed information how to use this + * widget. + * * This method can be overwritten to adjust the text for some content types. * {@link #getTitleLabel()} - * - * @return + * + * @return */ protected GlobalizedMessage getTitleHint() { - return GlobalizationUtil.globalize("cms.contenttypes.ui.title_hint"); + return GlobalizationUtil.globalize("cms.contenttypes.ui.title_hint"); } /** - * jensp, 2011-01-28 - * This method does the same as {@link #getTitleLabel() } for the label of - * the name (URL) field. + * jensp, 2011-01-28 This method does the same as {@link #getTitleLabel() } for the label of the + * name (URL) field. * * @return (Content for the) Label for the name field as string */ protected GlobalizedMessage getNameLabel() { - return GlobalizationUtil.globalize("cms.contenttypes.ui.name"); + return GlobalizationUtil.globalize("cms.contenttypes.ui.name"); } /** - * Provides the text for the unser hint providing some detailed information - * how to use this widget. - * + * Provides the text for the unser hint providing some detailed information how to use this + * widget. + * * This method can be overwritten to adjust the text for some content types. * {@link #getNameLabel()} - * - * @return + * + * @return */ protected GlobalizedMessage getNameHint() { - return GlobalizationUtil.globalize("cms.contenttypes.ui.name_hint"); + return GlobalizationUtil.globalize("cms.contenttypes.ui.name_hint"); } + } diff --git a/ccm-core/src/com/arsdigita/bebop/PageErrorDisplay.java b/ccm-core/src/com/arsdigita/bebop/PageErrorDisplay.java index 4e5372d05..e424804e6 100755 --- a/ccm-core/src/com/arsdigita/bebop/PageErrorDisplay.java +++ b/ccm-core/src/com/arsdigita/bebop/PageErrorDisplay.java @@ -28,13 +28,13 @@ import com.arsdigita.globalization.GlobalizedMessage; import java.util.Iterator; /** - * Displays validation errors for the page. These might have occured due to validation - * listeners on some state parameters within the page. + * Displays validation errors for the page. These might have occured due to validation listeners on + * some state parameters within the page. * - * @author Stanislav Freidin + * @author Stanislav Freidin * @version $Id: PageErrorDisplay.java 287 2005-02-22 00:29:02Z sskracic $ */ -public class PageErrorDisplay extends List { +public class PageErrorDisplay extends List { private static final String COLOR = "color"; @@ -46,8 +46,8 @@ public class PageErrorDisplay extends List { } /** - * Constructs a new PageErrorDisplay from the errors - * supplied by a list model builder. + * Constructs a new PageErrorDisplay from the errors supplied by a list model + * builder. * * @param builder the {@link ListModelBuilder} that will supply the errors * @@ -70,6 +70,7 @@ public class PageErrorDisplay extends List { /** * Gets the HTML color of the error messages. + * * @return the HTML color of the error messages. */ public String getTextColor() { @@ -80,23 +81,24 @@ public class PageErrorDisplay extends List { * Determines if there are errors to display. * * @param state the current page state - * @return true if there are any errors to display; - * false otherwise. + * + * @return true if there are any errors to display; false otherwise. */ protected boolean hasErrors(PageState state) { - return(state.getErrors().hasNext()); + return (state.getErrors().hasNext()); } /** - * Generates the XML for this component. If the state has no errors - * in it, does not generate any XML. + * Generates the XML for this component. If the state has no errors in it, does not generate any + * XML. * - * @param state the current page state + * @param state the current page state * @param parent the parent XML element */ public void generateXML(PageState state, Element parent) { - if(hasErrors(state)) + if (hasErrors(state)) { super.generateXML(state, parent); + } } // A private class which builds a ListModel based on form errors @@ -110,6 +112,7 @@ public class PageErrorDisplay extends List { public ListModel makeModel(List l, PageState state) { return new StringIteratorModel(state.getErrors()); } + } // A ListModel which generates items based on an Iterator @@ -126,22 +129,22 @@ public class PageErrorDisplay extends List { } public boolean next() { - if(!m_iter.hasNext()) { + if (!m_iter.hasNext()) { m_i = 0; return false; } - m_error = (GlobalizedMessage)m_iter.next(); + m_error = (GlobalizedMessage) m_iter.next(); ++m_i; return true; } private void checkState() { - if(m_i == 0) { - throw new IllegalStateException ( - "next() has not been called succesfully" - ); + if (m_i == 0) { + throw new IllegalStateException( + "next() has not been called succesfully" + ); } } @@ -154,14 +157,17 @@ public class PageErrorDisplay extends List { checkState(); return Integer.toString(m_i); } + } // A ListCellRenderer that renders labels private static class LabelCellRenderer implements ListCellRenderer { + public Component getComponent(List list, PageState state, Object value, String key, int index, boolean isSelected) { - return new Label((GlobalizedMessage)value); + return new Label((GlobalizedMessage) value); } + } } diff --git a/ccm-core/src/com/arsdigita/search/ui/ResultsPane.java b/ccm-core/src/com/arsdigita/search/ui/ResultsPane.java index f9ee83b7d..b53d3533b 100755 --- a/ccm-core/src/com/arsdigita/search/ui/ResultsPane.java +++ b/ccm-core/src/com/arsdigita/search/ui/ResultsPane.java @@ -21,7 +21,9 @@ package com.arsdigita.search.ui; import com.arsdigita.bebop.SimpleComponent; import com.arsdigita.bebop.PageState; import com.arsdigita.bebop.parameters.IntegerParameter; +import com.arsdigita.bebop.util.GlobalizationUtil; import com.arsdigita.globalization.Globalization; +import com.arsdigita.globalization.GlobalizedMessage; import com.arsdigita.kernel.Party; import com.arsdigita.xml.Element; @@ -44,265 +46,287 @@ import org.apache.log4j.Logger; public class ResultsPane extends SimpleComponent { - private static final Logger s_log = Logger.getLogger(ResultsPane.class); - public static final int PAGE_SIZE = 10; - private int m_pageSize = PAGE_SIZE; - private String m_engine; - private QueryGenerator m_query; - private IntegerParameter m_pageNumber; - private boolean m_relative; + private static final Logger s_log = Logger.getLogger(ResultsPane.class); + public static final int PAGE_SIZE = 10; + private int m_pageSize = PAGE_SIZE; + private String m_engine; + private QueryGenerator m_query; + private IntegerParameter m_pageNumber; + private boolean m_relative; + //jensp 2014-03-04 Allow using classes to set a suitable info messages. + private GlobalizedMessage searchHelpMsg; + private GlobalizedMessage noResultsMsg; - public ResultsPane(QueryGenerator query) { - this(query, null); - } + public ResultsPane(QueryGenerator query) { + this(query, null); + } - /** - * Determines whether the links to the search results will be relative or - * absolute. The default is absolute. - */ - public void setRelativeURLs(boolean relative) { - m_relative = relative; - } + /** + * Determines whether the links to the search results will be relative or absolute. The default + * is absolute. + */ + public void setRelativeURLs(boolean relative) { + m_relative = relative; + } - public ResultsPane(QueryGenerator query, - String engine) { - m_query = query; - m_engine = engine; - m_pageNumber = new IntegerParameter("page"); - m_relative = false; - } + public ResultsPane(QueryGenerator query, + String engine) { + m_query = query; + m_engine = engine; + m_pageNumber = new IntegerParameter("page"); + m_relative = false; + } - @Override - public void generateXML(PageState state, Element parent) { - if (!m_query.hasQuery(state)) { - if (s_log.isDebugEnabled()) { - s_log.debug("No query available, skipping XMl generation"); - } - Element content = Search.newElement("results"); - Element info = content.newChildElement("info"); -// info.setText(GlobalizationUtil.globalize("cms.ui.search_help").localize().toString()); - info.setText("To search for content items, please enter at least 3 letters into the search field. You can narrow the result by using additional parameters."); - parent.addContent(content); - return; - } + public void setSearchHelpMsg(final GlobalizedMessage msg) { + searchHelpMsg = msg; + } - QuerySpecification spec = m_query.getQuerySpecification(state); - ResultSet resultSet = null; - try { - resultSet = m_engine == null - ? Search.process(spec) - : Search.process(spec, Search.DEFAULT_RESULT_CACHE, - m_engine); + public void setNoResultsMsg(final GlobalizedMessage msg) { + noResultsMsg = msg; + } - if (s_log.isDebugEnabled()) { - s_log.debug("Got result set " + resultSet.getClass() - + " count: " + resultSet.getCount()); - } + @Override + public void generateXML(PageState state, Element parent) { + if (!m_query.hasQuery(state)) { + if (s_log.isDebugEnabled()) { + s_log.debug("No query available, skipping XMl generation"); + } + Element content = Search.newElement("results"); + Element info = content.newChildElement("info"); + if (searchHelpMsg == null) { + info.setText( + "To search for content items, please enter at least 3 letters into the search field. You can narrow the result by using additional parameters."); + } else { + //info.setText(GlobalizationUtil.globalize("cms.ui.search_help").localize().toString()); + info.setText(searchHelpMsg.localize().toString()); + } - if (resultSet.getCount() > 0) { + parent.addContent(content); + return; + } - Integer page = (Integer) m_pageNumber.transformValue(state. - getRequest()); - int pageNumber = (page == null ? 1 : page.intValue()); - long objectCount = resultSet.getCount(); - int pageCount = (int) Math.ceil((double) objectCount - / (double) m_pageSize); + QuerySpecification spec = m_query.getQuerySpecification(state); + ResultSet resultSet = null; + try { + resultSet = m_engine == null + ? Search.process(spec) + : Search.process(spec, Search.DEFAULT_RESULT_CACHE, + m_engine); - if (pageNumber < 1) { - pageNumber = 1; - } + if (s_log.isDebugEnabled()) { + s_log.debug("Got result set " + resultSet.getClass() + + " count: " + resultSet.getCount()); + } - if (pageNumber > pageCount) { - pageNumber = (pageCount == 0 ? 1 : pageCount); - } + if (resultSet.getCount() > 0) { - long begin = ((pageNumber - 1) * m_pageSize); - int count = (int) Math.min(m_pageSize, (objectCount - begin)); - long end = begin + count; + Integer page = (Integer) m_pageNumber.transformValue(state. + getRequest()); + int pageNumber = (page == null ? 1 : page.intValue()); + long objectCount = resultSet.getCount(); + int pageCount = (int) Math.ceil((double) objectCount + / (double) m_pageSize); - Iterator results = resultSet.getDocuments(begin, count); + if (pageNumber < 1) { + pageNumber = 1; + } - Element content = Search.newElement("results"); - exportAttributes(content); + if (pageNumber > pageCount) { + pageNumber = (pageCount == 0 ? 1 : pageCount); + } - if (s_log.isDebugEnabled()) { - s_log.debug("Paginator stats\n page number:" + pageNumber - + "\n page count: " + pageCount - + "\n page size: " - + m_pageSize + "\n start " + begin + "\n end: " - + end + "\n count: " + objectCount); - } + long begin = ((pageNumber - 1) * m_pageSize); + int count = (int) Math.min(m_pageSize, (objectCount - begin)); + long end = begin + count; - content.addContent(generatePaginatorXML(state, - m_pageNumber.getName(), - pageNumber, pageCount, - m_pageSize, begin, end, - objectCount)); - content.addContent(generateDocumentsXML(state, results)); + Iterator results = resultSet.getDocuments(begin, count); - parent.addContent(content); - } else { - // No search result, so we don't need a paginator, but we want - // to inform the user, that there are no results for this search - Element content = Search.newElement("results"); - Element info = content.newChildElement("info"); + Element content = Search.newElement("results"); + exportAttributes(content); + + if (s_log.isDebugEnabled()) { + s_log.debug("Paginator stats\n page number:" + pageNumber + + "\n page count: " + pageCount + + "\n page size: " + + m_pageSize + "\n start " + begin + "\n end: " + + end + "\n count: " + objectCount); + } + + content.addContent(generatePaginatorXML(state, + m_pageNumber.getName(), + pageNumber, pageCount, + m_pageSize, begin, end, + objectCount)); + content.addContent(generateDocumentsXML(state, results)); + + parent.addContent(content); + } else { + // No search result, so we don't need a paginator, but we want + // to inform the user, that there are no results for this search + Element content = Search.newElement("results"); + Element info = content.newChildElement("info"); // info.setText(GlobalizationUtil.globalize("cms.ui.search_no_results").localize().toString()); - info.setText("Sorry. Your search returned 0 results."); - parent.addContent(content); - } + if (noResultsMsg == null) { + info.setText("Sorry. Your search returned 0 results."); + } else { + info.setText(noResultsMsg.localize().toString()); + } + parent.addContent(content); + } - } finally { - if (resultSet != null) { - try { - resultSet.close(); - } catch (Exception e) { - /* - * If there is a problem closing the result set this probably means - * it has been closed elsewhere and is probably not fatal. We write - * a line to the error log but otherwise ignore the exception allowing - * the code to continue normally. Any issues willemerge in the log. - */ - s_log.error("Error closing resultset: " + e.getMessage()); - } - } - } - } + } finally { + if (resultSet != null) { + try { + resultSet.close(); + } catch (Exception e) { + /* + * If there is a problem closing the result set this probably means + * it has been closed elsewhere and is probably not fatal. We write + * a line to the error log but otherwise ignore the exception allowing + * the code to continue normally. Any issues willemerge in the log. + */ + s_log.error("Error closing resultset: " + e.getMessage()); + } + } + } + } - protected Element generatePaginatorXML(PageState state, - String pageParam, - int pageNumber, - int pageCount, - int pageSize, - long begin, - long end, - long objectCount) { - Element paginator = Search.newElement("paginator"); - URL url = Web.getContext().getRequestURL(); + protected Element generatePaginatorXML(PageState state, + String pageParam, + int pageNumber, + int pageCount, + int pageSize, + long begin, + long end, + long objectCount) { + Element paginator = Search.newElement("paginator"); + URL url = Web.getContext().getRequestURL(); - ParameterMap map = new ParameterMap(); - Iterator current = url.getParameterMap().keySet().iterator(); - while (current.hasNext()) { - String key = (String) current.next(); - if (key.equals(pageParam)) { - continue; - } - //map.setParameterValues(key, url.getParameterValues(key)); - map.setParameterValues(key, - decodeParameters(url.getParameterValues(key), - state)); - } + ParameterMap map = new ParameterMap(); + Iterator current = url.getParameterMap().keySet().iterator(); + while (current.hasNext()) { + String key = (String) current.next(); + if (key.equals(pageParam)) { + continue; + } + //map.setParameterValues(key, url.getParameterValues(key)); + map.setParameterValues(key, + decodeParameters(url.getParameterValues(key), + state)); + } - paginator.addAttribute("pageParam", m_pageNumber.getName()); - paginator.addAttribute("baseURL", URL.there(url.getPathInfo(), map). - toString()); - paginator.addAttribute("pageNumber", XML.format(new Integer(pageNumber))); - paginator.addAttribute("pageCount", XML.format(new Integer(pageCount))); - paginator.addAttribute("pageSize", XML.format(new Integer(pageSize))); - paginator.addAttribute("objectBegin", XML.format(new Long(begin + 1))); - paginator.addAttribute("objectEnd", XML.format(new Long(end))); - paginator.addAttribute("objectCount", XML.format(new Long(objectCount))); - return paginator; - } + paginator.addAttribute("pageParam", m_pageNumber.getName()); + paginator.addAttribute("baseURL", URL.there(url.getPathInfo(), map). + toString()); + paginator.addAttribute("pageNumber", XML.format(new Integer(pageNumber))); + paginator.addAttribute("pageCount", XML.format(new Integer(pageCount))); + paginator.addAttribute("pageSize", XML.format(new Integer(pageSize))); + paginator.addAttribute("objectBegin", XML.format(new Long(begin + 1))); + paginator.addAttribute("objectEnd", XML.format(new Long(end))); + paginator.addAttribute("objectCount", XML.format(new Long(objectCount))); + return paginator; + } - private String[] decodeParameters(final String[] parameters, - final PageState state) { - final String[] decoded = new String[parameters.length]; + private String[] decodeParameters(final String[] parameters, + final PageState state) { + final String[] decoded = new String[parameters.length]; - for (int i = 0; i < parameters.length; i++) { - decoded[i] = decodeParameter(parameters[i], state); - } + for (int i = 0; i < parameters.length; i++) { + decoded[i] = decodeParameter(parameters[i], state); + } - return decoded; - } + return decoded; + } - private String decodeParameter(final String parameter, - final PageState state) { - String re = state.getRequest().getParameter(Globalization.ENCODING_PARAM_NAME); + private String decodeParameter(final String parameter, + final PageState state) { + String re = state.getRequest().getParameter(Globalization.ENCODING_PARAM_NAME); - if ((re == null) || (re.isEmpty())) { - re = Globalization.getDefaultCharset(); - } + if ((re == null) || (re.isEmpty())) { + re = Globalization.getDefaultCharset(); + } - if ((parameter == null) || (parameter.isEmpty())) { - return parameter; - } else if (Globalization.getDefaultCharset(state.getRequest()).equals(re)) { - return parameter; - } else { - try { - return new String(parameter.getBytes(Globalization.getDefaultCharset( - state.getRequest())), re); - } catch (UnsupportedEncodingException ex) { - s_log.warn("Unsupported encoding.", ex); - return parameter; - } - } - } + if ((parameter == null) || (parameter.isEmpty())) { + return parameter; + } else if (Globalization.getDefaultCharset(state.getRequest()).equals(re)) { + return parameter; + } else { + try { + return new String(parameter.getBytes(Globalization.getDefaultCharset( + state.getRequest())), re); + } catch (UnsupportedEncodingException ex) { + s_log.warn("Unsupported encoding.", ex); + return parameter; + } + } + } - protected Element generateDocumentsXML(PageState state, - Iterator results) { - Element documents = Search.newElement("documents"); + protected Element generateDocumentsXML(PageState state, + Iterator results) { + Element documents = Search.newElement("documents"); - if (s_log.isDebugEnabled()) { - s_log.debug("Outputting documents"); - } - while (results.hasNext()) { - Document doc = (Document) results.next(); - if (s_log.isDebugEnabled()) { - s_log.debug("One doc " + doc.getOID() + " " + doc.getTitle()); - } - documents.addContent(generateDocumentXML(state, doc)); - } + if (s_log.isDebugEnabled()) { + s_log.debug("Outputting documents"); + } + while (results.hasNext()) { + Document doc = (Document) results.next(); + if (s_log.isDebugEnabled()) { + s_log.debug("One doc " + doc.getOID() + " " + doc.getTitle()); + } + documents.addContent(generateDocumentXML(state, doc)); + } - return documents; - } + return documents; + } - protected Element generateDocumentXML(PageState state, - Document doc) { - Element entry = Search.newElement("object"); + protected Element generateDocumentXML(PageState state, + Document doc) { + Element entry = Search.newElement("object"); - String summary = doc.getSummary(); + String summary = doc.getSummary(); - java.net.URL url = doc.getURL(); + java.net.URL url = doc.getURL(); - entry.addAttribute("oid", XML.format(doc.getOID())); - entry.addAttribute("url", XML.format(m_relative ? url.getPath() + "?" - + url.getQuery() - : url.toString())); - entry.addAttribute("score", XML.format(doc.getScore())); - entry.addAttribute("title", XML.format(doc.getTitle())); - if (summary != null) { - entry.addAttribute("summary", XML.format(summary)); - } + entry.addAttribute("oid", XML.format(doc.getOID())); + entry.addAttribute("url", XML.format(m_relative ? url.getPath() + "?" + + url.getQuery() + : url.toString())); + entry.addAttribute("score", XML.format(doc.getScore())); + entry.addAttribute("title", XML.format(doc.getTitle())); + if (summary != null) { + entry.addAttribute("summary", XML.format(summary)); + } - entry.addAttribute("locale", XML.format(doc.getLocale())); + entry.addAttribute("locale", XML.format(doc.getLocale())); - Date creationDate = doc.getCreationDate(); - if (creationDate != null) { - entry.addAttribute("creationDate", XML.format( - creationDate.toString())); - } - Party creationParty = doc.getCreationParty(); - if (creationParty != null) { - entry.addAttribute("creationParty", - XML.format(creationParty.getDisplayName())); - } + Date creationDate = doc.getCreationDate(); + if (creationDate != null) { + entry.addAttribute("creationDate", XML.format( + creationDate.toString())); + } + Party creationParty = doc.getCreationParty(); + if (creationParty != null) { + entry.addAttribute("creationParty", + XML.format(creationParty.getDisplayName())); + } - Date lastModifiedDate = doc.getLastModifiedDate(); - if (lastModifiedDate != null) { - entry.addAttribute("lastModifiedDate", - XML.format(lastModifiedDate)); - } - Party lastModifiedParty = doc.getLastModifiedParty(); - if (lastModifiedParty != null) { - entry.addAttribute("lastModifiedParty", - XML.format(lastModifiedParty.getDisplayName())); - } + Date lastModifiedDate = doc.getLastModifiedDate(); + if (lastModifiedDate != null) { + entry.addAttribute("lastModifiedDate", + XML.format(lastModifiedDate)); + } + Party lastModifiedParty = doc.getLastModifiedParty(); + if (lastModifiedParty != null) { + entry.addAttribute("lastModifiedParty", + XML.format(lastModifiedParty.getDisplayName())); + } - s_log.debug( - "about to add the contentSectionName from search index Doc to search result xml"); - entry.addAttribute("contentSectionName", XML.format(doc. - getContentSection())); + s_log.debug( + "about to add the contentSectionName from search index Doc to search result xml"); + entry.addAttribute("contentSectionName", XML.format(doc. + getContentSection())); + + return entry; + } - return entry; - } } diff --git a/ccm-core/src/com/arsdigita/web/DispatcherServlet.java b/ccm-core/src/com/arsdigita/web/DispatcherServlet.java index f9ee47b1a..4d165f0ff 100755 --- a/ccm-core/src/com/arsdigita/web/DispatcherServlet.java +++ b/ccm-core/src/com/arsdigita/web/DispatcherServlet.java @@ -130,7 +130,9 @@ public class DispatcherServlet extends BaseServlet { s_log.debug("Successfully dispatched to an application"); } else { s_log.debug("Could not dispatch this request to an " + - "application; using the fallback servlet"); + "application; sending 404"); + + sresp.sendError(HttpServletResponse.SC_NOT_FOUND); /* sreq.setAttribute(FALLING_BACK_ATTRIBUTE, Boolean.TRUE); @@ -143,6 +145,8 @@ public class DispatcherServlet extends BaseServlet { m_dispatcher.forward(fallbackDispatcher, sreq, sresp); DeveloperSupport.endStage("BaseDispatcher.forward"); + + */ } } diff --git a/ccm-ldn-search/src/com/arsdigita/london/search/SearchGlobalizationUtil.java b/ccm-ldn-search/src/com/arsdigita/london/search/SearchGlobalizationUtil.java new file mode 100644 index 000000000..54818d475 --- /dev/null +++ b/ccm-ldn-search/src/com/arsdigita/london/search/SearchGlobalizationUtil.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +package com.arsdigita.london.search; + +import com.arsdigita.globalization.Globalized; +import com.arsdigita.globalization.GlobalizedMessage; + +/** + * Compilation of methods to simplify the handling of globalizing keys. + * Basically it adds the name of package's resource bundle files to the + * globalize methods and forwards to GlobalizedMessage, shortening the + * method invocation in the various application classes. + * + * @author yon@arsdigita.com + * @version $Revision$ $Date$ + */ +public class SearchGlobalizationUtil implements Globalized { + + /** Name of Java resource files to handle CMS's globalisation. */ + private static final String BUNDLE_NAME = "com.arsdigita.london.search.SearchResources"; + + /** + * Returns a globalized message using the package specific bundle, + * provided by BUNDLE_NAME. + */ + public static GlobalizedMessage globalize(String key) { + return new GlobalizedMessage(key, BUNDLE_NAME); + } + + /** + * Returns a globalized message object, using the package specific bundle, + * as specified by BUNDLE_NAME. Also takes in an Object[] of arguments to + * interpolate into the retrieved message using the MessageFormat class. + */ + public static GlobalizedMessage globalize(String key, Object[] args) { + return new GlobalizedMessage(key, BUNDLE_NAME, args); + } + + /** + * Returns the name of the package specific resource bundle. + * + * Used e.g. by com.arsdigita.cms.ui.item.ItemLanguageTable to get the + * bundle tp pass to DataTable. + * + * @return Name of resource bundle as String + */ + public static String getBundleName() { + return BUNDLE_NAME; + } + +} diff --git a/ccm-ldn-search/src/com/arsdigita/london/search/SearchResources.properties b/ccm-ldn-search/src/com/arsdigita/london/search/SearchResources.properties new file mode 100644 index 000000000..c9219430d --- /dev/null +++ b/ccm-ldn-search/src/com/arsdigita/london/search/SearchResources.properties @@ -0,0 +1,7 @@ +# To change this license header, choose License Headers in Project Properties. +# To change this template file, choose Tools | Templates +# and open the template in the editor. + +search.ui.submit_button=Find +search.ui.help=Please enter at least three letters for a search. You may narrow the result by adding further parameters. +search.ui.no_results=No results found. diff --git a/ccm-ldn-search/src/com/arsdigita/london/search/SearchResources_de.properties b/ccm-ldn-search/src/com/arsdigita/london/search/SearchResources_de.properties new file mode 100644 index 000000000..274bbf20d --- /dev/null +++ b/ccm-ldn-search/src/com/arsdigita/london/search/SearchResources_de.properties @@ -0,0 +1,7 @@ +# To change this license header, choose License Headers in Project Properties. +# To change this template file, choose Tools | Templates +# and open the template in the editor. + +search.ui.submit_button=Finden +search.ui.help=Bitte geben Sie miindestens drei Buchstaben f\u00fcr die Suche ein. Sie k\u00f6nnen das Ergebnis mit weiteren Suchparametern weiter einschr\u00e4nken. +search.ui.no_results=Keine Ergebnisse gefunden. diff --git a/ccm-ldn-search/src/com/arsdigita/london/search/ui/SearchComponent.java b/ccm-ldn-search/src/com/arsdigita/london/search/ui/SearchComponent.java index 5b925ec40..a30eda781 100755 --- a/ccm-ldn-search/src/com/arsdigita/london/search/ui/SearchComponent.java +++ b/ccm-ldn-search/src/com/arsdigita/london/search/ui/SearchComponent.java @@ -26,6 +26,7 @@ import com.arsdigita.bebop.Page; import com.arsdigita.bebop.form.Submit; import com.arsdigita.bebop.parameters.BigDecimalParameter; import com.arsdigita.cms.ui.ItemSearch; +import com.arsdigita.london.search.SearchGlobalizationUtil; import com.arsdigita.search.ui.QueryComponent; import com.arsdigita.search.ui.ResultsPane; @@ -49,9 +50,11 @@ public class SearchComponent extends SimpleContainer { m_form = new Form("search", new SimpleContainer()); m_form.setMethod(Form.GET); m_form.add(m_query); - m_form.add(new Submit("search", "Search")); + m_form.add(new Submit("search", SearchGlobalizationUtil.globalize("search.ui.submit_button"))); m_results = new ResultsPane(query, engine); + m_results.setSearchHelpMsg(SearchGlobalizationUtil.globalize("search.ui.help")); + m_results.setNoResultsMsg(SearchGlobalizationUtil.globalize("search.ui.no_results")); add(m_form);