Essential ATG Dynamo Training - Got atg Certified Relationship Management Developer?
This is not an official ATG site: ATG, Dynamo, Scenario Server and Personalization Server are trademarks or registered trademarks of Art Technology Group
Articles Exercises Resources Links Search

Custom Tag Converter Example

Overview

This example creates and configures a custom tag converter for US format Zip Codes:

  • 91322-1232
  • 01231-0132
  • 83243

This example includes:

  • A self registering tag converter: ZipCodeTagConverter
  • A simple ZipCode class
  • A sample page which tests the tag converter

The tag converter class converts in the following ways:

  • from String to a 'ZipCode' formatted String
  • from ZipCode object to a 'ZipCode' formatted String

It is used in JHTML like this:

<VALUEOF PARAM="zip" converter="ZipCode">default</VALUEOF>

Where zip may be either a string or a ZipCode object.

Source Code and Configuration Files

ZipCodeTagConverter.java

package imagescript.atg.tagconverter;

import java.util.*;
import java.text.*;
import atg.servlet.DynamoHttpServletRequest;
import atg.droplet.*;
/**
 * @copyright Copyright (c) 2001
 * @company Art Technology Group
 * @author Stuart Jones
 * @version 1.0 ATG Training Supplemental Files
 */

public class ZipCodeTagConverter
           extends atg.nucleus.GenericService
           implements atg.droplet.TagConverter
{
  static final String NAME = "ZipCode";
  static final String NULLABLE_ATTRIBUTE = "nullable";
  static final String REQUIRED_ATTRIBUTE = "required";

  static final DecimalFormat nf1 = new DecimalFormat("00000");
  static final DecimalFormat nf2 = new DecimalFormat("0000");

  public ZipCodeTagConverter() {}

  // Register the tag converter with the manager
  public void doStartService()
  {
    TagConverterManager.registerTagConverter(this);
    if(isLoggingInfo())
    {
      logInfo("Registered '" + getName() + "' tag converter");
    }
  }

  private final static TagAttributeDescriptor[] sTagAttributeDescriptors = {
    new TagAttributeDescriptor(NULLABLE_ATTRIBUTE,
    	"If this attribute is present, the ZipCode may be set to null",
        true, false),
    new TagAttributeDescriptor(REQUIRED_ATTRIBUTE,
    	"If this attribute is present, the ZipCode is required",
        true, false)
  };

  public TagAttributeDescriptor [] getTagAttributeDescriptors() {
    return sTagAttributeDescriptors;
  }

  public String getName() {
    return NAME;
  }

  void log(String s)
  {
    if(isLoggingDebug()){ logDebug(s); }
  }
  void log(Exception e)
  {
    if(isLoggingError()){ logError(e); }
  }

  // Coverts a String which represents a ZipCode to a String
  //
  public Object convertStringToObject(DynamoHttpServletRequest pReq,
  				      String pValue,
                                      Properties pAttributes)
     throws TagConversionException
  {
    String strResult = null;

    boolean debugMode = isLoggingDebug();

    log("convertStringToObject: '" + pValue + "'");

    // Trim it
    if (pValue != null) pValue = pValue.trim();

    if (pValue == null || pValue.length() == 0)
    {
      // Should we allow a null value?
      if (pAttributes.getProperty(NULLABLE_ATTRIBUTE) != null)
      {
        log("Returning TagConverterManager.SET_AS_NULL");
	return TagConverterManager.SET_AS_NULL;
      }
      // is it required?
      else if (pAttributes.getProperty(REQUIRED_ATTRIBUTE) == null)
      {
        log("Value is null or 0 length, but is required: Returning null");
        return strResult;
      }
      // The value is null and it's required so that's an error
      else
      {
        throw new TagConversionException("Missing or empty value supplied for " 
                 + "a required ZipCode field", "missingRequiredValue");
      }
    }

    // Do the conversion
    strResult = getZipCode(pValue);
    if (strResult == null)
    {
      throw new TagConversionException("Unable to parse ZipCode from string: " 
                                      + pValue, "invalidZipCode");
    }

    return strResult;
  }

  // Convert zipcode to a string
  public String convertObjectToString(DynamoHttpServletRequest pReq,
  				      Object pValue, Properties pAttributes)
     throws TagConversionException
  {
    String strResult = "";

    if (pValue == null)
    {
      if (pAttributes.getProperty(NULLABLE_ATTRIBUTE) == null)
      {
        log("Attempting to convert null object to String");
      }
    }
    else if (pValue instanceof String)
    {
      log("Attempting to convert String '"+ pValue.toString());
      strResult =  getZipCode((String)pValue);
    }
    else if (pValue instanceof ZipCode)
    {
      log("Attempting to convert ZipCode '"+ pValue.toString());
      strResult =  ((ZipCode)pValue).getZipCode();
    }
    if(strResult == null)
    {
      throw new TagConversionException("Cannot convert: " + pValue 
                          + " into a ZipCode", "invalidZipCode");
    }
    return strResult;
  }

  String getZipCode(String str)
  {
    boolean debugMode = isLoggingDebug();

    String strResult = null;
    int iMain = 0;
    int iSecond = 0;
    boolean bFatalError = false;

    try
    {
      boolean bDash = false;

      log("getZipCode("+ str  + ")");

      if(str.length() >= 5)
      {
        String firstFive = str.substring(0,5);
        iMain = Integer.parseInt(firstFive);

        log("Main Zip Code Number = "+ iMain);

        if(str.length() > 5)
        {
          int iStartSecond = 5;

          if(str.length() >= 6)
          {
            bDash = (str.charAt(iStartSecond) == '-');
            if(bDash)
            {
              iStartSecond++;
            }
            log("str.charAt(iStartSecond) ="+ str.charAt(iStartSecond));
            log("bDash ="+ bDash);
          }

          logDebug("iStartSecond ="+ iStartSecond);

          if(str.length() == (iStartSecond + 4))
          {
            String secondFour = str.substring(iStartSecond);
            log("secondFour ="+ secondFour);
            iSecond = Integer.parseInt(secondFour);
            log("iSecond ="+ iSecond);
          }
          else
          {
            log("Wrong String length with optional second code");
            bFatalError = true;
          }
        }// more than 5 chars
        else
        {
          log("Code does not contain optional second code");
        }
      }
      else
      {
        bFatalError = true;
      }
    }
    catch(Exception e) //includes null
    {
      bFatalError = true;
      if(isLoggingDebug())
      {
        logDebug("Error parsing '" + str + "' : " + e.getMessage());
      }
    }

    if(!bFatalError)
    {
      strResult = assemble(iMain,iSecond);
    }

    return strResult;
  }

  public static String assemble(int nMain, int nSub)
  {
    String strResult = "";

    try
    {
      strResult = nf1.format(nMain);
      if(nSub > 0)
      {
        strResult = strResult + "-" + nf2.format(nSub);
      }
    }
    catch(NumberFormatException e)
    {
    }
    return strResult;
  }

}

