From 7b1e45f223150f337e42aae1a3c8c1d92db8463d Mon Sep 17 00:00:00 2001 From: jensp Date: Thu, 23 Feb 2017 20:49:00 +0000 Subject: [PATCH] CCM NG/ccm-cms: Creating new folders. git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@4597 8810af33-2d31-482b-a856-94f89814c4df Former-commit-id: 08fc76d7e6408b9be5884c4f0b1e0b4b0253cc42 --- .../com/arsdigita/cms/ui/FlatItemList.java | 110 ++----------- .../cms/ui/folder/FolderCreateForm.java | 101 ++++++++++++ .../cms/ui/folder/FolderCreator.java | 66 -------- ...olderEditor.java => FolderEditorForm.java} | 63 ++++++-- .../arsdigita/cms/ui/folder/FolderForm.java | 147 ++++++++++-------- .../cms/ui/folder/FolderSelectionModel.java | 2 +- .../cms/ui/folder/FolderTreeModelBuilder.java | 34 ++-- .../org/librecms/contentsection/Folder.java | 4 + .../org/librecms/CmsResources.properties | 3 + .../org/librecms/CmsResources_de.properties | 3 + .../org/librecms/CmsResources_fr.properties | 3 + .../main/java/com/arsdigita/bebop/Form.java | 4 +- .../arsdigita/ui/CcmObjectSelectionModel.java | 12 +- .../org/libreccm/categorization/Category.java | 12 ++ .../categorization/CategoryManager.java | 36 +++++ .../foundry/templates/admin-layout.xml | 1 + 16 files changed, 338 insertions(+), 263 deletions(-) create mode 100755 ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderCreateForm.java delete mode 100755 ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderCreator.java rename ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/{FolderEditor.java => FolderEditorForm.java} (54%) diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/FlatItemList.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/FlatItemList.java index 7ed338065..196b551cd 100755 --- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/FlatItemList.java +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/FlatItemList.java @@ -44,8 +44,8 @@ import org.librecms.contentsection.ContentSection; import com.arsdigita.cms.ui.authoring.CreationSelector; import com.arsdigita.cms.ui.authoring.NewItemForm; -import com.arsdigita.cms.ui.folder.FolderCreator; -import com.arsdigita.cms.ui.folder.FolderEditor; +import com.arsdigita.cms.ui.folder.FolderCreateForm; +import com.arsdigita.cms.ui.folder.FolderEditorForm; import com.arsdigita.cms.ui.folder.FolderManipulator; import com.arsdigita.cms.ui.folder.FolderPath; import com.arsdigita.cms.ui.folder.FolderRequestLocal; @@ -88,7 +88,7 @@ public class FlatItemList extends SegmentedPanel implements FormProcessListener, private final SingleSelectionModel typeSelectionModel; private final CreationSelector creationSelector; private final FolderManipulator folderManipulator; - private final FolderCreator folderCreator; + private final FolderCreateForm folderCreator; // private final ActionLink m_setHomeFolderAction; // private final ActionLink m_removeHomeFolderAction; private final ActionLink createFolderAction; @@ -102,7 +102,7 @@ public class FlatItemList extends SegmentedPanel implements FormProcessListener, private final CMSPermissionsPane permissionsPane; // Folder edit/rename functionality. private final ActionLink editFolderAction; - private final FolderEditor folderEditor; + private final FolderEditorForm folderEditor; private final Label contentLabel; private final FolderPath folderPath; private final Label chooseLabel; @@ -155,7 +155,6 @@ public class FlatItemList extends SegmentedPanel implements FormProcessListener, browseActions.setSubject(folderManipulator); - // The actions createFolderAction = new ActionLink(new Label(globalize( "cms.ui.new_folder"))); createFolderAction.addActionListener(this); @@ -166,67 +165,16 @@ public class FlatItemList extends SegmentedPanel implements FormProcessListener, editFolderAction.addActionListener(this); browseActions.addAction(editFolderAction); -// m_setHomeFolderAction = new ActionLink(new Label(globalize( -// "cms.ui.set_home_folder"))); -// m_setHomeFolderAction.addActionListener(this); -// browseActions.addAction(m_setHomeFolderAction); -// m_homeFolderLabel = new Label(new PrintListener() { -// -// @Override -// public final void prepare(final PrintEvent event) { -// Label label = (Label) event.getTarget(); -// User user = Web.getWebContext().getUser(); -// -// Folder folder = Folder.getUserHomeFolder(user, CMS.getContext() -// .getContentSection()); -// if (folder != null) { -// String url = folder.getContentSection().getURL() -// + PageLocations.SECTION_PAGE + "?" -// + ContentSectionPage.SET_FOLDER + "=" -// + folder.getID(); -// //label.setLabel("Go to home folder: " + folder.getLabel() + ""); -// String[] parts = new String[3]; -// parts[0] = ""; -// parts[1] = url; -// parts[2] = folder.getLabel(); -// // label.setLabel(String.format("%s: %s", -// // (String) globalize("cms.ui.go_to_home_folder").localize(), -// // url, -// // folder.getLabel())); -// label.setLabel(globalize("cms.ui.go_to_home_folder", parts)); -// } else { -// //label.setLabel("No home folder selected"); -// String[] parts = new String[3]; -// parts[0] = ""; -// parts[1] = ""; -// //label.setLabel(String.format("%s", -// // (String)globalize("cms.ui.no_home_folder_selected").localize())); -// label.setLabel(globalize("cms.ui.no_home_folder_selected", -// parts)); -// } -// label.setOutputEscaping(false); -// } -// -// }); -// browseActions.addAction(m_homeFolderLabel); -// m_removeHomeFolderAction = new ActionLink(new Label(globalize( -// "cms.ui.remove_home_folder"))); -// m_removeHomeFolderAction.addActionListener(this); -// browseActions.addAction(m_removeHomeFolderAction); - - /* */ newItemForm = new SectionNewItemForm("newItem"); newItemForm.addProcessListener(this); browseActions.addAction(newItemForm); - /* permission */ permissionsSegment = addSegment(); permissionsSegment.setIdAttr("folder-permissions"); final ActionGroup permissionActions = new ActionGroup(); permissionsSegment.add(permissionActions); - // The permissions segment permissionsSegment.addHeader(new Label(new GlobalizedMessage( "cms.ui.permissions", CmsConstants.CMS_BUNDLE))); @@ -244,31 +192,6 @@ public class FlatItemList extends SegmentedPanel implements FormProcessListener, (CcmObjectSelectionModel) folderSelectionModel); permissionActions.setSubject(permissionsPane); - // An action -// togglePrivateAction = new ActionLink(new Label(new PrintListener() { -// -// @Override -// public void prepare(final PrintEvent event) { -// final PageState state = event.getPageState(); -// final Label target = (Label) event.getTarget(); -// final Folder currentFolder = folderRequestLocal.getFolder(state); -// // ACSObject parent = currentFolder.getParent(); -// -//// if (context == null) { -// target.setLabel(new GlobalizedMessage( -// "cms.ui.restore_default_permissions", -// CmsConstants.CMS_BUNDLE)); -//// } else { -//// target.setLabel(GlobalizationUtil -//// .globalize("cms.ui.use_custom_permissions")); -//// } -// } -// -// })); -// togglePrivateAction.addActionListener(this); -// permissionActions.addAction(togglePrivateAction); - - // The 'new item' segment newItemSegment.addHeader(new Label(globalize("cms.ui.new_item"))); typeSelectionModel = new ParameterSingleSelectionModel<>( new LongParameter(CONTENT_TYPE_ID)); @@ -281,22 +204,21 @@ public class FlatItemList extends SegmentedPanel implements FormProcessListener, // The 'new folder' segment newFolderSegment.addHeader(new Label(globalize("cms.ui.new_folder"))); - Form folderCreate = new Form("fcreat"); - folderCreator = new FolderCreator("fcreat", folderSelectionModel); +// final Form folderCreate = new Form("fcreat"); + folderCreator = new FolderCreateForm("fcreat", folderSelectionModel); folderCreator.addSubmissionListener(this); folderCreator.addProcessListener(this); - folderCreate.add(folderCreator); - newFolderSegment.add(folderCreate); + //folderCreator.add(folderCreator); + newFolderSegment.add(folderCreator); newFolderSegment.add(new Label("
", false)); editFolderSegment.addHeader(new Label(globalize("cms.ui.edit_folder"))); - folderEditor = new FolderEditor("fedit", folderSelectionModel); + folderEditor = new FolderEditorForm("fedit", folderSelectionModel); folderEditor.addSubmissionListener(this); folderEditor.addProcessListener(this); - - Form folderEditorForm = new Form("fedit_form"); - folderEditorForm.add(folderEditor); - editFolderSegment.add(folderEditorForm); + //Form folderEditorForm = new Form("fedit_form"); + //folderEditorForm.add(folderEditor); + editFolderSegment.add(folderEditor); editFolderSegment.add(new Label("
", false)); } @@ -310,7 +232,7 @@ public class FlatItemList extends SegmentedPanel implements FormProcessListener, page.setVisibleDefault(newFolderSegment, false); page.setVisibleDefault(editFolderSegment, false); - page.addComponentStateParam(this, + page.addComponentStateParam(this, typeSelectionModel.getStateParameter()); page.addActionListener(new ActionListener() { @@ -399,8 +321,8 @@ public class FlatItemList extends SegmentedPanel implements FormProcessListener, browseMode(state); throw new FormProcessException(new GlobalizedMessage( "cms.ui.cancelled", CmsConstants.CMS_BUNDLE)); - } else if (event.getSource() == folderEditor && folderEditor - .isCancelled(state)) { + } else if (event.getSource() == folderEditor + && folderEditor.isCancelled(state)) { browseMode(state); throw new FormProcessException(new GlobalizedMessage( "cms.ui.cancelled", CmsConstants.CMS_BUNDLE)); @@ -453,7 +375,7 @@ public class FlatItemList extends SegmentedPanel implements FormProcessListener, } else if (source == editFolderAction) { permissionsSegment.setVisible(state, false); editFolderSegment.setVisible(state, true); - } + } // else if (source == togglePrivateAction) { // togglePermissions(state); // } diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderCreateForm.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderCreateForm.java new file mode 100755 index 000000000..265df4bf6 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderCreateForm.java @@ -0,0 +1,101 @@ +/* + * 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.folder; + +import com.arsdigita.bebop.FormData; +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.event.FormSectionEvent; +import com.arsdigita.globalization.GlobalizedMessage; +import com.arsdigita.kernel.KernelConfig; + +import org.libreccm.categorization.CategoryManager; +import org.libreccm.cdi.utils.CdiUtil; +import org.libreccm.configuration.ConfigurationManager; +import org.librecms.CmsConstants; +import org.librecms.contentsection.Folder; +import org.librecms.contentsection.FolderManager; +import org.librecms.contentsection.FolderRepository; + +import static com.arsdigita.cms.ui.folder.FolderForm.*; + +public class FolderCreateForm extends FolderForm { + + public FolderCreateForm(final String name, final FolderSelectionModel parent) { + super(name, parent); + } + + @Override + public void init(final FormSectionEvent event) throws FormProcessException { + final PageState state = event.getPageState(); + final FolderSelectionModel model = getFolderSelectionModel(); + } + + /** + * Validates the form. Checks for name uniqueness. + * + * @param event + * + */ + @Override + public void validate(final FormSectionEvent event) + throws FormProcessException { + final Folder folder = getCurrentFolder(event.getPageState()); + final FormData data = event.getFormData(); + final String name = data.getString(NAME); + final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); + final CategoryManager categoryManager = cdiUtil.findBean( + CategoryManager.class); + + if (categoryManager.hasSubCategoryWithName(folder, name)) { + data.addError(new GlobalizedMessage( + "cms.ui.folderform.error.child.name_not_unique", + CmsConstants.CMS_BUNDLE, + new Object[]{name})); + } + + } + + @Override + public void process(final FormSectionEvent event) throws + FormProcessException { + + final PageState state = event.getPageState(); + final FormData data = event.getFormData(); + final Folder parent = getCurrentFolder(state); + + final String name = data.getString(NAME); + final String title = data.getString(TITLE); + + final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); + final FolderRepository folderRepo = cdiUtil.findBean( + FolderRepository.class); + final FolderManager folderManager = cdiUtil + .findBean(FolderManager.class); + final ConfigurationManager confManager = cdiUtil.findBean( + ConfigurationManager.class); + final KernelConfig kernelConfig = confManager.findConfiguration( + KernelConfig.class); + + final Folder folder = folderManager.createFolder(name, parent); + folder.getTitle().addValue(kernelConfig.getDefaultLocale(), title); + folderRepo.save(folder); + } + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderCreator.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderCreator.java deleted file mode 100755 index 5ee2c2952..000000000 --- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderCreator.java +++ /dev/null @@ -1,66 +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.folder; - -import com.arsdigita.bebop.FormData; -import com.arsdigita.bebop.FormProcessException; -import com.arsdigita.bebop.PageState; -import com.arsdigita.bebop.event.FormSectionEvent; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.libreccm.categorization.Category; - - -public class FolderCreator extends FolderForm { - - private static Logger LOGGER = LogManager.getLogger(FolderCreator.class); - - public FolderCreator(final String name, final FolderSelectionModel parent) { - super(name, parent); - } - - @Override - public void init(final FormSectionEvent event) throws FormProcessException { - final PageState state = event.getPageState(); - final FolderSelectionModel model = getFolderSelectionModel(); - - // Create a new item_id and set it as the key - model.setSelectedKey(state, null); - } - - @Override - public void process(final FormSectionEvent event) - throws FormProcessException { - - final PageState state = event.getPageState(); - final FormData data = event.getFormData(); - final FolderSelectionModel model = getFolderSelectionModel(); - final long id = model.getSelectedKey(state); - final Category parent = getCurrentFolder(state); - - final Category child = new Category(); - - updateFolder(child, - parent, - data.getString(NAME), - data.getString(TITLE)); - } - -} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderEditor.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderEditorForm.java similarity index 54% rename from ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderEditor.java rename to ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderEditorForm.java index 012ad2142..c66e77b7c 100755 --- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderEditor.java +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderEditorForm.java @@ -22,53 +22,90 @@ import com.arsdigita.bebop.FormData; import com.arsdigita.bebop.FormProcessException; import com.arsdigita.bebop.PageState; import com.arsdigita.bebop.event.FormSectionEvent; +import com.arsdigita.globalization.GlobalizedMessage; import com.arsdigita.kernel.KernelConfig; + import org.libreccm.categorization.Category; +import org.libreccm.categorization.CategoryManager; import org.libreccm.cdi.utils.CdiUtil; import org.libreccm.configuration.ConfigurationManager; +import org.librecms.CmsConstants; +import org.librecms.contentsection.Folder; +import static com.arsdigita.cms.ui.folder.FolderForm.*; /** - * Implements functionality for renaming a folder. Most code taken from FolderCreator. Need to refactor out base - * functionality of FolderEditor & Creator. + * Implements functionality for renaming a folder. Most code taken from + * FolderCreator. Need to refactor out base functionality of FolderEditorForm & + * Creator. * * @author Jon Orris - * @author Jens >Pelzetter + * @author Jens >Pelzetter * */ +public class FolderEditorForm extends FolderForm { -public class FolderEditor extends FolderForm { - - public FolderEditor(final String name, final FolderSelectionModel folder) { + public FolderEditorForm(final String name, final FolderSelectionModel folder) { super(name, folder); } /** * Initialise the form with name & label of folder being edited. + * * @param event + * * @throws com.arsdigita.bebop.FormProcessException */ @Override public void init(final FormSectionEvent event) throws FormProcessException { final PageState state = event.getPageState(); final FormData data = event.getFormData(); - final Category folder = getCurrentFolder(state); + final Folder folder = getCurrentFolder(state); data.put(NAME, folder.getName()); final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); - final ConfigurationManager confManager = cdiUtil.findBean(ConfigurationManager.class); + final ConfigurationManager confManager = cdiUtil.findBean( + ConfigurationManager.class); final KernelConfig kernelConfig = confManager.findConfiguration( - KernelConfig.class); - data.put(TITLE, + KernelConfig.class); + data.put(TITLE, folder.getTitle().getValue(kernelConfig.getDefaultLocale())); } + /** + * Validates the form. Checks for name uniqueness. + * + * @param event + * + * @throws com.arsdigita.bebop.FormProcessException + */ + @Override + public void validate(final FormSectionEvent event) + throws FormProcessException { + final Category folder = getCurrentFolder(event.getPageState()) + .getParentCategory(); + final FormData data = event.getFormData(); + final String name = data.getString(NAME); + final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); + final CategoryManager categoryManager = cdiUtil.findBean( + CategoryManager.class); + + if (categoryManager.hasSubCategoryWithName(folder, name)) { + data.addError(new GlobalizedMessage( + "cms.ui.folderform.error.parent.name_not_unique", + CmsConstants.CMS_BUNDLE, + new Object[]{name})); + } + + } @Override - public void process(final FormSectionEvent event) throws FormProcessException { + public void process(final FormSectionEvent event) throws + FormProcessException { final PageState state = event.getPageState(); final FormData data = event.getFormData(); - final Category folder = getCurrentFolder(state); + final Folder folder = getCurrentFolder(state); - updateFolder(folder, (String)data.get(NAME), (String)data.get(TITLE)); + updateFolder(folder, (String) data.get(NAME), (String) data.get(TITLE)); } + } diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderForm.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderForm.java index 53150ae3d..5ee072b10 100755 --- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderForm.java +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderForm.java @@ -20,6 +20,8 @@ package com.arsdigita.cms.ui.folder; import com.arsdigita.bebop.ColumnPanel; import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.Form; +import com.arsdigita.bebop.FormData; import com.arsdigita.bebop.FormProcessException; import com.arsdigita.bebop.FormSection; import com.arsdigita.bebop.Label; @@ -45,11 +47,14 @@ import com.arsdigita.xml.Element; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.libreccm.categorization.Category; +import org.libreccm.categorization.CategoryManager; import org.libreccm.categorization.CategoryRepository; import org.libreccm.cdi.utils.CdiUtil; import org.libreccm.configuration.ConfigurationManager; import org.libreccm.l10n.GlobalizationHelper; import org.librecms.CmsConstants; +import org.librecms.contentsection.Folder; +import org.librecms.contentsection.FolderManager; /** * Class FolderForm implements the basic form for creating or editing folders. @@ -64,10 +69,9 @@ import org.librecms.CmsConstants; * @author Jon Orris * @author Jens Pelzetter */ -public abstract class FolderForm extends FormSection - implements FormInitListener, - FormProcessListener, - FormValidationListener { +public abstract class FolderForm extends Form implements FormInitListener, + FormProcessListener, + FormValidationListener { public static final Logger LOGGER = LogManager.getLogger(FolderForm.class); @@ -78,33 +82,30 @@ public abstract class FolderForm extends FormSection private final FolderSelectionModel currentFolder; private final SaveCancelSection saveCancelSection; - private final FormSection widgetSection; - - /** - * Currently, to insert javascript code the Label Widget is "abused". - */ - private final Label m_script = new Label(String.format( - "", - Web.getWebappContextPath()), - false); +// private final FormSection widgetSection; +// /** +// * Currently, to insert javascript code the Label Widget is "abused". +// */ +// private final Label m_script = new Label(String.format( +// "", +// Web.getWebappContextPath()), +// false); /** * Create a new folder form. * - * @param name Name of the form + * @param formName Name of the form * @param currentFolder SelectionModel containing the current folder being - * operated on. + * operated on. * * @pre name != null && folder != null */ - public FolderForm(final String name, + public FolderForm(final String formName, final FolderSelectionModel currentFolder) { - super(new ColumnPanel(2)); - - widgetSection = new FormSection(new ColumnPanel(2, true)); - - super.add(widgetSection, ColumnPanel.INSERT); + super(formName, new ColumnPanel(2)); +// widgetSection = new FormSection(new ColumnPanel(2, true)); +// super.add(widgetSection, ColumnPanel.INSERT); this.currentFolder = currentFolder; final ColumnPanel panel = (ColumnPanel) getPanel(); @@ -137,11 +138,11 @@ public abstract class FolderForm extends FormSection public FolderForm(final String formName, final ColumnPanel columnPanel, final FolderSelectionModel currentFolder) { - super(columnPanel); + super(formName, columnPanel); - widgetSection = new FormSection( - new ColumnPanel(columnPanel.getNumCols())); - super.add(widgetSection, ColumnPanel.INSERT); +// widgetSection = new FormSection( +// new ColumnPanel(columnPanel.getNumCols())); +// super.add(widgetSection, ColumnPanel.INSERT); this.currentFolder = currentFolder; saveCancelSection = new SaveCancelSection(); @@ -172,20 +173,20 @@ public abstract class FolderForm extends FormSection // it breaks URLs & potentially overwrites the user's // customizations. final TextField titleWidget = new TextField(new TrimmedStringParameter( - TITLE)); + TITLE)); titleWidget.setLabel(getTitleLabel()); titleWidget.setHint(getTitleHint()); titleWidget.addValidationListener(new NotNullValidationListener()); titleWidget.setOnFocus("if (this.form." + NAME + ".value == '') { " - + " defaulting = true; this.form." + NAME - + ".value = urlize(this.value); }"); + + " defaulting = true; this.form." + NAME + + ".value = urlize(this.value); }"); titleWidget.setOnKeyUp( - "if (defaulting) { this.form." + NAME - + ".value = urlize(this.value) }"); + "if (defaulting) { this.form." + NAME + + ".value = urlize(this.value) }"); add(titleWidget); final TextField nameWidget = new TextField(new TrimmedStringParameter( - NAME)); + NAME)); nameWidget.setLabel(getNameLabel()); nameWidget.setHint(getNameHint()); @@ -198,11 +199,11 @@ public abstract class FolderForm extends FormSection nameWidget.setMaxLength(190); nameWidget.setOnFocus("defaulting = false"); nameWidget.setOnBlur( - "if (this.value == '') " - + "{ defaulting = true; this.value = urlize(this.form." - + TITLE - + ".value) } " - + " else { this.value = urlize(this.value); }"); + "if (this.value == '') " + + "{ defaulting = true; this.value = urlize(this.form." + + TITLE + + ".value) } " + + " else { this.value = urlize(this.value); }"); add(nameWidget); } @@ -214,7 +215,7 @@ public abstract class FolderForm extends FormSection @Override public void generateXML(final PageState state, final Element parent) { - m_script.generateXML(state, parent); +// m_script.generateXML(state, parent); super.generateXML(state, parent); } @@ -228,7 +229,7 @@ public abstract class FolderForm extends FormSection */ @Override public abstract void init(final FormSectionEvent event) - throws FormProcessException; + throws FormProcessException; /** * Process the form. Children have to override this method to save the @@ -240,7 +241,7 @@ public abstract class FolderForm extends FormSection */ @Override public abstract void process(final FormSectionEvent event) - throws FormProcessException; + throws FormProcessException; /** * Validates the form. Checks for name uniqueness. @@ -251,11 +252,21 @@ public abstract class FolderForm extends FormSection */ @Override public void validate(final FormSectionEvent event) - throws FormProcessException { - Category folder = (Category) currentFolder.getSelectedObject(event - .getPageState()); - Assert.exists(folder); -// validateNameUniqueness(folder, event); + throws FormProcessException { + final Folder folder = getCurrentFolder(event.getPageState()); + final FormData data = event.getFormData(); + final String name = data.getString(NAME); + final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); + final CategoryManager categoryManager = cdiUtil.findBean( + CategoryManager.class); + + if (categoryManager.hasSubCategoryWithName(folder, name)) { + data.addError(new GlobalizedMessage( + "cms.ui.folderform.error.child.name_not_unique", + CmsConstants.CMS_BUNDLE, + new Object[]{name})); + } + } /** @@ -264,25 +275,23 @@ public abstract class FolderForm extends FormSection * @param component the component to add to this FolderForm * */ - @Override - public void add(final Component component) { - widgetSection.add(component); - } - +// @Override +// public void add(final Component component) { +// widgetSection.add(component); +// } /** * Adds a component with the specified layout constraints to this container. * Layout constraints are defined in each layout container as static ints. * Use a bitwise OR to specify multiple constraints. * - * @param component the component to add to this container + * @param component the component to add to this container * @param constraints layout constraints (a bitwise OR of static ints in the - * particular layout) + * particular layout) */ - @Override - public void add(final Component component, final int constraints) { - widgetSection.add(component, constraints); - } - +// @Override +// public void add(final Component component, final int constraints) { +// widgetSection.add(component, constraints); +// } /** * This method can be overridden to change the label of the title field. To * change to label of the title field can be useful for some content types. @@ -348,10 +357,10 @@ public abstract class FolderForm extends FormSection * * @param folder The folder to update * @param parent The new parent folder. May be null. - * @param name The new name of the folder - * @param label The new label for the folder + * @param name The new name of the folder + * @param label The new label for the folder */ - final protected void updateFolder(final Category folder, + final protected void updateFolder(final Folder folder, final Category parent, final String name, final String label) { @@ -363,23 +372,24 @@ public abstract class FolderForm extends FormSection * Updates a folder with a new name and label. * * @param folder The folder to update - * @param name The new name of the folder - * @param label The new label for the folder + * @param name The new name of the folder + * @param label The new label for the folder */ - final protected void updateFolder(final Category folder, + final protected void updateFolder(final Folder folder, final String name, final String label) { final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); - final ConfigurationManager confManager = cdiUtil.findBean(ConfigurationManager.class); + final ConfigurationManager confManager = cdiUtil.findBean( + ConfigurationManager.class); final KernelConfig kernelConfig = confManager.findConfiguration( - KernelConfig.class); + KernelConfig.class); folder.setName(name); folder.setDisplayName(name); folder.getTitle().addValue(kernelConfig.getDefaultLocale(), label); final CategoryRepository categoryRepo = cdiUtil.findBean( - CategoryRepository.class); + CategoryRepository.class); categoryRepo.save(folder); } @@ -387,12 +397,13 @@ public abstract class FolderForm extends FormSection * Returns the current folder being operated on. * * @param state + * * @return The current folder * */ - final protected Category getCurrentFolder(final PageState state) { - final Category folder = (Category) currentFolder - .getSelectedObject(state); + final protected Folder getCurrentFolder(final PageState state) { + final Folder folder = (Folder) currentFolder + .getSelectedObject(state); return folder; } diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderSelectionModel.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderSelectionModel.java index 1ae5e8fcd..c7f90484d 100755 --- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderSelectionModel.java +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderSelectionModel.java @@ -39,7 +39,7 @@ import org.librecms.contentsection.Folder; */ public class FolderSelectionModel extends CcmObjectSelectionModel { - public FolderSelectionModel(String name) { + public FolderSelectionModel(final String name) { super(Category.class.getName(), name); } diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderTreeModelBuilder.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderTreeModelBuilder.java index 6b506fdab..f193bc7b7 100755 --- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderTreeModelBuilder.java +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderTreeModelBuilder.java @@ -52,17 +52,17 @@ import org.libreccm.configuration.ConfigurationManager; * @author Jens Pelzetter */ public class FolderTreeModelBuilder extends LockableImpl - implements TreeModelBuilder { + implements TreeModelBuilder { /** * Make a tree model that lists the hierarchy of folders underneath the * folder returned by {@link #getRoot getRoot}. * - * @param tree the tree in which the model is used + * @param tree the tree in which the model is used * @param state represents the current request * * @return a tree model that lists the hierarchy of folders underneath the - * folder returned by {@link #getRoot getRoot}. + * folder returned by {@link #getRoot getRoot}. */ @Override public TreeModel makeModel(final Tree tree, final PageState state) { @@ -78,7 +78,7 @@ public class FolderTreeModelBuilder extends LockableImpl final PageState state) { final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); final FolderTreeModelController controller = cdiUtil.findBean( - FolderTreeModelController.class); + FolderTreeModelController.class); return controller.hasChildren(node); } @@ -90,7 +90,7 @@ public class FolderTreeModelBuilder extends LockableImpl // Always expand root node if (nodeKey.equals(getRoot(state).getKey().toString()) - && tree.isCollapsed(nodeKey, state)) { + && tree.isCollapsed(nodeKey, state)) { tree.expand(nodeKey, state); } @@ -100,13 +100,17 @@ public class FolderTreeModelBuilder extends LockableImpl final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); final FolderTreeModelController controller = cdiUtil.findBean( - FolderTreeModelController.class); + FolderTreeModelController.class); final List subFolders = controller.getChildren(node); return subFolders.stream() - .map(folder -> generateTreeNode(folder)) - .collect(Collectors.toList()) - .iterator(); + .map(folder -> generateTreeNode(folder)) + .sorted((node1, node2) -> { + return ((String) node1.getElement()) + .compareTo((String) node2.getElement()); + }) + .collect(Collectors.toList()) + .iterator(); } private TreeNode generateTreeNode(final Folder folder) { @@ -114,6 +118,7 @@ public class FolderTreeModelBuilder extends LockableImpl return node; } + }; /*return new DataQueryTreeModel(getRoot(state).getID(), @@ -170,7 +175,7 @@ public class FolderTreeModelBuilder extends LockableImpl * */ protected Folder getRootFolder(final PageState state) - throws IllegalStateException { + throws IllegalStateException { final ContentSection section = CMS.getContext().getContentSection(); return section.getRootDocumentsFolder(); @@ -193,17 +198,17 @@ public class FolderTreeModelBuilder extends LockableImpl public Object getElement() { final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); final GlobalizationHelper globalizationHelper = cdiUtil.findBean( - GlobalizationHelper.class); + GlobalizationHelper.class); final Locale locale = globalizationHelper.getNegotiatedLocale(); if (folder.getTitle().hasValue(locale)) { return folder.getTitle().getValue(locale); } else { final ConfigurationManager confManager = cdiUtil.findBean( - ConfigurationManager.class); + ConfigurationManager.class); final KernelConfig kernelConfig = confManager.findConfiguration( - KernelConfig.class); + KernelConfig.class); final String value = folder.getTitle().getValue(kernelConfig. - getDefaultLocale()); + getDefaultLocale()); if (value == null) { return folder.getName(); } else { @@ -211,6 +216,7 @@ public class FolderTreeModelBuilder extends LockableImpl } } } + } /*private class NewFolderBrowserIterator implements Iterator { diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/Folder.java b/ccm-cms/src/main/java/org/librecms/contentsection/Folder.java index f9ba65413..0d81af839 100644 --- a/ccm-cms/src/main/java/org/librecms/contentsection/Folder.java +++ b/ccm-cms/src/main/java/org/librecms/contentsection/Folder.java @@ -190,6 +190,10 @@ public class Folder extends Category implements Serializable { this.type = type; } + public Folder getParentFolder() { + return (Folder) getParentCategory(); + } + /** * A convenient method for getting all sub folders of folder. * diff --git a/ccm-cms/src/main/resources/org/librecms/CmsResources.properties b/ccm-cms/src/main/resources/org/librecms/CmsResources.properties index 688d316a3..7dcb4aa70 100644 --- a/ccm-cms/src/main/resources/org/librecms/CmsResources.properties +++ b/ccm-cms/src/main/resources/org/librecms/CmsResources.properties @@ -120,3 +120,6 @@ cms.ui.authoring.go=Go empty_text= cms.contenttypes.ui.title=Title cms.contenttypes.ui.name=Name (URL fragment) +cms.ui.content_section=Content Section: +cms.ui.folderform.error.child.name_not_unique=The current folder already contains a child with the name {0}. +cms.ui.folderform.error.parent.name_not_unique=The parent folder of the selected folder already contains a child with the name {0}. diff --git a/ccm-cms/src/main/resources/org/librecms/CmsResources_de.properties b/ccm-cms/src/main/resources/org/librecms/CmsResources_de.properties index a8c44a6d6..b59218687 100644 --- a/ccm-cms/src/main/resources/org/librecms/CmsResources_de.properties +++ b/ccm-cms/src/main/resources/org/librecms/CmsResources_de.properties @@ -119,3 +119,6 @@ cms.ui.authoring.go=Anlegen empty_text= cms.contenttypes.ui.title=Titel cms.contenttypes.ui.name=Name (URL-Fragment) +cms.ui.content_section=Content Section: +cms.ui.folderform.error.child.name_not_unique=Der derzeit ausgew\u00e4hlte Ordner enth\u00e4lt bereits einen Ordner oder ein Dokument mit dem Namen {0}. +cms.ui.folderform.error.parent.name_not_unique=Der \u00fcbergeordnete Ordner enth\u00e4lt bereits einen ein Objekt mit dem Namen {0}. diff --git a/ccm-cms/src/main/resources/org/librecms/CmsResources_fr.properties b/ccm-cms/src/main/resources/org/librecms/CmsResources_fr.properties index a1cfb39e7..dcb989af7 100644 --- a/ccm-cms/src/main/resources/org/librecms/CmsResources_fr.properties +++ b/ccm-cms/src/main/resources/org/librecms/CmsResources_fr.properties @@ -88,3 +88,6 @@ cms.ui.authoring.go=Go empty_text= cms.contenttypes.ui.title=Title cms.contenttypes.ui.name=Name (URL fragment) +cms.ui.content_section=Content Section: +cms.ui.folderform.error.child.name_not_unique=The current folder already contains a child with the name {0}. +cms.ui.folderform.error.parent.name_not_unique=The parent folder of the selected folder already contains a child with the name {0}. diff --git a/ccm-core/src/main/java/com/arsdigita/bebop/Form.java b/ccm-core/src/main/java/com/arsdigita/bebop/Form.java index afc666f42..17ad67632 100755 --- a/ccm-core/src/main/java/com/arsdigita/bebop/Form.java +++ b/ccm-core/src/main/java/com/arsdigita/bebop/Form.java @@ -435,9 +435,9 @@ public class Form extends FormSection implements BebopConstants { // Unless invisible form processing is turned on, don't run any // listeners if this form is not visible. - if (getProcessInvisible() || state.isVisibleOnPage(this)) { +// if (getProcessInvisible() || state.isVisibleOnPage(this)) { getModel().process(state, result); - } +// } return result; } diff --git a/ccm-core/src/main/java/com/arsdigita/ui/CcmObjectSelectionModel.java b/ccm-core/src/main/java/com/arsdigita/ui/CcmObjectSelectionModel.java index 26be3fb81..eefa97493 100644 --- a/ccm-core/src/main/java/com/arsdigita/ui/CcmObjectSelectionModel.java +++ b/ccm-core/src/main/java/com/arsdigita/ui/CcmObjectSelectionModel.java @@ -36,7 +36,7 @@ import org.libreccm.core.CcmObjectRepository; * */ public class CcmObjectSelectionModel - implements SingleSelectionModel { + implements SingleSelectionModel { private final Class clazz; private final SingleSelectionModel model; @@ -66,7 +66,7 @@ public class CcmObjectSelectionModel throw new RuntimeException(ex); } model = new ParameterSingleSelectionModel(new LongParameter( - parameterName)); + parameterName)); } public CcmObjectSelectionModel(final Class clazz, @@ -108,9 +108,11 @@ public class CcmObjectSelectionModel @Override public Long getSelectedKey(final PageState state) { final Object key = model.getSelectedKey(state); - if (key instanceof Long) { + if (key == null) { + return null; + } else if (key instanceof Long) { return (Long) key; - } else if(key instanceof String) { + } else if (key instanceof String) { return Long.parseLong((String) key); } else { return Long.parseLong(key.toString()); @@ -125,7 +127,7 @@ public class CcmObjectSelectionModel public T getSelectedObject(final PageState state) { final Long key = getSelectedKey(state); final CcmObjectRepository repository = CdiUtil.createCdiUtil().findBean( - CcmObjectRepository.class); + CcmObjectRepository.class); @SuppressWarnings("unchecked") final T object = (T) repository.findObjectById(key).get(); return object; diff --git a/ccm-core/src/main/java/org/libreccm/categorization/Category.java b/ccm-core/src/main/java/org/libreccm/categorization/Category.java index d1fcf8b46..08c35060f 100644 --- a/ccm-core/src/main/java/org/libreccm/categorization/Category.java +++ b/ccm-core/src/main/java/org/libreccm/categorization/Category.java @@ -90,6 +90,18 @@ import javax.xml.bind.annotation.XmlRootElement; query = "SELECT (CASE WHEN COUNT(c) > 0 THEN true ELSE false END) " + "FROM Category c " + "WHERE c.parentCategory = :category") + , + @NamedQuery( + name = "Category.findByNameAndParent", + query = "SELECT c FROM Category c " + + "WHERE c.name = :name AND c.parentCategory = :parent") + , + @NamedQuery( + name = "Category.hasSubCategoryWithName", + query = "SELECT (CASE WHEN COUNT(c) > 0 THEN true ELSE False END) " + + "FROM Category c " + + "WHERE c.name = :name AND c.parentCategory = :parent" + ) }) @NamedEntityGraphs({ @NamedEntityGraph( diff --git a/ccm-core/src/main/java/org/libreccm/categorization/CategoryManager.java b/ccm-core/src/main/java/org/libreccm/categorization/CategoryManager.java index 261005f0d..c2aba0ecd 100644 --- a/ccm-core/src/main/java/org/libreccm/categorization/CategoryManager.java +++ b/ccm-core/src/main/java/org/libreccm/categorization/CategoryManager.java @@ -524,6 +524,13 @@ public class CategoryManager { parentCategory.toString())); } + if (hasSubCategoryWithName(parent.get(), sub.get().getName())) { + throw new IllegalArgumentException(String.format( + "The provided category already has a sub category with " + + "the name '%s'.", + sub.get().getName())); + } + if (sub.get().getParentCategory() != null) { final Category oldParent = sub.get().getParentCategory(); removeSubCategoryFromCategory(sub.get(), oldParent); @@ -540,6 +547,35 @@ public class CategoryManager { }); } + /** + * Checks if a category has a sub category with the provided name. + * + * @param category The category. + * @param name The name. + * + * @return {@code true} if the provided {@code category} has a child with + * the provided {@code name}, {@code false} otherwise. + * + * @see {@link Category#name}. + */ + @Transactional(Transactional.TxType.REQUIRED) + public boolean hasSubCategoryWithName(final Category category, + final String name) { + Objects.requireNonNull(category, "category can't be null"); + Objects.requireNonNull(name, "name can't be null"); + + if (name.trim().isEmpty()) { + throw new IllegalArgumentException("name can't be empty."); + } + + final TypedQuery query = entityManager.createNamedQuery( + "Category.hasSubCategoryWithName", Boolean.class); + query.setParameter("name", name); + query.setParameter("parent", category); + + return query.getSingleResult(); + } + /** * Removes a sub category from its parent category. If the category is not * assigned to another parent category (or as root category to a diff --git a/ccm-theme-foundry/src/main/resources/themes/foundry/foundry/templates/admin-layout.xml b/ccm-theme-foundry/src/main/resources/themes/foundry/foundry/templates/admin-layout.xml index edaffdfe7..015bb5111 100644 --- a/ccm-theme-foundry/src/main/resources/themes/foundry/foundry/templates/admin-layout.xml +++ b/ccm-theme-foundry/src/main/resources/themes/foundry/foundry/templates/admin-layout.xml @@ -10,6 +10,7 @@