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 "IntegralBusUtils.h"
23
24 #include <U2Core/U2OpStatusUtils.h>
25 #include <U2Core/U2SafePoints.h>
26
27 #include <U2Lang/BaseSlots.h>
28 #include <U2Lang/BaseTypes.h>
29 #include <U2Lang/IntegralBus.h>
30 #include <U2Lang/IntegralBusModel.h>
31
32 namespace U2 {
33 namespace Workflow {
34
splitCandidates(const QList<Descriptor> & candidates,const Descriptor & toDesc,DataTypePtr toDatatype)35 IntegralBusUtils::SplitResult IntegralBusUtils::splitCandidates(const QList<Descriptor> &candidates, const Descriptor &toDesc, DataTypePtr toDatatype) {
36 CandidatesSplitter *splitter = CandidatesSplitterRegistry::instance()->findSplitter(toDesc, toDatatype);
37 SAFE_POINT(nullptr != splitter, "NULL splitter", SplitResult());
38 return splitter->splitCandidates(candidates);
39 }
40
remapBus(StrStrMap & busMap,const ActorId & oldId,const ActorId & newId,const PortMapping & mapping)41 void IntegralBusUtils::remapBus(StrStrMap &busMap, const ActorId &oldId, const ActorId &newId, const PortMapping &mapping) {
42 foreach (QString key, busMap.uniqueKeys()) {
43 U2OpStatus2Log os;
44 QList<IntegralBusSlot> slotList = IntegralBusSlot::listFromString(busMap[key], os);
45 QList<IntegralBusSlot> newSlots;
46 for (const IntegralBusSlot &slot : qAsConst(slotList)) {
47 IntegralBusSlot newSlot = slot;
48 if (slot.actorId() == oldId) {
49 U2OpStatusImpl os2;
50 QString newSlotId = mapping.getDstSlotId(slot.getId(), os2);
51 if (!os2.hasError()) {
52 newSlot = IntegralBusSlot(newSlotId, "", newId);
53 }
54 }
55 newSlots << newSlot;
56 }
57 busMap[key] = IntegralBusSlot::listToString(newSlots);
58 }
59 }
60
remapPathedSlotString(QString & pathedSlotStr,const ActorId & oldId,const ActorId & newId,const PortMapping & mapping)61 void IntegralBusUtils::remapPathedSlotString(QString &pathedSlotStr, const ActorId &oldId, const ActorId &newId, const PortMapping &mapping) {
62 if (pathedSlotStr.isEmpty()) {
63 return;
64 }
65 QString slotStr;
66 QStringList path;
67 BusMap::parseSource(pathedSlotStr, slotStr, path);
68
69 U2OpStatus2Log logOs;
70 IntegralBusSlot slot = IntegralBusSlot::fromString(slotStr, logOs);
71 if (slot.actorId() == oldId) {
72 U2OpStatusImpl os;
73 QString newSlot = mapping.getDstSlotId(slot.getId(), os);
74 if (!os.hasError()) {
75 slot = IntegralBusSlot(newSlot, "", newId);
76 }
77 }
78 pathedSlotStr = slot.toString();
79
80 if (!path.isEmpty()) {
81 for (QStringList::iterator i = path.begin(); i != path.end(); i++) {
82 if (*i == oldId) {
83 *i = newId;
84 }
85 }
86 pathedSlotStr += ">" + path.join(",");
87 }
88 }
89
90 namespace {
91 enum StringSlotType {
92 TEXT,
93 URL,
94 DATASET
95 };
96
isUrlSlot(const Descriptor & slot)97 bool isUrlSlot(const Descriptor &slot) {
98 const QString id = slot.getId();
99 return id.contains(BaseSlots::URL_SLOT().getId());
100 }
isDatasetSlot(const Descriptor & slot)101 bool isDatasetSlot(const Descriptor &slot) {
102 return (BaseSlots::DATASET_SLOT() == slot);
103 }
104
getSlotType(const Descriptor & slot)105 StringSlotType getSlotType(const Descriptor &slot) {
106 if (isUrlSlot(slot)) {
107 return URL;
108 }
109 if (isDatasetSlot(slot)) {
110 return DATASET;
111 }
112 return TEXT;
113 }
114 } // namespace
115
getSlotsByType(const QMap<Descriptor,DataTypePtr> & busMap,const Descriptor & slot,const DataTypePtr & type)116 QList<Descriptor> IntegralBusUtils::getSlotsByType(const QMap<Descriptor, DataTypePtr> &busMap, const Descriptor &slot, const DataTypePtr &type) {
117 QList<Descriptor> result = busMap.keys(type);
118 CHECK(BaseTypes::STRING_TYPE() == type, result);
119 CHECK(result.size() > 1, result);
120
121 const StringSlotType targetType = getSlotType(slot);
122 foreach (const Descriptor &desc, result) {
123 if (targetType != getSlotType(desc)) {
124 result.removeOne(desc);
125 }
126 }
127 return result;
128 }
129
130 /************************************************************************/
131 /* Splitters */
132 /************************************************************************/
133 class DefaultSplitter : public CandidatesSplitter {
134 public:
DefaultSplitter()135 DefaultSplitter()
136 : CandidatesSplitter(ID) {
137 }
138
canSplit(const Descriptor &,DataTypePtr)139 bool canSplit(const Descriptor & /*toDesc*/, DataTypePtr /*toDatatype*/) {
140 return true;
141 }
142
143 static const QString ID;
144
145 protected:
isMain(const QString &)146 bool isMain(const QString & /*candidateSlotId*/) {
147 return true;
148 }
149 };
150
151 const QString DefaultSplitter::ID = "default";
152
153 class TextSplitter : public CandidatesSplitter {
154 public:
TextSplitter()155 TextSplitter()
156 : CandidatesSplitter(ID) {
157 }
158
canSplit(const Descriptor &,DataTypePtr toDatatype)159 bool canSplit(const Descriptor & /*toDesc*/, DataTypePtr toDatatype) {
160 return (BaseTypes::STRING_TYPE() == toDatatype);
161 }
162
163 static const QString ID;
164
165 protected:
isMain(const QString & candidateSlotId)166 bool isMain(const QString &candidateSlotId) {
167 return (BaseSlots::URL_SLOT().getId() != candidateSlotId && BaseSlots::DATASET_SLOT().getId() != candidateSlotId);
168 }
169 };
170 const QString TextSplitter::ID = "text";
171
172 class DatasetsSplitter : public CandidatesSplitter {
173 public:
DatasetsSplitter()174 DatasetsSplitter()
175 : CandidatesSplitter(ID) {
176 }
177
canSplit(const Descriptor & toDesc,DataTypePtr toDatatype)178 bool canSplit(const Descriptor &toDesc, DataTypePtr toDatatype) {
179 return ((BaseTypes::STRING_TYPE() == toDatatype) && isDatasetSlot(toDesc));
180 }
181
182 static const QString ID;
183
184 protected:
isMain(const QString & candidateSlotId)185 bool isMain(const QString &candidateSlotId) {
186 return (BaseSlots::DATASET_SLOT().getId() == candidateSlotId);
187 }
188 };
189
190 const QString DatasetsSplitter::ID = "datasets";
191
192 class UrlSplitter : public CandidatesSplitter {
193 public:
UrlSplitter()194 UrlSplitter()
195 : CandidatesSplitter(ID) {
196 }
197
canSplit(const Descriptor & toDesc,DataTypePtr toDatatype)198 bool canSplit(const Descriptor &toDesc, DataTypePtr toDatatype) {
199 return ((BaseTypes::STRING_TYPE() == toDatatype) && isUrlSlot(toDesc));
200 }
201
202 static const QString ID;
203
204 protected:
isMain(const QString & candidateSlotId)205 bool isMain(const QString &candidateSlotId) {
206 return (BaseSlots::URL_SLOT().getId() == candidateSlotId);
207 }
208 };
209
210 const QString UrlSplitter::ID = "url";
211
212 /************************************************************************/
213 /* CandidatesSplitter */
214 /************************************************************************/
CandidatesSplitter(const QString & _id)215 CandidatesSplitter::CandidatesSplitter(const QString &_id)
216 : id(_id) {
217 }
218
~CandidatesSplitter()219 CandidatesSplitter::~CandidatesSplitter() {
220 }
221
splitCandidates(const QList<Descriptor> & candidates)222 IntegralBusUtils::SplitResult CandidatesSplitter::splitCandidates(const QList<Descriptor> &candidates) {
223 IntegralBusUtils::SplitResult r;
224 foreach (const Descriptor &c, candidates) {
225 U2OpStatus2Log os;
226 IntegralBusSlot slot = IntegralBusSlot::fromString(c.getId(), os);
227 if (slot.getId().isEmpty() || isMain(slot.getId())) {
228 r.mainDescs << c;
229 } else {
230 r.otherDescs << c;
231 }
232 }
233 return r;
234 }
235
getId() const236 const QString &CandidatesSplitter::getId() const {
237 return id;
238 }
239
240 /************************************************************************/
241 /* CandidatesSplitterRegistry */
242 /************************************************************************/
243 CandidatesSplitterRegistry *CandidatesSplitterRegistry::_instance = nullptr;
instance()244 CandidatesSplitterRegistry *CandidatesSplitterRegistry::instance() {
245 if (nullptr == _instance) {
246 _instance = new CandidatesSplitterRegistry();
247 }
248 return _instance;
249 }
250
findSplitter(const Descriptor & toDesc,DataTypePtr toDatatype)251 CandidatesSplitter *CandidatesSplitterRegistry::findSplitter(const Descriptor &toDesc, DataTypePtr toDatatype) {
252 foreach (CandidatesSplitter *splitter, splitters) {
253 if (splitter->canSplit(toDesc, toDatatype)) {
254 return splitter;
255 }
256 }
257 return nullptr;
258 }
259
findSplitter(const QString & id)260 CandidatesSplitter *CandidatesSplitterRegistry::findSplitter(const QString &id) {
261 foreach (CandidatesSplitter *splitter, splitters) {
262 if (id == splitter->getId()) {
263 return splitter;
264 }
265 }
266 return nullptr;
267 }
268
registerSplitter(CandidatesSplitter * splitter)269 void CandidatesSplitterRegistry::registerSplitter(CandidatesSplitter *splitter) {
270 if (!splitters.contains(splitter)) {
271 splitters.prepend(splitter);
272 }
273 }
274
unregisterSplitter(const QString & id)275 void CandidatesSplitterRegistry::unregisterSplitter(const QString &id) {
276 CandidatesSplitter *splitter = findSplitter(id);
277 CHECK(nullptr != splitter, );
278 splitters.removeAll(splitter);
279 delete splitter;
280 }
281
CandidatesSplitterRegistry()282 CandidatesSplitterRegistry::CandidatesSplitterRegistry() {
283 // The order is needed
284 splitters << new UrlSplitter();
285 splitters << new DatasetsSplitter();
286 splitters << new TextSplitter();
287 splitters << new DefaultSplitter();
288 }
289
~CandidatesSplitterRegistry()290 CandidatesSplitterRegistry::~CandidatesSplitterRegistry() {
291 qDeleteAll(splitters);
292 splitters.clear();
293 }
294
295 } // namespace Workflow
296 } // namespace U2
297