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    /** True to include only reference table content types */
059    protected boolean _referenceTableOnly;
060    /** The parent content types */
061    protected String[] _contentTypes;
062    /** The strict content types */
063    protected String[] _strictContentTypes;
064    
065    private ContentTypesTreeComponent _cTypeTreeComponent;
066    
067    @Override
068    public void service(ServiceManager smanager) throws ServiceException
069    {
070        _cTypeExtPt = (ContentTypeExtensionPoint) smanager.lookup(ContentTypeExtensionPoint.ROLE);
071        _cTypeTreeComponent = (ContentTypesTreeComponent) smanager.lookup(ContentTypesTreeComponent.ROLE);
072    }
073    
074    @Override
075    public void configure(Configuration configuration) throws ConfigurationException
076    {
077        Configuration allOptConf = configuration.getChild("enumeration").getChild("custom-enumerator").getChild("allOption", false);
078        _allOption = allOptConf != null ? allOptConf.getValue("disabled") : "disabled";
079        
080        Configuration privateConf = configuration.getChild("enumeration").getChild("custom-enumerator").getChild("excludePrivate", false);
081        _excludePrivate = privateConf != null ? Boolean.valueOf(privateConf.getValue("false")) : false;
082        
083        Configuration refTableConf = configuration.getChild("enumeration").getChild("custom-enumerator").getChild("excludeReferenceTable", false);
084        _excludeReferenceTable = refTableConf != null ? Boolean.valueOf(refTableConf.getValue("false")) : true;
085        
086        Configuration abstractConf = configuration.getChild("enumeration").getChild("custom-enumerator").getChild("excludeAbstract", false);
087        _excludeAbstract = abstractConf != null ? Boolean.valueOf(abstractConf.getValue("false")) : false;
088        
089        Configuration mixinConf = configuration.getChild("enumeration").getChild("custom-enumerator").getChild("excludeMixin", false);
090        _excludeMixin = mixinConf != null ? Boolean.valueOf(mixinConf.getValue("false")) : false;
091        
092        Configuration mixinOnlyConf = configuration.getChild("enumeration").getChild("custom-enumerator").getChild("includeMixinOnly", false);
093        _mixinOnly = mixinOnlyConf != null ? Boolean.valueOf(mixinOnlyConf.getValue("false")) : false;
094        
095        Configuration refTableOnlyConf = configuration.getChild("enumeration").getChild("custom-enumerator").getChild("includeReferenceTableOnly", false);
096        _referenceTableOnly = refTableOnlyConf != null ? Boolean.valueOf(refTableOnlyConf.getValue("false")) : false;
097        
098        String strictCTypes = configuration.getChild("enumeration").getChild("custom-enumerator").getChild("strictContentTypes").getValue(null);
099        _strictContentTypes = strictCTypes != null ? strictCTypes.split(",") : null;
100        
101        String cTypes = configuration.getChild("enumeration").getChild("custom-enumerator").getChild("contentTypes").getValue(null);
102        _contentTypes = cTypes != null ? cTypes.split(",") : null;
103    }
104    
105    @Override
106    public Map<String, Object> getConfiguration()
107    {
108        Map<String, Object> params = new HashMap<>();
109        
110        params.put("allOption", _allOption);
111        params.put("excludePrivate", _excludePrivate);
112        params.put("excludeReferenceTable", _excludeReferenceTable);
113        params.put("excludeAbstract", _excludeAbstract);
114        params.put("excludeMixin", _excludeMixin);
115        params.put("mixinOnly", _mixinOnly);
116        if (_strictContentTypes != null)
117        {
118            params.put("strictContentTypes", _strictContentTypes);
119        }
120        if (_contentTypes != null)
121        {
122            params.put("contentTypes", _contentTypes);
123        }
124        
125        return params;
126    }
127    
128    @Override
129    // TODO NEWATTRIBUTEAPI_CONTENT: remove this method when org.ametys.runtime.parameter.Enumerator will be removed
130    public Map<Object, I18nizableText> getEntries() throws Exception
131    {
132        Map<Object, I18nizableText> result = new HashMap<>();
133        for (Map.Entry<String, I18nizableText> entry : getTypedEntries().entrySet())
134        {
135            result.put(entry.getKey(), entry.getValue());
136        }
137        return Collections.unmodifiableMap(result);
138    }
139    
140    public Map<String, I18nizableText> getTypedEntries() throws Exception
141    {
142        Map<String, I18nizableText> entries = new HashMap<>();
143        
144        Set<ContentType> cTypes = getMatchingContentTypes();
145        for (ContentType cType : cTypes)
146        {
147            entries.put(cType.getId(), cType.getLabel());
148        }
149
150        // All contents
151        _handleAllOptionEntry(entries);
152        
153        return entries;
154    }
155    
156    /**
157     * Get the matching content types
158     * @return the matching content types
159     */
160    protected Set<ContentType> getMatchingContentTypes()
161    {
162        if (_strictContentTypes != null && _strictContentTypes.length != 0)
163        {
164            return _cTypeTreeComponent.getMatchingContentTypes(_strictContentTypes, false, _excludeReferenceTable, _excludePrivate, _excludeAbstract, _excludeMixin, _mixinOnly, _referenceTableOnly);
165        }
166        else if (_contentTypes != null && _contentTypes.length != 0)
167        {
168            return _cTypeTreeComponent.getMatchingContentTypes(_contentTypes, true, _excludeReferenceTable, _excludePrivate, _excludeAbstract, _excludeMixin, _mixinOnly, _referenceTableOnly);
169        }
170        else
171        {
172            return _cTypeTreeComponent.getMatchingContentTypes(_excludeReferenceTable, _excludePrivate, _excludeAbstract, _excludeMixin, _mixinOnly, _referenceTableOnly);
173        }
174    }
175
176    /**
177     * Add the all option entry to the entry list if necessary
178     * @param entries The enumerator entries
179     */
180    protected void _handleAllOptionEntry(Map<String, I18nizableText> entries)
181    {
182        if (!_allOption.equals("disabled"))
183        {
184            String value = _allOption.equals("concat") ? StringUtils.join(entries.keySet(), ',') : "";
185            if (!entries.containsKey(value))
186            {
187                entries.put(value, new I18nizableText("plugin.cms", "WIDGET_COMBOBOX_ALL_OPTIONS"));
188            }
189        }
190    }
191
192    @Override
193    public I18nizableText getEntry(String value) throws Exception
194    {
195        ContentType cType = _cTypeExtPt.getExtension(value);
196        return cType.getLabel();
197    }
198}