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 "AssemblyObject.h"
23 
24 #include <U2Core/AssemblyImporter.h>
25 #include <U2Core/DocumentModel.h>
26 #include <U2Core/GHints.h>
27 #include <U2Core/U2AssemblyDbi.h>
28 #include <U2Core/U2AttributeDbi.h>
29 #include <U2Core/U2AttributeUtils.h>
30 #include <U2Core/U2CoreAttributes.h>
31 #include <U2Core/U2DbiUtils.h>
32 #include <U2Core/U2ObjectDbi.h>
33 #include <U2Core/U2OpStatus.h>
34 #include <U2Core/U2OpStatusUtils.h>
35 #include <U2Core/U2SafePoints.h>
36 
37 namespace U2 {
38 
AssemblyObject(const QString & objectName,const U2EntityRef & ref,const QVariantMap & hints)39 AssemblyObject::AssemblyObject(const QString &objectName, const U2EntityRef &ref, const QVariantMap &hints)
40     : GObject(GObjectTypes::ASSEMBLY, objectName, hints) {
41     this->entityRef = ref;
42 }
43 
clone(const U2DbiRef & dstDbiRef,U2OpStatus & os,const QVariantMap & hints) const44 GObject *AssemblyObject::clone(const U2DbiRef &dstDbiRef, U2OpStatus &os, const QVariantMap &hints) const {
45     GHintsDefaultImpl gHints(getGHintsMap());
46     gHints.setAll(hints);
47 
48     U2EntityRef dstEntityRef = AssemblyObject::dbi2dbiClone(this, dstDbiRef, os, gHints.getMap());
49     CHECK_OP(os, nullptr);
50     AssemblyObject *dstObj = new AssemblyObject(this->getGObjectName(), dstEntityRef, gHints.getMap());
51 
52     return dstObj;
53 }
54 
55 class CloneInfo : public U2AssemblyReadsImportInfo {
56 public:
CloneInfo(qint64 readsCount,U2OpStatus & os)57     CloneInfo(qint64 readsCount, U2OpStatus &os)
58         : U2AssemblyReadsImportInfo(nullptr), os(os), readsCount(readsCount), addedCount(0), currentChunkSize(0) {
59         chunkSize = readsCount / 100;
60     }
61 
onReadImported()62     void onReadImported() {
63         addedCount++;
64         currentChunkSize++;
65         if (currentChunkSize >= chunkSize) {
66             os.setProgress(100 * addedCount / readsCount);
67             currentChunkSize = 0;
68         }
69     }
70 
71 private:
72     U2OpStatus &os;
73     qint64 readsCount;
74     qint64 addedCount;
75     qint64 currentChunkSize;
76     qint64 chunkSize;
77 };
78 
copyReadsUnrelatedAttributes(const U2DataId & srcObjId,const U2DataId & dstObjId,U2AttributeDbi * srcAttributeDbi,U2AttributeDbi * dstAttributeDbi,U2OpStatus & os)79 void copyReadsUnrelatedAttributes(const U2DataId &srcObjId, const U2DataId &dstObjId, U2AttributeDbi *srcAttributeDbi, U2AttributeDbi *dstAttributeDbi, U2OpStatus &os) {
80     CHECK_EXT(nullptr != srcAttributeDbi, os.setError("NULL source attribute dbi"), );
81     CHECK_EXT(nullptr != dstAttributeDbi, os.setError("NULL destination attribute dbi"), );
82 
83     U2Dbi *dstDbi = dstAttributeDbi->getRootDbi();
84     U2Dbi *srcDbi = srcAttributeDbi->getRootDbi();
85     CHECK_EXT(nullptr != srcDbi, os.setError("NULL source root dbi"), );
86     CHECK_EXT(nullptr != dstDbi, os.setError("NULL destination root dbi"), );
87 
88     if (!dstDbi->getFeatures().contains(U2DbiFeature_WriteAttributes)) {
89         os.setError("Destination dbi does not support writing");
90         return;
91     }
92 
93     const QStringList attributesNotToCopy = U2BaseAttributeName::getReadsRelatedAttributes();
94 
95     QList<U2DataId> attrIds = srcAttributeDbi->getObjectAttributes(srcObjId, "", os);
96     CHECK_OP(os, );
97 
98     foreach (const U2DataId &attrId, attrIds) {
99         U2DataType attrType = srcDbi->getEntityTypeById(attrId);
100         if (U2Type::AttributeInteger == attrType) {
101             U2IntegerAttribute attr = srcAttributeDbi->getIntegerAttribute(attrId, os);
102             CHECK_OP(os, );
103             if (attributesNotToCopy.contains(attr.name)) {
104                 continue;
105             }
106             attr.objectId = dstObjId;
107             dstAttributeDbi->createIntegerAttribute(attr, os);
108         } else if (U2Type::AttributeReal == attrType) {
109             U2RealAttribute attr = srcAttributeDbi->getRealAttribute(attrId, os);
110             CHECK_OP(os, );
111             if (attributesNotToCopy.contains(attr.name)) {
112                 continue;
113             }
114             attr.objectId = dstObjId;
115             dstAttributeDbi->createRealAttribute(attr, os);
116         } else if (U2Type::AttributeString == attrType) {
117             U2StringAttribute attr = srcAttributeDbi->getStringAttribute(attrId, os);
118             CHECK_OP(os, );
119             if (attributesNotToCopy.contains(attr.name)) {
120                 continue;
121             }
122             attr.objectId = dstObjId;
123             dstAttributeDbi->createStringAttribute(attr, os);
124         } else if (U2Type::AttributeByteArray == attrType) {
125             U2ByteArrayAttribute attr = srcAttributeDbi->getByteArrayAttribute(attrId, os);
126             CHECK_OP(os, );
127             if (attributesNotToCopy.contains(attr.name)) {
128                 continue;
129             }
130             attr.objectId = dstObjId;
131             dstAttributeDbi->createByteArrayAttribute(attr, os);
132         }
133         CHECK_OP(os, );
134     }
135 }
136 
dbi2dbiExtractRegion(const AssemblyObject * const srcObj,const U2DbiRef & dstDbiRef,U2OpStatus & os,const U2Region & desiredRegion,const QVariantMap & hints)137 U2EntityRef AssemblyObject::dbi2dbiExtractRegion(const AssemblyObject *const srcObj, const U2DbiRef &dstDbiRef, U2OpStatus &os, const U2Region &desiredRegion, const QVariantMap &hints) {
138     U2DbiRef srcDbiRef = srcObj->getEntityRef().dbiRef;
139     U2DataId srcObjId = srcObj->getEntityRef().entityId;
140     const QString dstFolder = hints.value(DocumentFormat::DBI_FOLDER_HINT, U2ObjectDbi::ROOT_FOLDER).toString();
141 
142     DbiConnection dstCon(dstDbiRef, true, os);
143     CHECK_OP(os, U2EntityRef());
144     DbiConnection srcCon(srcDbiRef, os);
145     CHECK_OP(os, U2EntityRef());
146 
147     U2ObjectDbi *dstObjectDbi = dstCon.dbi->getObjectDbi();
148     U2ObjectDbi *srcObjectDbi = srcCon.dbi->getObjectDbi();
149     SAFE_POINT_EXT(nullptr != dstObjectDbi, os.setError("NULL destination object dbi"), U2EntityRef());
150     SAFE_POINT_EXT(nullptr != srcObjectDbi, os.setError("NULL source object dbi"), U2EntityRef());
151 
152     U2AssemblyDbi *dstAssemblyDbi = dstCon.dbi->getAssemblyDbi();
153     U2AssemblyDbi *srcAssemblyDbi = srcCon.dbi->getAssemblyDbi();
154     SAFE_POINT_EXT(nullptr != dstAssemblyDbi, os.setError("NULL destination assembly dbi"), U2EntityRef());
155     SAFE_POINT_EXT(nullptr != srcAssemblyDbi, os.setError("NULL source assembly dbi"), U2EntityRef());
156 
157     // prepare reads
158     CHECK_OP(os, U2EntityRef());
159     qint64 readsCount = srcAssemblyDbi->countReads(srcObjId, desiredRegion, os);
160     CHECK_OP(os, U2EntityRef());
161     U2DbiIterator<U2AssemblyRead> *iter = srcAssemblyDbi->getReads(srcObjId, desiredRegion, os, true);
162     QScopedPointer<U2DbiIterator<U2AssemblyRead>> iterPtr(iter);
163     CHECK_OP(os, U2EntityRef());
164     Q_UNUSED(iterPtr);
165 
166     // copy object
167     U2Assembly assembly;
168     assembly.visualName = srcObj->getGObjectName();
169     CloneInfo info(readsCount, os);
170 
171     AssemblyImporter importer(os);
172     importer.createAssembly(dstDbiRef, dstFolder, iter, info, assembly);
173     CHECK_OP(os, U2EntityRef());
174 
175     // copy attributes
176     U2AttributeDbi *srcAttributeDbi = srcCon.dbi->getAttributeDbi();
177     U2AttributeDbi *dstAttributeDbi = dstCon.dbi->getAttributeDbi();
178     if (desiredRegion == U2_REGION_MAX) {
179         U2AttributeUtils::copyObjectAttributes(srcObjId, assembly.id, srcAttributeDbi, dstAttributeDbi, os);
180     } else {
181         copyReadsUnrelatedAttributes(srcObjId, assembly.id, srcAttributeDbi, dstAttributeDbi, os);
182     }
183     CHECK_OP(os, U2EntityRef());
184 
185     U2EntityRef dstEntityRef(dstDbiRef, assembly.id);
186 
187     return dstEntityRef;
188 }
189 
dbi2dbiClone(const AssemblyObject * const srcObj,const U2DbiRef & dstDbiRef,U2OpStatus & os,const QVariantMap & hints)190 U2EntityRef AssemblyObject::dbi2dbiClone(const AssemblyObject *const srcObj, const U2DbiRef &dstDbiRef, U2OpStatus &os, const QVariantMap &hints) {
191     return dbi2dbiExtractRegion(srcObj, dstDbiRef, os, U2_REGION_MAX, hints);
192 }
193 
194 }  // namespace U2
195