1/*******************************************************************
2* duplicatefinderjob.cpp
3* Copyright 2011 Matthias Fuchs <mat69@gmx.net>
4*
5* This program is free software; you can redistribute it and/or
6* modify it under the terms of the GNU General Public License as
7* published by the Free Software Foundation; either version 2 of
8* the License, or (at your option) any later version.
9*
10* This program is distributed in the hope that it will be useful,
11* but WITHOUT ANY WARRANTY; without even the implied warranty of
12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13* GNU General Public License for more details.
14*
15* You should have received a copy of the GNU General Public License
16* along with this program. If not, see <http://www.gnu.org/licenses/>.
17*
18******************************************************************/
19
20#include "duplicatefinderjob.h"
21
22#include <KDebug>
23
24#include "backtracegenerator.h"
25#include "parser/backtraceparser.h"
26#include "debuggermanager.h"
27#include "drkonqi.h"
28#include "parsebugbacktraces.h"
29
30DuplicateFinderJob::DuplicateFinderJob(const QList<int> &bugIds, BugzillaManager *manager, QObject *parent)
31 : KJob(parent),
32 m_manager(manager),
33 m_bugIds(bugIds)
34{
35 kDebug() << "Possible duplicates:" << m_bugIds;
36 connect(m_manager, SIGNAL(bugReportFetched(BugReport,QObject*)), this, SLOT(slotBugReportFetched(BugReport,QObject*)));
37 connect(m_manager, SIGNAL(bugReportError(QString,QObject*)), this, SLOT(slotBugReportError(QString,QObject*)));
38}
39
40DuplicateFinderJob::~DuplicateFinderJob()
41{
42}
43
44void DuplicateFinderJob::start()
45{
46 analyzeNextBug();
47}
48
49DuplicateFinderJob::Result DuplicateFinderJob::result() const
50{
51 return m_result;
52}
53
54void DuplicateFinderJob::analyzeNextBug()
55{
56 if (m_bugIds.isEmpty()) {
57 emitResult();
58 return;
59 }
60
61 const int bugId = m_bugIds.takeFirst();
62 kDebug() << "Fetching:" << bugId;
63 m_manager->fetchBugReport(bugId, this);
64}
65
66void DuplicateFinderJob::fetchBug(const QString &bugId)
67{
68 bool ok;
69 const int num = bugId.toInt(&ok);
70 if (ok) {
71 kDebug() << "Fetching:" << bugId;
72 m_manager->fetchBugReport(num, this);
73 } else {
74 kDebug() << "Bug id not valid:" << bugId;
75 analyzeNextBug();
76 }
77}
78
79void DuplicateFinderJob::slotBugReportFetched(const BugReport &bug, QObject *owner)
80{
81 if (this != owner) {
82 return;
83 }
84
85 ParseBugBacktraces parse(bug, this);
86 parse.parse();
87
88 BacktraceGenerator *btGenerator = DrKonqi::debuggerManager()->backtraceGenerator();
89 const ParseBugBacktraces::DuplicateRating rating = parse.findDuplicate(btGenerator->parser()->parsedBacktraceLines());
90 kDebug() << "Duplicate rating:" << rating;
91
92 //TODO handle more cases here
93 if (rating != ParseBugBacktraces::PerfectDuplicate) {
94 kDebug() << "Bug" << bug.bugNumber() << "most likely not a duplicate:" << rating;
95 analyzeNextBug();
96 return;
97 }
98
99 //The Bug is a duplicate, now find out the status and resolution of the existing report
100 if (bug.resolutionValue() == BugReport::Duplicate) {
101 kDebug() << "Found duplicate is a duplicate itself.";
102 if (!m_result.duplicate) {
103 m_result.duplicate = bug.bugNumberAsInt();
104 }
105 fetchBug(bug.markedAsDuplicateOf());
106 } else if ((bug.statusValue() == BugReport::UnknownStatus) || (bug.resolutionValue() == BugReport::UnknownResolution)) {
107 kDebug() << "Either the status or the resolution is unknown.";
108 kDebug() << "Status \"" << bug.bugStatus() << "\" known:" << (bug.statusValue() != BugReport::UnknownStatus);
109 kDebug() << "Resolution \"" << bug.resolution() << "\" known:" << (bug.resolutionValue() != BugReport::UnknownResolution);
110 analyzeNextBug();
111 } else {
112 if (!m_result.duplicate) {
113 m_result.duplicate = bug.bugNumberAsInt();
114 }
115 m_result.parentDuplicate = bug.bugNumberAsInt();
116 m_result.status = bug.statusValue();
117 m_result.resolution = bug.resolutionValue();
118 kDebug() << "Found duplicate information (id/status/resolution):" << bug.bugNumber() << bug.bugStatus() << bug.resolution();
119 emitResult();
120 }
121}
122
123void DuplicateFinderJob::slotBugReportError(const QString &message, QObject *owner)
124{
125 if (this != owner) {
126 return;
127 }
128 kDebug() << "Error fetching bug:" << message;
129 analyzeNextBug();
130}
131