blob: bd502e8aa0d2fc767de972e97e1e6a0794d7a8dd [file] [log] [blame]
/**
*
* 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)
}
}
}
}