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() = default;
56
57void ExtractorValidator::setAcceptedTypes(std::vector<const QMetaObject*> &&accptedTypes)
58{
59 d->m_acceptedTypes = std::move(accptedTypes);
60}
61
63{
64 d->m_onlyComplete = completeOnly;
65}
66
67
68bool ExtractorValidatorPrivate::filterLodgingReservation(const LodgingReservation &res) const
69{
70 return res.checkinTime().isValid() && res.checkoutTime().isValid() && res.checkinTime() <= res.checkoutTime();
71}
72
73bool ExtractorValidatorPrivate::filterAirport(const Airport &airport) const
74{
75 return !airport.iataCode().isEmpty() || !airport.name().isEmpty();
76}
77
78bool ExtractorValidatorPrivate::filterFlight(const Flight &flight) const
79{
80 // this will be valid if either boarding time, departure time or departure day is set
81 const auto validDate = flight.departureDay().isValid();
82 return filterAirport(flight.departureAirport())
83 && filterAirport(flight.arrivalAirport())
84 && validDate;
85}
86
87template <typename T>
88static bool filterPlace(const T &place)
89{
90 return !place.name().isEmpty();
91}
92
93bool ExtractorValidatorPrivate::filterTrainTrip(const TrainTrip &trip) const
94{
95 return filterPlace(trip.departureStation())
96 && filterPlace(trip.arrivalStation())
97 && trip.departureDay().isValid();
98}
99
100bool ExtractorValidatorPrivate::filterBusTrip(const BusTrip &trip) const
101{
102 return filterPlace(trip.departureBusStop())
103 && filterPlace(trip.arrivalBusStop())
104 && trip.departureTime().isValid();
105}
106
107bool ExtractorValidatorPrivate::filterBoatTrip(const BoatTrip &trip) const
108{
109 return filterPlace(trip.departureBoatTerminal())
110 && filterPlace(trip.arrivalBoatTerminal())
111 && trip.departureTime().isValid()
112 && trip.arrivalTime().isValid();
113}
114
115bool ExtractorValidatorPrivate::filterEvent(const Event &event) const
116{
117 return !event.name().isEmpty() && event.startDate().isValid();
118}
119
120bool ExtractorValidatorPrivate::filterFoodReservation(const FoodEstablishmentReservation &res) const
121{
122 return res.startTime().isValid();
123}
124
125bool ExtractorValidatorPrivate::filterLocalBusiness(const LocalBusiness &business) const
126{
127 return !business.name().isEmpty();
128}
129
130bool ExtractorValidatorPrivate::filterReservation(const Reservation &res) const
131{
132 if (!m_onlyComplete) { // accept minimal cancellation elements
133 if (res.reservationFor().isNull()
134 && res.modifiedTime().isValid()
135 && !res.reservationNumber().isEmpty()
136 && res.reservationStatus() == Reservation::ReservationCancelled)
137 {
138 return true;
139 }
140 }
141
142 if (!filterElement(res.reservationFor())) {
143 qCDebug(ValidatorLog) << "Reservation element discarded due to rejected reservationFor property:" << res.reservationFor().typeName();
144 return false;
145 }
146 return true;
147}
148
149bool ExtractorValidatorPrivate::filterProgramMembership(const ProgramMembership &program) const
150{
151 return (!program.membershipNumber().isEmpty() || !program.token().isEmpty()) && !program.programName().isEmpty();
152}
153
154bool ExtractorValidatorPrivate::filterTicket(const Ticket &ticket) const
155{
156 return !ticket.ticketToken().isEmpty() && !ticket.name().isEmpty();
157}
158
159template <typename T, bool (ExtractorValidatorPrivate::*F)(const T&) const>
160static inline bool callFilterWithType(const ExtractorValidatorPrivate *d, const QVariant &v)
161{
162 // JsonLd::canConvert<T>(v) is guaranteed by walking up the meta object tree here
163 return (d->*F)(JsonLd::convert<T>(v));
164}
165
166#define FILTER(Type, Func) { &Type::staticMetaObject, callFilterWithType<Type, &ExtractorValidatorPrivate::Func> }
167struct {
168 const QMetaObject *metaObject;
169 bool (*filter)(const ExtractorValidatorPrivate *d, const QVariant &v);
170} static const filter_func_map[] {
171 FILTER(Flight, filterFlight),
172 FILTER(TrainTrip, filterTrainTrip),
173 FILTER(BusTrip, filterBusTrip),
174 FILTER(BoatTrip, filterBoatTrip),
175 FILTER(KItinerary::Event, filterEvent),
176 FILTER(LocalBusiness, filterLocalBusiness),
177 FILTER(FoodEstablishmentReservation, filterFoodReservation),
178 FILTER(LodgingReservation, filterLodgingReservation),
179 FILTER(Reservation, filterReservation),
180 FILTER(ProgramMembership, filterProgramMembership),
181 FILTER(Ticket, filterTicket),
182};
183#undef FILTER
184
185bool ExtractorValidatorPrivate::filterElement(const QVariant &elem) const
186{
187 auto mo = QMetaType(elem.userType()).metaObject();
188 if (!mo) {
189 qCDebug(ValidatorLog) << "Element discarded due to non-gadget type:" << elem.typeName();
190 return false;
191 }
192 while (mo) {
193 for (const auto &f : filter_func_map) {
194 if (f.metaObject != mo) {
195 continue;
196 }
197 if (!f.filter(this, elem)) {
198 return false;
199 }
200 break;
201 }
202 mo = mo->superClass();
203 }
204 return true;
205}
206
207bool ExtractorValidatorPrivate::isSupportedTopLevelType(const QVariant &elem) const
208{
209 if (m_acceptedTypes.empty()) { // nothing configured, we accept everything
210 return true;
211 }
212
213 auto mo = QMetaType(elem.userType()).metaObject();
214 if (!mo) {
215 qCDebug(ValidatorLog) << "Element discarded due to non-gadget top-level type:" << elem.typeName();
216 return false;
217 }
218 while (mo) {
219 const auto it = std::find(m_acceptedTypes.begin(), m_acceptedTypes.end(), mo);
220 if (it != m_acceptedTypes.end()) {
221 return true;
222 }
223 mo = mo->superClass();
224 }
225 return false;
226}
227
229{
230 // check this is an allowed top-level type
231 if (!d->isSupportedTopLevelType(elem)) {
232 qCDebug(ValidatorLog) << "Element discarded due to unsupported top-level type:" << elem.typeName();
233 return false;
234 }
235
236 // apply type-specific filter functions
237 return d->filterElement(elem);
238}
A boat or ferry trip.
Definition boattrip.h:23
A bus trip.
Definition bustrip.h:22
An event.
Definition event.h:21
void setAcceptedTypes()
Convenience overload of setAcceptedTypes().
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
bool canConvert(const QVariant &value)
Checks if the given value can be up-cast to T.
Definition datatypes.h:31
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 Tue Mar 26 2024 11:14:49 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.