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

pl.net.bluesoft.awf.ext.droolsstep.DroolsUtils Maven / Gradle / Ivy

package pl.net.bluesoft.awf.ext.droolsstep;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.ConcurrentModificationException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.drools.KnowledgeBase;
import org.drools.KnowledgeBaseFactory;
import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.compiler.PackageBuilderConfiguration;
import org.drools.definition.KnowledgePackage;
import org.drools.io.ResourceFactory;
import org.drools.logger.KnowledgeRuntimeLoggerFactory;
import org.drools.rule.builder.dialect.mvel.MVELDialectConfiguration;
import org.drools.runtime.StatefulKnowledgeSession;
import org.drools.runtime.StatelessKnowledgeSession;

import pl.net.bluesoft.util.lang.Formats;
import pl.net.bluesoft.util.lang.Mapcar;

public class DroolsUtils {
	private static final Logger log = Logger.getLogger(DroolsUtils.class.getName());

    public static class DroolsResource {
        private String ruleUrl;
        private InputStream ruleStream;

        public DroolsResource(String ruleUrl) {
            this.ruleUrl = ruleUrl;
        }

        public DroolsResource(String ruleUrl, InputStream ruleStream) {
            this.ruleUrl = ruleUrl;
            this.ruleStream = ruleStream;
        }

        public String getRuleUrl() {
            return ruleUrl;
        }

        public InputStream getRuleStream() {
            return ruleStream;
        }
    }

	public static List processRules(List facts, String... rulesUrl) {
		Long timer = System.currentTimeMillis();
		List res = processRules("result", facts, rulesUrl);
		log.fine("Timing [processing drools rules]. Duration: " + (System.currentTimeMillis() - timer) + "ms");
		return res;
	}

	public static List processRules(String rulesUrl, List objects) {
		return processRules("result", objects, rulesUrl);
	}

	public static List processRulesStafeful(String rulesUrl, List objects) {
		final List res = new ArrayList();

		HashMap map = new HashMap();
		map.put("result", res);
		processCachedRulesAndReturnFacts(objects, map, rulesUrl);
		return res;
	}

    public static List processRules(List facts, Map globals, DroolsResource... droolsResources) {
        Long timer = System.currentTimeMillis();
        StatefulKnowledgeSession knowledgeSession = getCachedSession(droolsResources);
        try {
            log.fine("Timing [getting session]. Duration: " + (System.currentTimeMillis() - timer) + "ms");
            return processRulesWithSession(facts, globals, knowledgeSession);
        }
        catch (RuntimeException e) {
            //clear rule cache
            PACK_CACHE.clear();
            BASE_CACHE.clear();
            throw e;
        }
        finally {
            knowledgeSession.dispose();
            log.fine("Timing [process rules]. Duration: " + (System.currentTimeMillis() - timer) + "ms");
        }
    }

    public static DroolsResource[] transformRuleUrls(String... rulesUrls) {
        DroolsResource[] resources = new DroolsResource[rulesUrls.length];
        for (int i = 0; i < rulesUrls.length; ++i) {
            resources[i] = new DroolsResource(rulesUrls[i]);
        }
        return resources;
    }

    public static List processRules(List facts, Map globals, String... rulesUrls) {
        return processRules(facts, globals, transformRuleUrls(rulesUrls));
    }

	public static List processRulesWithSession(List facts, Map globals, StatefulKnowledgeSession session) {
		int cnt = 0;
		try {
			while (cnt++ < 10) {
				try {
					for (Map.Entry e : globals.entrySet()) {
						session.setGlobal(e.getKey(), e.getValue());
					}
					for (Object o : facts) {
						synchronized (session) {
							session.insert(o);
						}
                    }
					session.fireAllRules();
					return new ArrayList(session.getObjects());
				}
				catch (ConcurrentModificationException e) {
					session.dispose();
				}
			}
			throw new RuntimeException("drools failed to initialize session 10 times in a row!");
		}
		finally {
			session.dispose();
		}
	}


	private static List processRules(final String resultName, List objects, String... rulesUrls) {
		final List result = new ArrayList();
		HashMap map = new HashMap();
		map.put(resultName, result);
		processRules(objects, map, rulesUrls);
		return result;
	}

	public static Collection processCachedRulesAndReturnFacts(List objects, Map globals, String rulesUrl) {
		StatefulKnowledgeSession session = getCachedSession(rulesUrl);
		try {
			if (session != null) {
                for (Map.Entry e : globals.entrySet()) {
                    session.setGlobal(e.getKey(), e.getValue());
                }
                for (Object o : objects)
                    synchronized (session) {
                        session.insert(o);
                    }
                session.fireAllRules();
                return session.getObjects();
			} else {
				return null;
			}
		}
		finally {
			if (session != null) session.dispose();
		}
	}

	private static final Map BASE_CACHE = new HashMap();
	private static final Map> PACK_CACHE = new HashMap();
	private static final Map VALIDITY_CACHE = new HashMap();
	private static final Map PACK_VALIDITY_CACHE = new HashMap();
	private static final long VALIDITY_TIME = 15 * 60 * 1000; 
	private static final long PACK_VALIDITY_TIME = 60 * 60 * 1000; //1 godzina

