File

projects/wms-framework/src/lib/wcfserviceinvocationsupport/HttpBasicBinding.ts

Description

Defines a custom {CommunicationBinding} object that interacts with a server by using standard SOAP messages.

Extends

CommunicationBinding

Index

Properties
Methods

Constructor

constructor(serviceNamespace: string, contract: string)

Creates an instance of HttpBasicBinding that is able to consume Soap messages from the given service http://server/IMyContract/MethodName

Parameters :
Name Type Optional Description
serviceNamespace string No

Namespace of the service to consume data from

contract string No

contract name of the soap service, for instance in following sample http://server/IMyContract/MethodName

Properties

contract
Type : string
Elements
Type : BindingElementCollection
Default value : new BindingElementCollection()
serviceNamespace
Type : string
Public CloseTimeout
Type : any
Default value : null
Inherited from CommunicationBinding
Public EndpointSuffix
Type : string
Inherited from CommunicationBinding

EndpointSuffix property

Public OpenTimeout
Type : any
Default value : null
Inherited from CommunicationBinding
Public ReceiveTimeout
Type : any
Default value : null
Inherited from CommunicationBinding
Public SendTimeout
Type : any
Default value : null
Inherited from CommunicationBinding
Public UsePost
Type : boolean
Inherited from CommunicationBinding

UsePost property

Methods

Private convertBooleanValue
convertBooleanValue(value: any)

Converts the given value to a boolean value

Parameters :
Name Type Optional Description
value any No

the value to be converted

Returns : boolean

{boolean}

Private convertCollectionValue
convertCollectionValue(prefix: string, value: any, collectionElementType: any)

Converts a list of elements to be set to a ObservableCollection object.

Parameters :
Name Type Optional Description
prefix string No

the namespace prefix of the custom data

value any No

the value to be converted

collectionElementType any No
Returns : any

{*}

Private convertDateValue
convertDateValue(value: any)

Converts the given value to a Date object

Parameters :
Name Type Optional Description
value any No

the value to be converted

Returns : Date

a Date object

Private convertNumberValue
convertNumberValue(value: any)

Converts the given value to a number one

Parameters :
Name Type Optional Description
value any No

The value to be converted

Returns : number

{Number}

Private convertStringValue
convertStringValue(value: any)

Converts the given value to a string one

Parameters :
Name Type Optional Description
value any No

the value to be converted

Returns : string

{string}

CreateBindingElements
CreateBindingElements()
Inherited from CommunicationBinding
CreateMessage
CreateMessage(baseUrl: string, methodName: string, args: any[])
Inherited from CommunicationBinding
Parameters :
Name Type Optional
baseUrl string No
methodName string No
args any[] No
Returns : Message
CreateResponseMessage
CreateResponseMessage(result: any, classConstructor?: any)
Inherited from CommunicationBinding
Parameters :
Name Type Optional
result any No
classConstructor any Yes
Returns : Message
Private extractNs
extractNs(data: any)

Extracts the Envelope prefix, for the following definition it returns 's': xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"

Parameters :
Name Type Optional Description
data any No

the json representation of a soap xml

Returns : string

{string} a namespace prefix.

Private extractServiceNs
extractServiceNs(data: any, namespace: string)

Extracts the service namespace attribute. For the folowing service namespace it returns 'a': xmlns:a="http://myserver.com/MyService/2011/11"

Parameters :
Name Type Optional Description
data any No

the json object representation of an xml

namespace string No

the namespace to get the prefix for

Returns : string

a string with the prefix value for the given namespace

Private extractValue
extractValue(prefix: string, value: any, property: PropertyInfo)

Extracts the response value for a given property. Value is extracted depending on the property datatype, current support datatypes are String, Number, Boolean, Date and ObservableCollection

Parameters :
Name Type Optional Description
prefix string No

the namespace prefix of the custom data

value any No

the value to be converted

property PropertyInfo No

the property to be assigned

Returns : any

{*}

Private fillElement
fillElement(instance: any, element: any, prefix: string, classConstructor: any)

Filles the given instance with all properties gien in element object.

