BPMNFActory create properties panel

import {
    pick,
    assign,
    filter,
    forEach,
    isArray,
    isUndefined,
    has
} from 'min-dash';
import { is } from 'bpmn-js/lib/util/ModelUtil';
import { isAny } from 'bpmn-js/lib/features/modeling/util/ModelingUtil';
import {

    getBusinessObject
} from 'bpmn-js/lib/util/ModelUtil';
//util/ModelUtil

import {
    isExpanded,
    isEventSubProcess
} from 'bpmn-js/lib/util/DiUtil';

//../copy-paste/ModdleCopy
import { getPropertyNames } from 'bpmn-js/lib/features/copy-paste/ModdleCopy';
import * as _ModelCloneHelper from '../model/ModelCloneHelper';
import * as _ModelCloneUtils from '../model/ModelCloneUtils'
import * as _minDash from 'min-dash'
import * as _DiUtil from 'bpmn-js/lib/util/DiUtil'

function copyProperties(source, target, properties) {
    if (!isArray(properties)) {
        properties = [properties];
    }

    forEach(properties, function(property) {
        if (!isUndefined(source[property])) {
            target[property] = source[property];
        }
    });
}

var CUSTOM_PROPERTIES = [
    'cancelActivity',
    'instantiate',
    'eventGatewayType',
    'triggeredByEvent',
    'isInterrupting'
];


function toggeling(element, target) {

    var oldCollapsed = (
        element && has(element, 'collapsed') ? element.collapsed : !isExpanded(element)
    );

    var targetCollapsed;

    if (target && (has(target, 'collapsed') || has(target, 'isExpanded'))) {

        // property is explicitly set so use it
        targetCollapsed = (
            has(target, 'collapsed') ? target.collapsed : !target.isExpanded
        );
    } else {

        // keep old state
        targetCollapsed = oldCollapsed;
    }

    if (oldCollapsed !== targetCollapsed) {
        element.collapsed = oldCollapsed;
        return true;
    }

    return false;
}



/**
 * This module takes care of replacing BPMN elements
 */
