KItinerary

iatabcbpparser.cpp
1/*
2 SPDX-FileCopyrightText: 2018 Volker Krause <vkrause@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "iatabcbpparser.h"
8#include "logging.h"
9#include "reservationconverter.h"
10
11#include "iata/iatabcbp.h"
12
13#include "knowledgedb/airportdb.h"
14#include "knowledgedb/trainstationdb.h"
15
16#include <KItinerary/Flight>
17#include <KItinerary/JsonLdDocument>
18#include <KItinerary/Organization>
19#include <KItinerary/Person>
20#include <KItinerary/Place>
21#include <KItinerary/Reservation>
22#include <KItinerary/Ticket>
23#include <KItinerary/TrainTrip>
24
25#include <QJsonObject>
26#include <QVariant>
27
28using namespace Qt::Literals::StringLiterals;
29using namespace KItinerary;
30
31[[nodiscard]] static QString stripLeadingZeros(const QString &s)
32{
33 const auto it = std::find_if(s.begin(), s.end(), [](const QChar &c) { return c != '0'_L1; });
34 const auto d = std::distance(s.begin(), it);
35 return s.mid(d);
36}
37
38QList<QVariant> IataBcbpParser::parse(const QString &message, const QDateTime &externalIssueDate) {
39 IataBcbp bcbp(message);
40 if (!bcbp.isValid()) {
41 return {};
42 }
43 return parse(bcbp, externalIssueDate.isValid() ? externalIssueDate : QDateTime({1970, 1, 1}, {}));
44}
45
46[[nodiscard]] static QString ticketNumber(QStringView airlineNumericCode, QStringView documentNumber)
47{
48 if (airlineNumericCode.size() != 3 || documentNumber.size() != 10) {
49 return {};
50 }
51
52 if (std::any_of(airlineNumericCode.begin(), airlineNumericCode.end(), [](QChar c) { return !c.isDigit(); })
53 || std::any_of(documentNumber.begin(), documentNumber.end(), [](QChar c) { return !c.isDigit(); })) {
54 return {};
55 }
56
57 if (std::all_of(documentNumber.begin(), documentNumber.end(), [](QChar c) { return c == '0'_L1; })) {
58 return {};
59 }
60
61 return airlineNumericCode + ' '_L1 + documentNumber;
62}
63
64// check if one of the airports is actually a train station, and convert the reservation accordingly
65[[nodiscard]] QVariant checkModeOfTransport(FlightReservation &&res)
66{
67 const auto flight = res.reservationFor().value<Flight>();
68 const auto from = KnowledgeDb::IataCode(flight.departureAirport().iataCode());
69 const auto to = KnowledgeDb::IataCode(flight.arrivalAirport().iataCode());
70
72 return res;
73 }
74 if (KnowledgeDb::stationForIataCode(from).coordinate.isValid() || KnowledgeDb::stationForIataCode(to).coordinate.isValid()) {
76 auto trip = trainRes.reservationFor().value<TrainTrip>();
77 {
78 auto station = trip.departureStation();
79 station.setName(from.toString());
80 trip.setDepartureStation(station);
81 }
82 {
83 auto station = trip.arrivalStation();
84 station.setName(to.toString());
85 trip.setArrivalStation(station);
86 }
87 trainRes.setReservationFor(std::move(trip));
88 return trainRes;
89 }
90 return res;
91}
92
93QList<QVariant> IataBcbpParser::parse(const IataBcbp &bcbp, const QDateTime &contextDate) {
94 const auto count = bcbp.uniqueMandatorySection().numberOfLegs();
95 const auto issueDate = bcbp.uniqueConditionalSection().dateOfIssue(contextDate);
96
97 QList<QVariant> result;
98 result.reserve(count);
99
100 Person person;
101 {
102 const auto fullName = bcbp.uniqueMandatorySection().passengerName();
103 const auto idx = fullName.indexOf('/'_L1);
104 if (idx > 0 && idx < fullName.size() - 1) {
105 person.setFamilyName(fullName.left(idx));
106 person.setGivenName(fullName.mid(idx + 1));
107 } else {
108 person.setName(fullName);
109 }
110 }
111
112
113 for (auto i = 0; i < count; ++i) {
114 Flight flight;
115
116 const auto rms = bcbp.repeatedMandatorySection(i);
117 flight.setDepartureDay(rms.dateOfFlight(issueDate.isValid() ? QDateTime(issueDate, {}) : contextDate));
118
119 Airport dep;
120 dep.setIataCode(rms.fromCityAirportCode());
121 flight.setDepartureAirport(dep);
122 Airport arr;
123 arr.setIataCode(rms.toCityAirportCode());
124 flight.setArrivalAirport(arr);
125 Airline airline;
126 airline.setIataCode(rms.operatingCarrierDesignator());
127 flight.setAirline(airline);
128 flight.setFlightNumber(stripLeadingZeros(rms.flightNumber()));
129
131 res.setReservationFor(flight);
132 res.setPassengerSequenceNumber(stripLeadingZeros(rms.checkinSequenceNumber()));
133 res.setAirplaneSeat(stripLeadingZeros(rms.seatNumber()));
134 res.setReservationNumber(rms.operatingCarrierPNRCode());
135 res.setUnderName(person);
136
137 Ticket ticket;
138 ticket.setTicketToken("aztecCode:"_L1 + bcbp.rawData());
139 const auto rcs = bcbp.repeatedConditionalSection(i);
140 ticket.setTicketNumber(ticketNumber(rcs.airlineNumericCode(), rcs.documentNumber()));
141 res.setReservedTicket(ticket);
142
143 if (!rcs.frequenFlyerNumber().isEmpty()) {
144 ProgramMembership program;
145 program.setMembershipNumber(rcs.frequenFlyerNumber());
146 program.setProgramName(rcs.frequentFlyerAirlineDesignator());
147 program.setMember(person);
148 res.setProgramMembershipUsed(program);
149 }
150
151 result.push_back(checkModeOfTransport(std::move(res)));
152 }
153
154 return result;
155}
A flight reservation.
Definition reservation.h:90
A flight.
Definition flight.h:25
A IATA BarCoded Boarding Pass (BCBP)
Definition iatabcbp.h:21
Q_INVOKABLE KItinerary::IataBcbpRepeatedConditionalSection repeatedConditionalSection(int leg) const
Conditional (optional) section of leg.
Definition iatabcbp.cpp:92
Q_INVOKABLE KItinerary::IataBcbpRepeatedMandatorySection repeatedMandatorySection(int leg) const
Mandatory section of leg.
Definition iatabcbp.cpp:83
static QJsonArray toJson(const QList< QVariant > &data)
Serialize instantiated data types to JSON-LD.
static QVariant fromJsonSingular(const QJsonObject &obj)
Convert a single JSON-LD object into an instantiated data type.
A person.
Definition person.h:20
A frequent traveler, bonus points or discount scheme program membership.
A booked ticket.
Definition ticket.h:41
A train reservation.
A train trip.
Definition traintrip.h:24
QString fullName(const PartType &type)
QList< QVariant > parse(const QString &message, const QDateTime &externalIssueDateTime=QDateTime())
Parses the bar coded boarding pass message message into a list of FlightReservation instances.
Coordinate coordinateForAirport(IataCode iataCode)
Returns the geographical coordinates the airport with IATA code iataCode is in.
Definition airportdb.cpp:30
AlphaId< uint16_t, 3 > IataCode
IATA airport code.
Definition iatacode.h:17
TrainStation stationForIataCode(IataCode iataCode)
Lookup train station data by IATA location code.
QJsonObject flightToTrain(const QJsonObject &flightRes)
Convert a flight reservation to a train reservation.
Classes for reservation/travel data models, data extraction and data augmentation.
Definition berelement.h:17
bool isValid(QStringView ifopt)
bool isValid() const const
void push_back(parameter_type value)
void reserve(qsizetype size)
iterator begin()
iterator end()
qsizetype indexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const const
QString left(qsizetype n) const const
QString mid(qsizetype position, qsizetype n) const const
qsizetype size() const const
const_iterator begin() const const
const_iterator end() const const
qsizetype size() const const
T value() 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.