source: tags/ms_r16q3/PROBE_DESIGN/probe_collection.cxx

Last change on this file was 14692, checked in by westram, 8 years ago
  • change datatype used in awar-access (double→float)
    • forward changes down into ArbProbeMatchWeighting
File size: 50.4 KB
Line 
1// ----------------------------------------------------------------------------
2// probe_collection.cxx
3// ----------------------------------------------------------------------------
4// Implementations of classes used to create and manage probe collections in Arb.
5// ----------------------------------------------------------------------------
6
7
8#include "probe_collection.hxx"
9#include <xercesc/dom/DOM.hpp>
10#include <xercesc/dom/DOMDocument.hpp>
11#include <xercesc/dom/DOMDocumentType.hpp>
12#include <xercesc/dom/DOMElement.hpp>
13#include <xercesc/dom/DOMImplementation.hpp>
14#include <xercesc/dom/DOMImplementationLS.hpp>
15#include <xercesc/dom/DOMNodeIterator.hpp>
16#include <xercesc/dom/DOMNodeList.hpp>
17#include <xercesc/dom/DOMText.hpp>
18#include <xercesc/parsers/XercesDOMParser.hpp>
19#include <xercesc/util/XMLUni.hpp>
20#include <math.h>
21#include <arbdbt.h>
22#include <algorithm>
23
24using namespace xercesc;
25
26const size_t ArbMIN_PROBE_LENGTH = 6;
27
28typedef std::pair<const std::string, ArbMatchResult*> ArbMatchResultPtrStringPair;
29typedef std::pair<const double,      ArbMatchResult*> ArbMatchResultPtrDoublePair;
30
31// ----------------------------------------------------------------------------
32// Provide access to global objects
33// ----------------------------------------------------------------------------
34
35ArbProbeCollection& get_probe_collection() {
36    static ArbProbeCollection g_probe_collection;
37    return g_probe_collection;
38}
39ArbMatchResultsManager& get_results_manager() {
40    static ArbMatchResultsManager g_results_manager;
41    return g_results_manager;
42}
43
44static ArbStringCache& get_string_cache() {
45    static ArbStringCache g_string_cache;
46    return g_string_cache;
47}
48
49// ----------------------------------------------------------------------------
50// ArbStringCache method implementations
51// ----------------------------------------------------------------------------
52void ArbStringCache::open() {
53    char *uniqueName   = GB_unique_filename("ArbString", "cache");
54    char *pTmpFileName = GB_create_tempfile(uniqueName);
55
56    if (pTmpFileName != 0) {
57        WriteCacheFile  = fopen(pTmpFileName, "wb");
58        ReadCacheFile   = fopen(pTmpFileName, "rb");
59        IsOpen          = ((WriteCacheFile != 0) && (ReadCacheFile != 0));
60        FileName        = pTmpFileName;
61    }
62
63    free(pTmpFileName);
64    free(uniqueName);
65}
66
67// ----------------------------------------------------------------------------
68
69void ArbStringCache::close() {
70    if (ReadCacheFile != 0) {
71        fclose(ReadCacheFile);
72
73        ReadCacheFile = 0;
74    }
75
76    if (WriteCacheFile != 0) {
77        fclose(WriteCacheFile);
78        unlink(FileName.c_str());
79
80        WriteCacheFile = 0;
81    }
82
83    if (ReadBuffer != 0) {
84        delete [] ReadBuffer;
85        ReadBuffer = 0;
86    }
87
88    ReadBufferLength  = 0;
89    IsOpen            = false;
90}
91
92// ----------------------------------------------------------------------------
93
94bool ArbStringCache::allocReadBuffer(int nLength) const {
95    if (nLength + 1 > ReadBufferLength) {
96        if (ReadBuffer != 0) {
97            delete [] ReadBuffer;
98        }
99
100        ReadBufferLength  = nLength + 1;
101        ReadBuffer        = new char[ReadBufferLength];
102    }
103
104    return (ReadBuffer != 0);
105}
106
107// ----------------------------------------------------------------------------
108
109ArbStringCache::ArbStringCache() {
110    IsOpen            = false;
111    WriteCacheFile    = 0;
112    ReadCacheFile     = 0;
113    ReadBuffer        = 0;
114    ReadBufferLength  = 0;
115
116    open();
117}
118
119// ----------------------------------------------------------------------------
120
121ArbStringCache::~ArbStringCache() {
122    close();
123}
124
125// ----------------------------------------------------------------------------
126
127bool ArbStringCache::saveString(const char *pString, ArbCachedString& rCachedString) {
128    bool bSaved = saveString(pString, strlen(pString), rCachedString);
129
130    return (bSaved);
131}
132
133// ----------------------------------------------------------------------------
134
135bool ArbStringCache::saveString(const char *pString, int nLength, ArbCachedString& rCachedString) {
136    bool bSaved = false;
137
138    if (IsOpen && (pString != 0)) {
139        rCachedString.Len = nLength;
140
141        fgetpos(WriteCacheFile, &rCachedString.Pos);
142        fwrite(pString, nLength * sizeof(char), 1, WriteCacheFile);
143
144        bSaved = true;
145    }
146
147    return (bSaved);
148}
149
150// ----------------------------------------------------------------------------
151
152bool ArbStringCache::loadString(std::string& rString, const ArbCachedString& rCachedString) const {
153    bool bLoaded = false;
154
155    if (IsOpen                  &&
156        (rCachedString.Len > 0) &&
157        allocReadBuffer(rCachedString.Len))
158    {
159        fpos_t nPos = rCachedString.Pos;
160        fsetpos(ReadCacheFile, &nPos);
161
162        size_t read = fread(ReadBuffer, sizeof(char), rCachedString.Len, ReadCacheFile);
163        if (read == size_t(rCachedString.Len)) {
164            ReadBuffer[rCachedString.Len] = '\0';
165
166            rString = ReadBuffer;
167            bLoaded = true;
168        }
169    }
170
171    return (bLoaded);
172}
173
174// ----------------------------------------------------------------------------
175
176void ArbStringCache::flush() {
177    if (IsOpen) {
178        // Close and re-open to delete old cache file and create a new one
179        close();
180        open();
181    }
182}
183
184
185// ----------------------------------------------------------------------------
186// ArbProbeMatchWeighting method implementations
187// ----------------------------------------------------------------------------
188int ArbProbeMatchWeighting::toIndex(char nC) const {
189    int nIndex = 0;
190
191    switch (nC) {
192        case 'A':
193        case 'a': {
194            nIndex = 0;
195            break;
196        }
197
198        case 'C':
199        case 'c': {
200            nIndex = 1;
201            break;
202        }
203
204        case 'G':
205        case 'g': {
206            nIndex = 2;
207            break;
208        }
209
210        case 'U':
211        case 'u':
212        case 'T':
213        case 't': {
214            nIndex = 3;
215            break;
216        }
217
218        default: {
219            arb_assert(0);
220            break;
221        }
222    }
223
224    return (nIndex);
225}
226
227// ----------------------------------------------------------------------------
228
229double ArbProbeMatchWeighting::positionalWeight(int nPos, int nLength) const {
230    double dS       = -(::log(10) / Width);
231    double dP       = ((2.0 * nPos - nLength) / nLength) - Bias;
232    double dWeight  = ::exp(dS * dP * dP);
233
234    return (dWeight);
235}
236
237// ----------------------------------------------------------------------------
238
239void ArbProbeMatchWeighting::copy(const ArbProbeMatchWeighting& rCopy) {
240    Width = rCopy.Width;
241    Bias  = rCopy.Bias;
242
243    for (int cx = 0 ; cx < 4 ; cx++) {
244        for (int cy = 0 ; cy < 4 ; cy++) {
245            PenaltyMatrix[cy][cx] = rCopy.PenaltyMatrix[cy][cx];
246        }
247    }
248}
249
250// ----------------------------------------------------------------------------
251
252ArbProbeMatchWeighting::ArbProbeMatchWeighting()
253    : ArbRefCount(),
254      PenaltyMatrix()
255{
256    float aDefaultValues[16] = {
257        0.0, 1.0, 1.0, 1.0,
258        1.0, 0.0, 1.0, 1.0,
259        1.0, 1.0, 0.0, 1.0,
260        1.0, 1.0, 1.0, 0.0
261    };
262
263    float dWidth = 1.0;
264    float dBias  = 0.0;
265
266    initialise(aDefaultValues, dWidth, dBias);
267}
268
269// ----------------------------------------------------------------------------
270
271ArbProbeMatchWeighting::ArbProbeMatchWeighting(const float aValues[16], float dWidth, float dBias)
272    : ArbRefCount(),
273      PenaltyMatrix()
274{
275    Width = 1.0;
276    Bias  = 0.0;
277
278    initialise(aValues, dWidth, dBias);
279}
280
281// ----------------------------------------------------------------------------
282
283ArbProbeMatchWeighting::ArbProbeMatchWeighting(const ArbProbeMatchWeighting& rCopy)
284    : ArbRefCount(),
285      PenaltyMatrix()
286{
287    copy(rCopy);
288}
289
290// ----------------------------------------------------------------------------
291
292ArbProbeMatchWeighting::~ArbProbeMatchWeighting() {
293    // Do Nothing
294}
295
296// ----------------------------------------------------------------------------
297
298ArbProbeMatchWeighting& ArbProbeMatchWeighting::operator = (const ArbProbeMatchWeighting& rCopy) {
299    copy(rCopy);
300    return *this;
301}
302
303// ----------------------------------------------------------------------------
304
305void ArbProbeMatchWeighting::initialise(const float aValues[16], float dWidth, float dBias) {
306    Width = dWidth;
307    Bias  = dBias;
308
309    int cz = 0;
310
311    for (int cx = 0 ; cx < 4 ; cx++) {
312        for (int cy = 0 ; cy < 4 ; cy++) {
313            PenaltyMatrix[cy][cx] = aValues[cz];
314
315            cz++;
316        }
317    }
318}
319
320// ----------------------------------------------------------------------------
321
322bool ArbProbeMatchWeighting::initialise(const char *pCSValues, const char *pCSWidth, const char *pCSBias) {
323    bool bInitialised = false;
324
325    if ((pCSValues != 0) &&
326        (pCSWidth  != 0) &&
327        (pCSBias   != 0))
328    {
329        float dWidth = 0;
330        float dBias  = 0;
331        float aValues[16] = {
332            0.0, 1.0, 1.0, 1.0,
333            1.0, 0.0, 1.0, 1.0,
334            1.0, 1.0, 0.0, 1.0,
335            1.0, 1.0, 1.0, 0.0
336        };
337
338        int nItems = ::sscanf(pCSValues,
339                              "%f%f%f%f"
340                              "%f%f%f%f"
341                              "%f%f%f%f"
342                              "%f%f%f%f",
343                              aValues,      aValues + 1,  aValues + 2,  aValues + 3,
344                              aValues + 4,  aValues + 5,  aValues + 6,  aValues + 7,
345                              aValues + 8,  aValues + 9,  aValues + 10, aValues + 11,
346                              aValues + 12, aValues + 13, aValues + 14, aValues + 15);
347
348        nItems += ::sscanf(pCSWidth, "%f", &dWidth);
349        nItems += ::sscanf(pCSBias, "%f", &dBias);
350
351        if (nItems == (16 + 2)) {
352            initialise(aValues, dWidth, dBias);
353
354            bInitialised = true;
355        }
356    }
357
358    return (bInitialised);
359}
360
361// ----------------------------------------------------------------------------
362
363void ArbProbeMatchWeighting::getParameters(float aValues[16], float& dWidth, float& dBias) const {
364    int cz = 0;
365
366    for (int cx = 0 ; cx < 4 ; cx++) {
367        for (int cy = 0 ; cy < 4 ; cy++) {
368            aValues[cz] = PenaltyMatrix[cy][cx];
369
370            cz++;
371        }
372    }
373
374    dWidth  = Width;
375    dBias   = Bias;
376}
377
378// ----------------------------------------------------------------------------
379
380void ArbProbeMatchWeighting::writeXML(FILE *hFile, const char *pPrefix) const {
381    bool bFirst = true;
382
383    ::fprintf(hFile, "%s<match_weighting width=\"%g\" bias=\"%g\">\n", pPrefix, Width, Bias);
384    ::fprintf(hFile, "%s  <penalty_matrix values=\"", pPrefix);
385
386    for (int cx = 0 ; cx < 4 ; cx++) {
387        for (int cy = 0 ; cy < 4 ; cy++) {
388            if (bFirst) {
389                ::fprintf(hFile, "%g", PenaltyMatrix[cy][cx]);
390
391                bFirst = false;
392            }
393            else {
394                ::fprintf(hFile, " %g", PenaltyMatrix[cy][cx]);
395            }
396        }
397    }
398
399    ::fprintf(hFile, "\"/>\n");
400    ::fprintf(hFile, "%s</match_weighting>\n", pPrefix);
401}
402
403// ----------------------------------------------------------------------------
404
405double ArbProbeMatchWeighting::matchWeight(const char *pSequenceA, const char *pSequenceB) const {
406    double dWeight = -1.0;
407
408    if ((pSequenceA != 0) && (pSequenceB != 0)) {
409        int nLengthA = strlen(pSequenceA);
410        int nLengthB = strlen(pSequenceB);
411        int nLength  = (nLengthA < nLengthB) ? nLengthA : nLengthB;
412
413        const char *pA = pSequenceA;
414        const char *pB = pSequenceB;
415
416        dWeight = 0.0;
417
418        for (int cn = 0 ; cn < nLength ; cn++) {
419            switch (*pA) {
420                case 'N':
421                case 'n': {
422                    // Wildcard match so don't penalise it
423                    break;
424                }
425
426                default: {
427                    switch (*pB) {
428                        case 'N':
429                        case 'n': {
430                            // Wildcard match so don't penalise it
431                            break;
432                        }
433
434                        default: {
435                            dWeight += PenaltyMatrix[toIndex(*pA)][toIndex(*pB)] * positionalWeight(cn, nLength);
436                            break;
437                        }
438                    }
439                    break;
440                }
441            }
442
443            pA++;
444            pB++;
445        }
446    }
447    else {
448        arb_assert(0);
449    }
450
451    return (dWeight);
452}
453
454// ----------------------------------------------------------------------------
455
456double ArbProbeMatchWeighting::matchWeightResult(const char *pProbeSequence, const char *pMatchResult) const {
457    double dWeight = -1.0;
458
459    if ((pProbeSequence != 0) && (pMatchResult != 0)) {
460        int nMatchLength;
461        int nLengthResult = strlen(pMatchResult);
462        int nLength       = strlen(pProbeSequence);
463
464        const char *pS = pProbeSequence;
465        const char *pR = pMatchResult;
466        int         cn;
467
468        if (nLength <= nLengthResult) {
469            nMatchLength = nLength;
470        }
471        else {
472            nMatchLength = nLengthResult;
473        }
474
475        dWeight = 0.0;
476
477        for (cn = 0 ; cn < nMatchLength ; cn++) {
478            char cB;
479
480            switch (*pR) {
481                case '-':
482                case '=': {
483                    cB = *pS;
484                    break;
485                }
486
487                // I have no idea about this one. There is no mention in Arb about what
488                // .... means in terms of match results so I'll just assume it to be the
489                // same as U
490                case '.': {
491                    cB = 'U';
492                    break;
493                }
494
495                default: {
496                    cB = *pR;
497                    break;
498                }
499            }
500
501            switch (*pS) {
502                case 'N':
503                case 'n': {
504                    // Wildcard match so don't penalise it
505                    break;
506                }
507
508                default: {
509                    switch (cB) {
510                        case 'N':
511                        case 'n': {
512                            // Wildcard match so don't penalise it
513                            break;
514                        }
515
516                        default: {
517                            dWeight += PenaltyMatrix[toIndex(*pS)][toIndex(cB)] * positionalWeight(cn, nLength);
518                            break;
519                        }
520                    }
521                    break;
522                }
523            }
524
525            pS++;
526            pR++;
527        }
528
529        int nNoMatch = toIndex('U');
530
531        for (; cn < nLength ; cn++) {
532            dWeight += PenaltyMatrix[toIndex(*pS)][nNoMatch] * positionalWeight(cn, nLength);
533
534            pS++;
535        }
536    }
537    else {
538        arb_assert(0);
539    }
540
541    return (dWeight);
542}
543
544
545// ----------------------------------------------------------------------------
546// ArbProbe method implementations
547// ----------------------------------------------------------------------------
548ArbProbe::ArbProbe()
549    : ArbRefCount(),
550      Name(),
551      Sequence(),
552      DisplayName()
553{
554    // Do nothing
555}
556
557// ----------------------------------------------------------------------------
558
559ArbProbe::ArbProbe(const char *pName, const char *pSequence)
560    : ArbRefCount(),
561      Name(),
562      Sequence(),
563      DisplayName()
564{
565    nameAndSequence(pName, pSequence);
566}
567
568// ----------------------------------------------------------------------------
569
570ArbProbe::ArbProbe(const ArbProbe& rCopy)
571    : ArbRefCount(),
572      Name(),
573      Sequence(),
574      DisplayName()
575{
576    // Note that we do a copy of Name and Sequence via c_str() because std:string
577    // shares internal buffers between strings if using a copy constructor and
578    // this can potentially result in memory corrupting if the owner string is deleted
579    // (REFCOUNT_HACK)
580    nameAndSequence(rCopy.Name.c_str(), rCopy.Sequence.c_str());
581}
582
583// ----------------------------------------------------------------------------
584
585ArbProbe::~ArbProbe() {
586    // Do nothing
587}
588
589// ----------------------------------------------------------------------------
590
591void ArbProbe::writeXML(FILE *hFile, const char *pPrefix) const {
592    ::fprintf(hFile, "%s<probe seq=\"%s\" name=\"%s\"/>\n", pPrefix, Sequence.c_str(), Name.c_str());
593}
594
595// ----------------------------------------------------------------------------
596
597void ArbProbe::nameAndSequence(const char *pName, const char *pSequence) { // REFCOUNT_HACK
598    if (pName != 0) {
599        Name = pName;
600    }
601    else {
602        Name = "";
603    }
604
605    if (pSequence != 0) {
606        Sequence = pSequence;
607    }
608    else {
609        Sequence = "";
610
611        arb_assert(0);
612    }
613
614    DisplayName = Name + ":" + Sequence;
615}
616
617// ----------------------------------------------------------------------------
618
619int ArbProbe::allowedMismatches() const {
620    size_t nProbe_Length     = Sequence.length();
621    size_t nAllowedMistaches = (nProbe_Length - ArbMIN_PROBE_LENGTH) / 2;
622
623    // Arb probe server doesn't seem to like having more that 20 mis-matches.
624    if (nAllowedMistaches > 20) {
625        nAllowedMistaches = 20;
626    }
627
628    return (nAllowedMistaches);
629}
630
631
632// ----------------------------------------------------------------------------
633// ArbProbeCollection method implementations
634// ----------------------------------------------------------------------------
635void ArbProbeCollection::flush() {
636    ArbProbePtrListIter Iter;
637
638    for (Iter = ProbeList.begin() ; Iter != ProbeList.end() ; ++Iter) {
639        ArbProbe *pProbe = *Iter;
640
641        if (pProbe != 0) {
642            pProbe->free();
643        }
644    }
645
646    ProbeList.clear();
647}
648
649// ----------------------------------------------------------------------------
650
651void ArbProbeCollection::copy(const ArbProbePtrList& rList) {
652    ArbProbePtrListConstIter  Iter;
653
654    for (Iter = rList.begin() ; Iter != rList.end() ; ++Iter) {
655        ArbProbe *pProbe = *Iter;
656
657        if (pProbe != 0) {
658            ProbeList.push_back(pProbe);
659            pProbe->lock();
660        }
661    }
662}
663
664// ----------------------------------------------------------------------------
665
666ArbProbeCollection::ArbProbeCollection()
667    : ArbRefCount(),
668      Name(),
669      ProbeList(),
670      MatchWeighting()
671{
672    HasChanged = false;
673}
674
675// ----------------------------------------------------------------------------
676
677ArbProbeCollection::ArbProbeCollection(const char *pName)
678    : ArbRefCount(),
679      Name(),
680      ProbeList(),
681      MatchWeighting()
682{
683    // Note that we do a copy of Name via c_str() because std:string shares
684    // internal buffers between strings if using a copy constructor and this can
685    // potentially result in memory corrupting if the owner string is deleted
686    // (REFCOUNT_HACK)
687    name(pName);
688
689    HasChanged = false;
690}
691
692// ----------------------------------------------------------------------------
693
694ArbProbeCollection::ArbProbeCollection(const ArbProbeCollection& rCopy)
695    : ArbRefCount(),
696      Name(),
697      ProbeList(),
698      MatchWeighting(rCopy.MatchWeighting)
699{
700    name(rCopy.name().c_str());
701    copy(rCopy.ProbeList);
702
703    HasChanged = false;
704}
705
706// ----------------------------------------------------------------------------
707
708ArbProbeCollection::~ArbProbeCollection() {
709    flush();
710}
711
712// ----------------------------------------------------------------------------
713
714ArbProbeCollection& ArbProbeCollection::operator = (const ArbProbeCollection& rCopy) {
715    flush();
716    name(rCopy.name().c_str());
717    copy(rCopy.ProbeList);
718
719    MatchWeighting  = rCopy.MatchWeighting;
720    HasChanged      = false;
721
722    return (*this);
723}
724
725// ----------------------------------------------------------------------------
726
727static bool elementHasName(DOMElement *pElement, const char *pName) {
728    bool bHasName = false;
729
730    if (pName != 0) {
731        XMLCh *pNameStr;
732
733        pNameStr  = XMLString::transcode(pName);
734        bHasName  = XMLString::equals(pElement->getTagName(), pNameStr);
735        XMLString::release(&pNameStr);
736    }
737
738    return (bHasName);
739}
740
741// ----------------------------------------------------------------------------
742
743static bool isElement(DOMNode *pNode, DOMElement*& pElement, const char *pName) {
744    bool  bIsElement = false;
745
746    if (pNode != 0) {
747        short nNodeType = pNode->getNodeType();
748
749        if (nNodeType == DOMNode::ELEMENT_NODE) {
750            pElement = dynamic_cast<xercesc::DOMElement*>(pNode);
751
752            if (pName != 0) {
753                bIsElement = elementHasName(pElement, pName);
754            }
755            else {
756                bIsElement = true;
757            }
758        }
759    }
760
761    return (bIsElement);
762}
763
764// ----------------------------------------------------------------------------
765
766bool ArbProbeCollection::openXML(const char *pFileAndPath, std::string& rErrorMessage) {
767    bool bOpened = false;
768
769    rErrorMessage = "";
770
771    if (pFileAndPath != 0 && pFileAndPath[0]) {
772        struct stat   FileStatus;
773        int           nResult = ::stat(pFileAndPath, &FileStatus);
774
775        if ((nResult == 0) && !S_ISDIR(FileStatus.st_mode)) {
776            flush();
777
778            XMLPlatformUtils::Initialize();
779
780            // We need braces to ensure Parser goes out of scope be Terminate() is called
781            {
782                XercesDOMParser Parser;
783
784                Parser.setValidationScheme(XercesDOMParser::Val_Never);
785                Parser.setDoNamespaces(false);
786                Parser.setDoSchema(false);
787                Parser.setLoadExternalDTD(false);
788
789                try {
790                    Parser.parse(pFileAndPath);
791
792                    DOMDocument *pDoc  = Parser.getDocument();
793                    DOMElement  *pRoot = pDoc->getDocumentElement();
794
795                    if ((pRoot != 0) && elementHasName(pRoot, "probe_collection")) {
796                        char        *pNameAttr          = 0;
797                        XMLCh       *pNameAttrStr       = XMLString::transcode("name");
798                        DOMNodeList *pPC_Children;
799                        XMLSize_t    nPC_Count;
800                        bool         bHasProbeList      = false;
801                        bool         bHasMatchWeighting = false;
802
803                        pNameAttr = XMLString::transcode(pRoot->getAttribute(pNameAttrStr));
804                        name(pNameAttr);
805                        XMLString::release(&pNameAttr);
806
807                        pPC_Children  = pRoot->getChildNodes();
808                        nPC_Count     = pPC_Children->getLength();
809
810                        for (XMLSize_t cx = 0 ; cx < nPC_Count ; ++cx) {
811                            DOMNode    *pPC_Node    = pPC_Children->item(cx);
812                            DOMElement *pPC_Element = 0;
813
814                            if (isElement(pPC_Node, pPC_Element, "probe_list")) {
815                                DOMNodeList *pPL_Children;
816                                XMLSize_t    nPL_Count;
817                                XMLCh       *pSeqAttrStr;
818
819                                pSeqAttrStr   = XMLString::transcode("seq");
820                                pPL_Children  = pPC_Element->getChildNodes();
821                                nPL_Count     = pPL_Children->getLength();
822
823                                for (XMLSize_t cy = 0 ; cy < nPL_Count ; ++cy) {
824                                    DOMNode    *pPL_Node    = pPL_Children->item(cy);
825                                    DOMElement *pPL_Element = 0;
826                                    char       *pSeqAttr    = 0;
827
828                                    if (isElement(pPL_Node, pPL_Element, "probe")) {
829                                        pNameAttr = XMLString::transcode(pPL_Element->getAttribute(pNameAttrStr));
830                                        pSeqAttr  = XMLString::transcode(pPL_Element->getAttribute(pSeqAttrStr));
831
832                                        add(pNameAttr, pSeqAttr);
833
834                                        XMLString::release(&pNameAttr);
835                                        XMLString::release(&pSeqAttr);
836
837                                        bHasProbeList = true;
838                                    }
839                                }
840                            }
841                            else if (isElement(pPC_Node, pPC_Element, "match_weighting")) {
842                                DOMNodeList *pMW_Children;
843                                XMLSize_t    nMW_Count;
844                                XMLCh       *pWidthAttrStr = XMLString::transcode("width");
845                                XMLCh       *pBiasAttrStr  = XMLString::transcode("bias");
846                                char        *pWidthStr     = XMLString::transcode(pPC_Element->getAttribute(pWidthAttrStr));
847                                char        *pBiasStr      = XMLString::transcode(pPC_Element->getAttribute(pBiasAttrStr));
848
849                                pMW_Children    = pPC_Element->getChildNodes();
850                                nMW_Count       = pMW_Children->getLength();
851
852                                for (XMLSize_t cy = 0 ; cy < nMW_Count ; ++cy) {
853                                    DOMNode    *pPM_Node    = pMW_Children->item(cy);
854                                    DOMElement *pPM_Element = 0;
855
856                                    if (isElement(pPM_Node, pPM_Element, "penalty_matrix")) {
857                                        XMLCh *pValuesAttrStr = XMLString::transcode("values");
858                                        char  *pValuesAttr    = XMLString::transcode(pPM_Element->getAttribute(pValuesAttrStr));
859
860                                        if (MatchWeighting.initialise(pValuesAttr, pWidthStr, pBiasStr)) {
861                                            bHasMatchWeighting = true;
862                                        }
863                                        else {
864                                            rErrorMessage = "Too few penalty_matrix values";
865                                        }
866
867                                        XMLString::release(&pValuesAttrStr);
868                                        XMLString::release(&pValuesAttr);
869                                    }
870                                }
871
872                                XMLString::release(&pWidthAttrStr);
873                                XMLString::release(&pBiasAttrStr);
874                                XMLString::release(&pWidthStr);
875                                XMLString::release(&pBiasStr);
876                            }
877                        }
878
879                        XMLString::release(&pNameAttrStr);
880
881                        bOpened = bHasProbeList && bHasMatchWeighting;
882
883                        if (!bHasProbeList) {
884                            rErrorMessage += "\nprobe_list missing or empty";
885                        }
886
887                        if (!bHasMatchWeighting) {
888                            rErrorMessage += "\nmatch_weighting missing or empty";
889                        }
890                    }
891
892                    if (bOpened) {
893                        HasChanged  = false;
894                    }
895                }
896                catch (xercesc::DOMException& e1) {
897                    char *message = xercesc::XMLString::transcode(e1.getMessage());
898
899                    rErrorMessage  = "Error parsing file: ";
900                    rErrorMessage += message;
901
902                    XMLString::release(&message);
903                }
904                catch (xercesc::XMLException& e2) {
905                    char *message = xercesc::XMLString::transcode(e2.getMessage());
906
907                    rErrorMessage  = "Error parsing file: ";
908                    rErrorMessage += message;
909
910                    XMLString::release(&message);
911                }
912            }
913
914            XMLPlatformUtils::Terminate();
915        }
916        else if (nResult == EACCES) {
917            rErrorMessage = "Search permission is denied";
918        }
919        else if (nResult == EIO) {
920            rErrorMessage = "Error reading from the file system";
921        }
922        else if (nResult == ELOOP) {
923            rErrorMessage = "Loop exists in symbolic links";
924        }
925        else if (nResult == ENAMETOOLONG) {
926            rErrorMessage = "Path name too long";
927        }
928        else if (nResult == ENOENT) {
929            rErrorMessage = "Component of path existing file or missing";
930        }
931        else if (nResult == ENOTDIR) {
932            rErrorMessage = "Component of path not a directory";
933        }
934        else if (nResult == EOVERFLOW) {
935            rErrorMessage = "";
936        }
937    }
938    else {
939        rErrorMessage = "Please select a file to load";
940    }
941
942    return (bOpened);
943}
944
945// ----------------------------------------------------------------------------
946
947bool ArbProbeCollection::saveXML(const char *pFileAndPath) const {
948    bool bSaved = false;
949
950    if (pFileAndPath != 0) {
951        FILE *hFile = ::fopen(pFileAndPath, "wt");
952
953        if (hFile != 0) {
954            ArbProbePtrListConstIter  Iter;
955
956            ::fprintf(hFile, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
957            ::fprintf(hFile, "<!DOCTYPE probe_collection>\n");
958            ::fprintf(hFile, "<probe_collection name=\"%s\">\n", Name.c_str());
959            ::fprintf(hFile, "  <probe_list>\n");
960
961            for (Iter = ProbeList.begin() ; Iter != ProbeList.end() ; ++Iter) {
962                const ArbProbe *pProbe = *Iter;
963
964                if (pProbe != 0) {
965                    pProbe->writeXML(hFile, "    ");
966                }
967            }
968
969            ::fprintf(hFile, "  </probe_list>\n");
970
971            MatchWeighting.writeXML(hFile, "  ");
972
973            ::fprintf(hFile, "</probe_collection>\n");
974
975            ::fclose(hFile);
976
977            HasChanged = false;
978        }
979    }
980
981    return (bSaved);
982}
983
984// ----------------------------------------------------------------------------
985
986void ArbProbeCollection::setParameters(const float aValues[16], float dWidth, float dBias) {
987    MatchWeighting.setParameters(aValues, dWidth, dBias);
988
989    HasChanged = true;
990}
991
992// ----------------------------------------------------------------------------
993
994void ArbProbeCollection::getParameters(float aValues[16], float& dWidth, float& dBias) const {
995    MatchWeighting.getParameters(aValues, dWidth, dBias);
996}
997
998// ----------------------------------------------------------------------------
999
1000struct hasSequence {
1001    std::string seq;
1002    hasSequence(std::string seq_) : seq(seq_) {}
1003    bool operator()(const ArbProbe *probe) {
1004        return probe && probe->sequence() == seq;
1005    }
1006};
1007
1008const ArbProbe *ArbProbeCollection::find(const char *pSequence) const {
1009    if (pSequence) {
1010        ArbProbePtrListConstIter found = find_if(ProbeList.begin(), ProbeList.end(), hasSequence(pSequence));
1011        if (found != ProbeList.end()) {
1012            return *found;
1013        }
1014    }
1015    return NULL;
1016}
1017
1018// ----------------------------------------------------------------------------
1019
1020bool ArbProbeCollection::add(const char *pName, const char *pSequence, const ArbProbe **ppProbe) {
1021    bool bAdded = false;
1022
1023    if (pSequence && (strlen(pSequence) >= ArbMIN_PROBE_LENGTH)) {
1024        ArbProbe *pNewProbe = new ArbProbe(pName, pSequence);
1025
1026        if (pNewProbe != 0) {
1027            ProbeList.push_back(pNewProbe);
1028
1029            if (ppProbe != 0) *ppProbe = pNewProbe;
1030
1031            HasChanged  = true;
1032            bAdded      = true;
1033        }
1034    }
1035
1036    return (bAdded);
1037}
1038
1039bool ArbProbeCollection::replace(const char *oldSequence, const char *pName, const char *pSequence, const ArbProbe **ppProbe) {
1040    bool bReplaced = false;
1041
1042    if (oldSequence && pSequence && (strlen(pSequence) >= ArbMIN_PROBE_LENGTH)) {
1043        ArbProbePtrListIter found = find_if(ProbeList.begin(), ProbeList.end(), hasSequence(oldSequence));
1044        if (found != ProbeList.end()) {
1045            (*found)->free();
1046            *found = new ArbProbe(pName, pSequence);
1047
1048            if (ppProbe != 0) *ppProbe = *found;
1049
1050            HasChanged = true;
1051            bReplaced  = true;
1052        }
1053    }
1054
1055    return (bReplaced);
1056}
1057
1058
1059// ----------------------------------------------------------------------------
1060
1061bool ArbProbeCollection::remove(const char *pSequence) {
1062    bool bRemoved  = false;
1063
1064    if (pSequence != 0) {
1065        ArbProbePtrListIter Iter;
1066        std::string         rSequence(pSequence);
1067
1068        for (Iter = ProbeList.begin() ; Iter != ProbeList.end() ; ++Iter) {
1069            ArbProbe *pTestProbe = *Iter;
1070
1071            if ((pTestProbe != 0) && (pTestProbe->sequence() == rSequence)) {
1072                ProbeList.erase(Iter);
1073
1074                pTestProbe->free();
1075
1076                HasChanged  = true;
1077                bRemoved    = true;
1078                break;
1079            }
1080        }
1081    }
1082
1083    return (bRemoved);
1084}
1085
1086// ----------------------------------------------------------------------------
1087
1088bool ArbProbeCollection::clear() {
1089    bool bClear = false;
1090
1091    if (ProbeList.size() > 0) {
1092        flush();
1093
1094        HasChanged  = true;
1095        bClear      = true;
1096    }
1097
1098    return (bClear);
1099}
1100
1101// ----------------------------------------------------------------------------
1102
1103void ArbProbeCollection::name(const char *pName) { // REFCOUNT_HACK
1104    if (pName != 0) {
1105        Name = pName;
1106    }
1107    else {
1108        Name = "";
1109    }
1110
1111    HasChanged = true;
1112}
1113
1114
1115// ----------------------------------------------------------------------------
1116// ArbMatchResult method implementations
1117// ----------------------------------------------------------------------------
1118ArbMatchResult::ArbMatchResult()
1119    : ArbRefCount(),
1120      CachedResultA(),
1121      CachedResultB()
1122{
1123    Probe   = 0;
1124    Weight  = 0.0;
1125    Padding = 0;
1126    Index   = 0;
1127}
1128
1129// ----------------------------------------------------------------------------
1130
1131ArbMatchResult::ArbMatchResult(const ArbProbe *pProbe, const char *pResult, int nSplitPoint, double dWeight)
1132    : ArbRefCount(),
1133      CachedResultA(),
1134      CachedResultB()
1135{
1136    ArbStringCache& g_string_cache = get_string_cache();
1137    g_string_cache.saveString(pResult, nSplitPoint, CachedResultA);
1138    g_string_cache.saveString(pResult + nSplitPoint, CachedResultB);
1139
1140    Probe   = pProbe;
1141    Weight  = dWeight;
1142    Padding = 0;
1143    Index   = 0;
1144
1145    if (Probe != 0) {
1146        Probe->lock();
1147    }
1148}
1149
1150// ----------------------------------------------------------------------------
1151
1152ArbMatchResult::ArbMatchResult(const ArbMatchResult& rCopy)
1153    : ArbRefCount(),
1154      CachedResultA(rCopy.CachedResultA),
1155      CachedResultB(rCopy.CachedResultB)
1156{
1157    Probe   = rCopy.Probe;
1158    Weight  = rCopy.Weight;
1159    Padding = rCopy.Padding;
1160    Index   = rCopy.Index;
1161
1162    if (Probe != 0) {
1163        Probe->lock();
1164    }
1165}
1166
1167// ----------------------------------------------------------------------------
1168
1169ArbMatchResult::~ArbMatchResult() {
1170    if (Probe != 0) {
1171        Probe->free();
1172    }
1173}
1174
1175// ----------------------------------------------------------------------------
1176
1177ArbMatchResult& ArbMatchResult::operator = (const ArbMatchResult& rCopy) {
1178    Probe         = rCopy.Probe;
1179    CachedResultA = rCopy.CachedResultA;
1180    CachedResultB = rCopy.CachedResultB;
1181    Padding       = rCopy.Padding;
1182    Weight        = rCopy.Weight;
1183
1184    if (Probe != 0) {
1185        Probe->lock();
1186    }
1187
1188    return (*this);
1189}
1190
1191// ----------------------------------------------------------------------------
1192
1193void ArbMatchResult::addedHeadline(std::string& rHeadline) {
1194    rHeadline = "---error--probe-----------------";
1195}
1196
1197// ----------------------------------------------------------------------------
1198
1199void ArbMatchResult::weightAndResult(std::string& rDest) const {
1200    char        sBuffer[64] = {0};
1201    std::string sResult;
1202
1203    result(sResult);
1204    sprintf(sBuffer, "%8g %22.22s   ", Weight, Probe != 0 ? Probe->name().c_str() : "");
1205
1206    rDest  = sBuffer;
1207    rDest += sResult;
1208}
1209
1210// ----------------------------------------------------------------------------
1211
1212void ArbMatchResult::result(std::string& sResult) const {
1213    std::string sResultA;
1214    std::string sResultB;
1215
1216    ArbStringCache& g_string_cache = get_string_cache();
1217    g_string_cache.loadString(sResultA, CachedResultA);
1218    g_string_cache.loadString(sResultB, CachedResultB);
1219
1220    sResult.append(sResultA);
1221
1222    if (Padding > 0) {
1223        sResult.append(Padding, ' ');
1224    }
1225
1226    sResult.append(sResultB);
1227}
1228
1229
1230// ----------------------------------------------------------------------------
1231// ArbMatchResultSet method implementations
1232// ----------------------------------------------------------------------------
1233void ArbMatchResultSet::flush() {
1234    ArbMatchResultPtrByStringMultiMapIter Iter;
1235
1236    for (Iter = ResultMap.begin() ; Iter != ResultMap.end() ; ++Iter) {
1237        ArbMatchResult *pResult = (*Iter).second;
1238
1239        if (pResult != 0) {
1240            pResult->free();
1241        }
1242    }
1243
1244    ResultMap.clear();
1245    CommentList.clear();
1246
1247    Headline    = "";
1248    EndFullName = 0;
1249}
1250
1251// ----------------------------------------------------------------------------
1252
1253void ArbMatchResultSet::copy(const ArbMatchResultPtrByStringMultiMap& rMap) {
1254    ArbMatchResultPtrByStringMultiMapConstIter Iter;
1255
1256    for (Iter = rMap.begin() ; Iter != rMap.end() ; ++Iter) {
1257        const std::string&    sKey    = (*Iter).first;
1258        const ArbMatchResult *pResult = (*Iter).second;
1259
1260        if (pResult != 0) {
1261            ArbMatchResult *pCopy = new ArbMatchResult(*pResult);
1262
1263            if (pCopy != 0) {
1264                ResultMap.insert(ArbMatchResultPtrStringPair(sKey, pCopy));
1265            }
1266        }
1267    }
1268
1269    ResultMap.clear();
1270    CommentList.clear();
1271}
1272
1273// ----------------------------------------------------------------------------
1274
1275ArbMatchResultSet::ArbMatchResultSet()
1276    : ArbRefCount(),
1277      Headline(),
1278      ResultMap(),
1279      CommentList()
1280{
1281    Probe       = 0;
1282    Index       = 0;
1283    EndFullName = 0;
1284}
1285
1286// ----------------------------------------------------------------------------
1287
1288ArbMatchResultSet::ArbMatchResultSet(const ArbProbe *pProbe)
1289    : ArbRefCount(),
1290      Headline(),
1291      ResultMap(),
1292      CommentList()
1293{
1294    Probe       = 0;
1295    Index       = 0;
1296    EndFullName = 0;
1297
1298    initialise(pProbe, 0);
1299}
1300
1301// ----------------------------------------------------------------------------
1302
1303ArbMatchResultSet::ArbMatchResultSet(const ArbMatchResultSet& rCopy)
1304    : ArbRefCount(),
1305      Headline(rCopy.Headline.c_str()),
1306      ResultMap(),
1307      CommentList(rCopy.CommentList)
1308{
1309    Probe       = 0;
1310    Index       = 0;
1311    EndFullName = 0;
1312
1313    initialise(rCopy.Probe, rCopy.Index);
1314    copy(rCopy.ResultMap);
1315
1316    EndFullName = rCopy.EndFullName;
1317}
1318
1319// ----------------------------------------------------------------------------
1320
1321ArbMatchResultSet::~ArbMatchResultSet() {
1322    flush();
1323
1324    if (Probe != 0) {
1325        Probe->free();
1326    }
1327}
1328
1329// ----------------------------------------------------------------------------
1330
1331void ArbMatchResultSet::initialise(const ArbProbe *pProbe, int nIndex) {
1332    Probe = pProbe;
1333    Index = nIndex;
1334
1335    if (Probe != 0) {
1336        Probe->lock();
1337    }
1338
1339    flush();
1340}
1341
1342// ----------------------------------------------------------------------------
1343
1344bool ArbMatchResultSet::add(const char *pName,
1345                            const char *pFullName,
1346                            const char *pMatchPart,
1347                            const char *pResult,
1348                            const ArbProbeMatchWeighting& rMatchWeighting)
1349{
1350    bool bAdded = false;
1351
1352    if ((pResult    != 0) &&
1353        (pName      != 0) &&
1354        (pFullName  != 0) &&
1355        (pMatchPart != 0) &&
1356        (Probe      != 0) &&
1357        (Probe->sequence().length() > 0))
1358    {
1359        double          dWeight;
1360        const char     *pMatchStart = pMatchPart;
1361        bool            bContinue   = true;
1362        std::string     sKey(pName);
1363        ArbMatchResult *pMatchResult;
1364
1365        while (bContinue) {
1366            switch (*pMatchStart) {
1367                case '-': {
1368                    pMatchStart++;
1369
1370                    bContinue = false;
1371                    break;
1372                }
1373
1374                case '\0':
1375                case '=': {
1376                    bContinue = false;
1377                    break;
1378                }
1379
1380                default: {
1381                    pMatchStart++;
1382
1383                    bContinue = true;
1384                }
1385            }
1386        }
1387
1388        dWeight       = rMatchWeighting.matchWeightResult(Probe->sequence().c_str(), pMatchStart);
1389        pMatchResult  = new ArbMatchResult(Probe, pResult, EndFullName, dWeight);
1390
1391        if (pMatchResult != 0) {
1392            pMatchResult->index(Index);
1393            ResultMap.insert(ArbMatchResultPtrStringPair(sKey, pMatchResult));
1394
1395            bAdded = true;
1396        }
1397    }
1398
1399    return (bAdded);
1400}
1401
1402// ----------------------------------------------------------------------------
1403
1404bool ArbMatchResultSet::isMatched(const ArbStringList& rCladeList,
1405                                  bool& bPartialMatch,
1406                                  double dThreshold,
1407                                  double dCladeMarkedThreshold,
1408                                  double dCladePartiallyMarkedThreshold) const
1409{
1410    bool  bMatched    = false;
1411    int   nCladeSize  = rCladeList.size();
1412
1413    if (nCladeSize > 0) {
1414        int nMatchedSize          = (int)(nCladeSize * dCladeMarkedThreshold + 0.5);
1415        int nPartiallyMatchedSize = (int)(nCladeSize * dCladePartiallyMarkedThreshold + 0.5);
1416        int nMatchedCount         = 0;
1417
1418        for (ArbStringListConstIter Iter = rCladeList.begin() ; Iter != rCladeList.end() ; ++Iter) {
1419            const std::string&  rName = *Iter;
1420
1421            if (isMatched(rName, dThreshold)) {
1422                nMatchedCount++;
1423            }
1424        }
1425
1426        bMatched      = (nMatchedCount >= nMatchedSize);
1427        bPartialMatch = false;
1428
1429        // Only check for partial match if we don't have a match. If a partial
1430        // match is found then isMatched() should return true.
1431        if (!bMatched) {
1432            bPartialMatch = (nMatchedCount >= nPartiallyMatchedSize);
1433            bMatched      = bPartialMatch;
1434        }
1435    }
1436
1437    return (bMatched);
1438}
1439
1440// ----------------------------------------------------------------------------
1441
1442bool ArbMatchResultSet::isMatched(const std::string& rName, double dThreshold) const {
1443    bool bMatched = false;
1444
1445    ArbMatchResultPtrByStringMultiMapConstIter Iter = ResultMap.find(rName);
1446
1447    if (Iter != ResultMap.end()) {
1448        const ArbMatchResult *pResult = (*Iter).second;
1449
1450        bMatched = pResult->weight() <= dThreshold;
1451    }
1452
1453    return (bMatched);
1454}
1455
1456// ----------------------------------------------------------------------------
1457
1458bool ArbMatchResultSet::addComment(const char *pComment) {
1459    bool bAdded = false;
1460
1461    if ((pComment != 0) &&
1462        (Probe    != 0) &&
1463        (Probe->sequence().length() > 0))
1464    {
1465        CommentList.push_back(std::string(pComment));
1466
1467        bAdded = true;
1468    }
1469
1470    return (bAdded);
1471}
1472
1473// ----------------------------------------------------------------------------
1474
1475void ArbMatchResultSet::findMaximumWeight(double& dMaximumWeight) const {
1476    ArbMatchResultPtrByStringMultiMapConstIter Iter;
1477
1478    for (Iter = ResultMap.begin() ; Iter != ResultMap.end() ; ++Iter) {
1479        const ArbMatchResult *pResult = (*Iter).second;
1480
1481        if ((pResult != 0) && (dMaximumWeight < pResult->weight())) {
1482            dMaximumWeight = pResult->weight();
1483        }
1484    }
1485}
1486
1487// ----------------------------------------------------------------------------
1488
1489void ArbMatchResultSet::enumerateResults(ArbMatchResultPtrByDoubleMultiMap& rMap, int nMaxFullName) {
1490    ArbMatchResultPtrByStringMultiMapIter Iter;
1491
1492    for (Iter = ResultMap.begin() ; Iter != ResultMap.end() ; ++Iter) {
1493        ArbMatchResult *pResult = (*Iter).second;
1494
1495        if (pResult != 0) {
1496            pResult->padding(nMaxFullName - EndFullName);
1497            rMap.insert(ArbMatchResultPtrDoublePair(pResult->weight(), pResult));
1498        }
1499    }
1500}
1501
1502
1503// ----------------------------------------------------------------------------
1504// ArbMatchResultsManager method implementations
1505// ----------------------------------------------------------------------------
1506void ArbMatchResultsManager::flush() {
1507    ArbMatchResultPtrByStringMultiMapIter Iter;
1508
1509    for (Iter = ResultsMap.begin() ; Iter != ResultsMap.end() ; ++Iter) {
1510        ArbMatchResult *pMatchResult = (*Iter).second;
1511
1512        if (pMatchResult != 0) {
1513            pMatchResult->free();
1514        }
1515    }
1516
1517    ResultsMap.clear();
1518}
1519
1520// ----------------------------------------------------------------------------
1521
1522void ArbMatchResultsManager::initFileName() {
1523    char *uniqueName   = GB_unique_filename("ArbMatchResults", "txt");
1524    char *pTmpFileName = GB_create_tempfile(uniqueName);
1525
1526    if (pTmpFileName != 0) {
1527        ResultsFileName = pTmpFileName;
1528    }
1529
1530    free(pTmpFileName);
1531    free(uniqueName);
1532}
1533
1534// ----------------------------------------------------------------------------
1535
1536ArbMatchResultsManager::ArbMatchResultsManager()
1537    : ResultsMap(),
1538      ResultSetMap(),
1539      ResultsFileName()
1540{
1541    MaximumWeight = 0.0;
1542    initFileName();
1543}
1544
1545// ----------------------------------------------------------------------------
1546
1547ArbMatchResultsManager::ArbMatchResultsManager(const ArbMatchResultsManager& rCopy)
1548    : ResultsMap(),
1549      ResultSetMap(rCopy.ResultSetMap),
1550      ResultsFileName()
1551{
1552    MaximumWeight = rCopy.MaximumWeight;
1553    updateResults();
1554    initFileName();
1555}
1556
1557// ----------------------------------------------------------------------------
1558
1559ArbMatchResultsManager::~ArbMatchResultsManager() {
1560    ResultSetMap.clear();
1561    flush();
1562
1563    if (ResultsFileName.length() > 0) {
1564        unlink(ResultsFileName.c_str());
1565    }
1566
1567    // This assumes that there is only ever on instance of ArbMatchResultsManager
1568    // which is true at the moment. Slightly dodgey but it will stop the cache
1569    // file from ballooning out too much.
1570    get_string_cache().flush();
1571}
1572
1573// ----------------------------------------------------------------------------
1574
1575void ArbMatchResultsManager::reset() {
1576    ResultSetMap.clear();
1577    flush();
1578
1579    if (ResultsFileName.length() > 0) {
1580        unlink(ResultsFileName.c_str());
1581    }
1582
1583    // This assumes that there is only ever on instance of ArbMatchResultsManager
1584    // which is true at the moment. Slightly dodgey but it will stop the cache
1585    // file from ballooning out too much.
1586    get_string_cache().flush();
1587}
1588
1589// ----------------------------------------------------------------------------
1590
1591ArbMatchResultSet *ArbMatchResultsManager::addResultSet(const ArbProbe *pProbe) {
1592    ArbMatchResultSet *pResultSet = 0;
1593
1594    if (pProbe != 0) {
1595        pResultSet = (ArbMatchResultSet*)findResultSet(pProbe->sequence().c_str());
1596
1597        if (pResultSet == 0) {
1598            ResultSetMap[pProbe->sequence()] = ArbMatchResultSet();
1599
1600            pResultSet = (ArbMatchResultSet*)findResultSet(pProbe->sequence().c_str());
1601        }
1602    }
1603
1604    return (pResultSet);
1605}
1606
1607// ----------------------------------------------------------------------------
1608
1609const ArbMatchResultSet *ArbMatchResultsManager::findResultSet(const char *pProbeSequence) const {
1610    const ArbMatchResultSet *pResultSet = 0;
1611
1612    if (pProbeSequence != 0) {
1613        ArbMatchResultSetByStringMapConstIter Iter = ResultSetMap.find(std::string(pProbeSequence));
1614
1615        if (Iter != ResultSetMap.end()) {
1616            pResultSet = &((*Iter).second);
1617        }
1618    }
1619
1620    return (pResultSet);
1621}
1622
1623// ----------------------------------------------------------------------------
1624
1625void ArbMatchResultsManager::updateResults() {
1626    ArbMatchResultSetByStringMapIter            Iter;
1627    ArbMatchResultPtrByStringMultiMapConstIter  IterR;
1628
1629    flush();
1630
1631    MaximumWeight = 0.0;
1632
1633    for (Iter = ResultSetMap.begin() ; Iter != ResultSetMap.end() ; ++Iter) {
1634        ArbMatchResultSet&  rMatchResultSet = (*Iter).second;
1635
1636        rMatchResultSet.findMaximumWeight(MaximumWeight);
1637
1638        for (IterR = rMatchResultSet.resultMap().begin() ; IterR != rMatchResultSet.resultMap().end() ; ++IterR) {
1639            const std::string&    rKey         = (*IterR).first;
1640            const ArbMatchResult *pMatchResult = (*IterR).second;
1641
1642            pMatchResult->lock();
1643            ResultsMap.insert(ArbMatchResultPtrStringPair(rKey, (ArbMatchResult*)pMatchResult));
1644        }
1645    }
1646}
1647
1648// ----------------------------------------------------------------------------
1649
1650int ArbMatchResultsManager::enumerate_results(ArbMatchResultsEnumCallback pCallback, void *pContext) {
1651    int nResults = 0;
1652
1653    bool bAborted = false;
1654
1655    if (pCallback != 0) {
1656        ArbMatchResultPtrByDoubleMultiMap rResultsMap;
1657
1658        // Need to compile the results sorted in ascending match weight.
1659        ArbMatchResultSetByStringMapIter  Iter;
1660        int                               nItem         = 0;
1661        int                               nItems        = 1;
1662        int                               nMaxFullName  = 0;
1663        std::string                       sHeadline;
1664
1665        for (Iter = ResultSetMap.begin() ; (Iter != ResultSetMap.end()) && !bAborted ; ++Iter) {
1666            ArbMatchResultSet&  rMatchResultSet = (*Iter).second;
1667
1668            if (rMatchResultSet.endFullName() > nMaxFullName) {
1669                ArbMatchResult::addedHeadline(sHeadline);
1670
1671                sHeadline   += rMatchResultSet.headline();
1672                nMaxFullName = rMatchResultSet.endFullName();
1673            }
1674        }
1675
1676        if (pCallback(pContext, sHeadline.c_str(), true, nItem, nItems)) {
1677            bAborted = true;
1678        }
1679
1680        for (Iter = ResultSetMap.begin() ; (Iter != ResultSetMap.end()) && !bAborted ; ++Iter) {
1681            ArbMatchResultSet&  rMatchResultSet = (*Iter).second;
1682
1683            rMatchResultSet.enumerateResults(rResultsMap, nMaxFullName);
1684
1685            ArbStringListConstIter CommentIter;
1686
1687            for (CommentIter = rMatchResultSet.commentList().begin() ;
1688                 CommentIter != rMatchResultSet.commentList().begin() ;
1689                 ++CommentIter)
1690            {
1691                const std::string& rComment = *CommentIter;
1692
1693                if (pCallback(pContext, rComment.c_str(), true, nItem, nItems)) {
1694                    bAborted = true;
1695                    break;
1696                }
1697            }
1698        }
1699
1700        ArbMatchResultPtrByDoubleMultiMapIter ResIter;
1701
1702        nItems = rResultsMap.size();
1703
1704        for (ResIter = rResultsMap.begin() ; (ResIter != rResultsMap.end()) && !bAborted ; ++ResIter) {
1705            const ArbMatchResult *pResult = (*ResIter).second;
1706
1707            if (pResult != 0) {
1708                std::string sResult;
1709
1710                pResult->weightAndResult(sResult);
1711
1712                if (pCallback(pContext, sResult.c_str(), false, nItem, nItems)) {
1713                    bAborted = true;
1714                    break;
1715                }
1716
1717                nResults++;
1718                nItem++;
1719            }
1720        }
1721    }
1722
1723    return (nResults);
1724}
1725
1726// ----------------------------------------------------------------------------
1727
1728const char *ArbMatchResultsManager::resultsFileName() const {
1729    return (ResultsFileName.c_str());
1730}
1731
1732// ----------------------------------------------------------------------------
1733
1734void ArbMatchResultsManager::openResultsFile() const {
1735    pid_t pid = fork();
1736
1737    if (pid == 0) {
1738        // We are the child process. Execute system command to open the file.
1739        std::string sCommand("\"xdg-open ");
1740
1741        sCommand += ResultsFileName;
1742        sCommand += "\"";
1743
1744        execl("/bin/sh", sCommand.c_str(), (char *)0);
1745        exit(0);
1746    }
1747}
Note: See TracBrowser for help on using the repository browser.