File

projects/wms-framework/src/lib/domainservicesupport/DomainContext.ts

Extends

DomainContext

Index

Properties
Methods

Constructor

constructor(domainClient: DomainClient)
Parameters :
Name Type Optional
domainClient DomainClient No

Properties

Public angularHttp
Type : HttpClient
Inherited from DomainContext
Defined in DomainContext:54
Private endpoint
Type : string
Default value : ''
Inherited from DomainContext
Defined in DomainContext:60
Public EntityContainer
Default value : new EntityContainerHelper()
Inherited from DomainContext
Defined in DomainContext:52
Private inProgresRequest
Default value : new Set<string>()
Inherited from DomainContext
Defined in DomainContext:99
Public IsLoading
Type : boolean
Default value : false
Inherited from DomainContext
Defined in DomainContext:56
Protected pendingRequests
Type : any[]
Default value : []
Inherited from DomainContext
Defined in DomainContext:50
Public PropertyChanged
Type : function
Inherited from DomainContext
Defined in DomainContext:62
Public serviceName
Type : string
Default value : '/ClientBin/MyService.svc'
Inherited from DomainContext
Defined in DomainContext:59
Public servicesHost
Type : string
Default value : 'localhost'
Inherited from DomainContext
Defined in DomainContext:58
Protected triggerTimeout
Type : any
Default value : undefined
Inherited from DomainContext
Defined in DomainContext:51

Methods

Private convertJsonValueToPropertyType
convertJsonValueToPropertyType(propertyInfo: PropertyInfo, valueToAssign: any)
Inherited from DomainContext
Defined in DomainContext:233
Parameters :
Name Type Optional
propertyInfo PropertyInfo No
valueToAssign any No
Returns : any
Protected createGetOptions
createGetOptions()
Inherited from DomainContext
Defined in DomainContext:265

Creates the options object used to create a Get request

Returns : any

The get request Options object

Protected createHeaders
createHeaders()
Inherited from DomainContext
Defined in DomainContext:257

Creates the {@see HttpHeader} object used to make service calls.

Returns : HttpHeaders

