Skip to content

Commit a81d32e

Browse files
committed
Merge branch 'al-ews-tasks' into 'master'
References: vcs/pull/gromox/gromox!120
2 parents 485d30c + 4afef16 commit a81d32e

File tree

9 files changed

+223
-79
lines changed

9 files changed

+223
-79
lines changed

exch/ews/exceptions.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,7 @@ E(3244, "cannot access target folder");
367367
E(3245, "failed to load content table");
368368
E(3246, "failed to get named property id");
369369
E(3247, "too many sort fields");
370+
E(3248, "PidLidTaskRecurrence contents not recognized");
370371

371372
#undef E
372373
}

exch/ews/namedtags.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ static const PROPERTY_NAME NtTaskDueDate = {MNID_ID, PSETID_TASK, PidLidTaskDueD
2525
static const PROPERTY_NAME NtTaskDateCompleted = {MNID_ID, PSETID_TASK, PidLidTaskDateCompleted};
2626
static const PROPERTY_NAME NtTaskActualEffort = {MNID_ID, PSETID_TASK, PidLidTaskActualEffort};
2727
static const PROPERTY_NAME NtTaskEstimatedEffort = {MNID_ID, PSETID_TASK, PidLidTaskEstimatedEffort};
28+
static const PROPERTY_NAME NtTaskRecurrence = {MNID_ID, PSETID_TASK, PidLidTaskRecurrence};
2829
static const PROPERTY_NAME NtTaskComplete = {MNID_ID, PSETID_TASK, PidLidTaskComplete};
2930
static const PROPERTY_NAME NtTaskOwner = {MNID_ID, PSETID_TASK, PidLidTaskOwner};
3031
static const PROPERTY_NAME NtTaskFRecurring = {MNID_ID, PSETID_TASK, PidLidTaskFRecurring};

exch/ews/serialization.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,8 @@ void tTask::serialize(tinyxml2::XMLElement* xml) const
355355
XMLDUMPT(IsTeamTask);
356356
XMLDUMPT(Mileage);
357357
XMLDUMPT(Owner);
358-
// XMLDUMPT(PercentComplete);
358+
XMLDUMPT(PercentComplete);
359+
XMLDUMPT(Recurrence);
359360
XMLDUMPT(StartDate);
360361
XMLDUMPT(Status);
361362
XMLDUMPT(StatusDescription);
@@ -477,6 +478,12 @@ void tDeletedOccurrenceInfoType::serialize(tinyxml2::XMLElement* xml) const
477478
XMLDUMPT(Start);
478479
}
479480

481+
void tTaskRecurrence::serialize(tinyxml2::XMLElement* xml) const
482+
{
483+
XMLDUMPT(TaskRecurrencePattern);
484+
XMLDUMPT(RecurrenceRange);
485+
}
486+
480487
tCalendarItem::tCalendarItem(const tinyxml2::XMLElement* xml) :
481488
tItem(xml),
482489
XMLINIT(UID),

exch/ews/serialization.hpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,21 @@ struct ExplicitConvert<gromox::EWS::Structures::StrEnum<Cs...>>
212212
{setter(value);}
213213
};
214214

215+
/**
216+
* @brief Conversion specialization for float
217+
*/
218+
template<>
219+
struct ExplicitConvert<double>
220+
{
221+
static constexpr uint8_t value = EC_IN | EC_IMP_OUT;
222+
223+
static tinyxml2::XMLError deserialize(const tinyxml2::XMLElement* xml, double& value)
224+
{return xml->QueryDoubleText(&value);}
225+
226+
static tinyxml2::XMLError deserialize(const tinyxml2::XMLAttribute* xml, double& value)
227+
{return xml->QueryDoubleValue(&value);}
228+
};
229+
215230
///////////////////////////////////////////////////////////////////////////////
216231
//Type unpacking
217232

exch/ews/structures.cpp

Lines changed: 75 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -257,12 +257,12 @@ void daysofweek_to_str(const uint32_t& weekrecur, std::string& daysofweek)
257257
}
258258

