Hi Wolfgang,
We were able to get the code to work based on your previous suggestions.
Your following recommendation is definitely more elegant and complete. Many
thanks for following up. Most grateful!
Roger
On Thu, Nov 11, 2010 at 12:56 AM, Wolfgang Laun <wolfgang.laun(a)gmail.com>wrote:
[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
>
>