001 // GraphLab Project: http://graphlab.sharif.edu 002 // Copyright (C) 2008 Mathematical Science Department of Sharif University of Technology 003 // Distributed under the terms of the GNU General Public License (GPL): http://www.gnu.org/licenses/ 004 005 package graphlab.platform.attribute; 006 007 import java.util.Collection; 008 import java.util.Iterator; 009 import java.util.Map; 010 011 /** 012 * A handy NotifiableSet which acts on any AttributeSet and converts it to a NotifiableAttributeSet, 013 * This is done by checking the AttributeSet for changes in each (100) mili seconds. 014 * changes on (T) input will take effect on next 100 milisecond, 015 * using this class should be done with care, this class uses a thread 016 * and checks the edge on each 100ms for any changes, so creating a lot of 017 * instances of this class (for example for all edges of graph) 018 * will take more and more cpu, 019 * <p/> 020 * try to create as few as possible instances of this class and call stop() when you don't need 021 * it any more! 022 * <p/> 023 */ 024 public class TimeLimitedNotifiableAttrSet<T extends AttributeSet> implements Runnable, NotifiableAttributeSet { 025 private boolean started = false; 026 private long millis = 100; 027 Thread thread; 028 private T inp; 029 NotifiableAttributeSetImpl as = new NotifiableAttributeSetImpl(); 030 031 public TimeLimitedNotifiableAttrSet(T input) { 032 this.inp = input; 033 thread = new Thread(this); 034 } 035 036 /** 037 * starts firinig listeners to this class 038 */ 039 public void start() { 040 started = true; 041 thread.start(); 042 } 043 044 /** 045 * stops firing listeners 046 */ 047 public void stop() { 048 started = false; 049 } 050 051 /** 052 * -> Thread 053 */ 054 public void run() { 055 Map<String, Object> old = inp.getAttrs(); 056 Map<String, Object> _new; 057 while (started) { 058 _new = inp.getAttrs(); 059 fireChange(old, _new); 060 try { 061 old = inp.getAttrs(); 062 Thread.sleep(millis); 063 } catch (InterruptedException e1) { 064 e1.printStackTrace(); 065 } 066 } 067 } 068 069 private void fireChange(Map<String, Object> _new, Map<String, Object> old) { 070 Iterator<Map.Entry<String, Object>> i = old.entrySet().iterator(); 071 while (i.hasNext()) { 072 Map.Entry<String, Object> e = i.next(); 073 String key = e.getKey(); 074 Object value = e.getValue(); 075 if (value == null) { 076 if (!(_new.get(key) == null && _new.containsKey(key))) { 077 inp.put(key, value); 078 079 } 080 } else { 081 if (!value.equals(_new.get(key))) { 082 fireAttributeChange(getAttributeListeners(), key, old, value); 083 inp.put(key, value); 084 fireAttributeChange(getAttributeListeners(), key, old, value); 085 } 086 } 087 } 088 089 } 090 091 //----- NotifiableAttributeSet Methods 092 093 public Map<String, Object> getAttrs() { 094 return inp.getAttrs(); 095 } 096 097 public void put(String name, Object value) { 098 Object old = get(name); 099 inp.put(name, value); 100 fireAttributeChange(getAttributeListeners(), name, old, value); 101 } 102 103 public Object get(String name) { 104 return inp.get(name); 105 } 106 107 public void addAttributeListener(AttributeListener attributeListener) { 108 as.addAttributeListener(attributeListener); 109 } 110 111 public Collection<AttributeListener> getAttributeListeners() { 112 return as.getAttributeListeners(); 113 } 114 115 public void removeAttributeListener(AttributeListener attributeListener) { 116 as.removeAttributeListener(attributeListener); 117 } 118 119 public void fireAttributeChange(Collection<AttributeListener> listeners, String name, Object oldVal, Object newVal) { 120 if (listeners != null) { 121 for (AttributeListener l : listeners) { 122 l.attributeUpdated(name, oldVal, newVal); 123 } 124 } 125 } 126 127 }