259259
/**
260-
* @brief Get the recurrence pattern structure
260+
* @brief Get the appointment recurrence pattern structure
261261
*
262262
* @param recurData Recurrence data
263263
* @return APPOINTMENT_RECUR_PAT Appointment recurrence pattern
264264
*/
265-
APPOINTMENT_RECUR_PAT getAppointmentRecur(const BINARY* recurData)
265+
APPOINTMENT_RECUR_PAT getAppointmentRecurPattern(const BINARY* recurData)
266266
{
267267
EXT_PULL ext_pull;
268268
APPOINTMENT_RECUR_PAT apprecurr;
@@ -272,52 +272,84 @@ APPOINTMENT_RECUR_PAT getAppointmentRecur(const BINARY* recurData)
272272
return apprecurr;
273273
}
274274

275+
/**
276+
* @brief Get the recurrence pattern structure
277+
*
278+
* @param recurData Recurrence data
279+
* @return RECURRENCE_PATTERN Recurrence pattern
280+
*/
281+
RECURRENCE_PATTERN getRecurPattern(const BINARY* recurData)
282+
{
283+
EXT_PULL ext_pull;
284+
RECURRENCE_PATTERN recurr;
285+
ext_pull.init(recurData->pb, recurData->cb, gromox::zalloc, EXT_FLAG_UTF16);
286+
if(ext_pull.g_recpat(&recurr) != EXT_ERR_SUCCESS)
287+
throw InputError(E3248);
288+
return recurr;
289+
}
290+
275291
/**
276292
* @brief Get the Recurrence Pattern object
277293
*
278-
* @param apprecurr Appointment recurrence pattern
294+
* @param recur_pat Recurrence pattern
279295
* @return tRecurrencePattern
280296
*/
281-
tRecurrencePattern get_recurrence_pattern(const APPOINTMENT_RECUR_PAT& apprecurr)
297+
tRecurrencePattern get_recurrence_pattern(const RECURRENCE_PATTERN& recur_pat)
282298
{
283299
ICAL_TIME itime;
284300
std::string daysofweek("");
285-
switch (apprecurr.recur_pat.patterntype)
301+
switch (recur_pat.patterntype)
286302
{
287303
case PATTERNTYPE_DAY:
288-
return tDailyRecurrencePattern(apprecurr.recur_pat.period / 1440);
304+
if(recur_pat.slidingflag)
305+
return tDailyRegeneratingPattern(recur_pat.period / 1440);
306+
return tDailyRecurrencePattern(recur_pat.period / 1440);
289307
case PATTERNTYPE_WEEK:
290308
{
291-
daysofweek_to_str(apprecurr.recur_pat.pts.weekrecur, daysofweek);
292-
return tWeeklyRecurrencePattern(apprecurr.recur_pat.period, daysofweek,
293-
Enum::DayOfWeekType(uint8_t(apprecurr.recur_pat.firstdow)));
309+
daysofweek_to_str(recur_pat.pts.weekrecur, daysofweek);
310+
if(recur_pat.slidingflag)
311+
return tWeeklyRegeneratingPattern(recur_pat.period);
312+
return tWeeklyRecurrencePattern(recur_pat.period, daysofweek,
313+
Enum::DayOfWeekType(uint8_t(recur_pat.firstdow)));
294314
}
295315
case PATTERNTYPE_MONTH:
296316
case PATTERNTYPE_MONTHEND:
297317
case PATTERNTYPE_HJMONTH:
298318
case PATTERNTYPE_HJMONTHEND:
299319
{
300320
ical_get_itime_from_yearday(1601,
301-
apprecurr.recur_pat.firstdatetime / 1440 + 1, &itime);
302-
if(apprecurr.recur_pat.period % 12 != 0)
303-
return tAbsoluteMonthlyRecurrencePattern(apprecurr.recur_pat.period,
304-
apprecurr.recur_pat.pts.dayofmonth);
305-
return tAbsoluteYearlyRecurrencePattern(apprecurr.recur_pat.pts.dayofmonth,
306-
Enum::MonthNamesType(uint8_t(itime.month - 1)));
321+
recur_pat.firstdatetime / 1440 + 1, &itime);
322+
if(recur_pat.period % 12 != 0)
323+
{
324+
if(recur_pat.slidingflag)
325+
return tMonthlyRegeneratingPattern(recur_pat.period);
326+
return tAbsoluteMonthlyRecurrencePattern(recur_pat.period,
327+
recur_pat.pts.dayofmonth);
328+
}
329+
if(recur_pat.slidingflag)
330+
return tYearlyRegeneratingPattern(recur_pat.period);
331+
return tAbsoluteYearlyRecurrencePattern(recur_pat.pts.dayofmonth,
332+
Enum::MonthNamesType(uint8_t(itime.month - 1)));
307333
}
308334
case PATTERNTYPE_MONTHNTH:
309335
case PATTERNTYPE_HJMONTHNTH:
310336
{
311337
ical_get_itime_from_yearday(1601,
312-
apprecurr.recur_pat.firstdatetime / 1440 + 1, &itime);
313-
daysofweek_to_str(apprecurr.recur_pat.pts.weekrecur, daysofweek);
338+
recur_pat.firstdatetime / 1440 + 1, &itime);
339+
daysofweek_to_str(recur_pat.pts.weekrecur, daysofweek);
314340
Enum::DayOfWeekIndexType dayofweekindex(uint8_t(
315-
apprecurr.recur_pat.pts.monthnth.recurnum - 1));
316-
if(apprecurr.recur_pat.period % 12 != 0)
317-
return tRelativeMonthlyRecurrencePattern(apprecurr.recur_pat.period,
318-
daysofweek, dayofweekindex);
341+
recur_pat.pts.monthnth.recurnum - 1));
342+
if(recur_pat.period % 12 != 0)
343+
{
344+
if(recur_pat.slidingflag)
345+
return tMonthlyRegeneratingPattern(recur_pat.period);
346+
return tRelativeMonthlyRecurrencePattern(recur_pat.period,
347+
daysofweek, dayofweekindex);
348+
}
349+
if(recur_pat.slidingflag)
350+
return tYearlyRegeneratingPattern(recur_pat.period);
319351
return tRelativeYearlyRecurrencePattern(daysofweek, dayofweekindex,
320-
Enum::MonthNamesType(uint8_t(itime.month - 1)));
352+
Enum::MonthNamesType(uint8_t(itime.month - 1)));
321353
}
322354
default:
323355
throw InputError(E3110);
@@ -327,19 +359,19 @@ tRecurrencePattern get_recurrence_pattern(const APPOINTMENT_RECUR_PAT& apprecurr
327359
/**
328360
* @brief Get the Recurrence Range object
329361
*
330-
* @param apprecurr Appointment recurrence pattern
362+
* @param recur_pat Recurrence pattern
331363
* @return tRecurrenceRange
332364
*/
333-
tRecurrenceRange get_recurrence_range(const APPOINTMENT_RECUR_PAT& apprecurr)
365+
tRecurrenceRange get_recurrence_range(const RECURRENCE_PATTERN& recur_pat)
334366
{
335-
auto startdate = rop_util_rtime_to_unix2(apprecurr.recur_pat.startdate);
336-
switch (apprecurr.recur_pat.endtype)
367+
auto startdate = rop_util_rtime_to_unix2(recur_pat.startdate);
368+
switch (recur_pat.endtype)
337369
{
338370
case ENDTYPE_AFTER_N_OCCURRENCES:
339-
return tNumberedRecurrenceRange(startdate, apprecurr.recur_pat.occurrencecount);
371+
return tNumberedRecurrenceRange(startdate, recur_pat.occurrencecount);
340372
case ENDTYPE_AFTER_DATE:
341373
return tEndDateRecurrenceRange(startdate,
342-
rop_util_rtime_to_unix2(apprecurr.recur_pat.enddate));
374+
rop_util_rtime_to_unix2(recur_pat.enddate));
343375
default:
344376
return tNoEndRecurrenceRange(startdate);
345377
}
@@ -1318,6 +1350,17 @@ void tTask::update(const sShape& shape)
13181350
Status.emplace(statusType);
13191351
}
13201352
fromProp(shape.get(NtTaskEstimatedEffort), TotalWork);
1353+
if((prop = shape.get(NtTaskRecurrence)))
1354+
{
1355+
const BINARY* recurData = static_cast<BINARY*>(prop->pvalue);
1356+
if(recurData->cb > 0)
1357+
{
1358+
RECURRENCE_PATTERN recurr = getRecurPattern(recurData);
1359+
auto& rec = Recurrence.emplace();
1360+
rec.TaskRecurrencePattern = get_recurrence_pattern(recurr);
1361+
rec.RecurrenceRange = get_recurrence_range(recurr);
1362+
}
1363+
}
13211364
}
13221365