Parameters :
Name Type Optional Description
instance any No

the new object to fill

element any No

the json object containing the properties to set in instance

prefix string No

the namespace prefix

classConstructor any No
Returns : void
Private isNull
isNull(value)

Checks if the given value matches the explicit null one.

Parameters :
Name Optional Description
value No

the value to test for

Returns : boolean

{boolean}

Private processElements
processElements(data: any, classConstructor: any, prefix?: string)

Creates a new object of the given class constructor and sets its properties to the values in data.

Parameters :
Name Type Optional Description
data any No

the json value containing the object properties

classConstructor any No

the constructor of the resulting object.

prefix string Yes
Returns : any[]

{*} a new object created using the given constructor

Private processEnvelopeBody
processEnvelopeBody(message: SoapMessage, namespaceVar: string, body: any, classConstructor?: any)

Process the sopa body section of an evelop. As a result it returns a new {SoapMessage} object containing the results given in the body. Body Sample: <s:Body> <a:Employee> <a:Name>Olman ...

Parameters :
Name Type Optional Description
message SoapMessage No

The {SoapMessage} body containing the server response.

namespaceVar string No
body any No

the actual Soap message body containing the result data

classConstructor any Yes

Type of the elements to be loaded (Employee in above sample).

Returns : SoapMessage

a {SoapMessage} containing the loaded response.

import { Application } from '../basecomponentmodel/Application';
import { Exception } from '../baseframework';
import { ObservableCollection } from '../baseframework/collections';
import {
  PropertyInfo,
  ReflectionHelper,
} from '../baseframework/ReflectionSupport';
import { xml2json } from '../utils/XmlUtils';
import { BindingElementCollection } from './channels';
import { CommunicationBinding } from './CommunicationSupport';
import { Message } from './Message';
import { SoapMessage } from './SoapMessage';

/*****************************************************************************
 * Copyright (C) Mobilize.Net <info@mobilize.net> - All Rights Reserved
 *
 * This file is part of the Mobilize Frameworks, which is
 * proprietary and confidential.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of Mobilize.Net Corporation.
 * The intellectual and technical concepts contained herein are
 * proprietary to Mobilize.Net Corporation and may be covered
 * by U.S. Patents, and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Mobilize.Net Corporation.
 ******************************************************************************/
/**
 * Defines a custom {CommunicationBinding} object that interacts with a server by using
 * standard SOAP messages.
 *
 * @export
 * @class HttpBasicBinding
 * @extends {CommunicationBinding}
 */
export class HttpBasicBinding extends CommunicationBinding {
  #serviceNamespace: string;
  #contract: string;

  /**
   * Creates an instance of HttpBasicBinding that is able to consume Soap messages from
   * the given service
   * @param {string} serviceNamespace Namespace of the service to consume data from
   * @param {string} contract contract name of the soap service, for instance in following sample
   * http://server/IMyContract/MethodName
   * @memberof HttpBasicBinding
   */
  constructor(serviceNamespace: string, contract: string) {
    super();
    this.#serviceNamespace = serviceNamespace;
    this.#contract = contract;
  }

  Elements: BindingElementCollection = new BindingElementCollection();

  //inherited
  CreateMessage(baseUrl: string, methodName: string, args: any[]): Message {
    let message: SoapMessage = new SoapMessage(
      baseUrl,
      methodName,
      this.#serviceNamespace,
      this.#contract
    );
    message.requestArgs = args ?? [];
    return message;
  }

  //inherited
  CreateResponseMessage(result: any, classConstructor?: any): Message {
    /* istanbul ignore else */
    if (result.resultData) {
      let data =
        typeof result.resultData.d === 'undefined'
          ? result.resultData
          : result.resultData.d;
      let message: SoapMessage = result.resultData.message;
      /* istanbul ignore else */
      if (message) {
        let jsonData: any = xml2json(data);
        let namespaceVar = this.extractNs(jsonData);
        /* istanbul ignore else */
        if (namespaceVar) {
          let envelope = jsonData[`${namespaceVar}:Envelope`];
          /* istanbul ignore else */
          if (envelope) {
            return this.processEnvelopeBody(
              message,
              namespaceVar,
              envelope[`${namespaceVar}:Body`],
              classConstructor
            );
          }
        }
      }
    }
    return null;
  }

