using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Data;
using System.Collections;
using System.Collections.Specialized;
using UDDI.API;
using UDDI.API.ServiceType;
using UDDI.API.Binding;
using UDDI.API.Service;
using UDDI.API.Business;
namespace UDDI.VisualStudio
{
//
// Simple internal class to hold information about a Service.
//
internal class ServiceResultInfo
{
public string serviceName;
public string serviceKey;
}
//
// Simple internal class to hold information about a Business.
//
internal class BusinessResultInfo
{
public string businessName;
public ArrayList serviceResultInfos;
public BusinessResultInfo()
{
serviceResultInfos = new ArrayList();
}
}
///
/// ResultsList is a ASP.NET control that will display the results of our search.
/// TODO this class does a lot of work, consider moving some of the rendering out into a separate classs
///
public class ResultsList : UserControl
{
//
// This function is defined in search.aspx.
//
private static string EXPAND_JSCRIPT = "toggle(this, '{0}');";
private static string PLUS_SRC = "../images/plus.gif";
private ArrayList results;
private int currentPage;
///
/// Use this function to populate a ResultsList instance with raw values from the database.
/// The results from the database must be returned in the following order:
///
/// businessName
/// businessKey
/// serviceName
/// serviceKey
///
/// ParseResults will use indexes to read these values from the SqlDataReaderAccessor so this
/// order must be maintained from the database.
///
/// Reader returned from the database.
///
public int ParseResults( SqlDataReaderAccessor values )
{
results = new ArrayList();
string currentBusinessName = null;
string lastBusinessName = null;
BusinessResultInfo businessInfo = new BusinessResultInfo();
while( values.Read() )
{
currentBusinessName = values.GetString( 0 );
ServiceResultInfo serviceInfo = new ServiceResultInfo();
serviceInfo.serviceName = values.GetString( 2 );
serviceInfo.serviceKey = values.GetString( 3 );
if (null != lastBusinessName && false == lastBusinessName.Equals( currentBusinessName ) )
{
results.Add( businessInfo );
businessInfo = new BusinessResultInfo();
}
businessInfo.businessName = currentBusinessName;
businessInfo.serviceResultInfos.Add( serviceInfo );
lastBusinessName = currentBusinessName;
}
//
// Add our last one.
//
if( businessInfo.serviceResultInfos.Count > 0 )
{
results.Add( businessInfo );
}
return results.Count;
}
///
/// Overridden from UserControl. This method will get called when its time to render our control.
///
/// Passed in from ASP.NET, use it to write our HTML
protected override void Render( HtmlTextWriter writer )
{
//
// Figure out our current page and number of results
//
try
{
currentPage = Int32.Parse( Request[ StateParamNames.CurrentPage ] );
}
catch
{
currentPage = 1;
}
RenderResults( writer );
}
///
/// This method actually does the work of rendering our results.
///
/// Passed from Render()
private void RenderResults( HtmlTextWriter writer )
{
//
// TODO should this be in the PagingControl?
//
//
// Determine the start and end indexes of the results that we'll display. These values are based
// on the current page that we are displaying.
//
int startIndex;
int endIndex;
GetStartIndex( out startIndex, out endIndex );
if( endIndex > results.Count )
{
endIndex = results.Count;
}
if( startIndex < endIndex )
{
//
// Render everything in table.
//
writer.AddAttribute( HtmlTextWriterAttribute.Width, "95%" );
writer.RenderBeginTag( HtmlTextWriterTag.Table );
//
// Render the range of results.
//
RenderRange( writer, startIndex, endIndex );
//
// Render our paging information
//
RenderPaging( writer );
writer.RenderEndTag(); // TABLE
}
}
private void RenderPaging( HtmlTextWriter writer )
{
writer.RenderBeginTag( HtmlTextWriterTag.Tr );
writer.AddAttribute( HtmlTextWriterAttribute.Class, "pagesCell" );
writer.AddAttribute( HtmlTextWriterAttribute.Colspan, "3");
writer.RenderBeginTag( HtmlTextWriterTag.Td );
PagingRenderer paging = new PagingRenderer( results.Count, currentPage , Request.Path);
paging.Render( writer );
writer.RenderEndTag(); // Td
writer.RenderEndTag(); // Tr
}
///
/// Renders a range of businesses.
///
/// Writer to use to write our HTML.
/// The beginning of our range of businesses to render.
/// The end of our range of businesses to render.
private void RenderRange( HtmlTextWriter writer, int startIndex, int endIndex )
{
while( startIndex < endIndex )
{
BusinessResultInfo businessResultInfo = ( BusinessResultInfo )results[startIndex];
//
// Render the business name.
//
writer.RenderBeginTag( HtmlTextWriterTag.Tr );
writer.AddAttribute( HtmlTextWriterAttribute.Colspan, "3" );
writer.RenderBeginTag( HtmlTextWriterTag.Td );
writer.RenderBeginTag( HtmlTextWriterTag.B );
writer.Write( Server.HtmlEncode( businessResultInfo.businessName ) );
writer.RenderEndTag();
writer.RenderEndTag();
writer.RenderEndTag();
foreach( ServiceResultInfo serviceResultInfo in businessResultInfo.serviceResultInfos )
{
writer.RenderBeginTag( HtmlTextWriterTag.Tr );
//
// Write a placeholder cell so we can indent each service info under its
// business name.
//
writer.AddAttribute( HtmlTextWriterAttribute.Class, "space_cell" );
writer.RenderBeginTag( HtmlTextWriterTag.Td );
writer.Write( " " );
writer.RenderEndTag();
//
// Render the service.
//
RenderServiceInfo( serviceResultInfo, writer );
writer.RenderEndTag();
}
startIndex++;
}
}
///
/// This method renders an individual service.
///
/// The service to render.
/// Writer to use to write our HTML.
private void RenderServiceInfo( ServiceResultInfo serviceInfo, HtmlTextWriter writer )
{
//
// Render a plus/minus tag. We will use the service key of this service to name
// our hidden details panel.
//
writer.AddAttribute( HtmlTextWriterAttribute.Class, "expand_cell" );
writer.AddAttribute( HtmlTextWriterAttribute.Align, "center" );
writer.RenderBeginTag( HtmlTextWriterTag.Td );
RenderExpandTag( writer, serviceInfo.serviceKey );
writer.RenderEndTag();
//
// Render the name of the service. Use the first name that is registered with the service.
//
writer.AddAttribute( HtmlTextWriterAttribute.Width, "100%" );
writer.RenderBeginTag( HtmlTextWriterTag.Td );
writer.Write( Server.HtmlEncode( serviceInfo.serviceName ) );
writer.RenderEndTag();
writer.RenderEndTag();
//
// Render a details panel for the service that is initially hidden.
//
writer.AddAttribute( HtmlTextWriterAttribute.Id, serviceInfo.serviceKey );
writer.AddAttribute( HtmlTextWriterAttribute.Style, "display:none" );
writer.RenderBeginTag( HtmlTextWriterTag.Tr );
//
// Skip 2 cells
//
writer.RenderBeginTag( HtmlTextWriterTag.Td );
writer.RenderEndTag();
writer.RenderBeginTag( HtmlTextWriterTag.Td );
writer.RenderEndTag();
writer.AddAttribute( HtmlTextWriterAttribute.Id, serviceInfo.serviceKey + "_detailsPanel" );
writer.RenderBeginTag( HtmlTextWriterTag.Td );
RenderServiceDetail( serviceInfo.serviceKey, writer );
writer.RenderEndTag();
}
///
/// Renders the +/- sign used to show or hide the details of a service.
///
/// Writer to use to write our HTML.
/// The service key is used to uniquely identify this HTML component. We need to do this for the script
/// that is located in search.aspx.
///
private void RenderExpandTag( HtmlTextWriter writer, string serviceKey)
{
string jscript = EXPAND_JSCRIPT.Replace( "{0}", serviceKey );
writer.AddAttribute( HtmlTextWriterAttribute.Style, "cursor:hand" );
writer.AddAttribute( HtmlTextWriterAttribute.Src, ResultsList.PLUS_SRC );
writer.AddAttribute( HtmlTextWriterAttribute.Onclick, jscript );
writer.RenderBeginTag( HtmlTextWriterTag.Img );
writer.RenderEndTag();
}
private void RenderServiceDetail( string serviceKey, HtmlTextWriter writer )
{
//
// Get details for this service
//
StringCollection serviceKeys = new StringCollection();
serviceKeys.Add( serviceKey );
ServiceDetail serviceDetail = new ServiceDetail();
serviceDetail.Get( serviceKeys );
//
// We will only get the first one
//
BusinessService businessService = serviceDetail.BusinessServices[ 0 ];
writer.AddAttribute( HtmlTextWriterAttribute.Width, "100%" );
writer.AddAttribute( HtmlTextWriterAttribute.Class, "serviceDetailOuterTable" );
writer.RenderBeginTag( HtmlTextWriterTag.Table );
//
// Render the business descriptions if there is one
//
writer.RenderBeginTag( HtmlTextWriterTag.Tr );
writer.RenderBeginTag( HtmlTextWriterTag.Td );
writer.RenderBeginTag( HtmlTextWriterTag.B );
writer.Write( Localization.GetString( "AWR_SERVICE_DESCRIPTION" ) );
writer.RenderEndTag(); // B
writer.RenderEndTag(); // Td
writer.RenderEndTag(); // Tr
foreach( Description description in businessService.Descriptions )
{
writer.RenderBeginTag( HtmlTextWriterTag.Tr );
writer.RenderBeginTag( HtmlTextWriterTag.Td );
writer.Write( Server.HtmlEncode( description.Value ) );
writer.RenderEndTag(); // Td
writer.RenderEndTag(); // Tr
}
//
// Render each binding in the service that has a WSDL file associated with it
//
writer.RenderBeginTag( HtmlTextWriterTag.Tr );
writer.RenderBeginTag( HtmlTextWriterTag.Td );
writer.RenderBeginTag( HtmlTextWriterTag.B );
writer.Write( Localization.GetString( "AWR_BINDINGS" ) );
writer.RenderEndTag(); // B
writer.RenderEndTag(); // Td
writer.RenderEndTag(); // Tr
foreach( BindingTemplate bindingTemplate in businessService.BindingTemplates )
{
//
// Render each binding in a row
//
writer.RenderBeginTag( HtmlTextWriterTag.Tr );
writer.RenderBeginTag( HtmlTextWriterTag.Td );
writer.AddAttribute( HtmlTextWriterAttribute.Width, "100%" );
writer.AddAttribute( HtmlTextWriterAttribute.Class, "accessPointTable" );
writer.RenderBeginTag( HtmlTextWriterTag.Table );
//
// Render the access point
//
writer.RenderBeginTag( HtmlTextWriterTag.Tr );
writer.RenderBeginTag( HtmlTextWriterTag.Td );
writer.RenderBeginTag( HtmlTextWriterTag.B );
writer.Write( Localization.GetString( "AWR_ACCESS_POINT" ) );
writer.RenderEndTag(); // B
writer.RenderEndTag(); // Td
writer.RenderEndTag(); // Tr
writer.RenderBeginTag( HtmlTextWriterTag.Tr );
writer.RenderBeginTag( HtmlTextWriterTag.Td );
writer.Write( Server.HtmlEncode( bindingTemplate.AccessPoint.Value ) );
writer.RenderEndTag(); // Td
writer.RenderEndTag(); // Tr
//
// Render the descriptions.
//
writer.RenderBeginTag( HtmlTextWriterTag.Tr );
writer.RenderBeginTag( HtmlTextWriterTag.Td );
writer.RenderBeginTag( HtmlTextWriterTag.B );
writer.Write( Localization.GetString( "AWR_DESCRIPTION" ) );
writer.RenderEndTag(); // B
writer.RenderEndTag(); // Td
writer.RenderEndTag(); // Tr
foreach( Description description in bindingTemplate.Descriptions )
{
writer.RenderBeginTag( HtmlTextWriterTag.Tr );
writer.RenderBeginTag( HtmlTextWriterTag.Td );
writer.Write( Server.HtmlEncode( description.Value ) );
writer.RenderEndTag(); // Td
writer.RenderEndTag(); // Tr
//
// Render an empty row between descriptions
//
writer.RenderBeginTag( HtmlTextWriterTag.Tr );
writer.RenderBeginTag( HtmlTextWriterTag.Td );
writer.RenderEndTag(); // Tr
writer.RenderEndTag(); // Td
}
//
// Render the WSDL files. We are assuming that any overview doc urls are urls to WSDL files
//
writer.RenderBeginTag( HtmlTextWriterTag.Tr );
writer.RenderBeginTag( HtmlTextWriterTag.Td );
writer.RenderBeginTag( HtmlTextWriterTag.B );
writer.Write( Localization.GetString( "AWR_ID" ) );
writer.RenderEndTag(); // B
writer.RenderEndTag(); // Td
writer.RenderEndTag(); // Tr
int wsdlCount = 0;
foreach( TModelInstanceInfo instanceInfo in bindingTemplate.TModelInstanceInfos )
{
//
// Get the tModel related to this instance.
//
TModel tModel = new TModel( instanceInfo.TModelKey );
//
// We don't want any exceptions ruining the rest of our display
//
try
{
//
// Get details for this tModel.
//
tModel.Get();
bool isWsdlSpec = false;
foreach( KeyedReference keyedReference in tModel.CategoryBag )
{
if( true == keyedReference.KeyValue.Equals( UDDI.Constants.UDDITypeTaxonomyWSDLSpecKeyValue ) &&
true == keyedReference.TModelKey.ToLower().Equals( UDDI.Constants.UDDITypeTaxonomyTModelKey ) )
{
isWsdlSpec = true;
break;
}
}
//
// If this tModel has an overview doc, then consider that document as the link to the
// WSDL file.
//
if( true == isWsdlSpec &&
null != tModel.OverviewDoc.OverviewURL &&
tModel.OverviewDoc.OverviewURL.Length > 0 )
{
//
// Render the WSDL link
//
writer.RenderBeginTag( HtmlTextWriterTag.Tr );
writer.RenderBeginTag( HtmlTextWriterTag.Td );
//
// Render the arrow image.
//
writer.AddAttribute( HtmlTextWriterAttribute.Src, "../images/orange_arrow_right.gif" );
writer.RenderBeginTag( HtmlTextWriterTag.Img );
writer.Write(" ");
writer.RenderEndTag(); // Img
//
// Make the overview URL a hyper link
//
writer.AddAttribute( HtmlTextWriterAttribute.Href, tModel.OverviewDoc.OverviewURL );
writer.RenderBeginTag( HtmlTextWriterTag.A );
writer.Write( tModel.OverviewDoc.OverviewURL );
writer.RenderEndTag(); // A
//
// Render the first description if there is one
//
if( tModel.OverviewDoc.Descriptions.Count > 0 )
{
writer.Write( " - " );
writer.Write( tModel.OverviewDoc.Descriptions[0].Value );
}
wsdlCount++;
writer.RenderEndTag(); // Td
writer.RenderEndTag(); // Tr
}
}
catch
{
//
// Intentionally empty.
//
}
}
//
// If there were no WSDL files registered, render a message saying so.
//
if( 0 == wsdlCount )
{
writer.RenderBeginTag( HtmlTextWriterTag.Tr );
writer.RenderBeginTag( HtmlTextWriterTag.Td );
writer.Write( Localization.GetString( "AWR_NO_WSDLS" ) );
writer.RenderEndTag(); // Td
writer.RenderEndTag(); // Tr
}
writer.RenderEndTag(); // TABLE
writer.RenderEndTag(); // Td
writer.RenderEndTag(); // Tr
}
writer.RenderEndTag(); // TABLE
}
///
/// Returns the start index of the result we are supposed to show, taking into account paging.
///
/// The start index.
/// The 'raw' end index; that is not taking into account whether this value exceeds the number of pages we have.
private void GetStartIndex( out int startIndex, out int rawEndIndex )
{
startIndex = ( currentPage - 1) * Constants.NumResultsPerPage;
rawEndIndex = startIndex + Constants.NumResultsPerPage;
}
}
}