blob: 5468e0e1ee3156414e3fe66212d056de3a6a9b2f [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.net.MalformedURLException
import java.net.URL
import java.nio.file.Files
import java.nio.file.Paths
import java.text.ParseException
import java.util.HashSet
import org.eclipse.osbp.utils.common.SystemInformation
import org.eclipse.osbp.xtext.datainterchange.DataInterchangeFile
import org.eclipse.osbp.xtext.datainterchange.DataInterchangeFileCSV
import org.eclipse.osbp.xtext.datainterchange.DataInterchangeFileEDI
import org.eclipse.osbp.xtext.datainterchange.DataInterchangeFileXML
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.SignalHandler
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.TriggerFile
import org.eclipse.osbp.xtext.signal.WeeklyScheduler
import org.eclipse.osbp.xtext.signal.common.OSBPSignalConstants
import org.eclipse.xtext.validation.Check
import org.quartz.CronExpression
import static org.eclipse.osbp.xtext.signal.common.OSBPSignalConstants.*
/**
* This class contains custom validation rules.
*
* See https://www.eclipse.org/Xtext/documentation/303_runtime_concepts.html#validation
*/
class SignalDSLValidator extends AbstractSignalDSLValidator {
@Check
def checkDuplicateWatcherNames(SignalPackage pkg) {
var watchers = new HashSet<String>()
for (watcher : pkg.watchers) {
if (!watchers.contains(watcher.name)) {
watchers.add(watcher.name)
} else {
error("The watcher id has to be unique and [" + watcher.name + "] is already in use. Please change it.",
watcher, SignalDSLPackage.Literals.SIGNAL_WATCHER__NAME)
}
}
}
@Check
def checkDuplicateHandlerNames(SignalWatcher watcher) {
var handlers = new HashSet<String>()
for (handler : watcher.handlers) {
if (!handlers.contains(handler.name)) {
handlers.add(handler.name)
} else {
error("The handler id has to be unique.", handler, SignalDSLPackage.Literals.SIGNAL_HANDLER__NAME)
}
}
}
@Check
def boolean checkFileNameValidity(SignalHandler handler) {
for (interchange : handler.interchanges) {
if (interchange.dataRef !== null && interchange.fileName !== null &&
interchange.fileName.length > FILE_EXTENSION_MIN_SIZE) {
if (!isExtensionValid(interchange.fileName)) {
error(
"The filename extension you have entered is not currently supported. Only file with either following extension are allowed: .csv .edi or .xml",
interchange, SignalDSLPackage.Literals.SIGNAL_DATAINTERCHANGE__FILE_NAME)
}
var allowed_extension = getValidExtensionToInterchange(interchange.dataRef.fileEndpoint)
if (allowed_extension !== null &&
!isExtensionAllowedToInterchange(interchange.fileName, allowed_extension)) {
error(
"The filename extension you have entered is not valid with [" + interchange.dataRef.name +
"] definition. Only filename with " + allowed_extension + " as extension are allowed!",
interchange, SignalDSLPackage.Literals.SIGNAL_DATAINTERCHANGE__FILE_NAME)
}
val filename = interchange.fileName.substring(0,
interchange.fileName.length - (FILE_EXTENSION_MIN_SIZE))
if (!isFileNameWithoutExtensionValid(filename)) {
error(
"The filename contains one or more of the following non-allowed characters / \\ : * ? > < \" ' | please change it.",
interchange, SignalDSLPackage.Literals.SIGNAL_DATAINTERCHANGE__FILE_NAME)
}
}
}
}
def boolean isExtensionValid(String filename) {
return (filename.endsWith(CSV_EXTENSION) || filename.endsWith(CSV_EXTENSION.toUpperCase) ||
filename.endsWith(EDI_EXTENSION) || filename.endsWith(EDI_EXTENSION.toUpperCase) ||
filename.endsWith(XML_EXTENSION) || filename.endsWith(XML_EXTENSION.toUpperCase)
)
}
def boolean isExtensionAllowedToInterchange(String filename, String allowedextension) {
return (filename.endsWith(allowedextension) || filename.endsWith(allowedextension.toUpperCase))
}
def String getValidExtensionToInterchange(DataInterchangeFile file) {
if (file instanceof DataInterchangeFileCSV) {
return CSV_EXTENSION
}
if (file instanceof DataInterchangeFileEDI) {
return EDI_EXTENSION
}
if (file instanceof DataInterchangeFileXML) {
return XML_EXTENSION
}
return null
}
def boolean isFileNameWithoutExtensionValid(String filename) {
if(SystemInformation.isWindowsOS()){
return !filename.contains('/') && !filename.contains('\\') && !filename.contains(':') && ( !filename.contains('*') && !filename.contains('?')
&& !filename.contains('>') && !filename.contains('<') && !filename.contains('"') && !filename.contains('|'))
//based on win10 allowed characters on 12.04.2018
}
else if(SystemInformation.isMacOS()){
return
!filename.contains('/') && !filename.contains('\\') && !filename.contains('-') && ( !filename.contains('*') && !filename.contains('?')
&& !filename.contains('[') && !filename.contains(']') && !filename.contains('"') && !filename.contains('\'') && !filename.contains('{') && !filename.contains('}'))
// based on http://www.informit.com/articles/article.aspx?p=1144082&seqNum=5 accessed on 12.04.2018
}
else if(SystemInformation.isUnixOS()){
return
!filename.contains('/') && !filename.contains('\\') && !filename.contains(':') && ( !filename.contains('*') && !filename.contains('?')
&& !filename.contains('>') && !filename.contains('<') && !filename.contains('"') && !filename.contains('|')
)
}
return true
}
@Check
def checkDuplicateDirectoryNames(SignalPackage pkg) {
var watcherdir = new HashSet<String>()
for (watcher : pkg.watchers) {
if (!watcherdir.contains(watcher.directory)) {
watcherdir.add(watcher.directory)
} else {
error("The watcher directory '" + watcher.directory +
"' is already in use. Please choose another directory.", watcher,
SignalDSLPackage.Literals.SIGNAL_WATCHER__DIRECTORY)
}
}
}
@Check
def boolean checkDuplicateFileMasks(SignalWatcher watcher) {
var filemasks = new HashSet<String>()
for (handler : watcher.handlers) {
if (handler.triggerpolicy !== null && handler.triggerpolicy instanceof TriggerFile) {
var temp = handler.triggerpolicy as TriggerFile
if (!filemasks.contains(temp.filemask)) {
filemasks.add(temp.filemask)
} else {
error(
"This file mask is already in use, please change it.",
temp, SignalDSLPackage.Literals.TRIGGER_FILE__FILEMASK)
return true
}
}
}
return false
}
@Check
def void checkSignalSchedulerValidity(SignalScheduler signal) {
if (signal.scheduler !== null && signal.scheduler instanceof CronScheduler) {
checkCronExpressionValidity(signal.scheduler as CronScheduler)
} else if (signal.scheduler !== null && signal.scheduler instanceof HourlyScheduler) {
checkHourlySchedulerValidity(signal.scheduler as HourlyScheduler)
} else if (signal.scheduler !== null && signal.scheduler instanceof DailyScheduler) {
checkDailySchedulerValidity(signal.scheduler as DailyScheduler)
} else if (signal.scheduler !== null && signal.scheduler instanceof WeeklyScheduler) {
checkWeeklySchedulerValidity(signal.scheduler as WeeklyScheduler)
} else if (signal.scheduler !== null && signal.scheduler instanceof MonthlyScheduler) {
checkMonthlySchedulerValidity(signal.scheduler 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 +
OSBPSignalConstants.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 checkURLValidity(SignalHandler handler) {
if(handler.eContainer instanceof SignalWatcher){
var url = getDirectoryURL(((handler.eContainer as SignalWatcher).directory))
if(url !== null && !url.protocol.equals("file") && (handler.triggerpolicy instanceof TriggerFile)){
error("Only scheduler based handlers are allowed, since the watcher directory is not a file url.", handler, SignalDSLPackage.Literals.SIGNAL_HANDLER__TRIGGERPOLICY)
}
}
}
def getDirectoryURL(String directory) {
try {
return new URL(directory);
} catch (MalformedURLException e1) {
if(e1.getMessage().startsWith("unknown protocol") || e1.getMessage().startsWith("no protocol")) {
try {
return Paths.get(directory).toUri().toURL();
} catch (MalformedURLException e2) {
return null
}
}
}
return null
}
@Check
def checkDirectoryValidity(SignalWatcher watcher) {
var url = getDirectoryURL(watcher.directory)
if(url !== null && url.protocol.equals("file") && !existsDirectory(watcher.directory)){
error("This directory doesn't exist. Please correct the path you have entered.", watcher, SignalDSLPackage.Literals.SIGNAL_WATCHER__DIRECTORY)
}
}
def boolean existsDirectory(String path) {
try {
return Files.isDirectory(Paths.get(path));
} catch (Exception e) { }
return false;
}
}