Branch 'c++/master' - 5 commits - c++/CMakeLists.txt c++/lib c++/tests schemas/kolabformat-xcard.xsd schemas/xCard.xsd

Christian Mollekopf mollekopf at kolabsys.com
Sun Feb 12 23:26:26 CET 2012


 c++/CMakeLists.txt            |    2 
 c++/lib/CMakeLists.txt        |    2 
 c++/lib/DEVELOPMENT           |   12 
 c++/lib/global_definitions.h  |    2 
 c++/lib/kolabcontact.cpp      |  393 ++++++++++++++++++++++++
 c++/lib/kolabcontact.h        |  280 +++++++++++++++++
 c++/lib/kolabcontainers.h     |    6 
 c++/lib/kolabevent.h          |    2 
 c++/lib/kolabformat.cpp       |   19 -
 c++/lib/kolabformat.h         |   18 +
 c++/lib/utils.cpp             |   46 ++
 c++/lib/utils.h               |   47 ++
 c++/lib/xcalconversions.h     |   40 --
 c++/lib/xcardconversions.h    |  665 ++++++++++++++++++++++++++++++++++++++++--
 c++/tests/bindingstest.cpp    |  203 ++++++++----
 c++/tests/bindingstest.h      |   11 
 c++/tests/conversiontest.cpp  |   47 ++
 c++/tests/conversiontest.h    |    6 
 c++/tests/serializers.h       |   22 +
 schemas/kolabformat-xcard.xsd |   22 +
 schemas/xCard.xsd             |  248 ++++++++++++++-
 21 files changed, 1906 insertions(+), 187 deletions(-)

New commits:
commit 003f6c65819f8f31284af00316ce99c029b0f782
Merge: 7f0a2ab 16daa73
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date:   Sun Feb 12 23:23:13 2012 +0100

    Merge remote-tracking branch 'origin/c++/master' into c++/master
    
    Conflicts:
    	c++/lib/global_definitions.h

