View Javadoc
1 package com.bonevich.util.dependency; 2 3 import java.util.*; 4 5 /*** 6 * Provides automatic tracking of dependencies on dynamic and other 7 * dependent attributes in and outside an information model. 8 */ 9 public class Dependent extends Sentry 10 { 11 private static class Status { } 12 private static final Status INVALID = new Status(); 13 private static final Status VALID = new Status(); 14 private static final Status VALIDATING = new Status(); 15 16 private UpdateAction _update; 17 private Status _status = INVALID; 18 private List _sentries = new LinkedList(); 19 private DependentProxy _this = new DependentProxy() 20 { 21 public void invalidate() 22 { 23 Dependent.this.invalidate(); 24 } 25 public void addSentry(SentryProxy sentry) 26 { 27 Dependent.this.addSentry(sentry); 28 } 29 }; 30 31 public Dependent(UpdateAction update) 32 { 33 _update = update; 34 } 35 36 public boolean isValid() { return _status == VALID; } 37 public boolean isInvalid() { return _status == INVALID; } 38 public boolean isValidating() { return _status == VALIDATING; } 39 40 public void cleanup() 41 { 42 if ( isValid() ) 43 { 44 // This will make all sentries forget about me 45 invalidate(); 46 } 47 48 assertStatus(INVALID); 49 super.cleanup(); 50 } 51 52 /*** 53 * Check the current status and, if invalid, call onUpdate. If the 54 * current status is validating, throws an <code>IllegalStateException</code> 55 * as this indicates the presence of a cycle in the update process. 56 * NOTE: in order for a Dependent to automatically detect that the 57 * underlying information model has changed, it must use the model 58 * class instances on which it depends inside the <code>UpdateAction.onUpdate()</code> 59 * implementation. 60 */ 61 public final void onGet() 62 { 63 // Bring this attribute up to date whenever it is referenced 64 if ( isValidating() ) 65 { 66 throw new IllegalStateException("Cycle discovered during update"); 67 } 68 else if ( isInvalid() ) 69 { 70 // Push myself to the active dependent stack 71 DependentProxy stack = _activeDependent; 72 _activeDependent = _this; 73 74 // Update the attribute 75 _status = VALIDATING; 76 try 77 { 78 _update.onUpdate(); 79 } 80 finally 81 { 82 _status = VALID; 83 84 // Pop myself off the active dependent stack 85 // FIXME: is this really thread safe?? 86 _activeDependent = stack; 87 } 88 } 89 // else VALID: No action required 90 assertStatus(VALID); 91 92 // Establish dependency between the current update 93 // and this attribute 94 recordDependent(); 95 } 96 97 protected void invalidate() 98 { 99 assertStatus(VALID); 100 101 // Tell all sentries to forget about me 102 Iterator itr = _sentries.iterator(); 103 while (itr.hasNext()) 104 { 105 SentryProxy sentry = (SentryProxy)itr.next(); 106 sentry.removeDependent(_this); 107 } 108 _sentries.clear(); 109 110 // Make all indirect dependents out-of-date, too 111 invalidateDependents(); 112 _status = INVALID; 113 } 114 115 private void addSentry(SentryProxy sentry) 116 { 117 _sentries.add(sentry); 118 } 119 120 private void assertStatus(Status s) 121 { 122 if (_status != s) 123 { 124 throw new IllegalStateException("Improper usage of dependency sentries"); 125 } 126 } 127 } /*** end class Dependent */

This page was automatically generated by Maven