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.components;
029
030import org.opencms.file.CmsObject;
031import org.opencms.file.CmsResource;
032import org.opencms.i18n.CmsLocaleManager;
033import org.opencms.main.CmsException;
034import org.opencms.main.OpenCms;
035import org.opencms.ui.A_CmsUI;
036import org.opencms.ui.CmsVaadinUtils;
037import org.opencms.ui.apps.sitemanager.CmsSiteManager;
038import org.opencms.util.CmsMacroResolver;
039
040import java.io.ByteArrayInputStream;
041import java.io.IOException;
042import java.io.InputStreamReader;
043import java.nio.charset.StandardCharsets;
044import java.util.HashMap;
045import java.util.List;
046import java.util.Map;
047import java.util.Properties;
048import java.util.Set;
049
050import com.vaadin.ui.Button;
051import com.vaadin.ui.Button.ClickEvent;
052import com.vaadin.ui.Button.ClickListener;
053import com.vaadin.ui.FormLayout;
054import com.vaadin.ui.UI;
055import com.vaadin.v7.ui.TextField;
056
057/**
058 * Class for a dialog to show macros of a sitemap folder and allow the user to edit them.<p>
059 */
060public class CmsMacroResolverDialog extends CmsBasicDialog {
061
062    /**generated vaadin serial id.*/
063    private static final long serialVersionUID = 4326570443207345219L;
064
065    /** Action to execute when cancelled. */
066    Runnable m_cancelAction;
067
068    /** Action to execute when confirmed. */
069    Runnable m_okAction;
070
071    /**Map for storing relations for Vaadin Components to related key values.*/
072    private Map<TextField, String> m_bundleComponentKeyMap = new HashMap<TextField, String>();
073
074    /**Form Layout for displaying the bundle valuse in.*/
075    private FormLayout m_bundleValues;
076
077    /** Cancel button. */
078    private Button m_cancelButton;
079
080    /** OK button .*/
081    private Button m_okButton;
082
083    /**
084     * Public constructor.<p>
085     *
086     * @param okAction runnable for ok button.
087     * @param cancelAction runnable for cancel button.
088     * @param resource (folder) to resolve macros in.
089     */
090    public CmsMacroResolverDialog(Runnable okAction, Runnable cancelAction, CmsResource resource) {
091
092        CmsVaadinUtils.readAndLocalizeDesign(this, CmsVaadinUtils.getWpMessagesForCurrentLocale(), null);
093        m_okAction = okAction;
094
095        m_cancelAction = cancelAction;
096
097        m_okButton.addClickListener(new ClickListener() {
098
099            private static final long serialVersionUID = 1L;
100
101            public void buttonClick(ClickEvent event) {
102
103                if (m_okAction != null) {
104                    m_okAction.run();
105                }
106            }
107        });
108        m_cancelButton.addClickListener(new ClickListener() {
109
110            private static final long serialVersionUID = 1L;
111
112            public void buttonClick(ClickEvent event) {
113
114                if (m_cancelAction != null) {
115                    m_cancelAction.run();
116                }
117
118            }
119        });
120        CmsObject cms;
121        try {
122            cms = OpenCms.initCmsObject(A_CmsUI.getCmsObject());
123            cms.getRequestContext().setSiteRoot("");
124
125            //Read descriptor
126            CmsResource descriptor = cms.readResource(
127                resource.getRootPath() + CmsSiteManager.MACRO_FOLDER + "/" + CmsSiteManager.BUNDLE_NAME + "_desc");
128
129            //Read related bundle
130            Properties resourceBundle = getLocalizedBundle(cms, resource.getRootPath());
131            Map<String, String[]> bundleKeyDescriptorMap = CmsMacroResolver.getBundleMapFromResources(
132                resourceBundle,
133                descriptor,
134                cms);
135
136            for (String key : bundleKeyDescriptorMap.keySet()) {
137
138                //Create TextField
139                TextField field = new TextField();
140                field.setCaption(bundleKeyDescriptorMap.get(key)[0]);
141                field.setValue(bundleKeyDescriptorMap.get(key)[1]);
142                field.setWidth("100%");
143
144                //Add vaadin component to UI and keep related key in HashMap
145                m_bundleValues.addComponent(field);
146                m_bundleComponentKeyMap.put(field, key);
147            }
148
149        } catch (CmsException | IOException e) {
150            //
151        }
152
153    }
154
155    /**
156     * Reads the entered values for the macro and returns them together with their keys.<p>
157     *
158     * @return Maps
159     */
160    public Map<String, String> getMacroMap() {
161
162        Map<String, String> map = new HashMap<String, String>();
163        if (m_bundleComponentKeyMap != null) {
164            Set<TextField> fields = m_bundleComponentKeyMap.keySet();
165
166            for (TextField field : fields) {
167                map.put(m_bundleComponentKeyMap.get(field), field.getValue());
168            }
169        }
170        return map;
171    }
172
173    /**
174     * Returns the correct variant of a resource name according to locale.<p>
175     *
176     * @param cms CmsObject
177     * @param path where the considered resource is.
178     * @param baseName of the resource
179     * @return localized name of resource
180     */
181    private String getAvailableLocalVariant(CmsObject cms, String path, String baseName) {
182
183        A_CmsUI.get();
184        List<String> localVariations = CmsLocaleManager.getLocaleVariants(
185            baseName,
186            UI.getCurrent().getLocale(),
187            false,
188            true);
189
190        for (String name : localVariations) {
191            if (cms.existsResource(path + name)) {
192                return name;
193            }
194        }
195        return null;
196    }
197
198    /**
199     * Gets localized property object.<p>
200     *
201     * @param cms CmsObject
202     * @param path of resource
203     * @return Properties object
204     * @throws CmsException exception
205     * @throws IOException exception
206     */
207    private Properties getLocalizedBundle(CmsObject cms, String path) throws CmsException, IOException {
208
209        CmsResource bundleResource = cms.readResource(
210            path
211                + CmsSiteManager.MACRO_FOLDER
212                + "/"
213                + getAvailableLocalVariant(cms, path + CmsSiteManager.MACRO_FOLDER + "/", CmsSiteManager.BUNDLE_NAME));
214
215        Properties ret = new Properties();
216        InputStreamReader reader = new InputStreamReader(
217            new ByteArrayInputStream(cms.readFile(bundleResource).getContents()),
218            StandardCharsets.UTF_8);
219        ret.load(reader);
220
221        return ret;
222    }
223}