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    @Override
047    public void service(ServiceManager manager) throws ServiceException
048    {
049        super.service(manager);
050        _contentPropertyTypeExtensionPoint = (ModelItemTypeExtensionPoint) manager.lookup(ModelItemTypeExtensionPoint.ROLE_CONTENT_PROPERTY);
051    }
052    
053    @Override
054    public void addExtension(String id, String pluginName, String featureName, Configuration configuration) throws ConfigurationException
055    {
056        if (getLogger().isDebugEnabled())
057        {
058            getLogger().debug("Adding system properties from feature " + pluginName + "/" + featureName);
059        }
060        
061        try
062        {
063            for (Configuration propConf : configuration.getChildren("property"))
064            {
065                addSystemProperty(pluginName, featureName, propConf);
066            }
067        }
068        catch (ConfigurationException e)
069        {
070            if (getLogger().isWarnEnabled())
071            {
072                getLogger().warn("The feature '" + pluginName + "/" + featureName + "' declares a system property extension with an invalid configuration.", e);
073            }
074        }
075    }
076    
077    /**
078     * Declare a new system property.
079     * @param pluginName The name of the plugin declaring the extension
080     * @param featureName The feature name.
081     * @param configuration The configuration of the extension
082     * @throws ConfigurationException if configuration if not complete
083     */
084    @SuppressWarnings("unchecked")
085    protected void addSystemProperty(String pluginName, String featureName, Configuration configuration) throws ConfigurationException
086    {
087        String id = configuration.getAttribute("id", "");
088        if (StringUtils.isBlank(id))
089        {
090            throw new ConfigurationException("SystemProperty declaration is incorrect since no 'id' attribute is specified (or may be empty)", configuration);
091        }
092        
093        String className = configuration.getAttribute("class", "");
094        if (StringUtils.isBlank(className))
095        {
096            throw new ConfigurationException("SystemProperty declaration is incorrect since no 'class' attribute is specified (or may be empty)", configuration);
097        }
098        
099        try
100        {
101            Class<?> clazz = Class.forName(className);
102            if (!SystemProperty.class.isAssignableFrom(clazz))
103            {
104                throw new ConfigurationException("The system property declaration must be declared with a class implementing SystemProperty.");
105            }
106            
107            addComponent(pluginName, featureName, id, (Class<? extends SystemProperty>) clazz, configuration);
108        }
109        catch (ComponentException | ClassNotFoundException e)
110        {
111            throw new ConfigurationException("Unable to instanciate the SystemProperty of id '" + id + "'.", e);
112        }
113    }
114    
115    @SuppressWarnings("unchecked")
116    @Override
117    public void initializeExtensions() throws Exception
118    {
119        super.initializeExtensions();
120        
121        _displayProps = new ArrayList<>();
122        for (String id : getExtensionsIds())
123        {
124            SystemProperty prop = getExtension(id);
125            prop.setAvailableTypeExtensionPoint(_contentPropertyTypeExtensionPoint);
126            
127            if (prop.isDisplayable())
128            {
129                _displayProps.add(id);
130            }
131        }
132    }
133    
134    /**
135     * Get the IDs of the properties that can be displayed.
136     * @return The Collection of properties that can be displayed.
137     */
138    public List<String> getDisplayProperties()
139    {
140        return Collections.unmodifiableList(_displayProps);
141    }
142    
143    /**
144     * Tests if a property exists and is displayable.
145     * @param name The property name.
146     * @return <code>true</code> if the property exists and is displayable.
147     */
148    public boolean isDisplayable(String name)
149    {
150        return _displayProps.contains(name);
151    }
152}