diff --cc c++/lib/global_definitions.h
index 21aac74,326678c..2aa36e8
--- a/c++/lib/global_definitions.h
+++ b/c++/lib/global_definitions.h
@@@ -22,8 -22,8 +22,8 @@@
  namespace Kolab {
  
  const char* const KOLAB_LIBNAME = "libkolabxml";
 -const char* const KOLAB_LIB_VERSION = "0.9";
 +const char* const KOLAB_LIB_VERSION = "0.1";
- const char* const KOLAB_FORMAT_VERSION = "2.9.0";
+ const char* const KOLAB_FORMAT_VERSION = "3.0dev1";
  
  enum ErrorSeverity {
      NoError,


commit 7f0a2ab8882808ae2a542fe4ede54824f1502d77
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date:   Sun Feb 12 21:33:39 2012 +0100

    version 0.1

diff --git a/c++/lib/global_definitions.h b/c++/lib/global_definitions.h
index 1146e9c..21aac74 100644
--- a/c++/lib/global_definitions.h
+++ b/c++/lib/global_definitions.h
@@ -22,7 +22,7 @@
 namespace Kolab {
 
 const char* const KOLAB_LIBNAME = "libkolabxml";
-const char* const KOLAB_LIB_VERSION = "0.9";
+const char* const KOLAB_LIB_VERSION = "0.1";
 const char* const KOLAB_FORMAT_VERSION = "2.9.0";
 
 enum ErrorSeverity {


commit a996fc636886d3f86b9ff97f006c5c929007273f
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date:   Sun Feb 12 21:33:26 2012 +0100

    Tests and a couple of fixes

diff --git a/c++/lib/xcardconversions.h b/c++/lib/xcardconversions.h
index 938fdca..fb1871f 100644
--- a/c++/lib/xcardconversions.h
+++ b/c++/lib/xcardconversions.h
@@ -457,14 +457,26 @@ std::string serializeCard(const T &card, const std::string prod = std::string())
 
     try {
         vcard_4_0::vcard::uid_type uid(getUID(card.uid()));
-        setCreatedUid(uid.uri());
+        setCreatedUid(uid.text());
         vcard_4_0::vcard::x_kolab_version_type kolab_version(KOLAB_FORMAT_VERSION);
         vcard_4_0::vcard::prodid_type prodid(prod+KOLAB_LIBNAME+KOLAB_LIB_VERSION);
         vcard_4_0::vcard::rev_type rev(fromDateTime(getCurrentTime()));
         vcard_4_0::vcard::kind_type kind(getType<T>());
         vcard_4_0::vcard::fn_type fn(card.name());
+        
+        
 
         vcard_4_0::vcard vcard(uid, kolab_version, prodid, rev, kind, fn);
+        if (!card.categories().empty()) {
+            vcard_4_0::vcard::categories_type cat;
+            vcard_4_0::vcard::categories_type::text_sequence seq;
+            BOOST_FOREACH(const std::string &s, card.categories()) {
+                seq.push_back(s);
+            }
+            cat.text(seq);
+            vcard.categories(cat);
+        }
+        
         //TODO custom properties
         writeCard<T>(vcard, card);
         
@@ -739,6 +751,10 @@ boost::shared_ptr<T> deserializeCard(const std::string& s, bool isUrl)
         
         boost::shared_ptr<T> card = readCard<T>(vcards->vcard());
         card->setName(vcards->vcard().fn().text());
+
+        if (vcards->vcard().categories()) {
+            card->setCategories(toStringList((*vcards->vcard().categories()).text()));
+        }
         
         setProductId( vcards->vcard().prodid().text() );
 //         setFormatVersion( vcards->vcard().version().text() );
diff --git a/c++/tests/bindingstest.cpp b/c++/tests/bindingstest.cpp
index ed7d906..1d1433f 100644
--- a/c++/tests/bindingstest.cpp
+++ b/c++/tests/bindingstest.cpp
@@ -235,6 +235,7 @@ void BindingsTest::contactCompletness()
     stringlist.push_back("sdf");
 
     Kolab::Contact c;
+    c.setCategories(stringlist);
     c.setName("name");
     Kolab::NameComponents nc;
     nc.setSurnames(stringlist);
@@ -305,26 +306,37 @@ void BindingsTest::contactCompletness()
     std::cout << result << endl;
     Kolab::Contact e = Kolab::readContact(result, false);
     QVERIFY(Kolab::error() == Kolab::NoError);
+    QCOMPARE(e.uid(), c.uid());
+    QCOMPARE(e.created(), c.created());
+    QCOMPARE(e.categories(), c.categories());
     QCOMPARE(e.name(), c.name());
     QCOMPARE(e.nameComponents(), c.nameComponents());
     QCOMPARE(e.note(), c.note());
     QCOMPARE(e.freeBusyUrl(), c.freeBusyUrl());
+    QCOMPARE(e.affiliations(), c.affiliations());
     QCOMPARE(e.urls(), c.urls());
+    QCOMPARE(e.addresses(), c.addresses());
+    QCOMPARE(e.addressPreferredIndex(), c.addressPreferredIndex());
     QCOMPARE(e.nickNames(), c.nickNames());
+//     QCOMPARE(e.relateds(), c.relateds());
     QCOMPARE(e.bDay(), c.bDay());
     QCOMPARE(e.anniversary(), c.anniversary());
-    QCOMPARE(e.languages(), c.languages());
-    QCOMPARE(e.gender(), c.gender());
-    QCOMPARE(e.affiliations(), c.affiliations());
     QCOMPARE(e.photo(), c.photo());
-//     QCOMPARE(e.photoMimetype(), c.photoMimetype());
-    QCOMPARE(e.addresses(), c.addresses());
-    QCOMPARE(e.addressPreferredIndex(), c.addressPreferredIndex());
-
+    //     QCOMPARE(e.photoMimetype(), c.photoMimetype());
+    QCOMPARE(e.gender(), c.gender());
+    QCOMPARE(e.languages(), c.languages());
     QCOMPARE(e.telephones(), c.telephones());
     QCOMPARE(e.telephonesPreferredIndex(), c.telephonesPreferredIndex());
+    QCOMPARE(e.imAddresses(), c.imAddresses());
+    QCOMPARE(e.imAddressPreferredIndex(), c.imAddressPreferredIndex());
     QCOMPARE(e.emailAddresses(), c.emailAddresses());
     QCOMPARE(e.emailAddressPreferredIndex(), c.emailAddressPreferredIndex());
+//     QCOMPARE(e.gpsPos(), c.gpsPos());
+//     QCOMPARE(e.crypto(), c.crypto());
+//     QCOMPARE(e.customProperties(), c.customProperties());
+
+
+    
 
 
 }
diff --git a/schemas/kolabformat-xcard.xsd b/schemas/kolabformat-xcard.xsd
index a9ae046..407234c 100644
--- a/schemas/kolabformat-xcard.xsd
+++ b/schemas/kolabformat-xcard.xsd
@@ -40,6 +40,7 @@
                         <xs:element name="x-kolab-version" type="KolabVersion"/>
                         <xs:element name="prodid" type="prodidPropType"/>
                         <xs:element name="rev" type="revPropType"/>
+                        <xs:element name="categories" type="categoriesPropType" minOccurs="0" />
                         <xs:element name="kind" type="kindPropType"/>
                         <xs:element name="fn" type="fnPropType"/>
                         <xs:element name="n" type="nPropType" minOccurs="0"/>
diff --git a/schemas/xCard.xsd b/schemas/xCard.xsd
index 29d8f56..c523a80 100644
--- a/schemas/xCard.xsd
+++ b/schemas/xCard.xsd
@@ -211,6 +211,12 @@
     </xs:complexContent>
   </xs:complexType>
   
+  <xs:complexType name="categoriesPropType">
+    <xs:complexContent mixed="false">
+      <xs:extension base="xcard:TextListPropertyType"/>
+    </xs:complexContent>
+  </xs:complexType>
+  
   <xs:complexType name="fnPropType">
     <xs:complexContent mixed="false">
       <xs:extension base="xcard:TextPropertyType"/>
@@ -219,7 +225,7 @@
   
   <xs:complexType name="uidPropType">
     <xs:complexContent mixed="false">
-      <xs:extension base="xcard:UriPropertyType"/> <!--TODO not text?-->
+      <xs:extension base="xcard:TextPropertyType"/>
     </xs:complexContent>
   </xs:complexType>
   
@@ -327,11 +333,9 @@
     </xs:simpleType>
   
   <xs:complexType name="genderPropType">
-<!--    <xs:complexContent mixed="false">-->
   <xs:sequence>
       <xs:element name="sex" type="xcard:SexType" />
     </xs:sequence>
-<!--    </xs:complexContent>-->
   </xs:complexType>
   
   <xs:complexType name="langPropType">


commit 70cd843b8fcb9088a7a2bf381a64961a1fdf8112
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date:   Sun Feb 12 19:25:19 2012 +0100

    xCard Contacts implementation (not yet complete), cleanup, comments.

diff --git a/c++/CMakeLists.txt b/c++/CMakeLists.txt
index 2e4dd72..83ceb27 100644
--- a/c++/CMakeLists.txt
+++ b/c++/CMakeLists.txt
@@ -85,7 +85,7 @@ add_executable(xsdbin compiled/xsdbin.cxx)
 target_link_libraries(xsdbin ${XERCES_C})
 
 add_custom_command(OUTPUT kolabformat-xcal-schema.cxx
-    COMMAND ${CMAKE_BUILD_DIR}/xsdbin --verbose --array-name iCalendar_schema --output-dir ${CMAKE_BUILD_DIR}   ${SCHEMA_DIR}/ical/kolabformat-xcal.xsd ${SCHEMA_DIR}/ical/iCalendar-params.xsd ${SCHEMA_DIR}/ical/iCalendar-props.xsd ${SCHEMA_DIR}/ical/iCalendar-valtypes.xsd
+    COMMAND ${CMAKE_BUILD_DIR}/xsdbin --verbose --array-name iCalendar_schema --output-dir ${CMAKE_BUILD_DIR}   ${SCHEMA_DIR}/ical/kolabformat-xcal.xsd ${SCHEMA_DIR}/ical/iCalendar-params.xsd ${SCHEMA_DIR}/ical/iCalendar-props.xsd ${SCHEMA_DIR}/ical/iCalendar-valtypes.xsd ${SCHEMA_DIR}/xCard.xsd ${SCHEMA_DIR}/kolabformat-xcard.xsd
     COMMENT "Compiling Kolab XSD schema"
     WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
     DEPENDS ${XCAL_SCHEMAS} xsdbin
diff --git a/c++/lib/CMakeLists.txt b/c++/lib/CMakeLists.txt
index b48e630..e98acdc 100644
--- a/c++/lib/CMakeLists.txt
+++ b/c++/lib/CMakeLists.txt
@@ -9,7 +9,7 @@ SET_SOURCE_FILES_PROPERTIES(${SCHEMA_SOURCEFILES} PROPERTIES GENERATED 1)
 set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC " ) #always generate shared libraries with -fPIC
 
 #Library with serialization/deserialization code and kolab-containers
-add_library(kolabxml SHARED kolabformat.cpp kolabcontainers.cpp kolabevent.cpp kolabtodo.cpp utils.cpp base64.cpp ../compiled/XMLParserWrapper.cpp ../compiled/grammar-input-stream.cxx ${SCHEMA_SOURCEFILES})
+add_library(kolabxml SHARED kolabformat.cpp kolabcontainers.cpp kolabevent.cpp kolabtodo.cpp kolabcontact.cpp utils.cpp base64.cpp ../compiled/XMLParserWrapper.cpp ../compiled/grammar-input-stream.cxx ${SCHEMA_SOURCEFILES})
 target_link_libraries(kolabxml ${XERCES_C})
 
 #For the core library we can be stricter when compiling. This doesn't work with the auto generated code though.
diff --git a/c++/lib/DEVELOPMENT b/c++/lib/DEVELOPMENT
index 466c494..08cab4d 100644
--- a/c++/lib/DEVELOPMENT
+++ b/c++/lib/DEVELOPMENT
@@ -54,7 +54,7 @@ They were also designed to be easily copieable and make therefore minimal use of
 
 The containers are meant to not contain any logic, all logic should be implemented in the serialization functions.
 
-The validity of the containers can be checked using the isValid() function.
+The validity of the containers can be checked using the isValid() function. This function is used to check if a value has been set, and does not really verifiy the validity of the values in terms of what ranges/combinations are allowed.
 
 === Why KCalCore containers were not directly used ===
 
@@ -91,4 +91,12 @@ For further performance improvements read this: http://xerces.apache.org/xerces2
 All exceptions which could be thrown are caught within the serializing functions. There shouldn't be any uncaught exceptions because the bindings code doesn't handle that.
 If an error occurs a message is printed to the standard error output and a default constructed value is returned.
 
-Writing doesn't provide any validation (as it is hardly useful for the reason that it's anyways not possible to correct the mistake). For debugging purposes the document can be parsed again after writing. Validity is only ensured by typesafety, but range errors are easily possible.
\ No newline at end of file
+Writing doesn't provide any validation (as it is hardly useful for the reason that it's anyways not possible to correct the mistake). For debugging purposes the document can be parsed again after writing. Validity is only ensured by typesafety, but range errors are easily possible.
+
+
+
+=== The XSD based development checklist ===
+-Don't forget to add an element for each attribute in the style off: <xs:element name="pref" type="xcard:prefParamType" substitutionGroup="xcard:baseParameter"/>
+ Otherwise you won't get the serialization/deserialization code (or respectively just wrong code), which still compiles though and looks correct from the outside.
+
+-If you have modified the xsd's make sure to run "make clean && make" in the toplevel make directory, otherwise the schema is not recompiles => parsing errors
\ No newline at end of file
diff --git a/c++/lib/kolabcontact.cpp b/c++/lib/kolabcontact.cpp
new file mode 100644
index 0000000..7bc50ac
--- /dev/null
+++ b/c++/lib/kolabcontact.cpp
@@ -0,0 +1,393 @@
+/*
+ * Copyright (C) 2011  Christian Mollekopf <mollekopf at 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/>.
+*/
+
+#include "kolabcontact.h"
+
+namespace Kolab {
+    
+struct Contact::Private
+{
+    Private()
+    :  addressPreferredIndex(-1),
+    gender(NotSet),
+    telephonesPreferredIndex(-1),
+    imAddressPreferredIndex(-1),
+    emailAddressPreferredIndex(-1)
+    {}
+    
+    std::string uid;
+    DateTime created;
+    DateTime lastModified;
+    std::vector< std::string > categories;
+    
+    std::string name;
+    NameComponents nameComponents;
+    std::string note;
+    std::string freeBusyUrl;
+    std::vector<Affiliation> affiliations;
+    std::vector<std::string> urls;
+    std::vector<Address> addresses;
+    int addressPreferredIndex;
+    std::vector<std::string> nickNames;
+    std::vector<Related> relateds;
+    DateTime bDay;
+    DateTime anniversary;
+    std::string photo;
+    std::string photoMimetype;
+    Gender gender;
+    std::vector<std::string> languages;
+    std::vector<Telephone> telephones;
+    int telephonesPreferredIndex;
+    std::vector<std::string> imAddresses;
+    int imAddressPreferredIndex;
+    std::vector<std::string> emailAddresses;
+    int emailAddressPreferredIndex;
+    std::vector<std::string> gpsPos;
+    Crypto crypto;
+    std::vector<CustomProperty> customProperties;
+};
+
+Contact::Contact()
+: d(new Contact::Private())
+{
+    
+}
+
+Contact::Contact(const Contact &other)
+: d(new Contact::Private())
+{
+    *d = *other.d;
+}
+
+Contact::~Contact()
+{
+    
+}
+
+void Contact::operator=(const Kolab::Contact &other)
+{
+    *d = *other.d;
+}
+
+void Contact::setUid(const std::string &uid)
+{
+    d->uid = uid;
+}
+
+std::string Contact::uid() const
+{
+    return d->uid;
+}
+
+void Contact::setCreated(const Kolab::DateTime &created)
+{
+    d->created = created;
+}
+
+DateTime Contact::created() const
+{
+    return d->created;
+}
+
+void Contact::setLastModified(const Kolab::DateTime &dt)
+{
+    d->lastModified = dt;
+}
+
+DateTime Contact::lastModified() const
+{
+    return d->lastModified;
+}
+
+void Contact::setCategories(const std::vector< std::string > &cat)
+{
+ d->categories = cat;
+}
+
+void Contact::addCategory(const std::string &cat)
+{
+    d->categories.push_back(cat);
+}
+
+std::vector< std::string > Contact::categories() const
+{
+    return d->categories;
+}
+
+void Contact::setName(const std::string &name)
+{
+    d->name = name;
+}
+
+std::string Contact::name() const
+{
+    return d->name;
+}
+
+void Contact::setNameComponents(const Kolab::NameComponents &nc)
+{
+    d->nameComponents = nc;
+}
+
+NameComponents Contact::nameComponents() const
+{
+    return d->nameComponents;
+}
+
+void Contact::setNote(const std::string &note)
+{
+    d->note = note;
+}
+
+std::string Contact::note() const
+{
+    return d->note;
+}
+
+void Contact::setFreeBusyUrl(const std::string &url)
+{
+    d->freeBusyUrl = url;
+}
+
+std::string Contact::freeBusyUrl() const
+{
+    return d->freeBusyUrl;
+}
+
+void Contact::setAffiliations(const std::vector< Affiliation > &a)
+{
+    d->affiliations = a;
+}
+
+std::vector< Affiliation > Contact::affiliations() const
+{
+    return d->affiliations;
+}
+
+void Contact::setUrls(const std::vector< std::string > &urls)
+{
+    d->urls = urls;
+}
+
+std::vector< std::string > Contact::urls() const
+{
+    return d->urls;
+}
+
+void Contact::setAddresses(const std::vector< Address > &ad, int preferred)
+{
+    d->addresses = ad;
+    d->addressPreferredIndex = preferred;
+}
+
+std::vector< Address > Contact::addresses() const
+{
+    return d->addresses;
+}
+
+int Contact::addressPreferredIndex() const
+{
+    return d->addressPreferredIndex;
+}
+
+
+void Contact::setNickNames(const std::vector< std::string > &n)
+{
+    d->nickNames = n;
+}
+
+std::vector< std::string > Contact::nickNames() const
+{
+    return d->nickNames;
+}
+
+void Contact::setRelateds(const std::vector< Related > &relateds)
+{
+    d->relateds = relateds;
+}
+
+std::vector< Related > Contact::relateds() const
+{
+    return d->relateds;
+}
+
+void Contact::setBDay(const Kolab::DateTime &bday)
+{
+    d->bDay = bday;
+}
+
+DateTime Contact::bDay() const
+{
+    return d->bDay;
+}
+
+void Contact::setAnniversary(const Kolab::DateTime& dt)
+{
+    d->anniversary = dt;
+}
+
+DateTime Contact::anniversary() const
+{
+    return d->anniversary;
+}
+
+void Contact::setPhoto(const std::string& data, const std::string& mimetype)
+{
+    d->photo = data;
+    d->photoMimetype = mimetype;
+}
+
+std::string Contact::photo() const
+{
+    return d->photo;
+}
+
+std::string Contact::photoMimetype() const
+{
+    return d->photoMimetype;
+}
+
+void Contact::setGender(Contact::Gender g)
+{
+    d->gender = g;
+}
+
+Contact::Gender Contact::gender() const
+{
+    return d->gender;
+}
+
+void Contact::setLanguages(const std::vector< std::string >& l)
+{
+    d->languages = l;
+}
+
+std::vector< std::string > Contact::languages() const
+{
+    return d->languages;
+}
+
+void Contact::setTelephones(const std::vector< Telephone >& tel, int preferredIndex)
+{
+    d->telephonesPreferredIndex = preferredIndex;
+    d->telephones = tel;
+}
+
+std::vector< Telephone > Contact::telephones() const
+{
+    return d->telephones;
+}
+
+int Contact::telephonesPreferredIndex() const
+{
+    return d->telephonesPreferredIndex;
+}
+
+void Contact::setIMaddresses(const std::vector< std::string > &adr, int preferredIndex)
+{
+    d->imAddresses = adr;
+    d->imAddressPreferredIndex = preferredIndex;
+}
+
+std::vector< std::string > Contact::imAddresses() const
+{
+    return d->imAddresses;
+}
+
+int Contact::imAddressPreferredIndex() const
+{
+    return d->imAddressPreferredIndex;
+}
+
+void Contact::setEmailAddresses(const std::vector< std::string >& email, int preferredIndex)
+{
+    d->emailAddresses = email;
+    d->emailAddressPreferredIndex = preferredIndex;
+}
+
+std::vector< std::string > Contact::emailAddresses() const
+{
+    return d->emailAddresses;
+}
+
+int Contact::emailAddressPreferredIndex() const
+{
+    return d->emailAddressPreferredIndex;
+}
+
+void Contact::setGPSpos(const std::vector< std::string >& pos)
+{
+    d->gpsPos = pos;
+}
+
+std::vector< std::string > Contact::gpsPos() const
+{
+    return d->gpsPos;
+}
+
+void Contact::setCrypto(const Kolab::Crypto& c)
+{
+    d->crypto = c;
+}
+
+Crypto Contact::crypto() const
+{
+    return d->crypto;
+}
+
+void Contact::setCustomProperties(const std::vector< CustomProperty >& c)
+{
+    d->customProperties = c;
+}
+
+std::vector< CustomProperty > Contact::customProperties() const
+{
+    return d->customProperties;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+} //Namespace
+
diff --git a/c++/lib/kolabcontact.h b/c++/lib/kolabcontact.h
new file mode 100644
index 0000000..c4a3456
--- /dev/null
+++ b/c++/lib/kolabcontact.h
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2011  Christian Mollekopf <mollekopf at 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 KOLABCONTACT_H
+#define KOLABCONTACT_H
+
+#include <string>
+#include <vector>
+#include <boost/scoped_ptr.hpp>
+#include "kolabcontainers.h"
+
+namespace Kolab {
+    
+struct NameComponents {
+    bool operator==(const NameComponents &other) const { return mSurnames == other.mSurnames &&
+                                                        mGiven == other.mGiven &&
+                                                        mAdditional == other.mAdditional &&
+                                                        mPrefixes == other.mPrefixes &&
+                                                        mSuffixes == other.mSuffixes;
+                                                        };
+    void setSurnames(const std::vector<std::string> &s) { mSurnames = s; };
+    std::vector<std::string> surnames() const { return mSurnames; };
+    void setGiven(const std::vector<std::string> &s) { mGiven = s; };
+    std::vector<std::string> given() const { return mGiven; };
+    void setAdditional(const std::vector<std::string> &s) { mAdditional = s; };
+    std::vector<std::string> additional() const { return mAdditional; };
+    void setPrefixes(const std::vector<std::string> &s) { mPrefixes = s; };
+    std::vector<std::string> prefixes() const { return mPrefixes; };
+    void setSuffixes(const std::vector<std::string> &s) { mSuffixes = s; };
+    std::vector<std::string> suffixes() const { return mSuffixes; };
+    bool isValid() const { return !(mSurnames.empty() && mGiven.empty() && mAdditional.empty() && mPrefixes.empty() && mSuffixes.empty()); };
+private:
+    std::vector<std::string> mSurnames;
+    std::vector<std::string> mGiven;
+    std::vector<std::string> mAdditional;
+    std::vector<std::string> mPrefixes;
+    std::vector<std::string> mSuffixes;
+};
+
+struct Affiliation {
+    bool operator==(const Affiliation &other) const { return mOrg == other.mOrg &&
+                                                    mLogo == other.mLogo &&
+                                                    mTitles == other.mTitles &&
+                                                    mRoles == other.mRoles &&
+                                                    mManagers == other.mManagers &&
+                                                    mAssistants == other.mAssistants &&
+                                                    mOffices == other.mOffices;
+                                                    };
+    void setOrganisation(const std::string &org) { mOrg = org; };
+    std::string organisation() const { return mOrg; };
+//     void setOrganisationalUnits(const std::vector<std::string> &units);
+    void setLogo(const std::string &l) { mLogo = l; };
+    std::string logo() const { return mLogo; };
+    void setTitles(const std::vector<std::string> &titles) { mTitles = titles; };
+    std::vector<std::string> titles() const { return mTitles; };
+    void setRoles(const std::vector<std::string> &roles) { mRoles = roles; };
+    std::vector<std::string> roles() const { return mRoles; };
+    void setManagers(const std::vector<std::string> &managers) { mManagers = managers; };
+    std::vector<std::string> managers() const { return mManagers; };
+    void setAssistants(const std::vector<std::string> &assistants) { mAssistants = assistants; };
+    std::vector<std::string> assistants() const { return mAssistants; };
+    void setOffices(const std::vector<std::string> &offices) { mOffices = offices; };
+    std::vector<std::string> offices() const { return mOffices; };
+private:
+    std::string mOrg;
+    std::vector<std::string> mOrgUnits;
+    std::string mLogo;
+    std::vector<std::string> mTitles;
+    std::vector<std::string> mRoles;
+    std::vector<std::string> mManagers;
+    std::vector<std::string> mAssistants;
+    std::vector<std::string> mOffices;
+};
+
+struct Address {
+
+    Address(): mTypes(0) {};
+    enum Type {
+        Work = 0x01,
+        Home = 0x02
+    };
+    bool operator==(const Address &other) const { return mTypes == other.mTypes &&
+                                                    mLabel == other.mLabel &&
+                                                    mStreet == other.mStreet &&
+                                                    mLocality == other.mLocality &&
+                                                    mRegion == other.mRegion &&
+                                                    mCode == other.mCode &&
+                                                    mCountry == other.mCountry;
+                                                    };
+    void setTypes(int t) { mTypes = t; };
+    int types() const { return mTypes; };
+
+    void setLabel(const std::string &s) { mLabel = s; };
+    std::string label() const { return mLabel; }
+
+    void setStreet(const std::string &s) { mStreet = s; };
+    std::string street() const { return mStreet; };
+    
+    void setLocality(const std::string &s) { mLocality = s; };
+    std::string locality() const { return mLocality; };
+    
+    void setRegion(const std::string &s) { mRegion = s; };
+    std::string region() const { return mRegion; };
+    
+    void setCode(const std::string &s) { mCode = s; };
+    std::string code() const { return mCode; };
+    
+    void setCountry(const std::string &s) { mCountry = s; };
+    std::string country() const { return mCountry; };
+private:
+    int mTypes;
+    std::string mLabel;
+    std::string mStreet;
+    std::string mLocality;
+    std::string mRegion;
+    std::string mCode;
+    std::string mCountry;
+};
+
+struct Related {
+//     void setUri(const std::string &);
+//     std::string uri() const;
+//     void setText(const std::string &);
+//     std::string text() const;
+//     enum Type {
+//         Child,
+//         Spouse
+//     };
+//     void setType(Type t) { type = t; };
+//     Type type() const { return type; };
+// private:
+//     std::string uri;
+//     std::string text;
+//     Type type;
+};
+
+struct Telephone {
+    enum Type {
+        Work = 0x01,
+        Home = 0x02,
+        Text = 0x04,
+        Voice = 0x08,
+        Fax = 0x10,
+        Cell = 0x20,
+        Video = 0x40,
+        Pager = 0x80,
+        Textphone = 0x100,
+        Car = 0x200
+    };
+    Telephone(): mType(0){};
+    bool operator==(const Telephone &other) const { return mNumber == other.mNumber &&
+                                                    mType == other.mType;
+                                                    };
+    void setTypes(int t) { mType = t; };
+    int types() const { return mType; };
+    void setNumber(const std::string &n) { mNumber = n; };
+    std::string number() const { return mNumber; };
+private:
+    std::string mNumber;
+    int mType;
+};
+
+struct Crypto {
+    
+};
+
+class Contact {
+public:
+    Contact();
+    ~Contact();
+    Contact(const Contact &);
+    void operator=(const Contact &);
+    
+    void setUid(const std::string &);
+    std::string uid() const;
+    
+    void setCreated(const DateTime &);
+    DateTime created() const;
+    
+    void setLastModified(const DateTime &);
+    DateTime lastModified() const;
+    
+    void setCategories(const std::vector<std::string> &);
+    void addCategory(const std::string &);
+    std::vector<std::string> categories() const;
+    
+    void setName(const std::string &);
+    std::string name() const;
+    
+    void setNameComponents(const NameComponents &);
+    NameComponents nameComponents() const;
+    
+    void setNote(const std::string &);
+    std::string note() const;
+    
+    void setFreeBusyUrl(const std::string &);
+    std::string freeBusyUrl() const;
+    
+    void setAffiliations(const std::vector<Affiliation> &);
+    std::vector<Affiliation> affiliations() const;
+    
+    void setUrls(const std::vector<std::string> &);
+    std::vector<std::string> urls() const;
+    
+    void setAddresses(const std::vector<Address> &, int preferred = -1);
+    std::vector<Address> addresses() const;
+    int addressPreferredIndex() const;
+    
+    void setNickNames(const std::vector< std::string > &);
+    std::vector< std::string > nickNames() const;
+    
+    void setRelateds(const std::vector<Related> &);
+    std::vector<Related> relateds() const;
+     
+    void setBDay(const DateTime &);
+    DateTime bDay() const;
+    
+    void setAnniversary(const DateTime &);
+    DateTime anniversary() const;
+    
+    void setPhoto(const std::string &data, const std::string &mimetype);
+    std::string photo() const;
+    std::string photoMimetype() const;
+    
+    enum Gender {
+        NotSet,
+        NotSpecified,
+        Male,
+        Female
+    };
+    
+    void setGender(Gender);
+    Gender gender() const;
+    
+    void setLanguages(const std::vector<std::string> &);
+    std::vector<std::string> languages() const;
+    
+    void setTelephones(const std::vector<Telephone> &, int preferredIndex = -1);
+    std::vector<Telephone> telephones() const;
+    int telephonesPreferredIndex() const;
+    
+    void setIMaddresses(const std::vector<std::string> &, int preferredIndex = -1);
+    std::vector<std::string> imAddresses() const;
+    int imAddressPreferredIndex() const;
+    
+    void setEmailAddresses(const std::vector<std::string> &, int preferredIndex = -1);
+    std::vector<std::string> emailAddresses() const;
+    int emailAddressPreferredIndex() const;
+    
+    void setGPSpos(const std::vector<std::string> &);
+    std::vector<std::string> gpsPos() const;
+    
+    void setCrypto(const Crypto &);
+    Crypto crypto() const;
+    
+    void setCustomProperties(const std::vector<CustomProperty> &);
+    std::vector<CustomProperty> customProperties() const;
+
+private:
+    struct Private;
+    boost::scoped_ptr<Private> d;
+};
+
+} //Namespace
+
+#endif // KOLABCONTACT_H
diff --git a/c++/lib/kolabcontainers.h b/c++/lib/kolabcontainers.h
index 6f43ac8..a05dafe 100644
--- a/c++/lib/kolabcontainers.h
+++ b/c++/lib/kolabcontainers.h
@@ -345,12 +345,6 @@ class Journal {
     //TODO
 };
 
-class Contact {
-public:
-    std::string uid() const{return std::string();}
-    std::string fn() const{return std::string();}
-    //TODO
-};
 
 class DistList {
     //TODO
diff --git a/c++/lib/kolabevent.h b/c++/lib/kolabevent.h
index 668e254..6cb1587 100644
--- a/c++/lib/kolabevent.h
+++ b/c++/lib/kolabevent.h
@@ -106,7 +106,7 @@ public:
     
     void setCustomProperties(const std::vector<CustomProperty> &);
     std::vector<CustomProperty> customProperties() const;
-/*    TODO what is this?
+/*    TODO what is this? Exceptions it is
     void setExceptions(const std::vector<Event> &);
     std::vector<Event> exceptions() const;*/
     
diff --git a/c++/lib/kolabformat.cpp b/c++/lib/kolabformat.cpp
index 1538fad..3e72998 100644
--- a/c++/lib/kolabformat.cpp
+++ b/c++/lib/kolabformat.cpp
@@ -27,17 +27,17 @@ namespace Kolab {
     
 ErrorSeverity error()
 {
-    return getError();
+    return Utils::getError();
 }
 
 std::string errorMessage()
 {
-    return getErrorMessage();
+    return Utils::getErrorMessage();
 }
 
 std::string productId()
 {
-    return XCAL::global_productId;
+    return Utils::productId();
 }
 
 std::string xCalVersion()
@@ -47,7 +47,7 @@ std::string xCalVersion()
 
 std::string xKolabVersion()
 {
-    return XCAL::global_xKolabVersion;
+    return Utils::kolabVersion();
 }
 
 
@@ -112,11 +112,12 @@ std::string writeContact(const Contact &contact)
 
 DistList readDistlist(const std::string& s, bool isUrl)
 {
-    boost::shared_ptr <Kolab::DistList> ptr = XCARD::deserializeCard<Kolab::DistList>(s, isUrl);
-    if (!ptr.get()) {
-        return Kolab::DistList();
-    }
-    return *ptr;
+//     boost::shared_ptr <Kolab::DistList> ptr = XCARD::deserializeCard<Kolab::DistList>(s, isUrl);
+//     if (!ptr.get()) {
+//         return Kolab::DistList();
+//     }
+//     return *ptr;
+    return DistList();
 }
 
 std::string writeDistlist(const DistList &list)
diff --git a/c++/lib/kolabformat.h b/c++/lib/kolabformat.h
index 5af254a..0a46be7 100644
--- a/c++/lib/kolabformat.h
+++ b/c++/lib/kolabformat.h
@@ -22,15 +22,31 @@
 #include "kolabcontainers.h"
 #include "kolabtodo.h"
 #include "kolabevent.h"
+#include "kolabcontact.h"
 #include "global_definitions.h"
 
 namespace Kolab {
-    
+
+/**
+ * Check to see if serialization/deserialization was successful.
+ */
 Kolab::ErrorSeverity error();
 std::string errorMessage();
 
+/**
+ * Returns productId string of the last deserialized object.
+ * Updated during deserialization of object.
+ */
 std::string productId();
+/**
+ * Returns KolabFormat version of the last deserialized object.
+ * Updated during deserialization of object.
+ */
 std::string xKolabVersion();
+/**
+ * Returns KolabFormat version of the last deserialized xCal object.
+ * Updated during deserialization of object.
+ */
 std::string xCalVersion();
 
 Kolab::Event readEvent(const std::string& s, bool isUrl);
diff --git a/c++/lib/utils.cpp b/c++/lib/utils.cpp
index 2b9d54a..ce578ab 100644
--- a/c++/lib/utils.cpp
+++ b/c++/lib/utils.cpp
@@ -19,26 +19,58 @@
 #include <string>
 #include <boost/uuid/uuid.hpp>
 #include <boost/uuid/uuid_io.hpp>
-#include <time.h>
 #include <boost/lexical_cast.hpp>
+#include <time.h>
 
 namespace Kolab {
+    
+namespace Utils {
+    
+std::string global_createdUID;
+std::string global_productId;
+std::string global_xKolabVersion;
+
+void setKolabVersion(const std::string &s)
+{
+    global_xKolabVersion = s;
+}
+
+std::string kolabVersion()
+{
+    return global_xKolabVersion;
+}
+
+void setProductId(const std::string &s)
+{
+    global_productId = s;
+}
 
-std::string getUID()
+std::string productId()
 {
-    boost::uuids::uuid u; // initialize uuid
-    return boost::uuids::to_string(u);
+    return global_productId;
 }
 
+
+void setCreatedUid(const std::string &s)
+{
+    global_createdUID = s;
+}
+
+std::string createdUid()
+{
+    return global_createdUID;
+}
+
+
 std::string getUID(const std::string &s)
 {
     if (s.empty()) {
-        return getUID();
+        boost::uuids::uuid u; // initialize uuid
+        return boost::uuids::to_string(u);
     }
     return s;
 }
 
-
 DateTime getCurrentTime()
 {
     time_t rawtime;
@@ -74,7 +106,6 @@ void logMessage(const std::string &m, ErrorSeverity s)
                 global_errorBit = Critical;
                 global_errorMessage = m;
             }
-            
     }
 }
 
@@ -99,5 +130,6 @@ std::string getErrorMessage()
     return global_errorMessage;
 }
 
+}
 
 }
\ No newline at end of file
diff --git a/c++/lib/utils.h b/c++/lib/utils.h
index 886d181..29cacb7 100644
--- a/c++/lib/utils.h
+++ b/c++/lib/utils.h
@@ -21,11 +21,15 @@
 #include <string>
 #include "kolabcontainers.h"
 #include "global_definitions.h"
+#include <boost/numeric/conversion/cast.hpp>
 
 namespace Kolab {
 
-std::string getUID();
-std::string getUID(const std::string &);
+    namespace Utils {
+/**
+ * Returns a new globally unique UID if the parameter is empty
+ */
+std::string getUID(const std::string & = std::string());
 
 DateTime getCurrentTime();
 
@@ -42,6 +46,45 @@ void clearErrors();
 ErrorSeverity getError();
 std::string getErrorMessage();
 
+void setCreatedUid(const std::string &);
+std::string createdUid();
+void setProductId(const std::string &);
+std::string productId();
+void setKolabVersion(const std::string &);
+std::string kolabVersion();
+
+template <typename T>
+int convertToInt(T integer)
+{
+    try {
+        return boost::numeric_cast<int>(integer);
+    } catch(boost::numeric::negative_overflow& e) {
+        ERROR(e.what());
+    } catch(boost::numeric::positive_overflow& e) {
+        ERROR(e.what());
+    } catch(boost::numeric::bad_numeric_cast& e) {
+        ERROR(e.what());
+    }
+    return 0;
+}
+
+template <typename T> 
+T fromInt(int integer)
+{
+    try {
+        return boost::numeric_cast<T>(integer);
+    } catch(boost::numeric::negative_overflow& e) {
+        ERROR(e.what());
+    } catch(boost::numeric::positive_overflow& e) {
+        ERROR(e.what());
+    } catch(boost::numeric::bad_numeric_cast& e) {
+        ERROR(e.what());
+    }
+    return 0;
+}
+
+    }
+
 }
 
 #endif
\ No newline at end of file
diff --git a/c++/lib/xcalconversions.h b/c++/lib/xcalconversions.h
index 74df6e3..d308c6a 100644
--- a/c++/lib/xcalconversions.h
+++ b/c++/lib/xcalconversions.h
@@ -43,8 +43,6 @@
 namespace Kolab {
     namespace XCAL {
         
-std::string global_productId;
-std::string global_xKolabVersion;
 std::string global_xCalVersion;
 
 const char* const XCAL_VERSION = "2.0";
@@ -99,37 +97,10 @@ const char* const SU = "SU";
 const char* const START = "START";
 const char* const END = "END";
 
+using namespace Kolab::Utils;
+
 //=== Generic Conversions ===
     
-template <typename T>
-int convertToInt(T integer)
-{
-    try {
-        return boost::numeric_cast<int>(integer);
-    } catch(boost::numeric::negative_overflow& e) {
-        logMessage(e.what(), Error);
-    } catch(boost::numeric::positive_overflow& e) {
-        logMessage(e.what(), Error);
-    } catch(boost::numeric::bad_numeric_cast& e) {
-        logMessage(e.what(), Error);
-    }
-    return 0;
-}
-
-template <typename T> 
-T fromInt(int integer)
-{
-    try {
-        return boost::numeric_cast<T>(integer);
-    } catch(boost::numeric::negative_overflow& e) {
-        logMessage(e.what(), Error);
-    } catch(boost::numeric::positive_overflow& e) {
-        logMessage(e.what(), Error);
-    } catch(boost::numeric::bad_numeric_cast& e) {
-        logMessage(e.what(), Error);
-    }
-    return 0;
-}
 
 int toInt(const icalendar_2_0::IntegerPropertyType &prop)
 {
@@ -218,7 +189,7 @@ Kolab::DayPos toDayPos(const std::string &s)
                     try {
                         occurrence = boost::lexical_cast<int>(number);
                     } catch(boost::bad_lexical_cast &) {
-                        logMessage("failed to convert: " + number, Error);
+                        ERROR("failed to convert: " + number);
                         return DayPos();
                     }
                     number.clear();
@@ -1589,6 +1560,7 @@ std::string serializeIncidence(const typename T::IncidenceType &incidence, const
         T::setComponents(eventComponents, incidence);
 
         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;
@@ -1668,9 +1640,9 @@ typename T::IncidencePtr deserializeIncidence(const std::string& s, bool isUrl)
             incidences.push_back(e);
         }
         
-        global_productId = vcalendar.properties().prodid().text();
+        setProductId( vcalendar.properties().prodid().text() );
         global_xCalVersion = vcalendar.properties().version().text();
-        global_xKolabVersion = vcalendar.properties().x_kolab_version().text();
+        setKolabVersion( vcalendar.properties().x_kolab_version().text() );
 
 
         //TODO resolve events, exceptions can be identified based on the recurrence-id attribute
diff --git a/c++/lib/xcardconversions.h b/c++/lib/xcardconversions.h
index d9443ed..938fdca 100644
--- a/c++/lib/xcardconversions.h
+++ b/c++/lib/xcardconversions.h
@@ -22,8 +22,11 @@
 #include "kolabcontainers.h"
 #include <XMLParserWrapper.h>
 #include <boost/shared_ptr.hpp>
+#include <boost/foreach.hpp>
+#include <boost/lexical_cast.hpp>
 #include "global_definitions.h"
 #include "utils.h"
+#include "kolabcontact.h"
 
 namespace Kolab {
     namespace XCARD {
@@ -32,6 +35,8 @@ namespace Kolab {
     const char* const INDIVIDUAL = "individual";
     const char* const GROUP = "group";
     
+using namespace Kolab::Utils;
+    
 template <typename T> 
 std::string getType();
 
@@ -47,49 +52,420 @@ std::string getType<Kolab::DistList>()
     return GROUP;
 }
 
-template <typename T> 
-void writeCard(vcard_4_0::vcard vcard, const T &);
+template <typename T>
+xsd::cxx::tree::sequence<T> fromList(const std::vector<std::string> &input)
+{
+    xsd::cxx::tree::sequence<T> list;
+    BOOST_FOREACH(const std::string &s, input) {
+        list.push_back(T(s));
+    }
+    return list;
+}
 
-template <> 
-void writeCard<Kolab::Contact>(vcard_4_0::vcard vcard, const Kolab::Contact &contact)
+template <typename T>
+xsd::cxx::tree::sequence<T> fromList(const std::vector<std::string> &input, int preferredIndex)
 {
-    //TODO
+    xsd::cxx::tree::sequence<T> list;
+    int index = 0;
+    BOOST_FOREACH(const std::string &s, input) {
+        T im(s);
+        if(preferredIndex == index) {
+            typename T::parameters_type parameters;
+            parameters.baseParameter().push_back(vcard_4_0::prefParamType(vcard_4_0::prefParamType::integer_default_value()));
+            im.parameters(parameters);
+        }
+        index++;
+        list.push_back(im);
+    }
+    return list;
 }
 
-template <> 
-void writeCard<Kolab::DistList>(vcard_4_0::vcard vcard, const Kolab::DistList &distlist)
+template <typename T>
+std::vector<std::string> toUriList(const xsd::cxx::tree::sequence<T> &input)
 {
-    //TODO
+    std::vector<std::string> list;
+    BOOST_FOREACH(const vcard_4_0::UriPropertyType &s, input) {
+        list.push_back(s.uri());
+    }
+    return list;
+}
+
+template <typename T>
+std::vector<std::string> toTextList(const xsd::cxx::tree::sequence<T> &input)
+{
+    std::vector<std::string> list;
+    BOOST_FOREACH(const vcard_4_0::TextPropertyType &s, input) {
+        list.push_back(s.text());
+    }
+    return list;
+}
+
+std::vector<std::string> toStringList(const ::xsd::cxx::tree::sequence< ::xml_schema::string > &s)
+{
+    std::vector<std::string> d;
+    std::copy(s.begin(), s.end(), std::back_inserter(d));
+    return d;
 }
 
+::xsd::cxx::tree::sequence< ::xml_schema::string > fromStringList(const std::vector<std::string> &s)
+{
+    ::xsd::cxx::tree::sequence< ::xml_schema::string > d;
+    std::copy(s.begin(), s.end(), std::back_inserter(d));
+    return d;
+}
+
+std::string fromDate(const DateTime &dt)
+{
+    if (!dt.isDateOnly()) {
+        WARNING("fromDate called on date time value");
+    }
+    std::stringstream s;
+    s << dt.year() << dt.month() << dt.day();
+    return s.str();
+}
 
 std::string fromDateTime(const DateTime &dt)
 {
     std::stringstream s;
-    s << dt.year() << dt.month() << dt.day() << "T" << dt.hour() << dt.minute() << dt.second();
-    if (!dt.isUTC()) { //always UTC
-        std::cout << "Date is not UTC but it should be, UTC assumed." << std::endl;
+    s.fill('0');
+    s << std::right; 
+    s.width(4);
+    s << dt.year();
+    s.width(2);
+    s << dt.month();
+    s.width(2);
+    s << dt.day();
+    s.width(1);
+    if (dt.isDateOnly()) {
+        return s.str();
+    }
+    s << "T";
+    s.width(2);
+    s << dt.hour();
+    s.width(2);
+    s << dt.minute();
+    s.width(2);
+    s << dt.second();
+    if (dt.isUTC()) {
+        s << "Z";
     }
-    s << "Z";
     return s.str();
 }
 
+DateTime toDateTime(const std::string &input)
+{
+    int year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0;
+    bool isUtc = false;
+    try {
+        year = boost::lexical_cast<int>(input.substr(0, 4));
+        month = boost::lexical_cast<int>(input.substr(4, 2));
+        day = boost::lexical_cast<int>(input.substr(6, 2));
+        if (input.size() >= 15) { //Minimum for time
+            if (input.at(8) != 'T') {
+                ERROR("Wrong demiliter");
+                return DateTime();
+            }
+            hour = boost::lexical_cast<int>(input.substr(9, 2));
+            minute = boost::lexical_cast<int>(input.substr(11, 2));
+            second = boost::lexical_cast<int>(input.substr(13, 2));
+        } else {
+            if (input.size() >= 9) {
+                ERROR("Invalid dt " + input);
+                return DateTime();
+            }
+            return DateTime(year, month, day);
+        }
+        if (input.size() >= 16) {
+            if (input.at(15) == 'Z') {
+                isUtc = true;
+            } else {
+                ERROR("wrong utc char? " + input.at(15));
+                return DateTime();
+            }
+        }
+    } catch (boost::bad_lexical_cast &c) {
+        ERROR("failed to convert: "+std::string(c.what()));
+        return DateTime();
+    } catch (...) {
+        ERROR("failed to convert: unkown exception");
+        return DateTime();
+    }
+    return DateTime(year, month, day, hour, minute, second, isUtc);
+}
+
+DateTime toDateTime(const vcard_4_0::DateDatetimePropertyType &prop)
+{
+    if (prop.date_time()) {
+        return toDateTime(*prop.date_time());
+    } else if (prop.date()) {
+        return toDateTime(*prop.date());
+    }
+    ERROR("no date and no datetime");
+    return DateTime();
+}
+
+template <typename T>
+T fromDateTime(const Kolab::DateTime &dt)
+{
+    T prop;
+
+    if (dt.isDateOnly()) {
+        prop.date(fromDate(dt));
+    } else {
+        prop.date_time(fromDateTime(dt));
+    }
+    return prop;
+}
+
+template <typename T> 
+void writeCard(vcard_4_0::vcard &vcard, const T &);
+
+template <> 
+void writeCard<Kolab::Contact>(vcard_4_0::vcard &vcard, const Kolab::Contact &contact)
+{
+    using namespace vcard_4_0;
+    
+    if (contact.nameComponents().isValid()) {
+        const NameComponents &nc = contact.nameComponents();
+        vcard::n_type n;
+        n.surname(fromStringList(nc.surnames()));
+        n.given(fromStringList(nc.given()));
+        n.additional(fromStringList(nc.additional()));
+        n.prefix(fromStringList(nc.prefixes()));
+        n.suffix(fromStringList(nc.suffixes()));
+        vcard.n(n);
+    }
+    
+    if (!contact.note().empty()) {
+        vcard.note(vcard::note_type(contact.note()));
+    }
+    
+    if (!contact.freeBusyUrl().empty()) {
+        vcard.fburl(vcard::fburl_type(contact.freeBusyUrl()));
+    }
+    
+    if (!contact.affiliations().empty()) {
+        vcard::group_sequence affiliations;
+        BOOST_FOREACH(const Affiliation &a, contact.affiliations()) {
+            std::string encodedLogo = a.logo();//TODO encode logo
+            affiliationPropType::org_type org;
+            org.text().push_back(a.organisation());
+            vcard::group_type group(org, affiliationPropType::logo_type(encodedLogo));
+            group.title(fromList<affiliationPropType::title_type >(a.titles()));
+            group.role(fromList<affiliationPropType::role_type>(a.roles()));
+            group.x_manager(fromList<affiliationPropType::x_manager_type>(a.managers()));
+            group.x_assistant(fromList<affiliationPropType::x_assistant_type >(a.assistants()));
+            group.x_office(fromList<affiliationPropType::x_office_type>(a.offices()));
+            affiliations.push_back(group);
+        }
+        vcard.group(affiliations);
+    }
+    
+    if (!contact.urls().empty()) {
+        vcard.url(fromList<vcard::url_type>(contact.urls()));
+    }
+    
+    if (!contact.addresses().empty()) {
+        vcard::adr_sequence adrs;
+        int index = 0;
+        BOOST_FOREACH(const Kolab::Address &address, contact.addresses()) {
+            index++;
+            vcard::adr_type a(vcard::adr_type::pobox_type(std::string()/*address.pobox()*/), 
+                            vcard::adr_type::ext_type(std::string()/*address.ext()*/),
+                            vcard::adr_type::street_type(address.street()),
+                            vcard::adr_type::locality_type(address.locality()),
+                            vcard::adr_type::region_type(address.region()),
+                            address.code(),
+                            vcard::adr_type::country_type(address.country())
+            );
+            vcard::adr_type::parameters_type::baseParameter_sequence base;
+            vcard::adr_type::parameters_type b;
+            if (address.types()) {
+                vcard_4_0::typeParamType::text_sequence seq;
+                if (address.types() & Kolab::Address::Home) {
+                    seq.push_back(TypeValueType::home);
+                }
+                if (address.types() & Kolab::Address::Work) {
+                    seq.push_back(TypeValueType::work);
+                }
+                if (!seq.empty()) {
+                    vcard_4_0::typeParamType type;
+                    type.text(seq);
+                    b.baseParameter().push_back(type);
+                }
+            }
+            if (!address.label().empty()) {
+                b.baseParameter().push_back(vcard_4_0::labelParamType(address.label()));
+            }
+            if(contact.addressPreferredIndex() == index) {
+                b.baseParameter().push_back(vcard_4_0::prefParamType(vcard_4_0::prefParamType::integer_default_value()));
+            }
+            index++;
+            a.parameters(b);
+            adrs.push_back(a);
+        }
+        vcard.adr(adrs);
+    }
+    
+    if (!contact.nickNames().empty()) {
+        vcard::nickname_type::text_sequence textsequence;
+        BOOST_FOREACH(const std::string &s, contact.nickNames()) {
+            textsequence.push_back(s);
+        }
+        vcard::nickname_type nickName;
+        nickName.text(textsequence);
+        vcard.nickname(nickName);
+    }
+    
+    if (!contact.relateds().empty()) {
+        vcard::related_sequence seq;
+//         BOOST_FOREACH(const std::string &s, contact.urls()) {
+//             urls.push_back(vcard::url_type(s));
+//         }
+        //TODO
+        vcard.related(seq);
+    }
+    
+    if (contact.bDay().isValid()) {
+        Kolab::DateTime dt = contact.bDay();
+        if (dt.isUTC() || !dt.timezone().empty()) {
+            WARNING("Must be local time, local time assumed");
+            dt.setUTC(false);
+        }
+        vcard.bday(fromDateTime<vcard::bday_type>(dt));
+    }
+    
+    if (contact.anniversary().isValid()) {
+        Kolab::DateTime dt = contact.anniversary();
+        if (dt.isUTC() || !dt.timezone().empty()) {
+            WARNING("Must be local time, local time assumed");
+            dt.setUTC(false);
+        }
+        vcard.anniversary(fromDateTime<vcard::anniversary_type>(dt));
+    }
+    
+    if (!contact.photo().empty()) {
+        vcard::photo_type photo(vcard_4_0::UriPropertyType::uri_type(contact.photo()));
+        //TODO photo inline encoding
+        vcard.photo(photo);
+    }
+    
+    if (contact.gender() != Contact::NotSet) {
+        switch (contact.gender()) {
+            case Contact::NotSpecified:
+                vcard.gender(vcard::gender_type(vcard::gender_type::sex_type::empty));
+                break;
+            case Contact::Male:
+                vcard.gender(vcard::gender_type(vcard::gender_type::sex_type::M));
+                break;
+            case Contact::Female:
+                vcard.gender(vcard::gender_type(vcard::gender_type::sex_type::F));
+                break;
+            default:
+                ERROR("Unhandled gender");
+        }
+    }
+    
+    if (!contact.languages().empty()) {
+        vcard.lang(fromList<vcard::lang_type>(contact.languages()));
+    }
+    
+    if (!contact.telephones().empty()) {
+        vcard::tel_sequence seq;
+        int index = 0;
+        BOOST_FOREACH(const Kolab::Telephone &t, contact.telephones()) {
+            vcard::tel_type tel(t.number());
+            vcard_4_0::typeParamType telTypeParam;
+            if (t.types() & Kolab::Telephone::Car) {
+                telTypeParam.text().push_back(TypeValueType::x_car);
+            } 
+            if (t.types() & Kolab::Telephone::Cell) {
+                telTypeParam.text().push_back(TypeValueType::cell);
+            } 
+            if (t.types() & Kolab::Telephone::Fax) {
+                telTypeParam.text().push_back(TypeValueType::fax);
+            } 
+            if (t.types() & Kolab::Telephone::Home) {
+                telTypeParam.text().push_back(TypeValueType::home);
+            } 
+            if (t.types() & Kolab::Telephone::Work) {
+                telTypeParam.text().push_back(TypeValueType::work);
+            } 
+            if (t.types() & Kolab::Telephone::Text) {
+                telTypeParam.text().push_back(TypeValueType::text);
+            } 
+            if (t.types() & Kolab::Telephone::Voice) {
+                telTypeParam.text().push_back(TypeValueType::voice);
+            } 
+            if (t.types() & Kolab::Telephone::Video) {
+                telTypeParam.text().push_back(TypeValueType::video);
+            } 
+            if (t.types() & Kolab::Telephone::Textphone) {
+                telTypeParam.text().push_back(TypeValueType::textphone);
+            } 
+            if (t.types() & Kolab::Telephone::Pager) {
+                telTypeParam.text().push_back(TypeValueType::pager);
+            }
+            vcard::tel_type::parameters_type params;
+            if(contact.telephonesPreferredIndex() == index) {
+                params.baseParameter().push_back(vcard_4_0::prefParamType(vcard_4_0::prefParamType::integer_default_value()));
+            }
+            index++;
+
+            if (!telTypeParam.text().empty()) {
+                params.baseParameter().push_back(telTypeParam);
+                tel.parameters(params);
+            }
+            seq.push_back(tel);
+        }
+        vcard.tel(seq);
+    }
+    
+    if (!contact.imAddresses().empty()) {
+        vcard.impp(fromList<vcard::impp_type>(contact.imAddresses(), contact.imAddressPreferredIndex()));
+    }
+    
+    if (!contact.emailAddresses().empty()) {
+        vcard.email(fromList<vcard::email_type>(contact.emailAddresses(), contact.emailAddressPreferredIndex()));
+    }
+    
+    if (!contact.gpsPos().empty()) {
+        //TODO
+    }
+    
+//     if (!contact.crypto().isValid()) {
+//         //TODO
+//     }
+
+
+}
+
+template <> 
+void writeCard<Kolab::DistList>(vcard_4_0::vcard &vcard, const Kolab::DistList &distlist)
+{
+    //TODO
+}
+
+
 
 template <typename T>
 std::string serializeCard(const T &card, const std::string prod = std::string()) {
 
     using namespace vcard_4_0;
+    
+    clearErrors();
 
     try {
         vcard_4_0::vcard::uid_type uid(getUID(card.uid()));
+        setCreatedUid(uid.uri());
         vcard_4_0::vcard::x_kolab_version_type kolab_version(KOLAB_FORMAT_VERSION);
-        vcard_4_0::vcard::prodid_type prodid(prod+KOLAB_LIBNAME);
+        vcard_4_0::vcard::prodid_type prodid(prod+KOLAB_LIBNAME+KOLAB_LIB_VERSION);
         vcard_4_0::vcard::rev_type rev(fromDateTime(getCurrentTime()));
         vcard_4_0::vcard::kind_type kind(getType<T>());
-        vcard_4_0::vcard::fn_type fn(card.fn());
-        
-        
+        vcard_4_0::vcard::fn_type fn(card.name());
+
         vcard_4_0::vcard vcard(uid, kolab_version, prodid, rev, kind, fn);
+        //TODO custom properties
         writeCard<T>(vcard, card);
         
         VcardsType vcards(vcard);
@@ -101,9 +477,9 @@ std::string serializeCard(const T &card, const std::string prod = std::string())
         vcard_4_0::vcards(ostringstream, vcards, map);
         return ostringstream.str();
     } catch  (const xml_schema::exception& e) {
-        std::cerr << "failed to write Contact";
-        return std::string();
-    } 
+        CRITICAL("Unknown Exception: failed to write Contact");
+    }
+    return std::string();
 }
 
 template <typename T>
@@ -112,20 +488,236 @@ boost::shared_ptr<T> readCard(const vcard_4_0::VcardsType::vcard_type &vcard);
 template <>
 boost::shared_ptr<Kolab::Contact> readCard <Kolab::Contact> (const vcard_4_0::VcardsType::vcard_type &vcard)
 {
-    //TODO
-    return boost::shared_ptr<Kolab::Contact>();
+    using namespace vcard_4_0;
+    boost::shared_ptr<Kolab::Contact> contact(new Kolab::Contact);
+    if (vcard.n()) {
+        NameComponents nc;
+        nc.setSurnames(toStringList((*vcard.n()).surname()));
+        nc.setGiven(toStringList((*vcard.n()).given()));
+        nc.setPrefixes(toStringList((*vcard.n()).prefix()));
+        nc.setSuffixes(toStringList((*vcard.n()).suffix()));
+        nc.setAdditional(toStringList((*vcard.n()).additional()));
+        contact->setNameComponents(nc);
+    }
+    if (vcard.note()) {
+        contact->setNote((*vcard.note()).text());
+    }
+    if (vcard.fburl()) {
+        contact->setFreeBusyUrl((*vcard.fburl()).uri());
+    }
+    if (!vcard.group().empty()) {
+        std::vector<Kolab::Affiliation> list;
+        BOOST_FOREACH (const vcard::group_type &group, vcard.group()) {
+            Kolab::Affiliation aff;
+            std::string org;
+            if (!group.org().text().empty()) {
+                org = *group.org().text().begin();
+            } else {
+                WARNING("No org present");
+            }
+            aff.setOrganisation(org);
+            aff.setLogo(group.logo().uri());
+            aff.setTitles(toTextList<vcard::group_type::title_type>(group.title()));
+            aff.setRoles(toTextList<vcard::group_type::role_type>(group.role()));
+            aff.setManagers(toTextList<vcard::group_type::x_manager_type>(group.x_manager()));
+            aff.setAssistants(toTextList<vcard::group_type::x_assistant_type>(group.x_assistant()));
+            aff.setOffices(toTextList<vcard::group_type::x_office_type>(group.x_office()));
+            list.push_back(aff);
+        }
+        contact->setAffiliations(list);
+    }
+    if (!vcard.url().empty()) {
+        contact->setUrls(toUriList<vcard::url_type >(vcard.url()));
+    }
+    if (!vcard.adr().empty()) {
+        std::vector<Kolab::Address> list;
+        int preferredIndex = -1;
+        int index = 0;
+        BOOST_FOREACH(const vcard::adr_type &adr, vcard.adr()) {
+            Kolab::Address address;
+            if (adr.parameters()) {
+                BOOST_FOREACH(const vcard_4_0::ArrayOfParameters::baseParameter_type &param, (*adr.parameters()).baseParameter()) {
+                    if (const vcard_4_0::labelParamType *rel = dynamic_cast<const vcard_4_0::labelParamType*> (&param)) {
+                        address.setLabel(rel->text());
+                    } else if (dynamic_cast<const vcard_4_0::prefParamType*> (&param)) {
+                        preferredIndex = index;
+                    } else if (const vcard_4_0::typeParamType *rel = dynamic_cast<const vcard_4_0::typeParamType*> (&param)) {
+                        int types = 0;
+                        BOOST_FOREACH(const std::string &s, rel->text()) {
+                            if (s == TypeValueType(TypeValueType::work)) {
+                                types |= Kolab::Telephone::Work;
+                            }
+                            if (s == TypeValueType(TypeValueType::home)) {
+                                types |= Kolab::Telephone::Home;
+                            }
+                        }
+                        address.setTypes(types);
+                    } 
+                }
+            }
+            index++;
+
+            address.setCode(adr.code());
+            address.setCountry(adr.country());
+            address.setLocality(adr.locality());
+            address.setRegion(adr.region());
+            address.setStreet(adr.street());
+            list.push_back(address);
+        }
+        contact->setAddresses(list, preferredIndex);
+    }
+    if (vcard.nickname()) {
+        contact->setNickNames(toTextList<TextListPropertyType::text_type>((*vcard.nickname()).text()));
+    }
+    if (!vcard.related().empty()) {
+//         std::vector<Related> list;
+//         BOOST_FOREACH(const vcard::lang_type l, vcard.lang()) {
+//             list.push_back(l.language_tag());
+//         }
+//         contact->setRelateds();
+        //TODO
+    }
+    if (vcard.bday()) {
+        contact->setBDay(toDateTime(*vcard.bday()));
+    }
+    if (vcard.anniversary()) {
+        contact->setAnniversary(toDateTime(*vcard.anniversary()));
+    }
+    if (vcard.photo()) {
+        const std::string decodedPhoto =  (*vcard.photo()).uri(); //TODO decode photo
+        const std::string mimetype;
+        contact->setPhoto(decodedPhoto, mimetype);
+    }
+    if (vcard.gender()) {
+        if ((*vcard.gender()).sex() == vcard::gender_type::sex_type::empty) {
+            contact->setGender(Kolab::Contact::NotSpecified);
+        } else if ((*vcard.gender()).sex() == vcard::gender_type::sex_type::M) {
+            contact->setGender(Kolab::Contact::Male);
+        } else if ((*vcard.gender()).sex() == vcard::gender_type::sex_type::F) {
+            contact->setGender(Kolab::Contact::Female);
+        }
+    }
+    if (!vcard.lang().empty()) {
+        std::vector<std::string> list;
+        BOOST_FOREACH(const vcard::lang_type l, vcard.lang()) {
+            list.push_back(l.language_tag());
+        }
+        contact->setLanguages(list);
+    }
+    if (!vcard.tel().empty()) {
+        std::vector<Kolab::Telephone> list;
+        int preferredIndex = -1;
+        int index = 0;
+        BOOST_FOREACH(const vcard::tel_type &tel, vcard.tel()) {
+            Kolab::Telephone telephone;
+            if (tel.parameters()) {
+                BOOST_FOREACH(const vcard_4_0::ArrayOfParameters::baseParameter_type &param, (*tel.parameters()).baseParameter()) {
+                    if (dynamic_cast<const vcard_4_0::prefParamType*> (&param)) {
+                        preferredIndex = index;
+                    } else if (const vcard_4_0::typeParamType *rel = dynamic_cast<const vcard_4_0::typeParamType*> (&param)) {
+                        int types = 0;
+                        BOOST_FOREACH(const std::string &s, rel->text()) {
+                            if (s == TypeValueType(TypeValueType::work)) {
+                                types |= Kolab::Telephone::Work;
+                            }
+                            if (s == TypeValueType(TypeValueType::home)) {
+                                types |= Kolab::Telephone::Home;
+                            }
+                            if (s == TypeValueType(TypeValueType::text)) {
+                                types |= Kolab::Telephone::Text;
+                            }
+                            if (s == TypeValueType(TypeValueType::voice)) {
+                                types |= Kolab::Telephone::Voice;
+                            }
+                            if (s == TypeValueType(TypeValueType::fax)) {
+                                types |= Kolab::Telephone::Fax;
+                            }
+                            if (s == TypeValueType(TypeValueType::cell)) {
+                                types |= Kolab::Telephone::Cell;
+                            }
+                            if (s == TypeValueType(TypeValueType::video)) {
+                                types |= Kolab::Telephone::Video;
+                            }
+                            if (s == TypeValueType(TypeValueType::pager)) {
+                                types |= Kolab::Telephone::Pager;
+                            }
+                            if (s == TypeValueType(TypeValueType::textphone)) {
+                                types |= Kolab::Telephone::Textphone;
+                            }
+                            if (s == TypeValueType(TypeValueType::x_car)) {
+                                types |= Kolab::Telephone::Car;
+                            }
+                        }
+                        telephone.setTypes(types);
+                    } 
+                }
+            }
+            index++;
+
+            telephone.setNumber(tel.text());
+            list.push_back(telephone);
+        }
+        contact->setTelephones(list, preferredIndex);
+    }
+    
+    if (!vcard.impp().empty()) {
+        int preferredIndex = -1;
+        
+        std::vector<std::string> list;
+        int i = 0;
+        BOOST_FOREACH(const vcard_4_0::UriPropertyType &s, vcard.impp()) {
+            if (s.parameters()) {
+                BOOST_FOREACH(const vcard_4_0::ArrayOfParameters::baseParameter_type &param, (*s.parameters()).baseParameter()) {
+                    if (dynamic_cast<const vcard_4_0::prefParamType*> (&param)) {
+                        preferredIndex = i;
+                    } 
+                }
+            }
+            i++;
+            list.push_back(s.uri());
+        }
+        
+        contact->setIMaddresses(list, preferredIndex);
+    }
+    if (!vcard.email().empty()) {
+        int preferredIndex = -1;
+        
+        std::vector<std::string> list;
+        int i = 0;
+        BOOST_FOREACH(const vcard_4_0::TextPropertyType &s, vcard.email()) {
+            if (s.parameters()) {
+                BOOST_FOREACH(const vcard_4_0::ArrayOfParameters::baseParameter_type &param, (*s.parameters()).baseParameter()) {
+                    if (dynamic_cast<const vcard_4_0::prefParamType*> (&param)) {
+                        preferredIndex = i;
+                    } 
+                }
+            }
+            i++;
+            list.push_back(s.text());
+        }
+        
+        contact->setEmailAddresses(list, preferredIndex);
+    }
+    if (!vcard.geo().empty()) {
+        //TODO Geo
+    }
+    if (!vcard.x_crypto().empty()) {
+        //TODO Crypto
+    }
+    return contact;
 }
 
 template <>
 boost::shared_ptr<Kolab::DistList> readCard <Kolab::DistList> (const vcard_4_0::VcardsType::vcard_type &vcard)
 {
-    //TODO
+    //TODO DistList
     return boost::shared_ptr<Kolab::DistList>();
 }
 
 template <typename T>
 boost::shared_ptr<T> deserializeCard(const std::string& s, bool isUrl)
 {
+    clearErrors();
     try {
         std::auto_ptr<vcard_4_0::VcardsType> vcards;
         if (isUrl) {
@@ -139,15 +731,24 @@ boost::shared_ptr<T> deserializeCard(const std::string& s, bool isUrl)
                 vcards = vcard_4_0::vcards(doc);
             }
         }
-        
+
         if (!vcards.get()) {
-            std::cerr << "failed to parse card!" << std::endl;
+            CRITICAL("failed to parse card!");
             return boost::shared_ptr<T>();
         }
-        return readCard<T>(vcards->vcard());
+        
+        boost::shared_ptr<T> card = readCard<T>(vcards->vcard());
+        card->setName(vcards->vcard().fn().text());
+        
+        setProductId( vcards->vcard().prodid().text() );
+//         setFormatVersion( vcards->vcard().version().text() );
+//         global_xCarVersion = vcalendar.properties().version().text();
+        setKolabVersion( vcards->vcard().x_kolab_version().text() );
+        
+        return card;
     } catch  (const xml_schema::exception& e) {
         std::cerr <<  e << std::endl;
-        std::cerr <<  "Failed to read card!" << std::endl;
+        CRITICAL("Failed to read card!");
     }
 
     return boost::shared_ptr<T>();
diff --git a/c++/tests/bindingstest.cpp b/c++/tests/bindingstest.cpp
index 3fa7703..ed7d906 100644
--- a/c++/tests/bindingstest.cpp
+++ b/c++/tests/bindingstest.cpp
@@ -150,7 +150,6 @@ void checkIncidence(const T &ev, const T &re)
     QCOMPARE(r1.bysecond(), r2.bysecond());
     QCOMPARE(r1.byminute(), r2.byminute());
     QCOMPARE(r1.byhour(), r2.byhour());
-//     QEXPECT_FAIL("", "Implement Day parser", Continue);
     QCOMPARE(r1.byday(), r2.byday());
     QCOMPARE(r1.bymonthday(), r2.bymonthday());
     QCOMPARE(r1.byyearday(), r2.byyearday());
@@ -185,13 +184,12 @@ void BindingsTest::eventCompletness()
     ev.setTransparency(true);
     
     std::string result = Kolab::writeEvent(ev);
+    QVERIFY(Kolab::error() == Kolab::NoError);
 //     std::cout << result << endl;
     Kolab::Event e = Kolab::readEvent(result, false);
+    QVERIFY(Kolab::error() == Kolab::NoError);
     checkIncidence(ev, e);
     QCOMPARE(ev.end(), e.end());
-//     QEXPECT_FAIL("", "Will fix in the next release", Continue);
-//     QVERIFY(ev.duration().isValid());
-//     QCOMPARE(ev.duration(), re.duration());
     QCOMPARE(ev.transparency(), e.transparency());
     
 }
@@ -202,8 +200,10 @@ void BindingsTest::eventDuration()
     ev.setDuration(Kolab::Duration(11,22,33,44, true));
 
     const std::string result = Kolab::writeEvent(ev);
+    QVERIFY(Kolab::error() == Kolab::NoError);
 //     std::cout << result << endl;
     const Kolab::Event e = Kolab::readEvent(result, false);
+    QVERIFY(Kolab::error() == Kolab::NoError);
     QVERIFY(ev.duration().isValid());
     QCOMPARE(ev.duration(), e.duration());
 }
@@ -218,14 +218,117 @@ void BindingsTest::todoCompletness()
     ev.setPercentComplete(50);
     
     std::string result = Kolab::writeTodo(ev);
-//     std::cout << result << endl;
+    QVERIFY(Kolab::error() == Kolab::NoError);
+    std::cout << result << endl;
     Kolab::Todo e = Kolab::readTodo(result, false);
+    QVERIFY(Kolab::error() == Kolab::NoError);
     checkIncidence(ev, e);
     QCOMPARE(ev.due(), e.due());
     QCOMPARE(ev.relatedTo(), e.relatedTo());
     QCOMPARE(ev.percentComplete(), e.percentComplete());
 }
 
+void BindingsTest::contactCompletness()
+{
+    std::vector<std::string> stringlist;
+    stringlist.push_back("lbksdfbklsd");
+    stringlist.push_back("sdf");
+
+    Kolab::Contact c;
+    c.setName("name");
+    Kolab::NameComponents nc;
+    nc.setSurnames(stringlist);
+    nc.setGiven(stringlist);
+    nc.setAdditional(stringlist);
+    nc.setPrefixes(stringlist);
+    nc.setSuffixes(stringlist);
+    c.setNameComponents(nc);
+    c.setNote("note");
+    c.setFreeBusyUrl("freebusy");
+    c.setUrls(stringlist);
+    c.setNickNames(stringlist);
+    c.setBDay(Kolab::DateTime(2001,12,10,12,12,12,false));
+    c.setAnniversary(Kolab::DateTime(2001,3,2,1,1,1,false));
+    c.setPhoto("photo", "mimetype");
+    c.setGender(Kolab::Contact::Male);
+    c.setLanguages(stringlist);
+    c.setIMaddresses(stringlist,1);
+    c.setEmailAddresses(stringlist,1);
+    std::vector<Kolab::Affiliation> list;
+    Kolab::Affiliation aff;
+    aff.setOrganisation("org");
+    aff.setLogo("logo");
+    aff.setTitles(stringlist);
+    aff.setRoles(stringlist);
+    aff.setManagers(stringlist);
+    aff.setAssistants(stringlist);
+    aff.setOffices(stringlist);
+    list.push_back(aff);
+    list.push_back(aff);
+    c.setAffiliations(list);
+    Kolab::Address address;
+    address.setCode("oiuoiu");
+    address.setCountry("werwer");
+    address.setLabel("lkjlkj");
+    address.setLocality("alla");
+    address.setRegion("skjdfkd");
+    address.setStreet("sldkflsdfj");
+    address.setTypes( Kolab::Address::Work | Kolab::Address::Home );
+    std::vector<Kolab::Address> addresses;
+    addresses.push_back(address);
+    addresses.push_back(address);
+    c.setAddresses(addresses);
+    Kolab::Telephone phone;
+    phone.setNumber("lkjsdflkjfds");
+    phone.setTypes(Kolab::Telephone::Work|
+                    Kolab::Telephone::Home|
+                    Kolab::Telephone::Text|
+                    Kolab::Telephone::Voice|
+                    Kolab::Telephone::Fax|
+                    Kolab::Telephone::Cell|
+                    Kolab::Telephone::Video|
+                    Kolab::Telephone::Pager|
+                    Kolab::Telephone::Textphone|
+                    Kolab::Telephone::Car
+    );
+
+    std::vector<Kolab::Telephone> telephones;
+    telephones.push_back(phone);
+    telephones.push_back(phone);
+    c.setTelephones(telephones, 1);
+    c.setPhoto("photo", "mimetype");
+    
+//     c.setGPSpos(stringlist,1);
+    
+    const std::string result = Kolab::writeContact(c);
+    QVERIFY(Kolab::error() == Kolab::NoError);
+    std::cout << result << endl;
+    Kolab::Contact e = Kolab::readContact(result, false);
+    QVERIFY(Kolab::error() == Kolab::NoError);
+    QCOMPARE(e.name(), c.name());
+    QCOMPARE(e.nameComponents(), c.nameComponents());
+    QCOMPARE(e.note(), c.note());
+    QCOMPARE(e.freeBusyUrl(), c.freeBusyUrl());
+    QCOMPARE(e.urls(), c.urls());
+    QCOMPARE(e.nickNames(), c.nickNames());
+    QCOMPARE(e.bDay(), c.bDay());
+    QCOMPARE(e.anniversary(), c.anniversary());
+    QCOMPARE(e.languages(), c.languages());
+    QCOMPARE(e.gender(), c.gender());
+    QCOMPARE(e.affiliations(), c.affiliations());
+    QCOMPARE(e.photo(), c.photo());
+//     QCOMPARE(e.photoMimetype(), c.photoMimetype());
+    QCOMPARE(e.addresses(), c.addresses());
+    QCOMPARE(e.addressPreferredIndex(), c.addressPreferredIndex());
+
+    QCOMPARE(e.telephones(), c.telephones());
+    QCOMPARE(e.telephonesPreferredIndex(), c.telephonesPreferredIndex());
+    QCOMPARE(e.emailAddresses(), c.emailAddresses());
+    QCOMPARE(e.emailAddressPreferredIndex(), c.emailAddressPreferredIndex());
+
+
+}
+
 void BindingsTest::versionTest()
 {
     Kolab::Todo ev;
@@ -242,7 +345,7 @@ void BindingsTest::errorTest()
 {
     Kolab::Todo e = Kolab::readTodo("klbsdfbklsdbkl", false);
     QCOMPARE(Kolab::error(), Kolab::Critical);
-    QCOMPARE(Kolab::errorMessage(), std::string("/home/chrigi/work/kolab/xmlformat/libkolabxml/c++/lib/xcalconversions.h 1657:   Failed to parse calendar!"));
+    QVERIFY(!Kolab::errorMessage().empty());
 }
 
 //Don't break due to an error
diff --git a/c++/tests/bindingstest.h b/c++/tests/bindingstest.h
index 674d201..3abaac5 100644
--- a/c++/tests/bindingstest.h
+++ b/c++/tests/bindingstest.h
@@ -25,6 +25,8 @@ class BindingsTest : public QObject
     void eventCompletness();
     void eventDuration();
     void todoCompletness();
+    
+    void contactCompletness();
 
     void versionTest();
     void errorTest();
diff --git a/c++/tests/conversiontest.cpp b/c++/tests/conversiontest.cpp
index 5fe8f5e..ef3998c 100644
--- a/c++/tests/conversiontest.cpp
+++ b/c++/tests/conversiontest.cpp
@@ -2,11 +2,13 @@
 
 #include <QtTest/QtTest>
 #include <lib/xcalconversions.h>
+#include <lib/xcardconversions.h>
 
 #include "serializers.h"
 
 Q_DECLARE_METATYPE(Kolab::Duration);
 Q_DECLARE_METATYPE(Kolab::DayPos);
+Q_DECLARE_METATYPE(Kolab::DateTime);
 
 using namespace Kolab::XCAL;
  
@@ -36,8 +38,8 @@ void ConversionTest::durationSerializerTest_data()
 
     QTest::newRow("Time") << "PT2H3M4S" << Kolab::Duration(0,2,3,4, false);
     QTest::newRow("Day") << "P1DT2H3M4S" << Kolab::Duration(1,2,3,4, false);
-    QTest::newRow("Week") << "P1W" << Kolab::Duration(1, false);
-    QTest::newRow("Week") << "-P3W" << Kolab::Duration(3, false);
+    QTest::newRow("Week positive") << "P1W" << Kolab::Duration(1, false);
+    QTest::newRow("Week negative") << "-P3W" << Kolab::Duration(3, true);
     QTest::newRow("Week Multidigit, negative") << "-P23W" << Kolab::Duration(23, true);
 }
 
@@ -59,7 +61,6 @@ void ConversionTest::dayPosParserTest_data()
     QTest::newRow("positive with +") << Kolab::DayPos(15, Kolab::Wednesday) << "+15WE";
     QTest::newRow("negative") << Kolab::DayPos(-15, Kolab::Wednesday) << "-15WE";
     QTest::newRow("all occurrences") << Kolab::DayPos(0, Kolab::Wednesday) << "WE";
-
 }
 
 void ConversionTest::dayPosParserTest()
@@ -89,6 +90,46 @@ void ConversionTest::dayPosSerializerTest()
     QCOMPARE(QString::fromStdString(result), expected);
 }
 
+void ConversionTest::xcardDateParserTest_data()
+{
+    QTest::addColumn<QString>("input");
+    QTest::addColumn<Kolab::DateTime>("expected");
+
+    QTest::newRow("datetime local") << "20010102T030405" << Kolab::DateTime(2001, 01, 02, 03, 04 ,05, false);
+    QTest::newRow("datetime utc") << "20010102T030405Z" << Kolab::DateTime(2001, 01, 02, 03, 04 ,05, true);
+    QTest::newRow("date only") << "20010102" << Kolab::DateTime(2001, 01, 02);
+    QTest::newRow("fail 1 short") << "20010102T03040" << Kolab::DateTime();
+    QTest::newRow("fail non utc") << "20010102T030401s" << Kolab::DateTime();
+    QTest::newRow("fail no time") << "20010102T" << Kolab::DateTime();
+}
+
+
+void ConversionTest::xcardDateParserTest()
+{
+    QFETCH(QString, input);
+    QFETCH(Kolab::DateTime, expected);
+    const Kolab::DateTime &dt = Kolab::XCARD::toDateTime(input.toStdString());
+    QCOMPARE(dt, expected);
+}
+
+void ConversionTest::xCardSerializerTest_data()
+{
+    QTest::addColumn<QString>("expected");
+    QTest::addColumn<Kolab::DateTime>("dt");
+
+    QTest::newRow("datetime local") << "20010102T030405" << Kolab::DateTime(2001, 01, 02, 03, 04 ,05, false);
+    QTest::newRow("datetime utc") << "20010102T030405Z" << Kolab::DateTime(2001, 01, 02, 03, 04 ,05, true);
+    QTest::newRow("dateonly") << "20010102" << Kolab::DateTime(2001, 01, 02);
+}
+
+void ConversionTest::xCardSerializerTest()
+{
+    QFETCH(QString, expected);
+    QFETCH(Kolab::DateTime, dt);
+    const std::string &s = Kolab::XCARD::fromDateTime(dt);
+    QCOMPARE(QString::fromStdString(s), expected);
+}
+
 
 QTEST_MAIN( ConversionTest )
 
diff --git a/c++/tests/conversiontest.h b/c++/tests/conversiontest.h
index 8672b99..91fe618 100644
--- a/c++/tests/conversiontest.h
+++ b/c++/tests/conversiontest.h
@@ -20,6 +20,12 @@ class ConversionTest : public QObject
     
     void dayPosSerializerTest_data();
     void dayPosSerializerTest();
+    
+    void xcardDateParserTest_data();
+    void xcardDateParserTest();
+    
+    void xCardSerializerTest_data();
+    void xCardSerializerTest();
 };
 
 #endif // CONVERSIONTEST_H
diff --git a/c++/tests/serializers.h b/c++/tests/serializers.h
index 8548b62..c7f67d7 100644
--- a/c++/tests/serializers.h
+++ b/c++/tests/serializers.h
@@ -142,6 +142,28 @@ namespace QTest {
         ba += ")";
         return qstrdup(ba.data());
     }
+    
+    template<>
+    char *toString(const Kolab::Affiliation &a)
+    {
+        QByteArray ba = "Kolab::Affiliation(";
+        ba += QString::fromStdString(a.organisation()).toAscii()+ ", " + 
+        QString::fromStdString(a.logo()).toAscii()+", " +toString(a.titles()) + ", " + toString(a.roles())+  ", " + toString(a.managers()) +
+        + toString(a.assistants())  + ", " + toString(a.offices());
+        ba += ")";
+        return qstrdup(ba.data());
+    }
+    
+        template<>
+    char *toString(const std::vector<Kolab::Affiliation> &v)
+    {
+        QByteArray ba = "vector<Kolab::Affiliation>(";
+        for (int i = 0; i < v.size(); i++) {
+            ba += QByteArray(toString(v.at(i)))+ "\n";
+        }
+        ba += ")";
+        return qstrdup(ba.data());
+    }
 
  }
  
diff --git a/schemas/kolabformat-xcard.xsd b/schemas/kolabformat-xcard.xsd
index a7c4e9a..a9ae046 100644
--- a/schemas/kolabformat-xcard.xsd
+++ b/schemas/kolabformat-xcard.xsd
@@ -43,8 +43,25 @@
                         <xs:element name="kind" type="kindPropType"/>
                         <xs:element name="fn" type="fnPropType"/>
                         <xs:element name="n" type="nPropType" minOccurs="0"/>
-                        <xs:element name="member" type="memberPropType" minOccurs="0"/>
-                        <xs:element name="x-custom" type="uidPropType" minOccurs="0"/>
+                        <xs:element name="note" type="notePropType" minOccurs="0"/>
+                        <xs:element name="fburl" type="fburlPropType" minOccurs="0"/>
+                        <xs:element name="group" type="affiliationPropType" minOccurs="0" maxOccurs="unbounded"/>
+                        <xs:element name="url" type="urlPropType" minOccurs="0" maxOccurs="unbounded"/>
+                        <xs:element name="adr" type="adrPropType" minOccurs="0" maxOccurs="unbounded"/>
+                        <xs:element name="nickname" type="nicknamePropType" minOccurs="0"/>
+                        <xs:element name="related" type="relatedPropType" minOccurs="0" maxOccurs="unbounded"/>
+                        <xs:element name="bday" type="bdayPropType" minOccurs="0"/>
+                        <xs:element name="anniversary" type="anniversaryPropType" minOccurs="0"/>
+                        <xs:element name="photo" type="photoPropType" minOccurs="0"/>
+                        <xs:element name="gender" type="genderPropType" minOccurs="0"/>
+                        <xs:element name="lang" type="langPropType" minOccurs="0" maxOccurs="unbounded"/>
+                        <xs:element name="tel" type="telPropType" minOccurs="0" maxOccurs="unbounded"/>
+                        <xs:element name="impp" type="imppPropType" minOccurs="0" maxOccurs="unbounded"/>
+                        <xs:element name="email" type="emailPropType" minOccurs="0" maxOccurs="unbounded"/>
+                        <xs:element name="geo" type="geoPropType" minOccurs="0" maxOccurs="unbounded"/>
+                        <xs:element name="x-crypto" type="cryptoPropType" minOccurs="0" maxOccurs="unbounded"/>
+                        <xs:element name="member" type="memberPropType" minOccurs="0" maxOccurs="unbounded"/>
+                        <xs:element name="x-custom" type="CustomType" minOccurs="0" maxOccurs="unbounded"/>
                     </xs:sequence>
                 </xs:complexType>
             </xs:element>
diff --git a/schemas/xCard.xsd b/schemas/xCard.xsd
index ad6d723..29d8f56 100644
--- a/schemas/xCard.xsd
+++ b/schemas/xCard.xsd
@@ -29,25 +29,78 @@
       <xs:pattern value="\d{8}T\d{6}(Z|[+\-]\d\d(\d\d)?)?"/>
     </xs:restriction>
   </xs:simpleType>
-  <xs:element name="timestamp" type="xcard:DateTimeType"/>
+  <xs:element name="timestamp" type="xcard:TimeStampType"/>
 
 <!-- Parameters -->
 
   <xs:complexType name="BaseParameterType" abstract="true"/>
-  
   <xs:element name="baseParameter" type="xcard:BaseParameterType"/>
-  
   <xs:complexType name="ArrayOfParameters">
       <xs:sequence>
           <xs:element ref="xcard:baseParameter" minOccurs="0" maxOccurs="unbounded"/>
       </xs:sequence>
   </xs:complexType>
+  
+  <xs:complexType name="TextParameterType" mixed="false">
+      <xs:complexContent>
+          <xs:extension base="xcard:BaseParameterType">
+              <xs:sequence>
+                 <xs:element ref="xcard:text"/>
+              </xs:sequence>
+          </xs:extension>
+      </xs:complexContent>
+  </xs:complexType>
+  
+    <!-- WARNING: don't forget to add those, otherwise the serialization code will not be built and you're up for a long debugging session       -->
+    <xs:element name="type" type="xcard:typeParamType" substitutionGroup="xcard:baseParameter"/>
+    <xs:element name="label" type="xcard:labelParamType" substitutionGroup="xcard:baseParameter"/>
+    <xs:element name="pref" type="xcard:prefParamType" substitutionGroup="xcard:baseParameter"/>
+  
+    <xs:simpleType name="TypeValueType">
+        <xs:restriction base="xs:token">
+            <xs:enumeration value="work"/>
+            <xs:enumeration value="home"/>
+            <xs:enumeration value="text"/>
+            <xs:enumeration value="voice"/>
+            <xs:enumeration value="fax"/>
+            <xs:enumeration value="cell"/>
+            <xs:enumeration value="video"/>
+            <xs:enumeration value="pager"/>
+            <xs:enumeration value="textphone"/>
+            <xs:enumeration value="x-car"/>
+        </xs:restriction>
+    </xs:simpleType>
+    
+    <xs:complexType name="typeParamType" mixed="false">
+        <xs:complexContent>
+            <xs:extension base="xcard:BaseParameterType">
+                <xs:sequence>
+                    <xs:element name="text" type="xcard:TypeValueType" minOccurs="1" maxOccurs="unbounded" />
+                </xs:sequence>
+            </xs:extension>
+        </xs:complexContent>
+    </xs:complexType>
+    
+    <xs:complexType name="labelParamType" mixed="false">
+        <xs:complexContent>
+            <xs:extension base="xcard:TextParameterType"/>
+        </xs:complexContent>
+    </xs:complexType>
+    
+    <xs:complexType name="prefParamType" mixed="false">
+      <xs:complexContent>
+        <xs:extension base="xcard:BaseParameterType">            
+          <xs:sequence>
+            <xs:element name="integer" type="xs:string" fixed="1" />
+          </xs:sequence>
+        </xs:extension>
+      </xs:complexContent>    
+    </xs:complexType>
 
 <!-- Properties -->
   <xs:complexType name="BasePropertyType" abstract="true" >
     <xs:sequence>
-      <xs:element ref="xcard:parameters" 
-                  minOccurs="0" />
+      <xs:element ref="xcard:parameters" minOccurs="0" />
     </xs:sequence>
   </xs:complexType>
   
@@ -77,6 +130,26 @@
     </xs:complexContent>
   </xs:complexType>
   
+  <xs:complexType name="TextListPropertyType" >
+    <xs:complexContent mixed="false">
+      <xs:extension base="xcard:BasePropertyType">
+        <xs:sequence> 
+          <xs:element ref="xcard:text" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  
+  <xs:complexType name="NonEmptyTextListPropertyType" >
+    <xs:complexContent mixed="false">
+      <xs:extension base="xcard:BasePropertyType">
+        <xs:sequence> 
+          <xs:element ref="xcard:text" minOccurs="1" maxOccurs="unbounded"/>
+        </xs:sequence>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  
   <xs:complexType name="UriPropertyType" >
     <xs:complexContent mixed="false">
       <xs:extension base="xcard:BasePropertyType">
@@ -87,6 +160,19 @@
     </xs:complexContent>
   </xs:complexType>
   
+  <xs:complexType name="TextOrUriPropertyType" >
+    <xs:complexContent mixed="false">
+      <xs:extension base="xcard:BasePropertyType">
+        <xs:sequence> 
+          <xs:choice>
+            <xs:element ref="xcard:text"/>
+            <xs:element ref="xcard:uri"/>
+          </xs:choice>
+        </xs:sequence>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  
    <!-- Properties that take a date or date-time value -->
   <xs:complexType name="DateDatetimePropertyType" >
     <xs:complexContent mixed="false">
@@ -103,19 +189,12 @@
   
   <!-- Properties -->
   
-  <xs:complexType name="memberPropType">
-    <xs:complexContent mixed="false">
-      <xs:extension base="xcard:TextPropertyType"/>
-    </xs:complexContent>
-  </xs:complexType>
-  
   <xs:complexType name="kindPropType">
     <xs:complexContent mixed="false">
       <xs:extension base="xcard:TextPropertyType"/>
     </xs:complexContent>
   </xs:complexType>
   
-  
   <xs:complexType name="revPropType">
     <xs:complexContent mixed="false">
       <xs:extension base="xcard:BasePropertyType">
@@ -140,7 +219,7 @@
   
   <xs:complexType name="uidPropType">
     <xs:complexContent mixed="false">
-      <xs:extension base="xcard:UriPropertyType"/>
+      <xs:extension base="xcard:UriPropertyType"/> <!--TODO not text?-->
     </xs:complexContent>
   </xs:complexType>
   
@@ -157,12 +236,151 @@
       </xs:extension>   
     </xs:complexContent>
   </xs:complexType>
+  
+  <xs:complexType name="notePropType">
+    <xs:complexContent mixed="false">
+      <xs:extension base="xcard:TextPropertyType"/>
+    </xs:complexContent>
+  </xs:complexType>
+  
+  <xs:complexType name="fburlPropType">
+    <xs:complexContent mixed="false">
+      <xs:extension base="xcard:UriPropertyType"/>
+    </xs:complexContent>
+  </xs:complexType>
+  
+  <xs:complexType name="affiliationPropType">
+    <xs:complexContent mixed="false">
+      <xs:extension base="xcard:BasePropertyType">
+        <xs:sequence> 
+          <xs:element name="org" type="xcard:NonEmptyTextListPropertyType" />
+          <xs:element name="logo" type="xcard:UriPropertyType" />
+          <xs:element name="title" type="xcard:TextPropertyType" minOccurs="0" maxOccurs="unbounded"/>
+          <xs:element name="role" type="xcard:TextPropertyType" minOccurs="0" maxOccurs="unbounded"/>
+          <xs:element name="x-manager" type="xcard:TextPropertyType" minOccurs="0" maxOccurs="unbounded"/>
+          <xs:element name="x-assistant" type="xcard:TextPropertyType" minOccurs="0" maxOccurs="unbounded"/>
+          <xs:element name="x-office" type="xcard:TextPropertyType" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+        <xs:attribute name="name" type="xs:string" fixed="Affiliation" />
+      </xs:extension>   
+    </xs:complexContent>
+  </xs:complexType>
+  
+  <xs:complexType name="urlPropType">
+    <xs:complexContent mixed="false">
+      <xs:extension base="xcard:UriPropertyType"/>
+    </xs:complexContent>
+  </xs:complexType>
 
+  <xs:complexType name="adrPropType">
+    <xs:complexContent mixed="false">
+     <xs:extension base="xcard:BasePropertyType">
+        <xs:sequence> 
+          <xs:element name="pobox" type="xs:string" />
+          <xs:element name="ext" type="xs:string" />
+          <xs:element name="street" type="xs:string" />
+          <xs:element name="locality" type="xs:string" />
+          <xs:element name="region" type="xs:string" />
+          <xs:element name="code" type="xs:string" />
+          <xs:element name="country" type="xs:string" />
+        </xs:sequence>
+      </xs:extension>   
+    </xs:complexContent>
+  </xs:complexType>
+  
+  <xs:complexType name="nicknamePropType">
+    <xs:complexContent mixed="false">
+      <xs:extension base="xcard:TextListPropertyType"/>
+    </xs:complexContent>
+  </xs:complexType>
+  
+  <xs:complexType name="relatedPropType">
+    <xs:complexContent mixed="false">
+      <xs:extension base="xcard:TextOrUriPropertyType"/>
+    </xs:complexContent>
+  </xs:complexType>
+  
   <xs:complexType name="bdayPropType">
     <xs:complexContent mixed="false">
       <xs:extension base="xcard:DateDatetimePropertyType"/>
     </xs:complexContent>
   </xs:complexType>
+  
+  <xs:complexType name="anniversaryPropType">
+    <xs:complexContent mixed="false">
+      <xs:extension base="xcard:DateDatetimePropertyType"/>
+    </xs:complexContent>
+  </xs:complexType>
+  
+  <xs:complexType name="photoPropType">
+    <xs:complexContent mixed="false">
+      <xs:extension base="xcard:UriPropertyType"/>
+    </xs:complexContent>
+  </xs:complexType>
+  
+  <xs:simpleType name="SexType">
+        <xs:restriction base="xs:token">
+            <xs:enumeration value=""/>
+            <xs:enumeration value="M"/>
+            <xs:enumeration value="F"/>
+        </xs:restriction>
+    </xs:simpleType>
+  
+  <xs:complexType name="genderPropType">
+<!--    <xs:complexContent mixed="false">-->
+  <xs:sequence>
+      <xs:element name="sex" type="xcard:SexType" />
+    </xs:sequence>
+<!--    </xs:complexContent>-->
+  </xs:complexType>
+  
+  <xs:complexType name="langPropType">
+    <xs:complexContent mixed="false">
+      <xs:extension base="xcard:BasePropertyType">
+        <xs:sequence> 
+          <xs:element name="language-tag" type="xs:string"/>
+        </xs:sequence>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  
+  <xs:complexType name="telPropType">
+    <xs:complexContent mixed="false">
+      <xs:extension base="xcard:TextPropertyType" />
+    </xs:complexContent>
+  </xs:complexType>
+  
+  <xs:complexType name="imppPropType">
+    <xs:complexContent mixed="false">
+      <xs:extension base="xcard:UriPropertyType" />
+    </xs:complexContent>
+  </xs:complexType>
+  
+  <xs:complexType name="emailPropType">
+    <xs:complexContent mixed="false">
+      <xs:extension base="xcard:TextPropertyType" />
+    </xs:complexContent>
+  </xs:complexType>
+  
+  <xs:complexType name="geoPropType">
+    <xs:complexContent mixed="false">
+      <xs:extension base="xcard:UriPropertyType"/>
+    </xs:complexContent>
+  </xs:complexType>
+  
+  <xs:complexType name="cryptoPropType">
+    <xs:complexContent mixed="false">
+      <xs:extension base="xcard:TextPropertyType"/>
+<!-- TODO -->
+    </xs:complexContent>
+  </xs:complexType>
+  
+  <xs:complexType name="memberPropType">
+    <xs:complexContent mixed="false">
+      <xs:extension base="xcard:UriPropertyType"/>
+    </xs:complexContent>
+  </xs:complexType>
+  
 
     
 </xs:schema>


commit 9983d9df11edaefd68716bc869d4f2c373a0695b
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date:   Wed Feb 8 21:10:32 2012 +0100

    Removed some old tests.

diff --git a/c++/tests/bindingstest.cpp b/c++/tests/bindingstest.cpp
index 0b35721..3fa7703 100644
--- a/c++/tests/bindingstest.cpp
+++ b/c++/tests/bindingstest.cpp
@@ -19,75 +19,8 @@
 #include "serializers.h"
 #include <lib/utils.h>
 
-//TODO remove
-void BindingsTest::writeContact()
-{
-    Kolab::Contact contact;
-    std::cout << Kolab::writeContact(contact) << std::endl;
-}
-
-//TODO remove
-void BindingsTest::readEvent()
-{
-    const Kolab::Event &event = Kolab::readEvent("../../tests/testfiles/icalEvent.xml", true);
-    QCOMPARE(event.created(), Kolab::DateTime(2006,2,6,0,11,21,true));
-    QCOMPARE(event.start(), Kolab::DateTime("US/Eastern",2006,1,2,12,0,0));
-    
-    const Kolab::RecurrenceRule &rrule = event.recurrenceRule();
-    QCOMPARE(rrule.frequency(), Kolab::RecurrenceRule::Daily);
-    QCOMPARE(rrule.count(), 5);
-    QCOMPARE(rrule.interval(), 1);
-    
-    QCOMPARE(event.summary(), std::string("Event #2"));
-}
-
-//TODO remove
-void BindingsTest::writeEvent()
-{
-    Kolab::Event event;
-    event.setStart(Kolab::DateTime("US/Eastern", 2006,1,6,12,0,0));
-    event.setEnd(Kolab::DateTime("US/Eastern", 2006,1,8,12,0,0));
-    Kolab::RecurrenceRule rrule;
-    rrule.setFrequency(Kolab::RecurrenceRule::Daily);
-    rrule.setInterval(3);
-    rrule.setCount(5);
-    event.setRecurrenceRule(rrule);
-    std::cout << Kolab::writeEvent(event) << std::endl;
-}
 
-//TODO remove
-void BindingsTest::roundtripEvent()
-{
-    Kolab::Event event;
-    event.setStart(Kolab::DateTime("US/Eastern", 2006,1,6,12,0,0));
-    event.setEnd(Kolab::DateTime("US/Eastern", 2006,1,8,12,0,0));
-    Kolab::RecurrenceRule rrule;
-    rrule.setFrequency(Kolab::RecurrenceRule::Daily);
-    rrule.setInterval(3);
-    rrule.setCount(5);
-    event.setRecurrenceRule(rrule);
-    std::string result = Kolab::writeEvent(event);
-    std::cout << result << std::endl;
-}
-
-//TODO remove
-void BindingsTest::roundtripReverseEvent()
-{
-    const Kolab::Event &event = Kolab::readEvent("../../tests/testfiles/icalEvent.xml", true);
-    kDebug() << "-------------------";
-    std::cout << Kolab::writeEvent(event) << std::endl;
-    kDebug() << "-------------------";
-}
 
-void BindingsTest::BenchmarkRoundtrip()
-{
-    const Kolab::Event &event = Kolab::readEvent("../../tests/testfiles/icalEvent.xml", true);
-    std::string result;
-    QBENCHMARK {
-        result = Kolab::writeEvent(event);
-        Kolab::readEvent(result, false);
-    }
-}
 
 // void BindingsTest::eventCompletness_data()
 template <typename T>
@@ -343,6 +276,15 @@ void BindingsTest::BenchmarkRoundtripKCAL()
     }
 }
 
