001    /*
002     * Copyright 2005,2009 Ivan SZKIBA
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     */
016    package org.ini4j;
017    
018    import java.util.Map;
019    import java.util.SortedMap;
020    import java.util.TreeMap;
021    
022    public class CommonMultiMap<K, V> extends BasicMultiMap<K, V> implements CommentedMap<K, V>
023    {
024        private static final long serialVersionUID = 3012579878005541746L;
025        private static final String SEPARATOR = ";#;";
026        private static final String FIRST_CATEGORY = "";
027        private static final String LAST_CATEGORY = "zzzzzzzzzzzzzzzzzzzzzz";
028        private static final String META_COMMENT = "comment";
029        private SortedMap<String, Object> _meta;
030    
031        @Override public String getComment(Object key)
032        {
033            return (String) getMeta(META_COMMENT, key);
034        }
035    
036        @Override public void clear()
037        {
038            super.clear();
039            if (_meta != null)
040            {
041                _meta.clear();
042            }
043        }
044    
045        @SuppressWarnings("unchecked")
046        @Override public void putAll(Map<? extends K, ? extends V> map)
047        {
048            super.putAll(map);
049            if (map instanceof CommonMultiMap)
050            {
051                Map<String, String> meta = ((CommonMultiMap) map)._meta;
052    
053                if (meta != null)
054                {
055                    meta().putAll(meta);
056                }
057            }
058        }
059    
060        @Override public String putComment(K key, String comment)
061        {
062            return (String) putMeta(META_COMMENT, key, comment);
063        }
064    
065        @Override public V remove(Object key)
066        {
067            V ret = super.remove(key);
068    
069            removeMeta(key);
070    
071            return ret;
072        }
073    
074        @Override public V remove(Object key, int index)
075        {
076            V ret = super.remove(key, index);
077    
078            if (length(key) == 0)
079            {
080                removeMeta(key);
081            }
082    
083            return ret;
084        }
085    
086        @Override public String removeComment(Object key)
087        {
088            return (String) removeMeta(META_COMMENT, key);
089        }
090    
091        Object getMeta(String category, Object key)
092        {
093            return (_meta == null) ? null : _meta.get(makeKey(category, key));
094        }
095    
096        Object putMeta(String category, K key, Object value)
097        {
098            return meta().put(makeKey(category, key), value);
099        }
100    
101        void removeMeta(Object key)
102        {
103            if (_meta != null)
104            {
105                _meta.subMap(makeKey(FIRST_CATEGORY, key), makeKey(LAST_CATEGORY, key)).clear();
106            }
107        }
108    
109        Object removeMeta(String category, Object key)
110        {
111            return (_meta == null) ? null : _meta.remove(makeKey(category, key));
112        }
113    
114        private String makeKey(String category, Object key)
115        {
116            StringBuilder buff = new StringBuilder();
117    
118            buff.append(String.valueOf(key));
119            buff.append(SEPARATOR);
120            buff.append(category);
121    
122            return buff.toString();
123        }
124    
125        private Map<String, Object> meta()
126        {
127            if (_meta == null)
128            {
129                _meta = new TreeMap<String, Object>();
130            }
131    
132            return _meta;
133        }
134    }