545 lines
23 KiB
Java
Executable File
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))));
|
|
}
|
|
|
|
}
|
|
|
|
}
|