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.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.v7.ui.TextField;
055import com.vaadin.ui.UI;
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        CmsVaadinUtils.readAndLocalizeDesign(this, CmsVaadinUtils.getWpMessagesForCurrentLocale(), null);
092        m_okAction = okAction;
093
094        m_cancelAction = cancelAction;
095
096        m_okButton.addClickListener(new ClickListener() {
097
098            private static final long serialVersionUID = 1L;
099
100            public void buttonClick(ClickEvent event) {
101
102                if (m_okAction != null) {
103                    m_okAction.run();
104                }
105            }
106        });
107        m_cancelButton.addClickListener(new ClickListener() {
108
109            private static final long serialVersionUID = 1L;
110
111            public void buttonClick(ClickEvent event) {
112
113                if (m_cancelAction != null) {
114                    m_cancelAction.run();
115                }
116
117            }
118        });
119        CmsObject cms;
120        try {
121            cms = OpenCms.initCmsObject(A_CmsUI.getCmsObject());
122            cms.getRequestContext().setSiteRoot("");
123
124            //Read descriptor
125            CmsResource descriptor = cms.readResource(
126                resource.getRootPath() + CmsSiteManager.MACRO_FOLDER + "/" + CmsSiteManager.BUNDLE_NAME + "_desc");
127
128            //Read related bundle
129            Properties resourceBundle = getLocalizedBundle(cms, resource.getRootPath());
130            Map<String, String[]> bundleKeyDescriptorMap = CmsMacroResolver.getBundleMapFromResources(
131                resourceBundle,
132                descriptor,
133                cms);
134
135            for (String key : bundleKeyDescriptorMap.keySet()) {
136
137                //Create TextField
138                TextField field = new TextField();
139                field.setCaption(bundleKeyDescriptorMap.get(key)[0]);
140                field.setValue(bundleKeyDescriptorMap.get(key)[1]);
141                field.setWidth("100%");
142
143                //Add vaadin component to UI and keep related key in HashMap
144                m_bundleValues.addComponent(field);
145                m_bundleComponentKeyMap.put(field, key);
146            }
147
148        } catch (CmsException | IOException e) {
149            //
150        }
151
152    }
153
154    /**
155     * Reads the entered values for the macro and returns them together with their keys.<p>
156     *
157     * @return Maps
158     */
159    public Map<String, String> getMacroMap() {
160
161        Map<String, String> map = new HashMap<String, String>();
162        if (m_bundleComponentKeyMap != null) {
163            Set<TextField> fields = m_bundleComponentKeyMap.keySet();
164
165            for (TextField field : fields) {
166                map.put(m_bundleComponentKeyMap.get(field), field.getValue());
167            }
168        }
169        return map;
170    }
171
172    /**
173     * Returns the correct variant of a resource name according to locale.<p>
174     *
175     * @param cms CmsObject
176     * @param path where the considered resource is.
177     * @param baseName of the resource
178     * @return localized name of resource
179     */
180    private String getAvailableLocalVariant(CmsObject cms, String path, String baseName) {
181
182        A_CmsUI.get();
183        List<String> localVariations = CmsLocaleManager.getLocaleVariants(
184            baseName,
185            UI.getCurrent().getLocale(),
186            false,
187            true);
188
189        for (String name : localVariations) {
190            if (cms.existsResource(path + name)) {
191                return name;
192            }
193        }
194        return null;
195    }
196
197    /**
198     * Gets localized property object.<p>
199     *
200     * @param cms CmsObject
201     * @param path of resource
202     * @return Properties object
203     * @throws CmsException exception
204     * @throws IOException exception
205     */
206    private Properties getLocalizedBundle(CmsObject cms, String path) throws CmsException, IOException {
207
208        CmsResource bundleResource = cms.readResource(path
209            + CmsSiteManager.MACRO_FOLDER
210            + "/"
211            + getAvailableLocalVariant(cms, path + CmsSiteManager.MACRO_FOLDER + "/", CmsSiteManager.BUNDLE_NAME));
212
213        Properties ret = new Properties();
214        InputStreamReader reader = new InputStreamReader(
215            new ByteArrayInputStream(cms.readFile(bundleResource).getContents()),
216            StandardCharsets.UTF_8);
217        ret.load(reader);
218
219        return ret;
220    }
221}