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 "Marker.h"
23
24 #include <U2Core/DNASequence.h>
25 #include <U2Core/QVariantUtils.h>
26
27 #include <U2Lang/MarkerUtils.h>
28 #include <U2Lang/WorkflowEnv.h>
29
30 static const QString LENGTH_SLOT_ID("length-marker");
31 static const QString ANN_COUNT_SLOT_ID("ann-count-marker");
32 static const QString ANN_VALUE_SLOT_ID("ann-value-marker");
33 static const QString FILENAME_SLOT_ID("filename-marker");
34
35 namespace U2 {
36
37 const QString MarkerTypes::SEQ_LENGTH_MARKER_ID("sequence-length");
38 const QString MarkerTypes::SEQ_NAME_MARKER_ID("sequence-name");
39 const QString MarkerTypes::ANNOTATION_COUNT_MARKER_ID("annotations-count");
40 const QString MarkerTypes::ANNOTATION_LENGTH_MARKER_ID("annotation-length");
41 const QString MarkerTypes::QUAL_INT_VALUE_MARKER_ID("qualifier-int-value");
42 const QString MarkerTypes::QUAL_TEXT_VALUE_MARKER_ID("qualifier-text-value");
43 const QString MarkerTypes::QUAL_FLOAT_VALUE_MARKER_ID("qualifier-float-value");
44 const QString MarkerTypes::TEXT_MARKER_ID("text");
45
getDataTypeById(const QString & typeId)46 MarkerDataType MarkerTypes::getDataTypeById(const QString &typeId) {
47 if (SEQ_LENGTH_MARKER_ID == typeId) {
48 return INTEGER;
49 } else if (ANNOTATION_COUNT_MARKER_ID == typeId) {
50 return INTEGER;
51 } else if (ANNOTATION_LENGTH_MARKER_ID == typeId) {
52 return INTEGER;
53 } else if (QUAL_INT_VALUE_MARKER_ID == typeId) {
54 return INTEGER;
55 } else if (QUAL_TEXT_VALUE_MARKER_ID == typeId) {
56 return STRING;
57 } else if (QUAL_FLOAT_VALUE_MARKER_ID == typeId) {
58 return FLOAT;
59 } else if (TEXT_MARKER_ID == typeId) {
60 return STRING;
61 } else if (SEQ_NAME_MARKER_ID == typeId) {
62 return STRING;
63 } else {
64 assert(0);
65 return MarkerDataType();
66 }
67 }
68
SEQ_LENGTH()69 const Descriptor MarkerTypes::SEQ_LENGTH() {
70 return Descriptor(MarkerTypes::SEQ_LENGTH_MARKER_ID, tr("Length markers"), tr("Length markers group."));
71 }
SEQ_NAME()72 const Descriptor MarkerTypes::SEQ_NAME() {
73 return Descriptor(MarkerTypes::SEQ_NAME_MARKER_ID, tr("Sequence name markers"), tr("Sequence name markers group."));
74 }
ANNOTATION_COUNT()75 const Descriptor MarkerTypes::ANNOTATION_COUNT() {
76 return Descriptor(MarkerTypes::ANNOTATION_COUNT_MARKER_ID, tr("Annotation count markers"), tr("Annotation count markers group."));
77 }
ANNOTATION_LENGTH()78 const Descriptor MarkerTypes::ANNOTATION_LENGTH() {
79 return Descriptor(MarkerTypes::ANNOTATION_LENGTH_MARKER_ID, tr("Annotation length markers"), tr("Annotation length markers group."));
80 }
QUAL_INT_VALUE()81 const Descriptor MarkerTypes::QUAL_INT_VALUE() {
82 return Descriptor(MarkerTypes::QUAL_INT_VALUE_MARKER_ID, tr("Qualifier integer value markers"), tr("Qualifier integer value markers group."));
83 }
QUAL_FLOAT_VALUE()84 const Descriptor MarkerTypes::QUAL_FLOAT_VALUE() {
85 return Descriptor(MarkerTypes::QUAL_FLOAT_VALUE_MARKER_ID, tr("Qualifier float value markers"), tr("Qualifier float value markers group."));
86 }
QUAL_TEXT_VALUE()87 const Descriptor MarkerTypes::QUAL_TEXT_VALUE() {
88 return Descriptor(MarkerTypes::QUAL_TEXT_VALUE_MARKER_ID, tr("Qualifier text value markers"), tr("Qualifier text value markers group."));
89 }
TEXT()90 const Descriptor MarkerTypes::TEXT() {
91 return Descriptor(MarkerTypes::TEXT_MARKER_ID, tr("Text markers"), tr("Text markers group."));
92 }
93
getSlotByMarkerType(const QString & markerId,const QString & slotName)94 const Descriptor MarkerSlots::getSlotByMarkerType(const QString &markerId, const QString &slotName) {
95 if (markerId == MarkerTypes::SEQ_LENGTH_MARKER_ID) {
96 return Descriptor(slotName, slotName, tr("Sequence length marker."));
97 } else if (markerId == MarkerTypes::ANNOTATION_COUNT_MARKER_ID) {
98 return Descriptor(slotName, slotName, tr("Annotation count marker."));
99 } else if (markerId == MarkerTypes::ANNOTATION_LENGTH_MARKER_ID) {
100 return Descriptor(slotName, slotName, tr("Annotation length marker."));
101 } else if (markerId == MarkerTypes::QUAL_INT_VALUE_MARKER_ID) {
102 return Descriptor(slotName, slotName, tr("Qualifier integer value marker."));
103 } else if (markerId == MarkerTypes::QUAL_TEXT_VALUE_MARKER_ID) {
104 return Descriptor(slotName, slotName, tr("Qualifier text value marker."));
105 } else if (markerId == MarkerTypes::QUAL_FLOAT_VALUE_MARKER_ID) {
106 return Descriptor(slotName, slotName, tr("Qualifier float value marker."));
107 } else if (markerId == MarkerTypes::TEXT_MARKER_ID) {
108 return Descriptor(slotName, slotName, tr("Text marker."));
109 } else if (markerId == MarkerTypes::SEQ_NAME_MARKER_ID) {
110 return Descriptor(slotName, slotName, tr("Sequence name marker."));
111 } else {
112 assert(0);
113 return Descriptor();
114 }
115 }
116
IN_MARKER_SEQ_PORT()117 const QString MarkerPorts::IN_MARKER_SEQ_PORT() {
118 return "in-marked-seq";
119 }
OUT_MARKER_SEQ_PORT()120 const QString MarkerPorts::OUT_MARKER_SEQ_PORT() {
121 return "out-marked-seq";
122 }
123
createInstanse(const QString & type,const QVariant & additionalParam)124 Marker *MarkerFactory::createInstanse(const QString &type, const QVariant &additionalParam) {
125 Marker *m = nullptr;
126 if (type == MarkerTypes::QUAL_INT_VALUE_MARKER_ID || type == MarkerTypes::QUAL_TEXT_VALUE_MARKER_ID || type == MarkerTypes::QUAL_FLOAT_VALUE_MARKER_ID) {
127 m = new QualifierMarker(type, "NewQualMarker", additionalParam.toString());
128 } else if (MarkerTypes::ANNOTATION_LENGTH_MARKER_ID == type || MarkerTypes::ANNOTATION_COUNT_MARKER_ID == type) {
129 m = new AnnotationMarker(type, "NewQualMarker", additionalParam.toString());
130 } else if (MarkerTypes::TEXT_MARKER_ID == type) {
131 m = new TextMarker(type, "NewTextMarker");
132 } else {
133 m = new SequenceMarker(type, "NewSequenceMarker");
134 }
135
136 if (NONE != m->hasAdditionalParameter()) {
137 m->setAdditionalParameter(additionalParam);
138 }
139
140 return m;
141 }
142
143 /************************************************************************/
144 /* Marker */
145 /************************************************************************/
Marker(const QString & markerType,const QString & markerName)146 Marker::Marker(const QString &markerType, const QString &markerName)
147 : type(markerType), name(markerName) {
148 dataType = MarkerTypes::getDataTypeById(markerType);
149 values.insert(MarkerUtils::REST_OPERATION, tr("Rest"));
150 }
151
Marker(const Marker & m)152 Marker::Marker(const Marker &m)
153 : QObject(), type(m.type), name(m.name), dataType(m.dataType), values(m.values) {
154 }
155
addValue(QString name,QString value)156 void Marker::addValue(QString name, QString value) {
157 values.insert(name, value);
158 }
159
hasAdditionalParameter()160 ParameterState Marker::hasAdditionalParameter() {
161 return NONE;
162 }
163
setAdditionalParameter(const QVariant &)164 void Marker::setAdditionalParameter(const QVariant &) {
165 }
166
getAdditionalParameter()167 QVariant Marker::getAdditionalParameter() {
168 return QVariant();
169 }
170
getAdditionalParameterName()171 QString Marker::getAdditionalParameterName() {
172 return "";
173 }
174
getMarkingResult(const QVariant & object)175 QString Marker::getMarkingResult(const QVariant &object) {
176 foreach (QString val, values.keys()) {
177 if (MarkerUtils::REST_OPERATION == val) {
178 continue;
179 }
180 QVariantList expr;
181 bool res = MarkerUtils::stringToValue(dataType, val, expr);
182 if (!res) {
183 continue;
184 }
185
186 bool marked = false;
187 switch (dataType) {
188 case INTEGER:
189 marked = getMarkerIntResult(object, expr);
190 break;
191 case FLOAT:
192 marked = getMarkerFloatResult(object, expr);
193 break;
194 case BOOLEAN:
195 // marked = getMarkerBooleanResult(object, expr);
196 break;
197 case STRING:
198 marked = getMarkerStringResult(object, expr);
199 break;
200 }
201 if (marked) {
202 return values.value(val);
203 }
204 }
205
206 return values.value(MarkerUtils::REST_OPERATION);
207 }
208
getMarkerIntResult(const QVariant & object,QVariantList & expr)209 bool Marker::getMarkerIntResult(const QVariant &object, QVariantList &expr) {
210 int obj = object.toInt();
211 QString operation = expr.at(0).toString();
212
213 if (MarkerUtils::LESS_OPERATION == operation) {
214 int val = expr.at(1).toInt();
215 if (obj <= val) {
216 return true;
217 }
218 } else if (MarkerUtils::GREATER_OPERATION == operation) {
219 int val = expr.at(1).toInt();
220 if (obj >= val) {
221 return true;
222 }
223 } else if (MarkerUtils::INTERVAL_OPERATION == operation) {
224 int val1 = expr.at(1).toInt();
225 int val2 = expr.at(2).toInt();
226
227 if (obj >= val1 && obj <= val2) {
228 return true;
229 }
230 }
231
232 return false;
233 }
234
getMarkerFloatResult(const QVariant & object,QVariantList & expr)235 bool Marker::getMarkerFloatResult(const QVariant &object, QVariantList &expr) {
236 float obj = object.toFloat();
237 QString operation = expr.at(0).toString();
238
239 if (MarkerUtils::LESS_OPERATION == operation) {
240 float val = expr.at(1).toFloat();
241 if (obj <= val) {
242 return true;
243 }
244 } else if (MarkerUtils::GREATER_OPERATION == operation) {
245 float val = expr.at(1).toFloat();
246 if (obj >= val) {
247 return true;
248 }
249 } else if (MarkerUtils::INTERVAL_OPERATION == operation) {
250 float val1 = expr.at(1).toFloat();
251 float val2 = expr.at(2).toFloat();
252
253 if (obj >= val1 && obj <= val2) {
254 return true;
255 }
256 }
257
258 return false;
259 }
260
getMarkerStringResult(const QVariant & object,QVariantList & expr)261 bool Marker::getMarkerStringResult(const QVariant &object, QVariantList &expr) {
262 QString obj = object.toString();
263 QString operation = expr.at(0).toString();
264 QString val = expr.at(1).toString();
265
266 if (MarkerUtils::STARTS_OPERATION == operation) {
267 return obj.startsWith(val);
268 } else if (MarkerUtils::ENDS_OPERATION == operation) {
269 return obj.endsWith(val);
270 } else if (MarkerUtils::CONTAINS_OPERATION == operation) {
271 return obj.contains(val);
272 } else if (MarkerUtils::REGEXP_OPERATION == operation) {
273 QRegExp rx(val);
274 rx.setPatternSyntax(QRegExp::Wildcard);
275
276 return rx.exactMatch(obj);
277 }
278
279 return false;
280 }
281
getName() const282 const QString &Marker::getName() const {
283 return name;
284 }
285
getType() const286 const QString &Marker::getType() const {
287 return type;
288 }
289
getValues() const290 const QMap<QString, QString> &Marker::getValues() const {
291 return values;
292 }
293
getValues()294 QMap<QString, QString> &Marker::getValues() {
295 return values;
296 }
297
setName(const QString & newName)298 void Marker::setName(const QString &newName) {
299 name = newName;
300 }
301
toString() const302 const QString Marker::toString() const {
303 QString res;
304
305 foreach (QString key, values.keys()) {
306 res += key + " : " + values.value(key) + "; ";
307 }
308 return res;
309 }
310
311 /************************************************************************/
312 /* SequencerMarker */
313 /************************************************************************/
getMarkingResult(const QVariant & object)314 QString SequenceMarker::getMarkingResult(const QVariant &object) {
315 DNASequence seq = object.value<DNASequence>();
316
317 if (MarkerTypes::SEQ_LENGTH_MARKER_ID == type) {
318 return Marker::getMarkingResult(seq.length());
319 } else if (MarkerTypes::SEQ_NAME_MARKER_ID == type) {
320 return Marker::getMarkingResult(seq.getName());
321 } else {
322 assert(0);
323 return values.value(MarkerUtils::REST_OPERATION);
324 }
325 }
326
getGroup()327 MarkerGroup SequenceMarker::getGroup() {
328 return SEQUENCE;
329 }
330
clone()331 Marker *SequenceMarker::clone() {
332 return new SequenceMarker(*this);
333 }
334
335 /************************************************************************/
336 /* QualifierMarker */
337 /************************************************************************/
getMarkingResult(const QVariant & object)338 QString QualifierMarker::getMarkingResult(const QVariant &object) {
339 const QString rest = values.value(MarkerUtils::REST_OPERATION);
340
341 QList<SharedAnnotationData> anns;
342 foreach (const QVariant &ann, object.toList()) {
343 SAFE_POINT(ann.canConvert<SharedAnnotationData>(), "Invalid annotation data encountered!", QString());
344 anns << ann.value<SharedAnnotationData>();
345 }
346
347 for (const SharedAnnotationData &ann : qAsConst(anns)) {
348 foreach (const U2Qualifier &qual, ann->qualifiers) {
349 if (qual.name == qualName) {
350 bool ok = false;
351 QVariant value;
352 if (MarkerTypes::QUAL_INT_VALUE_MARKER_ID == type) {
353 value = qVariantFromValue(qual.value.toInt(&ok));
354 } else if (MarkerTypes::QUAL_FLOAT_VALUE_MARKER_ID == type) {
355 value = qVariantFromValue(qual.value.toFloat(&ok));
356 } else if (MarkerTypes::QUAL_TEXT_VALUE_MARKER_ID == type) {
357 value = qVariantFromValue(qual.value);
358 ok = true;
359 } else {
360 FAIL("Unexpected marker type!", rest);
361 }
362 SAFE_POINT(ok, "Variant conversion error!", QString());
363 QString mark = Marker::getMarkingResult(value);
364 if (rest != mark) {
365 return mark;
366 }
367 }
368 }
369 }
370 return rest;
371 }
372
getGroup()373 MarkerGroup QualifierMarker::getGroup() {
374 return QUALIFIER;
375 }
376
getQualifierName() const377 const QString &QualifierMarker::getQualifierName() const {
378 return qualName;
379 }
380
clone()381 Marker *QualifierMarker::clone() {
382 return new QualifierMarker(*this);
383 }
384
hasAdditionalParameter()385 ParameterState QualifierMarker::hasAdditionalParameter() {
386 return REQUIRED;
387 }
388
setAdditionalParameter(const QVariant & param)389 void QualifierMarker::setAdditionalParameter(const QVariant ¶m) {
390 qualName = param.toString();
391 }
392
getAdditionalParameter()393 QVariant QualifierMarker::getAdditionalParameter() {
394 return qualName;
395 }
396
getAdditionalParameterName()397 QString QualifierMarker::getAdditionalParameterName() {
398 return tr("Qualifier name");
399 }
400
401 /************************************************************************/
402 /* AnnotationMarker */
403 /************************************************************************/
getMarkingResult(const QVariant & object)404 QString AnnotationMarker::getMarkingResult(const QVariant &object) {
405 QList<SharedAnnotationData> anns;
406 foreach (const QVariant &ann, object.toList()) {
407 SAFE_POINT(ann.canConvert<SharedAnnotationData>(), "Invalid annotation data encountered!", QString());
408 anns << ann.value<SharedAnnotationData>();
409 }
410
411 if (MarkerTypes::ANNOTATION_COUNT_MARKER_ID == type) {
412 int count = 0;
413 if (annName.isEmpty()) {
414 count = anns.size();
415 } else {
416 foreach (const SharedAnnotationData &ann, anns) {
417 if (ann->name == annName) {
418 count++;
419 }
420 }
421 }
422 return Marker::getMarkingResult(qVariantFromValue(count));
423 } else if (MarkerTypes::ANNOTATION_LENGTH_MARKER_ID == type) {
424 return values.value(MarkerUtils::REST_OPERATION);
425 } else {
426 assert(0);
427 }
428
429 return values.value(MarkerUtils::REST_OPERATION);
430 }
431
getGroup()432 MarkerGroup AnnotationMarker::getGroup() {
433 return ANNOTATION;
434 }
435
getAnnotationName() const436 const QString &AnnotationMarker::getAnnotationName() const {
437 return annName;
438 }
439
clone()440 Marker *AnnotationMarker::clone() {
441 return new AnnotationMarker(*this);
442 }
443
hasAdditionalParameter()444 ParameterState AnnotationMarker::hasAdditionalParameter() {
445 return NOT_REQUIRED;
446 }
447
setAdditionalParameter(const QVariant & param)448 void AnnotationMarker::setAdditionalParameter(const QVariant ¶m) {
449 annName = param.toString();
450 }
451
getAdditionalParameter()452 QVariant AnnotationMarker::getAdditionalParameter() {
453 return annName;
454 }
455
getAdditionalParameterName()456 QString AnnotationMarker::getAdditionalParameterName() {
457 return tr("Annotation name");
458 }
459
460 /************************************************************************/
461 /* TextMarker */
462 /************************************************************************/
getMarkingResult(const QVariant & object)463 QString TextMarker::getMarkingResult(const QVariant &object) {
464 if (MarkerTypes::TEXT_MARKER_ID == type) {
465 return Marker::getMarkingResult(object);
466 } else {
467 assert(0);
468 }
469
470 return values.value(MarkerUtils::REST_OPERATION);
471 }
472
getGroup()473 MarkerGroup TextMarker::getGroup() {
474 return TEXT;
475 }
476
clone()477 Marker *TextMarker::clone() {
478 return new TextMarker(*this);
479 }
480
481 } // namespace U2
482