/** * Copyright 2010 JBoss Inc * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.drools.guvnor.importgenerator; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.text.DecimalFormat; import java.text.MessageFormat; import java.text.NumberFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.drools.compiler.DroolsParserException; import org.jboss.drools.guvnor.importgenerator.CmdArgsParser.Parameters; import org.jboss.drools.guvnor.importgenerator.utils.FileIO; import org.jboss.drools.guvnor.importgenerator.utils.Logger; import org.joda.time.DateTime; import org.joda.time.Minutes; import org.joda.time.Seconds; /** * a BRMS import file generator for drl and xml decision table files * * @author <a href="mailto:mallen@redhat.com">Mat Allen</a> */ public class ImportFileGenerator implements Constants{ private Logger logger=null; private CmdArgsParser options=null; private String BASE_DIR=System.getProperty("user.dir"); public enum PackageObjectType{ PACKAGE, PACKAGE_SNAPSHOT } public enum RuleObjectType{ RULE, SNAPSHOT_RULE } /** * The main action method * @param packages * @return * @throws Exception */ public String generateImportFile(Map<String, PackageFile> packages) throws Exception { // go thru each replacer definition creating drl template replacements //TODO: what is the org.drools.io.RuleSetReader ??? is this what Guvnor uses this to read the .drl file parts? String draftStateReferenceUUID=GeneratedData.generateUUID(); String categoryReferenceUUID=GeneratedData.generateUUID(); //reporting only int cok=0, cerror=0, derror=0, terror=0, total=0; StringBuffer packageContents = new StringBuffer(); StringBuffer snapshotContents = new StringBuffer(); double i=0,pct=0; for (Iterator<String> it = packages.keySet().iterator(); it.hasNext();) { double newPct=(int)(++i/(double)packages.size()*100); pct=newPct; String packageName = (String) it.next(); logger.debug(new DecimalFormat("##0").format(pct)+"% - "+packageName); PackageFile packageFile=packages.get(packageName); Map<String, Object> context=new HashMap<String, Object>(); context.put("file", packageFile.getFile()); context.put("draftStateReferenceUUID", draftStateReferenceUUID); context.put("categoryReferenceUUID", categoryReferenceUUID); context.put("packageFile", packageFile); //extract the rule contents StringBuffer ruleContents = new StringBuffer(); StringBuffer snapshotRuleContents = new StringBuffer(); Map<String, Rule> rules=packageFile.getRules(); packageFile.buildPackage(); for (Iterator<String> it2 = rules.keySet().iterator(); it2.hasNext();) { String ruleName=(String)it2.next(); Rule rule=(Rule)rules.get(ruleName); context.put("rule", rule); //inject the rule values into the rule template ruleContents.append(MessageFormat.format(readTemplate(MessageFormat.format(TEMPLATES_RULE, packageFile.getFormat())), getRuleObjects(context/*, RuleObjectType.RULE*/))); //inject the snapshot rule values in the the snapshot rule template snapshotRuleContents.append(MessageFormat.format(readTemplate(MessageFormat.format(TEMPLATES_SNAPSHOT_RULE, packageFile.getFormat())), getRuleObjects(context/*, RuleObjectType.SNAPSHOT_RULE*/))); } //inject the rule(s) into the package into the package contents String packageTemplate = readTemplate(TEMPLATES_PACKAGE);// FileIO.readAll(new FileInputStream(new File(TEMPLATES_FOLDER, TEMPLATES_PACKAGE))); packageContents.append(MessageFormat.format(packageTemplate, getPackageObjects(context, ruleContents, PackageObjectType.PACKAGE))); //inject the snapshot values into the snapshot contents if (options.getOption(Parameters.OPTIONS_SNAPSHOT_NAME)!=null){ snapshotContents.append(MessageFormat.format(readTemplate(TEMPLATES_SNAPSHOT), getPackageObjects(context, snapshotRuleContents, PackageObjectType.PACKAGE_SNAPSHOT))); } //display status of each packageFile total++; if (packageFile.hasErrors()) { terror++; if (packageFile.hasCompilationErrors()){ cerror++; logger.debugln(" - [COMPILATION/DEPENDENCY ERRORS]"); if ("true".equals(options.getOption(Parameters.OPTIONS_VERY_VERBOSE))){ logger.debugln(packageFile.getCompilationErrors().trim()); logger.debugln(packageFile.getDependencyErrors().trim()); } } else if (packageFile.hasDependencyErrors()) { derror++; logger.debugln(" - [DEPENDENCY ERRORS]"); if ("true".equals(options.getOption(Parameters.OPTIONS_VERY_VERBOSE))){ logger.debugln(packageFile.getDependencyErrors().trim()); } } } else{ cok++; //increment the "total rules compiled successfully" logger.debugln(" - [OK]"); } } //replace the placemarkers with the package data String parentContents = MessageFormat.format(readTemplate(TEMPLATES_PARENT), new Object[]{ packageContents ,categoryReferenceUUID ,draftStateReferenceUUID ,GeneratedData.getTimestamp() ,getSnapshotContents(snapshotContents) }); //write a summary report logger.debugln("=========================="); logger.debugln("=== PACKAGE SUMMARY ==="); logger.debugln("=========================="); logger.debugln(" Rules compiled OK: "+ NumberFormat.getInstance().format(cok)); logger.debugln(" Errors: "+ NumberFormat.getInstance().format(terror)); //comp or dep errors can no longer be detected accurately since many drl file can be in a single package // logger.logln(" Compilation errors: "+ NumberFormat.getInstance().format(cerror)); // logger.logln(" Dependency errors: "+ NumberFormat.getInstance().format(derror)); logger.debugln(" ____"); logger.debugln(" Total: "+ NumberFormat.getInstance().format(total)); logger.debugln("=========================="); return parentContents; } /** * returns a drools-5.0 formatted xml file for use with a drools 5.0 knowledge agent * @param packages * @return * @throws Exception */ public String generateKnowledgeAgentInitFile(Map<String, PackageFile> packages) throws Exception { StringBuffer kagentInitContents = new StringBuffer(); String kagentChildTemplate = readTemplate(TEMPLATES_KAGENT_CHILD_INIT); StringBuffer kagentChildContents=new StringBuffer(); for (Iterator<String> it = packages.keySet().iterator(); it.hasNext();) { String packageName = (String) it.next(); PackageFile packageFile=packages.get(packageName); kagentChildContents.append(MessageFormat.format(kagentChildTemplate, new Object[]{options.getOption(Parameters.OPTIONS_KAGENT_CHANGE_SET_SERVER), packageFile.getName()+"/"+options.getOption(Parameters.OPTIONS_SNAPSHOT_NAME), "PKG"})); } String kagentParentTemplate = readTemplate(TEMPLATES_KAGENT_PARENT_INIT); kagentInitContents.append(MessageFormat.format(kagentParentTemplate, new Object[]{kagentChildContents.toString()})); return kagentInitContents.toString(); } private StringBuffer getSnapshotContents(StringBuffer snapshotContents){ if (options.getOption(Parameters.OPTIONS_SNAPSHOT_NAME)!=null){ return snapshotContents; } return new StringBuffer(""); } private String readTemplate(String templateConst) throws FileNotFoundException{ return FileIO.readAll(new FileInputStream(new File(new File(BASE_DIR, TEMPLATES_FOLDER), templateConst))); } private Object[] getPackageObjects(Map<String, Object> context, StringBuffer ruleContents, PackageObjectType type) throws UnsupportedEncodingException, DroolsParserException, IOException{ List<String> objects=new LinkedList<String>(); PackageFile packageFile=(PackageFile)context.get("packageFile"); switch (type){ case PACKAGE: objects.add(packageFile.getName()); objects.add(getCreator()); objects.add(packageFile.getImports()); objects.add(ruleContents.toString()); objects.add(GeneratedData.generateUUID()); objects.add(GeneratedData.generateUUID()); objects.add(GeneratedData.generateUUID()); objects.add((String)context.get("draftStateReferenceUUID")); objects.add(GeneratedData.getTimestamp()); break; case PACKAGE_SNAPSHOT: objects.add(packageFile.getName()); objects.add(packageFile.getName().substring(packageFile.getName().lastIndexOf(".")+1));// //aka the title objects.add(options.getOption(Parameters.OPTIONS_SNAPSHOT_NAME)); objects.add(getCreator()); //3 objects.add(packageFile.getImports()); //4 objects.add(ruleContents.toString()); //5 objects.add((String)context.get("draftStateReferenceUUID")); objects.add(GeneratedData.getTimestamp()); //7 //objects.add(FileIO.toBase64(DroolsHelper.compileRuletoPKG(packageFile))); //8 objects.add(FileIO.toBase64(packageFile.toByteArray())); objects.add(GeneratedData.generateUUID()); //snapshot uuid objects.add(GeneratedData.generateUUID()); //snapshot base+predecessor uuid objects.add(GeneratedData.generateUUID()); //assets uuid objects.add(GeneratedData.generateUUID()); //assets base+predecessor uuid objects.add(GeneratedData.generateUUID()); //drools uuid objects.add(GeneratedData.generateUUID()); //drools base+predecessor uuid break; } return objects.toArray(new Object[objects.size()]); } private Object[] getRuleObjects(Map<String, Object> context/*, RuleObjectType type*/){ List<String> objects=new LinkedList<String>(); PackageFile packageFile=(PackageFile)context.get("packageFile"); Rule rule=(Rule)context.get("rule"); objects.add(rule.getRuleName()); objects.add(packageFile.getName()); objects.add(rule.getContent()); objects.add(GeneratedData.generateUUID()); //rule uuid objects.add((String)context.get("draftStateReferenceUUID")); objects.add((String)context.get("categoryReferenceUUID")); objects.add(getCreator()); objects.add(GeneratedData.getTimestamp()); objects.add(packageFile.getFormat()); objects.add(GeneratedData.generateUUID()); //base version + predecessor (currently only used in snapshot) if (packageFile.getFormat().equals("xls")){ objects.add(((File)context.get("file")).getName()); } return objects.toArray(new Object[]{}); } /** * get command line arguments * @return */ private String getCreator(){ if (options.getOption(Parameters.OPTIONS_CREATOR)!=null) return options.getOption(Parameters.OPTIONS_CREATOR); return DEFAULT_CREATOR; } public void run(CmdArgsParser options) throws Exception{ SimpleDateFormat fmt=new SimpleDateFormat("yyyy/MM/dd hh:mm:ss"); Date startd=new Date(); DateTime start=new DateTime(startd); this.options=options; BASE_DIR=options.getOption(Parameters.OPTIONS_BASE_DIR); logger=Logger.getLogger(ImportFileGenerator.class, options); logger.debugln("Running BRMS Import Generator (started "+ fmt.format(startd) +"):"); logger.debugln("Scanning directories..."); Map<String, PackageFile> details=PackageFile.buildPackages(options); logger.debugln("Generating 'Guvnor import data'..."); String guvnorImport=generateImportFile(details); File guvnorImportFile=getFile(options.getOption(Parameters.OPTIONS_OUTPUT_FILE)); logger.debugln("Writing 'Guvnor import data to disk' ("+ guvnorImportFile.getAbsolutePath() +")"); FileIO.write(guvnorImport, guvnorImportFile); if (options.getOption(Parameters.OPTIONS_KAGENT_CHANGE_SET_FILE)!=null){ logger.debugln("Generating 'Knowledge agent changeset' data..."); String kagentChangeSet=generateKnowledgeAgentInitFile(details); File kagentChangeSetFile=getFile(options.getOption(Parameters.OPTIONS_KAGENT_CHANGE_SET_FILE)); logger.debugln("Writing 'Knowledge agent changeset' to disk ("+ kagentChangeSetFile.getAbsolutePath() +")"); FileIO.write(kagentChangeSet, kagentChangeSetFile); } DateTime end=new DateTime(System.currentTimeMillis()); int m=Minutes.minutesBetween(start, end).getMinutes(); int s=Seconds.secondsBetween(start, end).getSeconds()-(m*60); logger.debugln("Finished in ("+m+"m"+s+"s)"); } private File getFile(String fileLoc){ if (fileLoc.startsWith("/") || fileLoc.startsWith("~")){ return new File(fileLoc); }else return new File(BASE_DIR, fileLoc); } public static void main(String[] args) { ImportFileGenerator i = new ImportFileGenerator(); try { CmdArgsParser cmd=new CmdArgsParser(); cmd.parse(args); i.run(cmd); } catch (Exception e) { e.printStackTrace(); } } }