1/*
2 * Copyright 2012 AndroidPlot.com
3 *
4 *    Licensed under the Apache License, Version 2.0 (the "License");
5 *    you may not use this file except in compliance with the License.
6 *    You may obtain a copy of the License at
7 *
8 *        http://www.apache.org/licenses/LICENSE-2.0
9 *
10 *    Unless required by applicable law or agreed to in writing, software
11 *    distributed under the License is distributed on an "AS IS" BASIS,
12 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 *    See the License for the specific language governing permissions and
14 *    limitations under the License.
15 */
16
17package com.androidplot.util;
18
19import java.util.HashMap;
20import java.util.List;
21
22/**
23 * Concrete implementation of ZIndexable.  Provides fast element retrieval via hash key.  Also provides
24 * mutable ordering (z indexing) of elements.
25 */
26public class ZHash<KeyType, ValueType> implements ZIndexable<KeyType> {
27
28    private HashMap<KeyType, ValueType> hash;
29    //private LinkedList<KeyType> zlist;
30    //private ListOrganizer<KeyType> listOrganizer;
31    private ZLinkedList<KeyType> zlist;
32
33    {
34        hash = new HashMap<KeyType, ValueType>();
35        zlist = new ZLinkedList<KeyType>();
36        //listOrganizer = new ListOrganizer<KeyType>(zlist);
37    }
38
39    public int size() {
40        return zlist.size();
41    }
42
43
44    public ValueType get(KeyType key) {
45        return hash.get(key);
46    }
47
48    public List<KeyType> getKeysAsList() {
49        return zlist;
50    }
51
52    /**
53     * If key already exists within the structure, it's value is replaced with the new value and
54     * it's existing order is maintained.
55     * @param key
56     * @param value
57     */
58    public synchronized void addToTop(KeyType key, ValueType value) {
59        if(hash.containsKey(key)) {
60            hash.put(key, value);
61           //throw new IllegalArgumentException("Key already exists in series structure...duplicates not permitted.");
62        } else {
63            hash.put(key, value);
64            zlist.addToTop(key);
65            //zlist.addToTop(key);
66        }
67    }
68
69    /**
70     * If key already exists within the structure, it's value is replaced with the new value and
71     * it's existing order is maintained.
72     * @param key
73     * @param value
74     */
75    public synchronized void addToBottom(KeyType key, ValueType value) {
76        if(hash.containsKey(key)) {
77            hash.put(key, value);
78           //throw new IllegalArgumentException("Key already exists in series structure...duplicates not permitted.");
79        } else {
80            hash.put(key, value);
81            zlist.addToBottom(key);
82            //zlist.addToBottom(key);
83        }
84    }
85
86    public synchronized boolean moveToTop(KeyType element) {
87        if(!hash.containsKey(element)) {
88            return false;
89        } else {
90            return zlist.moveToTop(element);
91        }
92    }
93
94    public synchronized boolean moveAbove(KeyType objectToMove, KeyType reference) {
95        if(objectToMove == reference) {
96            throw new IllegalArgumentException("Illegal argument to moveAbove(A, B); A cannot be equal to B.");
97        }
98        if(!hash.containsKey(reference) || !hash.containsKey(objectToMove)) {
99            return false;
100        } else {
101            return zlist.moveAbove(objectToMove, reference);
102        }
103    }
104
105    public synchronized boolean moveBeneath(KeyType objectToMove, KeyType reference) {
106        if(objectToMove == reference) {
107            throw new IllegalArgumentException("Illegal argument to moveBeaneath(A, B); A cannot be equal to B.");
108        }
109        if(!hash.containsKey(reference) || !hash.containsKey(objectToMove)) {
110            return false;
111        } else {
112            return zlist.moveBeneath(objectToMove, reference);
113        }
114    }
115
116    public synchronized boolean moveToBottom(KeyType key) {
117        if(!hash.containsKey(key)) {
118            return false;
119        } else {
120            return zlist.moveToBottom(key);
121        }
122    }
123
124    public synchronized boolean moveUp(KeyType key) {
125        if (!hash.containsKey(key)) {
126            return false;
127        } else {
128            return zlist.moveUp(key);
129        }
130    }
131
132    public synchronized boolean moveDown(KeyType key) {
133        if (!hash.containsKey(key)) {
134            return false;
135        } else {
136            return zlist.moveDown(key);
137        }
138    }
139
140    @Override
141    public List<KeyType> elements() {
142        return zlist;
143    }
144
145    /**
146     *
147     * @return Ordered list of keys.
148     */
149    public List<KeyType> keys() {
150        return elements();
151    }
152
153
154    public synchronized boolean remove(KeyType key) {
155        if(hash.containsKey(key)) {
156            hash.remove(key);
157            zlist.remove(key);
158            return true;
159        } else {
160            return false;
161        }
162    }
163}
164