[jboss-svn-commits] JBL Code SVN: r35944 - labs/jbossrules/trunk/drools-templates/src/main/java/org/drools/template/parser.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Thu Nov 11 07:36:36 EST 2010
Author: laune
Date: 2010-11-11 07:36:36 -0500 (Thu, 11 Nov 2010)
New Revision: 35944
Modified:
labs/jbossrules/trunk/drools-templates/src/main/java/org/drools/template/parser/DefaultTemplateContainer.java
Log:
many checks added: undeclared and duplicate parameters, missing and duplicate template names, unterminated and nested templates
bug fixes: JIRA-2786; handling of text around templates; recognition of indented keywords
add line numbers to error messages
Modified: labs/jbossrules/trunk/drools-templates/src/main/java/org/drools/template/parser/DefaultTemplateContainer.java
===================================================================
--- labs/jbossrules/trunk/drools-templates/src/main/java/org/drools/template/parser/DefaultTemplateContainer.java 2010-11-11 01:22:45 UTC (rev 35943)
+++ labs/jbossrules/trunk/drools-templates/src/main/java/org/drools/template/parser/DefaultTemplateContainer.java 2010-11-11 12:36:36 UTC (rev 35944)
@@ -15,14 +15,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
+import java.io.LineNumberReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
/**
*
@@ -33,144 +35,197 @@
*
*/
public class DefaultTemplateContainer implements TemplateContainer {
- private String header;
+ private String header;
- private Map<String, Column> columnMap = new HashMap<String, Column>();
+ private Map<String, Column> columnMap = new HashMap<String, Column>();
- private List<Column> columns = new ArrayList<Column>();
+ private List<Column> columns = new ArrayList<Column>();
- private Map<String, RuleTemplate> templates = new HashMap<String, RuleTemplate>();
+ private Map<String, RuleTemplate> templates = new HashMap<String, RuleTemplate>();
- public DefaultTemplateContainer(final String template) {
- this(DefaultTemplateContainer.class.getResourceAsStream(template));
- }
+ public DefaultTemplateContainer(final String template) {
+ this(DefaultTemplateContainer.class.getResourceAsStream(template));
+ }
- public DefaultTemplateContainer(final InputStream templateStream) {
- parseTemplate(templateStream);
- validateTemplate();
- }
+ public DefaultTemplateContainer(final InputStream templateReader) {
+ parseTemplate(templateReader);
+ validateTemplate();
+ }
- private void validateTemplate() {
- if (columns.size() == 0) {
- throw new DecisionTableParseException("Missing header columns");
- }
- if (templates.size() == 0) {
- throw new DecisionTableParseException("Missing templates");
- }
+ private void validateTemplate() {
+ if (columns.size() == 0) {
+ throw new DecisionTableParseException("No template parameters");
+ }
+ if (templates.size() == 0) {
+ throw new DecisionTableParseException("No templates");
+ }
+ }
- }
+ Pattern parPattern = Pattern.compile( "@\\{([^}]+)\\}" );
- private void parseTemplate(final InputStream templateStream) {
- try {
- final ColumnFactory cf = new ColumnFactory();
- final BufferedReader templateReader = new BufferedReader(
- new InputStreamReader(templateStream));
- String line = null;
- StringBuffer header = new StringBuffer();
- boolean inTemplate = false;
- boolean inHeader = false;
- boolean inContents = false;
- RuleTemplate template = null;
- StringBuffer contents = new StringBuffer();
- while ((line = templateReader.readLine()) != null) {
- if (line.trim().length() > 0) {
- if (line.startsWith("template header")) {
- inHeader = true;
- } else if (line.startsWith("template")) {
- inTemplate = true;
- String quotedName = line.substring(8).trim();
- quotedName = quotedName.substring(1, quotedName
- .length() - 1);
- template = new RuleTemplate(quotedName, this);
- addTemplate(template);
+ /**
+ * Check whether all parameters have been defined.
+ * @param line a line in a rule
+ * qparam lno the line number
+ */
+ private void checkLine( String line, int lno ){
+ Matcher parMatcher = parPattern.matcher( line );
+ while( parMatcher.find() ){
+ String par = parMatcher.group( 1 ).trim();
+ if( ! columnMap.containsKey( par ) ){
+ throw new DecisionTableParseException( "Undeclared parameter '" + par + "' in line " + lno );
+ }
+ }
+ }
- } else if (line.startsWith("package")) {
- if (inHeader == false) {
- throw new DecisionTableParseException(
- "Missing header");
- }
- inHeader = false;
- header.append(line).append("\n");
- } else if (inHeader) {
- addColumn(cf.getColumn(line.trim()));
- } else if (!inTemplate && !inHeader) {
- header.append(line).append("\n");
- } else if (!inContents && line.startsWith("rule")) {
- inContents = true;
- contents.append(line).append("\n");
- } else if (line.equals("end template")) {
- template.setContents(contents.toString());
- contents.setLength(0);
- inTemplate = false;
- inContents = false;
- } else if (inContents) {
- contents.append(line).append("\n");
- } else if (inTemplate) {
- template.addColumn(line.trim());
- }
- }
+ private void parseTemplate(final InputStream givenStream) {
+ try {
+ InputStreamReader isr = new InputStreamReader( givenStream );
+ LineNumberReader templateReader = new LineNumberReader( isr );
+ final ColumnFactory cf = new ColumnFactory();
+ String line = null;
+ StringBuilder header = new StringBuilder();
+ boolean inTemplate = false;
+ boolean inHeader = false;
+ boolean inContents = false;
+ RuleTemplate template = null;
+ StringBuilder contents = new StringBuilder();
+ String lastTemplateName = "?";
+ int lastTemplateLine = 0;
+ while ((line = templateReader.readLine()) != null) {
+ String trimmed = line.trim();
+ if( trimmed.length() > 0 ){
+ int lineNo = templateReader.getLineNumber();
- }
- if (inTemplate) {
- throw new DecisionTableParseException("Missing end template");
- }
- this.header = header.toString();
+ if( trimmed.matches( "template\\s+header" ) ){
+ inHeader = true;
- } catch (IOException e) {
- throw new RuntimeException(e);
- } finally {
- if (templateStream != null)
- closeStream(templateStream);
- }
- }
+ } else if (trimmed.startsWith("template")) {
+ if( inTemplate ){
+ throw new DecisionTableParseException(
+ "Nested template, within '" + lastTemplateName + "'. at line " + lineNo );
+ }
+ inTemplate = true;
+ String quotedName = line.substring(8).trim();
+ if( quotedName.startsWith( "\"" ) && quotedName.endsWith( "\"" ) ||
+ quotedName.startsWith( "'" ) && quotedName.endsWith( "'" ) ){
+ quotedName = quotedName.substring(1, quotedName.length() - 1);
+ }
+ if( quotedName.length() == 0 ){
+ throw new DecisionTableParseException(
+ "Template name missing at line " + lineNo );
+ }
+ if( templates.containsKey( quotedName ) ){
+ throw new DecisionTableParseException(
+ "Duplicate template name '" + quotedName + "' at line " + lineNo );
+ }
+ lastTemplateName = quotedName;
+ lastTemplateLine = lineNo;
+ template = new RuleTemplate( quotedName, this);
+ addTemplate(template);
- private void addTemplate(RuleTemplate template) {
- templates.put(template.getName(), template);
- }
+ } else if ( trimmed.startsWith("package") ) {
+ if ( ! inHeader ) {
+ throw new DecisionTableParseException(
+ "Missing header at line " + lineNo );
+ }
+ inHeader = false;
+ header.append(line).append("\n");
- /*
- * (non-Javadoc)
- *
- * @see org.drools.decisiontable.parser.TemplateContainer#getTemplates()
- */
- public Map<String, RuleTemplate> getTemplates() {
- return templates;
- }
+ } else if ( inHeader ) {
+ if( ! addColumn(cf.getColumn(trimmed)) ){
+ throw new DecisionTableParseException( "Duplicate parameter '" +
+ trimmed + "' at line " + lineNo);
+ }
- private void addColumn(Column c) {
- columns.add(c);
- columnMap.put(c.getName(), c);
- }
+ } else if (!inTemplate && !inHeader) {
+ header.append(line).append("\n");
- /*
- * (non-Javadoc)
- *
- * @see org.drools.decisiontable.parser.TemplateContainer#getColumns()
- */
- public Column[] getColumns() {
- return (Column[]) columns.toArray(new Column[columns.size()]);
- }
+ } else if (!inContents && trimmed.startsWith("rule")) {
+ if( !inTemplate ){
+ header.append(line).append("\n");
+ } else {
+ inContents = true;
+ checkLine( line, lineNo );
+ contents.append(line).append("\n");
+ }
- /*
- * (non-Javadoc)
- *
- * @see org.drools.decisiontable.parser.TemplateContainer#getHeader()
- */
- public String getHeader() {
- return header;
- }
+ } else if (trimmed.matches("end\\s+template")) {
+ template.setContents(contents.toString());
+ contents.setLength(0);
+ inTemplate = false;
+ inContents = false;
- private void closeStream(final InputStream stream) {
- try {
- stream.close();
- } catch (final Exception e) {
- System.err.print("WARNING: Wasn't able to "
- + "correctly close stream for decision table. "
- + e.getMessage());
- }
- }
+ } else if (inContents) {
+ checkLine( line, lineNo );
+ contents.append(line).append("\n");
- public Column getColumn(final String name) {
- return (Column) columnMap.get(name);
- }
+ } else if (inTemplate) {
+ template.addColumn( trimmed );
+ }
+ }
+ }
+ if (inTemplate) {
+ throw new DecisionTableParseException( "Unterminated template '" +
+ lastTemplateName + "', started in line " + lastTemplateLine );
+ }
+ this.header = header.toString();
+
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ } finally {
+ if (givenStream != null)
+ closeStream(givenStream);
+ }
+ }
+
+ private void addTemplate(RuleTemplate template) {
+ templates.put(template.getName(), template);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.drools.decisiontable.parser.TemplateContainer#getTemplates()
+ */
+ public Map<String, RuleTemplate> getTemplates() {
+ return templates;
+ }
+
+ private boolean addColumn(Column c) {
+ columns.add(c);
+ return null == columnMap.put(c.getName(), c);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.drools.decisiontable.parser.TemplateContainer#getColumns()
+ */
+ public Column[] getColumns() {
+ return (Column[]) columns.toArray(new Column[columns.size()]);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.drools.decisiontable.parser.TemplateContainer#getHeader()
+ */
+ public String getHeader() {
+ return header;
+ }
+
+ private void closeStream(final InputStream stream) {
+ try {
+ stream.close();
+ } catch (final Exception e) {
+ System.err.print("Warning: Unable to "
+ + "close stream for decision table template. "
+ + e.getMessage());
+ }
+ }
+
+ public Column getColumn(final String name) {
+ return (Column) columnMap.get(name);
+ }
}
More information about the jboss-svn-commits
mailing list