class WARCLimitEnforcer extends Processor {

    private final static Logger log =
            Logger.getLogger(WARCLimitEnforcer.class.getName());

    protected Map<String, Map<String, Long>> limits = new HashMap<String, Map<String, Long>>();
    /**
     * Should match structure of {@link BaseWARCWriterProcessor#getStats()}
     * @param limits
     */
    public void setLimits(Map<String, Map<String, Long>> limits) {
        this.limits = limits;
    }
    public Map<String, Map<String, Long>> getLimits() {
        return limits;
    }

    protected BaseWARCWriterProcessor warcWriter;
    @Autowired
    public void setWarcWriter(BaseWARCWriterProcessor warcWriter) {
        this.warcWriter = warcWriter;
    }
    public BaseWARCWriterProcessor getWarcWriter() {
        return warcWriter;
    }

    {
        setWarcWriters(new ArrayList<BaseWARCWriterProcessor>());
    }
    @SuppressWarnings("unchecked")
    public List<BaseWARCWriterProcessor> getWarcWriters() {
        return (List<BaseWARCWriterProcessor>) kp.get("warcWriters");
    }
    public void setWarcWriters(List<BaseWARCWriterProcessor> warcWriters) {
        kp.put("warcWriters", warcWriters);
    }

    protected CrawlController controller;
    public CrawlController getCrawlController() {
        return this.controller;
    }
    @Autowired
    public void setCrawlController(CrawlController controller) {
        this.controller = controller;
    }

    @Override
    protected boolean shouldProcess(CrawlURI uri) {
        return true;
    }

    @Override
    protected void innerProcess(CrawlURI uri) throws InterruptedException {<FILL_FUNCTION_BODY>}

}

        for (String j: limits.keySet()) {
            for (String k: limits.get(j).keySet()) {
                Long limit = limits.get(j).get(k);

                AtomicLong value = null;
                if(getWarcWriters() !=null && getWarcWriters().size()>0) {
                    value = new AtomicLong(0);
                    for (BaseWARCWriterProcessor w: getWarcWriters()) {
                        Map<String, AtomicLong> valueBucket = w.getStats().get(j);
                        if(valueBucket != null) {
                            value.set(value.addAndGet(valueBucket.get(k).get()));
                        }
                    }
                }
                else {
                    Map<String, AtomicLong> valueBucket = warcWriter.getStats().get(j);
                    if(valueBucket != null) {
                        value = valueBucket.get(k);
                    }
                }
                if (value != null
                        && value.get() >= limit) {
                    log.info("stopping crawl because warcwriter stats['" + j + "']['" + k + "']=" + value.get() + " exceeds limit " + limit);
                    controller.requestCrawlStop(CrawlStatus.FINISHED_WRITE_LIMIT);
                }
            }
        }
    
<methods>public non-sealed void <init>() ,public void doCheckpoint(org.archive.checkpointing.Checkpoint) throws java.io.IOException,public void finishCheckpoint(org.archive.checkpointing.Checkpoint) ,public static java.lang.String flattenVia(org.archive.modules.CrawlURI) ,public java.lang.String getBeanName() ,public boolean getEnabled() ,public org.archive.spring.KeyedProperties getKeyedProperties() ,public static long getRecordedSize(org.archive.modules.CrawlURI) ,public org.archive.modules.deciderules.DecideRule getShouldProcessRule() ,public long getURICount() ,public static boolean hasHttpAuthenticationCredential(org.archive.modules.CrawlURI) ,public boolean isRunning() ,public static boolean isSuccess(org.archive.modules.CrawlURI) ,public org.archive.modules.ProcessResult process(org.archive.modules.CrawlURI) throws java.lang.InterruptedException,public java.lang.String report() ,public void setBeanName(java.lang.String) ,public void setEnabled(boolean) ,public void setRecoveryCheckpoint(org.archive.checkpointing.Checkpoint) ,public void setShouldProcessRule(org.archive.modules.deciderules.DecideRule) ,public void start() ,public void startCheckpoint(org.archive.checkpointing.Checkpoint) ,public void stop() <variables>protected java.lang.String beanName,protected boolean isRunning,protected org.archive.spring.KeyedProperties kp,protected org.archive.checkpointing.Checkpoint recoveryCheckpoint,protected java.util.concurrent.atomic.AtomicLong uriCount