001/*
002 *  Copyright 2015 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.search.model;
017
018import java.util.ArrayList;
019import java.util.Collections;
020import java.util.List;
021
022import org.apache.avalon.framework.component.ComponentException;
023import org.apache.avalon.framework.configuration.Configuration;
024import org.apache.avalon.framework.configuration.ConfigurationException;
025import org.apache.avalon.framework.service.ServiceException;
026import org.apache.avalon.framework.service.ServiceManager;
027import org.apache.commons.lang3.StringUtils;
028
029import org.ametys.cms.data.type.ModelItemTypeExtensionPoint;
030import org.ametys.runtime.plugin.component.AbstractThreadSafeComponentExtensionPoint;
031
032/**
033 * Extension point handling {@link SystemProperty} objects.
034 */
035public class SystemPropertyExtensionPoint extends AbstractThreadSafeComponentExtensionPoint<SystemProperty>// implements Initializable
036{
037    /** The extension point role. */
038    public static final String ROLE = SystemPropertyExtensionPoint.class.getName();
039    
040    /** Content properties types extension point */
041    protected ModelItemTypeExtensionPoint _contentPropertyTypeExtensionPoint;
042    
043    /** Collection of the displayable properties. */
044    protected List<String> _displayProps;
045    
046    /** Collection of the searchable properties. */
047    protected List<String> _searchProps;
048    
049    @Override
050    public void service(ServiceManager manager) throws ServiceException
051    {
052        super.service(manager);
053        _contentPropertyTypeExtensionPoint = (ModelItemTypeExtensionPoint) manager.lookup(ModelItemTypeExtensionPoint.ROLE_CONTENT_PROPERTY);
054    }
055    
056    @Override
057    public void addExtension(String id, String pluginName, String featureName, Configuration configuration) throws ConfigurationException
058    {
059        if (getLogger().isDebugEnabled())
060        {
061            getLogger().debug("Adding system properties from feature " + pluginName + "/" + featureName);
062        }
063        
064        try
065        {
066            for (Configuration propConf : configuration.getChildren("property"))
067            {
068                addSystemProperty(pluginName, featureName, propConf);
069            }
070        }
071        catch (ConfigurationException e)
072        {
073            if (getLogger().isWarnEnabled())
074            {
075                getLogger().warn("The feature '" + pluginName + "/" + featureName + "' declares a system property extension with an invalid configuration.", e);
076            }
077        }
078    }
079    
080    /**
081     * Declare a new system property.
082     * @param pluginName The name of the plugin declaring the extension
083     * @param featureName The feature name.
084     * @param configuration The configuration of the extension
085     * @throws ConfigurationException if configuration if not complete
086     */
087    @SuppressWarnings("unchecked")
088    protected void addSystemProperty(String pluginName, String featureName, Configuration configuration) throws ConfigurationException
089    {
090        String id = configuration.getAttribute("id", "");
091        if (StringUtils.isBlank(id))
092        {
093            throw new ConfigurationException("SystemProperty declaration is incorrect since no 'id' attribute is specified (or may be empty)", configuration);
094        }
095        
096        String className = configuration.getAttribute("class", "");
097        if (StringUtils.isBlank(className))
098        {
099            throw new ConfigurationException("SystemProperty declaration is incorrect since no 'class' attribute is specified (or may be empty)", configuration);
100        }
101        
102        try
103        {
104            Class<?> clazz = Class.forName(className);
105            if (!SystemProperty.class.isAssignableFrom(clazz))
106            {
107                throw new ConfigurationException("The system property declaration must be declared with a class implementing SystemProperty.");
108            }
109            
110            addComponent(pluginName, featureName, id, (Class<? extends SystemProperty>) clazz, configuration);
111        }
112        catch (ComponentException | ClassNotFoundException e)
113        {
114            throw new ConfigurationException("Unable to instanciate the SystemProperty of id '" + id + "'.", e);
115        }
116    }
117    
118    @SuppressWarnings("unchecked")
119    @Override
120    public void initializeExtensions() throws Exception
121    {
122        super.initializeExtensions();
123        
124        _displayProps = new ArrayList<>();
125        _searchProps = new ArrayList<>();
126        
127        for (String id : getExtensionsIds())
128        {
129            SystemProperty prop = getExtension(id);
130            prop.setAvailableTypeExtensionPoint(_contentPropertyTypeExtensionPoint);
131            
132            if (prop.isDisplayable())
133            {
134                _displayProps.add(id);
135            }
136            if (prop.isSearchable())
137            {
138                _searchProps.add(id);
139            }
140        }
141    }
142    
143    /**
144     * Get the IDs of the properties that can be displayed.
145     * @return The Collection of properties that can be displayed.
146     */
147    public List<String> getDisplayProperties()
148    {
149        return Collections.unmodifiableList(_displayProps);
150    }
151    
152    /**
153     * Get the IDs of the properties that can be searched on.
154     * @return The Collection of properties that can be searched on.
155     */
156    public List<String> getSearchProperties()
157    {
158        return Collections.unmodifiableList(_searchProps);
159    }
160    
161    /**
162     * Tests if a property exists and is displayable.
163     * @param name The property name.
164     * @return <code>true</code> if the property exists and is displayable.
165     */
166    public boolean isDisplayable(String name)
167    {
168        return _displayProps.contains(name);
169    }
170    
171    /**
172     * Tests if a property exists and is searchable.
173     * @param name The property name.
174     * @return <code>true</code> if the property exists and is searchable.
175     */
176    public boolean isSearchable(String name)
177    {
178        return _searchProps.contains(name);
179    }
180
181}