"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.WorkflowModelValidator = void 0;
/********************************************************************************
 * Copyright (c) 2022-2023 STMicroelectronics and others.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the Eclipse
 * Public License v. 2.0 are satisfied: GNU General Public License, version 2
 * with the GNU Classpath Exception which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 ********************************************************************************/
const server_1 = require("@eclipse-glsp/server");
const inversify_1 = require("inversify");
const graph_extension_1 = require("../graph-extension");
let WorkflowModelValidator = class WorkflowModelValidator {
    validate(elements) {
        const markers = [];
        for (const element of elements) {
            if (element instanceof graph_extension_1.TaskNode) {
                markers.push(...this.validateTaskNode(element));
            }
            else if (element instanceof graph_extension_1.ActivityNode) {
                if (element.nodeType === 'decisionNode') {
                    markers.push(...this.validateDecisionNode(element));
                }
                else if (element.nodeType === 'mergeNode') {
                    markers.push(...this.validateMergeNode(element));
                }
            }
            if (element.children) {
                markers.push(...this.validate(element.children));
            }
        }
        return markers;
    }
    validateTaskNode(taskNode) {
        const markers = [];
        const automated = this.validateTaskNode_isAutomated(taskNode);
        if (automated) {
            markers.push(automated);
        }
        const upperCase = this.validateTaskNode_labelStartsUpperCase(taskNode);
        if (upperCase) {
            markers.push(upperCase);
        }
        return markers;
    }
    validateTaskNode_isAutomated(taskNode) {
        if (taskNode.taskType === 'automated') {
            return { kind: server_1.MarkerKind.INFO, description: 'This is an automated task', elementId: taskNode.id, label: 'Automated task' };
        }
        return undefined;
    }
    validateTaskNode_labelStartsUpperCase(taskNode) {
        const gCompartment = taskNode.children.find(child => child instanceof server_1.GCompartment);
        if (gCompartment) {
            const gLabels = gCompartment.children.filter(child => child instanceof server_1.GLabel).map(element => element);
            if (gLabels.length > 0 && gLabels[0].text.charAt(0) === gLabels[0].text.charAt(0).toLowerCase()) {
                return {
                    kind: server_1.MarkerKind.WARNING,
                    description: 'Task node names should start with upper case letters',
                    elementId: taskNode.id,
                    label: 'Task node label in upper case'
                };
            }
        }
        return undefined;
    }
    validateDecisionNode(decisionNode) {
        const markers = [];
        const oneIncoming = this.validateDecisionNode_hasOneIncomingEdge(decisionNode);
        if (oneIncoming) {
            markers.push(oneIncoming);
        }
        return markers;
    }
    validateDecisionNode_hasOneIncomingEdge(decisionNode) {
        const edges = this.modelState.index.getIncomingEdges(decisionNode);
        if (edges.length > 1) {
            return {
                kind: server_1.MarkerKind.ERROR,
                description: 'Decision node may only have one incoming edge.',
                elementId: decisionNode.id,
                label: 'Too many incoming edges'
            };
        }
        else if (edges.length === 0) {
            return {
                kind: server_1.MarkerKind.ERROR,
                description: 'Decision node must have one incoming edge.',
                elementId: decisionNode.id,
                label: 'Missing incoming edge'
            };
        }
        return undefined;
    }
    validateMergeNode(mergeNode) {
        const markers = [];
        const oneOutgoing = this.validateMergeNode_hasOneOutgoingEdge(mergeNode);
        if (oneOutgoing) {
            markers.push(oneOutgoing);
        }
        return markers;
    }
    validateMergeNode_hasOneOutgoingEdge(mergeNode) {
        const edges = this.modelState.index.getOutgoingEdges(mergeNode);
        if (edges.length > 1) {
            return {
                kind: server_1.MarkerKind.ERROR,
                description: 'Merge node may only have one outgoing edge.',
                elementId: mergeNode.id,
                label: 'Too many outgoing edges'
            };
        }
        else if (edges.length === 0) {
            return {
                kind: server_1.MarkerKind.ERROR,
                description: 'Merge node must have one outgoing edge.',
                elementId: mergeNode.id,
                label: 'Missing outgoing edge'
            };
        }
        return undefined;
    }
};
__decorate([
    (0, inversify_1.inject)(server_1.ModelState),
    __metadata("design:type", Object)
], WorkflowModelValidator.prototype, "modelState", void 0);
WorkflowModelValidator = __decorate([
    (0, inversify_1.injectable)()
], WorkflowModelValidator);
exports.WorkflowModelValidator = WorkflowModelValidator;
//# sourceMappingURL=workflow-model-validator.js.map