[Note: I see that template parsing is rather wobbly. The JIRA has to
be fixed in
org.drools.template.parser.DefaultTemplateContainer, and I think there are other
"holes" in the parseTemplate method.]
Roger,
while my previous suggestion avoids the NPE, it may not be the
adequate solution for your situation. I see that you have several
rules which classify ContractRule w.r.t. season and hourType. These do
not rely on template parameters, and they would be better off in a
separate simple .drl file.
Now let's look at your reduced original template
template contract_rate
rule "Summer on peak primary rate"
when
$r : ContractRule( season == "summer" && hourType ==
"onPeak" &&
type == "primary")
then
$r.setRate(@{summerOnPeakPrimaryRate});
end
end template
From the other parameter names I can imagine that you have similar
hand-written rules for all
other combinations of these three field values; templating is just
used to insert the rate values
programmatically rather than hand-coded. (I suppose good old
properties would solve this task
quite well!)
But templating may be used to save you the trouble of writing and
maintaining all the set-rate
rules themselves. (Just imagine of the Contractor comes up with the
notion of adding a rebate
for groups: You'll have to double your rules manually!)
Here's the template to achieve everything with a single rule:
template header
theSeason
theHour
theType
theRate
package resource
import resource.ContractRule
template contract_rate
rule "@{theSeason} @{theHour} @{theType} rate" ### DO NOT INDENT
THIS LINE. ARRGH!
when
$r : ContractRule( season == "@{theSeason}" && hourType ==
"@{theHour}" && type == "@{theType}")
then
$r.setRate(@{theRate});
end
end template
Now you'll have to use more than one parameter map - one for each such
combination. [[Aside: Adding
the "group" rebate can be done by
* adding the template parameter,
* adding the restriction to the template rule
* extending the rule name
* extend addParamMap
* write the additional addParamMap() calls ]]
Collection<Map<String,Object>> paramMaps = new
ArrayList<Map<String,Object>>();
private void addParamMap( String season, String hour, String type, int rate ){
Map<String,Object> params = new HashMap<String,Object>();
params.put( "theSeason", season );
params.put( "theHour", hour );
params.put( "theType", type );
params.put( "theRate", rate );
paramMaps.add( params );
}
addParamMap( "summer", "onPeak", "primary", 299 );
addParamMap( "summer", "onPeak", "secondary", 524 );
addParamMap( "summer", "semiPeak", "primary", 176 );
addParamMap( "summer", "semiPeak", "secondary", 305 );
addParamMap( "summer", "offPeak", "primary", 139 );
addParamMap( "summer", "offPeak", "secondary", 243 );
addParamMap( "winter", "onPeak", "primary", 249 );
addParamMap( "winter", "onPeak", "secondary", 438 );
addParamMap( "winter", "semiPeak", "primary", 176 );
addParamMap( "winter", "semiPeak", "secondary", 305 );
addParamMap( "winter", "offPeak", "primary", 139 );
addParamMap( "winter", "offPeak", "secondary", 243 );
String drl = converter.compile(paramMaps, dis);
And here we go: This is the generated DRL text:
package resource
import resource.ContractRule
rule "winter offPeak secondary rate"
when
$r : ContractRule( season == "winter" && hourType ==
"offPeak" &&
type == "secondary")
then
$r.setRate(243);
end
rule "winter offPeak primary rate"
when
$r : ContractRule( season == "winter" && hourType ==
"offPeak" &&
type == "primary")
then
$r.setRate(139);
end
rule "winter semiPeak secondary rate"
when
$r : ContractRule( season == "winter" && hourType ==
"semiPeak" &&
type == "secondary")
then
$r.setRate(305);
end
rule "winter semiPeak primary rate"
when
$r : ContractRule( season == "winter" && hourType ==
"semiPeak" &&
type == "primary")
then
$r.setRate(176);
end
rule "winter onPeak secondary rate"
when
$r : ContractRule( season == "winter" && hourType ==
"onPeak" &&
type == "secondary")
then
$r.setRate(438);
end
rule "winter onPeak primary rate"
when
$r : ContractRule( season == "winter" && hourType ==
"onPeak" &&
type == "primary")
then
$r.setRate(249);
end
rule "summer offPeak secondary rate"
when
$r : ContractRule( season == "summer" && hourType ==
"offPeak" &&
type == "secondary")
then
$r.setRate(243);
end
rule "summer offPeak primary rate"
when
$r : ContractRule( season == "summer" && hourType ==
"offPeak" &&
type == "primary")
then
$r.setRate(139);
end
rule "summer semiPeak secondary rate"
when
$r : ContractRule( season == "summer" && hourType ==
"semiPeak" &&
type == "secondary")
then
$r.setRate(305);
end
rule "summer semiPeak primary rate"
when
$r : ContractRule( season == "summer" && hourType ==
"semiPeak" &&
type == "primary")
then
$r.setRate(176);
end
rule "summer onPeak secondary rate"
when
$r : ContractRule( season == "summer" && hourType ==
"onPeak" &&
type == "secondary")
then
$r.setRate(524);
end
rule "summer onPeak primary rate"
when
$r : ContractRule( season == "summer" && hourType ==
"onPeak" &&
type == "primary")
then
$r.setRate(299);
end
-W
2010/11/10 Roger Smith <rogersmith1711(a)gmail.com>:
Wolfgang -
Thank you!!
On Wed, Nov 10, 2010 at 11:07 AM, Wolfgang Laun <wolfgang.laun(a)gmail.com>
wrote:
>
> If you move the
> template contract_rate
> up in front of the first rule "holiday july 4th" the NPE is gone. I
> haven't been able to validate the (presumably) generated rule set, but
> you should be able to do that now.
>
> Nevertheless, this warrants a JIRA, which I'll create forthwith. Also,
> the docs should indicate what is permitted up front, preceding the
> "template" statement.
>
> -W
>
>
> 2010/11/10 Roger Smith <rogersmith1711(a)gmail.com>:
> > Wolfgang,
> >
> > I have enclosed the template. For debugging purpose, I have removed all
> > but
> > one rule.
> >
> > Thanks,
> >
> > Roger
> >
> > - O -
> >
> > template header
> > summerOnPeakPrimaryRate
> > summerOnPeakSecondaryRate
> > summerSemiPeakPrimaryRate
> > summerSemiPeakSecondaryRate
> > summerOffPeakPrimaryRate
> > summerOffPeakSecondaryRate
> > winterOnPeakPrimaryRate
> > winterOnPeakSecondaryRate
> > winterSemiPeakPrimaryRate
> > winterSemiPeakSecondaryRate
> > winterOffPeakPrimaryRate
> > winterOffPeakSecondaryRate
> >
> > package tradex.contract.sde
> >
> > import tradex.process.ruler.server.ContractRule
> >
> > rule "holiday july 4th"
> > when
> > $r : ContractRule( year == 2010 && month == 7 && day == 4
&& holiday
> > ==
> > false)
> > then
> > modify($r){
> > setHoliday(true)
> > }
> > end
> >
> > rule "holiday xmas"
> > when
> > $r : ContractRule( year == 2010 && month == 12 && day == 25
&& holiday
> > ==
> > false)
> > then
> > modify($r){
> > setHoliday(true)
> > }
> > end
> >
> > rule "Season summer"
> > when
> > $r : ContractRule( dayOfYear >= 121 && dayOfYear <= 273
&& season ==
> > "undefined")
> > then
> > modify($r){
> > setSeason("summer")
> > }
> > end
> >
> > rule "Season winter"
> > when
> > $r : ContractRule( (dayOfYear >= 274 || dayOfYear <= 120) &&
season ==
> > "undefined")
> > then
> > modify($r){
> > setSeason("winter")
> > }
> > end
> >
> >
> > rule "On peak hour"
> > when
> > $r : ContractRule( holiday == false && dayOfWeek >= 1 &&
dayOfWeek <=
> > 6
> > && hourOfDay >= 1400 && hourOfDay <= 2000 &&
> > hourType == "undefined")
> > then
> > modify($r){
> > setHourType("onPeak")
> > }
> >
> > end
> >
> > rule "Semi peak hour"
> > when
> > $r : ContractRule( holiday == false && dayOfWeek >= 1 &&
dayOfWeek <=
> > 6
> > && (hourOfDay >= 600 && hourOfDay < 1400 ||
> > hourOfDay > 2000 && hourOfDay <= 2200) && hourType ==
"undefined")
> > then
> > modify($r){
> > setHourType("semiPeak")
> > }
> > end
> >
> > rule "Off peak hour"
> > when
> > $r : ContractRule( (holiday == true || dayOfWeek == 7 || hourOfDay <
> > 600
> > || hourOfDay > 2200) && hourType == "undefined" )
> > then
> > modify($r){
> > setHourType("offPeak")
> > }
> > end
> >
> > template contract_rate
> > rule "Summer on peak primary rate"
> > when
> > $r : ContractRule( season == "summer" && hourType ==
"onPeak" &&
> > type ==
> > "primary")
> > then
> > $r.setRate(@{summerOnPeakPrimaryRate});
> > end
> > end template
> >
> >
> >
> >
> > 2010/11/9 Wolfgang Laun <wolfgang.laun(a)gmail.com>
> >>
> >> Seeing the template .drl would help to resolve this. Are all
> >> @{parameter}s
> >> declared in the template header?
> >> -W
> >>
> >> 2010/11/9 Roger Smith <rogersmith1711(a)gmail.com>
> >>>
> >>>
> >>> All -
> >>>
> >>> I tried out Drools rule template with a with a proptotype app. Drools
> >>> is
> >>> throwing NullPointerException as below. I would much appreciate if
> >>> someone
> >>> on this list can help.
> >>> java.lang.NullPointerException
> >>> at
> >>>
> >>>
org.drools.template.parser.DefaultTemplateColumn.createCellCondition(DefaultTemplateColumn.java:68)
> >>> at
> >>>
> >>>
org.drools.template.parser.DefaultTemplateColumn.addCondition(DefaultTemplateColumn.java:91)
> >>> at
> >>>
> >>>
org.drools.template.parser.DefaultTemplateRuleBase.createColumnConditions(DefaultTemplateRuleBase.java:105)
> >>> at
> >>>
> >>>
org.drools.template.parser.DefaultTemplateRuleBase.createTemplateRule(DefaultTemplateRuleBase.java:98)
> >>> at
> >>>
> >>>
org.drools.template.parser.DefaultTemplateRuleBase.getDTRules(DefaultTemplateRuleBase.java:85)
> >>> at
> >>>
> >>>
org.drools.template.parser.DefaultTemplateRuleBase.<init>(DefaultTemplateRuleBase.java:64)
> >>> at
> >>>
> >>>
org.drools.template.parser.TemplateDataListener.<init>(TemplateDataListener.java:76)
> >>> at
> >>>
> >>>
org.drools.template.parser.TemplateDataListener.<init>(TemplateDataListener.java:52)
> >>> at
> >>>
> >>>
org.drools.template.ObjectDataCompiler.compile(ObjectDataCompiler.java:44)
> >>>
> >>>
> >>> Here is my code
> >>>
> >>> KnowledgeBuilder kBuilder =
> >>> KnowledgeBuilderFactory.newKnowledgeBuilder();
> >>> ObjectDataCompiler converter = new ObjectDataCompiler();
> >>> InputStream dis = new FileInputStream( new File(
> >>> "/home/pranab/Projects/gridx/ct11_1.drl" ) );
> >>> if (null == dis){
> >>> System.out.println("null rule template stream");
> >>> return;
> >>> }
> >>>
> >>> Collection<Map<String,Object>> paramMaps = new
> >>> ArrayList<Map<String,Object>>();
> >>>
> >>> Map<String,Object> params = new
HashMap<String,Object>();
> >>>
> >>> params.put("summerOnPeakPrimaryRate", new
Integer(299));
> >>> params.put("summerOnPeakSecondaryRate", new
Integer(524));
> >>> params.put("summerSemiPeakPrimaryRate", new
Integer(176));
> >>> params.put("summerSemiPeakSecondaryRate", new
Integer(305));
> >>> params.put("summerOffPeakPrimaryRate", new
Integer(139));
> >>> params.put("summerOffPeakSecondaryRate", new
Integer(243));
> >>> params.put("winterOnPeakPrimaryRate", new
Integer(249));
> >>> params.put("winterOnPeakSecondaryRate", new
Integer(438));
> >>> params.put("winterSemiPeakPrimaryRate", new
Integer(176));
> >>> params.put("winterSemiPeakSecondaryRate", new
Integer(305));
> >>> params.put("winterOffPeakPrimaryRate", new
Integer(139));
> >>> params.put("winterOffPeakSecondaryRate", new
Integer(243));
> >>> paramMaps.add(params);
> >>>
> >>> String drl = converter.compile(paramMaps, dis);
> >>> Reader rdr = new StringReader( drl );
> >>> kBuilder.add( ResourceFactory.newReaderResource(rdr),
> >>> ResourceType.DRL);
> >>>
> >>>
> >>> The line in blue is throwing the exception. This code is very similar
> >>> to
> >>> the example code in Drools Expert guide.
> >>>
> >>> Best,
> >>>
> >>> Roger
> >>>
> >>> _______________________________________________
> >>> rules-users mailing list
> >>> rules-users(a)lists.jboss.org
> >>>
https://lists.jboss.org/mailman/listinfo/rules-users
> >>>
> >>
> >>
> >> _______________________________________________
> >> rules-users mailing list
> >> rules-users(a)lists.jboss.org
> >>
https://lists.jboss.org/mailman/listinfo/rules-users
> >>
> >
> >
> > _______________________________________________
> > rules-users mailing list
> > rules-users(a)lists.jboss.org
> >
https://lists.jboss.org/mailman/listinfo/rules-users
> >
> >
>
> _______________________________________________
> rules-users mailing list
> rules-users(a)lists.jboss.org
>
https://lists.jboss.org/mailman/listinfo/rules-users
_______________________________________________
rules-users mailing list
rules-users(a)lists.jboss.org
https://lists.jboss.org/mailman/listinfo/rules-users