13231366
///////////////////////////////////////////////////////////////////////////////
@@ -1344,11 +1387,11 @@ void tCalendarItem::update(const sShape& shape)
13441387
CalendarItemType.emplace(Enum::RecurringMaster);
13451388
const BINARY* recurData = static_cast<BINARY*>(prop->pvalue);
13461389
if(recurData->cb > 0) {
1347-
APPOINTMENT_RECUR_PAT apprecurr = getAppointmentRecur(recurData);
1390+
APPOINTMENT_RECUR_PAT apprecurr = getAppointmentRecurPattern(recurData);
13481391

13491392
auto& rec = Recurrence.emplace();
1350-
rec.RecurrencePattern = get_recurrence_pattern(apprecurr);
1351-
rec.RecurrenceRange = get_recurrence_range(apprecurr);
1393+
rec.RecurrencePattern = get_recurrence_pattern(apprecurr.recur_pat);
1394+
rec.RecurrenceRange = get_recurrence_range(apprecurr.recur_pat);
13521395

13531396
// The count of the exceptions (modified and deleted occurrences)
13541397
// is summed in deletedinstancecount
@@ -2621,7 +2664,7 @@ decltype(tFieldURI::nameMap) tFieldURI::nameMap = {
26212664
{"task:Mileage", {NtMileage, PT_UNICODE}},
26222665
{"task:Owner", {NtTaskOwner, PT_UNICODE}},
26232666
{"task:PercentComplete", {NtPercentComplete, PT_DOUBLE}},
2624-
// {"task:Recurrence", {}},
2667+
{"task:Recurrence", {NtTaskRecurrence, PT_BINARY}},
26252668
{"task:StartDate", {NtTaskStartDate, PT_SYSTIME}},
26262669
{"task:Status", {NtTaskStatus, PT_LONG}},
26272670
// {"task:StatusDescription", {}},

exch/ews/structures.hpp

Lines changed: 78 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1392,16 +1392,80 @@ struct tDailyRecurrencePattern : public tIntervalRecurrencePatternBase
13921392
tDailyRecurrencePattern(const int& i) : tIntervalRecurrencePatternBase(i) {};
13931393
};
13941394

1395+
/**
1396+
* Types.xsd:4545
1397+
* <xs:complexType name="RegeneratingPatternBaseType" abstract="true">
1398+
*/
1399+
struct tRegeneratingPatternBase : public tIntervalRecurrencePatternBase
1400+
{
1401+
using tIntervalRecurrencePatternBase::tIntervalRecurrencePatternBase;
1402+
};
1403+
1404+
/**
1405+
* Types.xsd:4551
1406+
*/
1407+
struct tDailyRegeneratingPattern : public tIntervalRecurrencePatternBase
1408+
{
1409+
static constexpr char NAME[] = "DailyRegeneration";
1410+
1411+
using tIntervalRecurrencePatternBase::tIntervalRecurrencePatternBase;
1412+
};
1413+
1414+
/**
1415+
* Types.xsd:4551
1416+
*/
1417+
struct tWeeklyRegeneratingPattern : public tIntervalRecurrencePatternBase
1418+
{
1419+
static constexpr char NAME[] = "WeeklyRegeneration";
1420+
1421+
using tIntervalRecurrencePatternBase::tIntervalRecurrencePatternBase;
1422+
};
1423+
1424+
/**
1425+
* Types.xsd:4551
1426+
*/
1427+
struct tMonthlyRegeneratingPattern : public tIntervalRecurrencePatternBase
1428+
{
1429+
static constexpr char NAME[] = "MonthlyRegeneration";
1430+
1431+
using tIntervalRecurrencePatternBase::tIntervalRecurrencePatternBase;
1432+
};
1433+
1434+
/**
1435+
* Types.xsd:4551
1436+
*/
1437+
struct tYearlyRegeneratingPattern : public tIntervalRecurrencePatternBase
1438+
{
1439+
static constexpr char NAME[] = "YearlyRegeneration";
1440+
1441+
using tIntervalRecurrencePatternBase::tIntervalRecurrencePatternBase;
1442+
};
13951443
/**
13961444
* Types.xsd:4848
13971445
*/
1446+
// using tRecurrencePattern = std::variant<
1447+
// tRelativeYearlyRecurrencePattern,
1448+
// tAbsoluteYearlyRecurrencePattern,
1449+
// tRelativeMonthlyRecurrencePattern,
1450+
// tAbsoluteMonthlyRecurrencePattern,
1451+
// tWeeklyRecurrencePattern,
1452+
// tDailyRecurrencePattern
1453+
// >;
1454+
1455+
/**
1456+
* Types.xsd:4861
1457+
*/
13981458
using tRecurrencePattern = std::variant<
13991459
tRelativeYearlyRecurrencePattern,
14001460
tAbsoluteYearlyRecurrencePattern,
14011461
tRelativeMonthlyRecurrencePattern,
14021462
tAbsoluteMonthlyRecurrencePattern,
14031463
tWeeklyRecurrencePattern,
1404-
tDailyRecurrencePattern
1464+
tDailyRecurrencePattern,
1465+
tDailyRegeneratingPattern,
1466+
tWeeklyRegeneratingPattern,
1467+
tMonthlyRegeneratingPattern,
1468+
tYearlyRegeneratingPattern
14051469
>;
14061470

14071471
/**
@@ -1514,6 +1578,18 @@ struct tDeletedOccurrenceInfoType : public NS_EWS_Types
15141578
tDeletedOccurrenceInfoType(const gromox::time_point s) : Start(s) {};
15151579
};
15161580

1581+
/**
1582+
* Types.xsd:4895
1583+
*/
1584+
struct tTaskRecurrence
1585+
{
1586+
// tTaskRecurrencePattern TaskRecurrencePattern;
1587+
tRecurrencePattern TaskRecurrencePattern;
1588+
tRecurrenceRange RecurrenceRange;
1589+
1590+
void serialize(tinyxml2::XMLElement*) const;
1591+
};
1592+
15171593
/**
15181594
* Types.xsd:2353
15191595
*/
@@ -1632,7 +1708,7 @@ struct tTask : public tItem
16321708
std::optional<std::string> Mileage;
16331709
std::optional<std::string> Owner;
16341710
std::optional<double> PercentComplete;
1635-
// <xs:element name="Recurrence" type="t:TaskRecurrenceType" minOccurs="0" />
1711+
std::optional<tTaskRecurrence> Recurrence;
16361712
std::optional<gromox::time_point> StartDate;
16371713
std::optional<Enum::TaskStatusType> Status;
16381714
std::optional<std::string> StatusDescription;

include/gromox/ext_buffer.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ struct EXT_PULL {
194194
pack_result g_msgctnt(MESSAGE_CONTENT *);
195195
pack_result g_fb(freebusy_event *);
196196
pack_result g_fb_a(std::vector<freebusy_event> *);
197+
pack_result g_recpat(RECURRENCE_PATTERN *);
197198

198199
template<typename T> inline T *anew() { return static_cast<T *>(m_alloc(sizeof(T))); }
199200
template<typename T> inline T *anew(size_t elem) { return static_cast<T *>(m_alloc(sizeof(T) * elem)); }

include/gromox/mapitags.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1153,6 +1153,7 @@ enum {
11531153
PidLidTaskDateCompleted = 0x810F,
11541154
PidLidTaskActualEffort = 0x8110,
11551155
PidLidTaskEstimatedEffort = 0x8111,
1156+
PidLidTaskRecurrence = 0x8116,
11561157
PidLidTaskComplete = 0x811C,
11571158
PidLidTaskOwner = 0x811F,
11581159
PidLidTaskFRecurring = 0x8126,

0 commit comments

Comments
 (0)