001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018 package org.apache.commons.configuration;
019
020 import java.util.ArrayList;
021 import java.util.Iterator;
022 import java.util.List;
023 import java.util.Map;
024
025 /**
026 * <p>A Map based Configuration.</p>
027 * <p><em>Note:</em>Configuration objects of this type can be read concurrently
028 * by multiple threads. However if one of these threads modifies the object,
029 * synchronization has to be performed manually.</p>
030 *
031 * @author Emmanuel Bourg
032 * @version $Revision: 548098 $, $Date: 2007-06-17 21:34:03 +0200 (So, 17 Jun 2007) $
033 * @since 1.1
034 */
035 public class MapConfiguration extends AbstractConfiguration implements Cloneable
036 {
037 /** The Map decorated by this configuration. */
038 protected Map map;
039
040 /**
041 * Create a Configuration decorator around the specified Map. The map is
042 * used to store the configuration properties, any change will also affect
043 * the Map.
044 *
045 * @param map the map
046 */
047 public MapConfiguration(Map map)
048 {
049 this.map = map;
050 }
051
052 /**
053 * Return the Map decorated by this configuration.
054 *
055 * @return the map this configuration is based onto
056 */
057 public Map getMap()
058 {
059 return map;
060 }
061
062 public Object getProperty(String key)
063 {
064 Object value = map.get(key);
065 if ((value instanceof String) && (!isDelimiterParsingDisabled()))
066 {
067 List list = PropertyConverter.split((String) value, getListDelimiter());
068 return list.size() > 1 ? list : list.get(0);
069 }
070 else
071 {
072 return value;
073 }
074 }
075
076 protected void addPropertyDirect(String key, Object value)
077 {
078 Object previousValue = getProperty(key);
079
080 if (previousValue == null)
081 {
082 map.put(key, value);
083 }
084 else if (previousValue instanceof List)
085 {
086 // the value is added to the existing list
087 ((List) previousValue).add(value);
088 }
089 else
090 {
091 // the previous value is replaced by a list containing the previous value and the new value
092 List list = new ArrayList();
093 list.add(previousValue);
094 list.add(value);
095
096 map.put(key, list);
097 }
098 }
099
100 public boolean isEmpty()
101 {
102 return map.isEmpty();
103 }
104
105 public boolean containsKey(String key)
106 {
107 return map.containsKey(key);
108 }
109
110 protected void clearPropertyDirect(String key)
111 {
112 map.remove(key);
113 }
114
115 public Iterator getKeys()
116 {
117 return map.keySet().iterator();
118 }
119
120 /**
121 * Returns a copy of this object. The returned configuration will contain
122 * the same properties as the original. Event listeners are not cloned.
123 *
124 * @return the copy
125 * @since 1.3
126 */
127 public Object clone()
128 {
129 try
130 {
131 MapConfiguration copy = (MapConfiguration) super.clone();
132 copy.clearConfigurationListeners();
133 copy.map = (Map) ConfigurationUtils.clone(map);
134 return copy;
135 }
136 catch (CloneNotSupportedException cex)
137 {
138 // cannot happen
139 throw new ConfigurationRuntimeException(cex);
140 }
141 }
142 }