001/*
002 *  Copyright 2014 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.runtime.model.disableconditions;
017
018import java.util.ArrayList;
019import java.util.Collection;
020import java.util.UUID;
021
022import org.apache.avalon.framework.activity.Disposable;
023import org.apache.avalon.framework.component.Component;
024import org.apache.avalon.framework.configuration.Configurable;
025import org.apache.avalon.framework.configuration.Configuration;
026import org.apache.avalon.framework.configuration.ConfigurationException;
027import org.apache.avalon.framework.context.Context;
028import org.apache.avalon.framework.context.ContextException;
029import org.apache.avalon.framework.context.Contextualizable;
030import org.apache.avalon.framework.service.ServiceException;
031import org.apache.avalon.framework.service.ServiceManager;
032import org.apache.avalon.framework.service.Serviceable;
033import org.slf4j.Logger;
034
035import org.ametys.runtime.plugin.component.LogEnabled;
036import org.ametys.runtime.plugin.component.PluginAware;
037import org.ametys.runtime.plugin.component.ThreadSafeComponentManager;
038import org.ametys.runtime.util.ParameterizedTypesHelper;
039
040/**
041 * List of disable conditions
042 * Composed by a list of sub conditions or conditions and a association operator
043 * @param <T> The type of disable condition
044 */
045public abstract class AbstractStaticRelativeDisableConditions<T extends DisableCondition> extends AbstractDisableConditions<T> implements Component, Serviceable, Contextualizable, Configurable, Disposable, LogEnabled, PluginAware
046{
047    private Context _context;
048    private ServiceManager _manager;
049    private String _pluginName;
050    private String _featureName;
051    
052    private ThreadSafeComponentManager<DisableConditions> _disableConditionsManager;
053    private ThreadSafeComponentManager<T> _disableConditionManager;
054    private Logger _logger;
055    
056    private Class<T> _conditionType;
057    {
058        _conditionType = ParameterizedTypesHelper.getFirstActualClassArgument(AbstractDisableConditions.class, this.getClass());
059    }
060    
061    public void contextualize(Context context) throws ContextException
062    {
063        _context = context;
064    }
065
066    public void service(ServiceManager manager) throws ServiceException
067    {
068        _manager = manager;
069    }
070
071    public void configure(Configuration configuration) throws ConfigurationException
072    {
073        _disableConditionsManager = new ThreadSafeComponentManager<>();
074        _disableConditionsManager.setLogger(getLogger());
075        _disableConditionsManager.contextualize(_context);
076        _disableConditionsManager.service(_manager);
077        
078        _disableConditionManager = new ThreadSafeComponentManager<>();
079        _disableConditionManager.setLogger(getLogger());
080        _disableConditionManager.contextualize(_context);
081        _disableConditionManager.service(_manager);
082        
083        Collection<String> conditionsRoles = new ArrayList<>();
084        Collection<String> conditionRoles = new ArrayList<>();
085        
086        for (Configuration conditionConfiguration : configuration.getChildren())
087        {
088            String tagName = conditionConfiguration.getName();
089            
090            // Recursive case
091            if (tagName.equals("conditions"))
092            {
093                final String conditionsRole = getClass().getName() + "$" + UUID.randomUUID().toString();
094                _disableConditionsManager.addComponent(_pluginName, _featureName, conditionsRole, getClass(), conditionConfiguration);
095                conditionsRoles.add(conditionsRole);
096            }
097            else if (tagName.equals("condition"))
098            {
099                String conditionRole = configureDisableCondition(conditionConfiguration);
100                conditionRoles.add(conditionRole);
101            }
102        }
103        
104        try
105        {
106            _disableConditionsManager.initialize();
107            for (String conditionsRole : conditionsRoles)
108            {
109                DisableConditions<T> conditions = _disableConditionsManager.lookup(conditionsRole);
110                getSubConditions().add(conditions);
111            }
112            
113            _disableConditionManager.initialize();
114            for (String conditionRole : conditionRoles)
115            {
116                T condition = _disableConditionManager.lookup(conditionRole);
117                getConditions().add(condition);
118            }
119        }
120        catch (Exception e)
121        {
122            throw new ConfigurationException("Unable to configure disable conditions", configuration, e);
123        }
124        
125        setAssociation(ASSOCIATION_TYPE.valueOf(configuration.getAttribute("type", "and").toUpperCase()));
126    }
127    
128    /**
129     * Configures the disable condition from the given configuration
130     * @param conditionConfiguration the condition's configuration
131     * @return the role of the condition
132     * @throws ConfigurationException if an error occurs
133     */
134    protected String configureDisableCondition(Configuration conditionConfiguration) throws ConfigurationException
135    {
136        String id = conditionConfiguration.getAttribute("id", null);
137        if (id != null)
138        {
139            final String conditionRole = id + "$" + UUID.randomUUID().toString();
140            addDisableConditionComponent(conditionRole, _conditionType, conditionConfiguration);
141
142            return conditionRole;
143        }
144        else
145        {
146            throw new ConfigurationException("Unable to configure a condition with no specified id of relative item", conditionConfiguration);
147        }
148    }
149    
150    /**
151     * Add a component of disable condition
152     * @param conditionRole the condition's role
153     * @param conditionClass the condition's class
154     * @param conditionConfiguration the condition's configuration
155     */
156    protected void addDisableConditionComponent(String conditionRole, Class<T> conditionClass, Configuration conditionConfiguration)
157    {
158        _disableConditionManager.addComponent(_pluginName, _featureName, conditionRole, conditionClass, conditionConfiguration);
159    }
160    
161    public void setPluginInfo(String pluginName, String featureName, String id)
162    {
163        _pluginName = pluginName;
164        _featureName = featureName;
165    }
166    
167    /**
168     * Returns the {@link Logger}.
169     * @return the {@link Logger}.
170     */
171    protected Logger getLogger()
172    {
173        return _logger;
174    }
175
176    public void setLogger(Logger logger)
177    {
178        _logger = logger;
179    }
180    
181    public void dispose()
182    {
183        _disableConditionsManager.dispose();
184        _disableConditionsManager = null;
185        
186        _disableConditionManager.dispose();
187        _disableConditionManager = null;
188    }
189}