All Downloads are FREE. Search and download functionalities are using the official Maven repository.

gw.util.cache.WeakFqnCache Maven / Gradle / Ivy

There is a newer version: 1.18.2
Show newest version
/*
 * Copyright 2014 Guidewire Software, Inc.
 */

package gw.util.cache;

import gw.util.Predicate;

import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;

/**
 */
public class WeakFqnCache implements IFqnCache {
  private FqnCache> _cache;
  private ReferenceQueue _queue;

  public WeakFqnCache() {
    _cache = new FqnCache<>();
    _queue = new ReferenceQueue();
  }

  @Override
  public void add( String fqn ) {
    add( fqn, null );
  }

  @Override
  public void add( String fqn, T userData ) {
    removeReleasedEntries();
    KeyedReference ref = new KeyedReference( fqn, userData, _queue );
    _cache.add( fqn, ref );
  }

  @Override
  public boolean remove( String fqn ) {
    removeReleasedEntries();
    return _remove( fqn );
  }
  private boolean _remove( String fqn ) {
    return _cache.remove( fqn );
  }

  @Override
  public T get( String fqn ) {
    WeakReference ref = _cache.get( fqn );
    return ref == null ? null : ref.get();
  }

  @Override
  public FqnCacheNode> getNode( String fqn ) {
    return _cache.getNode( fqn );
  }

  @Override
  public boolean contains( String fqn ) {
    return _cache.contains( fqn );
  }

  @Override
  public void remove( String[] fqns ) {
    removeReleasedEntries();
    _cache.remove( fqns );
  }

  @Override
  public void clear() {
    _cache.clear();
  }

  @Override
  public Set getFqns() {
    return _cache.getFqns();
  }

  @Override
  public void visitDepthFirst( final Predicate visitor ) {
    Predicate> delegate = new Predicate>() {
      @Override
      public boolean evaluate( WeakReference node ) {
        T userData = node == null ? null : node.get();
        return visitor.evaluate( userData );
      }
    };
    List>> copy = new ArrayList>>( _cache.getRoot().getChildren() );
    for( FqnCacheNode> child: copy ) {
      if( !child.visitDepthFirst( delegate ) ) {
        return;
      }
    }
  }

  public void visitNodeDepthFirst( final Predicate visitor ) {
    List>> copy = new ArrayList>>( _cache.getRoot().getChildren() );
    for( FqnCacheNode> child: copy ) {
      if( !child.visitNodeDepthFirst( visitor ) ) {
        return;
      }
    }
  }

  @Override
  public void visitBreadthFirst( final Predicate visitor ) {
    Predicate> delegate = new Predicate>() {
      @Override
      public boolean evaluate( WeakReference node ) {
        T userData = node == null ? null : node.get();
        return visitor.evaluate( userData );
      }
    };
    List>> copy = new ArrayList>>( _cache.getRoot().getChildren() );
    for( FqnCacheNode> child: copy ) {
      child.visitBreadthFirst( delegate );
    }
  }

  private static class KeyedReference extends WeakReference {
    private String _fqn;

    public KeyedReference( String fqn, T referent, ReferenceQueue queue ) {
      super( referent, queue );
      _fqn = fqn;
    }

    public boolean equals( final Object o ) {
      if( this == o ) {
        return true;
      }
      if( o == null || getClass() != o.getClass() ) {
        return false;
      }

      final KeyedReference that = (KeyedReference)o;

      return _fqn.equals( that._fqn ) && equal( get(), that.get() );
    }

    private  boolean equal( T p1, T p2 ) {
      if( p1 == null || p2 == null ) {
        return p1 == p2;
      }
      else if( p1 instanceof Object[] && p2 instanceof Object[] ) {
        Object[] arr1 = (Object[])p1;
        Object[] arr2 = (Object[])p2;
        return Arrays.equals( arr1, arr2 );
      }
      else {
        return p1.equals( p2 );
      }
    }

    public int hashCode() {
      return _fqn.hashCode();
    }
  }

  private void removeReleasedEntries() {
    while( true ) {
      KeyedReference ref = (KeyedReference)_queue.poll();
      if( ref == null ) {
        break;
      }
      FqnCacheNode> node = getNode( ref._fqn );
      if( node != null && node.isLeaf() && node.getUserData() == ref ) {
        _remove( ref._fqn );
      }
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy