001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Mananagement 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.editors;
029
030import org.opencms.file.CmsFile;
031import org.opencms.file.CmsObject;
032import org.opencms.file.CmsResourceFilter;
033import org.opencms.i18n.CmsLocaleManager;
034import org.opencms.jsp.CmsJspActionElement;
035import org.opencms.main.CmsException;
036import org.opencms.main.CmsLog;
037import org.opencms.main.OpenCms;
038import org.opencms.util.CmsUUID;
039import org.opencms.workplace.CmsDialog;
040import org.opencms.workplace.CmsWorkplaceSettings;
041import org.opencms.xml.content.CmsXmlContent;
042import org.opencms.xml.content.CmsXmlContentFactory;
043
044import java.io.UnsupportedEncodingException;
045import java.util.ArrayList;
046import java.util.HashSet;
047import java.util.Iterator;
048import java.util.List;
049import java.util.Locale;
050import java.util.Set;
051
052import javax.servlet.http.HttpServletRequest;
053import javax.servlet.http.HttpServletResponse;
054import javax.servlet.jsp.JspException;
055import javax.servlet.jsp.PageContext;
056
057import org.apache.commons.logging.Log;
058
059/**
060 * Provides methods for the editor copy language dialog.<p>
061 *
062 * The following files use this class:
063 * <ul>
064 * <li>/jsp/editors/dialogs/copylanguage.html
065 * </ul>
066 * <p>
067 *
068 * @since 6.5.6
069 */
070public class CmsDialogCopyLanguage extends CmsDialog {
071
072    /** Value for the action: update languages of the page. */
073    public static final int ACTION_UPDATE_LANGUAGES = 310;
074
075    /** The dialog type. */
076    public static final String DIALOG_TYPE = "copylanguages";
077
078    /** Request parameter value for the action: update the elements of the page. */
079    public static final String DIALOG_UPDATE_LANGUAGES = "updatelanguages";
080
081    /** Param name for the html checkbox field for the language. */
082    public static final String PARAM_LANGUAGE = "language";
083
084    /** The log object for this class. */
085    private static final Log LOG = CmsLog.getLog(CmsDialogCopyLanguage.class);
086
087    /** The element locale. */
088    private Locale m_elementLocale;
089
090    /** Element language parameter. */
091    private String m_paramElementlanguage;
092
093    /** The selected languages. */
094    private Set<String> m_paramSelectedLanguages;
095
096    /** Temporary file parameter. */
097    private String m_paramTempFile;
098
099    /**
100     * Public constructor.<p>
101     *
102     * @param jsp an initialized JSP action element
103     */
104    public CmsDialogCopyLanguage(CmsJspActionElement jsp) {
105
106        super(jsp);
107    }
108
109    /**
110     * Public constructor with JSP variables.<p>
111     *
112     * @param context the JSP page context
113     * @param req the JSP request
114     * @param res the JSP response
115     */
116    public CmsDialogCopyLanguage(PageContext context, HttpServletRequest req, HttpServletResponse res) {
117
118        this(new CmsJspActionElement(context, req, res));
119    }
120
121    /**
122     * Updates the languages of the current xmlcontent by copying from the current language.<p>
123     *
124     * @throws JspException if there is an error including the error page
125     */
126    public void actionUpdateLanguages() throws JspException {
127
128        if ((m_paramSelectedLanguages != null) && !m_paramSelectedLanguages.isEmpty()) {
129            try {
130                CmsFile file = getCms().readFile(getParamTempfile(), CmsResourceFilter.IGNORE_EXPIRATION);
131                CmsXmlContent content = CmsXmlContentFactory.unmarshal(getCms(), file);
132
133                List<Locale> toLocales = new ArrayList<Locale>();
134                for (Iterator<String> i = m_paramSelectedLanguages.iterator(); i.hasNext();) {
135                    String language = i.next();
136                    toLocales.add(CmsLocaleManager.getLocale(language));
137                }
138
139                // now transfer the contents
140                transferContents(content, getElementLocale(), toLocales);
141
142                // write the temporary file
143                String decodedContent = content.toString();
144                try {
145                    file.setContents(decodedContent.getBytes(content.getEncoding()));
146                } catch (UnsupportedEncodingException e) {
147                    throw new CmsException(
148                        Messages.get().container(Messages.ERR_INVALID_CONTENT_ENC_1, getParamResource()),
149                        e);
150                }
151                // the file content might have been modified during the write operation
152                CmsObject cloneCms = OpenCms.initCmsObject(getCms());
153                CmsUUID tempProjectId = OpenCms.getWorkplaceManager().getTempFileProjectId();
154                cloneCms.getRequestContext().setCurrentProject(getCms().readProject(tempProjectId));
155                cloneCms.writeFile(file);
156
157            } catch (Throwable e) {
158                // show error dialog
159                setParamMessage(Messages.get().getBundle(getLocale()).key(Messages.ERR_UPDATE_LANGUAGES_0));
160                includeErrorpage(this, e);
161            }
162        }
163    }
164
165    /**
166     * Builds the html String for a form list of all possible page elements.<p>
167     *
168     * @return the html String for a form list
169     */
170    public String buildLanguageList() {
171
172        try {
173            StringBuffer retValue = new StringBuffer(512);
174            retValue.append("<table border=\"0\">\n");
175
176            // get locale for current element
177            Locale elLocale = getElementLocale();
178
179            // get locale names based on properties and global settings
180            List<Locale> localeList = OpenCms.getLocaleManager().getAvailableLocales(getCms(), getParamTempfile());
181
182            // read xml content for checking locale availability
183            CmsFile file = getCms().readFile(getParamTempfile(), CmsResourceFilter.IGNORE_EXPIRATION);
184            CmsXmlContent content = CmsXmlContentFactory.unmarshal(getCms(), file);
185
186            // show all possible elements
187            Iterator<Locale> i = localeList.iterator();
188            while (i.hasNext()) {
189                // get the current list element
190                Locale curLocale = i.next();
191
192                // skip locale of current element
193                if (elLocale.equals(curLocale)) {
194                    continue;
195                }
196
197                // build an element row
198                retValue.append("<tr>\n");
199                retValue.append("\t<td class=\"textcenter\" unselectable=\"on\"><input type=\"checkbox\" name=\"");
200                retValue.append(PARAM_LANGUAGE);
201                retValue.append("\" value=\"");
202                retValue.append(curLocale.toString());
203                retValue.append("\">");
204                retValue.append("</td>\n");
205                retValue.append("\t<td style=\"white-space: nowrap;\" unselectable=\"on\">");
206                retValue.append(curLocale.getDisplayName(getLocale()));
207                retValue.append(!content.hasLocale(curLocale) ? " [-]" : "");
208                retValue.append("</td>\n");
209                retValue.append("\t<td style=\"white-space: nowrap;\" unselectable=\"on\">");
210                retValue.append(
211                    !content.hasLocale(curLocale)
212                    ? Messages.get().getBundle(getLocale()).key(Messages.GUI_EDITOR_DIALOG_COPYLANGUAGE_NEW_0)
213                    : "");
214                retValue.append("</td>\n");
215
216                retValue.append("</tr>\n");
217            }
218
219            retValue.append("</table>\n");
220            return retValue.toString();
221
222        } catch (Throwable e) {
223            // should usually never happen
224            if (LOG.isInfoEnabled()) {
225                LOG.info(e.getLocalizedMessage(), e);
226            }
227            return "";
228        }
229    }
230
231    /**
232     * Returns the current element locale.<p>
233     *
234     * @return the current element locale
235     */
236    public Locale getElementLocale() {
237
238        if (m_elementLocale == null) {
239            m_elementLocale = CmsLocaleManager.getLocale(getParamElementLanguage());
240        }
241        return m_elementLocale;
242    }
243
244    /**
245     * Returns the current element language.<p>
246     *
247     * @return the current element language
248     */
249    public String getParamElementLanguage() {
250
251        return m_paramElementlanguage;
252    }
253
254    /**
255     * Returns the name of the temporary file.<p>
256     *
257     * @return the name of the temporary file
258     */
259    public String getParamTempfile() {
260
261        return m_paramTempFile;
262    }
263
264    /**
265     * Sets the current language.<p>
266     *
267     * @param elementLanguage the current element language
268     */
269    public void setParamElementLanguage(String elementLanguage) {
270
271        m_paramElementlanguage = elementLanguage;
272    }
273
274    /**
275     * Sets the list of selected languages.<p>
276     *
277     * @param language a selected language
278     */
279    public void setParamLanguage(String language) {
280
281        if (language != null) {
282            if (m_paramSelectedLanguages == null) {
283                m_paramSelectedLanguages = new HashSet<String>();
284            }
285            // add all available values here
286            String[] values = getParameterMap().get(PARAM_LANGUAGE);
287            for (int i = 0; i < values.length; i++) {
288                m_paramSelectedLanguages.add(decodeParamValue(PARAM_LANGUAGE, values[i]));
289            }
290        }
291    }
292
293    /**
294     * Sets the name of the temporary file.<p>
295     *
296     * @param fileName the name of the temporary file
297     */
298    public void setParamTempfile(String fileName) {
299
300        m_paramTempFile = fileName;
301    }
302
303    /**
304     * @see org.opencms.workplace.CmsWorkplace#initWorkplaceRequestValues(org.opencms.workplace.CmsWorkplaceSettings, javax.servlet.http.HttpServletRequest)
305     */
306    @Override
307    protected void initWorkplaceRequestValues(CmsWorkplaceSettings settings, HttpServletRequest request) {
308
309        // fill the parameter values in the get/set methods
310        fillParamValues(request);
311        // set the dialog type
312        setParamDialogtype(DIALOG_TYPE);
313        // set the action for the JSP switch
314        if (DIALOG_UPDATE_LANGUAGES.equals(getParamAction())) {
315            setAction(ACTION_UPDATE_LANGUAGES);
316        } else {
317            setAction(ACTION_DEFAULT);
318            // build title for delete dialog
319            setParamTitle(key(Messages.GUI_EDITOR_DIALOG_COPYLANGUAGE_TITLE_0));
320        }
321    }
322
323    /**
324     * Copies the contents from a source locale to a number of destination locales by overwriting them.<p>
325     *
326     * @param content the xml content
327     * @param sourceLocale the source locale
328     * @param destLocales a list of destination locales
329     * @throws CmsException if something goes wrong
330     */
331    protected void transferContents(CmsXmlContent content, Locale sourceLocale, List<Locale> destLocales)
332    throws CmsException {
333
334        for (Iterator<Locale> i = destLocales.iterator(); i.hasNext();) {
335            Locale to = i.next();
336            if (content.hasLocale(to)) {
337                content.removeLocale(to);
338            }
339            content.copyLocale(sourceLocale, to);
340        }
341    }
342}