  /**
   * Process the sopa body section of an evelop.  As a result it returns a new {SoapMessage} object containing
   * the results given in the body.
   * Body Sample:
   * <s:Body>
   *   <GetAllEmployeesResponse xmlns="http://myserver.com/MyService/2011/11">
   *     <GetAllEmployeesResult xmlns:a="http://myserver.com/MyService/2011/11" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
   *       <a:Employee>
   *           <a:Name>Olman</a:Name>
   *			...
   *
   * @private
   * @param {SoapMessage} message  The {SoapMessage} body containing the server response.
   * @param {*} body the actual Soap message body containing the result data
   * @param {*} [classConstructor] Type of the elements to be loaded (Employee in above sample).
   * @return {*} a {SoapMessage} containing the loaded response.
   * @memberof HttpBasicBinding
   */
  private processEnvelopeBody(
    message: SoapMessage,
    namespaceVar: string,
    body: any,
    classConstructor?: any
  ): SoapMessage {
    /* istanbul ignore else */
    if (body) {
      let response = body[`${message.methodName}Response`];
      /* istanbul ignore else */
      if (response) {
        let resultElement = response[`${message.methodName}Result`];
        if (classConstructor) {
          message.result = new ObservableCollection(
            this.processElements(resultElement, classConstructor)
          );
        } else {
          message.result = isNaN(resultElement)
            ? resultElement
            : parseInt(resultElement);
        }
      } else {
        throw new Exception(body[`${namespaceVar}:Fault`]['faultstring']['_']);
      }
      return message;
    }
  }

  /**
   * Creates a new object of the given class constructor and sets its properties to the values
   * in data.
   *
   * @private
   * @param {*} data the json value containing the object properties
   * @param {*} classConstructor the constructor of the resulting object.
   * @return {*}  {*} a new object created using the given constructor
   * @memberof HttpBasicBinding
   */
  private processElements(
    data: any,
    classConstructor: any,
    prefix?: string
  ): any[] {
    let tempInstance = new classConstructor();
    if (!prefix) {
      let scheme = tempInstance.getScheme();
      prefix = this.extractServiceNs(data, scheme);
    }
    data = data[`${prefix}:${tempInstance.getName()}`];

    let result = [];
    if (data instanceof Array) {
      let elements: any[] = data;
      elements.forEach((element) => {
        let instance = new classConstructor();
        result.push(instance);
        this.fillElement(instance, element, prefix, classConstructor);
      });
    } else if (data) {
      let instance = new classConstructor();
      this.fillElement(instance, data, prefix, classConstructor);
      result.push(instance);
    }
    return result;
  }

  /**
   * Filles the given instance with all properties gien in element object.
   *
   * @private
   * @param {*} instance the new object to fill
   * @param {*} element the json object containing the properties to set in instance
   * @param {string} prefix the namespace prefix
   * @memberof HttpBasicBinding
   */
  private fillElement(
    instance: any,
    element: any,
    prefix: string,
    classConstructor: any
  ) {
    let prefixLen = prefix.length + 1; // plus ":"
    let classInfo = ReflectionHelper.getTypeInfo(classConstructor);
    for (const e in element) {
      let name = e.substr(prefixLen);
      instance[name] = this.extractValue(
        prefix,
        element[e],
        classInfo.getProperty(name)
      );
    }
  }

