blob_splitter_maker.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:19k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: blob_splitter_maker.cpp,v $
  4.  * PRODUCTION Revision 1000.2  2004/06/01 19:24:50  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.10
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: blob_splitter_maker.cpp,v 1000.2 2004/06/01 19:24:50 gouriano Exp $
  10. * ===========================================================================
  11. *
  12. *                            PUBLIC DOMAIN NOTICE
  13. *               National Center for Biotechnology Information
  14. *
  15. *  This software/database is a "United States Government Work" under the
  16. *  terms of the United States Copyright Act.  It was written as part of
  17. *  the author's official duties as a United States Government employee and
  18. *  thus cannot be copyrighted.  This software/database is freely available
  19. *  to the public for use. The National Library of Medicine and the U.S.
  20. *  Government have not placed any restriction on its use or reproduction.
  21. *
  22. *  Although all reasonable efforts have been taken to ensure the accuracy
  23. *  and reliability of the software and data, the NLM and the U.S.
  24. *  Government do not and cannot warrant the performance or results that
  25. *  may be obtained by using this software or data. The NLM and the U.S.
  26. *  Government disclaim all warranties, express or implied, including
  27. *  warranties of performance, merchantability or fitness for any particular
  28. *  purpose.
  29. *
  30. *  Please cite the author in any work or product based on this material.
  31. *
  32. * ===========================================================================
  33. *
  34. * Author:  Eugene Vasilchenko
  35. *
  36. * File Description:
  37. *   Application for splitting blobs withing ID1 cache
  38. *
  39. * ===========================================================================
  40. */
  41. #include <ncbi_pch.hpp>
  42. #include <objmgr/split/blob_splitter_impl.hpp>
  43. #include <serial/objostr.hpp>
  44. #include <serial/serial.hpp>
  45. #include <serial/iterator.hpp>
  46. #include <objects/general/Object_id.hpp>
  47. #include <objects/seqloc/Seq_id.hpp>
  48. #include <objects/seqloc/Seq_loc.hpp>
  49. #include <objects/seqset/Seq_entry.hpp>
  50. #include <objects/seqset/Bioseq_set.hpp>
  51. #include <objects/seq/Bioseq.hpp>
  52. #include <objects/seq/Seq_annot.hpp>
  53. #include <objects/seq/Annot_id.hpp>
  54. #include <objects/seq/Annot_descr.hpp>
  55. #include <objects/seq/Annotdesc.hpp>
  56. #include <objects/seqalign/Seq_align.hpp>
  57. #include <objects/seqfeat/Seq_feat.hpp>
  58. #include <objects/seqres/Seq_graph.hpp>
  59. #include <objects/seqsplit/ID2S_Split_Info.hpp>
  60. #include <objects/seqsplit/ID2S_Chunk_Id.hpp>
  61. #include <objects/seqsplit/ID2S_Chunk.hpp>
  62. #include <objects/seqsplit/ID2S_Chunk_Data.hpp>
  63. #include <objects/seqsplit/ID2S_Chunk_Info.hpp>
  64. #include <objects/seqsplit/ID2S_Chunk_Content.hpp>
  65. #include <objects/seqsplit/ID2S_Seq_annot_Info.hpp>
  66. #include <objects/seqsplit/ID2S_Feat_type_Info.hpp>
  67. #include <objects/seqsplit/ID2_Seq_loc.hpp>
  68. #include <objects/seqsplit/ID2_Id_Range.hpp>
  69. #include <objects/seqsplit/ID2_Seq_range.hpp>
  70. #include <objects/seqsplit/ID2_Interval.hpp>
  71. #include <objects/seqsplit/ID2_Packed_Seq_ints.hpp>
  72. #include <objmgr/split/blob_splitter.hpp>
  73. #include <objmgr/split/object_splitinfo.hpp>
  74. #include <objmgr/split/annot_piece.hpp>
  75. #include <objmgr/split/asn_sizer.hpp>
  76. #include <objmgr/split/chunk_info.hpp>
  77. BEGIN_NCBI_SCOPE
  78. BEGIN_SCOPE(objects)
  79. template<class C>
  80. inline
  81. C& NonConst(const C& c)
  82. {
  83.     return const_cast<C&>(c);
  84. }
  85. /////////////////////////////////////////////////////////////////////////////
  86. // CBlobSplitterImpl
  87. /////////////////////////////////////////////////////////////////////////////
  88. CBlobSplitterImpl::CBlobSplitterImpl(const SSplitterParams& params)
  89.     : m_Params(params)
  90. {
  91. }
  92. CBlobSplitterImpl::~CBlobSplitterImpl(void)
  93. {
  94. }
  95. void CBlobSplitterImpl::Reset(void)
  96. {
  97.     m_SplitBlob.Reset();
  98.     m_Skeleton.Reset(new CSeq_entry);
  99.     m_NextBioseq_set_Id = 1;
  100.     m_Bioseqs.clear();
  101.     m_Pieces.reset();
  102.     m_Chunks.clear();
  103. }
  104. void CBlobSplitterImpl::MakeID2SObjects(void)
  105. {
  106.     m_Split_Info.Reset(new CID2S_Split_Info);
  107.     ITERATE ( TChunks, it, m_Chunks ) {
  108.         if ( it->first == 0 ) {
  109.             AttachToSkeleton(it->second);
  110.         }
  111.         else {
  112.             MakeID2Chunk(it->first, it->second);
  113.         }
  114.     }
  115.     m_SplitBlob.Reset(*m_Skeleton, *m_Split_Info);
  116.     ITERATE ( TID2Chunks, it, m_ID2_Chunks ) {
  117.         m_SplitBlob.AddChunk(it->first, *it->second);
  118.     }
  119. }
  120. struct SOneSeqAnnots
  121. {
  122.     typedef set<SAnnotTypeSelector> TTypeSet;
  123.     typedef COneSeqRange TTotalLocation;
  124.     void Add(const SAnnotTypeSelector& type, const COneSeqRange& loc)
  125.         {
  126.             m_TotalType.insert(type);
  127.             m_TotalLocation.Add(loc);
  128.         }
  129.     TTypeSet m_TotalType;
  130.     TTotalLocation m_TotalLocation;
  131. };
  132. struct SSplitAnnotInfo
  133. {
  134.     typedef vector<SAnnotTypeSelector> TTypeSet;
  135.     typedef CSeqsRange TLocation;
  136.     TTypeSet m_TypeSet;
  137.     TLocation m_Location;
  138. };
  139. struct SAllAnnots
  140. {
  141.     typedef map<CSeq_id_Handle, SOneSeqAnnots> TAllAnnots;
  142.     typedef vector<SAnnotTypeSelector> TTypeSet;
  143.     typedef map<TTypeSet, CSeqsRange> TSplitAnnots;
  144.     void Add(const CSeq_annot& annot)
  145.         {
  146.             switch ( annot.GetData().Which() ) {
  147.             case CSeq_annot::C_Data::e_Ftable:
  148.                 Add(annot.GetData().GetFtable());
  149.                 break;
  150.             case CSeq_annot::C_Data::e_Align:
  151.                 Add(annot.GetData().GetAlign());
  152.                 break;
  153.             case CSeq_annot::C_Data::e_Graph:
  154.                 Add(annot.GetData().GetGraph());
  155.                 break;
  156.             }
  157.         }
  158.     void Add(const CSeq_annot::C_Data::TGraph& objs)
  159.         {
  160.             SAnnotTypeSelector type(CSeq_annot::C_Data::e_Graph);
  161.             ITERATE ( CSeq_annot::C_Data::TGraph, it, objs ) {
  162.                 CSeqsRange loc;
  163.                 loc.Add(**it);
  164.                 Add(type, loc);
  165.             }
  166.         }
  167.     void Add(const CSeq_annot::C_Data::TAlign& objs)
  168.         {
  169.             SAnnotTypeSelector type(CSeq_annot::C_Data::e_Align);
  170.             ITERATE ( CSeq_annot::C_Data::TAlign, it, objs ) {
  171.                 CSeqsRange loc;
  172.                 loc.Add(**it);
  173.                 Add(type, loc);
  174.             }
  175.         }
  176.     void Add(const CSeq_annot::C_Data::TFtable& objs)
  177.         {
  178.             ITERATE ( CSeq_annot::C_Data::TFtable, it, objs ) {
  179.                 SAnnotTypeSelector type((*it)->GetData().GetSubtype());
  180.                 CSeqsRange loc;
  181.                 loc.Add(**it);
  182.                 Add(type, loc);
  183.             }
  184.         }
  185.     void Add(const SAnnotTypeSelector& sel, const CSeqsRange& loc)
  186.         {
  187.             ITERATE ( CSeqsRange, it, loc ) {
  188.                 m_AllAnnots[it->first].Add(sel, it->second);
  189.             }
  190.         }
  191.     void SplitInfo(void)
  192.         {
  193.             ITERATE ( TAllAnnots, it, m_AllAnnots ) {
  194.                 TTypeSet type_set;
  195.                 ITERATE(SOneSeqAnnots::TTypeSet, tit, it->second.m_TotalType) {
  196.                     type_set.push_back(*tit);
  197.                 }
  198.                 m_SplitAnnots[type_set].Add(it->first,
  199.                                             it->second.m_TotalLocation);
  200.             }
  201.         }
  202.     TAllAnnots m_AllAnnots;
  203.     TSplitAnnots m_SplitAnnots;
  204. };
  205. typedef set<int> TWhole_set;
  206. TWhole_set seq_gis;
  207. typedef set<CSeqsRange::TRange> TGiInt_set;
  208. typedef map<int, TGiInt_set> TInt_set;
  209. TGiInt_set seq_ints;
  210. CRef<CID2_Seq_loc> MakeLoc(int gi, const TGiInt_set& int_set)
  211. {
  212.     CRef<CID2_Seq_loc> loc(new CID2_Seq_loc);
  213.     if ( int_set.size() == 1 ) {
  214.         CID2_Interval& interval = loc->SetInterval();
  215.         interval.SetGi(gi);
  216.         const CSeqsRange::TRange& range = *int_set.begin();
  217.         interval.SetStart(range.GetFrom());
  218.         interval.SetLength(range.GetLength());
  219.     }
  220.     else {
  221.         CID2_Packed_Seq_ints& seq_ints = loc->SetPacked_ints();
  222.         seq_ints.SetGi(gi);
  223.         ITERATE ( TGiInt_set, it, int_set ) {
  224.             CRef<CID2_Seq_range> add(new CID2_Seq_range);
  225.             const CSeqsRange::TRange& range = *it;
  226.             add->SetStart(range.GetFrom());
  227.             add->SetLength(range.GetLength());
  228.             seq_ints.SetIntervals().push_back(add);
  229.         }
  230.     }
  231.     return loc;
  232. }
  233. void AddLoc(CRef<CID2_Seq_loc>& loc, const CRef<CID2_Seq_loc>& add)
  234. {
  235.     if ( !loc ) {
  236.         loc = add;
  237.     }
  238.     else {
  239.         if ( !loc->IsLoc_set() ) {
  240.             CRef<CID2_Seq_loc> loc_set(new CID2_Seq_loc);
  241.             loc_set->SetLoc_set().push_back(loc);
  242.             loc = loc_set;
  243.         }
  244.         loc->SetLoc_set().push_back(add);
  245.     }
  246. }
  247. void AddLoc(CRef<CID2_Seq_loc>& loc, const TInt_set& int_set)
  248. {
  249.     ITERATE ( TInt_set, it, int_set ) {
  250.         AddLoc(loc, MakeLoc(it->first, it->second));
  251.     }
  252. }
  253. void AddLoc(CRef<CID2_Seq_loc>& loc, int gi_start, int gi_count)
  254. {
  255.     if ( gi_count < 4 ) {
  256.         for ( int i = 0; i < gi_count; ++i ) {
  257.             CRef<CID2_Seq_loc> add(new CID2_Seq_loc);
  258.             add->SetGi_whole(gi_start + i);
  259.             AddLoc(loc, add);
  260.         }
  261.     }
  262.     else {
  263.         CRef<CID2_Seq_loc> add(new CID2_Seq_loc);
  264.         add->SetGi_whole_range().SetStart(gi_start);
  265.         add->SetGi_whole_range().SetCount(gi_count);
  266.         AddLoc(loc, add);
  267.     }
  268. }
  269. void AddLoc(CRef<CID2_Seq_loc>& loc, const TWhole_set& whole_set)
  270. {
  271.     int gi_start = 0, gi_count = 0;
  272.     ITERATE ( TWhole_set, it, whole_set ) {
  273.         if ( gi_count == 0 || *it != gi_start + gi_count ) {
  274.             AddLoc(loc, gi_start, gi_count);
  275.             gi_start = *it;
  276.             gi_count = 0;
  277.         }
  278.         ++gi_count;
  279.     }
  280.     AddLoc(loc, gi_start, gi_count);
  281. }
  282. CRef<CID2_Seq_loc> MakeLoc(const CSeqsRange& range)
  283. {
  284.     TWhole_set whole_set;
  285.     TInt_set int_set;
  286.     ITERATE ( CSeqsRange, it, range ) {
  287.         int gi = it->first.GetGi();
  288.         CSeqsRange::TRange range = it->second.GetTotalRange();
  289.         if ( range == range.GetWhole() ) {
  290.             whole_set.insert(gi);
  291.             _ASSERT(int_set.count(gi) == 0);
  292.         }
  293.         else {
  294.             int_set[gi].insert(range);
  295.             _ASSERT(whole_set.count(gi) == 0);
  296.         }
  297.     }
  298.     CRef<CID2_Seq_loc> loc;
  299.     AddLoc(loc, int_set);
  300.     AddLoc(loc, whole_set);
  301.     _ASSERT(loc);
  302.     return loc;
  303. }
  304. void CBlobSplitterImpl::MakeID2Chunk(int id, const SChunkInfo& info)
  305. {
  306.     CRef<CID2S_Chunk> chunk(new CID2S_Chunk);
  307.     CRef<CID2S_Chunk_Info> chunk_info(new CID2S_Chunk_Info);
  308.     chunk_info->SetId(CID2S_Chunk_Id(id));
  309.     typedef map<CAnnotName, SAllAnnots> TAllAnnots;
  310.     TAllAnnots all_annots;
  311.     ITERATE ( SChunkInfo::TChunkAnnots, it, info.m_Annots ) {
  312.         CRef<CID2S_Chunk_Data> data(new CID2S_Chunk_Data);
  313.         chunk->SetData().push_back(data);
  314.         CID2S_Chunk_Data::TId& id = data->SetId();
  315.         if ( it->first > 0 ) {
  316.             id.SetGi(it->first);
  317.         }
  318.         else {
  319.             id.SetBioseq_set(-it->first);
  320.         }
  321.         ITERATE ( SChunkInfo::TIdAnnots, annot_it, it->second ) {
  322.             CRef<CSeq_annot> annot = MakeSeq_annot(*annot_it->first,
  323.                                                    annot_it->second);
  324.             data->SetAnnots().push_back(annot);
  325.             // collect locations
  326.             CAnnotName name = CSeq_annot_SplitInfo::GetName(*annot_it->first);
  327.             all_annots[name].Add(*annot);
  328.         }
  329.     }
  330.     NON_CONST_ITERATE ( TAllAnnots, nit, all_annots ) {
  331.         nit->second.SplitInfo();
  332.         const CAnnotName& annot_name = nit->first;
  333.         ITERATE ( SAllAnnots::TSplitAnnots, it, nit->second.m_SplitAnnots ) {
  334.             const SAllAnnots::TTypeSet& type_set = it->first;
  335.             const CSeqsRange& location = it->second;
  336.             CRef<CID2S_Chunk_Content> content(new CID2S_Chunk_Content);
  337.             CID2S_Seq_annot_Info& annot_info = content->SetSeq_annot();
  338.             if ( annot_name.IsNamed() ) {
  339.                 annot_info.SetName(annot_name.GetName());
  340.             }
  341.             typedef CSeqFeatData::ESubtype TSubtype;
  342.             typedef CSeqFeatData::E_Choice TFeatType;
  343.             typedef set<TSubtype> TSubtypes;
  344.             typedef map<TFeatType, TSubtypes> TFeatTypes;
  345.             TFeatTypes feat_types;
  346.             ITERATE ( SAllAnnots::TTypeSet, tit, type_set ) {
  347.                 const SAnnotTypeSelector& t = *tit;
  348.                 switch ( t.GetAnnotType() ) {
  349.                 case CSeq_annot::C_Data::e_Align:
  350.                     annot_info.SetAlign();
  351.                     break;
  352.                 case CSeq_annot::C_Data::e_Graph:
  353.                     annot_info.SetGraph();
  354.                     break;
  355.                 case CSeq_annot::C_Data::e_Ftable:
  356.                     feat_types[t.GetFeatType()].insert(t.GetFeatSubtype());
  357.                     break;
  358.                 }
  359.             }
  360.             ITERATE ( TFeatTypes, tit, feat_types ) {
  361.                 TFeatType t = tit->first;
  362.                 const TSubtypes& subtypes = tit->second;
  363.                 bool all_subtypes =
  364.                     subtypes.find(CSeqFeatData::eSubtype_any) !=
  365.                     subtypes.end();
  366.                 if ( !all_subtypes ) {
  367.                     all_subtypes = true;
  368.                     for ( TSubtype st = CSeqFeatData::eSubtype_bad;
  369.                           st <= CSeqFeatData::eSubtype_max;
  370.                           st = TSubtype(st+1) ) {
  371.                         if ( CSeqFeatData::GetTypeFromSubtype(st) == t &&
  372.                              subtypes.find(st) == subtypes.end() ) {
  373.                             all_subtypes = false;
  374.                             break;
  375.                         }
  376.                     }
  377.                 }
  378.                 CRef<CID2S_Feat_type_Info> type_info(new CID2S_Feat_type_Info);
  379.                 type_info->SetType(t);
  380.                 if ( !all_subtypes ) {
  381.                     ITERATE ( TSubtypes, stit, subtypes ) {
  382.                         type_info->SetSubtypes().push_back(*stit);
  383.                     }
  384.                 }
  385.                 annot_info.SetFeat().push_back(type_info);
  386.             }
  387.             annot_info.SetSeq_loc(*MakeLoc(location));
  388.             chunk_info->SetContent().push_back(content);
  389.         }
  390.     }
  391. #if 0
  392.     NcbiCout << "Objects: in SChunkInfo: " << info.CountAnnotObjects() <<
  393.         " in CID2S_Chunk: " << CountAnnotObjects(*chunk) << 'n';
  394. #endif
  395.     m_ID2_Chunks[CID2S_Chunk_Id(id)] = chunk;
  396.     m_Split_Info->SetChunks().push_back(chunk_info);
  397. }
  398. void CBlobSplitterImpl::AttachToSkeleton(const SChunkInfo& info)
  399. {
  400.     ITERATE ( SChunkInfo::TChunkAnnots, it, info.m_Annots ) {
  401.         TBioseqs::iterator seq_it = m_Bioseqs.find(it->first);
  402.         _ASSERT(seq_it != m_Bioseqs.end());
  403.         _ASSERT(bool(seq_it->second.m_Bioseq) || bool(seq_it->second.m_Bioseq_set));
  404.         ITERATE ( SChunkInfo::TIdAnnots, annot_it, it->second ) {
  405.             CRef<CSeq_annot> annot = MakeSeq_annot(*annot_it->first,
  406.                                                    annot_it->second);
  407.             if ( seq_it->second.m_Bioseq ) {
  408.                 seq_it->second.m_Bioseq->SetAnnot().push_back(annot);
  409.             }
  410.             else {
  411.                 seq_it->second.m_Bioseq_set->SetAnnot().push_back(annot);
  412.             }
  413.         }
  414.     }
  415. }
  416. CRef<CSeq_annot>
  417. CBlobSplitterImpl::MakeSeq_annot(const CSeq_annot& src,
  418.                                  const TAnnotObjects& objs)
  419. {
  420.     CRef<CSeq_annot> annot(new CSeq_annot);
  421.     if ( src.IsSetId() ) {
  422.         CSeq_annot::TId& id = annot->SetId();
  423.         ITERATE ( CSeq_annot::TId, it, src.GetId() ) {
  424.             id.push_back(Ref(&NonConst(**it)));
  425.         }
  426.     }
  427.     if ( src.IsSetDb() ) {
  428.         annot->SetDb(src.GetDb());
  429.     }
  430.     if ( src.IsSetName() ) {
  431.         annot->SetName(src.GetName());
  432.     }
  433.     if ( src.IsSetDesc() ) {
  434.         annot->SetDesc(NonConst(src.GetDesc()));
  435.     }
  436.     switch ( src.GetData().Which() ) {
  437.     case CSeq_annot::C_Data::e_Ftable:
  438.         ITERATE ( CLocObjects_SplitInfo, it, objs ) {
  439.             CObject& obj = NonConst(*it->m_Object);
  440.             annot->SetData().SetFtable()
  441.                 .push_back(Ref(&dynamic_cast<CSeq_feat&>(obj)));
  442.         }
  443.         break;
  444.     case CSeq_annot::C_Data::e_Align:
  445.         ITERATE ( CLocObjects_SplitInfo, it, objs ) {
  446.             CObject& obj = NonConst(*it->m_Object);
  447.             annot->SetData().SetAlign()
  448.                 .push_back(Ref(&dynamic_cast<CSeq_align&>(obj)));
  449.         }
  450.         break;
  451.     case CSeq_annot::C_Data::e_Graph:
  452.         ITERATE ( CLocObjects_SplitInfo, it, objs ) {
  453.             CObject& obj = NonConst(*it->m_Object);
  454.             annot->SetData().SetGraph()
  455.                 .push_back(Ref(&dynamic_cast<CSeq_graph&>(obj)));
  456.         }
  457.         break;
  458.     }
  459.     return annot;
  460. }
  461. size_t CBlobSplitterImpl::CountAnnotObjects(const TID2Chunks& chunks)
  462. {
  463.     size_t count = 0;
  464.     ITERATE ( TID2Chunks, it, chunks ) {
  465.         count += CountAnnotObjects(*it->second);
  466.     }
  467.     return count;
  468. }
  469. size_t CBlobSplitterImpl::CountAnnotObjects(const CID2S_Chunk& chunk)
  470. {
  471.     size_t count = 0;
  472.     for ( CTypeConstIterator<CSeq_annot> it(ConstBegin(chunk)); it; ++it ) {
  473.         count += CSeq_annot_SplitInfo::CountAnnotObjects(*it);
  474.     }
  475.     return count;
  476. }
  477. END_SCOPE(objects)
  478. END_NCBI_SCOPE
  479. /*
  480. * ---------------------------------------------------------------------------
  481. * $Log: blob_splitter_maker.cpp,v $
  482. * Revision 1000.2  2004/06/01 19:24:50  gouriano
  483. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.10
  484. *
  485. * Revision 1.10  2004/05/21 21:42:13  gorelenk
  486. * Added PCH ncbi_pch.hpp
  487. *
  488. * Revision 1.9  2004/02/04 18:05:40  grichenk
  489. * Added annotation filtering by set of types/subtypes.
  490. * Renamed *Choice to *Type in SAnnotSelector.
  491. *
  492. * Revision 1.8  2004/01/22 20:10:42  vasilche
  493. * 1. Splitted ID2 specs to two parts.
  494. * ID2 now specifies only protocol.
  495. * Specification of ID2 split data is moved to seqsplit ASN module.
  496. * For now they are still reside in one resulting library as before - libid2.
  497. * As the result split specific headers are now in objects/seqsplit.
  498. * 2. Moved ID2 and ID1 specific code out of object manager.
  499. * Protocol is processed by corresponding readers.
  500. * ID2 split parsing is processed by ncbi_xreader library - used by all readers.
  501. * 3. Updated OBJMGR_LIBS correspondingly.
  502. *
  503. * Revision 1.7  2004/01/07 17:36:24  vasilche
  504. * Moved id2_split headers to include/objmgr/split.
  505. * Fixed include path to genbank.
  506. *
  507. * Revision 1.6  2003/12/03 19:30:45  kuznets
  508. * Misprint fixed
  509. *
  510. * Revision 1.5  2003/12/02 19:12:24  vasilche
  511. * Fixed compilation on MSVC.
  512. *
  513. * Revision 1.4  2003/12/01 18:37:10  vasilche
  514. * Separate different annotation types in split info to reduce memory usage.
  515. *
  516. * Revision 1.3  2003/11/26 23:04:58  vasilche
  517. * Removed extra semicolons after BEGIN_SCOPE and END_SCOPE.
  518. *
  519. * Revision 1.2  2003/11/26 17:56:02  vasilche
  520. * Implemented ID2 split in ID1 cache.
  521. * Fixed loading of splitted annotations.
  522. *
  523. * Revision 1.1  2003/11/12 16:18:28  vasilche
  524. * First implementation of ID2 blob splitter withing cache.
  525. *
  526. * ===========================================================================
  527. */