    public static synchronized StatefulKnowledgeSession getCachedSession(DroolsResource... droolsResources) {
        KnowledgeBase kb = getCachedKnowledgeBase(droolsResources);
        long t = System.currentTimeMillis();
        try {
            return initSession(kb);
        }
        finally {
            log.fine("initSession took: " + (System.currentTimeMillis() - t));
        }
    }

	public static synchronized StatefulKnowledgeSession getCachedSession(String... rulesUrls) {
        return getCachedSession(transformRuleUrls(rulesUrls));
	}

    private static KnowledgeBase getCachedKnowledgeBase(DroolsResource... droolsResources) {
        List resources = Arrays.asList(droolsResources);
        List rules = new Mapcar(resources) {
            @Override
            public String lambda(DroolsResource x) {
                return x.getRuleUrl();
            }
        }.go();
        Collections.sort(rules);
        String key = Formats.join(rules, ";");

        KnowledgeBase kb;
        synchronized (BASE_CACHE) {
            //nowy sposób, bazujący na cache knowledge package a nie knowledge base
            Collection knowledgePackages = PACK_CACHE.get(key);

            kb = BASE_CACHE.get(key);
            Long validTo = VALIDITY_CACHE.get(key);
            if (validTo != null && validTo < System.currentTimeMillis()) {
                log.warning("clearing cache for " + key);
                kb = null;
            }

            validTo = PACK_VALIDITY_CACHE.get(key);
            if (validTo != null && validTo < System.currentTimeMillis()) {
                log.warning("clearing packages cache for " + key);
                kb = null;
                knowledgePackages = null;
            }

            if (knowledgePackages == null) {
                knowledgePackages = getPackages(droolsResources);
                PACK_CACHE.put(key, knowledgePackages);
                PACK_VALIDITY_CACHE.put(key, System.currentTimeMillis() + PACK_VALIDITY_TIME);
                log.warning("registering drools packages for " + key);
            }
            else {
                log.fine("found cached drools packages for " + key);
            }
            if (kb == null) {
                kb = getKbase(knowledgePackages);
                BASE_CACHE.put(key, kb);
                VALIDITY_CACHE.put(key, System.currentTimeMillis() + VALIDITY_TIME);
                log.warning("registering KnowledgeBase for " + key);
            }
            else {
                log.fine("found cached KnowledgeBase for " + key);
            }
        }
        return kb;
    }

	private static KnowledgeBase getCachedKnowledgeBase(String... rulesUrls) {
        return getCachedKnowledgeBase(transformRuleUrls(rulesUrls));
	}

	public static synchronized StatelessKnowledgeSession getCachedStatelessSession(String... rulesUrls) {
		KnowledgeBase kb = getCachedKnowledgeBase(rulesUrls);
		long t = System.currentTimeMillis();
		try {
			return initStatelessSession(kb);
		}
		finally {
			log.fine("initStatelessSession took: " + (System.currentTimeMillis() - t));
		}
	}

	public synchronized static StatefulKnowledgeSession getSession(String... rulesUrls) {
		KnowledgeBase kbase = getKbase(rulesUrls);
		return initSession(kbase);
	}

	private static StatefulKnowledgeSession initSession(KnowledgeBase kbase) {
		StatefulKnowledgeSession session = null;
		if (kbase != null) {
			synchronized (kbase) {
				session = kbase.newStatefulKnowledgeSession();
			}
		}
		return session;
	}

	private static StatelessKnowledgeSession initStatelessSession(KnowledgeBase kbase) {
		StatelessKnowledgeSession session = null;
		if (kbase != null) {
			synchronized (kbase) {
				session = kbase.newStatelessKnowledgeSession();
				if (log.isLoggable(Level.FINEST))
					KnowledgeRuntimeLoggerFactory.newConsoleLogger(session);
			}
		}
		return session;
	}

	private static KnowledgeBase getKbase(String... rulesUrls) {
		Collection knowledgePackages = getPackages(rulesUrls);
		return getKbase(knowledgePackages);
	}

	private static KnowledgeBase getKbase(Collection knowledgePackages) {
		KnowledgeBase kbase = null;
		if (!knowledgePackages.isEmpty()) {
			kbase = KnowledgeBaseFactory.newKnowledgeBase();
			kbase.addKnowledgePackages(knowledgePackages);
		}
		return kbase;
	}

    private static Collection getPackages(DroolsResource... droolsResources) {
        MVELDialectConfiguration conf = (MVELDialectConfiguration) new PackageBuilderConfiguration().getDialectConfiguration("mvel");
        conf.setStrict(false);
        conf.getPackageBuilderConfiguration().setDefaultDialect("mvel");

        KnowledgeBuilder builder = KnowledgeBuilderFactory.newKnowledgeBuilder(conf.getPackageBuilderConfiguration());
        for (DroolsResource res : droolsResources) {
            builder.add(res.getRuleStream() != null ? ResourceFactory.newInputStreamResource(res.getRuleStream())
                    : ResourceFactory.newUrlResource(res.getRuleUrl()), ResourceType.DRL);
        }
        if (builder.hasErrors()) throw new RuntimeException(builder.getErrors().toString());
        Collection knowledgePackages = builder.getKnowledgePackages();
        return knowledgePackages;
    }

	private static Collection getPackages(String... rulesUrls) {
        return getPackages(transformRuleUrls(rulesUrls));
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy