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 */
016package org.ini4j;
017
018import java.util.Map;
019import java.util.SortedMap;
020import java.util.TreeMap;
021
022public 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}