Contacts Kit, quarter-term report

Blog post by Barrett on Mon, 2011-08-08 23:44

In these weeks i have improved the contacts kit core in order to have enough support for the formats supported. The vcard and people translators can now translate and exchange many types of field, though photo and groups aren't yet supported.

Main functionalities of the classes :
BRawContact
Their functionality is to deal with the BTranslatorRoster and keep track of basic informations, like the final format. The final destination is represented as a BPositionIO object. Basically the class find a suitable translator when initialized and provide two methods : Commit() and Read(). The first has as argument a BMessage that contain Flattened BContactFields, the second translate the source file (that can be a B_PEOPLE_FORMAT, B_VCARD_FORMAT, B_CONTACT_FORMAT) into a BMessage and return it.

BContact
BContact is the high level class representing a contact, it has the job to store informations about the raw contact, provide methods to add/remove/replace/compare the BContactFields. When initialized it use the BRawContact::Read() function to read fields from a location, and use BRawContact::Commit() to provide BContact::Commit().

BContactField and childs

BContactField is designed to support as well both People and VCard formats. The class is not intended to be used directly, but a common interface for the different types of fields that are supported. The usage of a field is defined by two enums at ContactDefs.h, it is a code that allow to specify additional informations for the data, for example if you want to add a phone number that is a fax you'll use this code :

...
BContactField* field = new BStringContactField(B_CONTACT_PHONE, value);
field->SetUsage(CONTACT_PHONE_FAX_WORK);
contact.AddField(field);
...

Another interesting function of BContactField is the Label() method, that return a friendly description of the field allowing to create easily apps like People without having care to translate a label for any field.

The class also accept any number of string parameters, the BFlattenable interface, and the BContactFieldVisitor interface.

BStringContactField
This is used for the major part of the fields, the value is represented as a BString object it is enough for fields like B_CONTACT_NAME, B_CONTACT_ORG...
BAddressContactField
It represent an address, allow to initialize a well-formed address via the constructor or alternatively the programmer can use the provided methods to set all the informations.

There are also other types of fields in the plans, one of these is the BCustomContactField.

Translators
As said while not supporting all fields, they can translate and exchange fields with a common format. There are some bugs, but the whole process is working as well and i consider this part of the project complete.

Services Kit
Unfortunately this side is not close to be completed, i have a draft and i'm working to get it enough complete.

At the moment the main classes are :
BServicesRoster
A simple class that allow to manage the addons in a more low-level manner...something similar to BTranslatorRoster giving access to the add-ons so nothing specific to the contacts support but a base for many uses (including contacts addons).

BServicesAddon
This will be the class specifying the API used by the addons, using a generic set of methods...version, name, friendlyname, services_addon_type, init and so more. Providing a Process() method used to receive data as BMessages from the server. In the same manner, will be instantiated with a messenger object to talk with the server.

BContactRoster,
basically store the BContacts provided in the address book. The user will instantiate an own object reading only the contacts they want. In future would be nice to see classes like BContactQuery...at the moment they will specify simple access to the fields stored in the address book. Internally will use an instance of the BServicesRoster talking with contacts addons.

I have created a git branch of the Haiku's tree at the url :

https://github.com/Barrett17/Haiku-services-branch

At the moment it is a plain copy of the tree, in the next day's i'll update the code since using the osdrawer repo was limitative.

Comments

Re: Contacts Kit, quarter-term report

From the 3 lines of code that i saw, i can say, that i would like that you use a little more handy c++. Why not use contact << field instead of contact.AddField(field)
And perhaps also using Manipulators instead of "SetUsage(....))".

Now that I see "AddField" which looks too similar with the "AddBlaBla" of BMessage I remembered that I quite dislike how BMessage works, i hope somebody will improve the BMessage.
Instead of BMessage message; message.AddString("lable", "value"), it's more convenient to have
message << "label" << "value". And when you want to read from a BMessage, just do
BString str1, str2;
Int32 value;
message << "string1" >> str1 << "string2" >> str2 << "integer" >> value;

Re: Contacts Kit, quarter-term report

Overloading of operators is a solution that i have considered also for BContactField, it's easy to implement since it will basically wrap AddField, IsEqual and similar methods, but at the moment it is not a priority. I don't like the BMessage suggestion, since it is too ugly than Add..() methods for me...maybe open a enhancement ticket : )

