In addition to the keyword and text search of the simple search functionality, the advanced search functionality allows the customer to search for products by part number and manufacturer, which are defined as product properties. Advanced search is divided into two types of search, part number search and searching by using manufacturer and category.

Part Number Searching

Since part number is not a property of Product items but instead a property of sku items, we use a different component, atg/projects/b2bstore/catalog/PartNumberSearchFormHandler, to search for part numbers. This component uses a custom form handler, CatalogSearchFormHandler, and uses different properties than AdvProductSearch.

This is the properties file for catalogSearchFormHandler:

# Allow users to search by part number
# Part number exists on a sku
$class=atg.commerce.catalog.custom.CatalogSearchFormHandler
$scope=request
catalogTools=/atg/commerce/catalog/CatalogTools
doTextSearch=true
textSearchPropertyNames=manufacturer_part_number
itemTypes=sku
repositories=/atg/commerce/catalog/ProductCatalog

The following is the code for Part Number searching in part_number_search.jsp.

<dsp:form action="part_number_search.jsp" method="POST">
<table width="100%" border="0" cellspacing="0" cellpadding="4" bgcolor="#FFCC66">
   <tr><td colspan=2><dsp:img src= "../images/d.gif" height="10"/></td></tr>
   <tr valign="top">
      <td width="15%" align="right">
      <span class="smallb">Part#</span>
      </td>
      <td>
         <dsp:input bean="PartNumberSearchFormHandler.searchInput" size="25"
            type="text"/>&nbsp;
            <br> <span class="small">Use <b>*</b> for partial part number
               search.</span>
      </td>
   </tr>
   <tr>
      <td>&nbsp;</td>
      <td>
      <input name="repositoryKey" type="hidden" value="<dsp:valueof
         bean="/OriginatingRequest.requestLocale.locale"/>">
      <input name="noCrumbs" type="hidden" value="<dsp:valueof
         param="noCrumbs"/>"><br>
      <dsp:input bean="PartNumberSearchFormHandler.search" type="hidden"
        value="Search"/>
      <dsp:input bean="PartNumberSearchFormHandler.search" type="submit"
        value="Search"/>
</dsp:form></td>

The SearchInput property of PartNumberSearchFormHandler component is set using the part number input from user. Based on this manufacturer_part_number property of SKU is searched.

part_number_search.jsp invokes the PartNumberSearchResults.jsp fragment passing the result of the search that contains the array of SKUs of the products found. The following is the code fragment in part_number_search.jsp to include this:

<dsp:getvalueof id="pval0" idtype="java.util.List"
   bean="PartNumberSearchFormHandler.searchResults">

   <dsp:include page="PartNumberSearchResults.jsp" flush="true">
   <dsp:param name="Skus" value="<%=pval0%>"/>
   </dsp:include>

   </dsp:getvalueof>

Once we get SKUs with the given part number, we fetch products corresponding to those SKUs in PartNumberSearchResults.jsp. We iterate through each SKU and get all the products corresponding to SKU using RQLQueryForEach and display them.

The following is a snippet from PartNumberSearchResults.jsp that display the products found:

<dsp:droplet name="ForEach">
  <dsp:param name="array" param="Skus"/>
  <dsp:param name="elementName" value="element"/>
  <dsp:oparam name="outputStart">
   <b>We found these products matching your search</b>
   <br><br>
  </dsp:oparam>
  <dsp:oparam name="output">

  <dsp:droplet name="RQLQueryForEach">
    <dsp:param name="skuId" param="element"/>
    <dsp:param name="repository" bean="/atg/commerce/catalog/ProductCatalog" />
    <dsp:param name="itemDescriptor" value="product"/>
    <dsp:param name="queryRQL" value="childSKUs INCLUDES :skuId  "/>
    <dsp:param bean="/atg/dynamo/transaction/TransactionManager"
      name="transactionManager"/>
    <dsp:oparam name="output">
      <%-- Display a link to the element: --%>
      <dsp:getvalueof id="urlStr" idtype="java.lang.String"
        param="element.template.url">
      <dsp:a page="<%=urlStr%>">
        <dsp:param name="id" param="element.repositoryId"/>
     <dsp:param name="navAction" value="jump"/>
     <dsp:param name="Item" param="element"/>
     <dsp:valueof param="element.displayName">No name</dsp:valueof>&nbsp;-
       &nbsp;<dsp:valueof param="element.description"/>
      </dsp:a>
      </dsp:getvalueof>
      <br>
     </dsp:oparam>
  </dsp:droplet>
  </dsp:oparam>
  <dsp:oparam name="empty">
    <b>There are no products matching your search</b>
    <p>
  </dsp:oparam>
