package foam.dao;

import foam.core.*;
import java.util.*;
import foam.mlang.order.Comparator;
import foam.mlang.predicate.Predicate;

public class MapDAO extends AbstractDAO {
  private Map<Object, FObject> data_ = null;

  private Map<Object, FObject> getData() {
    if ( data_ == null ) {
      data_ = (HashMap<Object, FObject>)getX().create(HashMap.class);
    }
    return data_;
  }

  public void setData(Map<Object, FObject> data) {
    data_ = data;
  }

  private ClassInfo of_ = null;
  private PropertyInfo primaryKey_ = null;

  public ClassInfo getOf() {
    return of_;
  }
  public MapDAO setOf(ClassInfo of) {
    of_ = of;
    primaryKey_ = (PropertyInfo)of.getAxiomByName("id");
    return this;
  }
  public PropertyInfo getPrimaryKey() {
    return primaryKey_;
  }


  public FObject put(FObject obj) {
    getData().put(getPrimaryKey().get(obj), obj);

    return obj;
  }

  public FObject remove(FObject obj) {
    getData().remove(getPrimaryKey().get(obj));
    return obj;
  }

  public FObject find(Object id) {
    FObject result = getData().get(id);
    return result;
  }

  public Sink select(Sink s, Integer skip, Integer limit, Comparator order, Predicate predicate) {
    if ( s == null ) {
      s = new ListSink();
    }

    s = decorateSink_(s, skip, limit, order, predicate);

    FlowControl fc = (FlowControl)getX().create(FlowControl.class);

    for ( FObject obj : getData().values() ) {
      if ( fc.getStopped() || fc.getErrorEvt() != null ) {
        break;
      }

      s.put(obj, fc);
    }

    if ( fc.getErrorEvt() != null ) {
      s.error();
      return s;
    }

    s.eof();

    return s;
  }

  public void removeAll(Integer skip, Integer limit, Comparator order, Predicate predicate) {
    setData(null);
  }

  public void pipe(Sink s) {
    // TODO
  }
}

@@ -48,24 +48,71 @@
 ava.util.*;%0A
+import java.util.concurrent.ConcurrentHashMap;%0A
 import foam.
@@ -277,36 +277,38 @@
 ate 
-Map%3CObject, FObject%3E getData
+synchronized void data_factory
 () %7B
@@ -350,20 +350,16 @@
 ata_ = (
-Hash
 Map%3CObje
@@ -385,16 +385,26 @@
 .create(
+Concurrent
 HashMap.
@@ -417,16 +417,119 @@
 ;%0A    %7D%0A
+  %7D%0A%0A  private Map%3CObject, FObject%3E getData() %7B%0A    if ( data_ == null ) %7B%0A      data_factory();%0A    %7D%0A
     retu
@@ -738,24 +738,25 @@
 rn of_;%0A  %7D%0A
+%0A
   public Map
@@ -1029,17 +1029,16 @@
 , obj);%0A
-%0A
     retu
@@ -1284,16 +1284,19 @@
 t(Sink s
+ink
 , Intege
@@ -1369,16 +1369,19 @@
   if ( s
+ink
  == null
@@ -1392,16 +1392,19 @@
 %0A      s
+ink
  = new L
@@ -1425,17 +1425,30 @@
  %7D%0A%0A    
-s
+Sink decorated
  = decor
@@ -1457,16 +1457,19 @@
 eSink_(s
+ink
 , skip, 
@@ -1700,17 +1700,25 @@
 %0A%0A      
-s
+decorated
 .put(obj
@@ -1775,17 +1775,25 @@
 %7B%0A      
-s
+decorated
 .error()
@@ -1804,24 +1804,27 @@
     return s
+ink
 ;%0A    %7D%0A%0A   
@@ -1824,17 +1824,25 @@
  %7D%0A%0A    
-s
+decorated
 .eof();%0A
@@ -1854,16 +1854,19 @@
 return s
+ink
 ;%0A  %7D%0A%0A 

Upgrade MapDAO to use a ConcurrentHashMap.