| /** |
| * |
| * Copyright (c) 2011, 2018 - Loetz GmbH&Co.KG (69115 Heidelberg, Germany) |
| * |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Christophe Loetz (Loetz GmbH&Co.KG) - initial implementation |
| * |
| * generated by Xtext 2.11.0 |
| * |
| */ |
| |
| package org.eclipse.osbp.xtext.signal.validation |
| |
| import java.nio.file.FileSystems |
| import java.nio.file.Path |
| import java.nio.file.PathMatcher |
| import java.text.ParseException |
| import java.util.HashSet |
| import java.util.regex.PatternSyntaxException |
| import javax.inject.Inject |
| import org.eclipse.osbp.xtext.datainterchange.validation.DataDSLValidator |
| import org.eclipse.osbp.xtext.signal.CronScheduler |
| import org.eclipse.osbp.xtext.signal.DailyScheduler |
| import org.eclipse.osbp.xtext.signal.HourlyScheduler |
| import org.eclipse.osbp.xtext.signal.MonthlyScheduler |
| import org.eclipse.osbp.xtext.signal.SignalDSLPackage |
| import org.eclipse.osbp.xtext.signal.SignalFunction |
| import org.eclipse.osbp.xtext.signal.SignalPackage |
| import org.eclipse.osbp.xtext.signal.SignalScheduler |
| import org.eclipse.osbp.xtext.signal.SignalWatcher |
| import org.eclipse.osbp.xtext.signal.WeeklyScheduler |
| import org.eclipse.osbp.xtext.signal.common.SignalConstants |
| import org.eclipse.osbp.xtext.signal.jvmmodel.SignalDSLJvmModelInferrer |
| import org.eclipse.xtext.validation.Check |
| import org.quartz.CronExpression |
| |
| /** |
| * This class contains custom validation rules. |
| * |
| * See https://www.eclipse.org/Xtext/documentation/303_runtime_concepts.html#validation |
| */ |
| class SignalDSLValidator extends AbstractSignalDSLValidator { |
| |
| @Inject extension DataDSLValidator dv |
| @Inject extension SignalDSLJvmModelInferrer jvm |
| |
| @Check |
| def checkDuplicateWatcherNames(SignalPackage pkg) { |
| var signals = new HashSet<String>() |
| for (signal : pkg.signals) { |
| if (!signals.contains(signal.name)) { |
| signals.add(signal.name) |
| } else { |
| error("Watcher's and scheduler's ID have to be unique and [" + signal.name + |
| "] is already in use. Please change it.", signal, SignalDSLPackage.Literals.SIGNAL_DEFINITION__NAME) |
| } |
| } |
| } |
| |
| @Check |
| def void checkSignalSchedulerValidity(SignalScheduler signal) { |
| if (signal.getSchedulertype !== null && signal.getSchedulertype instanceof CronScheduler) { |
| checkCronExpressionValidity(signal.getSchedulertype as CronScheduler) |
| } else if (signal.getSchedulertype !== null && signal.getSchedulertype instanceof HourlyScheduler) { |
| checkHourlySchedulerValidity(signal.getSchedulertype as HourlyScheduler) |
| } else if (signal.getSchedulertype !== null && signal.getSchedulertype instanceof DailyScheduler) { |
| checkDailySchedulerValidity(signal.getSchedulertype as DailyScheduler) |
| } else if (signal.getSchedulertype !== null && signal.getSchedulertype instanceof WeeklyScheduler) { |
| checkWeeklySchedulerValidity(signal.getSchedulertype as WeeklyScheduler) |
| } else if (signal.getSchedulertype !== null && signal.getSchedulertype instanceof MonthlyScheduler) { |
| checkMonthlySchedulerValidity(signal.getSchedulertype as MonthlyScheduler) |
| } |
| } |
| |
| def void checkCronExpressionValidity(CronScheduler scheduler) { |
| var expression = scheduler.expression // format: s m h dm m dw |
| try { |
| if (!CronExpression.isValidExpression(expression)) { |
| CronExpression.validateExpression(expression) |
| } |
| } catch (ParseException exception) { |
| error("The cron expression you have entered is invalid.\n\n" + exception + SignalConstants.CRONEXP_NOTICE, |
| scheduler, SignalDSLPackage.Literals.CRON_SCHEDULER__EXPRESSION) |
| } |
| } |
| |
| def void checkHourlySchedulerValidity(HourlyScheduler scheduler) { |
| if (!(scheduler.minute >= 0 && scheduler.minute <= 59)) { |
| error("The minute entry has to be between 0 and 59.", scheduler, |
| SignalDSLPackage.Literals.HOURLY_SCHEDULER__MINUTE) |
| } |
| } |
| |
| def void checkDailySchedulerValidity(DailyScheduler scheduler) { |
| if (!(scheduler.hour >= 0 && scheduler.hour <= 23)) { |
| error("The hour entry has to be between 0 and 23.", scheduler, |
| SignalDSLPackage.Literals.DAILY_SCHEDULER__HOUR) |
| } |
| if (!(scheduler.minute >= 0 && scheduler.minute <= 59)) { |
| error("The minute entry has to be between 0 and 59.", scheduler, |
| SignalDSLPackage.Literals.DAILY_SCHEDULER__MINUTE) |
| } |
| } |
| |
| def void checkWeeklySchedulerValidity(WeeklyScheduler scheduler) { |
| if (!(scheduler.hour >= 0 && scheduler.hour <= 23)) { |
| error("The hour entry has to be between 0 and 23.", scheduler, |
| SignalDSLPackage.Literals.WEEKLY_SCHEDULER__HOUR) |
| } |
| if (!(scheduler.minute >= 0 && scheduler.minute <= 59)) { |
| error("The minute entry has to be between 0 and 59.", scheduler, |
| SignalDSLPackage.Literals.WEEKLY_SCHEDULER__MINUTE) |
| } |
| |
| } |
| |
| def void checkMonthlySchedulerValidity(MonthlyScheduler scheduler) { |
| if (!(scheduler.dayofmonth >= 1 && scheduler.dayofmonth <= 31)) { |
| error("The hour entry has to be between 1 and 31.", scheduler, |
| SignalDSLPackage.Literals.MONTHLY_SCHEDULER__DAYOFMONTH) |
| } |
| if (!(scheduler.hour >= 0 && scheduler.hour <= 23)) { |
| error("The hour entry has to be between 0 and 23.", scheduler, |
| SignalDSLPackage.Literals.MONTHLY_SCHEDULER__HOUR) |
| } |
| if (!(scheduler.minute >= 0 && scheduler.minute <= 59)) { |
| error("The minute entry has to be between 0 and 59.", scheduler, |
| SignalDSLPackage.Literals.MONTHLY_SCHEDULER__MINUTE) |
| } |
| } |
| |
| @Check |
| def void checkWatcherValidity(SignalWatcher watcher) { |
| if (watcher !== null && watcher.tasks !== null && watcher.interchangegroup !== null) { |
| var interchangeCount = watcher.taskCount(true) |
| var functionCount = watcher.taskCount(false) |
| var baseinterchangeCount = watcher.definedBaseInterchangeCount |
| |
| var defaultInterchange = watcher.defaultInterchange |
| var baseInterchange = watcher.definedBaseInterchange |
| |
| if(watcher.hasFileMask && interchangeCount > 1) { |
| error("Only one interchange unit is allowed to be defined within a watcher with file mask.", |
| watcher , SignalDSLPackage.Literals.SIGNAL_DEFINITION__TASKS) |
| } |
| |
| if( (defaultInterchange === null && baseInterchange === null && interchangeCount >= 1) || |
| (defaultInterchange === null && interchangeCount == 0 && functionCount > 0) ){ |
| |
| error("You haven't specify the interchange unit, whose import path should be watched. You must define one with the keyword 'applyon'.", |
| watcher, SignalDSLPackage.Literals.SIGNAL_DEFINITION__TASKS) |
| } |
| if ( defaultInterchange !== null && baseInterchange !== null) { |
| error("You can only mark one interchange unit with the keyword 'applyon'.", |
| watcher, SignalDSLPackage.Literals.SIGNAL_WATCHER__DEFAULT_INTERCHANGE) |
| } |
| if ( baseinterchangeCount > 1) { |
| error("You can only mark one interchange unit with the keyword 'applyon'.", |
| watcher, SignalDSLPackage.Literals.SIGNAL_DEFINITION__NAME) |
| } |
| |
| } |
| } |
| |
| @Check |
| def void checkDuplicateFileMaskOrFileName(SignalPackage pck) { |
| var filemasks = new HashSet<String>() |
| for (watcher : pck.signals) { |
| if(watcher instanceof SignalWatcher){ |
| if(watcher.hasFileMask){ |
| if (!filemasks.contains(watcher.identifier)) { |
| filemasks.add(watcher.identifier) |
| } else { |
| error("This file mask is already in use in another watcher. Please change it.", watcher, |
| SignalDSLPackage.Literals.SIGNAL_WATCHER__IDENTIFIER) |
| } |
| } |
| else{ |
| if (!filemasks.contains(watcher.identifier)) { |
| filemasks.add(watcher.identifier) |
| } else { |
| error("This file name is already in use in another watcher. Please change it.", watcher, |
| SignalDSLPackage.Literals.SIGNAL_WATCHER__IDENTIFIER) |
| } |
| } |
| } |
| } |
| } |
| |
| @Check |
| def void checkFileMaskAndFileNameValidity(SignalWatcher watcher) { |
| checkFileNameExtension(watcher); |
| |
| if(watcher.hasFileMask){ |
| if (watcher !== null && watcher.identifier !== null && !watcher.identifier.isEmpty) { |
| try { |
| FileSystems.^default.getPathMatcher("glob:" + watcher.identifier) |
| } catch (PatternSyntaxException exception) { |
| error("The pattern of this file mask is invalid, please change it. Error: " + exception.message, |
| watcher, SignalDSLPackage.Literals.SIGNAL_WATCHER__IDENTIFIER) |
| } catch (UnsupportedOperationException exception) { |
| error("The pattern of this file mask is not recognized, please change it. Error: " + exception.message, |
| watcher, SignalDSLPackage.Literals.SIGNAL_WATCHER__IDENTIFIER) |
| } catch (IllegalArgumentException exception) { |
| error("The pattern of this file mask is invalid, please change it. Error: " + exception.message, |
| watcher, SignalDSLPackage.Literals.SIGNAL_WATCHER__IDENTIFIER) |
| } |
| } |
| } |
| } |
| |
| def void checkFileNameExtension(SignalWatcher watcher){ |
| if(watcher !== null && watcher.identifier !== null && !watcher.identifier.isEmpty && watcher.interchangegroup !== null) { |
| if (!isExtensionValid(watcher.identifier) && watcher.hasFileMask) { |
| error("The file mask extension you have entered is not currently supported. Only file masks ending with either one of the following extensions are allowed: '.csv' '.edi' '.txt' or '.xml' .", |
| watcher, SignalDSLPackage.Literals.SIGNAL_WATCHER__IDENTIFIER) |
| } |
| else if (!isExtensionValid(watcher.identifier) && !watcher.hasFileMask) { |
| error("The file name extension you have entered is not currently supported. Only file names ending with either one of the following extensions are allowed: '.csv' '.edi' '.txt' or '.xml' .", |
| watcher, SignalDSLPackage.Literals.SIGNAL_WATCHER__IDENTIFIER) |
| } |
| } |
| } |
| |
| def PathMatcher isFileMaskValid(String filemask) { |
| if (filemask !== null && !filemask.isEmpty) { |
| try { |
| return FileSystems.^default.getPathMatcher("glob:" + filemask) |
| } catch (Exception exception) { |
| return null |
| } |
| } |
| return null |
| } |
| |
| def String escapeCharacters(String pattern) { |
| if (pattern !== null && !pattern.isEmpty) { |
| var result = pattern |
| if (result.indexOf('*') !== -1) { |
| result = result.replaceAll("\\*", "") |
| } |
| if (result.contains("\\")) { |
| result = result.replaceAll("\\", "") |
| } |
| if (result.contains("?")) { |
| result = result.replaceAll("\\?", "") |
| } |
| return result |
| } |
| return null |
| } |
| |
| @Check |
| def void checkFunctionTaskValidity(SignalFunction function) { |
| if(function !== null && function.group !== null && function.doExecuteFunction !== null && function.doExecuteFunction.params !== null){ |
| if(function.onExportFile || function.onImportFile) { |
| if(function.doExecuteFunction.params.size !== 1) { |
| error("Only functions with one parameter from type java.nio.file.Path are allowed to be selected.", function, SignalDSLPackage.Literals.SIGNAL_FUNCTION__DO_EXECUTE_FUNCTION) |
| } |
| |
| if(function.doExecuteFunction.params.size === 1 && !function.doExecuteFunction.params.get(0).parameterType.type.identifier.equals(Path.name)){ |
| error("Only functions with one parameter from type java.nio.file.Path are allowed to be selected.", function, SignalDSLPackage.Literals.SIGNAL_FUNCTION__DO_EXECUTE_FUNCTION) |
| } |
| } |
| else if(!function.onExportFile && !function.onImportFile && !function.doExecuteFunction.params.empty){ |
| error("Only functions without parameter are allowed to be selected.", function, SignalDSLPackage.Literals.SIGNAL_FUNCTION__DO_EXECUTE_FUNCTION) |
| } |
| } |
| } |
| } |