/*
* Copyright 2011 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.drools.informer.write.questionnaire;
import java.io.*;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Iterator;
import com.sun.org.apache.xalan.internal.xsltc.compiler.Template;
import org.drools.informer.util.TemplateManager;
import org.drools.informer.write.questionnaire.PageTemplate;
import org.drools.informer.write.questionnaire.WhenClauseTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.drools.informer.Question;
import org.drools.informer.domain.questionnaire.Application;
import org.drools.informer.domain.questionnaire.Page;
import org.drools.informer.domain.questionnaire.PageElement;
import org.drools.informer.domain.questionnaire.conditions.PageElementCondition;
import org.drools.informer.domain.questionnaire.framework.ListEntryTuple;
import org.drools.informer.write.questionnaire.helpers.CopyrightWriter;
public class ApplicationTemplate {
private static final Logger logger = LoggerFactory.getLogger(ApplicationTemplate.class);
private Application app;
public ApplicationTemplate(Application application) {
super();
app = application;
}
// /**
// * Make sure that the directories and files exist, setting up for actually writing the drl file.
// * Will include copyright and import files (simple read line and then write line).
// *
// * @param directory
// * @param importDirectory
// * @param seperatePageDirectories
// * @return
// */
//// public boolean generateDRLFile(String directory, String importDirectory, boolean seperatePageDirectories) {
//// String fileName = directory + "/" + app.getId().replace(' ', '_') + ".drl";
//// try {
//// File outdir = new File(directory);
////
//// //Basic directory existence checks
//// if (outdir.exists() && !outdir.isDirectory()) {
//// throw new IOException(directory + " is not a valid directory.");
//// }
////
//// // create the directory if it doesn't exist.
//// if(!outdir.exists()) {
//// if(!outdir.mkdir()) {
//// throw new IOException("Unable to create directory: " + directory);
//// }
//// }
//// Formatter fmtFile;
//// fmtFile = new Formatter(new FileOutputStream(fileName));
//// CopyrightWriter.writeCopyright(fmtFile, importDirectory);
//// writeDRLFileContents(fmtFile);
////
//// if (importDirectory != null) {
//// File importDir = new File(importDirectory);
//// if(!importDir.exists()) {
//// throw new IOException("Unable to access import directory: " + importDirectory);
//// }
//// if (!importDirectory.endsWith("/") || !importDirectory.endsWith("\\")) {
//// importDirectory = importDirectory + "/";
//// }
//// for (Iterator<String> imports = app.getImports().iterator(); imports.hasNext();) {
//// String importFileName = imports.next();
//// File importFile = new File(importDirectory + importFileName);
//// if (!importFile.exists()) {
//// throw new IOException("The import file does not exist: " + importDirectory + importFileName);
//// }
//// BufferedReader reader = new BufferedReader(new FileReader(importFile));
////
//// //... Loop as long as there are input lines.
//// String line = null;
//// while ((line=reader.readLine()) != null) {
//// fmtFile.format("%s\n", line);
//// }
////
//// //... Close reader and writer.
//// reader.close(); // Close to unlock.
//// }
//// }
////
//// fmtFile.close();
//// } catch (IOException e) {
//// logger.debug(e.getMessage());
//// e.printStackTrace();
//// return false;
//// }
//// logger.debug("The " + fileName + " file has been written");
//// int count = 1;
//// for (Iterator<Page> iterator = app.getPageList().iterator(); iterator.hasNext();) {
//// Page pg = iterator.next();
//// boolean processed = new PageTemplate(pg).generateDRLFile(app, directory, importDirectory, count, seperatePageDirectories);
//// if (!processed) {
//// return false;
//// }
//// count++;
//// }
////
//// return true;
//// }
//
//
/**
* Make sure that the directories and files exist, setting up for actually writing the drl file.
* Will include copyright and import files (simple read line and then write line).
*
* @return
*/
public byte[] generateDRLAsBytes() {
TemplateManager tm = LoaderTemplateManager.getInstance();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Formatter fmtFile = new Formatter(baos);
compileToDRL(tm,fmtFile);
int count = 1;
for (Iterator<Page> iterator = app.getPageList().iterator(); iterator.hasNext();) {
Page pg = iterator.next();
new PageTemplate(pg).compileDRL(tm, fmtFile, app, count);
count++;
}
fmtFile.close();
return baos.toByteArray();
}
public void compileToDRL(TemplateManager tm, Formatter fmt) {
HashMap map = new HashMap();
map.put("pack","org.drools.informer");
tm.applyTemplate("header.drlt", null, map, fmt);
tm.applyTemplate("questionnaire.drlt", app, null, fmt);
for (Iterator<PageElement> i = app.getGlobalElements().iterator(); i.hasNext();) {
PageElement element = (PageElement) i.next();
new PageElementTemplate(element).compileContentsToDRL(app, tm, fmt);
}
// Now create any PossibleAnswer insert/remove logic, if there are any tuples with some logic
for (Iterator<Page> iterator = app.getPageList().iterator(); iterator.hasNext();) {
Page pg = iterator.next();
processConditionalTableElement(tm, fmt, pg.getParentPageElement());
}
}
//// /**
//// * Includes writing the import (class) statements, and the Questionnaire definition.
//// *
//// * @param fmt
//// * @throws IOException
//// */
//// public void writeDRLFileContents(Formatter fmt) throws IOException {
//// fmt.format("package %s;\n\n", app.getApplicationClass());
//// fmt.format("import org.drools.informer.Group;\n");
//// fmt.format("import org.drools.informer.InvalidAnswer;\n");
//// fmt.format("import org.drools.informer.MultipleChoiceQuestion;\n");
//// fmt.format("import org.drools.informer.MultipleChoiceQuestion.PossibleAnswer;\n");
//// fmt.format("import org.drools.informer.Note;\n");
//// fmt.format("import org.drools.informer.Question;\n");
//// fmt.format("import org.drools.informer.Answer;\n");
//// fmt.format("import org.drools.informer.Item;\n");
//// fmt.format("import org.drools.informer.InformerObject;\n");
//// fmt.format("import org.drools.informer.Questionnaire;\n");
////
//// fmt.format("import java.text.SimpleDateFormat;\n");
//// fmt.format("import java.util.Calendar;\n");
//// fmt.format("import java.util.Date;\n");
//// fmt.format("import java.util.Arrays;\n\n");
////
//// // TODO add in ability to add additional import statements?
//// // Maybe have an import filename as well as include filenames
////
//// fmt.format("rule \"%s\"\ndialect \"mvel\"\n", app.getId());
//// fmt.format("then\n");
//// fmt.format("\tQuestionnaire questionnaire = new Questionnaire(\"%s\");\n", app.getId());
//// fmt.format("\tquestionnaire.setLabel(\"%s\");\n", app.getApplicationName());
//// fmt.format("\tquestionnaire.setCompletionAction(\"%s\");\n", app.getCompletionAction());
//// fmt.format("\tquestionnaire.setItems({%s});\n", app.getItemList());
//// if (app.getActivePage() != null) {
//// fmt.format("\tquestionnaire.setActiveItem(\"%s\");\n", app.getActivePage());
//// }
//// fmt.format("\tquestionnaire.setEnableActionValidation(%s);\n", app.getActionValidation());
//// fmt.format("\tquestionnaire.setMarkupAllowed(%s);\n", app.getMarkupAllowed());
//// fmt.format("\tinsertLogical(questionnaire);\n");
////
//// fmt.format("end\n\n");
////
////
//// for (Iterator<PageElement> i = app.getGlobalElements().iterator(); i.hasNext();) {
//// PageElement element = (PageElement) i.next();
//// new PageElementTemplate(element).writeDRLFileContents(app, fmt);
//// }
////
//// // Used as a class to control insert/remove PossibleAnswer entry logic
//// fmt.format("declare ListEntryFact\n");
//// fmt.format("\tid : String @key\n");
//// fmt.format("end\n\n");
////
//// // Now create any PossibleAnswer insert/remove logic, if there are any tuples with some logic
//// for (Iterator<Page> iterator = app.getPageList().iterator(); iterator.hasNext();) {
//// Page pg = iterator.next();
//// processConditionalTableElement(fmt, pg.getParentPageElement());
//// }
////
//// }
////
////
//
//
/**
* Recursively find all list tuples with conditional logic, and then call {@link #writeConditionalTableElement(TemplateManager, Formatter, PageElement, ListEntryTuple, int)}
*
* @param fmt
* @param element
* @throws IOException
*/
protected void processConditionalTableElement(TemplateManager tm, Formatter fmt, PageElement element) {
if (element == null) {
return;
}
if ((element.getLookupTable() != null) && (element.getLookupTable().getEntries() != null)) {
int count = 0;
for (Iterator<ListEntryTuple> iterator = element.getLookupTable().getEntries().iterator(); iterator.hasNext();) {
ListEntryTuple tuple = (ListEntryTuple) iterator.next();
count++;
if (tuple.getConditionClause() != null) {
writeConditionalTableElement(tm, fmt, element, tuple, count);
}
}
}
for (Iterator<PageElement> iterator = element.getChildren().iterator(); iterator.hasNext();) {
PageElement child = (PageElement) iterator.next();
processConditionalTableElement(tm, fmt, child);
}
}
/**
* Writes the drl logic for one tuple:
* <p>
* The controlling fact is written:<br>
* The conditional logic is used to create a named instance of the (dynamically defined) ListEntryFact object.
* </p>
*
* <p>
* The insert rule is written:<br>
* If the controlling fact exists but the entry is not in the list of objects, <br>
* then insert a new PossibleAnswer into the list, at rowNumber
* </p>
*
* <p>
* The remove rule is written:<br>
* If the controlling fact no longer exists but the entry is still in the list of objects, <br>
* then remove the associated PossibleAnswer from the list
* </p>
*
* @param fmt
* @param element
* @param tuple
* @param rowNumber
* Important for distinguishing id and rule names if there is more than one conditional tuple for a list
* @throws IOException
*/
protected void writeConditionalTableElement(TemplateManager tm, Formatter fmt, PageElement element, ListEntryTuple tuple, int rowNumber) {
HashMap map = new HashMap();
String displayFactId = element.getId() + "row" + String.valueOf(rowNumber);
PageElementCondition c = new PageElementCondition(PageElementCondition.TYPE_INCLUSION, displayFactId, rowNumber);
c.addElement(tuple.getConditionClause());
PageElement pe = new PageElement();
pe.setId(element.getId(), -1, rowNumber);
pe.setDisplayCondition(c);
WhenClauseTemplate wce = new WhenClauseTemplate(pe);
String whenClause = wce.writeLogicSectionDRL(app, false);
map = new HashMap();
map.put("displayFactId",displayFactId);
map.put("whenClause",whenClause);
tm.applyTemplate("include.drlt",null,map,fmt);
map = new HashMap();
map.put("displayFactId",displayFactId);
map.put("elementId",element.getId());
map.put("tupleId",tuple.getId());
map.put("tupleRepresentation",tuple.getRepresentation());
map.put("rowNumber",rowNumber);
tm.applyTemplate("include.drlt",null,map,fmt);
map = new HashMap();
map.put("displayFactId",displayFactId);
map.put("elementId",element.getId());
map.put("tupleId",tuple.getId());
tm.applyTemplate("remove.drlt",null,map,fmt);
}
}