package edu.umd.rhsmith.diads.meater.core.config.container; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.TreeMap; import org.apache.commons.configuration.HierarchicalConfiguration; import org.apache.commons.configuration.SubnodeConfiguration; import org.apache.commons.configuration.tree.ConfigurationNode; import edu.umd.rhsmith.diads.meater.core.app.MEaterConfigurationException; import edu.umd.rhsmith.diads.meater.core.config.ConfigUnit; import edu.umd.rhsmith.diads.meater.core.config.setup.ops.instance.AddInstanceOperation; import edu.umd.rhsmith.diads.meater.core.config.setup.ops.instance.ListInstanceTypesOperation; import edu.umd.rhsmith.diads.meater.core.config.setup.ops.instance.ListInstancesOperation; import edu.umd.rhsmith.diads.meater.core.config.setup.ops.instance.RemoveInstanceOperation; import edu.umd.rhsmith.diads.meater.core.config.setup.ops.instance.SelectInstanceOperation; public class InstanceConfigContainer<I extends InstanceConfig> extends ConfigUnit { public static final String CKEY_INSTANCES = "instances"; // mapping of type names to routines for instantiating new configuration // types private final Map<String, InstanceConfigRegistration<? extends I>> typeRegistrations; // configurations belonging to this container private final List<I> configUnits; public InstanceConfigContainer(String uiName, String uiDescription) { super(uiName, uiDescription); this.typeRegistrations = new TreeMap<String, InstanceConfigRegistration<? extends I>>(); this.configUnits = new ArrayList<I>(); this.registerSetupConsoleOperation(new ListInstanceTypesOperation<I>( this)); this.registerSetupConsoleOperation(new AddInstanceOperation<I>(this)); this.registerSetupConsoleOperation(new ListInstancesOperation<I>(this)); this.registerSetupConsoleOperation(new SelectInstanceOperation<I>(this)); this.registerSetupConsoleOperation(new RemoveInstanceOperation<I>(this)); } public InstanceConfigContainer() { this(null, null); } /* * -------------------------------- * General getters/setters * -------------------------------- */ /* * -------------------------------- * Component type registrations * -------------------------------- */ public <T extends I> void registerConfigType(Class<T> type) { this.registerConfigType(new DefaultInstanceConfigRegistration<T>(type)); } public void registerConfigType( InstanceConfigRegistration<? extends I> registration) { this.typeRegistrations.put(registration.getName(), registration); } public String[] getInstanceConfigTypeNames() { String[] temp = new String[this.typeRegistrations.size()]; this.typeRegistrations.keySet().toArray(temp); return temp; } public String getConfigTypeDescription(String typeName) { InstanceConfigRegistration<?> registration = this.typeRegistrations .get(typeName); if (registration == null) { return null; } return registration.getDescription(); } public boolean supportsConfigType(String typeName) { return this.typeRegistrations.containsKey(typeName); } /* * -------------------------------- * Component configuration instances * -------------------------------- */ public I addNewConfigUnit(String typeName) throws ConfigInstantiationException { InstanceConfigRegistration<? extends I> registration = this.typeRegistrations .get(typeName); if (registration == null) { throw new ConfigInstantiationException(String.format( MSG_ERR_NOTREGISTERED_FMT, typeName, this.getUiName())); } I config = registration.createConfig(); config.setRegisteredTypeName(registration.getName()); this.configUnits.add(config); config.resetConfiguration(); return config; } public boolean removeInstanceConfig(I config) { return this.configUnits.remove(config); } public I getInstanceConfigByName(String instanceName) { for (I m : this.configUnits) { if (m.getInstanceName().equals(instanceName)) { return m; } } return null; } public List<I> getInstanceConfigs() { return new LinkedList<I>(this.configUnits); } public int getNumInstanceConfigs() { return this.configUnits.size(); } /* * -------------------------------- * Config operations * -------------------------------- */ @Override public void resetInternalConfiguration() { this.configUnits.clear(); } @Override protected void loadInternalConfigurationFrom( HierarchicalConfiguration config) throws MEaterConfigurationException { // load in components this.loadComponentConfigurationsFrom(config); } @Override protected void saveInternalConfigurationTo( HierarchicalConfiguration config) throws MEaterConfigurationException { // save out components this.saveComponentConfigurationsTo(config); } private void loadComponentConfigurationsFrom( HierarchicalConfiguration config) throws MEaterConfigurationException { // go to components section of config SubnodeConfiguration componentsConfig; try { componentsConfig = config.configurationAt(CKEY_INSTANCES); } catch (IllegalArgumentException e) { // though not in the apache javadoc, this exception is thrown if no // such configuration exists. // if it doesn't exist -- no components to load. return; } // pull out all components of types we know how to instantiate for (String typeName : this.typeRegistrations.keySet()) { List<HierarchicalConfiguration> ccs = componentsConfig .configurationsAt(typeName); // instantiate + load each one we find for (HierarchicalConfiguration cc : ccs) { I c; try { c = this.addNewConfigUnit(typeName); } catch (ConfigInstantiationException e) { throw new MEaterConfigurationException(e.getMessage()); } c.loadConfigurationFrom(cc); } } } private void saveComponentConfigurationsTo(HierarchicalConfiguration config) throws MEaterConfigurationException { // create a collection to hold the components section Collection<ConfigurationNode> configNodes = new LinkedList<ConfigurationNode>(); // save all of our components to the section for (I c : this.configUnits) { // create a configuration for the component + save it, add it HierarchicalConfiguration cc = new HierarchicalConfiguration(); c.saveConfigurationTo(cc); cc.getRootNode().setName(c.getRegisteredTypeName()); configNodes.add(cc.getRootNode()); } // add components section to config config.addNodes(CKEY_INSTANCES, configNodes); } /* * -------------------------------- * Messages * -------------------------------- */ private static final String MSG_ERR_NOTREGISTERED_FMT = "%s - No such instance type registered with %s"; }