001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (https://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software, please see the
018 * company website: https://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: https://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.ui.sitemap;
029
030import org.opencms.file.CmsObject;
031import org.opencms.file.CmsResource;
032import org.opencms.file.CmsResourceFilter;
033import org.opencms.i18n.tools.CmsContainerPageCopier;
034import org.opencms.i18n.tools.CmsContainerPageCopier.NoCustomReplacementException;
035import org.opencms.main.CmsException;
036import org.opencms.main.CmsLog;
037import org.opencms.main.OpenCms;
038import org.opencms.ui.CmsVaadinUtils;
039import org.opencms.ui.I_CmsDialogContext;
040import org.opencms.ui.Messages;
041import org.opencms.ui.components.CmsBasicDialog;
042import org.opencms.ui.components.CmsErrorDialog;
043import org.opencms.ui.components.fileselect.CmsPathSelectField;
044import org.opencms.util.CmsStringUtil;
045import org.opencms.util.CmsUUID;
046
047import java.util.ArrayList;
048import java.util.Arrays;
049
050import org.apache.commons.logging.Log;
051
052import com.vaadin.ui.Button;
053import com.vaadin.ui.Button.ClickEvent;
054import com.vaadin.ui.Button.ClickListener;
055import com.vaadin.ui.FormLayout;
056import com.vaadin.ui.Notification;
057import com.vaadin.ui.Notification.Type;
058import com.vaadin.v7.ui.ComboBox;
059
060/**
061 * Dialog used to copy container pages including their elements.<p>
062 */
063public class CmsCopyPageDialog extends CmsBasicDialog {
064
065    /**
066     * Helper class used to interpret the target path in the 'copy page' dioalog.<p>
067     */
068    public class TargetInfo {
069
070        /** True if the target path or its parent is a file, not a folder. */
071        private boolean m_isFile;
072
073        /** The target folder. */
074        private CmsResource m_targetFolder;
075
076        /** The target name. */
077        private String m_targetName;
078
079        /**
080         * Creates a new instance.<p>
081         *
082         * @param cms the CMS context to use
083         * @param path the target path to analyze
084         */
085        @SuppressWarnings("synthetic-access")
086        public TargetInfo(CmsObject cms, String path) {
087
088            try {
089                if (CmsStringUtil.isPrefixPath(CmsResource.VFS_FOLDER_SITES, path)
090                    || (OpenCms.getSiteManager().getSiteForRootPath(path) != null)) {
091                    cms = OpenCms.initCmsObject(cms);
092                    cms.getRequestContext().setSiteRoot("");
093                }
094                CmsResource resource = readIfExists(cms, path);
095                if (resource != null) {
096                    if (resource.isFile()) {
097                        m_isFile = true;
098                    } else {
099                        m_targetFolder = resource;
100                    }
101                    return;
102                }
103                resource = readIfExists(cms, CmsResource.getParentFolder(path));
104                if (resource != null) {
105                    if (resource.isFile()) {
106                        m_isFile = true;
107                    } else {
108                        m_targetFolder = resource;
109                        m_targetName = CmsResource.getName(path);
110                    }
111                    return;
112                }
113            } catch (CmsException e) {
114                LOG.warn(e.getLocalizedMessage(), e);
115            }
116        }
117
118        /**
119         * Gets the target folder resource, or null if no target folder could be determined.<p>
120         *
121         * @return the target folder resource
122         */
123        public CmsResource getTargetFolder() {
124
125            return m_targetFolder;
126        }
127
128        /**
129         * Gets the target name, or null if only the target folder was given in the target select widget.<p>
130         *
131         * @return the target name
132         */
133        public String getTargetName() {
134
135            return m_targetName;
136        }
137
138        /**
139         * Returns true if the target path or its parent is actually a file.<p>
140         *
141         * @return true if the target path or its parent is a file
142         */
143        public boolean isFile() {
144
145            return m_isFile;
146        }
147
148        /**
149         * Returns true if the target folder could be determined from the target path.<p>
150         *
151         * @return true if the target folder could be determined
152         */
153        public boolean isValid() {
154
155            return m_targetFolder != null;
156        }
157
158        /**
159         * Helper method for reading a resource 'safely', i.e. without logging errors when it fails.<p>
160         *
161         * @param cms the CMS context
162         * @param path a resource path
163         *
164         * @return the resource, or null if the resource doesn't exist or couldn't be read
165         */
166        @SuppressWarnings("synthetic-access")
167        private CmsResource readIfExists(CmsObject cms, String path) {
168
169            if (cms.existsResource(path, CmsResourceFilter.IGNORE_EXPIRATION)) {
170                try {
171                    return cms.readResource(path, CmsResourceFilter.IGNORE_EXPIRATION);
172                } catch (Exception e) {
173                    LOG.warn(e.getLocalizedMessage(), e);
174                    return null;
175                }
176            } else {
177                return null;
178            }
179        }
180    }
181
182    /** The logger instance for this class. */
183    private static final Log LOG = CmsLog.getLog(CmsCopyPageDialog.class);
184
185    /** Serial version id. */
186    private static final long serialVersionUID = 1L;
187
188    /** The cancel button. */
189    private Button m_cancelButton;
190
191    /** The dialog context. */
192    private I_CmsDialogContext m_context;
193
194    /** The copy mode selection field. */
195    private ComboBox m_copyMode = new ComboBox();
196
197    /** The OK button. */
198    private Button m_okButton;
199
200    /** The field for selecting the target folder. */
201    private CmsPathSelectField m_targetSelect;
202
203    /**
204     * Creates a new instance.<p>
205     *
206     * @param context the dialog context
207     */
208    public CmsCopyPageDialog(I_CmsDialogContext context) {
209
210        m_context = context;
211        displayResourceInfo(context.getResources());
212        initButtons();
213        m_copyMode.setNullSelectionAllowed(false);
214        setContent(initContent());
215    }
216
217    /**
218     * Initializes the button bar.<p>
219     */
220    void initButtons() {
221
222        m_okButton = new Button(CmsVaadinUtils.getMessageText(org.opencms.workplace.Messages.GUI_DIALOG_BUTTON_OK_0));
223        m_okButton.addClickListener(new ClickListener() {
224
225            private static final long serialVersionUID = 1L;
226
227            public void buttonClick(ClickEvent event) {
228
229                onClickOk();
230            }
231        });
232        addButton(m_okButton);
233        m_cancelButton = new Button(
234            CmsVaadinUtils.getMessageText(org.opencms.workplace.Messages.GUI_DIALOG_BUTTON_CANCEL_0));
235        m_cancelButton.addClickListener(new ClickListener() {
236
237            private static final long serialVersionUID = 1L;
238
239            @SuppressWarnings("synthetic-access")
240            public void buttonClick(ClickEvent event) {
241
242                m_context.finish(new ArrayList<CmsUUID>());
243            }
244        });
245
246        addButton(m_cancelButton);
247    }
248
249    /**
250     * Method that is called when the OK button is clicked.<p>
251     */
252    void onClickOk() {
253
254        CmsContainerPageCopier copier = new CmsContainerPageCopier(m_context.getCms());
255        try {
256            CmsContainerPageCopier.CopyMode mode = (CmsContainerPageCopier.CopyMode)(m_copyMode.getValue());
257            copier.setCopyMode(mode);
258            TargetInfo info = new TargetInfo(m_context.getCms(), m_targetSelect.getValue());
259            if (!info.isValid()) {
260                Type type = Type.ERROR_MESSAGE;
261                String error = CmsVaadinUtils.getMessageText(Messages.GUI_COPYPAGE_INVALID_TARGET_0);
262                Notification.show(error, type);
263                return;
264            }
265            CmsResource targetFolder = info.getTargetFolder();
266            copier.run(m_context.getResources().get(0), targetFolder, info.getTargetName());
267            m_context.finish(
268                Arrays.asList(
269                    copier.getTargetFolder().getStructureId(),
270                    copier.getCopiedFolderOrPage().getStructureId()));
271        } catch (CmsException e) {
272            m_context.error(e);
273        } catch (NoCustomReplacementException e) {
274            String errorMessage = CmsVaadinUtils.getMessageText(
275                Messages.GUI_COPYPAGE_NO_REPLACEMENT_FOUND_1,
276                e.getResource().getRootPath());
277            CmsErrorDialog.showErrorDialog(errorMessage, e);
278        }
279    }
280
281    /**
282     * Gets the initial target path to display, based on the selected resource.<p>
283     *
284     * @param cms the cms context
285     * @param resource the selected resource
286     *
287     * @return the initial target path
288     */
289    private String getInitialTarget(CmsObject cms, CmsResource resource) {
290
291        String sitePath = cms.getSitePath(resource);
292        String parent = CmsResource.getParentFolder(sitePath);
293        if (parent != null) {
294            return parent;
295        } else {
296            String rootParent = CmsResource.getParentFolder(resource.getRootPath());
297            if (rootParent != null) {
298                return rootParent;
299            } else {
300                return sitePath;
301            }
302        }
303    }
304
305    /**
306     * Initializes the content panel.<p>
307     *
308     * @return the content panel
309     */
310    private FormLayout initContent() {
311
312        FormLayout form = new FormLayout();
313        CmsPathSelectField field = new CmsPathSelectField();
314        field.setValue(getInitialTarget(m_context.getCms(), m_context.getResources().get(0)));
315        field.setStartWithSitempaView(true);
316        field.setResourceFilter(CmsResourceFilter.IGNORE_EXPIRATION.addRequireFolder());
317        field.setCaption(CmsVaadinUtils.getMessageText(org.opencms.workplace.commons.Messages.GUI_COPY_MOVE_TARGET_0));
318        form.addComponent(field);
319        m_targetSelect = field;
320        m_copyMode.addItem(CmsContainerPageCopier.CopyMode.automatic);
321        m_copyMode.setItemCaption(
322            CmsContainerPageCopier.CopyMode.automatic,
323            CmsVaadinUtils.getMessageText(Messages.GUI_COPYPAGE_MODE_AUTO_0));
324
325        m_copyMode.addItem(CmsContainerPageCopier.CopyMode.smartCopyAndChangeLocale);
326        m_copyMode.setItemCaption(
327            CmsContainerPageCopier.CopyMode.smartCopyAndChangeLocale,
328            CmsVaadinUtils.getMessageText(Messages.GUI_COPYPAGE_MODE_SMART_0));
329        m_copyMode.addItem(CmsContainerPageCopier.CopyMode.reuse);
330        m_copyMode.setItemCaption(
331            CmsContainerPageCopier.CopyMode.reuse,
332            CmsVaadinUtils.getMessageText(Messages.GUI_COPYPAGE_MODE_REUSE_0));
333        m_copyMode.setValue(CmsContainerPageCopier.CopyMode.automatic);
334        form.addComponent(m_copyMode);
335        m_copyMode.setCaption(CmsVaadinUtils.getMessageText(Messages.GUI_COPYPAGE_COPY_MODE_0));
336        return form;
337    }
338
339}