abstract aspect Caching {
  interface C {
    java.util.Vector allInvalidated();
  }
  Object C.cachedValue; 
  void C.clearCache() {
    System.err.println("clear cache"); 
    cachedValue = null;
  }
  abstract pointcut cachedmeth(C t);
  abstract pointcut invalidate(C t);
  Object around(C t): cachedmeth(t) {  /* \label{line:cachedmeth1} */
    if(t.cachedValue==null) {
      t.cachedValue = proceed(t);      /* \label{line:cachedmeth2} */
    } else { System.err.println("using cached value"); }
    return t.cachedValue;
  }
  before(C t):invalidate(t) {
    java.util.Iterator it = t.allInvalidated().iterator();
    while (it.hasNext()) 
      ((C)it.next()).clearCache();
  }
}

