Creating a new custom device requirement rule is similar to adding a new attribute, except that an additional <Rule-Info> element is associated with the attribute to provide rule information. A rule type must be specified for each group or attribute associated with a rule.
For more information about the <Rule-Info> element, see the attribute descriptors schema found in this directory on the Portal Server: wp_profile_root/PortalServer/wp.mobile/wp.mobile.mwp/shared/app/config.
The standard rule types included are mcs_conditional and mcs_reqctx. The mcs_conditional rule type generates string conditionals that are embedded in the markup for resolution by the Multi-Channel Server (MCS) servlet filter. The mcs_reqctx rule type generates rule resolver objects that implement the IRuleResolver interface. The resolver objects use a device input parameter that is retrieved from the MCS request context. The device object contains methods to fetch policy values that are used by the resolver objects to determine whether a rule matches or not. By default, the mcs_reqctx object is used to dynamically query the device policies to resolve the rule.
The seed for any rule is a Java™ class that implements the com.ibm.mwp.metadata.rule.IRuleGenerator interface. The implementation class of this interface must simply provide this method:
public Serializable generateRule(MetaData metaData);
An instance of this class is constructed and the generateRule() method is called to generate the rule resolver object, which is any object that implements Serializable and can resolve some rule using the MetaData parameter. This rule resolver object is cached and reused whenever a rule needs to be resolved for an attribute. The XDIME aggregator must have prior knowledge of the type of object that the rule resolver object represents and must cast it to the appropriate class. The mcs_conditional rule resolver object is simply a string that represents the conditional. The mcs_reqctx rule resolver object is an instance of a class that implements the com.ibm.mwp.metadata.rule.IRuleResolver interface. The implementation class of the IRuleResolver interface must simply provide this method:
public boolean resolve(Object parm);
The aggregator can call the resolve method at runtime but must pass in the appropriate input parameter if needed by the rule resolver object to run the rule resolution. For mcs_reqctx, the resulting Boolean determines whether to include the node markup or to skip it. However you decide to implement the rule, it is flexible enough for you to generate any type of rule, whether it is simple or complex.
Notice that many of the attributes have a <Rule-Info> element defined but do not specify a classname for the rule generator class. This is because a parent group has provided a default rule generator that is able to recursively generate a rule resolver object for all child attributes and resolve them together. If the default rule generator cannot handle an attribute generically, the attribute can specify the classname of a rule generator class which is able to generate a more specific rule resolver object.
<Attribute-Group name="rule">
<Rule-Info type="mcs_reqctx"
classname="com.ibm.mwp.metadata.rule.mcs.reqctx.DefaultMCSRuleGenerator" />
<Attribute name="simpleAttribute" type="boolean" required="false">
<Rule-Info type="mcs_reqctx"/>
</Attribute>
<Attribute name="complexAttribute" type="string" required="false">
<Rule-Info type="mcs_reqctx" classname="com.ibm.mwp.metadata.rule.mcs.reqctx.ComplexAttributeMCSRuleGenerator" />
</Attribute>
</Attribute-Group>
<Attribute-Group name="custom" friendly-name="Custom Rules" friendly-name-resource="ea.attr.rule.custom">
<Rule-Info type="mcs_conditional"/>
<Rule-Info type="mcs_reqctx"/>
</Attribute-Group>
<Attribute-Group name="custom" friendly-name="Custom Rules" friendly-name-resource="ea.attr.rule.custom">
<Rule-Info type="mcs_conditional"/>
<Rule-Info type="mcs_reqctx"/>
<Attribute name="photoCapable" type="boolean" required="false" max-length="5" friendly-name="Photo Capable">
<Rule-Info type="mcs_conditional" mapped-name="dstillscamera" />
<Rule-Info type="mcs_reqctx" mapped-name="dstillscamera" />
</Attribute>
</Attribute-Group>
This example adds a new attribute called photoCapable, which is of the type Boolean. For the two <Rule-Info> types, the mapped-name is dstillscamera which was the policy short name stored in the MCS DeviceRepository. A rule generator class attribute is not specified for the <Rule-Info> elements because their respective default rule generators specified in the parent rule <Attribute-Group> rule can recursively handle attributes with direct mappings to the MCS DeviceRepository. The only information the default rule generator needs is in the mapped-name attribute to determine the name mapping to the corresponding policy in the DeviceRepository. Because the new photoCapable <Attribute> was added to the custom <Attribute-Group>, the attribute is automatically available in the Advanced: Customized device requirements page in the Extended Properties Portlet Device Requirements page.
<Attribute-Group name="custom" friendly-name="Custom Rules" friendly-name-resource="ea.attr.rule.custom">
<Rule-Info type="mcs_conditional"/>
<Rule-Info type="mcs_reqctx"/>
</Attribute-Group>
<Attribute-Group name="custom" friendly-name="Custom Rules" friendly-name-resource="ea.attr.rule.custom">
<Rule-Info type="mcs_conditional"/>
<Rule-Info type="mcs_reqctx"/>
<Attribute name="validPocketIE" type="boolean" required="false" max-length="5" friendly-name="Running Valid PocketIE">
<Rule-Info type="mcs_conditional" class="com.test.conditional.ValidPocketIERuleGenerator"/>
<Rule-Info type="mcs_reqctx" class="com.test.reqctx.ValidPocketIERuleGenerator"/>
</Attribute>
</Attribute-Group>
package com.test.conditional.ValidPocketIERuleGenerator;
import java.io.Serializable;
import com.ibm.mwp.metadata.MetaData;
import com.ibm.mwp.metadata.rule.IRuleGenerator;
public class ValidPocketIERuleGenerator implements IRuleGenerator {
//if metadata is defined then check whether it is has
//a Boolean value of true and return the string conditional
public Serializable generateRule(MetaData metaData){
String conditional = null;
if(metaData != null){
boolean bool = metaData.getBooleanLiteral();
if(bool){
conditional = "device:getPolicyValue('brwsrname')='Pocket IE' and number(device:getPolicyValue('brwsrvers')) > 2";
}
}
return conditional;
}
}
package com.test.reqctx.ValidPocketIERuleGenerator;
import java.io.Serializable;
import com.ibm.mwp.metadata.MetaData;
import com.ibm.mwp.metadata.rule.IRuleGenerator;
import com.ibm.mwp.metadata.rule.IRuleResolver;
public class ValidPocketIERuleGenerator implements IRuleGenerator {
//if metadata is defined then check whether it is has
//a Boolean value of true and return the IRuleResolver object
public Serializable generateRule(MetaData metaData){
ValidPocketIERuleResolver resolver = null;
if(metaData != null){
boolean bool = metaData.getBooleanLiteral();
if(bool){
resolver = new ValidPocketIERuleResolver();
}
}
return resolver;
}
//Inner class which implements the IRuleResolver which is returned
//by the generateRule() method.
static class ValidPocketIERuleResolver implements IRuleResolver{
//resolves at runtime given the device parameter
//to see if the brwsrname and brwsrvers are valid
public boolean resolve(Object parm) throws Exception {
boolean ret = true;
Device device = (Device)parm;
String brwsrname = device.getPolicyValue("brwsrname");
String brwsrvers = device.getPolicyValue("brwsrvers");
float version = 0;
if(brwsrvers != null){
version = Float.parseFloat(brwsrvers);
}
ret = brwsrname != null && brwsrname.equals("Pocket IE") && brwsrvers && version > 2;
return ret;
}
}
}