// Path: access-control/src/main/java/org/archive/accesscontrol/model/RuleSet.java
// public class RuleSet implements Iterable<Rule> {
//     protected HashMap<String, TreeSet<Rule>> rulemap = new HashMap<String, TreeSet<Rule>>();
// 
//     class RuleSetIterator implements Iterator<Rule> {
//         private Iterator<TreeSet<Rule>> mapIterator;
//         private Iterator<Rule> setIterator;
// 
//         public RuleSetIterator() {
//             mapIterator = rulemap.values().iterator();
//             setIterator = null;
//             hasNext();
//         }
// 
//         public boolean hasNext() {
//             while (true) {
//                 if (setIterator != null && setIterator.hasNext())
//                     return true;
//                 if (!mapIterator.hasNext())
//                     return false;
//                 setIterator = mapIterator.next().iterator();
//             }
//         }
// 
//         public Rule next() {
//             if (hasNext()) {
//                 return setIterator.next();
//             }
//             return null;
//         }
// 
//         public void remove() {
//             throw new UnsupportedOperationException();
//         }
//     }
// 
//     public RuleSet() {
//         super();
//     }
// 
//     /**
//      * Return the most specific matching rule for the given request.
//      * 
//      * @param surt
//      * @param captureDate
//      * @param retrievalDate
//      * @param who
//      *            group
//      * @return
//      */
//     public Rule getMatchingRule(String surt, Date captureDate,
//             Date retrievalDate, String who) {
// 
//         NewSurtTokenizer tok = new NewSurtTokenizer(surt);
//         
//         // Best general rule (when accessGroup is blank)
//         Rule ruleGeneral = null;
// 
//         for (String key: tok.getSearchList()) {
//             Iterable<Rule> rules = rulemap.get(key); 
//             if (rules != null) {
//                 for (Rule rule : rules) {
//                     if (rule.matches(surt, captureDate, retrievalDate, who)) {
//                     	// Return this if accessGroup (who) matches exactly
//                     	if ((who != null) && who.equals(rule.getWho())) {
//                     		return rule;
//                     	// otherwise, store the first/best one
//                     	} else if (ruleGeneral == null) {
//                     		ruleGeneral = rule;
//                     	}
//                     }
//                 }
//             }
//         }
//         
//         return ruleGeneral;
//     }
// 
//     public void addAll(Iterable<Rule> rules) {
//         for (Rule rule : rules) {
//             add(rule);
//         }
//     }
// 
//     public void add(Rule rule) {
//         String surt = rule.getSurt();
//         TreeSet<Rule> set = rulemap.get(surt);
//         if (set == null) {
//             set = new TreeSet<Rule>();
//             rulemap.put(surt, set);
//         }
//         set.add(rule);
//     }
// 
//     public Iterator<Rule> iterator() {
//         return new RuleSetIterator();
//     }
// 
// }


import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.archive.accesscontrol.model.RuleSet;
package org.archive.accesscontrol;



/**
 * CachingRuleDao is a wrapper for another RuleDao that implements in-memory
 * caching of the rule trees.
 * 
 * @author aosborne
 * 
 */
public class CachingRuleDao implements RuleDao {
    private static final long serialVersionUID = 1L;
    private static final int PREPARE_THREAD_COUNT = 5;
    protected RuleDao ruleDao;
// Path: access-control/src/main/java/org/archive/accesscontrol/model/RuleSet.java
// public class RuleSet implements Iterable<Rule> {
//     protected HashMap<String, TreeSet<Rule>> rulemap = new HashMap<String, TreeSet<Rule>>();
// 
//     class RuleSetIterator implements Iterator<Rule> {
//         private Iterator<TreeSet<Rule>> mapIterator;
//         private Iterator<Rule> setIterator;
// 
//         public RuleSetIterator() {
//             mapIterator = rulemap.values().iterator();
//             setIterator = null;
//             hasNext();
//         }
// 
//         public boolean hasNext() {
//             while (true) {
//                 if (setIterator != null && setIterator.hasNext())
//                     return true;
//                 if (!mapIterator.hasNext())
//                     return false;
//                 setIterator = mapIterator.next().iterator();
//             }
//         }
// 
//         public Rule next() {
//             if (hasNext()) {
//                 return setIterator.next();
//             }
//             return null;
//         }
// 
//         public void remove() {
//             throw new UnsupportedOperationException();
//         }
//     }
// 
//     public RuleSet() {
//         super();
//     }
// 
//     /**
//      * Return the most specific matching rule for the given request.
//      * 
//      * @param surt
//      * @param captureDate
//      * @param retrievalDate
//      * @param who
//      *            group
//      * @return
//      */
//     public Rule getMatchingRule(String surt, Date captureDate,
//             Date retrievalDate, String who) {
// 
//         NewSurtTokenizer tok = new NewSurtTokenizer(surt);
//         
//         // Best general rule (when accessGroup is blank)
//         Rule ruleGeneral = null;
// 
//         for (String key: tok.getSearchList()) {
//             Iterable<Rule> rules = rulemap.get(key); 
//             if (rules != null) {
//                 for (Rule rule : rules) {
//                     if (rule.matches(surt, captureDate, retrievalDate, who)) {
//                     	// Return this if accessGroup (who) matches exactly
//                     	if ((who != null) && who.equals(rule.getWho())) {
//                     		return rule;
//                     	// otherwise, store the first/best one
//                     	} else if (ruleGeneral == null) {
//                     		ruleGeneral = rule;
//                     	}
//                     }
//                 }
//             }
//         }
//         
//         return ruleGeneral;
//     }
// 
//     public void addAll(Iterable<Rule> rules) {
//         for (Rule rule : rules) {
//             add(rule);
//         }
//     }
// 
//     public void add(Rule rule) {
//         String surt = rule.getSurt();
//         TreeSet<Rule> set = rulemap.get(surt);
//         if (set == null) {
//             set = new TreeSet<Rule>();
//             rulemap.put(surt, set);
//         }
//         set.add(rule);
//     }
// 
//     public Iterator<Rule> iterator() {
//         return new RuleSetIterator();
//     }
// 
// }


// Path: access-control/src/main/java/org/archive/accesscontrol/CachingRuleDao.java
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.archive.accesscontrol.model.RuleSet;

package org.archive.accesscontrol;



/**
 * CachingRuleDao is a wrapper for another RuleDao that implements in-memory
 * caching of the rule trees.
 * 
 * @author aosborne
 * 
 */
public class CachingRuleDao implements RuleDao {
    private static final long serialVersionUID = 1L;
    private static final int PREPARE_THREAD_COUNT = 5;
    protected RuleDao ruleDao;
    protected LruCache<String, RuleSet> cache = new LruCache<String, RuleSet>();