Customizing the promotion sequence builder

If the current sequence building rules for promotion evaluation do not meet your business requirements, you can customize the sequence builder. A WebSphere Commerce instance has only one sequence builder. Customizations apply to all stores in the same instance.

Procedure

  1. Implement your promotion sequence builder.

    All custom sequence builders must implement the PromotionExecutionSequenceBuilder interface, which is a subclass of XMLizable. The key method of the sequence builder is the buildSequence method. It takes a PromotionContext object as input.

    The following is a sample sequence builder. It is similar to the default sequence builder, except that it does not give priority to promotions for which a promotion code or coupon has been entered.
    
    package com.ibm.commerce.marketing.promotion.runtime;
    
    import java.util.Enumeration;
    import java.util.Vector;
    
    import org.w3c.dom.Node;
    
    import com.ibm.commerce.copyright.IBMCopyright;
    import com.ibm.commerce.marketing.promotion.Promotion;
    import com.ibm.commerce.marketing.promotion.group.PromotionGroup;
    import com.ibm.commerce.marketing.promotion.group.PromotionGroupKey;
    import com.ibm.commerce.marketing.promotion.xml.DeXMLizationException;
    import com.ibm.commerce.marketing.promotion.xml.XMLizationException;
    import com.ibm.commerce.marketing.util.XMLHelper;
    
    /**
     *A sequence builder for the promotion engine. The following rules are observed
     * 1. Promotions specified in a group that is defined earlier in the promotion
     *    invocation template are called before a promotion that is in a group defined
     *    later in the template.
     * 2. For promotions in the same group, when all else is equal, the one with a higher
     *    priority is invoked earlier than one that has a lower priority.
     *
     */
     
    public class StaticSequenceBuilder implements PromotionExecutionSequenceBuilder {
    
       /**
        * IBM Copyright
        */
       public static final String COPYRIGHT= IBMCopyright.SHORT_COPYRIGHT;
            
            
       /**
        * Constructor.
        *
        */ 
       public StaticSequenceBuilder() {
          super();
       }
    
       /**
        * Compares the priority of two promotions
        * @param promo1
        * @param promo2
        * @param context the current promotion context
        * @return >;0 when promo1 has precedence over promo2, =0,
        * promo1 and promo2 have the same priority, <0, promo2
        * takes precedence over promo1
        */
       protected int comparePromotionPriority(
          Promotion promo1,
          Promotion promo2,
          PromotionContext context) {
               
             PromotionGroupKey key1 = promo1.getGroupKey();
             PromotionGroupKey key2 = promo2.getGroupKey();
               
             PromotionGroup groups[] = context.getGroups();
             for (int i= 0; i < groups.length; i++) {
                if (groups[i].getKey().equals(key1)
                && (!groups[i].getKey().equals(key2))) {
                   return 1;
                }
                if (groups[i].getKey().equals(key2)
                   && (!groups[i].getKey().equals(key1))) {
                      return -1;
                   }
                }
               
                return promo1.getPriority().compareTo(promo2.getPriority());
             }
            
             /**
              * @see com.ibm.commerce.marketing.promotion.runtime.
              * PromotionExecutionSequenceBuilder#buildSequence(
              * com.ibm.commerce.marketing.promotion.runtime.PromotionContext)
              */
             public Vector buildSequence(PromotionContext context) {
                // calculate the sequence in which promotions will be evaluated
                Vector sequence = new Vector();
                Enumeration promos = context.listAllPromotions();
                while (promos.hasMoreElements()) {
                   Promotion promo = (Promotion) promos.nextElement();
                   boolean inserted = false;
                   for (int i = 0; i < sequence.size(); i++) {
                      if (comparePromotionPriority(promo,
                         (Promotion) sequence.elementAt(i),
                         context) > 0) {
                            sequence.insertElementAt(promo, i);
                            inserted = true;
                            break;
                      }
                   }
                   if (!inserted) {
                      sequence.addElement(promo);
                   }
                }
                return sequence;
             }
             
             /**
              * @see com.ibm.commerce.marketing.promotion.xml.XMLizable#toXML()
              */
             public String toXML() throws XMLizationException {
                StringBuffer buffer = new StringBuffer();
                buffer
                   .append("<PromotionExecutionSequenceBuilder impl=\"")
                   .append(this.getClass().getName())
                   .append("\"/>");
                   
                return buffer.toString();
             }
             
             
             /**
              * @see com.ibm.commerce.marketing.promotion.xml
              * .XMLizable#fromXML(org.w3c.dom.Node)
              */
             public void fromXML(Node anXMLNode) throws DeXMLizationException {
                try {
                   if this.getClass()
                      != Class.forName(
                      XMLHelper.getAttributeValue(anXMLNode,"impl"))) {
                         throw new DeXMLizationException("Wrong implementation");
                      }
                   } catch (DeXMLizationException e) {
                      throw e;
                   } catch (Throwable e) {
                      throw new DeXMLizationException(e.toString());
                   }
                }
                
             }
          }
    
  2. Configure the promotion engine for a custom sequence builder.
  3. Restart WebSphere Commerce. Since the agenda builder is initialized during WebSphere Commerce start up, a restart is required before the changes take effect.