KItinerary

extractorvalidator.cpp
1/*
2 SPDX-FileCopyrightText: 2019 Volker Krause <vkrause@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "extractorvalidator.h"
8#include "validator-logging.h"
9
10#include <KItinerary/BoatTrip>
11#include <KItinerary/BusTrip>
12#include <KItinerary/Event>
13#include <KItinerary/Flight>
14#include <KItinerary/Place>
15#include <KItinerary/ProgramMembership>
16#include <KItinerary/RentalCar>
17#include <KItinerary/Reservation>
18#include <KItinerary/Taxi>
19#include <KItinerary/Ticket>
20#include <KItinerary/TrainTrip>
21#include <KItinerary/Visit>
22
23#include <QDateTime>
24
25using namespace KItinerary;
26
27namespace KItinerary {
28class ExtractorValidatorPrivate {
29public:
30 bool isSupportedTopLevelType(const QVariant &elem) const;
31 bool filterElement(const QVariant &elem) const;
32
33 bool filterLodgingReservation(const LodgingReservation &res) const;
34 bool filterAirport(const Airport &airport) const;
35 bool filterFlight(const Flight &flight) const;
36 bool filterTrainTrip(const TrainTrip &trip) const;
37 bool filterBusTrip(const BusTrip &trip) const;
38 bool filterBoatTrip(const BoatTrip &trip) const;
39 bool filterEvent(const Event &event) const;
40 bool filterFoodReservation(const FoodEstablishmentReservation &res) const;
41 bool filterLocalBusiness(const LocalBusiness &business) const;
42 bool filterReservation(const Reservation &res) const;
43 bool filterProgramMembership(const ProgramMembership &program) const;
44 bool filterTicket(const Ticket &ticket) const;
45
46 std::vector<const QMetaObject*> m_acceptedTypes;
47 bool m_onlyComplete = true;
48};
49}
50
51ExtractorValidator::ExtractorValidator() :
52 d(new ExtractorValidatorPrivate)
53{}
54
55ExtractorValidator::ExtractorValidator(ExtractorValidator&&) noexcept = default;
57ExtractorValidator& ExtractorValidator::operator=(ExtractorValidator&&) noexcept = default;
58
59void ExtractorValidator::setAcceptedTypes(std::vector<const QMetaObject*> &&accptedTypes)
60{
61 d->m_acceptedTypes = std::move(accptedTypes);
62}
63
65{
66 d->m_onlyComplete = completeOnly;
67}
68
69
70bool ExtractorValidatorPrivate::filterLodgingReservation(const LodgingReservation &res) const
71{
72 return res.checkinTime().isValid() && res.checkoutTime().isValid() && res.checkinTime() <= res.checkoutTime();
73}
74
75bool ExtractorValidatorPrivate::filterAirport(const Airport &airport) const
76{
77 return !airport.iataCode().isEmpty() || !airport.name().isEmpty();
78}
79
80bool ExtractorValidatorPrivate::filterFlight(const Flight &flight) const
81{
82 // this will be valid if either boarding time, departure time or departure day is set
83 const auto validDate = flight.departureDay().isValid();
84 return filterAirport(flight.departureAirport())
85 && filterAirport(flight.arrivalAirport())
86 && validDate;
87}
88
89template <typename T>
90static bool filterPlace(const T &place)
91{
92 return !place.name().isEmpty();
93}
94
95bool ExtractorValidatorPrivate::filterTrainTrip(const TrainTrip &trip) const
96{
97 return filterPlace(trip.departureStation())
98 && filterPlace(trip.arrivalStation())
99 && trip.departureDay().isValid();
100}
101
102bool ExtractorValidatorPrivate::filterBusTrip(const BusTrip &trip) const
103{
104 return filterPlace(trip.departureBusStop())
105 && filterPlace(trip.arrivalBusStop())
106 && trip.departureTime().isValid();
107}
108
109bool ExtractorValidatorPrivate::filterBoatTrip(const BoatTrip &trip) const
110{
111 return filterPlace(trip.departureBoatTerminal())
112 && filterPlace(trip.arrivalBoatTerminal())
113 && trip.departureTime().isValid()
114 && trip.arrivalTime().isValid();
115}
116
117bool ExtractorValidatorPrivate::filterEvent(const Event &event) const
118{
119 return !event.name().isEmpty() && event.startDate().isValid();
120}
121
122bool ExtractorValidatorPrivate::filterFoodReservation(const FoodEstablishmentReservation &res) const
123{
124 return res.startTime().isValid();
125}
126
127bool ExtractorValidatorPrivate::filterLocalBusiness(const LocalBusiness &business) const
128{
129 return !business.name().isEmpty();
130}
131
132bool ExtractorValidatorPrivate::filterReservation(const Reservation &res) const
133{
134 if (!m_onlyComplete) { // accept minimal cancellation elements
135 if (res.reservationFor().isNull()
136 && res.modifiedTime().isValid()
137 && !res.reservationNumber().isEmpty()
138 && res.reservationStatus() == Reservation::ReservationCancelled)
139 {
140 return true;
141 }
142 }
143
144 if (!filterElement(res.reservationFor())) {
145 qCDebug(ValidatorLog) << "Reservation element discarded due to rejected reservationFor property:" << res.reservationFor().typeName();
146 return false;
147 }
148 return true;
149}
150
151bool ExtractorValidatorPrivate::filterProgramMembership(const ProgramMembership &program) const
152{
153 return (!program.membershipNumber().isEmpty() || !program.token().isEmpty()) && !program.programName().isEmpty();
154}
155
156bool ExtractorValidatorPrivate::filterTicket(const Ticket &ticket) const
157{
158 return !ticket.ticketToken().isEmpty() && !ticket.name().isEmpty();
159}
160
161template <typename T, bool (ExtractorValidatorPrivate::*F)(const T&) const>
162static inline bool callFilterWithType(const ExtractorValidatorPrivate *d, const QVariant &v)
163{
164 // JsonLd::canConvert<T>(v) is guaranteed by walking up the meta object tree here
165 return (d->*F)(JsonLd::convert<T>(v));
166}
167
168#define FILTER(Type, Func) { &Type::staticMetaObject, callFilterWithType<Type, &ExtractorValidatorPrivate::Func> }
169struct {
170 const QMetaObject *metaObject;
171 bool (*filter)(const ExtractorValidatorPrivate *d, const QVariant &v);
172} static const filter_func_map[] {
173 FILTER(Flight, filterFlight),
174 FILTER(TrainTrip, filterTrainTrip),
175 FILTER(BusTrip, filterBusTrip),
176 FILTER(BoatTrip, filterBoatTrip),
177 FILTER(KItinerary::Event, filterEvent),
178 FILTER(LocalBusiness, filterLocalBusiness),
179 FILTER(FoodEstablishmentReservation, filterFoodReservation),
180 FILTER(LodgingReservation, filterLodgingReservation),
181 FILTER(Reservation, filterReservation),
182 FILTER(ProgramMembership, filterProgramMembership),
183 FILTER(Ticket, filterTicket),
184};
185#undef FILTER
186
187bool ExtractorValidatorPrivate::filterElement(const QVariant &elem) const
188{
189 auto mo = QMetaType(elem.userType()).metaObject();
190 if (!mo) {
191 qCDebug(ValidatorLog) << "Element discarded due to non-gadget type:" << elem.typeName();
192 return false;
193 }
194 while (mo) {
195 for (const auto &f : filter_func_map) {
196 if (f.metaObject != mo) {
197 continue;
198 }
199 if (!f.filter(this, elem)) {
200 return false;
201 }
202 break;
203 }
204 mo = mo->superClass();
205 }
206 return true;
207}
208
209bool ExtractorValidatorPrivate::isSupportedTopLevelType(const QVariant &elem) const
210{
211 if (m_acceptedTypes.empty()) { // nothing configured, we accept everything
212 return true;
213 }
214
215 auto mo = QMetaType(elem.userType()).metaObject();
216 if (!mo) {
217 qCDebug(ValidatorLog) << "Element discarded due to non-gadget top-level type:" << elem.typeName();
218 return false;
219 }
220 while (mo) {
221 const auto it = std::find(m_acceptedTypes.begin(), m_acceptedTypes.end(), mo);
222 if (it != m_acceptedTypes.end()) {
223 return true;
224 }
225 mo = mo->superClass();
226 }
227 return false;
228}
229
231{
232 // check this is an allowed top-level type
233 if (!d->isSupportedTopLevelType(elem)) {
234 qCDebug(ValidatorLog) << "Element discarded due to unsupported top-level type:" << elem.typeName();
235 return false;
236 }
237
238 // apply type-specific filter functions
239 return d->filterElement(elem);
240}
A boat or ferry trip.
Definition boattrip.h:23
A bus trip.
Definition bustrip.h:22
An event.
Definition event.h:21
Validates extractor results.
void setAcceptOnlyCompleteElements(bool completeOnly)
Configure whether or not to accept also incomplete elements.
bool isValidElement(const QVariant &elem) const
Checks if the given element is valid.
A flight.
Definition flight.h:25
QDate departureDay
The scheduled day of departure.
Definition flight.h:46
A hotel reservation.
Definition reservation.h:77
A frequent traveler, bonus points or discount scheme program membership.
QString token
KItinerary extension: barcode token for program membership cards having a barcode representation (e....
Abstract base class for reservations.
Definition reservation.h:25
A booked ticket.
Definition ticket.h:41
QString ticketToken
The raw ticket token string.
Definition ticket.h:50
A train trip.
Definition traintrip.h:24
QDate departureDay
The scheduled day of departure.
Definition traintrip.h:42
T convert(const QVariant &value)
Up-cast value to T.
Definition datatypes.h:47
Classes for reservation/travel data models, data extraction and data augmentation.
Definition berelement.h:17
bool isValid(int year, int month, int day)
bool isValid() const const
const QMetaObject * metaObject() const const
bool isEmpty() const const
bool isNull() const const
const char * typeName() const const
int userType() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 4 2024 16:28:48 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.