001/*
002 *  Copyright 2017 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.cms.contenttype;
017
018import java.util.Collections;
019import java.util.HashMap;
020import java.util.Map;
021import java.util.Set;
022
023import org.apache.avalon.framework.configuration.Configurable;
024import org.apache.avalon.framework.configuration.Configuration;
025import org.apache.avalon.framework.configuration.ConfigurationException;
026import org.apache.avalon.framework.service.ServiceException;
027import org.apache.avalon.framework.service.ServiceManager;
028import org.apache.avalon.framework.service.Serviceable;
029import org.apache.commons.lang.StringUtils;
030
031import org.ametys.runtime.i18n.I18nizableText;
032import org.ametys.runtime.model.Enumerator;
033
034/**
035 * Enumerator for {@link ContentType}
036 *
037 */
038public class ContentTypeEnumerator implements Enumerator<String>, org.ametys.runtime.parameter.Enumerator, Serviceable, Configurable
039{
040    /** The content type extension point */
041    protected ContentTypeExtensionPoint _cTypeExtPt;
042    
043    /** All option : 'disabled' to disable the 'all' option, 
044     * 'blank' to use a blank value for 'all' option,
045     * or 'concat' to concat all content types' ids for 'all' option
046     **/
047    protected String _allOption;
048    /** True to exclude private content types */
049    protected boolean _excludePrivate;
050    /** True to exclude reference table content types */
051    protected boolean _excludeReferenceTable;
052    /** True to exclude abstract content types */
053    protected boolean _excludeAbstract;
054    /** True to exclude mixin content types */
055    protected boolean _excludeMixin;
056    /** True to include only mixin content types */
057    protected boolean _mixinOnly;
058    /** The parent content types */
059    protected String[] _contentTypes;
060    /** The strict content types */
061    protected String[] _strictContentTypes;
062    
063    private ContentTypesTreeComponent _cTypeTreeComponent;
064    
065    @Override
066    public void service(ServiceManager smanager) throws ServiceException
067    {
068        _cTypeExtPt = (ContentTypeExtensionPoint) smanager.lookup(ContentTypeExtensionPoint.ROLE);
069        _cTypeTreeComponent = (ContentTypesTreeComponent) smanager.lookup(ContentTypesTreeComponent.ROLE);
070    }
071    
072    @Override
073    public void configure(Configuration configuration) throws ConfigurationException
074    {
075        Configuration allOptConf = configuration.getChild("enumeration").getChild("custom-enumerator").getChild("allOption", false);
076        _allOption = allOptConf != null ? allOptConf.getValue("disabled") : "disabled";
077        
078        Configuration privateConf = configuration.getChild("enumeration").getChild("custom-enumerator").getChild("excludePrivate", false);
079        _excludePrivate = privateConf != null ? Boolean.valueOf(privateConf.getValue("false")) : false;
080        
081        Configuration refTableConf = configuration.getChild("enumeration").getChild("custom-enumerator").getChild("excludeReferenceTable", false);
082        _excludeReferenceTable = refTableConf != null ? Boolean.valueOf(refTableConf.getValue("false")) : true;
083        
084        Configuration abstractConf = configuration.getChild("enumeration").getChild("custom-enumerator").getChild("excludeAbstract", false);
085        _excludeAbstract = abstractConf != null ? Boolean.valueOf(abstractConf.getValue("false")) : false;
086        
087        Configuration mixinConf = configuration.getChild("enumeration").getChild("custom-enumerator").getChild("excludeMixin", false);
088        _excludeMixin = mixinConf != null ? Boolean.valueOf(mixinConf.getValue("false")) : false;
089        
090        Configuration mixinOnlyConf = configuration.getChild("enumeration").getChild("custom-enumerator").getChild("includeMixinOnly", false);
091        _mixinOnly = mixinOnlyConf != null ? Boolean.valueOf(mixinOnlyConf.getValue("false")) : false;
092        
093        String strictCTypes = configuration.getChild("enumeration").getChild("custom-enumerator").getChild("strictContentTypes").getValue(null);
094        _strictContentTypes = strictCTypes != null ? strictCTypes.split(",") : null;
095        
096        String cTypes = configuration.getChild("enumeration").getChild("custom-enumerator").getChild("contentTypes").getValue(null);
097        _contentTypes = cTypes != null ? cTypes.split(",") : null;
098    }
099    
100    @Override
101    public Map<String, Object> getConfiguration()
102    {
103        Map<String, Object> params = new HashMap<>();
104        
105        params.put("allOption", _allOption);
106        params.put("excludePrivate", _excludePrivate);
107        params.put("excludeReferenceTable", _excludeReferenceTable);
108        params.put("excludeAbstract", _excludeAbstract);
109        params.put("excludeMixin", _excludeMixin);
110        params.put("mixinOnly", _mixinOnly);
111        if (_strictContentTypes != null)
112        {
113            params.put("strictContentTypes", _strictContentTypes);
114        }
115        if (_contentTypes != null)
116        {
117            params.put("contentTypes", _contentTypes);
118        }
119        
120        return params;
121    }
122    
123    @Override
124    // TODO NEWATTRIBUTEAPI_CONTENT: remove this method when org.ametys.runtime.parameter.Enumerator will be removed
125    public Map<Object, I18nizableText> getEntries() throws Exception
126    {
127        Map<Object, I18nizableText> result = new HashMap<>();
128        for (Map.Entry<String, I18nizableText> entry : getTypedEntries().entrySet())
129        {
130            result.put(entry.getKey(), entry.getValue());
131        }
132        return Collections.unmodifiableMap(result);
133    }
134    
135    public Map<String, I18nizableText> getTypedEntries() throws Exception
136    {
137        Map<String, I18nizableText> entries = new HashMap<>();
138        
139        Set<ContentType> cTypes = getMatchingContentTypes();
140        for (ContentType cType : cTypes)
141        {
142            entries.put(cType.getId(), cType.getLabel());
143        }
144
145        // All contents
146        _handleAllOptionEntry(entries);
147        
148        return entries;
149    }
150    
151    /**
152     * Get the matching content types
153     * @return the matching content types
154     */
155    protected Set<ContentType> getMatchingContentTypes()
156    {
157        if (_strictContentTypes != null && _strictContentTypes.length != 0)
158        {
159            return _cTypeTreeComponent.getMatchingContentTypes(_strictContentTypes, false, _excludeReferenceTable, _excludePrivate, _excludeAbstract, _excludeMixin, _mixinOnly);
160        }
161        else if (_contentTypes != null && _contentTypes.length != 0)
162        {
163            return _cTypeTreeComponent.getMatchingContentTypes(_contentTypes, true, _excludeReferenceTable, _excludePrivate, _excludeAbstract, _excludeMixin, _mixinOnly);
164        }
165        else
166        {
167            return _cTypeTreeComponent.getMatchingContentTypes(_excludeReferenceTable, _excludePrivate, _excludeAbstract, _excludeMixin, _mixinOnly);
168        }
169    }
170
171    /**
172     * Add the all option entry to the entry list if necessary
173     * @param entries The enumerator entries
174     */
175    protected void _handleAllOptionEntry(Map<String, I18nizableText> entries)
176    {
177        if (!_allOption.equals("disabled"))
178        {
179            String value = _allOption.equals("concat") ? StringUtils.join(entries.keySet(), ',') : "";
180            if (!entries.containsKey(value))
181            {
182                entries.put(value, new I18nizableText("plugin.cms", "WIDGET_COMBOBOX_ALL_OPTIONS"));
183            }
184        }
185    }
186
187    @Override
188    public I18nizableText getEntry(String value) throws Exception
189    {
190        ContentType cType = _cTypeExtPt.getExtension(value);
191        return cType.getLabel();
192    }
193}