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