Adding custom device requirement rule properties

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.

The following example shows that a rule generator is defined for the attribute group rule. The rule generator can recursively handle sub-attributes which is why simpleAttribute does not require a rule generator class. However, the complexAttribute requires special processing therefore it provides its own rule generator class (this is only an example, the class does not really exist). This system provides an easy way for you to handle attributes generically or override with more complex logic.
<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>

Sample for adding simple device requirements rule

In this exercise, you update the attributes descriptor file to include a new device requirements rule for determining whether a device has a digital stills camera. First, use the Mobile Portal Toolkit Device Repository viewer or editor to find the short name of the policy value that contains this information. The digital stills camera short name is dstillscamera. The value can be either true or false, so you define a Boolean attribute to represent this policy.
  1. Open wp_root/shared/mwp/config/attr-descriptor.xml with a text editor and then find the following section in the file:
    <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"/>
  2. Add your new custom rule attribute within this group.
    </Attribute-Group>
  3. Within this specific custom attribute group, you can add as many new rule attributes as you require. See the schema for more information on the formatting of the attribute element. The following example shows how to add the digital stills camera rule attribute:
    <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.

Sample for adding complex device requirements rule

This example describes how to define a device requirements rule that can handle more complex policy value comparisons in addition to the single comparisons that the default rule generator can handle. Suppose you want to create a Boolean rule called validPocketIE that checks whether a device is running Pocket IE with a version of at least 2.0. Because you want one attribute to represent the lookup of two policy values, you must create a custom rule generator Java class to handle this.
  1. Use the Mobile Portal Toolkit Device Repository viewer or editor to find the short names of the browser name and browser version policies. They are brwsrname and brwsrvers respectively.
  2. Open wp_root/shared/mwp/config/attr-descriptor.xml with a text editor and find the following section:
    <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"/>
  3. Add your new custom rule attribute within this group.
    </Attribute-Group>
  4. Within this specific custom attribute group, you can add as many new rule attributes as you require. See the schema for more information on the formatting of the attribute element. The following example shows how to add the validPocketIE rule attribute:
    <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>
  5. In the descriptor file, you define a Boolean <Attribute> called validPocketIE . The user-friendly name of Running Valid PocketIE is shown in the Extended Properties portlet. Two <Rule-Info> elements are defined as well, one for the mcs_conditional type and another for the mcs_reqctx type. Each type handles the attribute differently:
    1. The mcs_conditional generates a string conditional which is used by the XDIME aggregator to set as an expression within the XDIME markup. The expression is then resolved by the MCS servlet filter to determine whether to show some content. See the MCS documentation for conditional markup support.
    2. The mcs_reqctx resolves a rule by accessing the MCS request context to retrieve device information. The comparison is done within Java code and a Boolean response is returned to the XDIME aggregator to determine whether to show some content.
  6. For each rule type, a class that implements IRuleGenerator has been specified in the class attribute of the <Rule-Info> elements. These Java classes generate a serializable object that represents the rule for use by the XDIME aggregator. Notice that the mapped-name attribute is not specified for the <Rule-Info> elements. Because the validPocketIE rule does not map directly to a single policy, there is no need to specify it when generating a custom Java class to handle comparing two policies. The class files must be placed in the classpath that is accessible by the IBM® Mobile Portal Accelerator code. It is suggested that you place it in portal/shared/mwp/.
  7. The mcs_conditional rule generator class would look like this:
    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;
      }
    }
  8. The mcs_reqctx rule generator would look like this:
    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;
        }
      }
    }
  9. Depending on which rule type is used, the XDIME aggregator takes the output of the generated rule object and decides what to do with it. If the rule type used is mcs_conditional, the aggregator casts the generated rule object to a string and include it as an expression in the XDIME markup. If the rule type used is mcs_reqctx, the aggregator casts the generated rule object into the IRuleResolver interface and passes in the required device object for use in the resolve(Object parm) method. The resulting Boolean then determines whether or not the aggregator shows any content.
  10. Now you can enable the Running Valid PocketIE option within the Extended Properties portlet for a node. When using a device that is not running Pocket IE or the correct version, the node should not be displayed in the device.



Terms of use
(C) Copyright IBM Corporation 2012. All Rights Reserved.