thanks for suggestions!

Re: Contacts Kit, quarter-term report

Such an approach can't work in the case of BMessage, since it supports storing multiple indices per field name, which the operator would have no way to distinguish.

I might further note, it'd also be impossible to tell if adding/finding a field succeeded or failed, since you can't distinguish "field present, but with empty value" from "field not present". Sorry if you find it inconvenient, but there are good reasons it's done the way it is.

Re: Contacts Kit, quarter-term report

there is a way (i use that). Before reading a value, you init it with the default value.
(The current FindBlaBla is overriding the value if it doesnt find anything, then you can for example a 0). And if you really want to check if the reading failed, just init the value with something that is for sure not in the message, and then check after the reading if that value has changed or not. I'm doing exactly that and it works quite good, and so my "Settings class" if very easy to use. If I want to save the settings I do the following:

Settings settings("MySettings1");
settings << "set1" << 10 << "set2" << 11.4 << "set3" << "Hello World" << endl;
Now if I want to read:
int32 i=0; float f=0; BString s = "";
settings << "set1" >> i << "set2" >> f << "set3" >> s;

Since my settings class works quite nicely, and since it is nothing else then wrapping around BMessage (and flatting and unflatting)
That means, BMessage could really easily do the same (or similar) additionally to the Find/Add, because of course Find/Add is still needed because of compatibility reasons.
(And additionally you can use own Manipulators to have more control).

Re: Contacts Kit, quarter-term report

Sure, technically it works.

But it wrongly let the code reader/maintainer thinking that there is a stream semantic behind your BMessage-based Settings object.
Which is misleading.

And the extraction interface, mixing both "stream" directions, is even more confusing.
As is the "<< endl;", which make no sense at all for a BMessage (there is no end-of-fields-set notion)
I also wonder how this pseudo-stream interface works when it comes to specify the field type, checking the field name was actually found or just retrieve a field Nth value without iterate all values before...

So, your code is shorter, yes.
But less self-explaining.

If it was all benefit and no cons, every C/C++ developer will write one-line source code since years.

The BeOS API was not after code shortness, but after keep it simple, clean and orthogonal as much as possible. Haiku team decide to follows this same road.
It doesn't forbid them to add usefull code shortcut here and there, like with the new layout *Builder class for instance. But again not for code compression but only for code readiness.

What could be great for you is not always the best for a code that is supposed / expected to be used by hopefully a larger and larger developers community, all with their own level of skills, tricks and so on. IT has to be taken care while designing an API for a large *public*.

Haiku one is not perfect, neither was BeOS API. But at least it's still cleaner and simpler than other framework, which is one requirement since day one.

Re: Contacts Kit, quarter-term report

related to the BMessage suggestion:
But you realize that it compresses the code?
In that example in one line i read 2 Strings and one Integer instead of using FindString and FindIn32

For example I wrote for my game a Settings class to store the settings, and for every different type I have to write a new overload method because of the AddBlaBla and FindBlaBla of BMessage.

Re: Contacts Kit, quarter-term report

The Services Kit is what confuses me the most... it's unrelated to last year's Services Kit, right?
http://www.haiku-os.org/blog/shisui/2010-08-19_services_kit_features_ove...

Re: Contacts Kit, quarter-term report

My project cover another area but the last year work will help us to implement web-based services like support for the Portable Contacts API. They are different bricks of the same kit.

Re: Contacts Kit, quarter-term report

Gotcha. Thanks for the clarification!

Re: Contacts Kit, quarter-term report

I gave a quick look at latest changes you've done to your repository, and so far I'm glad the idea to go with a raw contact format and move end-user formats like People and vCard files to a translator layer.

Considering the small amount of time left, I wonder if it will not be more useful to terminate this move by upgrade People and Mail apps to now use the new API, which will let in particular People app open vCard files, often found in mail attachment, as easily than it does with native People files?

You (or somebody else) could always continues later to add contact sync service, but you did what matter most before: buidling the missing Contact abstraction layer first.

Of course, if you want to continue your project after GSoC, you would be welcome! ;-)

Re: Contacts Kit, quarter-term report

Also alex agree with the way you suggested, i'm going to refactor People replacing the low level code with the new API....As you know, from the begin my intention was to continue the project after gsoc : )