export default function BpmnReplace(

    bpmnFactory, elementFactory, moddleCopy, replace, selection, modeling, eventBus
) {
    //start 123
    var helper = new _ModelCloneHelper.default(eventBus, bpmnFactory);

    //end 123
    /**
     * Prepares a new business object for the replacement element
     * and triggers the replace operation.
     *
     * @param  {djs.model.Base} element
     * @param  {Object} target
     * @param  {Object} [hints]
     *
     * @return {djs.model.Base} the newly created element
     */
    function replaceElement(element, target, hints) {

        hints = hints || {};

        var type = target.type,
            oldBusinessObject = element.businessObject;

        if (isSubProcess(oldBusinessObject)) {
            if (type === 'bpmn:SubProcess') {
                if (toggeling(element, target)) {

                    // expanding or collapsing process
                    modeling.toggleCollapse(element);

                    return element;
                }
            }
        }

        var newBusinessObject = bpmnFactory.create(type);

        var newElement = {
            type: type,
            businessObject: newBusinessObject
        };
        //akhil changes for unit testing of bots starts here
        if (newBusinessObject) {
            var elementProps = getPropertyNames(oldBusinessObject.$descriptor),
                newElementProps = getPropertyNames(newBusinessObject.$descriptor, true),
                copyProps = intersection(elementProps, newElementProps);
            assign(newBusinessObject, pick(target, CUSTOM_PROPERTIES));
            var properties = filter(copyProps, function(propertyName) {
                var propName = propertyName.replace(/bpmn:/, '');

                // copying event definitions, unless we replace
                if (propName === 'eventDefinitions') {
                    return hasEventDefinition(element, target.eventDefinitionType);
                }

                // retain loop characteristics if the target element
                // is not an event sub process
                if (propName === 'loopCharacteristics') {
                    return !isEventSubProcess(newBusinessObject);
                }

                // so the applied properties from 'target' don't get lost
                if (newBusinessObject.hasOwnProperty(propertyName)) {
                    return false;
                }

                if (propName === 'processRef' && target.isExpanded === false) {
                    return false;
                }

                if (propName === 'triggeredByEvent') {
                    return false;
                }
                return _ModelCloneUtils.IGNORED_PROPERTIES.indexOf(propName) === -1;

                // return true;
            });
            // newBusinessObject = helper.clone(oldBusinessObject, newBusinessObject, properties); // initialize custom BPMN extensions

            newBusinessObject = moddleCopy.copyElement(
                oldBusinessObject,
                newBusinessObject,
                properties
            );
            var custAttr = target.customAtttr;
            if (custAttr) {

                //ExtensionElementsHelper.addEntry(newBusinessObject,"camunda:Properties", {"name": "category", "value": "Java"});
                console.info("I am here");
                if (!newBusinessObject.extensionElements) {
                    console.info("Not extensions found");
                    newBusinessObject.extensionElements = bpmnFactory.create('bpmn:ExtensionElements');
                }
                var taskextvalues = newBusinessObject.extensionElements.values;
                if (!taskextvalues) {
                    taskextvalues = new Array();
                    newBusinessObject.extensionElements.values = taskextvalues
                }
                var taskproperties;
                for (var j = 0; j < taskextvalues.length; j++) {
                    if (taskextvalues[j].$type === "camunda:Properties") {
                        taskproperties = taskextvalues[j];
                        break;
                    }
                }
                if (!taskproperties) {
                    console.log(taskproperties, 'inside if')
                        taskproperties = bpmnFactory.create("camunda:Properties");
                        console.log(taskproperties, 'after calling create if')
                        // newBusinessObject.extensionElements.values.push(taskproperties);
                        // taskproperties.values = new Array();
                }

            }
        }
        //akhil changes for unit testing of bots end here

        // initialize special properties defined in target definition



        // initialize custom BPMN extensions
        if (target.eventDefinitionType) {

            // only initialize with new eventDefinition
            // if we did not set an event definition yet,
            // i.e. because we copied it
            if (!hasEventDefinition(newBusinessObject, target.eventDefinitionType)) {
                newElement.eventDefinitionType = target.eventDefinitionType;
                newElement.eventDefinitionAttrs = target.eventDefinitionAttrs;
            }
        }

        if (is(oldBusinessObject, 'bpmn:Activity')) {

            if (isSubProcess(oldBusinessObject)) {

                // no toggeling, so keep old state
                newElement.isExpanded = isExpanded(oldBusinessObject);
            }

            // else if property is explicitly set, use it
            else if (target && has(target, 'isExpanded')) {
                newElement.isExpanded = target.isExpanded;
            }

            // TODO: need also to respect min/max Size
            // copy size, from an expanded subprocess to an expanded alternative subprocess
            // except bpmn:Task, because Task is always expanded
            if ((isExpanded(oldBusinessObject) && !is(oldBusinessObject, 'bpmn:Task')) && newElement.isExpanded) {
                newElement.width = element.width;
                newElement.height = element.height;
            }
        }

        // remove children if not expanding sub process
        if (isSubProcess(oldBusinessObject) && !isSubProcess(newBusinessObject)) {
            hints.moveChildren = false;
        }

        // transform collapsed/expanded pools
        if (is(oldBusinessObject, 'bpmn:Participant')) {

            // create expanded pool
            if (target.isExpanded === true) {
                newBusinessObject.processRef = bpmnFactory.create('bpmn:Process');
            } else {

                // remove children when transforming to collapsed pool
                hints.moveChildren = false;
            }

            // apply same width and default height
            newElement.width = element.width;
            newElement.height = elementFactory._getDefaultSize(newBusinessObject).height;
        }

        newBusinessObject.name = oldBusinessObject.name;

        // retain default flow's reference between inclusive <-> exclusive gateways and activities
        if (
            isAny(oldBusinessObject, [
                'bpmn:ExclusiveGateway',
                'bpmn:InclusiveGateway',
                'bpmn:Activity'
            ]) &&
            isAny(newBusinessObject, [
                'bpmn:ExclusiveGateway',
                'bpmn:InclusiveGateway',
                'bpmn:Activity'
            ])
        ) {
            newBusinessObject.default = oldBusinessObject.default;
        }

        if (
            target.host &&
            !is(oldBusinessObject, 'bpmn:BoundaryEvent') &&
            is(newBusinessObject, 'bpmn:BoundaryEvent')
        ) {
            newElement.host = target.host;
        }

        newElement.di = {};

        // fill and stroke will be set to DI
        copyProperties(oldBusinessObject.di, newElement.di, [
            'fill',
            'stroke'
        ]);

        newElement = replace.replaceElement(element, newElement, hints);

        if (hints.select !== false) {
            selection.select(newElement);
        }

        return newElement;
    }

    this.replaceElement = replaceElement;
}

BpmnReplace.$inject = ['bpmnFactory', 'elementFactory', 'moddleCopy', 'replace', 'selection', 'modeling', 'eventBus'];


function isSubProcess(bo) {
    return is(bo, 'bpmn:SubProcess');
}

function hasEventDefinition(element, type) {

    var bo = getBusinessObject(element);

    return type && bo.get('eventDefinitions').some(function(definition) {
        return is(definition, type);
    });
}

/**
 * Compute intersection between two arrays.
 */
function intersection(a1, a2) {
    return a1.filter(function(el) {
        return a2.indexOf(el) !== -1;
    });
}```