1 package org.kuali.ole.deliver.drools;
2
3 import org.apache.camel.util.StopWatch;
4 import org.apache.commons.io.FileUtils;
5 import org.apache.commons.io.FilenameUtils;
6 import org.kie.api.event.rule.DebugAgendaEventListener;
7 import org.kie.api.io.ResourceType;
8 import org.kie.internal.KnowledgeBase;
9 import org.kie.internal.KnowledgeBaseFactory;
10 import org.kie.internal.builder.KnowledgeBuilder;
11 import org.kie.internal.builder.KnowledgeBuilderFactory;
12 import org.kie.internal.io.ResourceFactory;
13 import org.kie.internal.runtime.StatefulKnowledgeSession;
14 import org.kuali.ole.OLEConstants;
15 import org.kuali.ole.deliver.service.ParameterValueResolver;
16 import org.kuali.ole.sys.context.SpringContext;
17 import org.kuali.rice.core.api.config.property.ConfigContext;
18 import org.kuali.rice.coreservice.api.parameter.Parameter;
19 import org.kuali.rice.coreservice.api.parameter.ParameterType;
20 import org.kuali.rice.coreservice.framework.parameter.ParameterService;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23
24 import java.io.File;
25 import java.io.FileInputStream;
26 import java.io.FileNotFoundException;
27
28
29
30
31 public class DroolsEngine {
32 private Logger LOG = LoggerFactory.getLogger(DroolsEngine.class);
33 private KnowledgeBase knowledgeBase;
34 private ParameterService parameterService;
35
36 private static Boolean forceLoadPolicies = true;
37 private static final String LOAD_POLICIES_IND = "LOAD_CIRC_POLICIES_IND";
38
39 private static DroolsEngine droolsEngine = new DroolsEngine();
40
41 protected DroolsEngine() {
42
43 }
44
45 public static DroolsEngine getInstance() {
46 return droolsEngine;
47 }
48
49
50
51
52 public void initKnowledgeBase() {
53 long startTime = System.currentTimeMillis();
54 knowledgeBase = populateKnowledgeBase();
55 long endTime = System.currentTimeMillis();
56 System.out.println("Time taken to populate drools knowledgebase: " + (endTime - startTime) + " ms");
57 }
58
59 private KnowledgeBase populateKnowledgeBase() {
60 Boolean parameterValueAsBoolean = getParameterAsBoolean();
61 if (forceLoadPolicies || parameterValueAsBoolean) {
62 readRules();
63 updateParameter();
64 }
65 return knowledgeBase;
66 }
67
68 private Boolean getParameterAsBoolean() {
69 return ParameterValueResolver.getInstance().getParameterAsBoolean(OLEConstants
70 .APPL_ID, OLEConstants
71 .DLVR_NMSPC,
72 OLEConstants
73 .DLVR_CMPNT, LOAD_POLICIES_IND);
74 }
75
76 private void updateParameter() {
77 Parameter existingParameter = getParameterService().getParameter(OLEConstants.DLVR_NMSPC, OLEConstants
78 .DLVR_CMPNT, LOAD_POLICIES_IND);
79 if (existingParameter != null) {
80 Parameter.Builder updatedParameter = Parameter.Builder.create(existingParameter);
81 updatedParameter.setValue("N");
82 forceLoadPolicies = false;
83 getParameterService().updateParameter(updatedParameter.build());
84 } else {
85 Parameter.Builder newParameter = Parameter.Builder.create(OLEConstants.APPL_ID, OLEConstants.DLVR_NMSPC, OLEConstants.DLVR_CMPNT, LOAD_POLICIES_IND, ParameterType.Builder.create("CONFG"));
86 newParameter.setDescription("Set to 'Y' to have the application ingest the default circulation policies " +
87 "upon next policy evalvuation.");
88 newParameter.setValue("Y");
89 getParameterService().createParameter(newParameter.build());
90 forceLoadPolicies = false;
91 }
92 }
93
94 private void readRules() {
95
96 KnowledgeBuilder builder = KnowledgeBuilderFactory.newKnowledgeBuilder();
97
98 File rulesDirectory = FileUtils.getFile(getRulesDirectory());
99 if (null != rulesDirectory && rulesDirectory.isDirectory() && FileUtils.sizeOfDirectory(rulesDirectory) > 0) {
100 File[] files = rulesDirectory.listFiles();
101 loadRules(builder, files);
102
103 if (builder.hasErrors()) {
104 LOG.error("Could not load Circulation Rules as directory doest not exist or is unreadable.");
105 LOG.error(builder.getErrors().toString());
106 }
107
108
109 knowledgeBase = KnowledgeBaseFactory.newKnowledgeBase();
110 knowledgeBase.addKnowledgePackages(builder.getKnowledgePackages());
111 } else {
112 LOG.error("Could not load Circulation Rules as directory doest not exist or is unreadable.");
113 }
114 }
115
116 private void loadRules(KnowledgeBuilder builder, File[] files) {
117 for (int i = 0; i < files.length; i++) {
118 File file = files[i];
119 if (!file.isDirectory()) {
120 if (FilenameUtils.getExtension(file.getName()).equals("drl")) {
121 FileInputStream fis = null;
122 try {
123 fis = new FileInputStream(file);
124 builder.add(ResourceFactory.newInputStreamResource(fis), ResourceType.DRL);
125 } catch (FileNotFoundException e) {
126 e.printStackTrace();
127 }
128 }
129 } else {
130 File[] subDirFiles = file.listFiles();
131 loadRules(builder, subDirFiles);
132 }
133 }
134 }
135
136 public synchronized void disposePreviousSession(StatefulKnowledgeSession statefulKnowledgeSession) {
137 statefulKnowledgeSession.dispose();
138 }
139
140 public String getRulesDirectory() {
141 String rulesDirectory = ConfigContext.getCurrentContextConfig().getProperty("rules.directory");
142 return rulesDirectory;
143 }
144
145 public synchronized StatefulKnowledgeSession getSession() {
146 StopWatch stopWatch = new StopWatch();
147 stopWatch.restart();
148 StatefulKnowledgeSession statefulKnowledgeSession = null;
149
150 try {
151 Boolean parameterValueAsBoolean = getParameterAsBoolean();
152 if (null != parameterValueAsBoolean && parameterValueAsBoolean) {
153 populateKnowledgeBase();
154 }
155
156
157 statefulKnowledgeSession = knowledgeBase.newStatefulKnowledgeSession();
158 statefulKnowledgeSession.addEventListener(new CustomAgendaEventListener());
159 statefulKnowledgeSession.addEventListener(new DebugAgendaEventListener());
160
161 } catch (Exception e) {
162 e.printStackTrace();
163 }
164
165 stopWatch.stop();
166 System.out.println("Time taken to initialize Drools session: " + stopWatch.taken() + " milli seconds");
167 return statefulKnowledgeSession;
168 }
169
170 public ParameterService getParameterService() {
171 if (null == parameterService) {
172 parameterService = SpringContext.getBean(ParameterService.class);
173 }
174 return parameterService;
175 }
176
177 public void setParameterService(ParameterService parameterService) {
178 this.parameterService = parameterService;
179 }
180 }