1 /**
2 * UGENE - Integrated Bioinformatics Tools.
3 * Copyright (C) 2008-2021 UniPro <ugene@unipro.ru>
4 * http://ugene.net
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 * MA 02110-1301, USA.
20 */
21
22 #include "WorkflowDebugMessageParserImpl.h"
23
24 #include <QScopedPointer>
25 #include <QStringList>
26 #include <QVariantMap>
27
28 #include <U2Core/AnnotationTableObject.h>
29 #include <U2Core/AppContext.h>
30 #include <U2Core/AppSettings.h>
31 #include <U2Core/TextObject.h>
32 #include <U2Core/U2OpStatusUtils.h>
33 #include <U2Core/U2SafePoints.h>
34 #include <U2Core/UserApplicationsSettings.h>
35
36 #include <U2Gui/ExportObjectUtils.h>
37
38 #include <U2Lang/BaseSlots.h>
39 #include <U2Lang/WorkflowContext.h>
40 #include <U2Lang/WorkflowTransport.h>
41
42 #include "AnnotationsMessageTranslator.h"
43 #include "AssemblyMessageTranslator.h"
44 #include "BaseMessageTranslator.h"
45 #include "MultipleAlignmentMessageTranslator.h"
46 #include "SequenceMessageTranslator.h"
47 #include "VariationTrackMessageTranslator.h"
48
49 const QString PRODUCING_ACTOR_AND_DATA_TYPE_SEPARATOR = ":";
50 const QString FILE_NAME_WORDS_SEPARATOR = "_";
51 const QString INVESTIGATION_FILES_DIR_NAME = "investigation_files";
52
53 namespace U2 {
54
55 using namespace Workflow;
56
initParsedInfo()57 void WorkflowDebugMessageParserImpl::initParsedInfo() {
58 if (Q_LIKELY(!messageTypes.isEmpty())) {
59 foreach (const QString &typeName, messageTypes) {
60 parsedInfo[typeName] = QQueue<QString>();
61 }
62 }
63 }
64
convertToString(const QString & contentIdentifier,const QVariant & content) const65 QString WorkflowDebugMessageParserImpl::convertToString(const QString &contentIdentifier,
66 const QVariant &content) const {
67 QScopedPointer<BaseMessageTranslator> messageTranslator(createMessageTranslator(
68 getMessageTypeFromIdentifier(contentIdentifier), content));
69 SAFE_POINT(!messageTranslator.isNull(), "Invalid message translator detected!", QString());
70 const QString result = messageTranslator->getTranslation();
71 return result;
72 }
73
getMessageTypeFromIdentifier(const QString & messageIdentifier) const74 QString WorkflowDebugMessageParserImpl::getMessageTypeFromIdentifier(
75 const QString &messageIdentifier) const {
76 return messageIdentifier.right(messageIdentifier.size() - messageIdentifier.lastIndexOf(PRODUCING_ACTOR_AND_DATA_TYPE_SEPARATOR) - 1);
77 }
78
getAllMessageValues()79 WorkflowInvestigationData WorkflowDebugMessageParserImpl::getAllMessageValues() {
80 if (!sourceMessages.isEmpty()) {
81 foreach (const QString &key, sourceMessages.head().keys()) {
82 const QString messageType = getMessageTypeFromIdentifier(key);
83 if (Q_UNLIKELY(!possibleMessageTypes.contains(messageType))) {
84 coreLog.info(QObject::tr("Messages in requested queue include info of the '%1' "
85 "data type that is currently unsupported for view. "
86 "No intermediate data will be displayed")
87 .arg(messageType));
88 return parsedInfo;
89 }
90 if (Q_UNLIKELY(!messageTypes.contains(key))) {
91 messageTypes << key;
92 }
93 }
94 initParsedInfo();
95 foreach (const QVariantMap &messageContent, sourceMessages) {
96 foreach (const QString &key, messageContent.keys()) {
97 SAFE_POINT(messageTypes.contains(key), "Unexpected message type encountered!", parsedInfo);
98 parsedInfo[key].enqueue(convertToString(key, messageContent[key]));
99 }
100 }
101 }
102 return parsedInfo;
103 }
104
convertMessagesToDocuments(const QString & convertedType,const QString & schemeName,quint32 messageNumber)105 void WorkflowDebugMessageParserImpl::convertMessagesToDocuments(const QString &convertedType, const QString &schemeName, quint32 messageNumber) {
106 SAFE_POINT(!convertedType.isEmpty(), "Invalid message type detected!", );
107 const AppSettings *appSettings = AppContext::getAppSettings();
108 SAFE_POINT(nullptr != appSettings, "Invalid application settings' storage!", );
109 const UserAppsSettings *userSettings = appSettings->getUserAppsSettings();
110 SAFE_POINT(nullptr != userSettings, "Invalid user application settings' storage!", );
111 QString tmpFolderUrl = (userSettings->getCurrentProcessTemporaryDirPath());
112 tmpFolderUrl.replace("//", "/");
113
114 quint32 messageCounter = ++messageNumber;
115 foreach (const QVariantMap &mapData, sourceMessages) {
116 SAFE_POINT(mapData.keys().contains(convertedType), "Invalid message type detected!", );
117 const QString messageType = getMessageTypeFromIdentifier(convertedType);
118 const QString baseFileUrl = tmpFolderUrl + "/" + schemeName + FILE_NAME_WORDS_SEPARATOR + messageType + FILE_NAME_WORDS_SEPARATOR + "m" + QString::number(messageCounter);
119 if (BaseSlots::ANNOTATION_TABLE_SLOT().getId() == messageType) {
120 const QVariant annotationsData = mapData[convertedType];
121 const QList<SharedAnnotationData> annList = StorageUtils::getAnnotationTable(context->getDataStorage(), annotationsData);
122
123 AnnotationTableObject *annsObj = new AnnotationTableObject("Annotations", context->getDataStorage()->getDbiRef());
124 annsObj->addAnnotations(annList);
125
126 ExportObjectUtils::exportAnnotations(annsObj, baseFileUrl);
127 } else {
128 GObject *objectToWrite = fetchObjectFromMessage(messageType, mapData[convertedType]);
129 if (Q_LIKELY(nullptr != objectToWrite)) {
130 ExportObjectUtils::exportObject2Document(objectToWrite, baseFileUrl, false);
131 ++messageCounter;
132 }
133 }
134 }
135 }
136
createMessageTranslator(const QString & messageType,const QVariant & messageData) const137 BaseMessageTranslator *WorkflowDebugMessageParserImpl::createMessageTranslator(const QString &messageType, const QVariant &messageData) const {
138 BaseMessageTranslator *result = nullptr;
139 if (BaseSlots::DNA_SEQUENCE_SLOT().getId() == messageType) {
140 result = new SequenceMessageTranslator(messageData, context);
141 } else if (BaseSlots::ANNOTATION_TABLE_SLOT().getId() == messageType) {
142 result = new AnnotationsMessageTranslator(messageData, context);
143 } else if (BaseSlots::MULTIPLE_ALIGNMENT_SLOT().getId() == messageType) {
144 result = new MultipleAlignmentMessageTranslator(messageData, context);
145 } else if (BaseSlots::ASSEMBLY_SLOT().getId() == messageType) {
146 result = new AssemblyMessageTranslator(messageData, context);
147 } else if (BaseSlots::VARIATION_TRACK_SLOT().getId() == messageType) {
148 result = new VariationTrackMessageTranslator(messageData, context);
149 } else if (BaseSlots::TEXT_SLOT().getId() == messageType || BaseSlots::URL_SLOT().getId() == messageType || BaseSlots::DATASET_SLOT().getId() == messageType || BaseSlots::FASTA_HEADER_SLOT().getId() == messageType) {
150 result = new BaseMessageTranslator(messageData, context);
151 } else {
152 FAIL("Unable to determine message type", result);
153 }
154 return result;
155 }
156
fetchObjectFromMessage(const QString & messageType,const QVariant & messageData) const157 GObject *WorkflowDebugMessageParserImpl::fetchObjectFromMessage(const QString &messageType, const QVariant &messageData) const {
158 GObject *result = nullptr;
159 if (BaseSlots::TEXT_SLOT().getId() == messageType) {
160 SAFE_POINT(messageData.canConvert<QString>(), "Supplied message doesn't contain text data", nullptr);
161 const QString documentText = messageData.value<QString>();
162 U2OpStatus2Log os;
163 result = TextObject::createInstance(documentText, "wd_investigation_tmp_text_object", context->getDataStorage()->getDbiRef(), os);
164 return result;
165 } else if (BaseSlots::URL_SLOT().getId() == messageType || BaseSlots::DATASET_SLOT().getId() == messageType || BaseSlots::FASTA_HEADER_SLOT().getId() == messageType || BaseSlots::ANNOTATION_TABLE_SLOT().getId() == messageType) {
166 return result;
167 }
168 SAFE_POINT(messageData.canConvert<SharedDbiDataHandler>(),
169 "Supplied message doesn't contain DB reference",
170 nullptr);
171 SharedDbiDataHandler objectId = messageData.value<SharedDbiDataHandler>();
172
173 if (BaseSlots::DNA_SEQUENCE_SLOT().getId() == messageType) {
174 result = StorageUtils::getSequenceObject(context->getDataStorage(), objectId);
175 } else if (BaseSlots::MULTIPLE_ALIGNMENT_SLOT().getId() == messageType) {
176 result = StorageUtils::getMsaObject(context->getDataStorage(), objectId);
177 } else if (BaseSlots::ASSEMBLY_SLOT().getId() == messageType) {
178 result = StorageUtils::getAssemblyObject(context->getDataStorage(), objectId);
179 } else if (BaseSlots::VARIATION_TRACK_SLOT().getId() == messageType) {
180 result = StorageUtils::getVariantTrackObject(context->getDataStorage(), objectId);
181 }
182 SAFE_POINT(nullptr != result, "Could not obtain object from dbi", nullptr);
183 return result;
184 }
185
186 } // namespace U2
187