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