libreccm-legacy/ccm-subsite/src/com/arsdigita/subsite/ui/SiteForm.java

545 lines
23 KiB
Java
Executable File

/*
* 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.subsite.ui;
import com.arsdigita.bebop.ColumnPanel;
import com.arsdigita.bebop.Form;
import com.arsdigita.bebop.FormData;
import com.arsdigita.bebop.FormProcessException;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.SaveCancelSection;
import com.arsdigita.bebop.event.FormInitListener;
import com.arsdigita.bebop.event.FormProcessListener;
import com.arsdigita.bebop.event.FormSectionEvent;
import com.arsdigita.bebop.event.FormSubmissionListener;
import com.arsdigita.bebop.event.FormValidationListener;
import com.arsdigita.bebop.event.ParameterEvent;
import com.arsdigita.bebop.event.ParameterListener;
import com.arsdigita.bebop.event.PrintEvent;
import com.arsdigita.bebop.event.PrintListener;
import com.arsdigita.bebop.form.Option;
import com.arsdigita.bebop.form.SingleSelect;
import com.arsdigita.bebop.form.TextArea;
import com.arsdigita.bebop.form.TextField;
import com.arsdigita.bebop.form.Widget;
import com.arsdigita.bebop.parameters.NotNullValidationListener;
import com.arsdigita.bebop.parameters.ParameterData;
import com.arsdigita.bebop.parameters.StringParameter;
import com.arsdigita.categorization.Category;
import com.arsdigita.categorization.ui.CategoryPicker;
import com.arsdigita.kernel.ACSObject;
import com.arsdigita.persistence.DataCollection;
import com.arsdigita.persistence.SessionManager;
import com.arsdigita.subsite.Site;
import com.arsdigita.subsite.Subsite;
import com.arsdigita.subsite.util.SubsiteGlobalizationUtil;
import static com.arsdigita.subsite.util.SubsiteGlobalizationUtil.globalize;
import com.arsdigita.ui.UI;
import com.arsdigita.util.Assert;
import com.arsdigita.util.Classes;
import com.arsdigita.util.StringUtils;
import com.arsdigita.util.UncheckedWrapperException;
import com.arsdigita.web.Application;
import com.arsdigita.web.ApplicationCollection;
import java.math.BigDecimal;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TooManyListenersException;
import org.apache.log4j.Logger;
/**
* Class creates the administration input form.
*
* Used by ControlCenterPanel to construct the 'create new site' and
* 'edit existing site' input forms.
*/
public class SiteForm extends Form {
/** Internal logger instance to faciliate debugging. Enable logging output
* by editing /WEB-INF/conf/log4j.properties int the runtime environment
* and set com.arsdigita.subsite.ui.SiteForm=DEBUG
* by uncommenting or adding the line. */
private static final Logger s_log = Logger.getLogger(SiteForm.class);
private final SiteSelectionModel m_site;
private final BigDecimal siteDefaultRootPageID;
/**
* Input field subsite title
*/
private final TextField m_title;
private final TextField m_hostname;
private final TextArea m_description;
private final SingleSelect m_customFrontpageApp;
private final TextField m_styleDir;
private final CategoryPicker m_rootCategory;
private final SingleSelect m_themes;
private final SaveCancelSection m_buttons;
private final static String DEFAULT_APP = "DEFAULT_APP";
private final static String DEFAULT_APP_LABEL = "subsite.ui.default_app_label";
private final static String DEFAULT_STYLE = "DEFAULT_STYLE";
private final static String DEFAULT_STYLE_LABEL = "subsite.ui.default_style_label";
private final static String OTHER_STYLE = "OTHER_STYLE";
private final static String OTHER_STYLE_LABEL = "subsite.ui.other_style_label";
/**
* Constructor create input widgets and adds them to form.
*
* @param name
* @param site
*/
public SiteForm(String name, SiteSelectionModel site) {
//super(name, new SimpleContainer());
super(name, new ColumnPanel(2));
setClassAttr("simpleForm");
setRedirecting(true);
m_site = site;
String defAppPath = UI.getRootPageURL();
s_log.debug("defAppPath is: " + defAppPath);
siteDefaultRootPageID = Application.retrieveApplicationForPath(defAppPath).getID();
/* Setup text input field for subsite title property */
m_title = new TextField(new StringParameter("title"));
m_title.addValidationListener(new NotNullValidationListener());
m_title.setMetaDataAttribute("title", "Title");
m_title.setHint(SubsiteGlobalizationUtil.globalize("subsite.ui.title.hint"));
m_title.setSize(40);
add(new Label(SubsiteGlobalizationUtil.globalize("subsite.ui.title.label")));
add(m_title); // adds title input field to form
/* Setup text input field for hostname property */
m_hostname = new TextField(new StringParameter("hostname"));
m_hostname.addValidationListener(new NotNullValidationListener());
m_hostname.addValidationListener(new HostNameValidationListener());
m_hostname.setMetaDataAttribute("title", "Hostname");
m_hostname.setSize(40);
m_hostname.setHint(SubsiteGlobalizationUtil.globalize("subsite.ui.hostname.hint"));
add(new Label(SubsiteGlobalizationUtil.globalize("subsite.ui.hostname.label")));
add(m_hostname); // adds hostname input field to form
/* Setup text input area for description property */
m_description = new TextArea(new StringParameter("description"));
m_description.addValidationListener(new NotNullValidationListener());
m_description.setMetaDataAttribute("title", "Description");
m_description.setCols(45);
m_description.setRows(4);
m_description.setHint(SubsiteGlobalizationUtil.globalize(
"subsite.ui.description.hint"));
add(new Label(SubsiteGlobalizationUtil.globalize("subsite.ui.description.label")));
add(m_description); // adds description input field to form
/* Setup selection box for subsite start page (front page) Application
* by URL */
m_customFrontpageApp = new SingleSelect(
new StringParameter("customFrontpageApp"));
m_customFrontpageApp.setMetaDataAttribute("title", "Front Page (url)");
// m_customFrontpageApp.setSize(40);
m_customFrontpageApp.setHint(globalize(
"subsite.ui.customfrontpage.hint"));
try {
m_customFrontpageApp.addPrintListener(new FrontpageAppListener());
} catch (TooManyListenersException ex) {
throw new UncheckedWrapperException("This cannot happen", ex);
}
add(new Label(SubsiteGlobalizationUtil.globalize("subsite.ui.customfrontpage.label")));
add(m_customFrontpageApp); // adds selectfield start page to form
/* Setup selection box for themes */
m_themes = new SingleSelect(new StringParameter("selectStyleDir"));
m_themes.setMetaDataAttribute("title", "XSLT Directory");
m_themes.setHint(SubsiteGlobalizationUtil.globalize("subsite.ui.theme.hint"));
try {
m_themes.addPrintListener(new ThemesListener());
} catch (TooManyListenersException ex) {
throw new UncheckedWrapperException("This cannot happen", ex);
}
add(new Label(SubsiteGlobalizationUtil.globalize("subsite.ui.theme.label")));
add(m_themes); // adds themes selection box to form
/* Setup text input field to manually enter a style direcotry */
m_styleDir = new TextField(new StringParameter("styleDir"));
m_styleDir.setMetaDataAttribute("title", "XSLT Directory (Other)");
m_styleDir.setSize(40);
m_styleDir.setHint(globalize("subsite.ui.styledir.hint") );
add(new Label(SubsiteGlobalizationUtil.globalize("subsite.ui.styledir.label")));
add(m_styleDir); // adds inputfield style dir to form
/* Setup selection box for cagtegory domain */
m_rootCategory = (CategoryPicker) Classes.newInstance(
Subsite.getConfig().getRootCategoryPicker(),
new Class[]{String.class},
new Object[]{"rootCategory"});
if (m_rootCategory instanceof Widget) {
((Widget) m_rootCategory).setMetaDataAttribute("title", "Root category");
((Widget) m_rootCategory).setHint(SubsiteGlobalizationUtil.globalize(
"subsite.ui.root_category.hint"));
}
add(new Label(SubsiteGlobalizationUtil.globalize("subsite.ui.root_category.label")));
add(m_rootCategory); // adds domain category selection box to form
m_buttons = new SaveCancelSection();
m_buttons.getSaveButton().setButtonLabel(SubsiteGlobalizationUtil.globalize(
"subsite.ui.save"));
m_buttons.getSaveButton().setHint(globalize("subsite.ui.save.hint"));
m_buttons.getCancelButton().setButtonLabel(SubsiteGlobalizationUtil.globalize(
"subsite.ui.cancel"));
m_buttons.getCancelButton().setHint(globalize("subsite.ui.cancel.hint"));
add(m_buttons);
addSubmissionListener(new SiteSubmissionListener());
addProcessListener(new SiteProcessListener());
addInitListener(new SiteInitListener());
addValidationListener(new SiteValidationListener());
}
/**
*
*/
private class SiteSubmissionListener implements FormSubmissionListener {
@Override
public void submitted(FormSectionEvent e)
throws FormProcessException {
PageState state = e.getPageState();
if (m_buttons.getCancelButton().isSelected(state)) {
m_site.clearSelection(state);
throw new FormProcessException(
"cancel pressed",
globalize("cms.ui.authoring.submission_cancelled")
);
}
}
}
/**
* Validate the subsite form user input.
*/
private class SiteValidationListener implements FormValidationListener {
@Override
public void validate(FormSectionEvent e) {
PageState state = e.getPageState();
if (!m_buttons.getCancelButton().isSelected(state)) {
FormData data = e.getFormData();
// make sure that if a theme was typed in that the "other"
// was selected in the theme selection box.
String styleDir = (String) m_styleDir.getValue(state);
String themeDir = (String) m_themes.getValue(state);
if (styleDir != null) {
styleDir = styleDir.trim();
}
// if the styleDir is null/empty then the themeDir must not
// be null. If the themeDir is set to "other" then we leave
// need to make sure the styleDir is null
if (OTHER_STYLE.equals(themeDir)) {
if (StringUtils.emptyString(styleDir)) {
data.addError(SubsiteGlobalizationUtil.globalize(
"subsite.ui.other_style_missing",
new String[]{OTHER_STYLE_LABEL}));
}
} else {
if (!StringUtils.emptyString(styleDir)) {
data.addError(SubsiteGlobalizationUtil.globalize(
"subsite.ui.other_style_invalid",
new String[]{OTHER_STYLE_LABEL}));
}
}
/* Check whether a valid Root category has been selected. The
* default entry "-- pick one--" provides a null String
* ( null pointer exception). */
try {
Category testExist = m_rootCategory.getCategory(state);
String test = testExist.getDefaultDomainClass();
} catch (Exception ex) {
data.addError(SubsiteGlobalizationUtil.globalize(
"subsite.ui.root_category_missing"));
}
} // End if (!m_buttons ...)
} // End validate(FormSectionEvent e)
}
/**
* Checks whether hostname is alreafy in use.
*/
private class HostNameValidationListener implements ParameterListener {
@Override
public void validate(ParameterEvent e) {
ParameterData data = e.getParameterData();
String hostname = (String) data.getValue();
Site site = m_site.getSelectedSite(e.getPageState());
if (hostname != null && hostname.toString().length() > 0) {
DataCollection sites = SessionManager.getSession()
.retrieve(Site.BASE_DATA_OBJECT_TYPE);
sites.addEqualsFilter("lower(" + Site.HOSTNAME + ")",
hostname.toLowerCase());
if (site != null) {
sites.addNotEqualsFilter(Site.ID, site.getID());
}
if (sites.size() > 0) {
data.addError(SubsiteGlobalizationUtil.globalize(
"subsite.ui.hostname_already_in_use"));
}
}
}
}
/**
* Initializes the form. (when a new input form is requested by user either by editing an
* existing subsite or by creating a new one).
*/
private class SiteInitListener implements FormInitListener {
@Override
public void init(FormSectionEvent e)
throws FormProcessException {
PageState state = e.getPageState();
Site site = m_site.getSelectedSite(state);
if (site == null) {
m_title.setValue(state, null);
m_hostname.setValue(state, null);
m_description.setValue(state, null);
m_customFrontpageApp.setValue(state, DEFAULT_APP);
m_styleDir.setValue(state, null);
m_themes.setValue(state, DEFAULT_STYLE);
m_rootCategory.setCategory(state, null);
} else {
m_title.setValue(state, site.getTitle());
m_hostname.setValue(state, site.getHostname());
m_description.setValue(state, site.getDescription());
BigDecimal currentFrontpageID = site.getFrontPage().getID();
s_log.debug(" Site default frontpage is: " + siteDefaultRootPageID
+ ", Current frontpage is: " + currentFrontpageID);
m_customFrontpageApp.setValue(
state,
currentFrontpageID == siteDefaultRootPageID ? DEFAULT_APP
: currentFrontpageID.toString());
String styleURL = site.getStyleDirectory();
// if the value is in the config map, then styleDir is
// empty and themeDir gets the value. Otherwise, if the
// value is null, themeDir gets DEFAULT and styleDir is
// empty. Otherwise, themeDir gets OTHER and sytleDir
// gets the value
String styleDir = null;
String themeDir = null;
if (Subsite.getConfig().getThemes().get(styleURL) != null) {
themeDir = styleURL;
} else {
if (StringUtils.emptyString(styleURL)) {
// we want the default
themeDir = DEFAULT_STYLE;
} else {
themeDir = OTHER_STYLE;
styleDir = styleURL;
}
}
m_styleDir.setValue(state, styleDir);
m_themes.setValue(state, themeDir);
Category root = site.getRootCategory();
m_rootCategory.setCategory(state, root);
}
}
}
/**
*
*/
private class SiteProcessListener implements FormProcessListener {
@Override
public void process(FormSectionEvent e)
throws FormProcessException {
PageState state = e.getPageState();
Category root = m_rootCategory.getCategory(state);
Site site = m_site.getSelectedSite(state);
String style = (String) m_styleDir.getValue(state);
String theme = (String) m_themes.getValue(state);
if (style != null) {
style = style.trim();
}
String styleDir = style;
if (StringUtils.emptyString(style)) {
if (!OTHER_STYLE.equals(theme) && !DEFAULT_STYLE.equals(theme)) {
styleDir = theme;
}
}
/* Pre-process selected frontpage application: retrieve application */
String subsiteSelectedFrontpage = (String) m_customFrontpageApp
.getValue(state);
s_log.debug(" Site default frontpage ID is: " + siteDefaultRootPageID
+ ", selected frontpage Value is: "
+ subsiteSelectedFrontpage);
Application frontpageApp;
if (subsiteSelectedFrontpage.equals(DEFAULT_APP)) {
s_log.debug("About to create frontpage app ID: " + DEFAULT_APP);
frontpageApp = Application
.retrieveApplication(siteDefaultRootPageID);
} else {
s_log.debug("About to create frontpage app ID: "
+ subsiteSelectedFrontpage);
frontpageApp = Application
.retrieveApplication(new BigDecimal(subsiteSelectedFrontpage));
}
Assert.exists(frontpageApp, Application.class);
s_log.debug("Created frontpage app ID: " + frontpageApp.getID());
if (site == null) { // (sub)site not yet exists, create new one
if (!siteDefaultRootPageID.equals(frontpageApp.getID())) {
// Previous version executed setRoot.... for newly created
// application, which were created for the purpose to serve
// as a dedicated front page application for the created
// subsite with an added comment:
// "NB, explicitly don't set cat on shared front page!"
s_log.debug("Front page application ID: "
+ frontpageApp.getID());
s_log.debug("About to set cat on dedicated front page.");
Category.setRootForObject(frontpageApp, root);
}
// actually create a new subsite
site = Site.create((String) m_title.getValue(state),
(String) m_description.getValue(state),
(String) m_hostname.getValue(state),
styleDir,
root,
frontpageApp);
} else { // (sub)site already exists, modify mutable configuration
site.setTitle((String) m_title.getValue(state));
site.setDescription((String) m_description.getValue(state));
site.setHostname((String) m_hostname.getValue(state));
site.setStyleDirectory(styleDir);
site.setRootCategory(root);
// XXX Check: Frontpage application was not mutable in previous
// version! Check if we explicitly have to handle cat whether
// or not frontpage is shared. See comment above!
site.setFrontPage(frontpageApp);
}
m_site.clearSelection(state);
Application app = Application
.retrieveApplicationForPath("/navigation/");
Category.setRootForObject(app,
root,
site.getTemplateContext().getContext());
}
}
/**
*
*/
private class FrontpageAppListener implements PrintListener {
@Override
public void prepare(PrintEvent e) {
final SingleSelect target = (SingleSelect) e.getTarget();
ApplicationCollection customApps;
target.addOption(new Option(DEFAULT_APP,
new Label(SubsiteGlobalizationUtil
.globalize(DEFAULT_APP_LABEL))));
String[] customAppTypes = (String[]) Subsite.getConfig()
.getFrontPageApplicationTypes();
if (customAppTypes != null) {
for (String customAppType : customAppTypes) {
customApps = Application.retrieveAllApplications(customAppType);
while (customApps.next()) {
/* Create an entry for each application, consisting
* of the (BigDecimal) ID as value and the URL as
* label. */
String appID = customApps.get(ACSObject.ID).toString();
target.addOption(new Option(appID,
(customApps.getPrimaryURL()
+ "(" + appID + ")")));
}
}
}
}
}
/**
*
*/
private class ThemesListener implements PrintListener {
@Override
public void prepare(PrintEvent e) {
SingleSelect target = (SingleSelect) e.getTarget();
PageState state = e.getPageState();
Map themes = Subsite.getConfig().getThemes();
Set entrySet = themes.entrySet();
target.addOption(new Option(DEFAULT_STYLE,
new Label(SubsiteGlobalizationUtil.globalize(
DEFAULT_STYLE_LABEL))));
if (entrySet != null) {
Iterator entries = entrySet.iterator();
while (entries.hasNext()) {
Map.Entry entry = (Map.Entry) entries.next();
target.addOption(new Option(entry.getKey().toString(),
entry.getValue().toString()),
state);
}
}
target.addOption(new Option(OTHER_STYLE,
new Label(SubsiteGlobalizationUtil.globalize(
OTHER_STYLE_LABEL))));
}
}
}