ZipCode.java

This additional class is provided to show how to convert from objects other than strings.

package imagescript.atg.tagconverter;

/**
 *
 *
 * @copyright Copyright (c) 2001
 * @company Art Technology Group
 * @author Stuart Jones
 * @version 1.0 ATG Training Supplemental Files
 */

public class ZipCode
{
  public ZipCode() {  }

  int mMainCode;
  int mSubCode;

  public void setMainCode(int p) { mMainCode = p; }
  public int getMainCode() { return mMainCode; }
  public void setSubCode(int p) { mSubCode = p; }
  public int getSubCode() { return mSubCode; }

  public String toString()
  {
    return getClass().getName() + " : " + mMainCode + "-" + mSubCode;
  }

  public String getZipCode()
  {
    return ZipCodeTagConverter.assemble(mMainCode,mSubCode);
  }
}

/training/sf/tagconverter/ZipCode.properties

This is the configuration file for the tag converter component. I made it a component so it could be included in an Initial.properties file to cause the self registration.

# /training/sf/tagconverter/ZipCode
#Tue Aug 07 15:10:40 PDT 2001
$class=imagescript.atg.tagconverter.ZipCodeTagConverter
$description=ZipCode\ Converter
$scope=global
loggingDebug=true

/Initial.properties

This is the configuration file to add the converter to the initial services. At startup time this starts the converter and ensures that it's doStartService method is called, this registers the tagConverter.

# /Initial
#Tue Aug 07 15:00:37 PDT 2001
initialServices+=/training/sf/tagconverter/ZipCode

Test Files

These files are not required to run the ZipCodeTagConverter. They are only used here as a simple demonstration and test harness.

/test/MyZipCode.properties

This is the configuration file for the test ZipCode used in zipcode.jhtml

# /august/MyZipCode
#Tue Aug 07 17:35:10 PDT 2001
$class=imagescript.atg.tagconverter.ZipCode
$scope=global
mainCode=94706
subCode=1233

zipcode.jhtml

This is the a demo file to test the tag converter. It uses a page fragment to actually display the zip code conversion.

<IMPORTBEAN BEAN="/test/MyZipCode">
<HTML>
<HEAD>
<TITLE>ZipCode Form</TITLE>
</HEAD>

<BODY>
<h1>ZipCode tag converter test</h1>
<h2>Object Conversion Test</h2>

<DROPLET SRC="zipfragment.jhtml">
  <PARAM NAME="zip" VALUE="bean:MyZipCode">
</DROPLET>

<h2>Text Conversion</h2>
<DROPLET SRC="zipfragment.jhtml">
  <PARAM NAME="zip" VALUE="923421234">
</DROPLET>
<DROPLET SRC="zipfragment.jhtml">
  <PARAM NAME="zip" VALUE="92342">
</DROPLET>
<DROPLET SRC="zipfragment.jhtml">
  <PARAM NAME="zip" VALUE="94109-2601">
</DROPLET>
<DROPLET SRC="zipfragment.jhtml">
  <PARAM NAME="zip" VALUE="01234">
</DROPLET>
<DROPLET SRC="zipfragment.jhtml">
  <PARAM NAME="zip" VALUE="01234-0023">
</DROPLET>
<DROPLET SRC="zipfragment.jhtml">
  <PARAM NAME="zip" VALUE="012340123">
</DROPLET>

</BODY>
</HTML>

zipfragment.jhtml

This is the a demo file to test the tag converter. It uses a page fragment to actually display the zip code conversion.

<DECLAREPARAM NAME="zip" CLASS="java.lang.Object" DESCRIPTION="Any zip code">
<!-- Title: Display Zip Code Fragment -->
<hr>
Zip (<VALUEOF PARAM="zip">null</VALUEOF>) 
converts to = <VALUEOF PARAM="zip" converter="ZipCode">No Value</VALUEOF>
<hr>


Technical Training Advertise your Training Programs for Free! Los Angeles Web Design Shopping Cart Software  Form a Corporation