  /**
   * Extracts the response value for a given property.  Value is extracted depending on the property
   * datatype, current support datatypes are String, Number, Boolean, Date and ObservableCollection
   *
   * @private
   * @param {string} prefix the namespace prefix of the custom data
   * @param {*} value the value to be converted
   * @param {PropertyInfo} property the property to be assigned
   * @return {*}  {*}
   * @memberof HttpBasicBinding
   */
  private extractValue(
    prefix: string,
    value: any,
    property: PropertyInfo
  ): any {
    /* istanbul ignore else */
    if (this.isNull(value)) {
      return null;
    }
    switch (property.propertyType.FullName) {
      case 'String':
        return this.convertStringValue(value);
      case 'Number':
        return this.convertNumberValue(value);
      case 'Boolean':
        return this.convertBooleanValue(value);
      case 'Date':
        return this.convertDateValue(value);
      case 'ObservableCollection':
        return this.convertCollectionValue(
          prefix,
          value,
          property.collectionGenericType
        );
    }
    return value;
  }

  /**
   * Converts a list of elements to be set to a ObservableCollection object.
   *
   * @private
   * @param {string} prefix the namespace prefix of the custom data
   * @param {*} value the value to be converted
   * @param {*} collectionElementType
   * @return {*}  {*}
   * @memberof HttpBasicBinding
   */
  private convertCollectionValue(
    prefix: string,
    value: any,
    collectionElementType: any
  ): any {
    /* istanbul ignore else */
    if (collectionElementType) {
      let collection = new ObservableCollection();
      let newElement = this.processElements(
        value,
        collectionElementType,
        prefix
      );
      collection.addRange(newElement);
      return collection;
    }
    return value;
  }

  /**
   * Converts the given value to a Date object
   * @param value the value to be converted
   * @returns a Date object
   */
  private convertDateValue(value: any): Date {
    return new Date(Date.parse(value));
  }

  /**
   * Converts the given value to a boolean value
   *
   * @private
   * @param {*} value the value to be converted
   * @return {*}  {boolean}
   * @memberof HttpBasicBinding
   */
  private convertBooleanValue(value: any): boolean {
    return value === 'true';
  }

  /**
   * Converts the given value to a number one
   *
   * @private
   * @param {*} value The value to be converted
   * @return {*}  {Number}
   * @memberof HttpBasicBinding
   */
  private convertNumberValue(value: any): number {
    return Number.parseFloat(value);
  }

  /**
   * Converts the given value to a string one
   *
   * @private
   * @param {*} value the value to be converted
   * @return {*}  {string}
   * @memberof HttpBasicBinding
   */
  private convertStringValue(value: any): string {
    return value as string;
  }

  /**
   * Checks if the given value matches the explicit null one.
   *
   * @private
   * @param {*} value the value to test for
   * @return {*}  {boolean}
   * @memberof HttpBasicBinding
   */
  private isNull(value): boolean {
    return value.$ && value['$']['i:nil'] === 'true';
  }

  /**
   * Extracts the service namespace attribute.  For the folowing service namespace it returns 'a':
   * xmlns:a="http://myserver.com/MyService/2011/11"
   *
   * @private
   * @param {*} data the json object representation of an xml
   * @param {string} namespace the namespace to get the prefix for
   * @return {string} a string with the prefix value for the given namespace
   * @memberof HttpBasicBinding
   */
  private extractServiceNs(data: any, namespace: string): string {
    let sns = undefined;
    let namespaces = data['$'];
    /* istanbul ignore else */
    if (namespaces) {
      for (const e in namespaces) {
        /* istanbul ignore else */
        if (namespaces[e] === namespace) {
          sns = e.substr(6);
          break;
        }
      }
    }
    return sns;
  }

  /**
   * Extracts the Envelope prefix, for the following definition it returns 's':
   * xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
   *
   * @private
   * @param {*} data the json representation of a soap xml
   * @return {*}  {string} a namespace prefix.
   * @memberof HttpBasicBinding
   */
  private extractNs(data: any): string {
    let envelope: string = undefined;
    let ns: string = undefined;
    // extract main object
    for (const element in data) {
      envelope = element;
      break;
    }
    // extract the "$" element containing the namespace defintion
    /* istanbul ignore else */
    if (envelope && data[envelope] && data[envelope]['$']) {
      for (const e in data[envelope]['$']) {
        ns = e.substr(6);
        break;
      }
    }
    return ns;
  }

  //inherited
  CreateBindingElements(): BindingElementCollection {
    return this.Elements;
  }
}

result-matching ""

    No results matching ""