001    /*
002      GRANITE DATA SERVICES
003      Copyright (C) 2012 GRANITE DATA SERVICES S.A.S.
004    
005      This file is part of Granite Data Services.
006    
007      Granite Data Services is free software; you can redistribute it and/or modify
008      it under the terms of the GNU Library General Public License as published by
009      the Free Software Foundation; either version 2 of the License, or (at your
010      option) any later version.
011    
012      Granite Data Services is distributed in the hope that it will be useful, but
013      WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014      FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
015      for more details.
016    
017      You should have received a copy of the GNU Library General Public License
018      along with this library; if not, see <http://www.gnu.org/licenses/>.
019    */
020    
021    package org.granite.client.tide.data.impl;
022    
023    import java.util.ArrayList;
024    import java.util.List;
025    import java.util.WeakHashMap;
026    
027    import org.granite.client.tide.data.Identifiable;
028    
029    /**
030     *  Implementation of HashSet that holds weak references to UID entities 
031     *  
032     *  @author William DRAI
033     */
034    public class UIDWeakSet {
035        
036        private WeakHashMap<Object, Object>[] table;
037        
038        
039        public UIDWeakSet() {
040            this(64);
041        }
042        
043        @SuppressWarnings("unchecked")
044        public UIDWeakSet(int capacity) {
045            table = new WeakHashMap[capacity];  
046        }
047        
048        public void clear() {
049            for (int i = 0; i < table.length; i++)
050                table[i] = null;
051        }
052        
053        public Identifiable put(Identifiable uidObject) {
054            int h = hash(uidObject.getClass().getName() + ":" + uidObject.getUid());
055            
056            WeakHashMap<Object, Object> dic = table[h];
057            if (dic == null) {
058                dic = new WeakHashMap<Object, Object>();
059                table[h] = dic;
060            }
061            
062            Identifiable old = null;
063            for (Object o : dic.keySet()) {
064                if (o == uidObject)
065                    return (Identifiable)o;
066                
067                if (((Identifiable)o).getUid() == uidObject.getUid() && o.getClass().getName().equals(uidObject.getClass().getName())) {
068                    old = (Identifiable)o;
069                    dic.remove(o);
070                    break;
071                }
072            }
073            
074            dic.put(uidObject, null);
075            
076            return old;
077        }
078        
079        public Identifiable get(String uid) {
080            int h = hash(uid);
081            
082            Identifiable uidObject = null;
083            
084            WeakHashMap<Object, Object> dic = table[h];
085            if (dic != null) {
086                for (Object o : dic.keySet()) {
087                    if ((o.getClass().getName() + ":" + ((Identifiable)o).getUid()).equals(uid)) {
088                        uidObject = (Identifiable)o;
089                        break;
090                    }
091                }
092            }
093            
094            return uidObject;
095        }
096    
097        public static interface Matcher {
098            
099            public boolean match(Object o);
100        }
101        
102        public Object find(Matcher matcher) {
103            for (int i = 0; i < table.length; i++) {
104                WeakHashMap<Object, Object> dic = table[i];
105                if (dic != null) {
106                    for (Object o : dic.keySet()) {
107                        if (matcher.match(o))
108                            return o;
109                    }
110                }
111            }
112            return null;
113        }
114    
115        public static interface Operation {
116            
117            public void apply(Object o);
118        }
119        
120        public void apply(Operation operation) {
121            for (int i = 0; i < table.length; i++) {
122                WeakHashMap<Object, Object> dic = table[i];
123                if (dic != null) {
124                    for (Object o : dic.keySet())
125                        operation.apply(o);
126                }
127            }
128        }
129        
130        public Identifiable remove(String uid) {
131            int h = hash(uid);
132            
133            Identifiable uidObject = null;
134            
135            WeakHashMap<Object, Object> dic = table[h];
136            if (dic != null) {
137                for (Object o : dic.keySet()) {
138                    if ((o.getClass().getName() + ":" + ((Identifiable)o).getUid()).equals(uid)) {
139                        uidObject = (Identifiable)o;
140                        dic.remove(o);
141                        break;
142                    }
143                }
144            }
145            
146            return uidObject;
147        }
148        
149        public int size() {
150            int size = 0;
151            
152            for (int i = 0; i < table.length; i++) {
153                WeakHashMap<Object, Object> dic = table[i];
154                if (dic != null)
155                    size += dic.size();
156            }
157            
158            return size;
159        }
160        
161        public List<Object> data() {
162            List<Object> d = new ArrayList<Object>();
163            
164            for (int i = 0; i < table.length; i++) {
165                WeakHashMap<Object, Object> dic = table[i];
166                if (dic != null)
167                    d.addAll(dic.keySet());
168            }
169            return d;
170        }
171        
172        private int hash(String uid) {
173            int h = 0;
174            int max = uid.length();
175            for (int i = 0; i < max; i++)
176                h = (31 * h) + uid.charAt(i);
177            return (Math.abs(h) % table.length);
178        }
179    }