001    /**
002     * Copyright (C) 2007-2011, Jens Lehmann
003     *
004     * This file is part of DL-Learner.
005     *
006     * DL-Learner is free software; you can redistribute it and/or modify
007     * it under the terms of the GNU General Public License as published by
008     * the Free Software Foundation; either version 3 of the License, or
009     * (at your option) any later version.
010     *
011     * DL-Learner is distributed in the hope that it will be useful,
012     * but WITHOUT ANY WARRANTY; without even the implied warranty of
013     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014     * GNU General Public License for more details.
015     *
016     * You should have received a copy of the GNU General Public License
017     * along with this program.  If not, see <http://www.gnu.org/licenses/>.
018     */
019    
020    package org.dllearner.core;
021    
022    import java.util.HashMap;
023    import java.util.LinkedList;
024    import java.util.List;
025    import java.util.Map;
026    
027    import org.apache.log4j.Logger;
028    import org.dllearner.core.options.ConfigEntry;
029    import org.dllearner.core.options.ConfigOption;
030    
031    /**
032     * Stores all live components and the configuration options, which were applied
033     * to them. This allows to detect, which components are currently active, which
034     * values are assigned to specific options, and to collect statistics (e.g. in
035     * a web service scenario).
036     * 
037     * @author Jens Lehmann
038     * 
039     */
040    public final class ComponentPool {
041    
042            private static Logger logger = Logger.getLogger(ComponentPool.class);   
043            
044            // stores all components, which are live (components which are
045            // no longer used have to be deregistered)
046            private List<AbstractComponent> components = new LinkedList<AbstractComponent>();
047    
048            // stores the last value which was set for a particular
049            // config option
050            private Map<AbstractComponent, Map<ConfigOption<?>, Object>> lastValidConfigValue = new HashMap<AbstractComponent, Map<ConfigOption<?>, Object>>();
051            // complete history of all made config entries for a component
052            private Map<AbstractComponent, List<ConfigEntry<?>>> configEntryHistory = new HashMap<AbstractComponent, List<ConfigEntry<?>>>();
053    
054            /**
055             * Registers a component instance in the pool. 
056             * @param component The component to add to the pool.
057             */
058            public void registerComponent(AbstractComponent component) {
059                    components.add(component);
060                    Map<ConfigOption<?>, Object> emptyMap = new HashMap<ConfigOption<?>, Object>();
061                    lastValidConfigValue.put(component, emptyMap);
062                    configEntryHistory.put(component, new LinkedList<ConfigEntry<?>>());
063                    logger.debug("Component instance " + component + " added to component pool.");
064            }
065    
066            /**
067             * Unregisters a component instance. This method should be used if the
068             * component will not be used anymore. It frees the memory for
069             * storing the component and its configuration options.  
070             * @param component The component to remove from the pool.
071             */
072            public void unregisterComponent(AbstractComponent component) {
073                    configEntryHistory.remove(component);
074                    lastValidConfigValue.remove(component);
075                    components.remove(component);
076                    logger.debug("Component instance " + component + " removed from component pool.");
077            }
078    
079            /**
080             * Gets the last valid config value set for this component.
081             * @param <T> The type of the value of the config option (String, Integer etc.).
082             * @param component The component to query.
083             * @param option The option for which one wants to get the value.
084             * @return The last value set for this option or null if the value hasn't been 
085             * set using the {@link ComponentManager}. In this case, the value is
086             * usually at the default value (or has been set internally surpassing the
087             * component architecture, which is not recommended).
088             */
089            @SuppressWarnings("unchecked")
090            protected <T> T getLastValidConfigValue(AbstractComponent component, ConfigOption<T> option) {
091                    return (T) lastValidConfigValue.get(component).get(option);
092            }
093    
094            /**
095             * Add a config entry change for the specified component.
096             * @param component The component, where the config entry has been set.
097             * @param entry The set config entry.
098             * @param valid A boolean value indicating whether the value was valid or not.
099             */
100            protected void addConfigEntry(AbstractComponent component, ConfigEntry<?> entry, boolean valid) {
101                    configEntryHistory.get(component).add(entry);
102                    if (valid) {
103                            lastValidConfigValue.get(component).put(entry.getOption(), entry.getValue());
104                    }
105                    logger.trace("Config entry " + entry + " has been set for component " + component + " (validity: " + valid + ").");
106            }
107    
108            /**
109             * Unregisters all components.
110             */
111            protected void clearComponents() {
112                    components = new LinkedList<AbstractComponent>();
113                    lastValidConfigValue = new HashMap<AbstractComponent, Map<ConfigOption<?>, Object>>();
114                    configEntryHistory = new HashMap<AbstractComponent, List<ConfigEntry<?>>>();
115            }
116            
117            /**
118             * @return The components in this pool.
119             */
120            public List<AbstractComponent> getComponents(){
121                    return components;
122            }
123    
124    }