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.widgets;
029
030import org.opencms.ade.configuration.CmsADEConfigData;
031import org.opencms.ade.configuration.CmsConfigurationReader;
032import org.opencms.file.CmsObject;
033import org.opencms.file.CmsResource;
034import org.opencms.main.CmsException;
035import org.opencms.main.OpenCms;
036import org.opencms.util.CmsUUID;
037import org.opencms.xml.containerpage.CmsFunctionFormatterBean;
038import org.opencms.xml.containerpage.CmsMacroFormatterBean;
039import org.opencms.xml.containerpage.CmsSchemaFormatterBeanWrapper;
040import org.opencms.xml.containerpage.I_CmsFormatterBean;
041import org.opencms.xml.content.CmsXmlContent;
042import org.opencms.xml.content.CmsXmlContentRootLocation;
043
044import java.util.ArrayList;
045import java.util.Collections;
046import java.util.HashSet;
047import java.util.List;
048import java.util.Locale;
049import java.util.Map;
050import java.util.Set;
051
052import com.google.common.collect.Lists;
053
054/**
055 * Widget used to select a formatter to add.<p>
056 *
057 * Please note that this widget assumes the resource being edited is a sitemap configuration, and will not work correctly in a different context.
058 */
059public class CmsAddFormatterWidget extends A_CmsFormatterWidget {
060
061    /**
062     * Default constructor.<p>
063     */
064    public CmsAddFormatterWidget() {
065
066        super();
067    }
068
069    /**
070     * Constructor with a configuration parameter.<p>
071     * @param config the configuration string
072     */
073    public CmsAddFormatterWidget(String config) {
074
075        super();
076    }
077
078    /**
079     * Returns all values that can be selected in the widget.
080     * @param cms the current CMS object
081     * @param rootPath the root path to the currently edited xml file (sitemap config)
082     * @param allRemoved flag, indicating if all inheritedly available formatters should be disabled
083     * @return all values that can be selected in the widget.
084     */
085    public static List<String> getSelectOptionValues(CmsObject cms, String rootPath, boolean allRemoved) {
086
087        try {
088            cms = OpenCms.initCmsObject(cms);
089            cms.getRequestContext().setSiteRoot("");
090            CmsADEConfigData adeConfig = OpenCms.getADEManager().lookupConfiguration(cms, rootPath);
091            if (adeConfig.parent() != null) {
092                adeConfig = adeConfig.parent();
093            }
094
095            List<CmsSelectWidgetOption> options = getFormatterOptionsStatic(cms, adeConfig, rootPath, allRemoved);
096            List<CmsSelectWidgetOption> typeOptions = getTypeOptionsStatic(cms, adeConfig, allRemoved);
097            options.addAll(typeOptions);
098            List<String> result = new ArrayList<String>(options.size());
099            for (CmsSelectWidgetOption o : options) {
100                result.add(o.getValue());
101            }
102            return result;
103        } catch (CmsException e) {
104            // should never happen
105            LOG.error(e.getLocalizedMessage(), e);
106            return null;
107        }
108
109    }
110
111    /**
112     * Gets the options corresponding to external (non-schema) formatters.<p>
113     *
114     * @param cms the CMS context
115     * @param config the ADE configuration
116     * @param rootPath the root path of the edited file
117     * @param allRemoved flag, indicating if all inheritedly available formatters should be disabled
118     *
119     * @return the select widget options for the external formatters
120     */
121    protected static List<CmsSelectWidgetOption> getFormatterOptionsStatic(
122        CmsObject cms,
123        CmsADEConfigData config,
124        String rootPath,
125        boolean allRemoved) {
126
127        Map<CmsUUID, I_CmsFormatterBean> inactiveFormatters = config.getInactiveFormatters();
128        List<CmsSelectWidgetOption> result = Lists.newArrayList();
129        List<I_CmsFormatterBean> formatters = Lists.newArrayList(inactiveFormatters.values());
130        if (allRemoved) {
131            Map<CmsUUID, I_CmsFormatterBean> activeFormatters = config.getActiveFormatters();
132            formatters.addAll(Lists.newArrayList(activeFormatters.values()));
133        }
134        Collections.sort(formatters, new A_CmsFormatterWidget.FormatterSelectComparator());
135        for (I_CmsFormatterBean formatterBean : formatters) {
136            if ((formatterBean instanceof CmsFunctionFormatterBean)
137                || (formatterBean instanceof CmsSchemaFormatterBeanWrapper)) {
138                continue;
139            }
140
141            if (formatterBean instanceof CmsMacroFormatterBean) {
142                boolean systemOrShared = formatterBean.getLocation().startsWith(CmsResource.VFS_FOLDER_SYSTEM + "/")
143                    || formatterBean.getLocation().startsWith(OpenCms.getSiteManager().getSharedFolder());
144                if (!systemOrShared) {
145                    String formatterSubSite = CmsResource.getParentFolder(
146                        CmsResource.getParentFolder(CmsResource.getParentFolder(formatterBean.getLocation())));
147                    String subSite = CmsResource.getParentFolder(CmsResource.getParentFolder(rootPath));
148                    if (subSite.equals(formatterSubSite) || !subSite.startsWith(formatterSubSite)) {
149                        // we ignore macro formatters that are defined in the current sub site (they are added automatically), or not within a parent site
150                        continue;
151                    }
152                }
153            }
154            try {
155                CmsSelectWidgetOption option = getWidgetOptionForFormatter(cms, formatterBean);
156                result.add(option);
157            } catch (Exception e) {
158                LOG.error(e.getLocalizedMessage(), e);
159            }
160        }
161        return result;
162
163    }
164
165    /**
166     * Gets the options corresponding to the schemas which define formatters.<p>
167     *
168     * @param cms the current CMS context
169     * @param adeConfig the ADE configuration
170     * @param allRemoved flag, indicating if all inheritedly available formatters should be disabled
171     *
172     * @return the select widget options for the content types with formatters in the schema
173     */
174    protected static List<CmsSelectWidgetOption> getTypeOptionsStatic(
175        CmsObject cms,
176        CmsADEConfigData adeConfig,
177        boolean allRemoved) {
178
179        List<CmsSelectWidgetOption> result = Lists.newArrayList();
180        Set<String> types = adeConfig.getTypesWithModifiableFormatters();
181        Set<String> inactiveTypes = new HashSet<String>(types);
182        if (!allRemoved) {
183            Set<String> activeTypes = adeConfig.getTypesWithActiveSchemaFormatters();
184            inactiveTypes.removeAll(activeTypes);
185        }
186        for (String inactiveType : inactiveTypes) {
187            CmsSelectWidgetOption option = getWidgetOptionForType(cms, inactiveType);
188            result.add(option);
189        }
190        return result;
191
192    }
193
194    /**
195     * @see org.opencms.widgets.I_CmsADEWidget#getCssResourceLinks(org.opencms.file.CmsObject)
196     */
197    @Override
198    public List<String> getCssResourceLinks(CmsObject cms) {
199
200        return null;
201    }
202
203    /**
204     * @see org.opencms.widgets.I_CmsADEWidget#getInitCall()
205     */
206    @Override
207    public String getInitCall() {
208
209        return null;
210    }
211
212    /**
213     * @see org.opencms.widgets.I_CmsADEWidget#getJavaScriptResourceLinks(org.opencms.file.CmsObject)
214     */
215    @Override
216    public List<String> getJavaScriptResourceLinks(CmsObject cms) {
217
218        return null;
219    }
220
221    /**
222     * @see org.opencms.widgets.I_CmsADEWidget#isInternal()
223     */
224    @Override
225    public boolean isInternal() {
226
227        return true;
228    }
229
230    /**
231     * @see org.opencms.widgets.CmsSelectWidget#newInstance()
232     */
233    @Override
234    public I_CmsWidget newInstance() {
235
236        return new CmsAddFormatterWidget();
237    }
238
239    /**
240     * @see org.opencms.widgets.A_CmsFormatterWidget#getFormatterOptions(org.opencms.file.CmsObject, org.opencms.ade.configuration.CmsADEConfigData, java.lang.String, boolean)
241     */
242    @Override
243    protected List<CmsSelectWidgetOption> getFormatterOptions(
244        CmsObject cms,
245        CmsADEConfigData config,
246        String rootPath,
247        boolean allRemoved) {
248
249        return getFormatterOptionsStatic(cms, config, rootPath, allRemoved);
250
251    }
252
253    /**
254     * @see org.opencms.widgets.A_CmsFormatterWidget#getSelectedInFile(org.opencms.ade.configuration.CmsConfigurationReader, org.opencms.xml.content.CmsXmlContent)
255     */
256    @Override
257    protected Set<String> getSelectedInFile(CmsConfigurationReader reader, CmsXmlContent content) {
258
259        CmsXmlContentRootLocation root = new CmsXmlContentRootLocation(content, Locale.ENGLISH);
260        Set<String> addFormatters = reader.parseAddFormatters(root);
261        return addFormatters;
262    }
263
264    /**
265     * @see org.opencms.widgets.A_CmsFormatterWidget#getTypeOptions(org.opencms.file.CmsObject, org.opencms.ade.configuration.CmsADEConfigData, boolean)
266     */
267    @Override
268    protected List<CmsSelectWidgetOption> getTypeOptions(
269        CmsObject cms,
270        CmsADEConfigData adeConfig,
271        boolean allRemoved) {
272
273        return getTypeOptionsStatic(cms, adeConfig, allRemoved);
274
275    }
276
277}