/* * Copyright (C) 2003-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.lifecycle; import com.arsdigita.bebop.ColumnPanel; import com.arsdigita.bebop.FormProcessException; import com.arsdigita.bebop.Label; import com.arsdigita.bebop.PageState; import com.arsdigita.bebop.SimpleContainer; import com.arsdigita.bebop.event.FormInitListener; import com.arsdigita.bebop.event.FormProcessListener; import com.arsdigita.bebop.event.FormSectionEvent; import com.arsdigita.bebop.event.FormValidationListener; import com.arsdigita.bebop.form.FormErrorDisplay; import com.arsdigita.bebop.form.Submit; import com.arsdigita.bebop.form.TextArea; import com.arsdigita.bebop.form.TextField; import com.arsdigita.bebop.parameters.IntegerParameter; import com.arsdigita.bebop.parameters.NotEmptyValidationListener; import com.arsdigita.bebop.parameters.NumberInRangeValidationListener; import com.arsdigita.bebop.parameters.StringLengthValidationListener; import com.arsdigita.bebop.parameters.TrimmedStringParameter; import com.arsdigita.cms.SecurityManager; import com.arsdigita.cms.lifecycle.Duration; import com.arsdigita.cms.lifecycle.PhaseDefinition; import com.arsdigita.cms.lifecycle.PhaseDefinitionCollection; import com.arsdigita.cms.ui.CMSForm; import com.arsdigita.cms.ui.FormSecurityListener; import com.arsdigita.cms.util.GlobalizationUtil; import com.arsdigita.globalization.GlobalizedMessage; /** * This class contains a form component to edit a lifecycle * phase definition. * * @author Jack Chung * @author Xixi D'Moon * @author Michael Pih * @version $Id: EditPhaseForm.java 287 2005-02-22 00:29:02Z sskracic $ */ class EditPhaseForm extends CMSForm { private final static String PHASE_ID = "id"; private final static String LABEL = "label"; private final static String DESCRIPTION = "description"; private final static String DELAY_DAYS = "delay_days"; private final static String DELAY_HOURS = "delay_hours"; private final static String DELAY_MINUTES = "delay_minutes"; private final static String DURATION_DAYS = "duration_days"; private final static String DURATION_HOURS = "duration_hours"; private final static String DURATION_MINUTES = "duration_minutes"; private final static String SUBMIT = "submit"; private final static String CANCEL = "cancel"; private final PhaseRequestLocal m_phase; private TextField m_label; private TextArea m_description; private TextField m_delayDays; private TextField m_delayHours; private TextField m_delayMinutes; private TextField m_durDays; private TextField m_durHours; private TextField m_durMinutes; private Submit m_submit; private Submit m_cancel; /** * Constructor. * * @param m A single selection model for phase definitions. * This is to tell the form which phase definition is selected for editing. * @pre phases != null */ public EditPhaseForm(final PhaseRequestLocal phase) { super("EditPhaseDefinition"); m_phase = phase; add(new Label()); add(new FormErrorDisplay(this)); add(new Label(gz("cms.ui.name"))); m_label = new TextField(new TrimmedStringParameter(LABEL)); m_label.addValidationListener(new NotEmptyValidationListener()); m_label.setSize(40); m_label.setMaxLength(1000); add(m_label); add(new Label(gz("cms.ui.description"))); m_description = new TextArea(new TrimmedStringParameter(DESCRIPTION)); m_description.addValidationListener (new StringLengthValidationListener(4000)); m_description.setCols(40); m_description.setRows(5); m_description.setWrap(TextArea.SOFT); add(m_description); // Phase duration // Max value: days: 60 years, hours: 7 days, minutes: 1 day m_delayDays = new TextField(new IntegerParameter(DELAY_DAYS)); m_delayDays.addValidationListener (new NumberInRangeValidationListener(0, 21900)); m_delayDays.setSize(7); m_delayDays.setClassAttr("DaysField"); m_delayHours = new TextField(new IntegerParameter(DELAY_HOURS)); m_delayHours.addValidationListener (new NumberInRangeValidationListener(0, 168)); m_delayHours.setClassAttr("HoursField"); m_delayHours.setSize(7); m_delayMinutes = new TextField(new IntegerParameter(DELAY_MINUTES)); m_delayMinutes.addValidationListener (new NumberInRangeValidationListener(0, 1440)); m_delayMinutes.setSize(7); m_delayMinutes.setClassAttr("MinutesField"); add(new Label(GlobalizationUtil.globalize ("cms.ui.lifecycle.start_delay"))); SimpleContainer de = new SimpleContainer(); de.add(new Label(gz("cms.ui.lifecycle.phase_days"))); de.add(m_delayDays); de.add(new Label(gz("cms.ui.lifecycle.phase_hours"))); de.add(m_delayHours); de.add(new Label(gz("cms.ui.lifecycle.phase_mins"))); de.add(m_delayMinutes); add(de); // Phase duration // Max value: days: 60 years, hours: 7 days, minutes: 1 day m_durDays = new TextField(new IntegerParameter(DURATION_DAYS)); m_durDays.addValidationListener (new NumberInRangeValidationListener(0, 21900)); m_durDays.setSize(7); m_durDays.setClassAttr("DaysField"); m_durHours = new TextField(new IntegerParameter(DURATION_HOURS)); m_durHours.addValidationListener (new NumberInRangeValidationListener(0, 168)); m_durHours.setSize(7); m_durHours.setClassAttr("HoursField"); m_durMinutes = new TextField(new IntegerParameter(DURATION_MINUTES)); m_durMinutes.addValidationListener (new NumberInRangeValidationListener(0, 1440)); m_durMinutes.setSize(7); m_durMinutes.setClassAttr("MinutesField"); add(new Label(gz("cms.ui.lifecycle.duration"))); SimpleContainer du = new SimpleContainer(); du.add(new Label(gz("cms.ui.lifecycle.phase_days"))); du.add(m_durDays); du.add(new Label(gz("cms.ui.lifecycle.phase_hours"))); du.add(m_durHours); du.add(new Label(gz("cms.ui.lifecycle.phase_mins"))); du.add(m_durMinutes); add(du); // Submit and cancel buttons SimpleContainer s = new SimpleContainer(); m_submit = new Submit(SUBMIT); m_submit.setButtonLabel("Edit Phase"); s.add(m_submit); m_cancel = new Submit(CANCEL); m_cancel.setButtonLabel("Cancel"); s.add(m_cancel); add(s, ColumnPanel.FULL_WIDTH | ColumnPanel.CENTER); // Add form listeners. addInitListener(new FormInitListener() { public final void init(final FormSectionEvent event) throws FormProcessException { initializePhaseDefinition(event.getPageState()); } }); addSubmissionListener (new FormSecurityListener(SecurityManager.LIFECYCLE_ADMIN)); addValidationListener(new FormValidationListener() { public final void validate(final FormSectionEvent event) throws FormProcessException { final PageState state = event.getPageState(); validateDuration(state); validateUniqueName(state); } }); addProcessListener(new FormProcessListener() { public void process(FormSectionEvent event) throws FormProcessException { updatePhaseDefinition(event.getPageState()); } }); } /** * Returns true if this form was cancelled. * * @param state The page state * @return True if the form was cancelled, false otherwise * @pre state != null */ public boolean isCancelled(final PageState state) { return m_cancel.isSelected(state); } /** * Populate the form fields with the current phase definition * attribute values. * * @param state The page state * @pre state != null */ private void initializePhaseDefinition(final PageState state) throws FormProcessException { PhaseDefinition pd = m_phase.getPhase(state); m_label.setValue(state, pd.getLabel()); m_description.setValue(state, pd.getDescription()); Integer delay[] = Duration.formatDHM(pd.getDefaultDelay()); m_delayDays.setValue(state, delay[0]); m_delayHours.setValue(state, delay[1]); m_delayMinutes.setValue(state, delay[2]); Integer duration = pd.getDefaultDuration(); if (duration != null) { Integer dhm[] = Duration.formatDHM(duration); m_durDays.setValue(state, dhm[0]); m_durHours.setValue(state, dhm[1]); m_durMinutes.setValue(state, dhm[2]); } } /** * Update the phase definition with values from the form. * * @param state The page state * @pre state != null */ private void updatePhaseDefinition(final PageState state) throws FormProcessException { String label = (String) m_label.getValue(state); String description = (String) m_description.getValue(state); Integer delayDays = (Integer) m_delayDays.getValue(state); Integer delayHours = (Integer) m_delayHours.getValue(state); Integer delayMinutes = (Integer) m_delayMinutes.getValue(state); Integer durDays = (Integer) m_durDays.getValue(state); Integer durHours = (Integer) m_durHours.getValue(state); Integer durMinutes = (Integer) m_durMinutes.getValue(state); PhaseDefinition pd = m_phase.getPhase(state); pd.setLabel(label); pd.setDescription(description); pd.setDefaultDelay(delayDays, delayHours, delayMinutes); pd.setDefaultDuration(durDays, durHours, durMinutes); pd.save(); } /** * Ensures that the new name (if it has changed) is unique within the * lifecycle definition. * * @param state The page state * @pre state != null */ private void validateUniqueName(final PageState state) throws FormProcessException { final String newLabel = (String) m_label.getValue(state); PhaseDefinition pd = m_phase.getPhase(state); PhaseDefinitionCollection phaseDefs = pd.getLifecycleDefinition().getPhaseDefinitions(); // If the name has changed, check for uniqueness. if (!pd.getLabel().equalsIgnoreCase(newLabel)) { while (phaseDefs.next()) { PhaseDefinition phaseDef = phaseDefs.getPhaseDefinition(); if (phaseDef.getLabel().equalsIgnoreCase(newLabel)) { phaseDefs.close(); throw new FormProcessException (lz("cms.ui.lifecycle.phase_name_not_unique")); } } } } /** * Validate the phase duration. The duration cannot be 0. * * @param state The page state * @pre state != null */ private void validateDuration(final PageState state) throws FormProcessException { final Integer durDays = (Integer) m_durDays.getValue(state); final Integer durHours = (Integer) m_durHours.getValue(state); final Integer durMinutes = (Integer) m_durMinutes.getValue (state); // Phase duration is infinite, so the duration is valid. if (durDays == null && durHours == null && durMinutes == null) { return; } int days, hours, minutes; if (durDays != null) { days = durDays.intValue(); } else { days = 0; } if (durHours != null) { hours = durHours.intValue(); } else { hours = 0; } if (durMinutes != null) { minutes = durMinutes.intValue(); } else { minutes = 0; } if ((days + hours + minutes) == 0) { throw new FormProcessException (lz("cms.ui.phase.duration_negative")); } } private static GlobalizedMessage gz(final String key) { return GlobalizationUtil.globalize(key); } private static String lz(final String key) { return (String) gz(key).localize(); } }