Fixed: missing globalization in content-center (#1763), fixed layout of error message (part of #2090).

git-svn-id: https://svn.libreccm.org/ccm/trunk@2697 8810af33-2d31-482b-a856-94f89814c4df
master
pb 2014-06-13 06:32:36 +00:00
parent ba8419d8b2
commit 88b61faeb6
30 changed files with 427 additions and 394 deletions

View File

@ -35,6 +35,7 @@ import com.arsdigita.bebop.form.TextField;
import com.arsdigita.bebop.parameters.DateParameter;
import com.arsdigita.bebop.parameters.NotEmptyValidationListener;
import com.arsdigita.bebop.parameters.NotNullValidationListener;
import com.arsdigita.bebop.parameters.URLTokenValidationListener;
import com.arsdigita.bebop.parameters.ParameterModel;
import com.arsdigita.bebop.parameters.TrimmedStringParameter;
import com.arsdigita.cms.ContentItem;
@ -43,7 +44,6 @@ import com.arsdigita.cms.ContentSection;
import com.arsdigita.cms.Folder;
import com.arsdigita.cms.ItemSelectionModel;
import com.arsdigita.cms.contenttypes.MultiPartArticle;
import com.arsdigita.cms.ui.authoring.NameValidationListener;
import com.arsdigita.cms.util.GlobalizationUtil;
import com.arsdigita.cms.contenttypes.util.MPArticleGlobalizationUtil;
import com.arsdigita.persistence.DataQuery;
@ -132,7 +132,8 @@ public abstract class MultiPartArticleForm extends FormSection
add(new Label(GlobalizationUtil
.globalize("cms.contenttypes.ui.name")));
TextField nameWidget = new TextField(new TrimmedStringParameter(NAME));
nameWidget.addValidationListener(new NameValidationListener());
nameWidget.addValidationListener(new NotNullValidationListener());
nameWidget.addValidationListener(new URLTokenValidationListener());
nameWidget.setOnFocus("defaulting = false");
nameWidget.setOnBlur(
"if (this.value == '') " +

View File

@ -263,7 +263,7 @@ cms.ui.item_search.search=Search
# Package com.arsdigita.cms.ui.authoring
# ======================================
cms.ui.authoring.an_item_with_this_name_already_exists=An item with this name already exists!
cms.ui.authoring.an_item_with_this_name_exists=An item with this name already exists!
cms.ui.authoring.bad_getblob_datatype=Bad getBlob datatype
cms.ui.authoring.bad_getclob_datatype=Bad getClob datatype
cms.ui.authoring.body=Body:

View File

@ -261,7 +261,7 @@ cms.ui.item_search.search=Suchen
# Package com.arsdigita.cms.ui.authoring
# ======================================
cms.ui.authoring.an_item_with_this_name_already_exists=Ein Dokument mit diesem Namen existiert bereits!
cms.ui.authoring.an_item_with_this_name_exists=Ein Dokument mit diesem Namen existiert bereits!
cms.ui.authoring.bad_getblob_datatype=Ung\u00fcltiger Datentyp getBlob
cms.ui.authoring.bad_getclob_datatype=Ung\u00fcltiger Datentyp getClob
cms.ui.authoring.body=Textbereich:

View File

@ -157,7 +157,7 @@ cms.ui.no_items_matched_the_search=Pas d'\u00e9l\u00e9ment trouv\u00e9 dans la r
# Package com.arsdigita.cms.ui.authoring
# ======================================
cms.ui.authoring.an_item_with_this_name_already_exists=Un \u00e9l\u00e9ment de ce nom existe d\u00e9j\u00e0!
cms.ui.authoring.an_item_with_this_name_exists=Un \u00e9l\u00e9ment de ce nom existe d\u00e9j\u00e0!
cms.ui.authoring.bad_getblob_datatype=TRANSLATE THIS: Bad getBlob datatype (cms.ui.authoring.bad_getblob_datatype)
cms.ui.authoring.bad_getclob_datatype=TRANSLATE THIS: Bad getClob datatype (cms.ui.authoring.bad_getclob_datatype)
cms.ui.authoring.body=Corsp de la page

View File

@ -34,9 +34,15 @@ import java.util.Date;
import org.apache.log4j.Logger;
/**
* This class extends {@link com.arsdigita.cms.ContentItem content
* item} with the additional attributes name, title and description. The name attribute is used in
* generating the URL for this content page.
* This class extends {@link com.arsdigita.cms.ContentItem content item} with
* the additional attributes name, title and description. The name attribute is
* used in generating the URL for this content page.
* It is the base class for any document-type of content, i.e. content bearing a
* title, name and description/abstract (in con trast to assets or special
* content as Contact or internal type as folder).
*
* ContentPage is a bit of missleading, more adaquat would have been
* ContentDocument.
*
* @author Uday Mathur
* @author Jack Chung

View File

@ -253,9 +253,10 @@ public class ItemSelectionModel extends ACSObjectSelectionModel {
}
/**
* @return The content type of the items which are produced by
* this model, or null if the content type has not been specified
* in the constructor.
*
* @return The content type of the items which are produced by this model,
* or null if the content type has not been specified in the
* constructor.
*/
public ContentType getContentType() {

View File

@ -35,6 +35,10 @@ import com.arsdigita.cms.ui.authoring.BasicPageForm;
public class GenericArticlePropertyForm extends BasicPageForm
implements FormProcessListener, FormInitListener, FormSubmissionListener {
/** Internal logger instance to faciliate debugging. Enable logging output
* by editing /WEB-INF/conf/log4j.properties int hte runtime environment
* and set com.arsdigita.cms.contenttypes.ui.GenericArticlePropertyForm=DEBUG
* by uncommenting or adding the line. */
private final static org.apache.log4j.Logger s_log =
org.apache.log4j.Logger.getLogger(GenericArticlePropertyForm.class);
private GenericArticlePropertiesStep m_step;

View File

@ -449,14 +449,14 @@ public abstract class CategoryForm extends Form
if (query.size() > 0) {
// we need to make sure that there is not an item
ACSObject item = getObject(state);
Collection list = null;
Collection list;
if (item instanceof ContentItem) {
list = BasicItemForm.getAllVersionIDs((ContentItem) item);
} else {
list = new ArrayList();
list.add(item.getID());
}
BigDecimal itemID = null;
BigDecimal itemID;
while (query.next()) {
itemID = (BigDecimal) query.get("itemID");
if (!list.contains(itemID)) {

View File

@ -81,6 +81,7 @@ public class ItemPropertySheet extends PropertySheet {
* @deprecated
*/
public ItemPropertySheet(ItemSelectionModel itemModel, boolean valueOutputEscape) {
super(new ItemModelBuilder(), valueOutputEscape);
m_itemModel = itemModel;
@ -102,7 +103,7 @@ public class ItemPropertySheet extends PropertySheet {
* @param label The label for the attribute
* @param attribute The name for the attribute. Could be a simple name
* or a compound path, such as "foo.bar.baz"
* @deprecated
* @deprecated use add(GlobalizedMessage label, String attribute) instead
*/
public void add(String label, String attribute) {
add(GlobalizationUtil.globalize(label), attribute);
@ -110,8 +111,8 @@ public class ItemPropertySheet extends PropertySheet {
/**
* Add a new property to the sheet. The sheet will automatically
* retrieve an attribute of the item and call toString() on it
* Add a new property to the sheet. The sheet will automatically retrieve
* an attribute of the item and call toString() on it
*
* @param label The label for the attribute
* @param attribute The name for the attribute. Could be a simple name

View File

@ -33,7 +33,9 @@ import com.arsdigita.bebop.event.FormValidationListener;
import com.arsdigita.bebop.form.Hidden;
import com.arsdigita.bebop.form.TextField;
import com.arsdigita.bebop.parameters.NotNullValidationListener;
import com.arsdigita.bebop.parameters.ParameterData;
import com.arsdigita.bebop.parameters.TrimmedStringParameter;
import com.arsdigita.bebop.parameters.URLTokenValidationListener;
import com.arsdigita.cms.ContentItem;
import com.arsdigita.cms.ContentPage;
import com.arsdigita.cms.Folder;
@ -85,6 +87,7 @@ public abstract class BasicItemForm extends FormSection
* for loading the current item
*/
public BasicItemForm(String formName, ItemSelectionModel itemModel) {
super(new ColumnPanel(2));
m_widgetSection = new FormSection(new ColumnPanel(2, true));
@ -196,8 +199,12 @@ public abstract class BasicItemForm extends FormSection
final TextField nameWidget = new TextField(new TrimmedStringParameter(NAME));
nameWidget.setLabel(getNameLabel());
nameWidget.setHint(getNameHint());
// We just check parameter specific properties here! Additionally,
// context properties as uniqueness in folder must be validated
// for the form es the whole (using the validate method required by
// implementing FormValidationListener in this form.
nameWidget.addValidationListener(new NotNullValidationListener());
nameWidget.addValidationListener(new NameValidationListener());
nameWidget.addValidationListener(new URLTokenValidationListener());
nameWidget.setMaxLength(190);
nameWidget.setOnFocus("defaulting = false");
nameWidget.setOnBlur(
@ -249,8 +256,9 @@ public abstract class BasicItemForm extends FormSection
public abstract void process(FormSectionEvent e) throws FormProcessException;
/**
* Validate the form. Children should override this method to provide
* custom form validation.
* Validate the form. Children have to override this method to provide
* context form validation, specifically name (url) uniqueness in a
* folder!
*
* @param e
* @throws com.arsdigita.bebop.FormProcessException
@ -261,173 +269,6 @@ public abstract class BasicItemForm extends FormSection
}
/**
* 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 use provided on the input form.
*/
public void validateNameUniqueness(Folder parent, FormSectionEvent event)
throws FormProcessException {
FormData data = event.getFormData();
String newName = (String) data.get(NAME);
validateNameUniqueness(parent, event, newName);
}
/**
*
* @param parent
* @param event
* @param newName
*
* @throws FormProcessException
*/
public void validateNameUniqueness(Folder parent,
FormSectionEvent event,
String newName)
throws FormProcessException {
if (newName != null) {
final String query = "com.arsdigita.cms.validateUniqueItemName";
DataQuery dq = SessionManager.getSession().retrieveQuery(query);
dq.setParameter("parentId", parent.getID());
dq.setParameter("name", newName.toUpperCase());
FormData data = event.getFormData();
if (dq.size() > 0) {
// we need to add all of the items that are
// different versions of this item to the list
// so that we do not throw an error if those
// are the only problems
BigDecimal itemID = null;
ContentItem item = null;
if (getItemSelectionModel() != null) {
item = (ContentItem) getItemSelectionModel()
.getSelectedObject(event.getPageState());
}
if (item == null) {
// this means it is a creation form
data.addError(globalize(
"cms.ui.authoring.an_item_with_this_name_already_exists"));
throw new FormProcessException(
"An item with this name already exists",
globalize("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)) {
String[] itemObj=new String[1];
itemObj[0]=itemID.toString();
dq.close();
data.addError(globalize(
"cms.ui.authoring.an_item_with_this_name_already_exists"));
throw new FormProcessException(
"An item with this name already exists",
globalize(
"cms.ui.authoring.items_with_this_name_already_exist",
itemObj)
);
}
}
}
}
}
/**
* 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.
*/
public void validateNameUniquenessWithinCategory(FormSectionEvent event,
BigDecimal id)
throws FormProcessException {
if (id == null) {
s_log.warn("Trying to validation the name uniqueness without "
+ " a valid item is invalid. This method should only "
+ " be called in \"edit\" forms. The passed in id "
+ " was null.");
return;
}
// now we check to make sure that the new name is valid
// within every category that the item is mapped to
// this is only necessary for category browsing
FormData data = event.getFormData();
String url = (String) data.get(NAME);
if (url == null) {
return;
}
DataQuery query = SessionManager.getSession().retrieveQuery(
"com.arsdigita.categorization.getAllItemURLsForCategoryFromItem");
query.setParameter("itemID", id);
query.addEqualsFilter("lower(url)", url.toLowerCase());
if (query.size() > 0) {
// we need to make sure that the conflicting item is not a
// pending or live version of the same item
BigDecimal itemID = null;
ContentItem item = (ContentItem)getItemSelectionModel()
.getSelectedObject(event.getPageState());
Collection list = getAllVersionIDs(item);
try {
while (query.next()) {
itemID = (BigDecimal) query.get("itemID");
if (!list.contains(itemID)) {
// StringBuffer buffer = new StringBuffer((String) GlobalizationUtil
// .globalize("cms.ui.authoring.error_conflicts_with_this_url")
// .localize());
// buffer.append(url);
String[] urlObj=new String[1];
urlObj[0]=url;
throw new FormProcessException(
"Error: Conflict with url: "+url,
globalize(
"cms.ui.authoring.error_conflicts_with_this_url",
urlObj)
);
}
}
} finally {
query.close();
}
}
}
public static Collection getAllVersionIDs(ContentItem item) {
// we need to add all of the items that are different versions
// of this item to the list so that we do not throw an error
// if those are the only problems
ArrayList list = new ArrayList();
list.add(item.getID());
ContentItem live = item.getLiveVersion();
if (live != null) {
list.add(live.getID());
}
ItemCollection collection = item.getPendingVersions();
while (collection.next()) {
list.add(collection.getID());
}
return list;
}
/**
* Adds a component to this container.
*
@ -500,4 +341,181 @@ public abstract class BasicItemForm extends FormSection
return GlobalizationUtil.globalize("cms.contenttypes.ui.name_hint");
}
// //////////////////////////////////////////////////////////////////////
//
// VALIDATION helper methods
//
// //////////////////////////////////////////////////////////////////////
/**
* 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 use provided on the input form.
*/
public void validateNameUniqueness(Folder parent, FormSectionEvent event) {
FormData data = event.getFormData();
String newName = (String) data.get(NAME);
validateNameUniqueness(parent, event, newName);
}
/**
*
* @param parent
* @param event
* @param newName
*
* @throws FormProcessException
*/
public void validateNameUniqueness(Folder parent,
FormSectionEvent event,
String newName) {
final String ERR_MSG = "cms.ui.authoring.an_item_with_this_name_exists";
if (newName != null) {
final String query = "com.arsdigita.cms.validateUniqueItemName";
DataQuery dq = SessionManager.getSession().retrieveQuery(query);
dq.setParameter("parentId", parent.getID());
dq.setParameter("name", newName.toUpperCase());
FormData data = event.getFormData();
ParameterData name = data.getParameter(NAME);
if (dq.size() > 0) {
// Try to get a currently selected content item
ContentItem item = null;
if (getItemSelectionModel() != null) {
item = (ContentItem) getItemSelectionModel()
.getSelectedObject(event.getPageState());
}
if (item == null) { // The content item being null
// means it is a creation form.
// Therefore finding any item of the same name is a fault.
name.addError(globalize(ERR_MSG));
return;
} else {
// means we are in a edit form.
// We need to add all of the items that are different
// versions of this item to the list so that we do not mark
// an error if those are the only problems.
BigDecimal itemID = null;
Collection list = getAllVersionIDs(item);
while (dq.next()) {
itemID = (BigDecimal) dq.get("itemID");
if (!list.contains(itemID)) {
String[] itemObj=new String[1];
itemObj[0]=itemID.toString();
dq.close();
name.addError(globalize(ERR_MSG));
return;
}
}
}
}
}
}
/**
* NOT USED ANYMORE.
*
* 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.
* @return
*
* @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 {
if (id == null) {
s_log.warn("Trying to validation the name uniqueness without "
+ " a valid item is invalid. This method should only "
+ " be called in \"edit\" forms. The passed in id "
+ " was null.");
return;
}
// now we check to make sure that the new name is valid
// within every category that the item is mapped to
// this is only necessary for category browsing
FormData data = event.getFormData();
String url = (String) data.get(NAME);
if (url == null) {
return;
}
DataQuery query = SessionManager.getSession().retrieveQuery(
"com.arsdigita.categorization.getAllItemURLsForCategoryFromItem");
query.setParameter("itemID", id);
query.addEqualsFilter("lower(url)", url.toLowerCase());
if (query.size() > 0) {
// we need to make sure that the conflicting item is not a
// pending or live version of the same item
BigDecimal itemID = null;
ContentItem item = (ContentItem)getItemSelectionModel()
.getSelectedObject(event.getPageState());
Collection list = getAllVersionIDs(item);
try {
while (query.next()) {
itemID = (BigDecimal) query.get("itemID");
if (!list.contains(itemID)) {
// StringBuffer buffer = new StringBuffer((String) GlobalizationUtil
// .globalize("cms.ui.authoring.error_conflicts_with_this_url")
// .localize());
// buffer.append(url);
String[] urlObj=new String[1];
urlObj[0]=url;
throw new FormProcessException(
"Error: Conflict with url: "+url,
globalize(
"cms.ui.authoring.error_conflicts_with_this_url",
urlObj)
);
}
}
} finally {
query.close();
}
}
}
*/
/**
* Helper Method for name uniqueness validation.
*
* @param item
* @return
*/
public static Collection getAllVersionIDs(ContentItem item) {
// we need to add all of the items that are different versions
// of this item to the list so that we do not throw an error
// if those are the only problems
ArrayList list = new ArrayList();
list.add(item.getID());
ContentItem live = item.getLiveVersion();
if (live != null) {
list.add(live.getID());
}
ItemCollection collection = item.getPendingVersions();
while (collection.next()) {
list.add(collection.getID());
}
return list;
}
}

View File

@ -44,11 +44,18 @@ import javax.servlet.ServletException;
import java.util.Date;
/**
* A form for editing subclasses of ContentPage.
* A form for editing basic properties of documents (that is subclasses of
* class ContentPage).
*
* Document specific classes inherit from this class which provides the basic
* widgets for title, name launch date to use by those classes.
*
* This is just a convenience class. It uses parent class to construct the form
* including basic widgets (i.e. title and name/url as well as save/cancel
* buttons) and adds optional Lunchdate
* buttons) and adds optional Lunchdate.
*
* Note: It is for editing existing content (specifically due to its validation
* method).
*
* @author Stanislav Freidin (stas@arsdigita.com)
* @version $Revision: #22 $ $DateTime: 2004/08/17 23:15:09 $
@ -56,6 +63,12 @@ import java.util.Date;
public abstract class BasicPageForm extends BasicItemForm {
private FormSection m_widgetSection;
// description / abstract has been delegated to document-specific classes
// propably to better adjust to specific needs, unfortunately to the
// expense of internal consistency (because any document should carry a
// description in constrast to items as folders of parts of a document, as
// a section in a multipart article).
// public static final String DESCRIPTION = ContentPage.DESCRIPTION;
public static final String LAUNCH_DATE = ContentPage.LAUNCH_DATE;
@ -144,13 +157,16 @@ public abstract class BasicPageForm extends BasicItemForm {
}
/**
* Class specific implementation of FormValidationListener interface
* (inherited from BasicItemForm).
*
* @param fse
* @throws FormProcessException
*/
@Override
public void validate(final FormSectionEvent fse) throws FormProcessException {
super.validate(fse);
super.validate(fse); //noop, BasicItemForm#validate does nothing
final ContentItem item = getItemSelectionModel()
.getSelectedItem(fse.getPageState());
@ -165,7 +181,7 @@ public abstract class BasicPageForm extends BasicItemForm {
Assert.exists(folder);
final FormData data = fse.getFormData();
final String name = data.getString(NAME);
if (!item.getName().equals(name)) {
if (!item.getName().equals(name)) { // name modified?
validateNameUniqueness(folder, fse);
}
}
@ -250,7 +266,6 @@ public abstract class BasicPageForm extends BasicItemForm {
if (value == null) {
data.addError("launch date is required");
return;
}
}
}

View File

@ -1,100 +0,0 @@
/*
* Copyright (C) 2001-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.cms.ui.authoring;
import com.arsdigita.bebop.event.ParameterEvent;
import com.arsdigita.bebop.event.ParameterListener;
import com.arsdigita.bebop.parameters.ParameterData;
import com.arsdigita.cms.util.GlobalizationUtil;
import java.util.StringTokenizer;
import org.apache.log4j.Logger;
/**
* Verifies that the parameter is a valid filenamersp. URL stub, is not null,
* and contains no reserved characters.
*
* @author Justin Ross <jross@redhat.com>
* @author Peter Boy <pb@zes.uni-bremen.de>
* @version $Id: NameValidationListener.java 2090 2010-04-17 08:04:14Z pboy $
*/
public class NameValidationListener implements ParameterListener {
/** Internal logger instance to faciliate debugging. Enable logging output
* by editing /WEB-INF/conf/log4j.properties int hte runtime environment
* and set com.arsdigita.cms.ui.authoring.NameValidationListener=DEBUG
* by uncommenting or adding the line. */
private static final Logger s_log = Logger.getLogger
(NameValidationListener.class);
/**
* Default Constructor, creates a new <code>NameValidationListener</code>.
*/
public NameValidationListener() {
}
/**
* Constructs a new <code>NameValidationListener</code>.
*
* @param label the label for the error message
* @deprecated with no replacement. Does nothing anymore.
*/
public NameValidationListener(final String label) {
// Do nothing
}
/**
* Validate the input field as passed in by ParameterEvent.
*
* @param e ParameterEvent containing input data.
*/
@Override
public void validate(final ParameterEvent e) {
final ParameterData data = e.getParameterData();
final Object value = data.getValue();
if (value == null || value.toString().length() < 1) {
data.addError(GlobalizationUtil
.globalize("cms.ui.authoring.parameter_not_empty"));
return;
}
final String text = value.toString();
final StringTokenizer tok =
new StringTokenizer(text, "*? /\\\'\"&$`~");
if (tok.hasMoreTokens()) {
final String token = tok.nextToken();
if (!token.equals(text)) {
data.addError(GlobalizationUtil.globalize(
"cms.ui.authoring.parameter_should_be_a_valid_filename"));
}
}
if (text.indexOf(".") != -1) {
data.addError(GlobalizationUtil.globalize(
"cms.ui.authoring.parameter_should_be_a_valid_filename"));
}
}
}

View File

@ -94,6 +94,7 @@ public abstract class NewItemForm extends Form {
m_typeWidget.addPrintListener(new PrintListener() {
// Read the content section's content types and add them as options
@Override
public void prepare(PrintEvent e) {
OptionGroup o = (OptionGroup) e.getTarget();
PageState state = e.getPageState();

View File

@ -38,7 +38,8 @@ import java.util.Date;
import org.apache.log4j.Logger;
/**
* A form which will create a new ContentPage or one of its subclasses.
* A form which will create a new documnent (that is subclasses of class
* ContentPage).
*
* Used to create a new document / content item. Creates widgets to select the
* workflow, and language. It displays the type of document as well. Super class
@ -54,12 +55,16 @@ import org.apache.log4j.Logger;
public class PageCreate extends BasicPageForm
implements FormSubmissionListener, CreationComponent {
/** Internal logger instance to faciliate debugging. Enable logging output
* by editing /WEB-INF/conf/log4j.properties int hte runtime environment
* and set com.arsdigita.cms.ui.authoring.PageCreate=DEBUG
* by uncommenting or adding the line. */
private final static org.apache.log4j.Logger s_log =
org.apache.log4j.Logger.getLogger(PageCreate.class);
protected final CreationSelector m_parent;
protected ApplyWorkflowFormSection m_workflowSection;
/**
* The state parameter which specifies the content section
*/
/** The state parameter which specifies the content section */
public static final String SECTION_ID = "sid";
/**
@ -154,6 +159,7 @@ public class PageCreate extends BasicPageForm
* tries to access things which on existing yet.
*
* @param event
* @throws com.arsdigita.bebop.FormProcessException
*/
@Override
public void validate(final FormSectionEvent event) throws FormProcessException {
@ -162,7 +168,14 @@ public class PageCreate extends BasicPageForm
validateNameUniqueness(folder, event);
}
// Process: save fields to the database
/**
* Class specific implementation if FormProcessListener (as inherited from
* BasicItemForm), saves fields to the database.
*
* @param e
* @throws FormProcessException
*/
@Override
public void process(final FormSectionEvent e) throws FormProcessException {
final FormData data = e.getFormData();
final PageState state = e.getPageState();

View File

@ -32,27 +32,27 @@ import com.arsdigita.cms.ui.ItemPropertySheet;
import com.arsdigita.cms.ui.workflow.WorkflowLockedComponentAccess;
import com.arsdigita.cms.util.GlobalizationUtil;
import com.arsdigita.util.Assert;
import org.apache.log4j.Logger;
import java.text.DateFormat;
import org.apache.log4j.Logger;
/**
* The article editing component. Consists of a display component
* which displays the form metadata, and a form which edits the
* metadata as well as text.
* The article editing component. Consists of a display component which
* displays the form metadata, and a form which edits the metadata as well
* as text.
*
* The {@link com.arsdigita.bebop.PropertySheet} class is often used
* as the display component in the default authoring kit steps of
* this class.
*
* @author Stanislav Freidin
* @version $Revision: #14 $ $DateTime: 2004/08/17 23:15:09 $
* @version $Id: PageEdit.java 2090 2010-04-17 08:04:14Z pboy $
*/
public class PageEdit extends SimpleEditStep {
private static Logger s_log =
private static final Logger s_log =
Logger.getLogger(PageEdit.class);
//XD: The output escaping of the values of the label value pairs
@ -73,18 +73,23 @@ public class PageEdit extends SimpleEditStep {
super(itemModel, parent);
PageEditForm form = new PageEditForm(itemModel);
add("edit", "Edit", new WorkflowLockedComponentAccess(form, itemModel),
add("edit",
GlobalizationUtil.globalize("cms.ui.edit"),
new WorkflowLockedComponentAccess(form, itemModel),
form.getSaveCancelSection().getCancelButton());
//DomainObjectPropertySheet sheet = new DomainObjectPropertySheet(itemModel);
ItemPropertySheet sheet =
new ItemPropertySheet(itemModel, VALUE_OUTPUT_ESCAPE);
sheet.add((String) GlobalizationUtil.globalize("cms.ui.authoring.name").localize(), ContentPage.NAME);
sheet.add((String) GlobalizationUtil.globalize("cms.ui.authoring.title").localize(), ContentPage.TITLE);
sheet.add(GlobalizationUtil.globalize("cms.ui.authoring.name"),
ContentPage.NAME);
sheet.add(GlobalizationUtil.globalize("cms.ui.authoring.title"),
ContentPage.TITLE);
if (!ContentSection.getConfig().getHideLaunchDate()) {
sheet.add("Launch Date:",
ContentPage.LAUNCH_DATE,
new ItemPropertySheet.AttributeFormatter() {
@Override
public String format(ContentItem item,
String attribute,
PageState state) {
@ -146,6 +151,11 @@ public class PageEdit extends SimpleEditStep {
}
}
/**
*
* @param event
* @throws FormProcessException
*/
@Override
public void validate(FormSectionEvent event) throws FormProcessException {
super.validate(event);

View File

@ -38,6 +38,7 @@ import com.arsdigita.bebop.parameters.NotNullValidationListener;
import com.arsdigita.bebop.parameters.ParameterModel;
import com.arsdigita.bebop.parameters.StringParameter;
import com.arsdigita.bebop.parameters.TrimmedStringParameter;
import com.arsdigita.bebop.parameters.URLTokenValidationListener;
import com.arsdigita.cms.ContentItem;
import com.arsdigita.cms.ContentPage;
import com.arsdigita.cms.ContentSection;
@ -286,7 +287,8 @@ public class PageEditDynamic extends SecurityPropertyEditor {
add(new Label(GlobalizationUtil.globalize("cms.ui.authoring.name")));
add(new Label(""));
TextField nameWidget = new TextField(new TrimmedStringParameter(NAME));
nameWidget.addValidationListener(new NameValidationListener());
nameWidget.addValidationListener(new NotNullValidationListener());
nameWidget.addValidationListener(new URLTokenValidationListener());
add(nameWidget);
add(new Label(GlobalizationUtil.globalize("cms.ui.authoring.title")));

View File

@ -25,6 +25,7 @@ import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.event.FormSectionEvent;
import com.arsdigita.bebop.form.TextField;
import com.arsdigita.bebop.parameters.NotNullValidationListener;
import com.arsdigita.bebop.parameters.URLTokenValidationListener;
import com.arsdigita.bebop.parameters.TrimmedStringParameter;
import com.arsdigita.cms.ContentItem;
import com.arsdigita.cms.Folder;
@ -32,7 +33,6 @@ import com.arsdigita.cms.ItemSelectionModel;
import com.arsdigita.cms.Template;
import com.arsdigita.cms.ui.authoring.AuthoringKitWizard;
import com.arsdigita.cms.ui.authoring.BasicPageForm;
import com.arsdigita.cms.ui.authoring.NameValidationListener;
import com.arsdigita.cms.ui.authoring.SimpleEditStep;
import com.arsdigita.cms.ui.workflow.WorkflowLockedComponentAccess;
import com.arsdigita.cms.util.GlobalizationUtil;
@ -50,8 +50,11 @@ import org.apache.log4j.Logger;
*/
public class TemplateEdit extends SimpleEditStep {
private static Logger s_log =
Logger.getLogger(TemplateEdit.class);
/** Internal logger instance to faciliate debugging. Enable logging output
* by editing /WEB-INF/conf/log4j.properties int hte runtime environment
* and set com.arsdigita.cms.ui.templates.TemplateEdit=DEBUG
* by uncommenting or adding the line. */
private static final Logger s_log = Logger.getLogger(TemplateEdit.class);
/**
* Construct a new TemplateEdit component
@ -72,8 +75,10 @@ public class TemplateEdit extends SimpleEditStep {
//DomainObjectPropertySheet sheet = new DomainObjectPropertySheet(itemModel);
DomainObjectPropertySheet sheet = new DomainObjectPropertySheet(itemModel, false);
sheet.add((String) GlobalizationUtil.globalize("cms.ui.templates.name").localize(), ContentItem.NAME);
sheet.add((String) GlobalizationUtil.globalize("cms.ui.templates.label").localize(), Template.LABEL);
sheet.add(GlobalizationUtil.globalize("cms.ui.templates.name"),
ContentItem.NAME);
sheet.add(GlobalizationUtil.globalize("cms.ui.templates.label"),
Template.LABEL);
setDisplayComponent(sheet);
}
@ -97,11 +102,13 @@ public class TemplateEdit extends SimpleEditStep {
/**
* Create the widgets for this form
*/
@Override
protected void addWidgets() {
add(new Label(GlobalizationUtil.globalize("cms.ui.templates.name")));
TextField nameWidget =
new TextField(new TrimmedStringParameter(NAME));
nameWidget.addValidationListener(new NameValidationListener());
nameWidget.addValidationListener(new NotNullValidationListener());
nameWidget.addValidationListener(new URLTokenValidationListener());
add(nameWidget);
add(new Label(GlobalizationUtil.globalize("cms.ui.templates.label")));
@ -111,7 +118,13 @@ public class TemplateEdit extends SimpleEditStep {
add(labelWidget);
}
// Init: load the item and preset the widgets
/**
* Load the item and preset the widgets.
*
* @param e
* @throws FormProcessException
*/
@Override
public void init(FormSectionEvent e) throws FormProcessException {
FormData data = e.getFormData();
PageState state = e.getPageState();
@ -121,7 +134,13 @@ public class TemplateEdit extends SimpleEditStep {
data.put(Template.LABEL, t.getLabel());
}
// Process: save fields to the database
/**
* Save fields to the database.
*
* @param e
* @throws FormProcessException
*/
@Override
public void process(FormSectionEvent e) throws FormProcessException {
FormData data = e.getFormData();
PageState state = e.getPageState();
@ -131,9 +150,15 @@ public class TemplateEdit extends SimpleEditStep {
t.save();
}
/**
*
* @param event
* @throws FormProcessException
*/
@Override
public void validate(FormSectionEvent event) throws FormProcessException {
//Calling super.validate(e) here causes an exception because the super method checks things which not available
//here.
// Calling super.validate(e) here causes an exception because the
// super method checks things which not available here.
PageState state = event.getPageState();
FormData data = event.getFormData();
@ -148,7 +173,12 @@ public class TemplateEdit extends SimpleEditStep {
}
}
// Get the current template
/**
* Get the current template.
*
* @param state
* @return
*/
public Template getTemplate(PageState state) {
Template t =
(Template) getItemSelectionModel().getSelectedObject(state);

View File

@ -56,7 +56,6 @@ public class NotEmptyValidationListener extends GlobalizedParameterListener {
setError(new GlobalizedMessage(label, getBundleBaseName()));
}
/**
* Constructor taking a GlobalizedMessage as error message to display.
*

View File

@ -7,3 +7,4 @@ file_empty_or_not_found=is empty or was not found.
file_too_large=is too large
uri_parameter_is_invalid=This parameter must be a URI formatted according to RFC2396
bebop.parameters.parameter_not_empty=This field must not be empty.
bebop.parameters.must_be_valid_part_of_url=Parameter must contain only alpha-numeric, hyphen, or underscore characters!

View File

@ -7,3 +7,4 @@ file_empty_or_not_found=ist leer oder wurde nicht gefunden.
file_too_large=ist zu gro\u00df
uri_parameter_is_invalid=Dieser Parameter muss ein URI sein, das entsprechend RFC2396 formatiert wird
bebop.parameters.parameter_not_empty=Dieser Eintrag darf nicht leer sein!
bebop.parameters.must_be_valid_part_of_url=Dieser Parameter darf nur aus Buchstaben, Zahlen, Bindestrich und Unterstrich bestehen.

View File

@ -7,3 +7,4 @@ file_empty_or_not_found=is empty or was not found.
file_too_large=is too large
uri_parameter_is_invalid=This parameter must be a URI formatted according to RFC2396
bebop.parameters.parameter_not_empty=This field must not be empty.
bebop.parameters.must_be_valid_part_of_url=Parameter must contain only alpha-numeric, hyphen, or underscore characters!

View File

@ -2,3 +2,4 @@ bebop.parameters.parameter_is_required=Este par\u00e1metro es requerido
string_in_range=Este par\u00e1metro no tiene entre {0} y {1} caracteres
type_check={0} tiene que ser de clase {1} pero el objecto {2} es de clase {3}
bebop.parameters.parameter_not_empty=This field must not be empty.
bebop.parameters.must_be_valid_part_of_url=Parameter must contain only alpha-numeric, hyphen, or underscore characters!

View File

@ -3,3 +3,4 @@ string_in_range=La longueur de ce param\u00e8tre n'est pas comprise entre {0} e
type_check={0} doit \u00eatre de type {1} mais poss\u00e8de {2} de type {3}
parameter.only.letters.digits=Ce param\u00e8tre ne doit contenir que des lettres ou des chiffres
bebop.parameters.parameter_not_empty=This field must not be empty.
bebop.parameters.must_be_valid_part_of_url=Parameter must contain only alpha-numeric, hyphen, or underscore characters!

View File

@ -37,6 +37,7 @@ public class URLParameter extends StringParameter {
super(name);
}
@Override
public Object transformValue(HttpServletRequest request)
throws IllegalArgumentException {

View File

@ -18,37 +18,58 @@
*/
package com.arsdigita.bebop.parameters;
import com.arsdigita.bebop.parameters.ParameterData;
import com.arsdigita.bebop.event.ParameterListener;
import com.arsdigita.bebop.event.ParameterEvent;
import com.arsdigita.globalization.GlobalizedMessage;
//import com.arsdigita.bebop.parameters.ParameterData;
import org.apache.oro.text.perl.Perl5Util;
/**
* Verifies that the
* parameter's value is composed of only alpha-numeric,
* underscore, or hyphen characters. [a-zA-Z_0-9\-]
* Verifies that the parameter's value is composed only of character which are
* valid as part on an URL name (the token).
* That is only alpha-numeric, underscore, or hyphen characters.
* [a-zA-Z_0-9\-]
*
* Note: An empty string will pass the validation tests.
*
* @author Michael Pih
* @version $Id: URLTokenValidationListener.java 287 2005-02-22 00:29:02Z sskracic $
**/
public class URLTokenValidationListener implements ParameterListener {
*/
public class URLTokenValidationListener extends GlobalizedParameterListener {
// match 1 or more instances of a non-alpha-numeric character
/** match 1 or more instances of a non-alpha-numeric character */
private static final String NON_KEYWORD_PATTERN = "/[^a-zA-Z_0-9\\-]+/";
private String m_label;
public URLTokenValidationListener(String label) {
m_label = label;
}
/**
* Default Constructor setting a predefined label as error message.
*/
public URLTokenValidationListener() {
this("This parameter");
setError(new GlobalizedMessage("bebop.parameters.must_be_valid_part_of_url",
getBundleBaseName() )
);
}
/**
* Constructor taking a label specified as key into a resource bundle to
* customize the error message.
*
* @param label key into the resource bundle
* @deprecated use URLTokenValidationListener(GlobalizedMessage error)
*/
public URLTokenValidationListener(String label) {
setError(new GlobalizedMessage(label, getBundleBaseName()));
}
/**
* Constructor taking a GlobalizedMessage as error message to display.
*
* @param error GloblizedMessage taken as customized error message.
*/
public URLTokenValidationListener(GlobalizedMessage error) {
setError(error);
}
/**
* Validates the parameter by checking if the value is a valid keyword.
* A keyword is defined as any combination of alph-numeric characters,
@ -58,6 +79,7 @@ public class URLTokenValidationListener implements ParameterListener {
*
* @param event The parameter event
*/
@Override
public void validate(ParameterEvent event) {
ParameterData data = event.getParameterData();
Object value = data.getValue();
@ -66,13 +88,6 @@ public class URLTokenValidationListener implements ParameterListener {
if ( !util.match(NON_KEYWORD_PATTERN, value.toString()) ) {
return;
}
// The error message
StringBuffer msg = new StringBuffer(128);
msg
.append(m_label)
.append(
" must contain only alpha-numeric, hyphen, or underscore characters");
data.addError(msg.toString());
data.addError(getError());
}
}

View File

@ -21,14 +21,17 @@ package com.arsdigita.bebop.parameters;
import com.arsdigita.bebop.event.ParameterEvent;
import com.arsdigita.bebop.event.ParameterListener;
import com.arsdigita.bebop.FormProcessException;
import com.arsdigita.bebop.parameters.ParameterData;
//import com.arsdigita.bebop.parameters.ParameterData;
import java.net.MalformedURLException;
import java.net.URL;
/**
*
*
*/
public class URLValidationListener implements ParameterListener {
@Override
public void validate(ParameterEvent e)
throws FormProcessException {

View File

@ -103,10 +103,10 @@ import org.apache.log4j.Logger;
* store the origin. This is used by <code>LoginSignal</code> and
* <code>ReturnSignal</code> to implement UI excursions.</p>
*
* <p>All static create methods taking an
* <code>HttpServletRequest</code> (1) preserve the request's scheme,
* server name, and port and (2) run parameter listeners if the URL's
* parameter map is not null.</p>
* <p>All static create methods taking an <code>HttpServletRequest</code>
* (1) preserve the request's scheme, server name, and port and
* (2) run parameter listeners if the URL's parameter map is not null.
* </p>
*
* <p>Those methods not taking an <code>HttpServletRequest</code> use
* the scheme, server name, and port defined in
@ -132,15 +132,12 @@ import org.apache.log4j.Logger;
*/
public class URL {
/** Internal logger instance to faciliate debugging. Enable logging output
* by editing /WEB-INF/conf/log4j.properties int hte runtime environment
* and set com.arsdigita.web.URL=DEBUG
* by uncommenting or adding the line. */
private static final Logger s_log = Logger.getLogger(URL.class);
/**
* The standard location for XSL files.
* No longer in use.
*/
// public static final String XSL_DIR = INTERNAL_DIR + "/xsl";
public static final String THEMES_DIR = "/themes";
/** Base direcotry for template files provided by packages. Each package

View File

@ -26,7 +26,6 @@ import com.arsdigita.bebop.event.FormInitListener;
import com.arsdigita.bebop.event.FormProcessListener;
import com.arsdigita.bebop.event.FormSectionEvent;
import com.arsdigita.cms.ContentType;
import com.arsdigita.cms.Folder;
import com.arsdigita.cms.ItemSelectionModel;
import com.arsdigita.cms.contenttypes.ArticleInJournal;
import com.arsdigita.cms.contenttypes.ArticleInJournalCollection;
@ -35,7 +34,7 @@ import com.arsdigita.cms.contenttypes.PublicationsConfig;
import com.arsdigita.cms.ui.ItemSearchWidget;
import com.arsdigita.cms.ui.authoring.BasicItemForm;
import com.arsdigita.kernel.Kernel;
import java.math.BigDecimal;
import org.apache.log4j.Logger;
/**

View File

@ -82,8 +82,8 @@ public class ThemeDevelopmentFileManager extends ThemeFileManager {
* This will not start up multiple threads...if there is already
* a thread running, it will return that thread to you.
*
* @param startupDelay number of seconds to wait before starting to
* process the file. A startupDelay of 0 means that this is a no-op
* @param startupDelay number of seconds to wait before starting to process
* the file. A startupDelay of 0 means that this is a no-op
* @param pollDelay number of seconds to wait between checks if the file
* has any entries.
* @param baseDirectory

View File

@ -40,8 +40,8 @@ public class ThemePublishedFileManager extends ThemeFileManager {
* by editing /WEB-INF/conf/log4j.properties int hte runtime environment
* and set com.arsdigita.themedirector.util.ThemePublishedFileManager=DEBUG
* by uncommenting or adding the line. */
private static Logger s_log =
Logger.getLogger(ThemePublishedFileManager.class);
private static Logger s_log = Logger.getLogger(
ThemePublishedFileManager.class);
// The code in this class borrows heavily from
// com.arsdigita.cms.publishToFile.FileManager
@ -74,9 +74,12 @@ public class ThemePublishedFileManager extends ThemeFileManager {
* process the file. A startupDelay of 0 means that this is a no-op
* @param pollDelay number of seconds to wait between checks if the file
* has any entries.
* @param baseDirectory
* @return
*/
public static ThemeFileManager startWatchingFiles
(int startupDelay, int pollDelay, String baseDirectory) {
public static ThemeFileManager startWatchingFiles(int startupDelay,
int pollDelay,
String baseDirectory) {
if (s_manager == null) {
s_log.info("Starting Theme File Manager Thread with the base " +
"directory of " + baseDirectory);
@ -96,8 +99,10 @@ public class ThemePublishedFileManager extends ThemeFileManager {
}
/**
* This returns the current thread or null if the thread has not
* yet been started.
* This returns the current thread or null if the thread has not yet
* been started.
*
* @return
*/
public static ThemeFileManager getInstance() {
return s_manager;
@ -105,19 +110,23 @@ public class ThemePublishedFileManager extends ThemeFileManager {
/**
* this typically returns something like "getBaseDirectory() + PROD_DIR"
* This typically returns something like "getBaseDirectory() + PROD_DIR".
*
* @return
*/
@Override
protected String getManagerSpecificDirectory() {
return getBaseDirectory() + PROD_THEMES_BASE_DIR;
}
/**
* This looks at all of the files in the db for the passed in theme
* and makes sure that this servers file system has all of the
* updated files. If the thread has run since the theme was
* last published then this is a no-op
* This looks at all of the files in the db for the passed in theme and
* makes sure that this servers file system has all of the updated files.
* If the thread has run since the theme was last published then this is
* a no-op
*/
@Override
protected void updateTheme(Theme theme) {
if (getLastRunDate() == null || m_ignoreInterrupt ||
!(new File(getManagerSpecificDirectory() + theme.getURL())).exists() ||
@ -134,7 +143,10 @@ public class ThemePublishedFileManager extends ThemeFileManager {
/**
* This allows subclasses to filter the collection as appropriate.
* (e.g. only return "live" files or only "draft" files).
*
* @return
*/
@Override
protected ThemeFileCollection getThemeFilesCollection(Theme theme) {
return theme.getPublishedThemeFiles();
}