KItinerary

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

KDE's Doxygen guidelines are available online.