ATG’s basic search form handlers are based on the class atg.repository.servlet.SearchFormHandler. This class accepts arguments that allow you to filter search results to include only those repository items that are affiliated with specified sites. When using a search form handler based on this class, or one of its subclasses such as atg.commerce.catalog.custom.CatalogSearchFormhandler, you can set one of the following search form handler properties to filter search results:

In addition to siteIds and siteScope, you can also set the parameter activeSitesOnly. When this parameter is set to true, search results are further limited to active sites only. When it is set to false, results from both active and disabled sites are returned.

SearchFormHandler includes a method, generateResultSet(), that builds and executes the search query. If necessary, this method will take the siteIds and siteScope parameters into account, as shown in this code sample:

if (q != null) {
   // Generate site context filters using the generateSiteFilter() method.
   // This method uses the siteIds and siteScope parameters to create the filters.
   ContextFilteringRules siteFilter = generateSiteFilter();

   // Add site context filters to the query
      if (siteFilter != null) {
         q = view.getQueryBuilder().addContextMembershipFilters(q, siteFilter);
   }
   // Execute the query
   RepositoryItem[] items = view.executeQuery(q, 0, endIndex, null);

Subclasses that override generateResultSet() and need to be site-aware should implement similar logic to create and execute queries that incorporate site context filters. Commerce Reference Store implements such a subclass in atg.projects.store.catalog.StoreSearchFormHandler. The /atg/commerce/catalog/ProductSearch.properties component uses this class to search the Catalog Repository for product items. The remainder of this section shows several examples of how to use the ProductSearch component in a JSP page. These examples are simplified versions of the store.war/search/gadgets/simpleSearch.jsp page found in Commerce Reference Store.

Example 1: This code sample shows a product search form that uses the siteIds property to filter search results. In this example, siteIds is set to include the current site and sites that share a shopping cart with the current site.

<dsp:importbean bean="/atg/dynamo/droplet/multisite/SharingSitesDroplet" />
<dsp:importbean bean="/atg/dynamo/droplet/ForEach" />
<dsp:importbean bean="/atg/multisite/Site"/>
<dsp:importbean bean="/atg/commerce/catalog/ProductSearch"/>
<dsp:getvalueof id="contextroot" idtype="java.lang.String"
  bean="/OriginatingRequest.contextPath"/>

<dsp:form action="${contextroot}/search/searchResults.jsp" method="post"
  id="simpleSearch" formid="simplesearchform">

    <%-- Search input control --%>
    <dsp:input bean="ProductSearch.searchInput" type="text" value="" />

    <%-- Get the list of sites that share a shopping cart with the
    current site. --%>
    <dsp:droplet name="SharingSitesDroplet">
      <dsp:param name="shareableTypeId" value="atg.ShoppingCart"/>
      <dsp:param name="excludeInputSite" value="true"/>

      <%-- Loop through the sites that share a shopping cart and render labels
      and checkboxes for them. --%>
      <dsp:oparam name="output">
        <dsp:droplet name="ForEach">
          <dsp:param name="array" param="sites"/>
          <dsp:setvalue param="site" paramvalue="element"/>

            <%-- Display a checkbox and name for the current site first. --%>
            <dsp:oparam name="outputStart">
              <dsp:input bean="ProductSearch.siteIds" type="checkbox"
                         beanvalue="Site.id" checked="true" id="currentStore"/>
              <label for="currentStore">
                <dsp:valueof bean="Site.name"/>
              </label>
            </dsp:oparam>

            <%-- Display the other sites that share shopping cart with the current
            site. --%>
            <dsp:oparam name="output">
                <dsp:input bean="ProductSearch.siteIds" type="checkbox"
                           paramvalue="site.id" id="otherStore" checked="false"/>
                <label for="otherStore">
                  <dsp:valueof param="site.name"/>
                </label>
            </dsp:oparam>
        </dsp:droplet>
      </dsp:oparam>

      <%-- If there are no shared sites, include the current site only and
      don't display checkboxes. --%>
      <dsp:oparam name="empty">
        <dsp:input bean="ProductSearch.siteIds" type="hidden"
                   beanvalue="Site.id"/>
      </dsp:oparam>
    </dsp:droplet>

    <%-- Display the search form's submit button. --%>
    <dsp:input bean="ProductSearch.search" type="submit"  value="Search"/>

</dsp:form>

Example 2: In this example, the product search form returns results from all active sites.

<dsp:importbean bean="/atg/dynamo/droplet/ForEach" />
<dsp:importbean bean="/atg/multisite/Site"/>
<dsp:importbean bean="/atg/commerce/catalog/ProductSearch"/>
<dsp:getvalueof id="contextroot" idtype="java.lang.String"
bean="/OriginatingRequest.contextPath"/>

<dsp:form action="${contextroot}/search/searchResults.jsp" method="post"
id="simpleSearch" formid="simplesearchform">

    <%-- Search input control --%>
    <dsp:input bean="ProductSearch.searchInput" type="text" value="" />

    <%-- Get the list of all active sites --%>
    <dsp:getvalueof var="sites" bean="/atg/multisite/SiteManager.activeSites"/>

        <%-- Loop through the all active sites --%>
        <dsp:droplet name="ForEach">
          <dsp:param name="array" value="${sites}"/>
          <dsp:setvalue param="site" paramvalue="element"/>

            <%-- Display a checkbox and name for the current site first. --%>
            <dsp:oparam name="outputStart">
              <dsp:input bean="ProductSearch.siteIds" type="checkbox"
                         beanvalue="Site.id" checked="true" id="currentStore"/>
              <label for="currentStore">
                <dsp:valueof bean="Site.name"/>
              </label>
            </dsp:oparam>

            <%-- Display the other sites that share a shopping cart with the
            current site. --%>
            <dsp:oparam name="output">
              <dsp:getvalueof var="siteId" param="site.id"/>
              <dsp:getvalueof var="currentSiteId" bean="Site.id"/>
              <%-- Check that the site is not the current site. If so, display
              its name and checkbox so it can be included in the search. --%>
              <c:if test="${siteId != currentSiteId}">
                <dsp:input bean="ProductSearch.siteIds" type="checkbox"
                           paramvalue="site.id" id="otherStore" checked="false"/>
                <label for="otherStore">
                  <dsp:valueof param="site.name"/>
                </label>
              </c:if>
            </dsp:oparam>
        </dsp:droplet>

    <%-- Display the search form's submit button --%>
    <dsp:input bean="ProductSearch.search" type="submit"  value="Search"/>

</dsp:form>

Example 3: This code sample shows a product search form that uses the siteScope property to filter search results. In this example, siteScope is set to a shareable type ID so that only products from sites that share a shopping cart with the current site are returned.

<dsp:importbean bean="/atg/commerce/catalog/ProductSearch"/>
  <dsp:getvalueof id="contextroot" idtype="java.lang.String"
                  bean="/OriginatingRequest.contextPath"/>

  <dsp:form action="${contextroot}/search/searchResults.jsp" method="post"
            id="simpleSearch" formid="simplesearchform">

    <%-- Search input control --%>
    <dsp:input bean="ProductSearch.searchInput" type="text" value="" />

    <%-- Specify the shopping cart shareable type ID in the siteScope
    property. --%>
    <dsp:input bean="ProductSearch.siteScope" type="hidden"
               value="atg.ShoppingCart" />

    <%-- Display the search form's submit button. --%>
    <dsp:input bean="ProductSearch.search" type="submit"  value="Search"/>

  </dsp:form>