Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F117756521
xcalconversions.h
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
56 KB
Referenced Files
None
Subscribers
None
xcalconversions.h
View Options
/*
* Copyright (C) 2011 Christian Mollekopf <mollekopf@kolabsys.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XCALCONVERSIONS_H
#define XCALCONVERSIONS_H
#include
"global_definitions.h"
#include
<bindings/kolabformat-xcal.hxx>
#include
<bindings/iCalendar-props.hxx>
#include
<compiled/XMLParserWrapper.h>
#include
<boost/shared_ptr.hpp>
#include
<boost/numeric/conversion/converter_policies.hpp>
#include
<boost/numeric/conversion/cast.hpp>
#include
<boost/foreach.hpp>
#include
<fstream>
#include
<iostream>
#include
<boost/lexical_cast.hpp>
#include
"kolabcontainers.h"
#include
"kolabtodo.h"
#include
"kolabevent.h"
#include
"kolabjournal.h"
#include
"utils.h"
#include
"base64.h"
#include
"shared_conversions.h"
namespace
Kolab
{
namespace
XCAL
{
std
::
string
global_xCalVersion
;
const
char
*
const
XCAL_VERSION
=
"2.0"
;
const
char
*
const
XCAL_NAMESPACE
=
"urn:ietf:params:xml:ns:icalendar-2.0"
;
const
char
*
const
TZ_PREFIX
=
"/kolab.org/"
;
const
char
*
const
THISANDFUTURE
=
"THISANDFUTURE"
;
const
char
*
const
BASE64
=
"BASE64"
;
const
char
*
const
NEEDSACTION
=
"NEEDS-ACTION"
;
const
char
*
const
COMPLETED
=
"OPAQUE"
;
const
char
*
const
INPROCESS
=
"IN-PROCESS"
;
const
char
*
const
CANCELLED
=
"CANCELLED"
;
const
char
*
const
TENTATIVE
=
"TENTATIVE"
;
const
char
*
const
CONFIRMED
=
"CONFIRMED"
;
const
char
*
const
DRAFT
=
"DRAFT"
;
const
char
*
const
FINAL
=
"FINAL"
;
const
char
*
const
CONFIDENTIAL
=
"CONFIDENTIAL"
;
const
char
*
const
PRIVATE
=
"PRIVATE"
;
const
char
*
const
PUBLIC
=
"PUBLIC"
;
const
char
*
const
PARTACCEPTED
=
"ACCEPTED"
;
const
char
*
const
PARTDECLINED
=
"DECLINED"
;
const
char
*
const
PARTDELEGATED
=
"DELEGATED"
;
const
char
*
const
PARTNEEDSACTION
=
"NEEDS-ACTION"
;
const
char
*
const
PARTTENTATIVE
=
"TENTATIVE"
;
const
char
*
const
CHAIR
=
"CHAIR"
;
const
char
*
const
NONPARTICIPANT
=
"NON-PARTICIPANT"
;
const
char
*
const
OPTIONAL
=
"OPT-PARTICIPANT"
;
const
char
*
const
REQUIRED
=
"REQ-PARTICIPANT"
;
const
char
*
const
DISPLAYALARM
=
"DISPLAY"
;
const
char
*
const
EMAILALARM
=
"EMAIL"
;
const
char
*
const
AUDIOALARM
=
"AUDIO"
;
const
char
*
const
TRANSPARENT
=
"TRANSPARENT"
;
const
char
*
const
OPAQUE
=
"OPAQUE"
;
const
char
*
const
MO
=
"MO"
;
const
char
*
const
TU
=
"TU"
;
const
char
*
const
WE
=
"WE"
;
const
char
*
const
TH
=
"TH"
;
const
char
*
const
FR
=
"FR"
;
const
char
*
const
SA
=
"SA"
;
const
char
*
const
SU
=
"SU"
;
//Alarms
const
char
*
const
START
=
"START"
;
const
char
*
const
END
=
"END"
;
using
namespace
Kolab
::
Utils
;
using
namespace
Kolab
::
Shared
;
//=== Generic Conversions ===
int
toInt
(
const
icalendar_2_0
::
IntegerPropertyType
&
prop
)
{
return
convertToInt
<
icalendar_2_0
::
IntegerPropertyType
::
integer_type
>
(
prop
.
integer
());
}
std
::
vector
<
std
::
string
>
toStringList
(
const
icalendar_2_0
::
TextListPropertyType
&
s
)
{
std
::
vector
<
std
::
string
>
d
;
std
::
copy
(
s
.
text
().
begin
(),
s
.
text
().
end
(),
std
::
back_inserter
(
d
));
return
d
;
}
template
<
typename
T
>
std
::
auto_ptr
<
T
>
fromStringList
(
const
std
::
vector
<
std
::
string
>
&
list
)
{
std
::
auto_ptr
<
T
>
ptr
(
new
T
());
std
::
copy
(
list
.
begin
(),
list
.
end
(),
std
::
back_inserter
(
ptr
->
text
()));
return
ptr
;
}
//TODO doesn't seem very useful after all, remove
std
::
string
toString
(
const
icalendar_2_0
::
TextPropertyType
&
s
)
{
return
s
.
text
();
}
std
::
string
fromDayPos
(
const
Kolab
::
DayPos
&
d
)
{
std
::
string
s
;
if
(
d
.
occurence
()
!=
0
)
{
s
.
append
(
boost
::
lexical_cast
<
std
::
string
>
(
d
.
occurence
()));
}
switch
(
d
.
weekday
())
{
case
Kolab
::
Monday
:
s
.
append
(
MO
);
break
;
case
Kolab
::
Tuesday
:
s
.
append
(
TU
);
break
;
case
Kolab
::
Wednesday
:
s
.
append
(
WE
);
break
;
case
Kolab
::
Thursday
:
s
.
append
(
TH
);
break
;
case
Kolab
::
Friday
:
s
.
append
(
FR
);
break
;
case
Kolab
::
Saturday
:
s
.
append
(
SA
);
break
;
case
Kolab
::
Sunday
:
s
.
append
(
SU
);
break
;
}
return
s
;
}
Kolab
::
DayPos
toDayPos
(
const
std
::
string
&
s
)
{
std
::
string
number
;
bool
gotOccurrence
=
false
;
int
occurrence
=
0
;
for
(
std
::
string
::
const_iterator
it
=
s
.
begin
();
it
!=
s
.
end
();
it
++
)
{
switch
(
*
it
)
{
case
'0'
:
case
'1'
:
case
'2'
:
case
'3'
:
case
'4'
:
case
'5'
:
case
'6'
:
case
'7'
:
case
'8'
:
case
'9'
:
case
'+'
:
case
'-'
:
number
.
push_back
(
*
it
);
break
;
default
:
if
(
!
gotOccurrence
&&
!
number
.
empty
())
{
try
{
occurrence
=
boost
::
lexical_cast
<
int
>
(
number
);
}
catch
(
boost
::
bad_lexical_cast
&
)
{
ERROR
(
"failed to convert: "
+
number
);
return
DayPos
();
}
number
.
clear
();
}
gotOccurrence
=
true
;
number
.
push_back
(
*
it
);
break
;
}
}
if
(
number
==
MO
)
{
return
DayPos
(
occurrence
,
Kolab
::
Monday
);
}
else
if
(
number
==
TU
)
{
return
DayPos
(
occurrence
,
Kolab
::
Tuesday
);
}
else
if
(
number
==
WE
)
{
return
DayPos
(
occurrence
,
Kolab
::
Wednesday
);
}
else
if
(
number
==
TH
)
{
return
DayPos
(
occurrence
,
Kolab
::
Thursday
);
}
else
if
(
number
==
FR
)
{
return
DayPos
(
occurrence
,
Kolab
::
Friday
);
}
else
if
(
number
==
SA
)
{
return
DayPos
(
occurrence
,
Kolab
::
Saturday
);
}
else
if
(
number
==
SU
)
{
return
DayPos
(
occurrence
,
Kolab
::
Sunday
);
}
return
DayPos
();
}
std
::
string
fromDuration
(
const
Kolab
::
Duration
&
d
)
{
std
::
string
s
;
if
(
!
d
.
isValid
())
{
return
s
;
}
if
(
d
.
isNegative
())
{
s
.
push_back
(
'-'
);
}
s
.
push_back
(
'P'
);
try
{
if
(
d
.
weeks
()
>
0
)
{
s
.
append
(
boost
::
lexical_cast
<
std
::
string
>
(
d
.
weeks
()));
s
.
push_back
(
'W'
);
}
if
(
d
.
days
()
>
0
)
{
s
.
append
(
boost
::
lexical_cast
<
std
::
string
>
(
d
.
days
()));
s
.
push_back
(
'D'
);
}
if
(
d
.
hours
()
>
0
||
d
.
minutes
()
>
0
||
d
.
seconds
()
>
0
)
{
s
.
push_back
(
'T'
);
if
(
d
.
hours
()
>
0
)
{
s
.
append
(
boost
::
lexical_cast
<
std
::
string
>
(
d
.
hours
()));
s
.
push_back
(
'H'
);
}
if
(
d
.
minutes
()
>
0
)
{
s
.
append
(
boost
::
lexical_cast
<
std
::
string
>
(
d
.
minutes
()));
s
.
push_back
(
'M'
);
}
if
(
d
.
seconds
()
>
0
)
{
s
.
append
(
boost
::
lexical_cast
<
std
::
string
>
(
d
.
seconds
()));
s
.
push_back
(
'S'
);
}
}
}
catch
(
boost
::
bad_lexical_cast
&
)
{
ERROR
(
"failed to convert duration"
);
return
std
::
string
();
}
return
s
;
}
Kolab
::
Duration
toDuration
(
const
icalendar_2_0
::
DurationValueType
&
d
)
{
int
weeks
=
0
;
int
days
=
0
;
int
hours
=
0
;
int
minutes
=
0
;
int
seconds
=
0
;
bool
negative
=
false
;
std
::
string
number
;
for
(
std
::
string
::
const_iterator
it
=
d
.
begin
();
it
!=
d
.
end
();
it
++
)
{
switch
(
*
it
)
{
case
'0'
:
case
'1'
:
case
'2'
:
case
'3'
:
case
'4'
:
case
'5'
:
case
'6'
:
case
'7'
:
case
'8'
:
case
'9'
:
number
.
push_back
(
*
it
);
break
;
case
'H'
:
try
{
hours
=
boost
::
lexical_cast
<
int
>
(
number
);
}
catch
(
boost
::
bad_lexical_cast
&
)
{
ERROR
(
"failed to convert: "
+
number
);
return
Duration
();
}
number
.
clear
();
break
;
case
'M'
:
try
{
minutes
=
boost
::
lexical_cast
<
int
>
(
number
);
}
catch
(
boost
::
bad_lexical_cast
&
)
{
ERROR
(
"failed to convert: "
+
number
);
return
Duration
();
}
number
.
clear
();
break
;
case
'S'
:
try
{
seconds
=
boost
::
lexical_cast
<
int
>
(
number
);
}
catch
(
boost
::
bad_lexical_cast
&
)
{
ERROR
(
"failed to convert: "
+
number
);
return
Duration
();
}
number
.
clear
();
break
;
case
'T'
:
break
;
case
'W'
:
try
{
weeks
=
boost
::
lexical_cast
<
int
>
(
number
);
}
catch
(
boost
::
bad_lexical_cast
&
)
{
ERROR
(
"failed to convert: "
+
number
);
return
Duration
();
}
return
Duration
(
weeks
,
negative
);
case
'D'
:
try
{
days
=
boost
::
lexical_cast
<
int
>
(
number
);
}
catch
(
boost
::
bad_lexical_cast
&
)
{
ERROR
(
"failed to convert: "
+
number
);
return
Duration
();
}
number
.
clear
();
break
;
case
'+'
:
break
;
case
'-'
:
negative
=
true
;
break
;
case
'P'
:
break
;
default
:
ERROR
(
"failed to convert duration: "
+
*
it
);
return
Duration
();
}
}
return
Duration
(
days
,
hours
,
minutes
,
seconds
,
negative
);
}
void
setCalAddress
(
const
icalendar_2_0
::
CalAddressPropertyType
&
cal
,
std
::
string
&
email
,
std
::
string
&
name
)
{
if
(
cal
.
parameters
())
{
for
(
icalendar_2_0
::
ArrayOfParameters
::
baseParameter_const_iterator
it
((
*
cal
.
parameters
()).
baseParameter
().
begin
());
it
!=
(
*
cal
.
parameters
()).
baseParameter
().
end
();
it
++
)
{
if
(
const
icalendar_2_0
::
CnParamType
*
tz
=
dynamic_cast
<
const
icalendar_2_0
::
CnParamType
*>
(
&*
it
))
{
name
=
tz
->
text
();
}
}
}
email
=
fromMailto
(
cal
.
cal_address
());
}
template
<
typename
T
>
Kolab
::
Attachment
toAttachment
(
T
aProp
)
{
Kolab
::
Attachment
a
;
std
::
string
mimetype
;
if
(
aProp
.
parameters
())
{
const
icalendar_2_0
::
AttachPropType
::
parameters_type
&
parameters
=
*
aProp
.
parameters
();
for
(
icalendar_2_0
::
AttachPropType
::
parameters_type
::
baseParameter_const_iterator
it
(
parameters
.
baseParameter
().
begin
());
it
!=
parameters
.
baseParameter
().
end
();
it
++
)
{
if
(
const
icalendar_2_0
::
FmttypeParamType
*
p
=
dynamic_cast
<
const
icalendar_2_0
::
FmttypeParamType
*>
(
&*
it
))
{
mimetype
=
p
->
text
();
}
if
(
const
icalendar_2_0
::
EncodingParamType
*
p
=
dynamic_cast
<
const
icalendar_2_0
::
EncodingParamType
*>
(
&*
it
))
{
if
(
p
->
text
()
!=
BASE64
)
{
ERROR
(
"wrong encoding"
);
return
Kolab
::
Attachment
();
}
}
if
(
const
icalendar_2_0
::
XlabelParamType
*
p
=
dynamic_cast
<
const
icalendar_2_0
::
XlabelParamType
*>
(
&*
it
))
{
a
.
setLabel
(
p
->
text
());
}
}
}
if
(
mimetype
.
empty
())
{
ERROR
(
"no mimetype"
);
}
if
(
aProp
.
uri
())
{
a
.
setUri
(
*
aProp
.
uri
(),
mimetype
);
}
else
if
(
aProp
.
binary
())
{
a
.
setData
(
base64_decode
(
*
aProp
.
binary
()),
mimetype
);
}
else
{
ERROR
(
"not uri and no data available"
);
}
return
a
;
}
icalendar_2_0
::
AttachPropType
fromAttachment
(
const
Kolab
::
Attachment
&
a
)
{
icalendar_2_0
::
AttachPropType
attachment
;
icalendar_2_0
::
AttachPropType
::
parameters_type
p
;
p
.
baseParameter
().
push_back
(
icalendar_2_0
::
FmttypeParamType
(
a
.
mimetype
()));
if
(
!
a
.
label
().
empty
())
{
p
.
baseParameter
().
push_back
(
icalendar_2_0
::
XlabelParamType
(
a
.
label
()));
}
if
(
!
a
.
uri
().
empty
())
{
attachment
.
uri
(
a
.
uri
());
}
else
if
(
!
a
.
data
().
empty
())
{
attachment
.
binary
(
base64_encode
(
reinterpret_cast
<
const
unsigned
char
*>
(
a
.
data
().
c_str
()),
a
.
data
().
length
()));
p
.
baseParameter
().
push_back
(
icalendar_2_0
::
EncodingParamType
(
BASE64
));
}
else
{
ERROR
(
"no uri and no data"
);
}
attachment
.
parameters
(
p
);
return
attachment
;
}
//==== cDateTime ====
std
::
string
getTimezone
(
const
icalendar_2_0
::
ArrayOfParameters
&
parameters
)
{
for
(
icalendar_2_0
::
DateDatetimePropertyType
::
parameters_type
::
baseParameter_const_iterator
it
(
parameters
.
baseParameter
().
begin
());
it
!=
parameters
.
baseParameter
().
end
();
it
++
)
{
if
(
const
icalendar_2_0
::
TzidParamType
*
tz
=
dynamic_cast
<
const
icalendar_2_0
::
TzidParamType
*>
(
&*
it
))
{
std
::
string
tzid
=
tz
->
text
();
if
(
tzid
.
find
(
TZ_PREFIX
)
!=
std
::
string
::
npos
)
{
tzid
.
erase
(
0
,
strlen
(
TZ_PREFIX
));
}
else
{
WARNING
(
"/kolab.org/ timezone prefix is missing"
);
}
return
tzid
;
}
}
return
std
::
string
();
}
cDateTimePtr
toDate
(
const
icalendar_2_0
::
DateDatetimePropertyType
&
dtProperty
)
{
cDateTimePtr
date
;
if
(
dtProperty
.
date_time
())
{
date
=
Shared
::
toDate
(
*
dtProperty
.
date_time
());
}
else
if
(
dtProperty
.
date
())
{
date
=
Shared
::
toDate
(
*
dtProperty
.
date
());
}
if
(
dtProperty
.
parameters
())
{
const
std
::
string
&
tzid
=
getTimezone
(
*
dtProperty
.
parameters
());
if
(
tzid
.
size
())
{
date
->
setTimezone
(
tzid
);
}
}
return
date
;
}
cDateTimePtr
toDate
(
const
icalendar_2_0
::
UtcDatetimePropertyType
&
dtProperty
)
{
cDateTimePtr
date
;
if
(
dtProperty
.
date_time
())
{
date
=
Shared
::
toDate
(
*
dtProperty
.
date_time
());
}
else
{
//The utc-date-time element shouldn't even exist
date
=
cDateTimePtr
(
new
cDateTime
());
ERROR
(
"This element shouldn't even be existing"
);
//TODO Implement anyways?
return
date
;
}
date
->
setUTC
(
true
);
return
date
;
}
template
<
typename
I
>
std
::
auto_ptr
<
I
>
fromDate
(
const
cDateTime
&
dt
)
{
std
::
auto_ptr
<
I
>
ptr
(
new
I
);
if
(
dt
.
isDateOnly
())
{
ptr
->
date
(
Shared
::
fromDate
(
dt
));
}
else
{
ptr
->
date_time
(
Shared
::
fromDateTime
(
dt
));
const
std
::
string
&
timezone
=
dt
.
timezone
();
if
(
timezone
.
size
()
!=
0
)
{
std
::
string
tz
(
TZ_PREFIX
);
tz
.
append
(
timezone
);
icalendar_2_0
::
TzidParamType
tzidParam
(
tz
);
icalendar_2_0
::
ArrayOfParameters
parameters
;
parameters
.
baseParameter
().
push_back
(
tzidParam
);
ptr
->
parameters
(
parameters
);
}
}
return
ptr
;
}
template
<
typename
I
>
std
::
vector
<
cDateTime
>
toDateTimeList
(
I
datelistProperty
)
{
std
::
vector
<
cDateTime
>
list
;
std
::
string
tzid
;
if
(
datelistProperty
.
parameters
())
{
tzid
=
getTimezone
(
*
datelistProperty
.
parameters
());
}
if
(
!
datelistProperty
.
date
().
empty
())
{
BOOST_FOREACH
(
const
xml_schema
::
date
&
d
,
datelistProperty
.
date
())
{
list
.
push_back
(
*
Shared
::
toDate
(
d
));
}
}
else
if
(
!
datelistProperty
.
date_time
().
empty
())
{
BOOST_FOREACH
(
const
xml_schema
::
date_time
&
d
,
datelistProperty
.
date_time
())
{
cDateTimePtr
date
=
Shared
::
toDate
(
d
);
if
(
tzid
.
size
())
{
date
->
setTimezone
(
tzid
);
}
list
.
push_back
(
*
date
);
}
}
return
list
;
}
template
<
typename
I
>
std
::
auto_ptr
<
I
>
fromDateTimeList
(
const
std
::
vector
<
cDateTime
>
&
dtlist
)
{
std
::
auto_ptr
<
I
>
ptr
(
new
I
);
BOOST_FOREACH
(
const
cDateTime
&
dt
,
dtlist
)
{
if
(
dt
.
isDateOnly
())
{
ptr
->
date
().
push_back
(
Shared
::
fromDate
(
dt
));
}
else
{
ptr
->
date_time
().
push_back
(
Shared
::
fromDateTime
(
dt
));
}
//TODO handle utc
//TODO check for equality of timezones?
}
if
(
!
dtlist
.
empty
()
&&
!
dtlist
.
at
(
0
).
timezone
().
empty
())
{
const
std
::
string
&
timezone
=
dtlist
.
at
(
0
).
timezone
();
if
(
timezone
.
size
()
!=
0
)
{
std
::
string
tz
(
TZ_PREFIX
);
tz
.
append
(
timezone
);
icalendar_2_0
::
TzidParamType
tzidParam
(
tz
);
icalendar_2_0
::
ArrayOfParameters
parameters
;
parameters
.
baseParameter
().
push_back
(
tzidParam
);
ptr
->
parameters
(
parameters
);
}
}
return
ptr
;
}
//---- cDateTime ----
//=== Attendee ===
std
::
string
mapPartStat
(
PartStatus
status
)
{
switch
(
status
)
{
case
PartAccepted
:
return
PARTACCEPTED
;
case
PartDeclined
:
return
PARTDECLINED
;
case
PartDelegated
:
return
PARTDELEGATED
;
case
PartNeedsAction
:
return
PARTNEEDSACTION
;
case
PartTentative
:
return
PARTTENTATIVE
;
}
ERROR
(
"PartStat not handled: "
+
status
);
return
std
::
string
();
}
PartStatus
mapPartStat
(
const
std
::
string
&
status
)
{
if
(
status
==
PARTACCEPTED
)
{
return
PartAccepted
;
}
else
if
(
status
==
PARTDECLINED
)
{
return
PartDeclined
;
}
else
if
(
status
==
PARTDELEGATED
)
{
return
PartDelegated
;
}
else
if
(
status
==
PARTNEEDSACTION
)
{
return
PartNeedsAction
;
}
else
if
(
status
==
PARTTENTATIVE
)
{
return
PartTentative
;
}
ERROR
(
"PartStat not handled: "
+
status
);
return
PartNeedsAction
;
}
std
::
string
mapRole
(
Role
status
)
{
switch
(
status
)
{
case
Chair
:
return
std
::
string
(
CHAIR
);
case
NonParticipant
:
return
NONPARTICIPANT
;
case
Optional
:
return
OPTIONAL
;
case
Required
:
return
REQUIRED
;
}
ERROR
(
"PartStat not handled: "
+
status
);
return
std
::
string
();
}
Role
mapRole
(
const
std
::
string
&
status
)
{
if
(
status
==
CHAIR
)
{
return
Chair
;
}
else
if
(
status
==
NONPARTICIPANT
)
{
return
NonParticipant
;
}
else
if
(
status
==
OPTIONAL
)
{
return
Optional
;
}
else
if
(
status
==
REQUIRED
)
{
return
Required
;
}
ERROR
(
"Unhandled Role "
+
status
);
return
Required
;
}
//----------------
//=== Recurrence Rule ===
typedef
std
::
auto_ptr
<
RecurrenceRule
>
RecurrencePtr
;
RecurrenceRule
::
Frequency
mapRecurrenceFrequency
(
const
icalendar_2_0
::
RecurType
::
freq_type
&
freq
)
{
using
namespace
icalendar_2_0
;
switch
(
freq
)
{
case
FreqRecurType
::
YEARLY
:
return
RecurrenceRule
::
Yearly
;
case
FreqRecurType
::
MONTHLY
:
return
RecurrenceRule
::
Monthly
;
case
FreqRecurType
::
WEEKLY
:
return
RecurrenceRule
::
Weekly
;
case
FreqRecurType
::
DAILY
:
return
RecurrenceRule
::
Daily
;
case
FreqRecurType
::
HOURLY
:
return
RecurrenceRule
::
Hourly
;
case
FreqRecurType
::
MINUTELY
:
return
RecurrenceRule
::
Minutely
;
case
FreqRecurType
::
SECONDLY
:
return
RecurrenceRule
::
Secondly
;
default
:
ERROR
(
"invalid unhandled recurrenc type"
+
freq
);
}
return
RecurrenceRule
::
FreqNone
;
}
icalendar_2_0
::
RecurType
::
freq_type
mapRecurrenceFrequency
(
RecurrenceRule
::
Frequency
freq
)
{
using
namespace
icalendar_2_0
;
switch
(
freq
)
{
case
RecurrenceRule
::
Yearly
:
return
FreqRecurType
::
YEARLY
;
case
RecurrenceRule
::
Monthly
:
return
FreqRecurType
::
MONTHLY
;
case
RecurrenceRule
::
Weekly
:
return
FreqRecurType
::
WEEKLY
;
case
RecurrenceRule
::
Daily
:
return
FreqRecurType
::
DAILY
;
case
RecurrenceRule
::
Hourly
:
return
FreqRecurType
::
HOURLY
;
case
RecurrenceRule
::
Minutely
:
return
FreqRecurType
::
MINUTELY
;
case
RecurrenceRule
::
Secondly
:
return
FreqRecurType
::
SECONDLY
;
default
:
ERROR
(
"invalid unhandled recurrenc type"
);
}
return
0
;
}
static
void
setWeekStart
(
RecurrencePtr
&
r
,
const
icalendar_2_0
::
RecurType
::
wkst_type
&
wkst
)
{
using
namespace
icalendar_2_0
;
switch
(
wkst
)
{
case
WeekdayRecurType
::
MO
:
r
->
setWeekStart
(
Kolab
::
Monday
);
break
;
case
WeekdayRecurType
::
TU
:
r
->
setWeekStart
(
Kolab
::
Tuesday
);
break
;
case
WeekdayRecurType
::
WE
:
r
->
setWeekStart
(
Kolab
::
Wednesday
);
break
;
case
WeekdayRecurType
::
TH
:
r
->
setWeekStart
(
Kolab
::
Thursday
);
break
;
case
WeekdayRecurType
::
FR
:
r
->
setWeekStart
(
Kolab
::
Friday
);
break
;
case
WeekdayRecurType
::
SA
:
r
->
setWeekStart
(
Kolab
::
Saturday
);
break
;
case
WeekdayRecurType
::
SU
:
r
->
setWeekStart
(
Kolab
::
Sunday
);
break
;
default
:
ERROR
(
"invalid unhandled weekday"
+
wkst
);
}
}
static
void
setByday
(
RecurrencePtr
&
r
,
const
icalendar_2_0
::
RecurType
::
byday_sequence
&
list
)
{
std
::
vector
<
DayPos
>
by
;
for
(
icalendar_2_0
::
RecurType
::
byday_const_iterator
it
(
list
.
begin
());
it
!=
list
.
end
();
it
++
)
{
by
.
push_back
(
toDayPos
(
*
it
));
}
r
->
setByday
(
by
);
}
template
<
typename
T
,
typename
I
>
std
::
vector
<
int
>
bylist
(
const
xsd
::
cxx
::
tree
::
sequence
<
T
>
&
list
)
{
std
::
vector
<
int
>
by
;
BOOST_FOREACH
(
const
T
i
,
list
)
{
by
.
push_back
(
convertToInt
<
I
>
(
i
));
}
return
by
;
}
RecurrencePtr
toRRule
(
const
icalendar_2_0
::
RecurType
&
rrule
)
{
using
namespace
icalendar_2_0
;
RecurrencePtr
r
(
new
RecurrenceRule
());
r
->
setFrequency
(
mapRecurrenceFrequency
(
rrule
.
freq
()));
if
(
rrule
.
until
())
{
cDateTimePtr
date
;
if
((
*
rrule
.
until
()).
date_time
())
{
date
=
Shared
::
toDate
(
*
(
*
rrule
.
until
()).
date_time
());
}
else
if
((
*
rrule
.
until
()).
date
())
{
date
=
Shared
::
toDate
(
*
(
*
rrule
.
until
()).
date
());
}
r
->
setEnd
(
*
date
);
}
else
if
(
rrule
.
count
())
{
r
->
setCount
(
toInt
(
*
rrule
.
count
()));
}
if
(
rrule
.
interval
())
{
r
->
setInterval
(
toInt
(
*
rrule
.
interval
()));
}
else
{
r
->
setInterval
(
1
);
}
r
->
setBysecond
(
bylist
<
RecurType
::
bysecond_type
,
xml_schema
::
non_negative_integer
>
(
rrule
.
bysecond
()));
r
->
setByminute
(
bylist
<
RecurType
::
byminute_type
,
xml_schema
::
non_negative_integer
>
(
rrule
.
byminute
()));
r
->
setByhour
(
bylist
<
RecurType
::
byhour_type
,
xml_schema
::
non_negative_integer
>
(
rrule
.
byhour
()));
setByday
(
r
,
rrule
.
byday
());
r
->
setBymonthday
(
bylist
<
RecurType
::
bymonthday_type
,
xml_schema
::
integer
>
(
rrule
.
bymonthday
()));
r
->
setByyearday
(
bylist
<
RecurType
::
byyearday_type
,
xml_schema
::
integer
>
(
rrule
.
byyearday
()));
r
->
setByweekno
(
bylist
<
RecurType
::
byweekno_type
,
xml_schema
::
integer
>
(
rrule
.
byweekno
()));
r
->
setBymonth
(
bylist
<
RecurType
::
bymonth_type
,
xml_schema
::
integer
>
(
rrule
.
bymonth
()));
if
(
rrule
.
wkst
())
{
setWeekStart
(
r
,
*
rrule
.
wkst
());
}
return
r
;
}
//--- Recurrence Rule ---
template
<
typename
I
,
typename
T
>
void
setIncidenceProperties
(
I
&
inc
,
const
T
&
prop
)
{
inc
.
setUid
(
toString
(
prop
.
uid
()));
inc
.
setCreated
(
*
toDate
(
prop
.
created
()));
inc
.
setLastModified
(
*
toDate
(
prop
.
dtstamp
()));
if
(
prop
.
sequence
())
{
inc
.
setSequence
(
toInt
(
*
prop
.
sequence
()));
}
if
(
prop
.
class_
())
{
std
::
string
string
(
toString
(
*
prop
.
class_
()));
Kolab
::
Classification
sec
=
ClassPublic
;
if
(
string
==
PRIVATE
)
{
sec
=
ClassPrivate
;
}
else
if
(
string
==
CONFIDENTIAL
)
{
sec
=
ClassConfidential
;
}
inc
.
setClassification
(
sec
);
}
if
(
prop
.
categories
())
{
inc
.
setCategories
(
toStringList
(
*
prop
.
categories
()));
}
if
(
prop
.
dtstart
())
{
const
cDateTimePtr
date
=
toDate
(
*
prop
.
dtstart
());
inc
.
setStart
(
*
date
);
}
if
(
prop
.
summary
())
{
inc
.
setSummary
(
toString
(
*
prop
.
summary
()));
}
if
(
prop
.
description
())
{
inc
.
setDescription
(
toString
(
*
prop
.
description
()));
}
if
(
prop
.
status
())
{
const
std
::
string
&
status
=
toString
(
*
prop
.
status
());
if
(
status
==
NEEDSACTION
)
{
inc
.
setStatus
(
StatusNeedsAction
);
}
else
if
(
status
==
COMPLETED
)
{
inc
.
setStatus
(
StatusCompleted
);
}
else
if
(
status
==
INPROCESS
)
{
inc
.
setStatus
(
StatusInProcess
);
}
else
if
(
status
==
CANCELLED
)
{
inc
.
setStatus
(
StatusCancelled
);
}
else
if
(
status
==
TENTATIVE
)
{
inc
.
setStatus
(
StatusTentative
);
}
else
if
(
status
==
CONFIRMED
)
{
inc
.
setStatus
(
StatusConfirmed
);
}
else
if
(
status
==
DRAFT
)
{
inc
.
setStatus
(
StatusDraft
);
}
else
if
(
status
==
FINAL
)
{
inc
.
setStatus
(
StatusFinal
);
}
else
{
ERROR
(
"Unhandled status"
);
}
}
if
(
prop
.
attendee
().
size
())
{
std
::
vector
<
Kolab
::
Attendee
>
attendees
;
BOOST_FOREACH
(
typename
T
::
attendee_type
aProp
,
prop
.
attendee
())
{
Kolab
::
Attendee
a
(
fromMailto
(
toString
(
aProp
.
cal_address
())));
if
(
aProp
.
parameters
())
{
const
icalendar_2_0
::
AttendeePropType
::
parameters_type
&
parameters
=
*
aProp
.
parameters
();
for
(
icalendar_2_0
::
AttendeePropType
::
parameters_type
::
baseParameter_const_iterator
it
(
parameters
.
baseParameter
().
begin
());
it
!=
parameters
.
baseParameter
().
end
();
it
++
)
{
if
(
const
icalendar_2_0
::
CnParamType
*
p
=
dynamic_cast
<
const
icalendar_2_0
::
CnParamType
*>
(
&*
it
))
{
a
.
setName
(
p
->
text
());
}
if
(
const
icalendar_2_0
::
PartstatParamType
*
p
=
dynamic_cast
<
const
icalendar_2_0
::
PartstatParamType
*>
(
&*
it
))
{
PartStatus
s
=
mapPartStat
(
p
->
text
());
if
(
s
!=
PartNeedsAction
)
{
a
.
setPartStat
(
s
);
}
}
if
(
const
icalendar_2_0
::
RoleParamType
*
p
=
dynamic_cast
<
const
icalendar_2_0
::
RoleParamType
*>
(
&*
it
))
{
Role
s
=
mapRole
(
p
->
text
());
if
(
s
!=
Required
)
{
a
.
setRole
(
s
);
}
}
if
(
const
icalendar_2_0
::
RsvpParamType
*
p
=
dynamic_cast
<
const
icalendar_2_0
::
RsvpParamType
*>
(
&*
it
))
{
a
.
setRSVP
(
p
->
boolean
());
}
if
(
const
icalendar_2_0
::
XuidParamType
*
p
=
dynamic_cast
<
const
icalendar_2_0
::
XuidParamType
*>
(
&*
it
))
{
a
.
setUid
(
p
->
text
());
}
}
}
attendees
.
push_back
(
a
);
}
inc
.
setAttendees
(
attendees
);
}
if
(
prop
.
attach
().
size
())
{
std
::
vector
<
Kolab
::
Attachment
>
attachments
;
BOOST_FOREACH
(
typename
T
::
attach_type
aProp
,
prop
.
attach
())
{
const
Kolab
::
Attachment
&
a
=
toAttachment
<
typename
T
::
attach_type
>
(
aProp
);
if
(
!
a
.
isValid
())
{
ERROR
(
"invalid attachment"
);
continue
;
}
attachments
.
push_back
(
a
);
}
inc
.
setAttachments
(
attachments
);
}
if
(
prop
.
x_custom
().
size
())
{
std
::
vector
<
Kolab
::
CustomProperty
>
customProperties
;
BOOST_FOREACH
(
typename
T
::
x_custom_type
p
,
prop
.
x_custom
())
{
customProperties
.
push_back
(
CustomProperty
(
p
.
identifier
(),
p
.
value
()));
}
inc
.
setCustomProperties
(
customProperties
);
}
}
template
<
typename
I
,
typename
T
>
void
setTodoEventProperties
(
I
&
inc
,
const
T
&
prop
)
{
if
(
prop
.
rrule
())
{
RecurrencePtr
rrule
=
toRRule
(
prop
.
rrule
()
->
recur
());
inc
.
setRecurrenceRule
(
*
rrule
);
}
if
(
prop
.
rdate
())
{
inc
.
setRecurrenceDates
(
toDateTimeList
<
icalendar_2_0
::
KolabEvent
::
properties_type
::
rdate_type
>
(
*
prop
.
rdate
()));
if
(
!
prop
.
rdate
()
->
period
().
empty
())
{
ERROR
(
"the period element must not be used, ignored."
);
}
}
if
(
prop
.
exdate
())
{
inc
.
setExceptionDates
(
toDateTimeList
<
icalendar_2_0
::
KolabEvent
::
properties_type
::
exdate_type
>
(
*
prop
.
exdate
()));
}
if
(
prop
.
recurrence_id
())
{
bool
thisandfuture
=
false
;
if
(
prop
.
recurrence_id
()
->
parameters
())
{
const
icalendar_2_0
::
RecurrenceIdPropType
::
parameters_type
&
parameters
=
*
prop
.
recurrence_id
()
->
parameters
();
for
(
icalendar_2_0
::
RecurrenceIdPropType
::
parameters_type
::
baseParameter_const_iterator
it
(
parameters
.
baseParameter
().
begin
());
it
!=
parameters
.
baseParameter
().
end
();
it
++
)
{
if
(
dynamic_cast
<
const
icalendar_2_0
::
RangeParamType
*>
(
&*
it
))
{
thisandfuture
=
true
;
}
}
}
inc
.
setRecurrenceID
(
*
toDate
(
*
prop
.
recurrence_id
()),
thisandfuture
);
}
if
(
prop
.
priority
())
{
inc
.
setPriority
(
toInt
(
*
prop
.
priority
()));
}
if
(
prop
.
location
())
{
inc
.
setLocation
(
toString
(
*
prop
.
location
()));
}
if
(
prop
.
organizer
())
{
std
::
string
email
;
std
::
string
name
;
setCalAddress
(
*
prop
.
organizer
(),
email
,
name
);
inc
.
setOrganizer
(
email
,
name
);
}
}
template
<
typename
T
,
typename
I
>
T
fromList
(
const
std
::
vector
<
int
>
&
input
)
{
T
list
;
BOOST_FOREACH
(
int
i
,
input
)
{
list
.
push_back
(
convertToInt
<
I
>
(
i
));
}
return
list
;
}
std
::
auto_ptr
<
icalendar_2_0
::
RrulePropType
>
recurrenceProperty
(
const
RecurrenceRule
&
r
)
{
using
namespace
icalendar_2_0
;
std
::
auto_ptr
<
RrulePropType
>
rruleProp
(
new
RrulePropType
(
mapRecurrenceFrequency
(
r
.
frequency
())));
RecurPropertyType
::
recur_type
&
recur
=
rruleProp
->
recur
();
const
cDateTime
&
endDate
=
r
.
end
();
if
(
endDate
.
isValid
())
{
RecurPropertyType
::
recur_type
::
until_type
until
;
if
(
endDate
.
isDateOnly
())
{
until
.
date
(
Shared
::
fromDate
(
endDate
));
}
else
{
until
.
date_time
(
Shared
::
fromDateTime
(
endDate
));
}
recur
.
until
(
until
);
}
else
if
(
r
.
count
()
>
0
)
{
recur
.
count
(
fromInt
<
RecurType
::
count_type
>
(
r
.
count
()));
}
if
(
r
.
interval
()
>
1
)
{
recur
.
interval
(
fromInt
<
RecurType
::
interval_type
>
(
r
.
interval
()));
}
if
(
!
r
.
bysecond
().
empty
())
{
recur
.
bysecond
(
fromList
<
RecurType
::
bysecond_sequence
,
xml_schema
::
non_negative_integer
>
(
r
.
bysecond
()));
}
if
(
!
r
.
byminute
().
empty
())
{
recur
.
byminute
(
fromList
<
RecurType
::
byminute_sequence
,
xml_schema
::
non_negative_integer
>
(
r
.
byminute
()));
}
if
(
!
r
.
byhour
().
empty
())
{
recur
.
byhour
(
fromList
<
RecurType
::
byhour_sequence
,
xml_schema
::
non_negative_integer
>
(
r
.
byhour
()));
}
if
(
!
r
.
byday
().
empty
())
{
RecurType
::
byday_sequence
byday
;
BOOST_FOREACH
(
const
Kolab
::
DayPos
&
daypos
,
r
.
byday
())
{
byday
.
push_back
(
fromDayPos
(
daypos
));
}
recur
.
byday
(
byday
);
}
if
(
!
r
.
bymonthday
().
empty
())
{
recur
.
bymonthday
(
fromList
<
RecurType
::
bymonthday_sequence
,
xml_schema
::
integer
>
(
r
.
bymonthday
()));
}
if
(
!
r
.
byyearday
().
empty
())
{
recur
.
byyearday
(
fromList
<
RecurType
::
byyearday_sequence
,
xml_schema
::
integer
>
(
r
.
byyearday
()));
}
if
(
!
r
.
byweekno
().
empty
())
{
recur
.
byweekno
(
fromList
<
RecurType
::
byweekno_sequence
,
xml_schema
::
integer
>
(
r
.
byweekno
()));
}
if
(
!
r
.
bymonth
().
empty
())
{
recur
.
bymonth
(
fromList
<
RecurType
::
bymonth_sequence
,
xml_schema
::
integer
>
(
r
.
bymonth
()));
}
return
rruleProp
;
}
template
<
typename
T
,
typename
I
>
void
getIncidenceProperties
(
T
&
prop
,
const
I
&
inc
)
{
using
namespace
icalendar_2_0
;
typedef
T
properties
;
prop
.
sequence
(
fromInt
<
xml_schema
::
integer
>
(
inc
.
sequence
()));
switch
(
inc
.
classification
())
{
case
Kolab
::
ClassConfidential
:
prop
.
class_
(
typename
properties
::
class_type
(
CONFIDENTIAL
));
break
;
case
Kolab
::
ClassPrivate
:
prop
.
class_
(
typename
properties
::
class_type
(
PRIVATE
));
break
;
default
:
prop
.
class_
(
typename
properties
::
class_type
(
PUBLIC
));
break
;
}
if
(
!
inc
.
categories
().
empty
())
{
prop
.
categories
(
*
fromStringList
<
typename
properties
::
categories_type
>
(
inc
.
categories
()));
}
if
(
inc
.
start
().
isValid
())
{
prop
.
dtstart
(
fromDate
<
typename
properties
::
dtstart_type
>
(
inc
.
start
()));
}
if
(
!
inc
.
summary
().
empty
())
{
prop
.
summary
(
typename
properties
::
summary_type
(
inc
.
summary
()));
}
if
(
!
inc
.
description
().
empty
())
{
prop
.
description
(
typename
properties
::
description_type
(
inc
.
description
()));
}
if
(
inc
.
status
()
!=
StatusUndefined
)
{
switch
(
inc
.
status
())
{
case
StatusNeedsAction
:
prop
.
status
(
typename
properties
::
status_type
(
NEEDSACTION
));
break
;
case
StatusCompleted
:
prop
.
status
(
typename
properties
::
status_type
(
COMPLETED
));
break
;
case
StatusInProcess
:
prop
.
status
(
typename
properties
::
status_type
(
INPROCESS
));
break
;
case
StatusCancelled
:
prop
.
status
(
typename
properties
::
status_type
(
CANCELLED
));
break
;
case
StatusTentative
:
prop
.
status
(
typename
properties
::
status_type
(
TENTATIVE
));
break
;
case
StatusConfirmed
:
prop
.
status
(
typename
properties
::
status_type
(
CONFIRMED
));
break
;
case
StatusDraft
:
prop
.
status
(
typename
properties
::
status_type
(
DRAFT
));
break
;
case
StatusFinal
:
prop
.
status
(
typename
properties
::
status_type
(
FINAL
));
break
;
default
:
ERROR
(
"unhandled status "
+
inc
.
status
());
}
}
if
(
!
inc
.
attendees
().
empty
())
{
BOOST_FOREACH
(
const
Kolab
::
Attendee
&
a
,
inc
.
attendees
())
{
typename
properties
::
attendee_type
attendee
(
toMailto
(
a
.
email
()));
typename
properties
::
attendee_type
::
parameters_type
p
;
if
(
!
a
.
name
().
empty
())
{
icalendar_2_0
::
CnParamType
name
(
a
.
name
());
p
.
baseParameter
().
push_back
(
name
);
}
std
::
string
stat
=
mapPartStat
(
a
.
partStat
());
if
(
!
stat
.
empty
())
{
p
.
baseParameter
().
push_back
(
icalendar_2_0
::
PartstatParamType
(
stat
));
}
std
::
string
r
=
mapRole
(
a
.
role
());
if
(
!
r
.
empty
())
{
p
.
baseParameter
().
push_back
(
icalendar_2_0
::
RoleParamType
(
r
));
}
if
(
a
.
rsvp
())
{
p
.
baseParameter
().
push_back
(
icalendar_2_0
::
RsvpParamType
(
true
));
}
if
(
!
a
.
uid
().
empty
())
{
p
.
baseParameter
().
push_back
(
icalendar_2_0
::
XuidParamType
(
a
.
uid
()));
}
attendee
.
parameters
(
p
);
prop
.
attendee
().
push_back
(
attendee
);
}
}
if
(
!
inc
.
attachments
().
empty
())
{
BOOST_FOREACH
(
const
Kolab
::
Attachment
&
a
,
inc
.
attachments
())
{
prop
.
attach
().
push_back
(
fromAttachment
(
a
));
}
}
if
(
!
inc
.
customProperties
().
empty
())
{
BOOST_FOREACH
(
const
Kolab
::
CustomProperty
&
a
,
inc
.
customProperties
())
{
prop
.
x_custom
().
push_back
(
typename
properties
::
x_custom_type
(
a
.
identifier
,
a
.
value
));
}
}
}
template
<
typename
T
,
typename
I
>
void
getTodoEventProperties
(
T
&
prop
,
const
I
&
inc
)
{
using
namespace
icalendar_2_0
;
typedef
T
properties
;
if
(
inc
.
recurrenceRule
().
isValid
())
{
const
RecurrenceRule
&
r
=
inc
.
recurrenceRule
();
prop
.
rrule
(
recurrenceProperty
(
r
));
//TODO check if startdate is allDay if recurrence is allDay
//TODO check if startdate matches the one of the event (it MUST)
}
if
(
!
inc
.
recurrenceDates
().
empty
())
{
prop
.
rdate
(
fromDateTimeList
<
typename
properties
::
rdate_type
>
(
inc
.
recurrenceDates
()));
}
if
(
!
inc
.
exceptionDates
().
empty
())
{
prop
.
exdate
(
fromDateTimeList
<
typename
properties
::
exdate_type
>
(
inc
.
exceptionDates
()));
}
if
(
inc
.
recurrenceID
().
isValid
())
{
std
::
auto_ptr
<
typename
properties
::
recurrence_id_type
>
recurrenceId
=
fromDate
<
typename
properties
::
recurrence_id_type
>
(
inc
.
recurrenceID
());
if
(
inc
.
thisAndFuture
())
{
if
(
!
recurrenceId
->
parameters
())
{
recurrenceId
->
parameters
(
typename
properties
::
recurrence_id_type
::
parameters_type
());
}
typename
properties
::
recurrence_id_type
::
parameters_type
&
parameters
=
*
recurrenceId
->
parameters
();
//There is maybe already a timezone set
icalendar_2_0
::
RangeParamType
range
(
THISANDFUTURE
);
parameters
.
baseParameter
().
push_back
(
range
);
}
prop
.
recurrence_id
(
recurrenceId
);
}
if
(
inc
.
priority
()
!=
0
)
{
prop
.
priority
(
typename
properties
::
priority_type
(
fromInt
<
typename
properties
::
priority_type
::
integer_type
>
(
inc
.
priority
())));
}
if
(
!
inc
.
location
().
empty
())
{
prop
.
location
(
typename
properties
::
location_type
(
inc
.
location
()));
}
if
(
!
inc
.
organizerEmail
().
empty
())
{
//email is required
typename
properties
::
organizer_type
organizer
(
toMailto
(
inc
.
organizerEmail
()));
typename
properties
::
organizer_type
::
parameters_type
p
;
//There is maybe already a timezone set
icalendar_2_0
::
CnParamType
name
(
inc
.
organizerName
());
p
.
baseParameter
().
push_back
(
name
);
organizer
.
parameters
(
p
);
prop
.
organizer
(
organizer
);
}
}
//=== Alarms ===
template
<
typename
KolabType
,
typename
IncidenceType
>
void
setAlarms
(
typename
KolabType
::
components_type
&
components
,
const
IncidenceType
&
incidence
)
{
BOOST_FOREACH
(
const
Kolab
::
Alarm
&
alarm
,
incidence
.
alarms
())
{
typedef
icalendar_2_0
::
ValarmType
::
properties_type
PropType
;
PropType
::
trigger_type
trigger
;
if
(
alarm
.
start
().
isValid
())
{
trigger
.
date_time
(
fromDateTime
(
alarm
.
start
()));
}
else
{
if
(
!
alarm
.
relativeStart
().
isValid
())
{
ERROR
(
"no start and no relativeStart"
);
continue
;
}
trigger
.
duration
(
PropType
::
trigger_type
::
duration_type
(
fromDuration
(
alarm
.
relativeStart
())));
icalendar_2_0
::
ArrayOfParameters
parameters
;
if
(
alarm
.
relativeTo
()
==
Kolab
::
End
)
{
parameters
.
baseParameter
().
push_back
(
icalendar_2_0
::
RelatedParamType
(
END
));
}
else
{
parameters
.
baseParameter
().
push_back
(
icalendar_2_0
::
RelatedParamType
(
START
));
}
trigger
.
parameters
(
parameters
);
}
std
::
auto_ptr
<
PropType
>
p
;
switch
(
alarm
.
type
())
{
case
Kolab
::
Alarm
::
DisplayAlarm
:
p
=
std
::
auto_ptr
<
PropType
>
(
new
PropType
(
PropType
::
action_type
(
DISPLAYALARM
),
trigger
));
p
->
description
(
PropType
::
description_type
(
alarm
.
description
()));
break
;
case
Kolab
::
Alarm
::
EMailAlarm
:
p
=
std
::
auto_ptr
<
PropType
>
(
new
PropType
(
PropType
::
action_type
(
EMAILALARM
),
trigger
));
p
->
summary
(
PropType
::
summary_type
(
alarm
.
summary
()));
p
->
description
(
PropType
::
description_type
(
alarm
.
description
()));
BOOST_FOREACH
(
const
std
::
string
&
attendee
,
alarm
.
attendees
())
{
p
->
attendee
().
push_back
(
icalendar_2_0
::
ContactType
(
toMailto
(
attendee
)));
}
break
;
case
Kolab
::
Alarm
::
AudioAlarm
:
p
=
std
::
auto_ptr
<
PropType
>
(
new
PropType
(
PropType
::
action_type
(
AUDIOALARM
),
trigger
));
p
->
description
(
PropType
::
description_type
(
alarm
.
description
()));
p
->
attach
(
fromAttachment
(
alarm
.
audioFile
()));
break
;
default
:
ERROR
(
"invalid alarm"
);
continue
;
}
if
(
alarm
.
duration
().
isValid
())
{
p
->
duration
(
PropType
::
duration_type
(
fromDuration
(
alarm
.
duration
())));
p
->
repeat
(
PropType
::
repeat_type
(
fromInt
<
PropType
::
repeat_type
::
integer_type
>
(
alarm
.
numrepeat
())));
}
components
.
valarm
().
push_back
(
icalendar_2_0
::
ValarmType
(
p
));
}
}
template
<
typename
IncidenceType
,
typename
KolabType
>
void
getAlarms
(
IncidenceType
&
incidence
,
const
typename
KolabType
::
components_type
&
components
)
{
typedef
icalendar_2_0
::
ValarmType
::
properties_type
PropType
;
std
::
vector
<
Kolab
::
Alarm
>
alarms
;
BOOST_FOREACH
(
const
typename
KolabType
::
components_type
::
valarm_type
&
valarm
,
components
.
valarm
())
{
const
icalendar_2_0
::
ValarmType
::
properties_type
&
prop
=
valarm
.
properties
();
Kolab
::
Alarm
alarm
;
if
(
prop
.
action
().
text
()
==
DISPLAYALARM
)
{
if
(
!
prop
.
description
())
{
ERROR
(
"description is missing"
);
continue
;
}
alarm
=
Kolab
::
Alarm
((
*
prop
.
description
()).
text
());
}
else
if
(
prop
.
action
().
text
()
==
EMAILALARM
)
{
std
::
vector
<
std
::
string
>
attendees
;
for
(
typename
PropType
::
attendee_const_iterator
at
(
prop
.
attendee
().
begin
());
at
!=
prop
.
attendee
().
end
();
at
++
)
{
attendees
.
push_back
(
fromMailto
((
*
at
).
cal_address
()));
}
if
(
!
prop
.
description
()
||
!
prop
.
summary
())
{
ERROR
(
"description or summary is missing"
);
continue
;
}
alarm
=
Kolab
::
Alarm
((
*
prop
.
summary
()).
text
(),
(
*
prop
.
description
()).
text
(),
attendees
);
}
else
if
(
prop
.
action
().
text
()
==
AUDIOALARM
)
{
if
(
!
prop
.
attach
())
{
ERROR
(
"audio file is missing"
);
continue
;
}
const
Kolab
::
Attachment
&
attach
=
toAttachment
<
icalendar_2_0
::
properties
::
attach_type
>
(
*
prop
.
attach
());
if
(
!
attach
.
isValid
())
{
ERROR
(
"audio file is invalid"
);
continue
;
}
alarm
=
Kolab
::
Alarm
(
attach
);
}
else
{
ERROR
(
"unknown alarm type "
+
prop
.
action
().
text
());
continue
;
}
if
(
prop
.
trigger
().
date_time
())
{
alarm
.
setStart
(
*
Shared
::
toDate
(
*
prop
.
trigger
().
date_time
()));
if
(
!
alarm
.
start
().
isUTC
())
{
ERROR
(
"The start date time must be in UTC "
);
continue
;
}
}
else
if
(
prop
.
trigger
().
duration
())
{
Kolab
::
Relative
relativeTo
=
Kolab
::
Start
;
if
(
prop
.
trigger
().
parameters
())
{
BOOST_FOREACH
(
const
icalendar_2_0
::
ArrayOfParameters
::
baseParameter_type
&
param
,
(
*
prop
.
trigger
().
parameters
()).
baseParameter
())
{
if
(
const
icalendar_2_0
::
RelatedParamType
*
rel
=
dynamic_cast
<
const
icalendar_2_0
::
RelatedParamType
*>
(
&
param
))
{
if
(
rel
->
text
()
==
START
)
{
relativeTo
=
Kolab
::
Start
;
}
else
if
(
rel
->
text
()
==
END
)
{
relativeTo
=
Kolab
::
End
;
}
else
{
LOG
(
"relativeTo not specified, default to start "
);
}
}
}
}
alarm
.
setRelativeStart
(
toDuration
(
*
prop
.
trigger
().
duration
()),
relativeTo
);
}
else
{
ERROR
(
"no duration and not starttime "
);
continue
;
}
if
(
prop
.
duration
())
{
int
repeat
=
0
;
if
(
prop
.
repeat
())
{
repeat
=
toInt
(
*
prop
.
repeat
());
}
alarm
.
setDuration
(
toDuration
((
*
prop
.
duration
()).
duration
()),
repeat
);
//TODO check duration?
}
alarms
.
push_back
(
alarm
);
}
incidence
.
setAlarms
(
alarms
);
}
//--- Alarms ---
class
Incidence
;
//Just for Trait
///Trait for Incidence object
template
<
typename
T
,
typename
I
>
struct
IncidenceConverter
;
template
<
typename
T
>
struct
IncidenceConverter
<
Incidence
,
T
>
{
static
std
::
string
uid
(
const
T
&
inc
)
{
if
(
inc
.
uid
().
empty
())
{
//generate new UID
return
getUID
();
}
return
inc
.
uid
();
}
static
xml_schema
::
date_time
dtstamp
()
{
return
fromDateTime
(
getCurrentTime
());
}
static
xml_schema
::
date_time
created
(
const
T
&
inc
)
{
if
(
inc
.
created
().
isValid
())
{
return
fromDateTime
(
inc
.
created
());
}
return
fromDateTime
(
getCurrentTime
());
}
};
///Trait for incidence properties specialized for Event/Todo/Journal
template
<
typename
T
>
struct
IncidenceTrait
;
template
<
>
struct
IncidenceTrait
<
Kolab
::
Event
>
{
typedef
icalendar_2_0
::
KolabEvent
KolabType
;
typedef
Kolab
::
Event
IncidenceType
;
typedef
boost
::
shared_ptr
<
Kolab
::
Event
>
IncidencePtr
;
static
void
writeIncidence
(
icalendar_2_0
::
KolabEvent
&
vevent
,
const
Kolab
::
Event
&
event
)
{
KolabType
::
components_type
eventComponents
;
setAlarms
<
icalendar_2_0
::
KolabEvent
,
IncidenceType
>
(
eventComponents
,
event
);
if
(
!
eventComponents
.
valarm
().
empty
())
{
vevent
.
components
(
eventComponents
);
}
icalendar_2_0
::
KolabEvent
::
properties_type
&
prop
=
vevent
.
properties
();
getIncidenceProperties
<
icalendar_2_0
::
KolabEvent
::
properties_type
>
(
prop
,
event
);
getTodoEventProperties
<
icalendar_2_0
::
KolabEvent
::
properties_type
>
(
prop
,
event
);
if
(
!
event
.
start
().
isValid
())
{
ERROR
(
"Start date is missing, but is mandatory for events"
);
}
if
(
event
.
end
().
isValid
())
{
prop
.
dtend
(
fromDate
<
icalendar_2_0
::
KolabEvent
::
properties_type
::
dtend_type
>
(
event
.
end
()));
}
else
if
(
event
.
duration
().
isValid
())
{
prop
.
duration
(
icalendar_2_0
::
KolabEvent
::
properties_type
::
duration_type
(
fromDuration
(
event
.
duration
())));
}
if
(
event
.
transparency
())
{
prop
.
transp
(
icalendar_2_0
::
KolabEvent
::
properties_type
::
transp_type
(
TRANSPARENT
));
}
}
static
void
addIncidence
(
icalendar_2_0
::
VcalendarType
::
components_type
&
components
,
icalendar_2_0
::
KolabEvent
inc
)
//TODO to base trait
{
components
.
vevent
().
push_back
(
inc
);
}
static
void
readIncidence
(
Kolab
::
Event
&
event
,
const
icalendar_2_0
::
KolabEvent
&
vevent
)
{
const
icalendar_2_0
::
KolabEvent
::
properties_type
&
prop
=
vevent
.
properties
();
if
(
!
prop
.
dtstart
())
{
ERROR
(
"Start date is missing, but is mandatory for events"
);
}
setIncidenceProperties
<
Kolab
::
Event
,
icalendar_2_0
::
KolabEvent
::
properties_type
>
(
event
,
prop
);
setTodoEventProperties
<
Kolab
::
Event
,
icalendar_2_0
::
KolabEvent
::
properties_type
>
(
event
,
prop
);
if
(
prop
.
dtend
())
{
event
.
setEnd
(
*
toDate
(
*
prop
.
dtend
()));
if
(
event
.
end
().
isUTC
()
!=
event
.
end
().
isUTC
()
&&
event
.
end
().
timezone
()
!=
event
.
end
().
timezone
()
&&
event
.
end
().
isDateOnly
()
!=
event
.
end
().
isDateOnly
())
{
ERROR
(
"dtEnd has wrong timespec"
);
}
}
else
if
(
prop
.
duration
())
{
event
.
setDuration
(
toDuration
((
*
prop
.
duration
()).
duration
()));
}
if
(
prop
.
transp
())
{
if
(
toString
(
*
prop
.
transp
())
==
TRANSPARENT
)
{
event
.
setTransparency
(
true
);
}
else
{
event
.
setTransparency
(
false
);
if
(
toString
(
*
prop
.
transp
())
!=
OPAQUE
)
{
ERROR
(
"wrong transparency value "
+
toString
(
*
prop
.
transp
()));
}
}
}
if
(
vevent
.
components
())
{
getAlarms
<
Kolab
::
Event
,
icalendar_2_0
::
KolabEvent
>
(
event
,
*
vevent
.
components
());
}
}
static
icalendar_2_0
::
VcalendarType
::
components_type
::
vevent_const_iterator
begin
(
const
icalendar_2_0
::
VcalendarType
::
components_type
&
components
)
{
return
components
.
vevent
().
begin
();
}
static
icalendar_2_0
::
VcalendarType
::
components_type
::
vevent_const_iterator
end
(
const
icalendar_2_0
::
VcalendarType
::
components_type
&
components
)
{
return
components
.
vevent
().
end
();
}
};
template
<
>
struct
IncidenceTrait
<
Kolab
::
Todo
>
{
typedef
icalendar_2_0
::
KolabTodo
KolabType
;
typedef
Kolab
::
Todo
IncidenceType
;
typedef
boost
::
shared_ptr
<
Kolab
::
Todo
>
IncidencePtr
;
static
void
writeIncidence
(
icalendar_2_0
::
KolabTodo
&
vevent
,
const
Kolab
::
Todo
&
todo
)
{
KolabType
::
components_type
eventComponents
;
setAlarms
<
icalendar_2_0
::
KolabTodo
,
IncidenceType
>
(
eventComponents
,
todo
);
if
(
!
eventComponents
.
valarm
().
empty
())
{
vevent
.
components
(
eventComponents
);
}
icalendar_2_0
::
KolabTodo
::
properties_type
&
prop
=
vevent
.
properties
();
getIncidenceProperties
<
icalendar_2_0
::
KolabTodo
::
properties_type
>
(
prop
,
todo
);
getTodoEventProperties
<
icalendar_2_0
::
KolabTodo
::
properties_type
>
(
prop
,
todo
);
if
(
!
todo
.
relatedTo
().
empty
())
{
icalendar_2_0
::
KolabTodo
::
properties_type
::
related_to_sequence
list
;
BOOST_FOREACH
(
std
::
string
relatedTo
,
todo
.
relatedTo
())
{
list
.
push_back
(
icalendar_2_0
::
KolabTodo
::
properties_type
::
related_to_type
(
relatedTo
));
}
prop
.
related_to
(
list
);
}
if
(
todo
.
due
().
isValid
())
{
prop
.
due
(
fromDate
<
icalendar_2_0
::
KolabTodo
::
properties_type
::
due_type
>
(
todo
.
due
()));
}
if
(
todo
.
percentComplete
()
>
0
)
{
prop
.
percent_complete
(
icalendar_2_0
::
KolabTodo
::
properties_type
::
percent_complete_type
(
fromInt
<
icalendar_2_0
::
IntegerPropertyType
::
integer_type
>
(
todo
.
percentComplete
())));
}
}
static
void
addIncidence
(
icalendar_2_0
::
VcalendarType
::
components_type
&
components
,
icalendar_2_0
::
KolabTodo
inc
)
//TODO to base trait
{
components
.
vtodo
().
push_back
(
inc
);
}
static
void
readIncidence
(
Kolab
::
Todo
&
todo
,
const
icalendar_2_0
::
KolabTodo
&
vevent
)
{
const
icalendar_2_0
::
KolabTodo
::
properties_type
&
prop
=
vevent
.
properties
();
setIncidenceProperties
<
Kolab
::
Todo
,
icalendar_2_0
::
KolabTodo
::
properties_type
>
(
todo
,
prop
);
setTodoEventProperties
<
Kolab
::
Todo
,
icalendar_2_0
::
KolabTodo
::
properties_type
>
(
todo
,
prop
);
if
(
!
prop
.
related_to
().
empty
())
{
BOOST_FOREACH
(
icalendar_2_0
::
KolabTodo
::
properties_type
::
related_to_type
p
,
prop
.
related_to
())
{
todo
.
addRelatedTo
(
p
.
text
());
}
}
if
(
prop
.
due
())
{
todo
.
setDue
(
*
toDate
(
*
prop
.
due
()));
}
if
(
prop
.
percent_complete
())
{
todo
.
setPercentComplete
(
toInt
(
*
prop
.
percent_complete
()));
}
if
(
vevent
.
components
())
{
getAlarms
<
Kolab
::
Todo
,
icalendar_2_0
::
KolabTodo
>
(
todo
,
*
vevent
.
components
());
}
}
static
icalendar_2_0
::
VcalendarType
::
components_type
::
vevent_const_iterator
begin
(
const
icalendar_2_0
::
VcalendarType
::
components_type
&
components
)
{
return
components
.
vtodo
().
begin
();
}
static
icalendar_2_0
::
VcalendarType
::
components_type
::
vevent_const_iterator
end
(
const
icalendar_2_0
::
VcalendarType
::
components_type
&
components
)
{
return
components
.
vtodo
().
end
();
}
};
template
<
>
struct
IncidenceTrait
<
Kolab
::
Journal
>
{
typedef
icalendar_2_0
::
KolabJournal
KolabType
;
typedef
Kolab
::
Journal
IncidenceType
;
typedef
boost
::
shared_ptr
<
Kolab
::
Journal
>
IncidencePtr
;
static
void
writeIncidence
(
icalendar_2_0
::
KolabJournal
&
vjournal
,
const
Kolab
::
Journal
&
journal
)
{
icalendar_2_0
::
KolabJournal
::
properties_type
&
prop
=
vjournal
.
properties
();
getIncidenceProperties
<
icalendar_2_0
::
KolabJournal
::
properties_type
>
(
prop
,
journal
);
}
static
void
addIncidence
(
icalendar_2_0
::
VcalendarType
::
components_type
&
components
,
icalendar_2_0
::
KolabJournal
inc
)
{
components
.
vjournal
().
push_back
(
inc
);
}
static
void
readIncidence
(
Kolab
::
Journal
&
journal
,
const
icalendar_2_0
::
KolabJournal
&
vjournal
)
{
const
icalendar_2_0
::
KolabJournal
::
properties_type
&
prop
=
vjournal
.
properties
();
setIncidenceProperties
<
Kolab
::
Journal
,
icalendar_2_0
::
KolabJournal
::
properties_type
>
(
journal
,
prop
);
}
static
icalendar_2_0
::
VcalendarType
::
components_type
::
vjournal_const_iterator
begin
(
const
icalendar_2_0
::
VcalendarType
::
components_type
&
components
)
{
return
components
.
vjournal
().
begin
();
}
static
icalendar_2_0
::
VcalendarType
::
components_type
::
vjournal_const_iterator
end
(
const
icalendar_2_0
::
VcalendarType
::
components_type
&
components
)
{
return
components
.
vjournal
().
end
();
}
};
//////////////////////////////////=========================================
template
<
typename
T
>
std
::
string
serializeIncidence
(
const
typename
T
::
IncidenceType
&
incidence
,
const
std
::
string
productid
=
std
::
string
())
{
using
namespace
icalendar_2_0
;
typedef
IncidenceConverter
<
Incidence
,
typename
T
::
IncidenceType
>
IC
;
typedef
typename
T
::
KolabType
KolabType
;
clearErrors
();
try
{
typename
KolabType
::
properties_type
::
uid_type
uid
(
IC
::
uid
(
incidence
));
setCreatedUid
(
uid
.
text
());
typename
KolabType
::
properties_type
::
dtstamp_type
dtstamp
;
dtstamp
.
date_time
(
IC
::
dtstamp
());
typename
KolabType
::
properties_type
::
created_type
created
;
created
.
date_time
(
IC
::
created
(
incidence
));
typename
KolabType
::
properties_type
eventProps
(
uid
,
created
,
dtstamp
);
KolabType
inc
(
eventProps
);
T
::
writeIncidence
(
inc
,
incidence
);
VcalendarType
::
components_type
components
;
T
::
addIncidence
(
components
,
inc
);
VcalendarType
::
properties_type
::
prodid_type
prodid
(
productid
+
KOLAB_LIBNAME
+
KOLAB_LIB_VERSION
);
//FIXME own version field for lib version
VcalendarType
::
properties_type
::
version_type
version
(
XCAL_VERSION
);
VcalendarType
::
properties_type
::
x_kolab_version_type
x_kolab_version
(
KOLAB_FORMAT_VERSION
);
VcalendarType
::
properties_type
properties
(
prodid
,
version
,
x_kolab_version
);
VcalendarType
vcalendar
(
properties
,
components
);
IcalendarType
icalendar
(
vcalendar
);
xml_schema
::
namespace_infomap
map
;
map
[
""
].
name
=
XCAL_NAMESPACE
;
std
::
ostringstream
ostringstream
;
icalendar_2_0
::
icalendar
(
ostringstream
,
icalendar
,
map
);
return
ostringstream
.
str
();
}
catch
(
const
xml_schema
::
exception
&
e
)
{
CRITICAL
(
"failed to write Incidence"
);
}
catch
(...)
{
CRITICAL
(
"Unhandled exception"
);
}
return
std
::
string
();
}
template
<
typename
T
>
typename
T
::
IncidencePtr
deserializeIncidence
(
const
std
::
string
&
s
,
bool
isUrl
)
{
using
namespace
icalendar_2_0
;
typedef
typename
T
::
IncidencePtr
IncidencePtr
;
typedef
typename
T
::
IncidenceType
IncidenceType
;
typedef
typename
T
::
KolabType
KolabType
;
clearErrors
();
try
{
std
::
auto_ptr
<
icalendar_2_0
::
IcalendarType
>
icalendar
;
if
(
isUrl
)
{
xsd
::
cxx
::
xml
::
dom
::
auto_ptr
<
xercesc_3_1
::
DOMDocument
>
doc
=
XMLParserWrapper
::
inst
().
parseFile
(
s
);
if
(
doc
.
get
())
{
icalendar
=
icalendar_2_0
::
icalendar
(
doc
);
}
}
else
{
xsd
::
cxx
::
xml
::
dom
::
auto_ptr
<
xercesc_3_1
::
DOMDocument
>
doc
=
XMLParserWrapper
::
inst
().
parseString
(
s
);
if
(
doc
.
get
())
{
icalendar
=
icalendar_2_0
::
icalendar
(
doc
);
}
}
if
(
!
icalendar
.
get
())
{
CRITICAL
(
"Failed to parse calendar!"
);
return
IncidencePtr
();
}
const
icalendar_2_0
::
VcalendarType
&
vcalendar
=
icalendar
->
vcalendar
();
std
::
vector
<
IncidencePtr
>
incidences
;
for
(
typename
xsd
::
cxx
::
tree
::
sequence
<
KolabType
>::
const_iterator
it
(
T
::
begin
(
vcalendar
.
components
()));
it
!=
T
::
end
(
vcalendar
.
components
());
it
++
)
{
IncidencePtr
e
=
IncidencePtr
(
new
IncidenceType
);
const
KolabType
&
event
=
*
it
;
T
::
readIncidence
(
*
e
,
event
);
incidences
.
push_back
(
e
);
}
setProductId
(
vcalendar
.
properties
().
prodid
().
text
()
);
global_xCalVersion
=
vcalendar
.
properties
().
version
().
text
();
setKolabVersion
(
vcalendar
.
properties
().
x_kolab_version
().
text
()
);
//TODO resolve events, exceptions can be identified based on the recurrence-id attribute
// foreach (KCalCore::Event * event, events) {
// if (!event->hasRecurrenceId()) {
// return event;
// }
// }
if
(
incidences
.
size
()
!=
1
)
{
WARNING
(
"wrong number of incidences: "
+
incidences
.
size
());
}
return
*
incidences
.
begin
();
}
catch
(
const
xml_schema
::
exception
&
e
)
{
std
::
cout
<<
e
<<
std
::
endl
;
CRITICAL
(
"Failed to read incidence!"
);
}
catch
(...)
{
CRITICAL
(
"Unhandled exception"
);
}
return
IncidencePtr
();
}
}
}
//Namespace
#endif
File Metadata
Details
Attached
Mime Type
text/x-c++
Expires
Sat, Apr 4, 8:43 AM (2 w, 5 d ago)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
03/c2/e18b98faf7c221764eb7e4d008a7
Default Alt Text
xcalconversions.h (56 KB)
Attached To
Mode
rLKX libkolabxml
Attached
Detach File
Event Timeline