View Javadoc
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   * Created by pvsubrah on 3/23/15.
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      This method should be called first to load the rules repository.
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          // seed a builder with our rules file from classpath
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             // create a knowledgeBase from our builder packages
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             // load a new knowledgeBase with our rules
156             // initialize a session for usage
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 }