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 ¬ificationList); 148 static bool validateInputDirs(QString urls, NotificationsList ¬ificationList); 149 150 static bool validateInputDbObject(const QString &url, NotificationsList ¬ificationList); 151 static bool validateInputDbFolders(QString urls, NotificationsList ¬ificationList); 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 ¬ificationList); 160 static bool validateOutputDir(const QString &url, NotificationsList ¬ificationList); 161 162 static bool isSharedDbUrlAttribute(const Attribute *attr, const Actor *actor); 163 static bool validateSharedDbUrl(const QString &url, NotificationsList ¬ificationList); 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 ¬ificationList); 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 ¬ificationList); 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