As you should be aware of, the shipment search is being used on several pages in the website and allows you to simply enter criteria in a simple textbox...similar to a Google search. This single text query allows you to enter a date range, an ASN ID, an invoice number, and more. Below is a discussion of how this works under the hood and how you can go about creating new ways of searching data.
SearchInterpreterBase
For each type of search that we want to implement, we need to create a class that extends SearchInterpreterBase. This is a simple implementation that simply asserts which search operators are allowed to be used. For instance, it is allowed to search by invoice number for shipments, but invoice number is invalid (at this time) for searching loads.
The interpreter really just needs this single method to instruct which operators to use:
protected override SearchOperatorBase<Shipment>[] GetOperators()
{
return new SearchOperatorBase<Shipment>[]{
new IntegerIDOperator<Shipment>(),
new InvoiceOperator<Shipment>(),
new BillOfLadingOperator<Shipment>(),
new DateRangeOperator<Shipment>(),
new ShipperOperator<Shipment>(),
new ShipLogixShipmentOperator<Shipment>()
};
}
SearchOperatorBase
For each method of searching, we need to create a class that extends SearchOperatorBase. These implementations are the brains behind our searches and contain any logic to parse information from the search query as well as actually invoke controller methods to perform the search.
The cool thing here is that we can reuse search operators for many different types of searches. For instance, both shipments and loads can be searched by the user typing in the ID of the entity. Both types of search can use the IntegerIDOperator class to parse a single (or a comma-separated list) of integer value(s).
SearchOperatorBase classes are slightly complicated in that they make use of .NET Generics to know which type of search they should be targeting. So, while you can reuse search operators for new types of searches, the operator will most likely need to be slightly modified (in the ExecuteSearch method) to perform the different searches that the operator supports.
Here is an example of a simple operator that currently only targets Shipment searches:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ProTrans.Enterprise.Entities.Enterprise.SearchInterpreters;
namespace ProTrans.Enterprise.Entities.Enterprise.SearchOperators
{
/// <summary>
/// Provides search where a bill of lading number is the basis of the search.
/// </summary>
/// <typeparam name="TResult">The type of result to search for.</typeparam>
public class BillOfLadingOperator<TResult> : SearchOperatorBase<TResult>
where TResult : ProTransEntityBase
{
public BillOfLadingOperator() : base(typeof(Shipment)) { }
/// <summary>
/// Gets or sets the bill of lading number to search with, or null.
/// </summary>
public string BillOfLadingNumber { get; set; }
/// <summary>
/// Gets the unique operator prefix that can be applied to searches to ensure
/// that only this operator executes (standard practice to append a ":" to the end of the prefix).
/// </summary>
protected override string UniqueOperatorPrefix
{
get
{
return "BOL:";
}
}
/// <summary>
/// Runs parsing against this search query, but does not perform any actual searching.
/// </summary>
/// <param name="searchText">The search query.</param>
/// <returns>True if no other operator should even execute a search against this query.</returns>
protected override bool InterpretSearch(string searchText)
{
// If a comma is found, then it is a comma-separated list and cannot a BOL search
if (!searchText.Contains(","))
BillOfLadingNumber = searchText;
return false;
}
/// <summary>
/// Performs the search for this operator.
/// </summary>
/// <returns>The list of results found.</returns>
protected override List<TResult> ExecuteSearch()
{
List<TResult> lstResults = new List<TResult>();
if (!string.IsNullOrEmpty(BillOfLadingNumber))
{
List<Shipment> lstTemp = ControllerShipment.ShipmentGetListByBillOfLadingNumber(BillOfLadingNumber);
foreach (Shipment temp in lstTemp)
lstResults.Add((TResult)(ProTransEntityBase)(temp));
}
return lstResults;
}
/// <summary>
/// Obtains a listing of search suggestions for the interpreted search.
/// </summary>
/// <returns>A list of suggestions that might help in narrowing down future queries.</returns>
public override List<SearchSuggestion> GetSuggestions()
{
List<SearchSuggestion> lst = new List<SearchSuggestion>();
if (!string.IsNullOrEmpty(BillOfLadingNumber))
{
lst.Add(new SearchSuggestion(UniqueOperatorPrefix + BillOfLadingNumber,
BillOfLadingNumber + " (Bill of Lading)"));
}
return lst;
}
}
}

No comments:
Post a Comment