001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://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: http://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: http://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.v7.ui.ComboBox;
056import com.vaadin.ui.FormLayout;
057import com.vaadin.ui.Notification;
058import com.vaadin.ui.Notification.Type;
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            try {
088                if (CmsStringUtil.isPrefixPath(CmsResource.VFS_FOLDER_SITES, path)
089                    || (OpenCms.getSiteManager().getSiteForRootPath(path) != null)) {
090                    cms = OpenCms.initCmsObject(cms);
091                    cms.getRequestContext().setSiteRoot("");
092                }
093                CmsResource resource = readIfExists(cms, path);
094                if (resource != null) {
095                    if (resource.isFile()) {
096                        m_isFile = true;
097                    } else {
098                        m_targetFolder = resource;
099                    }
100                    return;
101                }
102                resource = readIfExists(cms, CmsResource.getParentFolder(path));
103                if (resource != null) {
104                    if (resource.isFile()) {
105                        m_isFile = true;
106                    } else {
107                        m_targetFolder = resource;
108                        m_targetName = CmsResource.getName(path);
109                    }
110                    return;
111                }
112            } catch (CmsException e) {
113                LOG.warn(e.getLocalizedMessage(), e);
114            }
115        }
116
117        /**
118         * Gets the target folder resource, or null if no target folder could be determined.<p>
119         *
120         * @return the target folder resource
121         */
122        public CmsResource getTargetFolder() {
123
124            return m_targetFolder;
125        }
126
127        /**
128         * Gets the target name, or null if only the target folder was given in the target select widget.<p>
129         *
130         * @return the target name
131         */
132        public String getTargetName() {
133
134            return m_targetName;
135        }
136
137        /**
138         * Returns true if the target path or its parent is actually a file.<p>
139         *
140         * @return true if the target path or its parent is a file
141         */
142        public boolean isFile() {
143
144            return m_isFile;
145        }
146
147        /**
148         * Returns true if the target folder could be determined from the target path.<p>
149         *
150         * @return true if the target folder could be determined
151         */
152        public boolean isValid() {
153
154            return m_targetFolder != null;
155        }
156
157        /**
158         * Helper method for reading a resource 'safely', i.e. without logging errors when it fails.<p>
159         *
160         * @param cms the CMS context
161         * @param path a resource path
162         *
163         * @return the resource, or null if the resource doesn't exist or couldn't be read
164         */
165        @SuppressWarnings("synthetic-access")
166        private CmsResource readIfExists(CmsObject cms, String path) {
167
168            if (cms.existsResource(path, CmsResourceFilter.IGNORE_EXPIRATION)) {
169                try {
170                    return cms.readResource(path, CmsResourceFilter.IGNORE_EXPIRATION);
171                } catch (Exception e) {
172                    LOG.warn(e.getLocalizedMessage(), e);
173                    return null;
174                }
175            } else {
176                return null;
177            }
178        }
179    }
180
181    /** The logger instance for this class. */
182    private static final Log LOG = CmsLog.getLog(CmsCopyPageDialog.class);
183
184    /** Serial version id. */
185    private static final long serialVersionUID = 1L;
186
187    /** The cancel button. */
188    private Button m_cancelButton;
189
190    /** The dialog context. */
191    private I_CmsDialogContext m_context;
192
193    /** The copy mode selection field. */
194    private ComboBox m_copyMode = new ComboBox();
195
196    /** The OK button. */
197    private Button m_okButton;
198
199    /** The field for selecting the target folder. */
200    private CmsPathSelectField m_targetSelect;
201
202    /**
203     * Creates a new instance.<p>
204     *
205     * @param context the dialog context
206     */
207    public CmsCopyPageDialog(I_CmsDialogContext context) {
208        m_context = context;
209        displayResourceInfo(context.getResources());
210        initButtons();
211        m_copyMode.setNullSelectionAllowed(false);
212        setContent(initContent());
213    }
214
215    /**
216     * Initializes the button bar.<p>
217     */
218    void initButtons() {
219
220        m_okButton = new Button(CmsVaadinUtils.getMessageText(org.opencms.workplace.Messages.GUI_DIALOG_BUTTON_OK_0));
221        m_okButton.addClickListener(new ClickListener() {
222
223            private static final long serialVersionUID = 1L;
224
225            public void buttonClick(ClickEvent event) {
226
227                onClickOk();
228            }
229        });
230        addButton(m_okButton);
231        m_cancelButton = new Button(
232            CmsVaadinUtils.getMessageText(org.opencms.workplace.Messages.GUI_DIALOG_BUTTON_CANCEL_0));
233        m_cancelButton.addClickListener(new ClickListener() {
234
235            private static final long serialVersionUID = 1L;
236
237            @SuppressWarnings("synthetic-access")
238            public void buttonClick(ClickEvent event) {
239
240                m_context.finish(new ArrayList<CmsUUID>());
241            }
242        });
243
244        addButton(m_cancelButton);
245    }
246
247    /**
248     * Method that is called when the OK button is clicked.<p>
249     */
250    void onClickOk() {
251
252        CmsContainerPageCopier copier = new CmsContainerPageCopier(m_context.getCms());
253        try {
254            CmsContainerPageCopier.CopyMode mode = (CmsContainerPageCopier.CopyMode)(m_copyMode.getValue());
255            copier.setCopyMode(mode);
256            TargetInfo info = new TargetInfo(m_context.getCms(), m_targetSelect.getValue());
257            if (!info.isValid()) {
258                Type type = Type.ERROR_MESSAGE;
259                String error = CmsVaadinUtils.getMessageText(Messages.GUI_COPYPAGE_INVALID_TARGET_0);
260                Notification.show(error, type);
261                return;
262            }
263            CmsResource targetFolder = info.getTargetFolder();
264            copier.run(m_context.getResources().get(0), targetFolder, info.getTargetName());
265            m_context.finish(
266                Arrays.asList(
267                    copier.getTargetFolder().getStructureId(),
268                    copier.getCopiedFolderOrPage().getStructureId()));
269        } catch (CmsException e) {
270            m_context.error(e);
271        } catch (NoCustomReplacementException e) {
272            String errorMessage = CmsVaadinUtils.getMessageText(
273                Messages.GUI_COPYPAGE_NO_REPLACEMENT_FOUND_1,
274                e.getResource().getRootPath());
275            CmsErrorDialog.showErrorDialog(errorMessage, e);
276        }
277    }
278
279    /**
280     * Gets the initial target path to display, based on the selected resource.<p>
281     *
282     * @param cms the cms context
283     * @param resource the selected resource
284     *
285     * @return the initial target path
286     */
287    private String getInitialTarget(CmsObject cms, CmsResource resource) {
288
289        String sitePath = cms.getSitePath(resource);
290        String parent = CmsResource.getParentFolder(sitePath);
291        if (parent != null) {
292            return parent;
293        } else {
294            String rootParent = CmsResource.getParentFolder(resource.getRootPath());
295            if (rootParent != null) {
296                return rootParent;
297            } else {
298                return sitePath;
299            }
300        }
301    }
302
303    /**
304     * Initializes the content panel.<p>
305     *
306     * @return the content panel
307     */
308    private FormLayout initContent() {
309
310        FormLayout form = new FormLayout();
311        CmsPathSelectField field = new CmsPathSelectField();
312        field.setValue(getInitialTarget(m_context.getCms(), m_context.getResources().get(0)));
313        field.setStartWithSitempaView(true);
314        field.setResourceFilter(CmsResourceFilter.IGNORE_EXPIRATION.addRequireFolder());
315        field.setCaption(CmsVaadinUtils.getMessageText(org.opencms.workplace.commons.Messages.GUI_COPY_MOVE_TARGET_0));
316        form.addComponent(field);
317        m_targetSelect = field;
318        m_copyMode.addItem(CmsContainerPageCopier.CopyMode.automatic);
319        m_copyMode.setItemCaption(
320            CmsContainerPageCopier.CopyMode.automatic,
321            CmsVaadinUtils.getMessageText(Messages.GUI_COPYPAGE_MODE_AUTO_0));
322
323        m_copyMode.addItem(CmsContainerPageCopier.CopyMode.smartCopyAndChangeLocale);
324        m_copyMode.setItemCaption(
325            CmsContainerPageCopier.CopyMode.smartCopyAndChangeLocale,
326            CmsVaadinUtils.getMessageText(Messages.GUI_COPYPAGE_MODE_SMART_0));
327        m_copyMode.addItem(CmsContainerPageCopier.CopyMode.reuse);
328        m_copyMode.setItemCaption(
329            CmsContainerPageCopier.CopyMode.reuse,
330            CmsVaadinUtils.getMessageText(Messages.GUI_COPYPAGE_MODE_REUSE_0));
331        m_copyMode.setValue(CmsContainerPageCopier.CopyMode.automatic);
332        form.addComponent(m_copyMode);
333        m_copyMode.setCaption(CmsVaadinUtils.getMessageText(Messages.GUI_COPYPAGE_COPY_MODE_0));
334        return form;
335    }
336
337}