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 "MultipleChromatogramAlignmentImporter.h"
23 
24 #include <U2Core/ChromatogramUtils.h>
25 #include <U2Core/DNAAlphabet.h>
26 #include <U2Core/GObjectTypes.h>
27 #include <U2Core/L10n.h>
28 #include <U2Core/McaDbiUtils.h>
29 #include <U2Core/MultipleAlignmentInfo.h>
30 #include <U2Core/MultipleChromatogramAlignmentObject.h>
31 #include <U2Core/MultipleChromatogramAlignmentRow.h>
32 #include <U2Core/U2AttributeDbi.h>
33 #include <U2Core/U2MsaDbi.h>
34 #include <U2Core/U2ObjectDbi.h>
35 #include <U2Core/U2ObjectRelationsDbi.h>
36 #include <U2Core/U2OpStatus.h>
37 #include <U2Core/U2SafePoints.h>
38 #include <U2Core/U2SequenceDbi.h>
39 #include <U2Core/U2SequenceUtils.h>
40 
41 #include "datatype/msa/MultipleAlignmentRowInfo.h"
42 
43 namespace U2 {
44 
createAlignment(U2OpStatus & os,const U2DbiRef & dbiRef,const QString & folder,MultipleChromatogramAlignment & mca)45 MultipleChromatogramAlignmentObject *MultipleChromatogramAlignmentImporter::createAlignment(U2OpStatus &os,
46                                                                                             const U2DbiRef &dbiRef,
47                                                                                             const QString &folder,
48                                                                                             MultipleChromatogramAlignment &mca) {
49     DbiConnection connection(dbiRef, true, os);
50     CHECK(!os.isCanceled(), nullptr);
51     SAFE_POINT_OP(os, nullptr);
52     SAFE_POINT_EXT(nullptr != connection.dbi, os.setError(L10N::nullPointerError("Destination database")), nullptr);
53 
54     TmpDbiObjects objs(dbiRef, os);
55 
56     // MCA object and info
57     U2Mca dbMca = importMcaObject(os, connection, folder, mca);
58     objs.objects << dbMca.id;
59     CHECK_OP(os, nullptr);
60 
61     importMcaInfo(os, connection, dbMca.id, mca);
62     CHECK_OP(os, nullptr);
63 
64     // MCA rows
65     QList<McaRowDatabaseData> mcaRowsDatabaseData = importRowChildObjects(os, connection, folder, mca);
66     CHECK_OP(os, nullptr);
67 
68     QList<U2McaRow> rows = importRows(os, connection, dbMca, mcaRowsDatabaseData);
69     CHECK_OP(os, nullptr);
70     SAFE_POINT_EXT(rows.size() == mca->getNumRows(), os.setError(QObject::tr("Unexpected error on MCA rows import")), nullptr);
71 
72     for (int i = 0, n = mca->getNumRows(); i < n; ++i) {
73         mca->getMcaRow(i)->setRowDbInfo(rows.at(i));
74     }
75 
76     return new MultipleChromatogramAlignmentObject(mca->getName(), U2EntityRef(dbiRef, dbMca.id), QVariantMap(), mca);
77 }
78 
importMcaObject(U2OpStatus & os,const DbiConnection & connection,const QString & folder,const MultipleChromatogramAlignment & mca)79 U2Mca MultipleChromatogramAlignmentImporter::importMcaObject(U2OpStatus &os, const DbiConnection &connection, const QString &folder, const MultipleChromatogramAlignment &mca) {
80     U2Mca dbMca;
81     const DNAAlphabet *alphabet = mca->getAlphabet();
82     SAFE_POINT_EXT(nullptr != alphabet, os.setError("The alignment alphabet is NULL during importing"), U2Mca());
83 
84     dbMca.alphabet.id = alphabet->getId();
85     dbMca.length = mca->getLength();
86     dbMca.visualName = mca->getName();
87     if (dbMca.visualName.isEmpty()) {
88         QDate date = QDate::currentDate();
89         QString generatedName = "MCA" + date.toString();
90         coreLog.trace(QString("A multiple alignment name was empty. Generated a new name %1").arg(generatedName));
91         dbMca.visualName = generatedName;
92     }
93 
94     U2MsaDbi *msaDbi = connection.dbi->getMsaDbi();
95     SAFE_POINT_EXT(nullptr != msaDbi, os.setError("NULL MSA Dbi during importing an alignment"), U2Mca());
96 
97     dbMca.id = msaDbi->createMcaObject(folder, dbMca.visualName, dbMca.alphabet, dbMca.length, os);
98     CHECK_OP(os, U2Mca());
99 
100     return dbMca;
101 }
102 
importMcaInfo(U2OpStatus & os,const DbiConnection & connection,const U2DataId & mcaId,const MultipleChromatogramAlignment & mca)103 void MultipleChromatogramAlignmentImporter::importMcaInfo(U2OpStatus &os, const DbiConnection &connection, const U2DataId &mcaId, const MultipleChromatogramAlignment &mca) {
104     const QVariantMap info = mca->getInfo();
105 
106     U2AttributeDbi *attributeDbi = connection.dbi->getAttributeDbi();
107     SAFE_POINT_EXT(nullptr != attributeDbi, os.setError("NULL Attribute Dbi during importing an alignment"), );
108 
109     foreach (const QString key, info.keys()) {
110         if (key != MultipleAlignmentInfo::NAME) {  // name is stored in the object
111             const QString value = info.value(key).toString();
112             U2StringAttribute attribute(mcaId, key, value);
113             attributeDbi->createStringAttribute(attribute, os);
114             CHECK_OP(os, );
115         }
116     }
117 }
118 
importRowChildObjects(U2OpStatus & os,const DbiConnection & connection,const QString & folder,const MultipleChromatogramAlignment & mca)119 QList<McaRowDatabaseData> MultipleChromatogramAlignmentImporter::importRowChildObjects(U2OpStatus &os,
120                                                                                        const DbiConnection &connection,
121                                                                                        const QString &folder,
122                                                                                        const MultipleChromatogramAlignment &mca) {
123     QList<McaRowDatabaseData> mcaRowsDatabaseData;
124     UdrDbi *udrDbi = connection.dbi->getUdrDbi();
125     SAFE_POINT_EXT(nullptr != udrDbi, os.setError("NULL UDR Dbi during importing an alignment"), mcaRowsDatabaseData);
126     U2SequenceDbi *sequenceDbi = connection.dbi->getSequenceDbi();
127     SAFE_POINT_EXT(nullptr != sequenceDbi, os.setError("NULL Sequence Dbi during importing an alignment"), mcaRowsDatabaseData);
128 
129     const DNAAlphabet *alphabet = mca->getAlphabet();
130     SAFE_POINT_EXT(nullptr != alphabet, os.setError("MCA alphabet is NULL"), mcaRowsDatabaseData);
131     const U2AlphabetId alphabetId = alphabet->getId();
132 
133     foreach (const MultipleChromatogramAlignmentRow &row, mca->getMcaRows()) {
134         McaRowDatabaseData mcaRowDatabaseData;
135 
136         mcaRowDatabaseData.chromatogram = importChromatogram(os, connection, folder, row->getChromatogram());
137         CHECK_OP(os, mcaRowsDatabaseData);
138 
139         mcaRowDatabaseData.sequence = importSequence(os, connection, folder, row->getSequence(), alphabetId);
140         CHECK_OP(os, mcaRowsDatabaseData);
141 
142         createRelation(os, connection, mcaRowDatabaseData.sequence, mcaRowDatabaseData.chromatogram.id);
143 
144         mcaRowDatabaseData.additionalInfo = row->getAdditionalInfo();
145         importRowAdditionalInfo(os, connection, mcaRowDatabaseData.chromatogram, mcaRowDatabaseData.additionalInfo);
146         CHECK_OP(os, mcaRowsDatabaseData);
147 
148         mcaRowDatabaseData.gapModel = row->getGapModel();
149         mcaRowDatabaseData.rowLength = row->getRowLengthWithoutTrailing();
150 
151         mcaRowsDatabaseData << mcaRowDatabaseData;
152     }
153 
154     return mcaRowsDatabaseData;
155 }
156 
importRows(U2OpStatus & os,const DbiConnection & connection,U2Mca & dbMca,const QList<McaRowDatabaseData> & mcaRowsDatabaseData)157 QList<U2McaRow> MultipleChromatogramAlignmentImporter::importRows(U2OpStatus &os,
158                                                                   const DbiConnection &connection,
159                                                                   U2Mca &dbMca,
160                                                                   const QList<McaRowDatabaseData> &mcaRowsDatabaseData) {
161     QList<U2McaRow> rows;
162 
163     foreach (const McaRowDatabaseData &mcaRowDatabaseData, mcaRowsDatabaseData) {
164         U2McaRow row;
165         row.chromatogramId = mcaRowDatabaseData.chromatogram.id;
166         row.sequenceId = mcaRowDatabaseData.sequence.id;
167         row.gaps = mcaRowDatabaseData.gapModel;
168         row.gstart = 0;
169         row.gend = mcaRowDatabaseData.sequence.length;
170         row.length = mcaRowDatabaseData.rowLength;
171 
172         rows << row;
173     }
174 
175     McaDbiUtils::addRows(os, U2EntityRef(connection.dbi->getDbiRef(), dbMca.id), rows);
176     CHECK_OP(os, QList<U2McaRow>());
177     return rows;
178 }
179 
importChromatogram(U2OpStatus & os,const DbiConnection & connection,const QString & folder,const DNAChromatogram & chromatogram)180 U2Chromatogram MultipleChromatogramAlignmentImporter::importChromatogram(U2OpStatus &os,
181                                                                          const DbiConnection &connection,
182                                                                          const QString &folder,
183                                                                          const DNAChromatogram &chromatogram) {
184     const U2EntityRef chromatogramRef = ChromatogramUtils::import(os, connection.dbi->getDbiRef(), folder, chromatogram);
185     CHECK_OP(os, U2Chromatogram());
186     connection.dbi->getObjectDbi()->setObjectRank(chromatogramRef.entityId, U2DbiObjectRank_Child, os);
187     CHECK_OP(os, U2Chromatogram());
188     return ChromatogramUtils::getChromatogramDbInfo(os, chromatogramRef);
189 }
190 
importSequence(U2OpStatus & os,const DbiConnection & connection,const QString & folder,const DNASequence & sequence,const U2AlphabetId & alphabetId)191 U2Sequence MultipleChromatogramAlignmentImporter::importSequence(U2OpStatus &os,
192                                                                  const DbiConnection &connection,
193                                                                  const QString &folder,
194                                                                  const DNASequence &sequence,
195                                                                  const U2AlphabetId &alphabetId) {
196     const U2EntityRef sequenceRef = U2SequenceUtils::import(os, connection.dbi->getDbiRef(), folder, sequence, alphabetId);
197     CHECK_OP(os, U2Sequence());
198     connection.dbi->getObjectDbi()->setObjectRank(sequenceRef.entityId, U2DbiObjectRank_Child, os);
199     CHECK_OP(os, U2Sequence());
200     return connection.dbi->getSequenceDbi()->getSequenceObject(sequenceRef.entityId, os);
201 }
202 
importRowAdditionalInfo(U2OpStatus & os,const DbiConnection & connection,const U2Chromatogram & chromatogram,const QVariantMap & additionalInfo)203 void MultipleChromatogramAlignmentImporter::importRowAdditionalInfo(U2OpStatus &os, const DbiConnection &connection, const U2Chromatogram &chromatogram, const QVariantMap &additionalInfo) {
204     U2IntegerAttribute reversedAttribute;
205     reversedAttribute.objectId = chromatogram.id;
206     reversedAttribute.name = MultipleAlignmentRowInfo::REVERSED;
207     reversedAttribute.version = chromatogram.version;
208     reversedAttribute.value = MultipleAlignmentRowInfo::getReversed(additionalInfo) ? 1 : 0;
209 
210     connection.dbi->getAttributeDbi()->createIntegerAttribute(reversedAttribute, os);
211     CHECK_OP(os, );
212 
213     U2IntegerAttribute complementedAttribute;
214     complementedAttribute.objectId = chromatogram.id;
215     complementedAttribute.name = MultipleAlignmentRowInfo::COMPLEMENTED;
216     complementedAttribute.version = chromatogram.version;
217     complementedAttribute.value = MultipleAlignmentRowInfo::getComplemented(additionalInfo) ? 1 : 0;
218 
219     connection.dbi->getAttributeDbi()->createIntegerAttribute(complementedAttribute, os);
220     CHECK_OP(os, );
221 }
222 
createRelation(U2OpStatus & os,const DbiConnection & connection,const U2Sequence & sequence,const U2DataId & chromatogramId)223 void MultipleChromatogramAlignmentImporter::createRelation(U2OpStatus &os, const DbiConnection &connection, const U2Sequence &sequence, const U2DataId &chromatogramId) {
224     U2ObjectRelation dbRelation;
225     dbRelation.id = chromatogramId;
226     dbRelation.referencedName = sequence.visualName;
227     dbRelation.referencedObject = sequence.id;
228     dbRelation.referencedType = GObjectTypes::SEQUENCE;
229     dbRelation.relationRole = ObjectRole_Sequence;
230 
231     connection.dbi->getObjectRelationsDbi()->createObjectRelation(dbRelation, os);
232     CHECK_OP(os, );
233 }
234 
235 }  // namespace U2
236