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 #ifndef _U2_WORKFLOW_UTILS_H_
23 #define _U2_WORKFLOW_UTILS_H_
24 
25 #include <QObject>
26 #include <QProcess>
27 #include <QVariant>
28 
29 #include <U2Lang/Dataset.h>
30 #include <U2Lang/Descriptor.h>
31 #include <U2Lang/IntegralBusModel.h>
32 #include <U2Lang/Schema.h>
33 #include <U2Lang/SupportClass.h>
34 #include <U2Lang/SupportStructures.h>
35 #include <U2Lang/WorkflowContext.h>
36 
37 class QListWidgetItem;
38 
39 namespace U2 {
40 
41 class Descriptor;
42 class DocumentFormat;
43 class Folder;
44 
45 using namespace Workflow;
46 
47 enum UrlAttributeType { NotAnUrl,
48                         DatasetAttr,
49                         InputFile,
50                         InputDir,
51                         OutputFile,
52                         OutputDir };
53 
54 class U2LANG_EXPORT WorkflowUtils : public QObject {
55     Q_OBJECT
56 public:
57     static QString getRichDoc(const Descriptor &d);
58     static void setQObjectProperties(QObject &, const QVariantMap &);
59     static QString getDropUrl(QList<DocumentFormat *> &fs, const QMimeData *md);
60     static QStringList expandToUrls(const QString &);
61 
62     static const QStringList WD_FILE_EXTENSIONS;
63     static const QString WD_XML_FORMAT_EXTENSION;
64     static const QString HREF_PARAM_ID;
65 
66     // used in GUI schema validating
67     static bool validate(const Workflow::Schema &s, QList<QListWidgetItem *> &errs);
68     // used in cmdline schema validating
69     static bool validate(const Workflow::Schema &s, QStringList &errs);
70 
71     static QList<Descriptor> findMatchingTypes(DataTypePtr set, DataTypePtr elementDataType);
72     static QStringList findMatchingTypesAsStringList(DataTypePtr set, DataTypePtr elementDatatype);
73     static QStringList candidatesAsStringList(const QList<Descriptor> &candidates);
74     static QList<Descriptor> findMatchingCandidates(DataTypePtr from, DataTypePtr to, const Descriptor &key);
75     static QList<Descriptor> findMatchingCandidates(DataTypePtr from, DataTypePtr elementDatatype);
76     static Descriptor getCurrentMatchingDescriptor(const QList<Descriptor> &candidates, DataTypePtr to, const Descriptor &key, const StrStrMap &bindings);
77     static DataTypePtr getToDatatypeForBusport(IntegralBusPort *p);
78     static DataTypePtr getFromDatatypeForBusport(IntegralBusPort *p, DataTypePtr to);
79 
80     // find schema with 'name' in common folders or from settings
81     static QString findPathToSchemaFile(const QString &name);
82 
83     static void getLinkedActorsId(Actor *a, QList<QString> &linkedActors);  // get list of ID's of all linked actors
84 
85     static bool isPathExist(const Port *src, const Port *dest);
86 
87     static QString getStringForParameterDisplayRole(const QVariant &value);
88 
89     static Actor *findActorByParamAlias(const QList<Actor *> &procs, const QString &alias, QString &attrName, bool writeLog = true);
90 
91     static Descriptor getSlotDescOfDatatype(const DataTypePtr &dt);
92 
93     static QString getParamIdFromHref(const QString &href);
94 
95     static QString generateIdFromName(const QString &name);
96 
97     static void print(const QString &slotString, const QVariant &data, DataTypePtr type, WorkflowContext *context);
98 
99     static bool validateSchemaForIncluding(const Schema &s, QString &error);
100 
101     static void extractPathsFromBindings(StrStrMap &busMap, SlotPathMap &pathMap);
102 
103     static void applyPathsToBusMap(StrStrMap &busMap, const SlotPathMap &pathMap);
104 
105     static bool startExternalProcess(QProcess *process, const QString &program, const QStringList &arguments);
106 
107     static QStringList getDatasetsUrls(const QList<Dataset> &sets);
108 
109     static QStringList getAttributeUrls(Attribute *attr);
110 
111     static Actor *actorById(const QList<Actor *> &actors, const ActorId &id);
112 
113     static QMap<Descriptor, DataTypePtr> getBusType(Port *inPort);
114 
115     static bool isBindingValid(const QString &srcSlotId, const QMap<Descriptor, DataTypePtr> &srcBus, const QString &dstSlotId, const QMap<Descriptor, DataTypePtr> &dstBus);
116 
117     /** Returns the string which is not contained by @uniqueStrs list
118      * Result is created from @str rolling @sep + number suffix
119      */
120     static QString createUniqueString(const QString &str, const QString &sep, const QStringList &uniqueStrs);
121 
122     /** if path == "default" then nothing is changed. Returns the new path */
123     static QString updateExternalToolPath(const QString &id, const QString &path);
124 
125     static QString getExternalToolPath(const QString &toolId);
126     static QString externalToolIsAbsentError(const QString &toolName);
127     static QString externalToolError(const QString &toolName);
128     static QString externalToolInvalidError(const QString &toolName);
129     static QString customExternalToolInvalidError(const QString &toolName, const QString &elementName);
130 
131     static void schemaFromFile(const QString &url, Schema *schema, Metadata *meta, U2OpStatus &os);
132 
133     /** Use it to check if the attribute contains URL(s) and what are they (input/output, etc.) */
134     static UrlAttributeType isUrlAttribute(Attribute *attr, const Actor *actor);
135 
136     static bool checkSharedDbConnection(const QString &fullDbUrl);
137 
138     /**
139      * Validation of input files/folders.
140      * Empty input string is considered valid.
141      * Otherwise, the input string is split into separate URL(s) by ';'.
142      * For each input file: the URL must exist, be a file and have permissions to read from it.
143      * For each input folder: the URL must exist and be a folder.
144      * For each object from a database: DB URL must be available, object must exist
145      * For each folder from a database: DB URL must be available, folder must exist
146      */
147     static bool validateInputFiles(QString urls, NotificationsList &notificationList);
148     static bool validateInputDirs(QString urls, NotificationsList &notificationList);
149 
150     static bool validateInputDbObject(const QString &url, NotificationsList &notificationList);
151     static bool validateInputDbFolders(QString urls, NotificationsList &notificationList);
152 
153     /**
154      * Validation of output file/folder.
155      * Empty URL is considered valid.
156      * For output URL it is verified that it is accessible for
157      * writing (the path can be absolute or relative to the Workflow Output Folder).
158      */
159     static bool validateOutputFile(const QString &url, NotificationsList &notificationList);
160     static bool validateOutputDir(const QString &url, NotificationsList &notificationList);
161 
162     static bool isSharedDbUrlAttribute(const Attribute *attr, const Actor *actor);
163     static bool validateSharedDbUrl(const QString &url, NotificationsList &notificationList);
164 
165     /**
166      * Validates input files in datasets are present and readable (i.e.
167      * filtered files in input folders are verified).
168      */
169     static bool validateDatasets(const QList<Dataset> &sets, NotificationsList &notificationList);
170 
171     static QScriptValue datasetsToScript(const QList<Dataset> &sets, QScriptEngine &engine);
172 
173     static QString getDatasetSplitter(const QString &filePaths);
174 
175     static QString packSamples(const QList<TophatSample> &samples);
176     static QList<TophatSample> unpackSamples(const QString &samplesStr, U2OpStatus &os);
177 
178 private:
179     static QStringList initExtensions();
180     static bool validate(const Workflow::Schema &s, NotificationsList &notificationList);
181 };  // WorkflowUtils
182 
183 class U2LANG_EXPORT WorkflowEntityValidator {
184 public:
185     static const QString NAME_INACCEPTABLE_SYMBOLS_TEMPLATE;
186     static const QString ID_ACCEPTABLE_SYMBOLS_TEMPLATE;
187 
188     static const QRegularExpression ACCEPTABLE_NAME;
189     static const QRegularExpression INACCEPTABLE_SYMBOL_IN_NAME;
190     static const QRegularExpression ACCEPTABLE_ID;
191     static const QRegularExpression INACCEPTABLE_SYMBOLS_IN_ID;
192 };
193 
194 /**
195  * provides utility functions for ActorDocument purposes
196  */
197 class U2LANG_EXPORT PrompterBaseImpl : public ActorDocument, public Prompter {
198     Q_OBJECT
199 public:
200     PrompterBaseImpl(Actor *p = 0)
ActorDocument(p)201         : ActorDocument(p) {
202     }
203 
isWildcardURL(const QString & url)204     static bool isWildcardURL(const QString &url) {
205         return url.indexOf(QRegExp("[*?\\[\\]]")) >= 0;
206     }
207 
208     virtual ActorDocument *createDescription(Actor *) = 0;
209 
210     QString getURL(const QString &id, bool *empty = nullptr, const QString &onEmpty = "", const QString &defaultValue = "");
211     QString getScreenedURL(IntegralBusPort *input, const QString &id, const QString &slot, const QString &onEmpty = "");
212     QString getRequiredParam(const QString &id);
213     QVariant getParameter(const QString &id);
214     QString getProducers(const QString &port, const QString &slot);
215     QString getProducersOrUnset(const QString &port, const QString &slot);
216     static QString getHyperlink(const QString &id, const QString &val);
217     static QString getHyperlink(const QString &id, int val);
218     static QString getHyperlink(const QString &id, qreal val);
219 
220     virtual QString composeRichDoc() = 0;
update(const QVariantMap & cfg)221     virtual void update(const QVariantMap &cfg) {
222         map = cfg;
223         sl_actorModified();
224     }
225 
226 protected slots:
227     virtual void sl_actorModified();
228 
229 protected:
230     QVariantMap map;
231 
232 };  // PrompterBaseImpl
233 
234 /**
235  * template realization of Prompter and ActorDocument in one entity
236  * represents creating description, updating description and displaying description facilities
237  *
238  * only classes that inherit ActorDocument can be used as a template argument
239  * provides
240  */
241 template<typename T>
242 class PrompterBase : public PrompterBaseImpl {
243 public:
244     PrompterBase(Actor *p = 0, bool listenInputs = true)
PrompterBaseImpl(p)245         : PrompterBaseImpl(p), listenInputs(listenInputs) {
246     }
247     virtual ~PrompterBase() = default;
createDescription(Actor * a)248     virtual ActorDocument *createDescription(Actor *a) {
249         T *doc = new T(a);
250         doc->connect(a, SIGNAL(si_labelChanged()), SLOT(sl_actorModified()));
251         doc->connect(a, SIGNAL(si_modified()), SLOT(sl_actorModified()));
252         if (listenInputs) {
253             foreach (Workflow::Port *input, a->getInputPorts()) {
254                 doc->connect(input, SIGNAL(bindingChanged()), SLOT(sl_actorModified()));
255             }
256         }
257 
258         foreach (Workflow::Port *input, a->getOutputPorts()) {
259             doc->connect(input, SIGNAL(bindingChanged()), SLOT(sl_actorModified()));
260         }
261         //}
262         return doc;
263     }
264 
265 protected:
266     bool listenInputs;
267 
268 };  // PrompterBase
269 
270 }  // namespace U2
271 
272 #endif
273