</dsp:droplet>
Manufacturer and Text Input Search

The AdvProductSearch component is used for this search.

The advanced search functionality uses the SearchFormHandler but requires a slightly more complex properties file than the simple search Nucleus component. Advanced searches return only products because the additional search criteria are based on products only.

/atg/commerce/catalog/AdvProductSearch.properties

$class=atg.commerce.catalog.SearchFormHandler
$scope=session
doKeywordSearch=true
keywordsPropertyNames=keywords
doTextSearch=true
textSearchPropertyNames=description,displayName
doAdvancedSearch=true
advancedSearchPropertyNames=childSKUs
doHierarchicalSearch=true
ancestorCategoriesPropertyName=ancestorCategories
minScore=1
catalogTools=CatalogTools
itemTypes^=CatalogTools.productItemTypes
maxResultsPerPage=20
enableCountQuery=true

At the Motorprise configuration layer, we added a manufacturer property to this component:

# /atg/commerce/catalog/AdvProductSearch
advancedSearchPropertyNames+=manufacturer

As with the simple search, the SearchFormHandler is session scoped. Keyword and text searching are configured identically for both simple and advanced searches and they both use the same catalog. For the enumerated types used in the search (manufacturer), the possible values are inserted into <select> input tags on the form. These values are not coded into the form, but instead are retrieved from the catalog via the propertyValuesByType property of the SearchFormHandler.

The propertyValuesByType property is a map with property names for keys and arrays of all possible values for the given property. By default, no enumerated property information is available from the propertyValuesByType property of the SearchFormHandler. Instead, you must explicitly set the names of required enumerated properties in the search component’s advancedSearchPropertyNames property. In this case, the value is manufacturer.

Thus, when a search is performed in Motorprise the propertyValuesByType map returns two entries. One entry corresponds to the category item-type and the other entry corresponds to the product item-type. This is because these are the two item-descriptor types that are searched on in the ProductCatalog repository. Associated with the category entry will be a list of category repository items that were found in the search; similarly the product key will contain a list of product repository items.

By having the list of repository items split up by type, we are able to control how a repository item is displayed. For example, when a matching product repository item gets displayed, we want to link to product.jsp; for categories we want to link to category.jsp. That is why in the simple_search.jsp example shown above, there is a switch statement on the key property of the propertyValuesByType array.

The search form’s categories in the advanced search, manufacturer, is populated with valid choices for each item. These choices (<select> components) are loaded from the repository rather than coded into the page so that the page need not be changed when changes are made to the repository.

To display the list of all categories, we used the RepositoryValues servlet bean. It takes the input parameter itemDescriptorName that in this case is set to category because that is the type of repository item that we want to list. The servlet bean outputs an array of repository items that can be rendered using the ForEach component.

The following is part of the code for category search in advanced_search.jsp:

