Untitled

mail@pastecode.io avatar
unknown
typescript
a year ago
6.0 kB
5
Indexable
Never
import { Injectable } from '@angular/core';
import { xml2json } from 'xml-js';

import { ProcessChildEnum } from '../../enums/process-child.enum';
import {
  InputTypesMappedToVariableTypes,
  VariableTypesMappedToInputTypes
} from '../../enums/variable-types.enum';
import { FormVariableField } from '../../models/form-variable-field.model';
import { FormVariableValidators } from '../../models/form-variable-validators.model';
import { FormVariableSelectOptions } from '../../models/form-variables-select-options.model';

@Injectable({
  providedIn: 'root'
})
export class FormVariablesAdapterService {

  parseXMLToJSON(
    bpmn20Xml: string,
    processChild: ProcessChildEnum,
    taskDefinitionKey
  ): FormVariableField[] | any {

    const jsonResult = this.getJSON(bpmn20Xml);
    const process = this.getProcess(jsonResult);

    if (!process) {
      return null;
    }

    const childResult = this.getProcessChild(process, processChild);

    if (!childResult) {
      return null;
    }

    let extensionElementsFound = null;

    if (processChild === ProcessChildEnum.userTask) {
      const userTaskFound = this.getUserTask(childResult, taskDefinitionKey);

      if (!userTaskFound) {
        return null;
      }

      extensionElementsFound = this.getExtensionElements(userTaskFound, processChild);
    } else {
      extensionElementsFound = this.getExtensionElements(childResult, processChild);
    }

    if (!extensionElementsFound) {
      return null;
    }

    const formDataElementsFound = this.getFormDataElements(extensionElementsFound);
    if (!formDataElementsFound) {
      return null;
    }

    return !formDataElementsFound ? null : this.getFormFields(formDataElementsFound);
  }

  parseToVariableType(key: string): string {
    return InputTypesMappedToVariableTypes[key];
  }

  parseToTypeForm(name: string): string {
    return VariableTypesMappedToInputTypes[name];
  }

  validateFormValues(name: string, value) {
    const types = {
      'checkbox': (value !== '' && value !== null),
      'date': value !== 'Invalid date',
      'select': (value !== '' && value !== null)
    };

    if (name !== 'text') {
      return (types[name] || false);
    }

    return false;
  }

  private buildValidators(name: string, config = null) {

    const parseConfig = config ? parseInt(config) : null;

    const validators = {
      isRequired: true,
      isReadonly: true,
      minLength: parseConfig,
      maxLength: parseConfig,
      min: parseConfig,
      max: parseConfig
    };

    return validators[name];
  }

  private formatNameValidators(name: string) {
    const attributesValidators = {
      minlength: 'minLength',
      maxlength: 'maxLength',
      required: 'isRequired',
      readonly: 'isReadonly'
    };

    return attributesValidators[name] ?? name;
  }

  private getJSON(bpmn20Xml: string): string {
    return JSON.parse(xml2json(bpmn20Xml, { compact: false, spaces: 4 }));
  }

  private getProcess(jsonResult): any {
    return jsonResult.elements[0].elements.find(({ name }) => name === 'bpmn:process');
  }

  private getProcessChild(process, nameChild: string): any {
    return process.elements.filter(({ name }) => name === nameChild);
  }

  private getUserTask(userTasksFiltered, taskDefinitionKey): any {
    return userTasksFiltered.find(({ attributes: { id } }) => id === taskDefinitionKey);
  }

  private getExtensionElements(elementFound, processChild: string): any {
    const filter = 'bpmn:extensionElements';

    const actions = {
      [ProcessChildEnum.startEvent]: () => {
        return elementFound[0].elements.find(({ name }) => name === filter);
      },
      [ProcessChildEnum.userTask]: () => {
        return elementFound.elements.find(({ name }) => name === filter);
      }
    };

    const action = actions[processChild];
    if (action) {
      return action();
    }
  }

  private getFormDataElements(extensionElementsFound): any {
    return extensionElementsFound.elements
      .find(({ name }) => name === 'camunda:formData').elements;
  }

  private getFormFields(formDataElementsFound: any): FormVariableField[] {

    return formDataElementsFound.map(elementFound => {
      return this.handleVariable(elementFound);
    });
  }

  private getSelectOptions = (type: string, elements: any, id: any) => {
    return type === 'enum'
      ? this.handleSelectOptions(elements, id)
      : null;
  }

  private getValidations(elements: any) {
    const validators: FormVariableValidators = { };

    const validatorsFound = elements.find(({ name }) => name === 'camunda:validation')?.elements;

    if (!validatorsFound) {
      return null;
    }

    validatorsFound.map( ({ attributes }) => {
      const name = this.formatNameValidators(attributes.name);
      validators[name] = this.buildValidators(name, attributes.config);
    });

    return validators;
  }

  private handleVariable(formDataElement): FormVariableField {
    const { attributes, elements } = formDataElement;
    let validators: FormVariableValidators = null;

    if (elements) {
      validators = this.getValidations(elements);
    }

    return {
      defaultFieldName: attributes.id,
      label: attributes.label,
      type: this.parseToTypeForm(attributes.type),
      selectOptions: this.getSelectOptions(attributes.type, elements, attributes.id),
      validators,
      value: null
    };
  }

  private handleSelectOptions(elementsOptions, idTask): FormVariableSelectOptions[] {
    return elementsOptions
      .filter(element => element.name === 'camunda:value')
      .map(element => {
        return {
          value: element.attributes.id,
          label: element.attributes.name,
          idFormVariable: idTask
        };
      });
  }
}