View Javadoc
1   package org.kuali.ole.deliver.drools;
2   
3   import org.apache.commons.io.FileUtils;
4   import org.apache.commons.io.FilenameUtils;
5   import org.apache.lucene.util.CollectionUtil;
6   import org.drools.core.definitions.rule.impl.RuleImpl;
7   import org.kie.api.KieServices;
8   import org.kie.api.builder.KieBuilder;
9   import org.kie.api.builder.KieFileSystem;
10  import org.kie.api.builder.Message;
11  import org.kie.api.builder.Results;
12  import org.kie.api.definition.KiePackage;
13  import org.kie.api.definition.rule.Rule;
14  import org.kie.api.event.rule.DebugAgendaEventListener;
15  import org.kie.api.runtime.KieContainer;
16  import org.kie.api.runtime.KieSession;
17  import org.kie.internal.io.ResourceFactory;
18  import org.kuali.ole.OLEConstants;
19  import org.kuali.ole.deliver.service.ParameterValueResolver;
20  import org.kuali.ole.sys.context.SpringContext;
21  import org.kuali.rice.core.api.config.property.ConfigContext;
22  import org.kuali.rice.coreservice.api.parameter.Parameter;
23  import org.kuali.rice.coreservice.api.parameter.ParameterType;
24  import org.kuali.rice.coreservice.framework.parameter.ParameterService;
25  import org.slf4j.Logger;
26  import org.slf4j.LoggerFactory;
27  
28  import java.io.File;
29  import java.util.*;
30  
31  /**
32   * Created by pvsubrah on 3/23/15.
33   */
34  public class DroolsKieEngine {
35      private Logger LOG = LoggerFactory.getLogger(DroolsKieEngine.class);
36      private KieContainer kieContainer;
37      private ParameterService parameterService;
38  
39      private static Boolean forceLoadPolicies = true;
40      private static final String LOAD_POLICIES_IND = "LOAD_CIRC_POLICIES_IND";
41  
42      private static DroolsKieEngine droolsEngine = new DroolsKieEngine();
43  
44      protected DroolsKieEngine() {
45  
46      }
47  
48      public static DroolsKieEngine getInstance() {
49          return droolsEngine;
50      }
51  
52      /*
53      This method should be called first to load the rules repository.
54       */
55      public void initKnowledgeBase() {
56          long startTime = System.currentTimeMillis();
57          populateKnowledgeBase();
58          long endTime = System.currentTimeMillis();
59          System.out.println("Time taken to populate drools knowledgebase: " + (endTime - startTime) + " ms");
60      }
61  
62      private void populateKnowledgeBase() {
63          Boolean parameterValueAsBoolean = getParameterAsBoolean();
64          if (forceLoadPolicies || parameterValueAsBoolean) {
65              readRules();
66              updateParameter();
67          }
68      }
69  
70      private Boolean getParameterAsBoolean() {
71          return ParameterValueResolver.getInstance().getParameterAsBoolean(OLEConstants
72                          .APPL_ID, OLEConstants
73                          .DLVR_NMSPC,
74                  OLEConstants
75                          .DLVR_CMPNT, LOAD_POLICIES_IND);
76      }
77  
78      private void updateParameter() {
79          Parameter existingParameter = getParameterService().getParameter(OLEConstants.DLVR_NMSPC, OLEConstants
80                  .DLVR_CMPNT, LOAD_POLICIES_IND);
81          if (existingParameter != null) {
82              Parameter.Builder updatedParameter = Parameter.Builder.create(existingParameter);
83              updatedParameter.setValue("N");
84              forceLoadPolicies = false;
85              getParameterService().updateParameter(updatedParameter.build());
86          } else {
87              Parameter.Builder newParameter = Parameter.Builder.create(OLEConstants.APPL_ID, OLEConstants.DLVR_NMSPC, OLEConstants.DLVR_CMPNT, LOAD_POLICIES_IND, ParameterType.Builder.create("CONFG"));
88              newParameter.setDescription("Set to 'Y' to have the application ingest the default circulation policies " +
89                      "upon next policy evaluation.");
90              newParameter.setValue("Y");
91              getParameterService().createParameter(newParameter.build());
92              forceLoadPolicies = false;
93          }
94      }
95  
96      private void readRules() {
97  
98          File rulesDirectory = FileUtils.getFile(getRulesDirectory());
99          if (null != rulesDirectory && rulesDirectory.isDirectory() && FileUtils.sizeOfDirectory(rulesDirectory) > 0) {
100             File[] files = rulesDirectory.listFiles();
101 
102             KieServices kieServices = KieServices.Factory.get();
103             KieFileSystem kfs = kieServices.newKieFileSystem();
104 
105             loadRules(kfs, files);
106 
107             KieBuilder kieBuilder = kieServices.newKieBuilder(kfs).buildAll();
108             Results results = kieBuilder.getResults();
109 
110             if (results.hasMessages(Message.Level.ERROR)) {
111                //TODO: Populate the DroolResponse object with the appropriate message.
112             }
113 
114             long startTime = System.currentTimeMillis();
115             kieContainer = kieServices.newKieContainer(kieServices.getRepository().getDefaultReleaseId());
116             long endTime = System.currentTimeMillis();
117             System.out.println("Time taken to initiallize KieContainer: " + (endTime - startTime) + "ms");
118 
119 
120         } else {
121             LOG.error("Could not load Circulation Rules as directory doest not exist or is unreadable.");
122         }
123     }
124 
125     private void loadRules(KieFileSystem kfs, File[] files) {
126         for (int i = 0; i < files.length; i++) {
127             File file = files[i];
128             if (!file.isDirectory()) {
129                 if (FilenameUtils.getExtension(file.getName()).equals("drl")) {
130                     kfs.write(ResourceFactory.newFileResource(file));
131                 }
132             } else {
133                 File[] subDirFiles = file.listFiles();
134                 loadRules(kfs, subDirFiles);
135             }
136         }
137     }
138 
139     public synchronized void disposeSession(KieSession kieSession) {
140         kieSession.dispose();
141     }
142 
143     public String getRulesDirectory() {
144         String rulesDirectory = ConfigContext.getCurrentContextConfig().getProperty("rules.directory");
145         return rulesDirectory;
146     }
147 
148     public synchronized KieSession getSession() {
149         populateKnowledgeBase();
150         long startTime1 = System.currentTimeMillis();
151         KieSession kieSession = kieContainer.newKieSession();
152         kieSession.addEventListener(new CustomAgendaEventListener());
153         kieSession.addEventListener(new DebugAgendaEventListener());
154         long endTime1 = System.currentTimeMillis();
155 
156         System.out.println("Time taken to initialize KieSession: " + (endTime1 - startTime1) + "ms");
157 
158         return kieSession;
159 
160     }
161 
162     public ParameterService getParameterService() {
163         if (null == parameterService) {
164             parameterService = SpringContext.getBean(ParameterService.class);
165         }
166         return parameterService;
167     }
168 
169     public void setParameterService(ParameterService parameterService) {
170         this.parameterService = parameterService;
171     }
172 
173 
174     public List<String> getRulesByAgendaGroup(List<String>agendaGroups){
175         List<String> ruleNames = new ArrayList<>();
176 
177         for (Iterator iterator = kieContainer.getKieBase().getKiePackages().iterator(); iterator.hasNext(); ) {
178             KiePackage kiePackage = (KiePackage) iterator.next();
179             Collection<Rule> rules = kiePackage.getRules();
180             for (Iterator<Rule> ruleIterator = rules.iterator(); ruleIterator.hasNext(); ) {
181                 Rule rule = ruleIterator.next();
182                 if(agendaGroups.contains(((RuleImpl)rule).getAgendaGroup())){
183                     ruleNames.add(rule.getName());
184                 }
185             }
186         }
187         Collections.sort(ruleNames);
188         return ruleNames;
189     }
190 
191 
192     public List<String> getAllLoadedRules(){
193         List<String> ruleNames = new ArrayList<>();
194 
195         for (Iterator iterator = kieContainer.getKieBase().getKiePackages().iterator(); iterator.hasNext(); ) {
196             KiePackage kiePackage = (KiePackage) iterator.next();
197             Collection<Rule> rules = kiePackage.getRules();
198             for (Iterator<Rule> ruleIterator = rules.iterator(); ruleIterator.hasNext(); ) {
199                 Rule rule = ruleIterator.next();
200                     ruleNames.add(rule.getName());
201             }
202         }
203 
204         return ruleNames;
205     }
206 }