1 33 34 package edu.rice.cs.drjava.model.cache; 35 36 import javax.swing.text.BadLocationException ; 37 import java.util.*; 38 import java.io.IOException ; 39 40 import edu.rice.cs.drjava.model.definitions.DefinitionsDocument; 41 import edu.rice.cs.drjava.model.OpenDefinitionsDocument; 42 import edu.rice.cs.drjava.model.FileMovedException; 43 import edu.rice.cs.util.UnexpectedException; 44 import edu.rice.cs.util.swing.Utilities; 45 import edu.rice.cs.util.OrderedHashSet; 46 47 72 73 public class DocumentCache { 74 75 private static final int INIT_CACHE_SIZE = 32; 76 77 78 private int CACHE_SIZE; 79 80 private OrderedHashSet<DocManager> _residentQueue; 81 82 private Object _cacheLock = new Object (); 83 84 85 public DocumentCache(int size) { 86 CACHE_SIZE = size; 88 _residentQueue = new OrderedHashSet<DocManager>(); 89 } 90 91 92 public DocumentCache() { this(INIT_CACHE_SIZE); } 93 94 99 public DCacheAdapter register(OpenDefinitionsDocument odd, DDReconstructor rec) { 100 DocManager mgr = new DocManager(rec, odd.toString(), odd.isUntitled()); 101 notifyRegistrationListeners(odd, mgr); return mgr; 104 } 105 106 110 public void setCacheSize(int size) { 111 if (size <= 0) throw new IllegalArgumentException ("Cannot set the cache size to zero or less."); 112 int diff; 113 DocManager[] removed = null; synchronized(_cacheLock) { CACHE_SIZE = size; 116 diff = _residentQueue.size() - CACHE_SIZE; 117 if (diff > 0) { 118 removed = new DocManager[diff]; 119 for (int i = 0; i < diff; i++) removed[i] = _residentQueue.remove(0); 120 } 121 if (diff > 0) kickOut(removed); 122 } 123 } 124 125 126 private void kickOut(DocManager[] removed) { 127 for (DocManager dm: removed) dm.kickOut(); 128 } 129 130 public int getCacheSize() { return CACHE_SIZE; } 131 public int getNumInCache() { return _residentQueue.size(); } 132 133 134 135 137 private static final int IN_QUEUE = 0; private static final int UNTITLED = 1; private static final int NOT_IN_QUEUE = 2; private static final int UNMANAGED = 3; 142 143 147 private class DocManager implements DCacheAdapter { 148 149 private final DDReconstructor _rec; 150 private volatile int _stat; private volatile DefinitionsDocument _doc; 152 private volatile String _fileName; 153 154 157 public DocManager(DDReconstructor rec, String fn, boolean isUntitled) { 158 _rec = rec; 160 if (isUntitled) _stat = UNTITLED; 161 else _stat = NOT_IN_QUEUE; 162 _doc = null; 163 _fileName = fn; 164 } 165 166 public DDReconstructor getReconstructor() { return _rec; } 167 168 173 public DefinitionsDocument getDocument() throws IOException , FileMovedException { 174 176 if (_doc != null) return _doc; 178 synchronized(_cacheLock) { if (_doc != null) return _doc; try { _doc = _rec.make(); 182 assert _doc != null; 183 } 184 catch(BadLocationException e) { throw new UnexpectedException(e); } 185 if (_stat == NOT_IN_QUEUE) add(); return _doc; 188 } 189 } 190 191 194 public boolean isReady() { synchronized (_cacheLock) { return _doc != null; } } 195 196 197 public void close() { 198 synchronized(_cacheLock) { 200 _residentQueue.remove(this); 201 closingKickOut(); 202 } 203 } 204 205 public void documentModified() { 206 synchronized(_cacheLock) { 207 _residentQueue.remove(this); _stat = UNMANAGED; 209 } 210 } 211 212 public void documentReset() { 213 synchronized(_cacheLock) { 214 if (_stat == UNMANAGED) add(); } 216 } 217 218 219 public void documentSaved(String fileName) { 220 synchronized(_cacheLock) { if (isUnmanagedOrUntitled()) { 223 _fileName = fileName; 224 add(); } 226 } 227 } 228 229 230 private void add() { 231 if (! _residentQueue.contains(this)) { 233 _residentQueue.add(this); 234 _stat = IN_QUEUE; 235 } 236 if (_residentQueue.size() > CACHE_SIZE) _residentQueue.get(0).remove(); 237 } 238 239 240 private void remove() { 241 boolean removed = _residentQueue.remove(this); 242 kickOut(); 243 } 244 245 246 private boolean isUnmanagedOrUntitled() { return (_stat & 0x1) != 0; } 248 251 void kickOut() { kickOut(false); } 252 253 256 void closingKickOut() { kickOut(true); } 257 258 259 private void kickOut(boolean isClosing) { 260 if (! isClosing) { 262 263 _rec.saveDocInfo(_doc); 265 } 266 if (_doc != null) { 267 _doc.close(); 268 _doc = null; 269 } 270 _stat = NOT_IN_QUEUE; 271 } 272 273 public String toString() { return _fileName; } 274 } 275 276 278 281 public interface RegistrationListener { 282 public void registered(OpenDefinitionsDocument odd, DCacheAdapter man); 283 } 284 285 private LinkedList<RegistrationListener> _regListeners = new LinkedList<RegistrationListener>(); 286 287 public void addRegistrationListener(RegistrationListener list) { synchronized(_regListeners) { _regListeners.add(list); } } 288 public void removeRegistrationListener(RegistrationListener list) { synchronized(_regListeners) { _regListeners.remove(list); } } 289 public void clearRegistrationListeners() { _regListeners.clear(); } 290 private void notifyRegistrationListeners(final OpenDefinitionsDocument odd, final DocManager man) { 292 synchronized(_regListeners) { 293 if (_regListeners.isEmpty()) return; 294 Utilities.invokeAndWait(new Runnable () { 295 public void run() { for (RegistrationListener list : _regListeners) { list.registered(odd, man); } } 296 }); 297 } 298 } 299 } 300 | Popular Tags |