File

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

Description

Defines an object that serializes elements to xml format understood by SOAP tehcnology.

Index

Methods

Methods

Private getEntityProperties
getEntityProperties(entity)

Gets all the entity properties to serialize. Because the entity must be decorated with the Entity decorator it is required to look one level up

Parameters :
Name Optional Description
entity No

the entity to extract properties for

Returns : {}
Private mustSkipSerialization
mustSkipSerialization(value: any)

Indicates whether a property must be serialized or not. For now Date set to null must not be serialized

Parameters :
Name Type Optional Description
value any No

the value to test for

Returns : boolean

{boolean} true if value must be serialized

Private serialize
serialize(value: any)

Serializes a scalar value object.

Parameters :
Name Type Optional Description
value any No

the object to serilize

Returns : any

{*}

Private serializeCollection
serializeCollection(collection: ObservableCollection<unknown>)

Serializes an { ObservableCollection } object by serializing everyone of its elements.

Parameters :
Name Type Optional Description
collection ObservableCollection<unknown> No

the collection to serialize

Returns : string

{string}

Private serializeCollectionParam
serializeCollectionParam(paramName: string, collection: ObservableCollection<unknown>)
Parameters :
Name Type Optional
paramName string No
collection ObservableCollection<unknown> No
Returns : string
Private serializeComplexParameter
serializeComplexParameter(paramName: string, entity: any)

Serializes a complex value (an entity such as Employee). Entities to be serilized must have the getScheme and getName methods defined.

Parameters :
Name Type Optional Description
paramName string No

Name of the parameter to serialize

entity any No

the value of the paramter to serialize

Returns : string

{string}

Private serializeEntity
serializeEntity(entity: any)

Serializes a comple entity object by generating an xml tag for every entity property.

Parameters :
Name Type Optional Description
entity any No

the object to serialize

Returns : string
Private serializeEntityProperty
serializeEntityProperty(propName: string, value: any)

Serializes and entity property

Parameters :
Name Type Optional Description
propName string No

name of the property to serializer

value any No

value to serialize

Returns : string
Private serializeParameter
serializeParameter(paramName: string, paramValue: any)

Serializes a single parameter element. A simple serialized parameter looks like 4

Parameters :
Name Type Optional Description
paramName string No

Name of the parameter to serialize

paramValue any No

value of the parameter to serialize

Returns : string
Private serializeProperty
serializeProperty(value: any)

Serializes a given property value. Currently there is support of scalar values, ObserverableCollections objects and other Entity objects.

Parameters :
Name Type Optional
value any No
Returns : string

{string}

toXml
toXml(requestArgs: any[])

Converts a collection of arguments to xml soap representation.

Parameters :
Name Type Optional Description
requestArgs any[] No

the objects to be converted as {name, value} object

Returns : string

{string} the xml representing the args serialized

import { SupportDateTime } from '../baseframework';
import { ObservableCollection } from '../baseframework/collections';
import { IAsyncResult } from './AsyncResultSupport';
import { Message } from './Message';
import { MessageHeader } from './MessageHeader';
import { SoapAsyncResult } from './soapAsyncResult';

export class SoapMessage extends Message {
  /**
   * Namespace of the service being called
   *
   * @type {string}
   * @memberof SoapMessage
   */
  public Namespace: string;

  /**
   * Creates an instance of SoapMessage that will be sent to the given baseUrl
   * @param {string} baseUrl
   * @memberof SoapMessage
   */
  constructor(
    baseUrl: string,
    methodName: string,
    namespace: string,
    contract: string
  ) {
    super();
    this.BaseUrl = baseUrl;
    this.methodName = methodName;
    this.Namespace = namespace;
    this.Headers.add(
      new MessageHeader('Accept', '', 'text/xml; charset=utf-8')
    );
    this.Headers.add(
      new MessageHeader('Content-Type', '', 'text/xml; charset=utf-8')
    );
    this.Headers.add(
      new MessageHeader(
        'SOAPAction',
        '',
        `${namespace}/${contract}/${methodName}`
      )
    );
    this.responseType = 'text';
  }

  /**
   * Builds the url of this SoapMessage by returning the base url only
   *
   * @return {*}  {string}
   * @memberof SoapMessage
   */
  public buildUrl(): string {
    return this.BaseUrl;
  }

  /**
   * Builds the message body to be sent to the server side.  The message is compliant with
   * Soap Envelope
   *
   * @return {*}
   * @memberof SoapMessage
   */
  public buildBody() {
    const bodyStart =
      '<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body>';
    const bodyEnd = '</s:Body></s:Envelope>';

    let serializer: SoapMessageSerializer = new SoapMessageSerializer();
    let parameters = serializer.toXml(this.requestArgs);
    return `${bodyStart}<${this.methodName} xmlns="${this.Namespace}">${parameters}</${this.methodName}>${bodyEnd}`;
  }

  // inherited
  public buildPostResult(userData: any, result: any): IAsyncResult {
    let operationResult: SoapAsyncResult = new SoapAsyncResult();
    operationResult.AsyncState = userData;
    operationResult.IsCompleted = true;
    operationResult.resultData = {
      message: this,
      d: typeof result?.d !== 'undefined' ? result.d : result,
    };
    return operationResult;
  }
}

/**
 *  Defines an object that serializes elements to xml format understood by SOAP tehcnology.
 *
 * @class SoapMessageSerializer
 */
class SoapMessageSerializer {
  /**
   * Converts a collection of arguments to xml soap representation.
   *
   * @param {any[]} requestArgs  the objects to be converted as {name, value} object
   * @return {*}  {string} the xml representing the args serialized
   * @memberof SoapMessageSerializer
   */
  toXml(requestArgs: any[]): string {
    let parameters = '';
    for (const arg of requestArgs) {
      parameters = parameters + this.serializeParameter(arg.name, arg.value);
    }
    return parameters;
  }