+void BindingsTest::BenchmarkRoundtrip()
+{
+    const Kolab::Event &event = Kolab::readEvent("../../tests/testfiles/icalEvent.xml", true);
+    std::string result;
+    QBENCHMARK {
+        result = Kolab::writeEvent(event);
+        Kolab::readEvent(result, false);
+    }
+}
 
 QTEST_MAIN( BindingsTest )
 
diff --git a/c++/tests/bindingstest.h b/c++/tests/bindingstest.h
index ab34319..674d201 100644
--- a/c++/tests/bindingstest.h
+++ b/c++/tests/bindingstest.h
@@ -21,14 +21,7 @@ class BindingsTest : public QObject
   Q_OBJECT
   private slots:
 
-    void writeContact();
-      
     //Kolabformat
-    void readEvent();
-    void writeEvent();
-    void roundtripEvent();
-    void roundtripReverseEvent();
-    void BenchmarkRoundtrip();
     void eventCompletness();
     void eventDuration();
     void todoCompletness();
@@ -39,6 +32,8 @@ class BindingsTest : public QObject
 
     void BenchmarkRoundtripKolab();
     void BenchmarkRoundtripKCAL();
+    void BenchmarkRoundtrip();
+
 };
 
 #endif
\ No newline at end of file





More information about the commits mailing list