Skip to content
Snippets Groups Projects
Commit 92add8cc authored by vkovtun's avatar vkovtun
Browse files

SSDM-13794: Improved error messages in default ELN dropbox.

parent 405232ef
No related branches found
No related tags found
1 merge request!40SSDM-13578 : 2PT : Database and V3 Implementation - include the new AFS "free"...
import re import re
import uuid
from ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.fetchoptions import ExperimentFetchOptions from ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.fetchoptions import ExperimentFetchOptions
from ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.id import ExperimentIdentifier from ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.id import ExperimentIdentifier
from ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.fetchoptions import SampleFetchOptions from ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.fetchoptions import SampleFetchOptions
from ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.id import SampleIdentifier from ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.id import SampleIdentifier
from ch.systemsx.cisd.common.mail import EMailAddress from ch.systemsx.cisd.common.mail import EMailAddress
from ch.systemsx.cisd.openbis.generic.client.web.client.exception import UserFailureException
from ch.systemsx.cisd.openbis.dss.generic.shared import ServiceProvider from ch.systemsx.cisd.openbis.dss.generic.shared import ServiceProvider
from ch.systemsx.cisd.openbis.generic.client.web.client.exception import UserFailureException
from java.io import File from java.io import File
from java.nio.file import Files, Paths, StandardCopyOption from java.nio.file import Files, Paths, StandardCopyOption
from java.util import List from java.util import List
from org.json import JSONObject
from org.apache.commons.io import FileUtils from org.apache.commons.io import FileUtils
from org.json import JSONObject
INVALID_FORMAT_ERROR_MESSAGE = "Invalid format for the folder name, should follow the pattern <ENTITY_KIND>+<SPACE_CODE>+<PROJECT_CODE>+[<EXPERIMENT_CODE>|<SAMPLE_CODE>]+<OPTIONAL_DATASET_TYPE>+<OPTIONAL_NAME>"; INVALID_FORMAT_ERROR_MESSAGE = "Invalid format for the folder name, should follow the pattern <ENTITY_KIND>+<SPACE_CODE>+<PROJECT_CODE>+[<EXPERIMENT_CODE>|<SAMPLE_CODE>]+<OPTIONAL_DATASET_TYPE>+<OPTIONAL_NAME>";
ILLEGAL_CHARACTERS_IN_FILE_NAMES_ERROR_MESSAGE = "Directory or its content contain illegal characters: \"', ~, $, %\""; ILLEGAL_CHARACTERS_IN_FILE_NAMES_ERROR_MESSAGE = "Directory or its content contain illegal characters: \"', ~, $, %\"";
...@@ -25,174 +23,184 @@ EXPERIMENT_MISSING_ERROR_MESSAGE = "Experiment not found"; ...@@ -25,174 +23,184 @@ EXPERIMENT_MISSING_ERROR_MESSAGE = "Experiment not found";
NAME_PROPERTY_SET_IN_TWO_PLACES_ERROR_MESSAGE = "$NAME property specified twice, it should just be in either folder name or metadata.json" NAME_PROPERTY_SET_IN_TWO_PLACES_ERROR_MESSAGE = "$NAME property specified twice, it should just be in either folder name or metadata.json"
EMAIL_SUBJECT = "ELN LIMS Dropbox Error"; EMAIL_SUBJECT = "ELN LIMS Dropbox Error";
ILLEGAL_FILES = ["desktop.ini", "IconCache.db", "thumbs.db"]; ILLEGAL_FILES = ["desktop.ini", "IconCache.db", "thumbs.db"];
ILLEGAL_FILES_ERROR_MESSAGE = "Directory or contains illegal files: " + str(ILLEGAL_FILES); ILLEGAL_FILES_ERROR_MESSAGE = "Directory contains illegal files: " + str(ILLEGAL_FILES);
HIDDEN_FILES_ERROR_MESSAGE = "Directory or contains hidden files: files starting with '.'"; HIDDEN_FILES_ERROR_MESSAGE = "Directory contains hidden files: files starting with '.'";
errorMessages = []
def process(transaction): def process(transaction):
incoming = transaction.getIncoming(); incoming = transaction.getIncoming();
folderName = incoming.getName(); folderName = incoming.getName();
emailAddress = None
if not folderName.startswith('.'):
datasetInfo = folderName.split("+"); try:
entityKind = None; if not folderName.startswith('.'):
sample = None; datasetInfo = folderName.split("+");
experiment = None; entityKind = None;
datasetType = None; sample = None;
name = None; experiment = None;
datasetType = None;
# Parse entity Kind name = None;
if len(datasetInfo) >= 1:
entityKind = datasetInfo[0]; # Parse entity Kind
else: if len(datasetInfo) >= 1:
raise UserFailureException(INVALID_FORMAT_ERROR_MESSAGE + ":" + FAILED_TO_PARSE_ERROR_MESSAGE); entityKind = datasetInfo[0];
else:
v3 = ServiceProvider.getV3ApplicationService(); raise UserFailureException(INVALID_FORMAT_ERROR_MESSAGE + ":" + FAILED_TO_PARSE_ERROR_MESSAGE);
sessionToken = transaction.getOpenBisServiceSessionToken();
projectSamplesEnabled = v3.getServerInformation(sessionToken)['project-samples-enabled'] == 'true' v3 = ServiceProvider.getV3ApplicationService();
sessionToken = transaction.getOpenBisServiceSessionToken();
# Parse entity Kind Format projectSamplesEnabled = v3.getServerInformation(sessionToken)['project-samples-enabled'] == 'true'
if entityKind == "O":
if len(datasetInfo) >= 4 and projectSamplesEnabled: # Parse entity Kind Format
sampleSpace = datasetInfo[1]; if entityKind == "O":
projectCode = datasetInfo[2]; if len(datasetInfo) >= 4 and projectSamplesEnabled:
sampleCode = datasetInfo[3]; sampleSpace = datasetInfo[1];
projectCode = datasetInfo[2];
emailAddress = getSampleRegistratorsEmail(transaction, sampleSpace, projectCode, sampleCode) sampleCode = datasetInfo[3];
sample = transaction.getSample("/" + sampleSpace + "/" + projectCode + "/" + sampleCode);
if sample is None: emailAddress = getSampleRegistratorsEmail(transaction, sampleSpace, projectCode, sampleCode)
reportIssue(transaction, sample = transaction.getSample("/" + sampleSpace + "/" + projectCode + "/" + sampleCode);
INVALID_FORMAT_ERROR_MESSAGE + ":" + SAMPLE_MISSING_ERROR_MESSAGE, if sample is None:
None); reportIssue(INVALID_FORMAT_ERROR_MESSAGE + ":" + SAMPLE_MISSING_ERROR_MESSAGE)
if len(datasetInfo) >= 5: raise UserFailureException(INVALID_FORMAT_ERROR_MESSAGE + ":" + SAMPLE_MISSING_ERROR_MESSAGE)
datasetType = datasetInfo[4]; if len(datasetInfo) >= 5:
if len(datasetInfo) >= 6: datasetType = datasetInfo[4];
name = datasetInfo[5]; if len(datasetInfo) >= 6:
if len(datasetInfo) > 6: name = datasetInfo[5];
reportIssue(transaction, if len(datasetInfo) > 6:
INVALID_FORMAT_ERROR_MESSAGE + ":" + FAILED_TO_PARSE_SAMPLE_ERROR_MESSAGE, reportIssue(INVALID_FORMAT_ERROR_MESSAGE + ":" + FAILED_TO_PARSE_SAMPLE_ERROR_MESSAGE)
emailAddress) elif len(datasetInfo) >= 3 and not projectSamplesEnabled:
elif len(datasetInfo) >= 3 and not projectSamplesEnabled: sampleSpace = datasetInfo[1];
sampleSpace = datasetInfo[1]; sampleCode = datasetInfo[2];
sampleCode = datasetInfo[2];
emailAddress = getSampleRegistratorsEmail(transaction, sampleSpace, None, sampleCode)
emailAddress = getSampleRegistratorsEmail(transaction, sampleSpace, None, sampleCode) sample = transaction.getSample("/" + sampleSpace + "/" + sampleCode);
sample = transaction.getSample("/" + sampleSpace + "/" + sampleCode); if sample is None:
if sample is None: reportIssue(INVALID_FORMAT_ERROR_MESSAGE + ":" + SAMPLE_MISSING_ERROR_MESSAGE)
reportIssue(transaction, raise UserFailureException(INVALID_FORMAT_ERROR_MESSAGE + ":" + SAMPLE_MISSING_ERROR_MESSAGE)
INVALID_FORMAT_ERROR_MESSAGE + ":" + SAMPLE_MISSING_ERROR_MESSAGE, if len(datasetInfo) >= 4:
None); datasetType = datasetInfo[3];
if len(datasetInfo) >= 5:
name = datasetInfo[4];
if len(datasetInfo) > 5:
reportIssue(INVALID_FORMAT_ERROR_MESSAGE + ":" + FAILED_TO_PARSE_SAMPLE_ERROR_MESSAGE)
else:
raise UserFailureException(INVALID_FORMAT_ERROR_MESSAGE + ":" + FAILED_TO_PARSE_SAMPLE_ERROR_MESSAGE);
hiddenFiles = getHiddenFiles(incoming)
if hiddenFiles:
reportIssue(HIDDEN_FILES_ERROR_MESSAGE + ":" + FAILED_TO_PARSE_SAMPLE_ERROR_MESSAGE + ":\n" + pathListToStr(hiddenFiles))
illegalFiles = getIllegalFiles(incoming)
if illegalFiles:
reportIssue(ILLEGAL_FILES_ERROR_MESSAGE + ":" + FAILED_TO_PARSE_SAMPLE_ERROR_MESSAGE + ":\n" + pathListToStr(illegalFiles))
filesWithIllegalCharacters = getFilesWithIllegalCharacters(incoming)
if filesWithIllegalCharacters:
reportIssue(ILLEGAL_CHARACTERS_IN_FILE_NAMES_ERROR_MESSAGE + ":"
+ FAILED_TO_PARSE_SAMPLE_ERROR_MESSAGE + ":\n" + pathListToStr(filesWithIllegalCharacters))
readOnlyFiles = getReadOnlyFiles(incoming)
if readOnlyFiles:
reportIssue(FOLDER_CONTAINS_NON_DELETABLE_FILES_ERROR_MESSAGE + ":" + FAILED_TO_PARSE_SAMPLE_ERROR_MESSAGE + ":\n" + pathListToStr(readOnlyFiles));
if entityKind == "E":
if len(datasetInfo) >= 4: if len(datasetInfo) >= 4:
datasetType = datasetInfo[3]; experimentSpace = datasetInfo[1];
if len(datasetInfo) >= 5: projectCode = datasetInfo[2];
name = datasetInfo[4]; experimentCode = datasetInfo[3];
if len(datasetInfo) > 5:
reportIssue(transaction, emailAddress = getExperimentRegistratorsEmail(transaction, experimentSpace, projectCode,
INVALID_FORMAT_ERROR_MESSAGE + ":" + FAILED_TO_PARSE_SAMPLE_ERROR_MESSAGE, experimentCode);
emailAddress) experiment = transaction.getExperiment("/" + experimentSpace + "/" + projectCode + "/" + experimentCode);
if experiment is None:
reportIssue(INVALID_FORMAT_ERROR_MESSAGE + ":" + EXPERIMENT_MISSING_ERROR_MESSAGE)
raise UserFailureException(INVALID_FORMAT_ERROR_MESSAGE + ":" + EXPERIMENT_MISSING_ERROR_MESSAGE)
if len(datasetInfo) >= 5:
datasetType = datasetInfo[4];
if len(datasetInfo) >= 6:
name = datasetInfo[5];
if len(datasetInfo) > 6:
reportIssue(INVALID_FORMAT_ERROR_MESSAGE + ":" + FAILED_TO_PARSE_EXPERIMENT_ERROR_MESSAGE);
else:
raise UserFailureException(INVALID_FORMAT_ERROR_MESSAGE + ":" + FAILED_TO_PARSE_EXPERIMENT_ERROR_MESSAGE);
hiddenFiles = getHiddenFiles(incoming)
if hiddenFiles:
reportIssue(HIDDEN_FILES_ERROR_MESSAGE + ":" + FAILED_TO_PARSE_EXPERIMENT_ERROR_MESSAGE + ":\n" + pathListToStr(hiddenFiles))
illegalFiles = getIllegalFiles(incoming)
if illegalFiles:
reportIssue(ILLEGAL_FILES_ERROR_MESSAGE + ":" + FAILED_TO_PARSE_EXPERIMENT_ERROR_MESSAGE + ":\n" + pathListToStr(illegalFiles))
filedWithIllegalCharacters = getFilesWithIllegalCharacters(incoming)
if filedWithIllegalCharacters:
reportIssue(ILLEGAL_CHARACTERS_IN_FILE_NAMES_ERROR_MESSAGE + ":"
+ FAILED_TO_PARSE_EXPERIMENT_ERROR_MESSAGE + ":\n" + pathListToStr(filedWithIllegalCharacters))
readOnlyFiles = getReadOnlyFiles(incoming)
if readOnlyFiles:
reportIssue(FOLDER_CONTAINS_NON_DELETABLE_FILES_ERROR_MESSAGE + ":"
+ FAILED_TO_PARSE_EXPERIMENT_ERROR_MESSAGE + ":\n" + pathListToStr(readOnlyFiles))
# Create dataset
dataSet = None;
if datasetType is not None: # Set type if found
dataSet = transaction.createNewDataSet(datasetType);
else: else:
raise UserFailureException(INVALID_FORMAT_ERROR_MESSAGE + ":" + FAILED_TO_PARSE_SAMPLE_ERROR_MESSAGE); dataSet = transaction.createNewDataSet();
if hasFolderHiddenFiles(incoming): if name is not None:
reportIssue(transaction, HIDDEN_FILES_ERROR_MESSAGE + ":" dataSet.setPropertyValue("$NAME", name); # Set name if found
+ FAILED_TO_PARSE_SAMPLE_ERROR_MESSAGE, emailAddress);
if hasFolderIllegalFiles(incoming): # Set sample or experiment
reportIssue(transaction, ILLEGAL_FILES_ERROR_MESSAGE + ":" if sample is not None:
+ FAILED_TO_PARSE_SAMPLE_ERROR_MESSAGE, emailAddress); dataSet.setSample(sample);
if hasFolderIllegalCharacters(incoming):
reportIssue(transaction, ILLEGAL_CHARACTERS_IN_FILE_NAMES_ERROR_MESSAGE + ":"
+ FAILED_TO_PARSE_SAMPLE_ERROR_MESSAGE, emailAddress);
if hasFolderReadOnlyFiles(incoming):
reportIssue(transaction, FOLDER_CONTAINS_NON_DELETABLE_FILES_ERROR_MESSAGE + ":"
+ FAILED_TO_PARSE_SAMPLE_ERROR_MESSAGE, emailAddress);
if entityKind == "E":
if len(datasetInfo) >= 4:
experimentSpace = datasetInfo[1];
projectCode = datasetInfo[2];
experimentCode = datasetInfo[3];
emailAddress = getExperimentRegistratorsEmail(transaction, experimentSpace, projectCode,
experimentCode);
experiment = transaction.getExperiment("/" + experimentSpace + "/" + projectCode + "/" + experimentCode);
if experiment is None:
reportIssue(transaction,
INVALID_FORMAT_ERROR_MESSAGE + ":" + EXPERIMENT_MISSING_ERROR_MESSAGE,
None);
if len(datasetInfo) >= 5:
datasetType = datasetInfo[4];
if len(datasetInfo) >= 6:
name = datasetInfo[5];
if len(datasetInfo) > 6:
reportIssue(transaction,
INVALID_FORMAT_ERROR_MESSAGE + ":" + FAILED_TO_PARSE_EXPERIMENT_ERROR_MESSAGE,
emailAddress);
else: else:
raise UserFailureException(INVALID_FORMAT_ERROR_MESSAGE + ":" + FAILED_TO_PARSE_EXPERIMENT_ERROR_MESSAGE); dataSet.setExperiment(experiment);
if hasFolderHiddenFiles(incoming): # Move folder to dataset
reportIssue(transaction, HIDDEN_FILES_ERROR_MESSAGE + ":" filesInFolder = incoming.listFiles();
+ FAILED_TO_PARSE_EXPERIMENT_ERROR_MESSAGE, emailAddress);
if hasFolderIllegalFiles(incoming): itemsInFolder = 0;
reportIssue(transaction, ILLEGAL_FILES_ERROR_MESSAGE + ":" datasetItem = None;
+ FAILED_TO_PARSE_EXPERIMENT_ERROR_MESSAGE, emailAddress); for item in filesInFolder:
if hasFolderIllegalCharacters(incoming): fileName = item.getName()
reportIssue(transaction, ILLEGAL_CHARACTERS_IN_FILE_NAMES_ERROR_MESSAGE + ":" if fileName == "metadata.json":
+ FAILED_TO_PARSE_EXPERIMENT_ERROR_MESSAGE, emailAddress); root = JSONObject(FileUtils.readFileToString(item, "UTF-8"))
if hasFolderReadOnlyFiles(incoming): properties = root.get("properties")
reportIssue(transaction, FOLDER_CONTAINS_NON_DELETABLE_FILES_ERROR_MESSAGE + ":" for propertyKey in properties.keys():
+ FAILED_TO_PARSE_EXPERIMENT_ERROR_MESSAGE, emailAddress); if propertyKey == "$NAME" and name is not None:
raise UserFailureException(NAME_PROPERTY_SET_IN_TWO_PLACES_ERROR_MESSAGE)
# Create dataset propertyValue = properties.get(propertyKey)
dataSet = None; if propertyValue is not None:
if datasetType is not None: # Set type if found propertyValueString = str(propertyValue)
dataSet = transaction.createNewDataSet(datasetType); dataSet.setPropertyValue(propertyKey, propertyValueString)
else: else:
dataSet = transaction.createNewDataSet(); itemsInFolder = itemsInFolder + 1;
datasetItem = item;
if name is not None:
dataSet.setPropertyValue("$NAME", name); # Set name if found if itemsInFolder > 1:
tmpPath = incoming.getAbsolutePath() + "/default";
# Set sample or experiment tmpDir = File(tmpPath);
if sample is not None: tmpDir.mkdir();
dataSet.setSample(sample);
else: try:
dataSet.setExperiment(experiment); for inputFile in filesInFolder:
Files.move(inputFile.toPath(), Paths.get(tmpPath, inputFile.getName()),
# Move folder to dataset StandardCopyOption.ATOMIC_MOVE);
filesInFolder = incoming.listFiles(); transaction.moveFile(tmpDir.getAbsolutePath(), dataSet);
finally:
itemsInFolder = 0; if tmpDir is not None:
datasetItem = None; tmpDir.delete();
for item in filesInFolder:
fileName = item.getName()
if fileName == "metadata.json":
root = JSONObject(FileUtils.readFileToString(item, "UTF-8"))
properties = root.get("properties")
for propertyKey in properties.keys():
if propertyKey == "$NAME" and name is not None:
raise UserFailureException(NAME_PROPERTY_SET_IN_TWO_PLACES_ERROR_MESSAGE)
propertyValue = properties.get(propertyKey)
if propertyValue is not None:
propertyValueString = str(propertyValue)
dataSet.setPropertyValue(propertyKey, propertyValueString)
else: else:
itemsInFolder = itemsInFolder + 1; transaction.moveFile(datasetItem.getAbsolutePath(), dataSet);
datasetItem = item; finally:
reportAllIssues(transaction, emailAddress)
if itemsInFolder > 1:
tmpPath = incoming.getAbsolutePath() + "/default";
tmpDir = File(tmpPath); def pathListToStr(list):
tmpDir.mkdir(); return "\n".join(list)
try:
for inputFile in filesInFolder:
Files.move(inputFile.toPath(), Paths.get(tmpPath, inputFile.getName()),
StandardCopyOption.ATOMIC_MOVE);
transaction.moveFile(tmpDir.getAbsolutePath(), dataSet);
finally:
if tmpDir is not None:
tmpDir.delete();
else:
transaction.moveFile(datasetItem.getAbsolutePath(), dataSet);
def getContactsEmailAddresses(transaction): def getContactsEmailAddresses(transaction):
...@@ -200,62 +208,69 @@ def getContactsEmailAddresses(transaction): ...@@ -200,62 +208,69 @@ def getContactsEmailAddresses(transaction):
return re.split("[,;]", emailString) if emailString is not None else [] return re.split("[,;]", emailString) if emailString is not None else []
def reportIssue(transaction, errorMessage, emailAddress): def reportIssue(errorMessage):
contacts = getContactsEmailAddresses(transaction); errorMessages.append(errorMessage)
allAddresses = [emailAddress] + contacts if emailAddress is not None else contacts;
sendMail(transaction, map(lambda address: EMailAddress(address), allAddresses), EMAIL_SUBJECT, errorMessage);
raise UserFailureException(errorMessage); def reportAllIssues(transaction, emailAddress):
if len(errorMessages) > 0:
contacts = getContactsEmailAddresses(transaction)
allAddresses = [emailAddress] + contacts if emailAddress is not None else contacts
joinedErrorMessages = "\n".join(errorMessages)
sendMail(transaction, map(lambda address: EMailAddress(address), allAddresses), EMAIL_SUBJECT, joinedErrorMessages);
raise UserFailureException(joinedErrorMessages)
def hasFolderIllegalCharacters(incoming): def getFilesWithIllegalCharacters(folder):
if bool(re.search(r"['~$%]", incoming.getName())): result = []
return True; if bool(re.search(r"['~$%]", folder.getPath())):
result.append(folder.getName())
files = incoming.listFiles() files = folder.listFiles()
if files is not None: if files is not None:
for f in files: for f in files:
if hasFolderIllegalCharacters(f): result.extend(getFilesWithIllegalCharacters(f))
return True;
return False; return False;
def hasFolderHiddenFiles(incoming): def getHiddenFiles(folder):
if incoming.getName().startswith("."): result = []
return True; if folder.getName().startswith("."):
result.append(folder.getPath())
files = incoming.listFiles() files = folder.listFiles()
if files is not None: if files is not None:
for f in files: for f in files:
if hasFolderHiddenFiles(f): result.extend(getHiddenFiles(f))
return True;
return result
return False;
def hasFolderIllegalFiles(incoming): def getIllegalFiles(folder):
if incoming.getName() in ILLEGAL_FILES: result = []
return True; if folder.getName() in ILLEGAL_FILES:
result.append(folder.getPath())
files = incoming.listFiles() files = folder.listFiles()
if files is not None: if files is not None:
for f in files: for f in files:
if hasFolderIllegalFiles(f): result.extend(getIllegalFiles(f))
return True;
return False; return result
def hasFolderReadOnlyFiles(incoming): def getReadOnlyFiles(folder):
if not incoming.renameTo(incoming): result = []
return True; if not folder.renameTo(folder):
result.append(folder.getPath())
files = incoming.listFiles() files = folder.listFiles()
if files is not None: if files is not None:
for f in files: for f in files:
if hasFolderReadOnlyFiles(f): result.extend(getReadOnlyFiles(f))
return True;
return False; return result
def sendMail(transaction, emailAddresses, subject, body): def sendMail(transaction, emailAddresses, subject, body):
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment