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 }