8 Ekim 2020 Perşembe

Hierarchical Cache - Hiyerarşik Önbellek

Giriş
Bize önce bir tane multimap lazım. Ancak bu multimap concurrent bir multimap olmalı.
Şöyle yaparız
public class ConcurrentMultiMap<K> {
  ConcurrentHashMap<Class<? extends K>,ConcurrentSkipListSet<K>> map = ...
  ...
}
Elimizde şöyle bir nesne olsun. Bu sınıf güncellenecek veriyi ve bu verinin kalıtım hiyerarşisini saklar.
public class DataEvent {
  private MyBaseObject data = ...;
  private Collection<Class<? extends MyBaseObject>> hierarchy = ...;

  Collection<Class<? extends MyBaseObject>> getHierarchy(){
    return hierarchy;
  }
  ... 
}
DataEvent'leri işleyen bir sınıf olsun. Bu sınıf gelen veriyi tüm ata sınıflara da ekler.
public class DataEventListener {
  private ConcurrentMultiMap<MyBaseObject> map;

  public void addToMap(DataEvent dataEvent){
    Collection<Class<? extends MyBaseObject>> hierarchy = dataEvent.getHierarchy();
    for(Class<? extends MyBaseObject> clazz : hierarchy){
      map.add(clazz,data);
    }
  }
}
Burada eksik kalan şey DataEvent nesnesini oluştururken data yanında bu data'ya ait üst sınıfları da verebilmek. Bunun için elimizde şöyle bir kod olsun
public class ClassCapsule<C> {
  private Class<? extends MyBaseObject> clazz;
  private HierarchicalCollection<Class<? extends MyBaseObject>> hierarchy; 

  public ClassCapsule(Class<? extends MyBaseObject> clazz){
    this.clazz = clazz;
    this.hierarchy = new HierarchicalCollection();
  }

  public void setParent(ClassCapsule<C> parent){
    hierarchy.setParent(parent.hierarchy);
  }

  public Collection<Class<? extends MyBaseObject> getHierarchy(){
    return hierarchy;
  }
}
HierarchicalCollection şöyle olsun
public class HierarchicalCollection<T> extends AbstractCollection {
  private Set<T> set = new HashSet<>();
  private HierarchicalCollection<T> parent;
  
  public setParentCollection(HierarchicalCollection<T> parent){
    this.parent = parent;
  }
  public Iterator<T> iterator(){
    return Iterators.concat(set.iterator(),parent.iterator());
  }
  public boolean contains(T object){
    return set.contains(object) || parent.contains(object);
  }
}
Şimdi elimizdeki sınıfları kalıtıma göre indeksleyelim
public class ClassCapsuleIndexer<C> {
  private Map<Class<? extends MyBaseObject>,ClassCapsule<C> capsuleMap = ...;

  public ClassCapsule<C> getClassCapsule(Class<? extends MyBaseObject> clazz){
    ClassCapsule<C> capsule = capsuleMap.get(clazz) 
    if (capsule == null){
      capsule = new ClassCapsule<C>(clazz);
      Class<? extends MyBaseObject> superClass = findSuperClass(clazz);
      if (superClass != null){
        classCapsule.setParent(getClassCapsuleFroClass(superClass));
      }
      capsuleMap.put(clazz,capsule);
    }
    return capsule;
  }
  
  private Class>? extends MyBaseObject> findSuperClass(Class<?> clazz){
    Class<? extends MyBaseObject> result = null;
    try {
      clazz.getSuperClass().asSubclass(MyBaseObject.class);
    } catch (ClassCastException e){
      ...
    }
   }
}
Böylece ClassCapsuleIndexer ile istenilen sınıf tipine ait ClassCapsule bulunur. ClassCapsule sınıfının getHierarchy() metodu ile ata sınıfların listesi elimize geçer. Biz de bu hiyerarşi üzerinde dolaşıp ConcurrentMultiMap'teki ata sınıflara ait key değerlerine de güncelleme yapabiliriz.

Hiç yorum yok:

Yorum Gönder