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 GmbH & Co. KG, 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.workplace.commons;
029
030import org.opencms.file.CmsProperty;
031import org.opencms.file.CmsPropertyDefinition;
032import org.opencms.file.CmsResource;
033import org.opencms.file.CmsResourceFilter;
034import org.opencms.file.types.CmsResourceTypeImage;
035import org.opencms.jsp.CmsJspActionElement;
036import org.opencms.main.CmsException;
037import org.opencms.main.OpenCms;
038import org.opencms.security.CmsPermissionSet;
039import org.opencms.util.CmsStringUtil;
040import org.opencms.util.PrintfFormat;
041import org.opencms.workplace.CmsDialog;
042import org.opencms.workplace.CmsWorkplaceSettings;
043
044import java.util.ArrayList;
045import java.util.Iterator;
046import java.util.List;
047
048import javax.servlet.http.HttpServletRequest;
049import javax.servlet.http.HttpServletResponse;
050import javax.servlet.jsp.JspException;
051import javax.servlet.jsp.PageContext;
052
053/**
054 * Provides methods for the rename images dialog.<p>
055 *
056 * The following files use this class:
057 * <ul>
058 * <li>/commons/renameimages.jsp
059 * </ul>
060 * <p>
061 *
062 * @since 6.1.3
063 */
064public class CmsRenameImages extends CmsDialog {
065
066    /** Value for the action: rename images. */
067    public static final int ACTION_RENAMEIMAGES = 100;
068
069    /** The dialog type. */
070    public static final String DIALOG_TYPE = "renameimages";
071
072    /** Selectbox option for decimal places selection: 1 place. */
073    public static final String OPTION_DECIMALPLACES_1 = "1 (1, 2, ..., 9)";
074
075    /** Selectbox option for decimal places selection: 2 places. */
076    public static final String OPTION_DECIMALPLACES_2 = "2 (01, 02, ..., 99)";
077
078    /** Selectbox option for decimal places selection: 3 places. */
079    public static final String OPTION_DECIMALPLACES_3 = "3 (001, 002, ..., 999)";
080
081    /** Selectbox option for decimal places selection: 4 places. */
082    public static final String OPTION_DECIMALPLACES_4 = "4 (0001, 0002, ..., 9999)";
083
084    /** Request parameter name for the counter places. */
085    public static final String PARAM_PLACES = "places";
086
087    /** Request parameter name for the image prefix. */
088    public static final String PARAM_PREFIX = "prefix";
089
090    /** Request parameter name for the remove title flag. */
091    public static final String PARAM_REMOVETITLE = "removetitle";
092
093    /** Request parameter name for the start count. */
094    public static final String PARAM_STARTCOUNT = "startcount";
095
096    /** Dialog parameter. */
097    private String m_paramPlaces;
098
099    /** Dialog parameter. */
100    private String m_paramPrefix;
101
102    /** Dialog parameter. */
103    private String m_paramRemovetitle;
104
105    /** Dialog parameter. */
106    private String m_paramStartcount;
107
108    /**
109     * Public constructor with JSP action element.<p>
110     *
111     * @param jsp an initialized JSP action element
112     */
113    public CmsRenameImages(CmsJspActionElement jsp) {
114
115        super(jsp);
116    }
117
118    /**
119     * Public constructor with JSP variables.<p>
120     *
121     * @param context the JSP page context
122     * @param req the JSP request
123     * @param res the JSP response
124     */
125    public CmsRenameImages(PageContext context, HttpServletRequest req, HttpServletResponse res) {
126
127        this(new CmsJspActionElement(context, req, res));
128    }
129
130    /**
131     * Performs the rename images action, will be called by the JSP page.<p>
132     *
133     * @throws JspException if problems including sub-elements occur
134     */
135    public void actionRenameImages() throws JspException {
136
137        // save initialized instance of this class in request attribute for included sub-elements
138        getJsp().getRequest().setAttribute(SESSION_WORKPLACE_CLASS, this);
139        try {
140            if (performDialogOperation()) {
141                // if no exception is caused and "true" is returned rename operation was successful
142                actionCloseDialog();
143            } else {
144                // "false" returned, display "please wait" screen
145                getJsp().include(FILE_DIALOG_SCREEN_WAIT);
146            }
147        } catch (Throwable e) {
148            // error during rename images, show error dialog
149            includeErrorpage(this, e);
150        }
151    }
152
153    /**
154     * Returns information about the image count of the selected gallery folder.<p>
155     *
156     * @return information about the image count of the selected gallery folder
157     */
158    public String buildImageInformation() {
159
160        // count all image resources of the gallery folder
161        int count = 0;
162        try {
163            int imageId = OpenCms.getResourceManager().getResourceType(
164                CmsResourceTypeImage.getStaticTypeName()).getTypeId();
165            CmsResourceFilter filter = CmsResourceFilter.IGNORE_EXPIRATION.addRequireType(imageId);
166            List<CmsResource> images = getCms().readResources(getParamResource(), filter, false);
167            count = images.size();
168        } catch (CmsException e) {
169            // ignore this exception
170        }
171
172        Object[] args = new Object[] {getParamResource(), Integer.valueOf(count)};
173        return key(Messages.GUI_RENAMEIMAGES_INFO_IMAGECOUNT_2, args);
174    }
175
176    /**
177     * Builds the html for the default copy folder mode select box.<p>
178     *
179     * @param htmlAttributes optional html attributes for the &lgt;select&gt; tag
180     * @return the html for the default copy folder mode select box
181     */
182    public String buildSelectPlaces(String htmlAttributes) {
183
184        List<String> options = new ArrayList<String>(4);
185        options.add(OPTION_DECIMALPLACES_1);
186        options.add(OPTION_DECIMALPLACES_2);
187        options.add(OPTION_DECIMALPLACES_3);
188        options.add(OPTION_DECIMALPLACES_4);
189        List<String> values = new ArrayList<String>(4);
190        values.add("1");
191        values.add("2");
192        values.add("3");
193        values.add("4");
194        int selectedIndex = 2;
195        if (getAction() != ACTION_DEFAULT) {
196            selectedIndex = values.indexOf(getParamPlaces());
197        }
198        return buildSelect(htmlAttributes, options, values, selectedIndex);
199    }
200
201    /**
202     * Returns the default prefix shown when opening the dialog.<p>
203     *
204     * @return the default prefix shown when opening the dialog
205     */
206    public String getDefaultPrefix() {
207
208        return key(Messages.GUI_RENAMEIMAGES_DEFAULT_PREFIX_0);
209    }
210
211    /**
212     * Returns the default start count shown when opening the dialog.<p>
213     *
214     * @return the default start count shown when opening the dialog
215     */
216    public String getDefaultStartcount() {
217
218        return "1";
219    }
220
221    /**
222     * Returns the value of the places parameter.<p>
223     *
224     * @return the value of the places parameter
225     */
226    public String getParamPlaces() {
227
228        return m_paramPlaces;
229    }
230
231    /**
232     * Returns the value of the prefix parameter.<p>
233     *
234     * @return the value of the prefix parameter
235     */
236    public String getParamPrefix() {
237
238        return m_paramPrefix;
239    }
240
241    /**
242     * Returns the value of the remove title parameter.<p>
243     *
244     * @return the value of the remove title parameter
245     */
246    public String getParamRemovetitle() {
247
248        return m_paramRemovetitle;
249    }
250
251    /**
252     * Returns the value of the startcount parameter.<p>
253     *
254     * @return the value of the startcount parameter
255     */
256    public String getParamStartcount() {
257
258        return m_paramStartcount;
259    }
260
261    /**
262     * Sets the value of the places parameter.<p>
263     *
264     * @param paramPlaces the value of the places parameter
265     */
266    public void setParamPlaces(String paramPlaces) {
267
268        m_paramPlaces = paramPlaces;
269    }
270
271    /**
272     * Sets the value of the prefix parameter.<p>
273     *
274     * @param paramPrefix the value of the prefix parameter
275     */
276    public void setParamPrefix(String paramPrefix) {
277
278        m_paramPrefix = paramPrefix;
279    }
280
281    /**
282     * Sets the value of the remove title parameter.<p>
283     *
284     * @param paramRemovetitle the value of the remove title parameter
285     */
286    public void setParamRemovetitle(String paramRemovetitle) {
287
288        m_paramRemovetitle = paramRemovetitle;
289    }
290
291    /**
292     * Sets the value of the startcount parameter.<p>
293     *
294     * @param paramStartcount the value of the startcount parameter
295     */
296    public void setParamStartcount(String paramStartcount) {
297
298        m_paramStartcount = paramStartcount;
299    }
300
301    /**
302     * @see org.opencms.workplace.CmsWorkplace#initWorkplaceRequestValues(org.opencms.workplace.CmsWorkplaceSettings, javax.servlet.http.HttpServletRequest)
303     */
304    @Override
305    protected void initWorkplaceRequestValues(CmsWorkplaceSettings settings, HttpServletRequest request) {
306
307        // fill the parameter values in the get/set methods
308        fillParamValues(request);
309
310        // check the required permissions to rename the resource
311        if (!checkResourcePermissions(CmsPermissionSet.ACCESS_WRITE, false)) {
312            // no write permissions for the resource, set cancel action to close dialog
313            setParamAction(DIALOG_CANCEL);
314        }
315
316        // set the dialog type
317        setParamDialogtype(DIALOG_TYPE);
318        // set the action for the JSP switch
319        if (DIALOG_TYPE.equals(getParamAction())) {
320            setAction(ACTION_RENAMEIMAGES);
321        } else if (DIALOG_WAIT.equals(getParamAction())) {
322            setAction(ACTION_WAIT);
323        } else if (DIALOG_LOCKS_CONFIRMED.equals(getParamAction())) {
324            setAction(ACTION_LOCKS_CONFIRMED);
325        } else if (DIALOG_CANCEL.equals(getParamAction())) {
326            setAction(ACTION_CANCEL);
327        } else {
328            setAction(ACTION_DEFAULT);
329            // build title for rename images dialog
330            Object[] args = new Object[] {getParamResource()};
331            setParamTitle(key(Messages.GUI_RENAMEIMAGES_TITLE_1, args));
332        }
333    }
334
335    /**
336     * Performs the rename images operation.<p>
337     *
338     * @return true, if the resources were successfully renamed, otherwise false
339     * @throws CmsException if renaming is not successful
340     */
341    protected boolean performDialogOperation() throws CmsException {
342
343        // display "please wait" screen before renaming the images
344        if (!DIALOG_WAIT.equals(getParamAction())) {
345            // return false, this will trigger the "please wait" screen
346            return false;
347        }
348
349        // lock the image gallery folder
350        checkLock(getParamResource());
351
352        // get all image resources of the folder
353        int imageId = OpenCms.getResourceManager().getResourceType(
354            CmsResourceTypeImage.getStaticTypeName()).getTypeId();
355        CmsResourceFilter filter = CmsResourceFilter.IGNORE_EXPIRATION.addRequireType(imageId);
356        List<CmsResource> images = getCms().readResources(getParamResource(), filter, false);
357
358        // determine start count
359        int count = 1;
360        try {
361            count = Integer.parseInt(getParamStartcount());
362        } catch (Exception e) {
363            // ignore this exception
364        }
365
366        // create number printer instance
367        PrintfFormat numberFormat = new PrintfFormat("%0." + getParamPlaces() + "d");
368
369        // create image galler folder name
370        String folder = getParamResource();
371        if (!folder.endsWith("/")) {
372            folder += "/";
373        }
374
375        Iterator<CmsResource> i = images.iterator();
376        // loop over all image resource to change
377        while (i.hasNext()) {
378            CmsResource res = i.next();
379            String oldName = CmsResource.getName(res.getRootPath());
380            CmsProperty titleProperty = getCms().readPropertyObject(res, CmsPropertyDefinition.PROPERTY_TITLE, false);
381            String oldTitle = titleProperty.getValue();
382
383            // store image name suffix
384            int lastDot = oldName.lastIndexOf('.');
385            String suffix = "";
386            String oldNameWithoutSuffix = oldName;
387            if (lastDot > -1) {
388                suffix = oldName.substring(lastDot);
389                oldNameWithoutSuffix = oldName.substring(0, lastDot);
390            }
391
392            // determine new image name
393            String newName = "";
394            if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(getParamPrefix()) && !"null".equals(getParamPrefix())) {
395                newName += getParamPrefix();
396            }
397            // create image number
398            String imageNumber = numberFormat.sprintf(count);
399            newName += imageNumber + suffix;
400
401            if (!newName.equals(oldName)) {
402                // only rename resources which have a new resource name
403                if (getCms().existsResource(folder + newName, CmsResourceFilter.ALL)) {
404                    // target resource exists, interrupt & show error
405                    throw new CmsException(
406                        Messages.get().container(
407                            Messages.ERR_MOVE_FAILED_TARGET_EXISTS_2,
408                            getCms().getSitePath(res),
409                            folder + newName));
410                }
411
412                // determine the new title property value
413                if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(oldTitle)) {
414                    if (oldTitle.equals(oldNameWithoutSuffix)) {
415                        if (Boolean.valueOf(getParamRemovetitle()).booleanValue()) {
416                            // remove the title property value
417                            if (oldTitle.equals(titleProperty.getStructureValue())) {
418                                titleProperty.setStructureValue(CmsProperty.DELETE_VALUE);
419                            }
420                            if (oldTitle.equals(titleProperty.getResourceValue())) {
421                                titleProperty.setResourceValue(CmsProperty.DELETE_VALUE);
422                            }
423                        } else {
424                            // set the title property to the new resource name
425                            if (oldTitle.equals(titleProperty.getStructureValue())) {
426                                titleProperty.setStructureValue(getParamPrefix() + imageNumber);
427                            } else if (oldTitle.equals(titleProperty.getResourceValue())) {
428                                titleProperty.setResourceValue(getParamPrefix() + imageNumber);
429                            }
430                        }
431                        // write changed title property
432                        getCms().writePropertyObject(getCms().getSitePath(res), titleProperty);
433                    }
434                }
435
436                // now rename the resource
437                getCms().renameResource(folder + oldName, folder + newName);
438            }
439
440            // increase image counter
441            count++;
442        }
443
444        return true;
445    }
446
447}