Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom getter in VCardProperty #133

Open
prrvchr opened this issue May 2, 2023 · 9 comments
Open

Custom getter in VCardProperty #133

prrvchr opened this issue May 2, 2023 · 9 comments

Comments

@prrvchr
Copy link

prrvchr commented May 2, 2023

I am trying to retrieve all the values by calling a custom method on a VCardProperty. (Address, Email, Categories...)
I'm not a Java specialist, but I can't manage to do this without modifying the VCardProperty class.
Thank you for your help.

@mangstadt
Copy link
Owner

Not quite sure what you're trying to accomplish. The VCard.toString() method will generate a string that displays the contents of each property object.

VCard vcard = new VCard();
vcard.setFormattedName("John Doe");
Address adr = new Address();
adr.setStreetAddress("123 Main St");
adr.setLocality("New York");
adr.setRegion("NY");
adr.setPostalCode("12345");
vcard.addAddress(adr);
System.out.println(vcard.toString());

Prints:

version=3.0
ezvcard.property.FormattedName [ group=null | parameters={} | value=John Doe ]
ezvcard.property.Address [ group=null | parameters={} | poBoxes=[] | extendedAddresses=[] | streetAddresses=[123 Main St] | localities=[New York] | regions=[NY] | postalCodes=[12345] | countries=[] ]

@prrvchr
Copy link
Author

prrvchr commented May 3, 2023

Hi mangstadt,

In fact I am trying to import cards into a database:
To complete this task I need:

  • Treat nulls for each value independently.
  • If the value is a list extract the first value.
  • If needed convert data to string type.
  • Uniquely identify the value.
  • Accumulate the values in order to update with a batch.

And this for each value of each property, independently of each other...

If I have the possibility to use a customized getter here is the code I get to import:

  • For each property it is 1 line of code per value to process. See Address
  • For global processing, it is a loop of 30 lines

What will the code look like if I don't have a custom getter?
I'm surprised that I'm the first to claim this....

@prrvchr
Copy link
Author

prrvchr commented May 3, 2023

I would like to add that this mode of use has the advantage of separating the processing of data (class Address, Email...) from the import logic (global processing).
It makes it possible to add processing of new properties without having to modify the import logic...

EDIT: And this is important if i want the user to be able to choose which vCard properties he wants to import

@mangstadt
Copy link
Owner

You could serialize the vCard using Ezvcard.write() and store that in the database. ez-vcard is pretty good about round-tripping.

@prrvchr
Copy link
Author

prrvchr commented May 4, 2023

I need to be more specific about the purpose.
In fact, this is part of a LibreOffice extension allowing mass mailing by email with your vCard address book.

This extension vCardOOo has some particularities:

  • It is seen by LibreOffice OpenOffice as a database driver.
  • It is synchronized with an account of a NextCloud server during its use after the connection of the user to the database.
  • It is only read-only (in fact the data displayed by the driver are only HsqlDB views)
  • These views are composed of columns calculated dynamically from a configuration file allowing to choose the vcard properties to import.
  • vCard typed properties will produce as many columns in HsqlDB views as there are types and values.
  • I would like to be able to drive views and import data from configuration files.

I already have an extension that does exactly the same thing but with Google contacts: gContactOOo
And I'm about to finish the one for Microsoft Contact: mContactOOo

All these extensions are written in Python except the parsing part for vCardOOo where I use ez-vcard which is the best API on vCard. ;-)

So I admit that my need is really specific, but if I want to be able to follow my specifications I will just use my modified version of ez-vcard (all my jar libraries are embedded in the extension oxt files)

@mangstadt
Copy link
Owner

Using sub-classes can be problematic. I might do something like this instead:

public Map<String, String> getPropertiesValue(VCardProperty property) {
  if (property instanceof Address) {
    return getPropertiesValue((Address)property);
  }
  if (property instanceof Categories) {
    return getPropertiesValue((Categories)property);
  }
  //etc
}

public Map<String, String> getPropertiesValue(Address property) {
  Map<String, String> values = new LinkedHashMap<>();
  if (getPoBox() != null) values.put("poBox", getPoBox());
  //...
  return values;
}

@prrvchr
Copy link
Author

prrvchr commented May 5, 2023

Can you confirm that if I follow your recommendations then it is no longer necessary to modify the VCardProperty class, but only the Address, Email, etc. subclasses?

In the implementation of my class Address which extends the class ezvcard.property.Address what are the methods that must be implemented?

Thank you for these hints.

@mangstadt
Copy link
Owner

If your goal is to convert each vCard property object (Address, Categories, etc) to a Map<String,String> object, then you shouldn't need to subclass anything! For example:

VCard vcard = ...
for (VCardProperty property : vcard.getProperties()) {
  Map<String,String> values = getPropertiesValue(property);
}

@prrvchr
Copy link
Author

prrvchr commented May 13, 2023

Yes in fact I am looking to have a single method whatever the property to obtain 3 things:

  • property values as a Map<String,String> object.
  • the categories as a String[] array if the property is a ezvcard.property.Categories.
  • the types as a String[] array if the property is typed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants