Commit 718fa90b authored by Volker Krause's avatar Volker Krause
Browse files

Use the new uPER element macros and expand ERA FCB type definitions

parent 2c4c7fe3
Pipeline #247235 passed with stage
in 15 minutes and 16 seconds
......@@ -12,116 +12,290 @@ using namespace KItinerary;
void Fcb::IssuingData::decode(UPERDecoder &decoder)
{
assert(!decoder.readBoolean()); // TODO extension marker
const auto optionals = decoder.readBitset<14>();
if (optionals[13]) {
m_optionals = decoder.readBitset<14>();
if (securityProviderNumIsSet()) {
securityProviderNum = decoder.readConstrainedWholeNumber(1, 32000);
}
if (optionals[12]) {
if (securityProviderIA5IsSet()) {
securityProviderIA5 = decoder.readIA5String();
}
if (optionals[11]) {
if (issuerNumIsSet()) {
issuerNum = decoder.readConstrainedWholeNumber(1, 32000);
}
if (optionals[10]) {
if (issuerIA5IsSet()) {
issuerIA5 = decoder.readIA5String();
}
issuingYear = decoder.readConstrainedWholeNumber(2016, 2269);
issuingDay = decoder.readConstrainedWholeNumber(1, 366);
if (optionals[9]) {
if (issuingTimeIsSet()) {
issuingTime = decoder.readConstrainedWholeNumber(0, 1440);
}
if (optionals[8]) {
if (issuerNameIsSet()) {
issuerName = decoder.readUtf8String();
}
specimen = decoder.readBoolean();
securePaperTicket = decoder.readBoolean();
activated = decoder.readBoolean();
if (optionals[7]) {
if (currencyIsSet()) {
currency = decoder.readIA5String(3, 3);
}
if (optionals[6]) {
if (currencyFractIsSet()) {
currencyFract = decoder.readConstrainedWholeNumber(1, 3);
}
if (optionals[5]) {
if (issuerPNRIsSet()) {
issuerPNR = decoder.readIA5String();
}
assert(!optionals[4]); // TODO ExtensionData
assert(!optionals[3]); // TODO unconstrained number
if (optionals[2]) {
assert(!m_optionals[4]); // TODO ExtensionData
if (issuedOnTrainNumIsSet()) {
issuedOnTrainNum = decoder.readUnconstrainedWholeNumber();
}
if (issuedOnTrainNumIsSet()) {
issuedOnTrainIA5 = decoder.readIA5String();
}
assert(!optionals[1]); // TODO unconstrained number
assert(!optionals[0]); // TODO GeoCoordinateType
if (issuedOnLineIsSet()) {
issuedOnLine = decoder.readUnconstrainedWholeNumber();
}
assert(!m_optionals[0]); // TODO GeoCoordinateType
}
void Fcb::TravelerType::decode(UPERDecoder &decoder)
{
assert(!decoder.readBoolean()); // TODO extension marker
const auto optionals = decoder.readBitset<17>();
if (optionals[16]) {
m_optionals = decoder.readBitset<17>();
if (firstNameIsSet()) {
firstName = decoder.readUtf8String();
}
if (optionals[15]) {
if (secondNameIsSet()) {
secondName = decoder.readUtf8String();
}
if (optionals[14]) {
if (lastNameIsSet()) {
lastName = decoder.readUtf8String();
}
if (optionals[13]) {
if (idCardIsSet()) {
idCard = decoder.readIA5String();
}
if (optionals[12]) {
if (passportIdIsSet()) {
passportId = decoder.readIA5String();
}
if (optionals[11]) {
if (titleIsSet()) {
title = decoder.readIA5String(1, 3);
}
assert(!optionals[10]); // TODO gender
if (optionals[9]) {
if (genderIsSet()) {
gender = decoder.readEnumeratedWithExtensionMarker<GenderType>();
}
if (customerIdIA5IsSet()) {
customerIdIA5 = decoder.readIA5String();
}
if (optionals[8]) {
assert(false);
// TODO read unconstrained integer
if (customerIdNumIsSet()) {
customerIdNum = decoder.readUnconstrainedWholeNumber();
}
if (optionals[7]) {
if (yearOfBirthIsSet()) {
yearOfBirth = decoder.readConstrainedWholeNumber(1901, 2155);
}
if (optionals[6]) {
if (dayOfBirthIsSet()) {
dayOfBirth = decoder.readConstrainedWholeNumber(0, 370);
}
ticketHolder = decoder.readBoolean();
assert(!optionals[5]); // TODO passengerType
assert(!optionals[4]); // TODO passengerWithReducedMobility
if (optionals[3]) {
if (passengerTypeIsSet()) {
passengerType = decoder.readEnumeratedWithExtensionMarker<PassengerType>();
}
if (passengerWithReducedMobilityIsSet()) {
passengerWithReducedMobility = decoder.readBoolean();
}
if (countryOfResidenceIsSet()) {
countryOfResidence = decoder.readConstrainedWholeNumber(1, 999);
}
if (optionals[2]) {
if (countryOfPassportIsSet()) {
countryOfPassport = decoder.readConstrainedWholeNumber(1, 999);
}
if (optionals[1]) {
if (countryOfIdCardIsSet()) {
countryOfIdCard = decoder.readConstrainedWholeNumber(1, 999);
}
assert(!optionals[0]); // TODO status
assert(!m_optionals[0]); // TODO status
}
void Fcb::TravelerData::decode(UPERDecoder &decoder)
{
assert(!decoder.readBoolean()); // TODO extension marker
const auto optionals = decoder.readBitset<3>();
if (optionals[2]) {
m_optionals = decoder.readBitset<3>();
if (travelerIsSet()) {
traveler = decoder.readSequenceOf<TravelerType>();
}
if (optionals[1]) {
if (preferredLanguageIsSet()) {
preferredLanguage = decoder.readIA5String(2, 2);
}
if (optionals[0]) {
if (groupNameIsSet()) {
groupName = decoder.readUtf8String();
}
}
void Fcb::TrainLinkType::decode(UPERDecoder &decoder)
{
m_optionals = decoder.readBitset<9>();
if (trainNumIsSet()) {
trainNum = decoder.readUnconstrainedWholeNumber();
}
if (trainIA5IsSet()) {
trainIA5 = decoder.readIA5String();
}
travelDate = decoder.readConstrainedWholeNumber(-1, 370);
departureTime = decoder.readConstrainedWholeNumber(0, 1440);
if (departureUTCOffsetIsSet()) {
departureUTCOffset = decoder.readConstrainedWholeNumber(-60, 60);
}
if (fromStationNumIsSet()) {
fromStationNum = decoder.readConstrainedWholeNumber(1, 9999999);
}
if (fromStationIA5IsSet()) {
fromStationIA5 = decoder.readIA5String();
}
if (toStationNumIsSet()) {
toStationNum = decoder.readConstrainedWholeNumber(1, 9999999);
}
if (toStationIA5IsSet()) {
toStationIA5 = decoder.readIA5String();
}
if (fromStationNameUTF8IsSet()) {
fromStationNameUTF8 = decoder.readUtf8String();
}
if (toStationNameUTF8IsSet()) {
toStationNameUTF8 = decoder.readUtf8String();
}
}
void Fcb::RegionalValidityType::decode(UPERDecoder &decoder)
{
assert(!decoder.readBoolean()); // TODO extension marker
const auto choice = decoder.readConstrainedWholeNumber(0, 4);
switch (choice) {
case 0:
{
TrainLinkType v;
v.decode(decoder);
value = QVariant::fromValue(v);
break;
}
default:
qDebug() << choice; // TODO
assert(false);
}
}
void Fcb::ReturnRouteDescriptionType::decode(UPERDecoder &decoder)
{
// TODO
assert(false);
}
void Fcb::OpenTicketData::decode(UPERDecoder &decoder)
{
assert(!decoder.readBoolean()); // TODO extension marker
m_optionals = decoder.readBitset<38>();
if (referenceNumIsSet()) {
referenceNum = decoder.readUnconstrainedWholeNumber();
}
if (referenceIA5IsSet()) {
referenceIA5 = decoder.readIA5String();
}
if (productOwnerNumIsSet()) {
productOwnerNum = decoder.readConstrainedWholeNumber(1, 32000);
}
if (productOwnerIA5IsSet()) {
productOwnerIA5 = decoder.readIA5String();
}
if (productIdNumIsSet()) {
productIdNum = decoder.readConstrainedWholeNumber(0, 32000);
}
if (productIdIA5IsSet()) {
productIdIA5 = decoder.readIA5String();
}
if (extIssuerIdIsSet()) {
extIssuerId = decoder.readUnconstrainedWholeNumber();
}
if (issuerAutorizationIdIsSet()) {
issuerAutorizationId = decoder.readUnconstrainedWholeNumber();
}
returnIncluded = decoder.readBoolean();
if (stationCodeTableIsSet()) {
stationCodeTable = decoder.readEnumerated<CodeTableType>();
}
if (fromStationNumIsSet()) {
fromStationNum = decoder.readConstrainedWholeNumber(1, 9999999);
}
if (fromStationIA5IsSet()) {
fromStationIA5 = decoder.readIA5String();
}
if (toStationNumIsSet()) {
toStationNum = decoder.readConstrainedWholeNumber(1, 9999999);
}
if (toStationIA5IsSet()) {
toStationIA5 = decoder.readIA5String();
}
if (fromStationNameUTF8IsSet()) {
fromStationNameUTF8 = decoder.readUtf8String();
}
if (toStationNameUTF8IsSet()) {
toStationNameUTF8 = decoder.readUtf8String();
}
if (validRegionDescIsSet()) {
validRegionDesc = decoder.readUtf8String();
}
if (validRegionIsSet()) {
validRegion = decoder.readSequenceOf<RegionalValidityType>();
}
if (returnDescriptionIsSet()) {
returnDescription.decode(decoder);
}
if (validFromDayIsSet()) {
validFromDay = decoder.readConstrainedWholeNumber(-1, 700);
}
if (validFromTimeIsSet()) {
validFromTime = decoder.readConstrainedWholeNumber(0, 1440);
}
if (validFromUTCOffsetIsSet()) {
validFromUTCOffset = decoder.readConstrainedWholeNumber(-60, 60);
}
if (validUntilDayIsSet()) {
validUntilDay = decoder.readConstrainedWholeNumber(0, 370);
}
if (validUntilTimeIsSet()) {
validUntilTime = decoder.readConstrainedWholeNumber(0, 1440);
}
if (validUntilUTCOffsetIsSet()) {
validUntilUTCOffset = decoder.readConstrainedWholeNumber(-60, 60);
}
// TODO activatedDay
if (classCodeIsSet()) {
classCode = decoder.readEnumeratedWithExtensionMarker<TravelClassType>();
}
if (serviceLevelIsSet()) {
serviceLevel = decoder.readIA5String(1, 2);
}
// TODO
}
void Fcb::DocumentData::decode(UPERDecoder &decoder)
{
assert(!decoder.readBoolean()); // TODO extension marker
m_optionals = decoder.readBitset<1>();
assert(!m_optionals[0]); // TODO token
assert(!decoder.readBoolean()); // TODO extension marker for CHOICE
const auto choiceIdx = decoder.readConstrainedWholeNumber(0, 11);
switch (choiceIdx) {
// TODO
case 2: {
OpenTicketData t;
t.decode(decoder);
ticket = QVariant::fromValue(t);
}
}
}
Fcb::UicRailTicketData::UicRailTicketData() = default;
Fcb::UicRailTicketData::UicRailTicketData(const Uic9183Block &block)
......@@ -134,11 +308,14 @@ Fcb::UicRailTicketData::UicRailTicketData(const Uic9183Block &block)
void Fcb::UicRailTicketData::decode(UPERDecoder &decoder)
{
assert(!decoder.readBoolean()); // TODO extension marker
const auto optionals = decoder.readBitset<4>();
if (optionals[3]) {
issuingDetail.decode(decoder);
}
if (optionals[2]) {
m_optionals = decoder.readBitset<4>();
issuingDetail.decode(decoder);
if (travelerDetailIsSet()) {
travelerDetail.decode(decoder);
}
if (transportDocumentIsSet()) {
transportDocument = decoder.readSequenceOf<DocumentData>();
}
}
#include "moc_fcbticket.cpp"
......@@ -8,7 +8,12 @@
#include <KItinerary/Uic9183Block>
#include "asn1/uperelement.h"
#include <QList>
#include <QVariant>
#include <bitset>
namespace KItinerary {
......@@ -19,128 +24,228 @@ class UPERDecoder;
*/
namespace Fcb {
Q_NAMESPACE
class IssuingData {
Q_GADGET
Q_PROPERTY(int securityProviderNum MEMBER securityProviderNum)
Q_PROPERTY(QByteArray securityProviderIA5 MEMBER securityProviderIA5)
Q_PROPERTY(int issuerNum MEMBER issuerNum)
Q_PROPERTY(QByteArray issuerIA5 MEMBER issuerIA5)
Q_PROPERTY(int issuingYear MEMBER issuingYear)
Q_PROPERTY(int issuingDay MEMBER issuingDay)
Q_PROPERTY(int issuingTime MEMBER issuingTime)
Q_PROPERTY(QString issuerName MEMBER issuerName)
Q_PROPERTY(bool specimen MEMBER specimen)
Q_PROPERTY(bool securePaperTicket MEMBER securePaperTicket)
Q_PROPERTY(bool activated MEMBER activated)
Q_PROPERTY(QByteArray currency MEMBER currency)
Q_PROPERTY(int currencyFract MEMBER currencyFract)
Q_PROPERTY(QByteArray issuerPNR MEMBER issuerPNR)
// TODO extension data
Q_PROPERTY(int issuedOnTrainNum MEMBER issuedOnTrainNum)
Q_PROPERTY(QByteArray issuedOnTrainIA5 MEMBER issuedOnTrainIA5)
Q_PROPERTY(int issuedOnLine MEMBER issuedOnLine)
// TODO pointOfSale
UPER_GADGET
UPER_ELEMENT_OPTIONAL(int, securityProviderNum, 0)
UPER_ELEMENT_OPTIONAL(QByteArray, securityProviderIA5, 1)
UPER_ELEMENT_OPTIONAL(int, issuerNum, 2)
UPER_ELEMENT_OPTIONAL(QByteArray, issuerIA5, 3)
UPER_ELEMENT(int, issuingYear)
UPER_ELEMENT(int, issuingDay)
UPER_ELEMENT_OPTIONAL(int, issuingTime, 4)
UPER_ELEMENT_OPTIONAL(QString, issuerName, 5)
UPER_ELEMENT(bool, specimen)
UPER_ELEMENT(bool, securePaperTicket)
UPER_ELEMENT(bool, activated)
UPER_ELEMENT_DEFAULT(QByteArray, currency, "EUR", 6)
UPER_ELEMENT_DEFAULT(int, currencyFract, 2, 7)
UPER_ELEMENT_OPTIONAL(QByteArray, issuerPNR, 8)
// TODO extension ExtensionData OPTIONAL
UPER_ELEMENT_OPTIONAL(int, issuedOnTrainNum, 10)
UPER_ELEMENT_OPTIONAL(QByteArray, issuedOnTrainIA5, 11)
UPER_ELEMENT_OPTIONAL(int, issuedOnLine, 12)
// TODO pointOfSale GeoCoordinateType OPTIONAL
public:
void decode(UPERDecoder &decoder);
int securityProviderNum; // INTEGER (1..32000) OPTIONAL
QByteArray securityProviderIA5; // IA5String OPTIONAL
int issuerNum; // INTEGER (1..32000) OPTIONAL
QByteArray issuerIA5; // IA5String OPTIONAL
int issuingYear; // INTEGER (2016..2269)
int issuingDay; // INTEGER (1..366)
int issuingTime; // INTEGER (0..1440) OPTIONAL
QString issuerName; // UTF8String OPTIONAL
bool specimen;
bool securePaperTicket;
bool activated;
QByteArray currency = QByteArray("EUR"); // IA5String (SIZE(3)) DEFAULT "EUR"
int currencyFract = 2; // INTEGER (1..3) DEFAULT 2
QByteArray issuerPNR; //IA5String OPTIONAL
// TODO extension ExtensionData OPTIONAL,
int issuedOnTrainNum; // OPTIONAL
QByteArray issuedOnTrainIA5; // OPTIONAL
int issuedOnLine; // OPTIONAL
// TODO pointOfSale GeoCoordinateType OPTIONAL
private:
std::bitset<14> m_optionals;
};
enum GenderType {
unspecified = 0,
female = 1,
male = 2,
other = 3,
};
Q_ENUM_NS(GenderType)
enum PassengerType {
adult = 0,
senior = 1,
child = 2,
youth = 3,
dog = 4,
bicycle = 5,
freeAddonPassenger = 6,
freeAddonChild = 7,
};
Q_ENUM_NS(PassengerType)
class TravelerType {
Q_GADGET
Q_PROPERTY(QString firstName MEMBER firstName)
Q_PROPERTY(QString secondName MEMBER secondName)
Q_PROPERTY(QString lastName MEMBER lastName)
Q_PROPERTY(QByteArray idCard MEMBER idCard)
Q_PROPERTY(QByteArray passportId MEMBER passportId)
Q_PROPERTY(QByteArray title MEMBER title)
// TODO gender
Q_PROPERTY(QByteArray customerIdIA5 MEMBER customerIdIA5)
Q_PROPERTY(int customerIdNum MEMBER customerIdNum)
Q_PROPERTY(int yearOfBirth MEMBER yearOfBirth)
Q_PROPERTY(int dayOfBirth MEMBER dayOfBirth)
Q_PROPERTY(bool ticketHolder MEMBER ticketHolder)
// TODO passengerType
// TODO passengerWithReducedMobility
Q_PROPERTY(int countryOfResidence MEMBER countryOfResidence)
Q_PROPERTY(int countryOfPassport MEMBER countryOfPassport)
Q_PROPERTY(int countryOfIdCard MEMBER countryOfIdCard)
// TODO status
UPER_GADGET
UPER_ELEMENT_OPTIONAL(QString, firstName, 0)
UPER_ELEMENT_OPTIONAL(QString, secondName, 1)
UPER_ELEMENT_OPTIONAL(QString, lastName, 2)
UPER_ELEMENT_OPTIONAL(QByteArray, idCard, 3)
UPER_ELEMENT_OPTIONAL(QByteArray, passportId, 4)
UPER_ELEMENT_OPTIONAL(QByteArray, title, 5)
UPER_ELEMENT_OPTIONAL(KItinerary::Fcb::GenderType, gender, 6)
UPER_ELEMENT_OPTIONAL(QByteArray, customerIdIA5, 7)
UPER_ELEMENT_OPTIONAL(int, customerIdNum, 8)
UPER_ELEMENT_OPTIONAL(int, yearOfBirth, 9)
UPER_ELEMENT_OPTIONAL(int, dayOfBirth, 10)
UPER_ELEMENT(bool, ticketHolder)
UPER_ELEMENT_OPTIONAL(KItinerary::Fcb::PassengerType, passengerType, 11)
UPER_ELEMENT_OPTIONAL(bool, passengerWithReducedMobility, 12)
UPER_ELEMENT_OPTIONAL(int, countryOfResidence, 13)
UPER_ELEMENT_OPTIONAL(int, countryOfPassport, 14)
UPER_ELEMENT_OPTIONAL(int, countryOfIdCard, 15)
// TODO status SEQUENCE OF CustomerStatusType OPTIONAL
public:
void decode(UPERDecoder &decoder);
QString firstName; // UTF8String OPTIONAL
QString secondName; // UTF8String OPTIONAL
QString lastName; // UTF8String OPTIONAL
QByteArray idCard; // IA5String OPTIONAL
QByteArray passportId; // IA5String OPTIONAL
QByteArray title; // IA5String (SIZE(1..3)) OPTIONAL
// TODO gender GenderType OPTIONAL
QByteArray customerIdIA5; // IA5String OPTIONAL
int customerIdNum; // INTEGER OPTIONAL
int yearOfBirth; // INTEGER (1901..2155) OPTIONAL
int dayOfBirth; // INTEGER (0..370) OPTIONAL
bool ticketHolder;
// TODO passengerType PassengerType OPTIONAL
// TODO passengerWithReducedMobility BOOLEAN OPTIONAL
int countryOfResidence; // INTEGER (1..999) OPTIONAL
int countryOfPassport; // INTEGER (1..999) OPTIONAL
int countryOfIdCard; // INTEGER (1..999) OPTIONAL
// TODO status SEQUENCE OF CustomerStatusType OPTIONAL
private:
std::bitset<17> m_optionals;
};
class TravelerData {
Q_GADGET
Q_PROPERTY(QList<KItinerary::Fcb::TravelerType> traveler MEMBER traveler CONSTANT)
Q_PROPERTY(QByteArray preferredLanguage MEMBER preferredLanguage)
Q_PROPERTY(QString groupName MEMBER groupName)
UPER_GADGET
UPER_ELEMENT_OPTIONAL(QList<KItinerary::Fcb::TravelerType>, traveler, 0)
UPER_ELEMENT_OPTIONAL(QByteArray, preferredLanguage, 1)
UPER_ELEMENT_OPTIONAL(QString, groupName, 2)
public:
void decode(UPERDecoder &decoder);
QList<TravelerType> traveler; // OPTIONAL
QByteArray preferredLanguage; // IA5String (SIZE(2)) OPTIONAL
QString groupName; // UTF8String OPTIONAL
private:
std::bitset<3> m_optionals;
};
class KITINERARY_EXPORT UicRailTicketData {
Q_GADGET
Q_PROPERTY(KItinerary::Fcb::IssuingData issuingDetail MEMBER issuingDetail CONSTANT)
Q_PROPERTY(KItinerary::Fcb::TravelerData travelerDetail MEMBER travelerDetail CONSTANT)
enum CodeTableType {
stationUIC = 0,
stationUICReservation = 1,
stationERA = 2,
localCarrierStationCodeTable = 3,
proprietaryIssuerStationCodeTable = 4,
};
Q_ENUM_NS(CodeTableType)
class TrainLinkType {
UPER_GADGET
UPER_ELEMENT_OPTIONAL(int, trainNum, 0)
UPER_ELEMENT_OPTIONAL(QByteArray, trainIA5, 1)
UPER_ELEMENT(int, travelDate)
UPER_ELEMENT(int, departureTime)
UPER_ELEMENT_OPTIONAL(int, departureUTCOffset, 2)
UPER_ELEMENT_OPTIONAL(int, fromStationNum, 3)
UPER_ELEMENT_OPTIONAL(QByteArray, fromStationIA5, 4)
UPER_ELEMENT_OPTIONAL(int, toStationNum, 5)
UPER_ELEMENT_OPTIONAL(QByteArray, toStationIA5, 6)
UPER_ELEMENT_OPTIONAL(QString, fromStationNameUTF8, 7)
UPER_ELEMENT_OPTIONAL(QString, toStationNameUTF8, 8)
public:
UicRailTicketData();
UicRailTicketData(const Uic9183Block &block);
void decode(UPERDecoder &decoder);
private:
std::bitset<9> m_optionals;
};
class RegionalValidityType {
UPER_GADGET
UPER_ELEMENT(QVariant, value)
public:
void decode(UPERDecoder &decoder);
};
class ReturnRouteDescriptionType {
UPER_GADGET
// TODO
public:
void decode(UPERDecoder &decoder);
};
enum TravelClassType {
notApplicable = 0,
first = 1,
second = 2,
tourist = 3,
comfort = 4,
premium = 5,
business = 6,
all = 7
};
Q_ENUM_NS(TravelClassType)
class OpenTicketData {