the {

Protected CreateQuery
CreateQuery(methodName: string, parameters?: literal type, hasSideEffects: boolean, isComposable: boolean, classConstructor: IClassConstructor<T>)
Inherited from DomainContext
Defined in DomainContext:271
Type parameters :
  • T
Parameters :
Name Type Optional Default value
methodName string No
parameters literal type Yes
hasSideEffects boolean No true
isComposable boolean No false
classConstructor IClassConstructor<T> No null
Returns : EntityQuery<T>
Public Load
Load(query: EntityQuery, loadBehavior: LoadBehavior, flg: boolean, aClassConstructor: IClassConstructor<T>)
Inherited from DomainContext
Defined in DomainContext:101
Type parameters :
  • T
Parameters :
Name Type Optional
query EntityQuery<T> No
loadBehavior LoadBehavior No
flg boolean No
aClassConstructor IClassConstructor<T> No
Returns : LoadOperation<T>
Private mergeResults
mergeResults(entityName, resultSet, constructorClass)
Inherited from DomainContext
Defined in DomainContext:83
Parameters :
Name Optional
entityName No
resultSet No
constructorClass No
Returns : void
Protected processResponseResults
processResponseResults(results: unknown[], loadBehavior: LoadBehavior)
Inherited from DomainContext
Defined in DomainContext:167
Type parameters :
  • T
Parameters :
Name Type Optional
results unknown[] No
loadBehavior LoadBehavior No
Returns : void
Private processSubmitChangesValidResponse
processSubmitChangesValidResponse(response: any)
Inherited from DomainContext
Defined in DomainContext:345
Parameters :
Name Type Optional
response any No
Returns : void
Private registerNewElements
registerNewElements(addedElements: Map, changeSet: any[], id: number)
Inherited from DomainContext
Defined in DomainContext:323
Parameters :
Name Type Optional
addedElements Map<string | any[]> No
changeSet any[] No
id number No
Returns : number
Private registerUpdates
registerUpdates(changedEntities: string[], changesPayload: Map<string | Map<string, IPendingChange>>, changeSet: any[], id: number)
Inherited from DomainContext
Defined in DomainContext:367
Parameters :
Name Type Optional
changedEntities string[] No
changesPayload Map<string | Map<string, IPendingChange>> No
changeSet any[] No
id number No
Returns : number
Public SubmitChanges
SubmitChanges(callback?: (result?: SubmitOperation) => void, userData?: any)
Inherited from DomainContext
Defined in DomainContext:284
Parameters :
Name Type Optional
callback function Yes
userData any Yes
Returns : SubmitOperation
Protected ValidateMethod
ValidateMethod(methodName: string, p: any)
Inherited from DomainContext
Defined in DomainContext:402
Parameters :
Name Type Optional
methodName string No
p any No
Returns : void
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { catchError, map } from 'rxjs/operators';
import { forkJoin } from 'rxjs';
import {
  EntityContainerHelper,
  EntityQuery,
  EntityState,
  IPendingChange,
} from './EntitiesSupport';
import { LoadOperation, SubmitOperation } from './OperationsSupport';
import { Application } from '../basecomponentmodel/Application';
import { Uri } from '../baseframework/Uri';
import {
  PropertyInfo,
  ReflectionHelper,
} from '../baseframework/ReflectionSupport';
import { tryImplicitDeserialization } from '../baseframework/SerializationHelper';

/**
 * @wEnum System.ServiceModel.DomainServices.Client.LoadBehavior
 */
export enum LoadBehavior {
  RefreshCurrent,
}

export interface IClassConstructor<T> {
  new (): T;
}

/**
 * @wType System.ServiceModel.DomainServices.Client.DomainContext
 */
export class DomainContext {
  protected pendingRequests: any[] = [];
  protected triggerTimeout: any = undefined;
  public EntityContainer = new EntityContainerHelper();

  public angularHttp: HttpClient;

  public IsLoading: boolean = false;

  public servicesHost = 'localhost';
  public serviceName = '/ClientBin/MyService.svc';
  private endpoint: string = '';

  public PropertyChanged: (x: any, y: any) => void;

  constructor(private client?: any, private format?: string) {
    let urlSuffix: string = '';
    if (format) {
      urlSuffix = `/${format}/`;
    }
    this.servicesHost = window.location.origin.toString() + '/';
    if (client && client.uri && client.uri.url) {
      if (client.uri.url.startsWith('http')) {
        this.endpoint = client.uri.url + urlSuffix;
      } else {
        this.serviceName = '/ClientBin/' + client.uri.url;
        this.endpoint = `${this.servicesHost}${this.serviceName}${urlSuffix}`;
      }
    } else {
      this.serviceName = this.constructor.name.replace(/Client$/, '.svc');
      this.endpoint = `${this.servicesHost}${this.serviceName}/json/`;
    }
  }

  private mergeResults(entityName, resultSet, constructorClass) {
    var currentValues = EntityContainerHelper.entities[entityName];
    var index = {};
    var currentValuesLength = currentValues.length;
    var keyField = constructorClass['KeyField'] || 'UID';
    for (let i = 0; i < currentValuesLength; i++) {
      index[currentValues[i][keyField]] = currentValues[i];
    }
    for (let item of resultSet) {
      if (!(item[keyField] in index)) {
        currentValues.push(item);
      }
    }
    // EntityContainerHelper.entities[entityName] = resultSet;
  }

  private inProgresRequest = new Set<string>();

  public Load<T>(
    query: EntityQuery<T>,
    loadBehavior: LoadBehavior,
    flg: boolean,
    aClassConstructor: IClassConstructor<T>
  ): LoadOperation<T> {
    let resultLoadOp = new LoadOperation<T>();
    //let endpoint = this.servicesHost + this.serviceName + "/json/";
    if (!this.angularHttp) {
      this.angularHttp = Application.Current.angularHttpClient;
    }

    if (this.angularHttp) {
      const url = this.endpoint + query.getUrlFragment();
      if (this.inProgresRequest.has(url)) {
        return;
      } else {
        this.inProgresRequest.add(url);
      }
      let request = this.angularHttp
        .get(url, this.createGetOptions())
        .pipe(
          catchError((e, y) => {
            this.inProgresRequest.delete(url);
            console.error(e);
            return [];
          })
        )
        .pipe(
          map((result) => {
            this.inProgresRequest.delete(url);
            return {
              result: result,
              query: query,
              aClassConstructor: aClassConstructor,
              resultLoadOp: resultLoadOp,
            };
          })
        );
      this.pendingRequests.push(request);
      if (this.triggerTimeout === undefined) {
        this.triggerTimeout = setTimeout(() => {
          forkJoin(this.pendingRequests).subscribe((results) => {
            //Application.Current.displayLoader = false;
            this.IsLoading = true;
            EntityContainerHelper.changeTrackingEnabled = false;
            if (this.PropertyChanged) {
              this.PropertyChanged(null, { PropertyName: 'IsLoading' });
            }
            this.processResponseResults<T>(results, loadBehavior);
            this.IsLoading = false;
            EntityContainerHelper.changeTrackingEnabled = true;
            if (this.PropertyChanged) {
              this.PropertyChanged(null, { PropertyName: 'IsLoading' });
            }
            this.triggerTimeout = undefined;
            this.pendingRequests = [];
          });
        });
      }
    } else {
      console.error('HTTP Service not available');
    }
    return resultLoadOp;
  }

  protected processResponseResults<T>(
    results: unknown[],
    loadBehavior: LoadBehavior
  ) {
    for (let requestResultT of results) {
      var requestResult: any = requestResultT;
      let result = requestResult.result;
      let resultSet = [];
      for (let item of result[requestResult.query.methodName + 'Result']
        .RootResults) {
        var newObj = new requestResult.aClassConstructor();
        let classInfo = ReflectionHelper.getTypeInfo(
          requestResult.aClassConstructor
        );
        for (let propName of Object.keys(item)) {
          let propertyInfo = classInfo.getProperty(propName);
          let valueToAssign = item[propName];
          if (propertyInfo && propertyInfo.propertyType) {
            valueToAssign = this.convertJsonValueToPropertyType(
              propertyInfo,
              valueToAssign
            );
          }
          newObj[propName] = valueToAssign;
        }
        newObj.EntityState = EntityState.Unmodified;
        resultSet.push(newObj);
      }
      if (
        !(
          requestResult.aClassConstructor.name in EntityContainerHelper.entities
        ) ||
        loadBehavior == LoadBehavior.RefreshCurrent
      ) {
        EntityContainerHelper.entities[requestResult.aClassConstructor.name] =
          resultSet;
      } else {
        this.mergeResults(
          requestResult.aClassConstructor.name,
          resultSet,
          requestResult.aClassConstructor
        );
      }

      // process included results
      if (result[requestResult.query.methodName + 'Result'].IncludedResults) {
        for (let item of result[requestResult.query.methodName + 'Result']
          .IncludedResults) {
          if (EntityContainerHelper.cachedConstructors[item.__type]) {
            var ctor = EntityContainerHelper.cachedConstructors[item.__type];
            var newObj = new ctor();
            for (let propName of Object.keys(item)) {
              newObj[propName] = item[propName];
            }
            this.mergeResults(ctor.name, [newObj], ctor);
          }
        }
      }
      requestResult.resultLoadOp.Entities = resultSet;
      // process included results
      if (requestResult.resultLoadOp && requestResult.resultLoadOp.Completed) {
        requestResult.resultLoadOp.Completed(null, null);
      }
    }
  }

  private convertJsonValueToPropertyType(
    propertyInfo: PropertyInfo,
    valueToAssign: any
  ) {
    if (
      propertyInfo.propertyType?.innerType == window.Date &&
      typeof valueToAssign === 'string'
    ) {
      valueToAssign = new Date(
        parseInt(valueToAssign.replace(/^\/Date\((.*)-.*$/, '$1'))
      );
    } else {
      valueToAssign = tryImplicitDeserialization(
        valueToAssign,
        propertyInfo.propertyType?.innerType
      );
    }
    return valueToAssign;
  }

  /**
   * Creates the {@see HttpHeader} object used to make service calls.
   * @returns the {@see HttpHeader} object used to call the service
   */
  protected createHeaders(): HttpHeaders {
    return new HttpHeaders();
  }

  /**
   * Creates the options object used to create a Get request
   * @returns The get request Options object
   */
  protected createGetOptions(): any {
    return {
      headers: this.createHeaders(),
    };
  }

  protected CreateQuery<T>(
    methodName: string,
    parameters?: { [x: string]: any },
    hasSideEffects: boolean = true,
    isComposable: boolean = false,
    classConstructor: IClassConstructor<T> = null
  ): EntityQuery<T> {
    let result = new EntityQuery<T>(methodName);
    result.parameters = parameters;
    result.Constructor = classConstructor;
    return result;
  }

  public SubmitChanges(
    callback?: (result: SubmitOperation) => void,
    userData?: any
  ): SubmitOperation {
    let addedElements = EntityContainerHelper.addedElements;
    var changesPayload = EntityContainerHelper.pendingChanges;

    let changedEntities = [...changesPayload.keys()];
    if (changedEntities.length > 0 || addedElements.size > 0) {
      var changeSet = [];
      let id = 0;
      id = this.registerUpdates(changedEntities, changesPayload, changeSet, id);
      id = this.registerNewElements(addedElements, changeSet, id);

      let changeSetToSend = { changeSet: changeSet };

      this.angularHttp
        .post(
          this.servicesHost + this.serviceName + '/Json/SubmitChanges',
          changeSetToSend
        )
        .pipe(
          catchError((e) => {
            alert('Internal error submitting changes');
            console.error(e);
            return [];
          })
        )
        .subscribe((response) => {
          this.processSubmitChangesValidResponse(response);
        });
    }

    EntityContainerHelper.pendingChanges.clear();
    EntityContainerHelper.addedElements.clear();

    return new SubmitOperation();
  }

  private registerNewElements(
    addedElements: Map<string, any[]>,
    changeSet: any[],
    id: number
  ) {
    for (let [entityName, newElements] of addedElements) {
      for (let newElement of newElements) {
        var changeObj = {};
        changeObj['__type'] = entityName + ':#' + newElement.entityNamespace;

        newElement.copyEntityObjectDataInto(changeObj);

        changeSet.push({
          Id: id++,
          Entity: changeObj,
          Operation: 2 /*add*/,
        });
      }
    }
    return id;
  }

  private processSubmitChangesValidResponse(response: any) {
    let submitResult = response['SubmitChangesResult'];
    let errorMessages = 'Validation errors:';
    let hasErrors = false;
    if (submitResult instanceof Array) {
      for (let obj of submitResult) {
        let validationErrors = obj['ValidationErrors'];
        if (validationErrors instanceof Array) {
          hasErrors = true;
          for (let error of validationErrors) {
            errorMessages = errorMessages + '\n' + error['Message'];
          }
        }
      }
    } else {
      console.log('SubmitChanges finished');
    }
    if (hasErrors) {
      alert(errorMessages);
    }
  }

  private registerUpdates(
    changedEntities: string[],
    changesPayload: Map<string, Map<string, IPendingChange>>,
    changeSet: any[],
    id: number
  ) {
    for (let entityName of changedEntities) {
      var localChanges = changesPayload.get(entityName);
      for (let registeredChangeChangeKey of localChanges.keys()) {
        let registeredChange = localChanges.get(registeredChangeChangeKey);
        var changeObj = {};

        changeObj['__type'] =
          entityName + ':#' + registeredChange.entityNamespace;
        let originalObj = {
          __type: entityName + ':#' + registeredChange.entityNamespace,
        };
        for (let originalObjProp in registeredChange.originalData) {
          originalObj[originalObjProp] =
            registeredChange.originalData[originalObjProp];
        }

        registeredChange.entity.copyEntityObjectDataInto(changeObj);

        changeSet.push({
          Id: id++,
          Entity: changeObj,
          OriginalEntity: originalObj,
          Operation: 3 /*update*/,
        });
      }
    }
    return id;
  }

  protected ValidateMethod(methodName: string, p: any) {}
}

/**
 * @wType System.ServiceModel.DomainServices.Client.ApplicationServices.AuthenticationDomainContextBase
 */
export class AuthenticationDomainContextBase extends DomainContext {
  constructor(private domainClient: DomainClient) {
    super(domainClient);
  }
}

/**
 * @wType System.ServiceModel.DomainServices.Client.DomainClient
 */
export class DomainClient {}

/**
 * WebDomainClient class
 *
 * @export
 * @class WebDomainClient
 * @extends {DomainClient}
 * @template T
 * @wType System.ServiceModel.DomainServices.Client.WebDomainClient`1
 */
export class WebDomainClient<T> extends DomainClient {
  constructor(private uri: Uri) {
    super();
  }
}

result-matching ""

    No results matching ""