<!--search box starts here-->
  <table width=100% bgcolor="#FFCC66" border=0 cellpadding=0 cellspacing=0>
    <tr bgcolor="#666666">
      <td bgcolor="#666666" width=1><dsp:img src="../images/d.gif"
        width="1"/></td>
      <td colspan=2>
      <table cellpadding=3 cellspacing=0 border=0>
        <tr><td class=box-top>&nbsp;Advanced Product Search</td></tr>
      </table>
      </td>
    </tr>

    <tr>
      <td bgcolor="#666666" width=1><dsp:img src="../images/d.gif"
        width="1"/></td>
      <td>
      <table width=100% bgcolor="#FFCC66" border=0 cellpadding=0 cellspacing=0>
        <tr valign=top>
          <td width=50%>
            <dsp:form action="advanced_search.jsp" method="POST">
            <table width="100%" border="0" cellspacing="0" cellpadding="4"
              bgcolor="#FFCC66">
              <tr><td colspan=2><dsp:img src= "../images/d.gif"
                height="10"/></td></tr>

              <tr valign=top>
                <td width="15%" align="right"><span class=
                  "smallb">Text</span></td>
                <td><dsp:input bean="AdvProductSearch.searchInput" size="25"
                  type="text"/>&nbsp; <br> <span class="small">Use <b>AND</b> or
                  <b>OR</b> to separate words or phrases.</span>
                </td>
              </tr>
              <tr>
                <td align="right"><span class=smallb>Category</span></td>
                <td>
                <dsp:select bean="AdvProductSearch.hierarchicalCategoryId">
                  <dsp:option value=""/>-- All categories --
                  <dsp:droplet name="RepositoryValues">
                    <dsp:param name="itemDescriptorName" value="category"/>
                    <dsp:oparam name="output">
                      <dsp:droplet name="ForEach">
                        <dsp:param name="array" param="values"/>
                        <dsp:param name="sortProperties" value="+displayName"/>
                        <dsp:oparam name="output">
                          <dsp:getvalueof id="elem"
                           idtype="atg.repository.RepositoryItem" param="element">
                            <dsp:option value="<%=elem.getRepositoryId()%>"/>
                            <dsp:valueof param="element.displayName"/>
                          </dsp:getvalueof>
                        </dsp:oparam>
                      </dsp:droplet>
                    </dsp:oparam>
                  </dsp:droplet>
                </dsp:select>
                </td>
              </tr>
              <tr>
                <td align="right">&nbsp;<span class=
                  smallb>Manufacturer</span></td>
                <td>
                <dsp:select bean="AdvProductSearch.propertyValues.manufacturer">
                  <dsp:option value=""/>-- Any --
                  <dsp:droplet name="RepositoryValues">
                    <dsp:param name="itemDescriptorName" value="product"/>
                    <dsp:param name="propertyName" value="manufacturer"/>
                    <dsp:oparam name="output">
                      <dsp:droplet name="ForEach">
                        <dsp:param name="array" param="values"/>
                        <dsp:param name="sortProperties" value="+displayName"/>
                        <dsp:oparam name="output">

                          <dsp:getvalueof id="elemName" idtype="java.lang.String"
                            param="element.displayName">
                            <dsp:option value="<%=elemName%>"/>
                            <dsp:valueof param="element.displayName"/>
                          </dsp:getvalueof>

                        </dsp:oparam>
                      </dsp:droplet>
                    </dsp:oparam>
                  </dsp:droplet>
                </dsp:select>
                </td>
              </tr>
              <tr>
                <td>&nbsp;</td>
                <td><br>
                <dsp:input bean="AdvProductSearch.currentResultPageNum"
                  type="hidden" value="1"/>
                <input name="repositoryKey" type="hidden" value="<dsp:valueof
                  bean="/OriginatingRequest.requestLocale.locale"/>">
                <input name="noCrumbs" type="hidden" value="<dsp:valueof
             param="noCrumbs"/>">
                <dsp:input bean="AdvProductSearch.search" type="hidden"
                  value="Search"/>
                <dsp:input bean="AdvProductSearch.search" type="submit"
                  value="Search"/>
                </td>
              </tr>
              <tr>
                <td colspan=2>&nbsp;</td>
              </tr>
              <tr>
                <td>&nbsp;</td>
                <td><span class=smallb><dsp:a href="simple_search.jsp">
                       <dsp:param name="noCrumbs" param="noCrumbs"/>
                       Use simple search form</dsp:a></span>
                </td>
              </tr>
 
loading table of contents...