  /**
   * Serializes a single parameter element.  A simple serialized parameter looks like
   * <param1>4</param1>
   *
   * @private
   * @param {string} paramName Name of the parameter to serialize
   * @param {*} paramValue value of the parameter to serialize
   * @return {*}
   * @memberof SoapMessageSerializer
   */
  private serializeParameter(paramName: string, paramValue: any) {
    if (paramValue instanceof ObservableCollection) {
      return this.serializeCollectionParam(
        paramName,
        paramValue as ObservableCollection<unknown>
      );
    }
    if (paramValue && paramValue.getName && paramValue.getScheme) {
      return this.serializeComplexParameter(paramName, paramValue);
    } else {
      let valueSerialized = this.serialize(paramValue);
      return `<${paramName}>${valueSerialized}</${paramName}>`;
    }
  }

  /**
   * Serializes a scalar value object.
   *
   * @private
   * @param {*} value  the object to serilize
   * @return {*}  {*}
   * @memberof SoapMessageSerializer
   */
  private serialize(value: any): any {
    switch (typeof value) {
      case 'string':
      case 'number':
      case 'boolean':
        return value;
      default:
        if (value instanceof Date) {
          return value.toISOString();
        }
    }
    return null;
  }

  private serializeCollectionParam(
    paramName: string,
    collection: ObservableCollection<unknown>
  ): string {
    if (collection.count > 0 && (collection.getItem(0) as any).getScheme) {
      let properties = '';
      collection.forEach(
        (entity) => (properties += this.serializeEntity(entity))
      );
      let scheme = (collection.getItem(0) as any).getScheme();
      return `<${paramName} xmlns:d4p1="${scheme}" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">${properties}</${paramName}>`;
    }
    return '';
  }
  /**
   * Serializes a complex value (an entity such as Employee).  Entities to be serilized must have the
   * getScheme and getName methods defined.
   *
   * @private
   * @param {string} paramName Name of the parameter to serialize
   * @param {*} entity the value of the paramter to serialize
   * @return {*}  {string}
   * @memberof SoapMessageSerializer
   */
  private serializeComplexParameter(paramName: string, entity: any): string {
    let properties = '';
    properties = this.serializeEntity(entity);
    return `<${paramName} xmlns:d4p1="${entity.getScheme()}" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">${properties}</${paramName}>`;
  }

  /**
   * Serializes a comple entity object by generating an xml tag for every entity property.
   * @param entity the object to serialize
   * @returns
   */
  private serializeEntity(entity: any): string {
    let properties: string = '';
    for (let propName of this.getEntityProperties(entity)) {
      let value: any = entity[propName];
      properties += this.serializeEntityProperty(propName, value);
    }
    return `<d4p1:${entity.getName()}>${properties}</d4p1:${entity.getName()}>`;
  }

  /**
   * Serializes and entity property
   *
   * @private
   * @param {string} propName name of the property to serializer
   * @param {*} value value to serialize
   * @return {*}
   * @memberof SoapMessageSerializer
   */
  private serializeEntityProperty(propName: string, value: any) {
    if (!this.mustSkipSerialization(value)) {
      if (value !== null) {
        let valueAsStr: string = this.serializeProperty(value);
        return `<d4p1:${propName}>${valueAsStr}</d4p1:${propName}>`;
      } else {
        return `<d4p1:${propName} i:nil="true" />`;
      }
    }
    return '';
  }

  /**
   * Indicates whether a property must be serialized or not.
   * For now Date set to null must not be serialized
   *
   * @private
   * @param {*} value the value to test for
   * @return {*}  {boolean} true if value must be serialized
   * @memberof SoapMessageSerializer
   */
  private mustSkipSerialization(value: any): boolean {
    return value instanceof Date && SupportDateTime.IsMinValue(value);
  }

  /**
   * Serializes a given property value.  Currently there is support of scalar values, ObserverableCollections objects
   * and other Entity objects.
   *
   * @private
   * @param {*} value
   * @return {*}  {string}
   * @memberof SoapMessageSerializer
   */
  private serializeProperty(value: any): string {
    let valueAsStr: string = '';
    if (value instanceof ObservableCollection) {
      valueAsStr = this.serializeCollection(
        value as ObservableCollection<unknown>
      );
    } else if (value && value.getName && value.getScheme) {
      valueAsStr = this.serializeEntity(value);
    } else {
      valueAsStr = this.serialize(value);
    }
    return valueAsStr;
  }

  /**
   * Serializes an { ObservableCollection } object by serializing everyone of its elements.
   *
   * @private
   * @param {ObservableCollection<unknown>} collection the collection to serialize
   * @return {*}  {string}
   * @memberof SoapMessageSerializer
   */
  private serializeCollection(
    collection: ObservableCollection<unknown>
  ): string {
    let valueAsString: string = '';
    for (const e of collection) {
      valueAsString += this.serializeEntity(e);
    }
    return valueAsString;
  }

  /**
   * Gets all the entity properties to serialize.  Because the entity must be decorated with the {@link Entity}
   * decorator it is required to look one level up
   *
   * @private
   * @param {*} entity the entity to extract properties for
   * @memberof SoapMessageSerializer
   */
  private *getEntityProperties(entity) {
    // go to prototype of up because of annotation
    let entityPrototype = Object.getPrototypeOf(Object.getPrototypeOf(entity));
    let descriptors = Object.getOwnPropertyDescriptors(entityPrototype);
    for (var propName in descriptors) {
      let propDefinition = descriptors[propName];
      if (propDefinition.get && propDefinition.set) {
        yield propName;
      }
    }
  }
}

result-matching ""

    No results matching ""