Author: nmalin
Date: Fri Aug 19 17:33:15 2016
New Revision: 1756949

URL: http://svn.apache.org/viewvc?rev=1756949&view=rev
Log:
 

With the suppression of all jar to download them form jcenter, the jpim.jar 
isn't present.

To resolve this issue we can convert the current use for import/export vcard by 
an other api ez-vcard (https://github.com/mangstadt/ez-vcard) under bsd licence 
and present on jcenter.

The refactoring raise some problem on existant code, we will try with Gil to 
improve the import/export to grow data conversion to functional framework.
Some improve on import :
 * check if more than one email is present before check the prefered else take 
the one
 * check if more than one phone is present before check the prefered else take 
the one
 * check if more than one address is present before check the prefered else 
take the one
 * When you load a party by vcard, initialize a reference by fn attribute on 
PartyIndentification to escape the second loading
Will need continue improve the import like correct Organization loading, update 
process, add service to detect already party present
I also improve the screen result to display all parties loaded by the import 
and all already present.
The solution isn't perfect but it's work and compile, first purpose to delete 
jpim.jar is done :)
Related issue OFBIZ-7961

Added:
    ofbiz/trunk/applications/marketing/widget/sfa/forms/CommonForms.xml   (with 
props)
Removed:
    ofbiz/trunk/framework/base/lib/jpim-0.1.jar
Modified:
    ofbiz/trunk/applications/marketing/config/MarketingUiLabels.xml
    ofbiz/trunk/applications/marketing/data/MarketingTypeData.xml
    ofbiz/trunk/applications/marketing/servicedef/services.xml
    
ofbiz/trunk/applications/marketing/src/main/java/org/apache/ofbiz/sfa/vcard/VCard.java
    ofbiz/trunk/applications/marketing/webapp/sfa/WEB-INF/controller.xml
    ofbiz/trunk/applications/marketing/widget/sfa/CommonScreens.xml
    ofbiz/trunk/build.gradle

Modified: ofbiz/trunk/applications/marketing/config/MarketingUiLabels.xml
URL: 
http://svn.apache.org/viewvc/ofbiz/trunk/applications/marketing/config/MarketingUiLabels.xml?rev=1756949&r1=1756948&r2=1756949&view=diff
==============================================================================
--- ofbiz/trunk/applications/marketing/config/MarketingUiLabels.xml (original)
+++ ofbiz/trunk/applications/marketing/config/MarketingUiLabels.xml Fri Aug 19 
17:33:15 2016
@@ -951,6 +951,10 @@
         <value xml:lang="zh">雇员数量</value>
         <value xml:lang="zh-TW">員工數量</value>
     </property>
+    <property key="MarketingNoPartyLoad">
+        <value xml:lang="en">No party load</value>
+        <value xml:lang="fr">Aucun acteur chargé</value>
+    </property>
     <property key="MarketingOrderAmount">
         <value xml:lang="de">Auftragssumme</value>
         <value xml:lang="en">Amount of Orders</value>
@@ -995,6 +999,14 @@
         <value xml:lang="zh">上级攻势标识</value>
         <value xml:lang="zh-TW">上級活動識別</value>
     </property>
+    <property key="MarketingPartiesLoaded">
+        <value xml:lang="en">Parties Loaded</value>
+        <value xml:lang="fr">Acteurs chargés</value>
+    </property>
+    <property key="MarketingPartiesNoLoadedAlreadyExist">
+        <value xml:lang="en">Parties no loaded because they already exist on 
the system</value>
+        <value xml:lang="fr">Acteurs non chargés car déjà présent dans le 
système</value>
+    </property>
     <property key="MarketingPartyStatusReport">
         <value xml:lang="de">Statusbericht Akteur</value>
         <value xml:lang="en">Party Status Report</value>

Modified: ofbiz/trunk/applications/marketing/data/MarketingTypeData.xml
URL: 
http://svn.apache.org/viewvc/ofbiz/trunk/applications/marketing/data/MarketingTypeData.xml?rev=1756949&r1=1756948&r2=1756949&view=diff
==============================================================================
--- ofbiz/trunk/applications/marketing/data/MarketingTypeData.xml (original)
+++ ofbiz/trunk/applications/marketing/data/MarketingTypeData.xml Fri Aug 19 
17:33:15 2016
@@ -99,5 +99,6 @@ under the License.
     <StatusValidChange statusId="LEAD_ASSIGNED" statusIdTo="PARTY_DISABLED" 
transitionName="Disabled"/>
 
     <EnumerationType enumTypeId="SLSOPP_TYP_ENUM" description="Sales 
Opportunity Type"/>
-    
+
+    <PartyIdentificationType description="VCard reference origin" 
partyIdentificationTypeId="VCARD_FN_ORIGIN" parentTypeId=""/>
 </entity-engine-xml>

Modified: ofbiz/trunk/applications/marketing/servicedef/services.xml
URL: 
http://svn.apache.org/viewvc/ofbiz/trunk/applications/marketing/servicedef/services.xml?rev=1756949&r1=1756948&r2=1756949&view=diff
==============================================================================
--- ofbiz/trunk/applications/marketing/servicedef/services.xml (original)
+++ ofbiz/trunk/applications/marketing/servicedef/services.xml Fri Aug 19 
17:33:15 2016
@@ -517,10 +517,11 @@ under the License.
     <!-- VCard services -->
     <service name="importVCard" engine="java" 
location="org.apache.ofbiz.sfa.vcard.VCard" invoke="importVCard" 
transaction-timeout="7200">
         <attribute name="infile" type="java.nio.ByteBuffer" mode="IN" 
optional="false"/>
-        <attribute name="partyId" type="String" mode="OUT" optional="false"/>
         <attribute name="partyType" type="String" mode="IN" optional="true"/>
         <attribute name="serviceContext" type="Map" mode="IN" optional="true"/>
         <attribute name="serviceName" type="String" mode="IN" 
optional="false"/>
+        <attribute name="partiesCreated" type="List" mode="OUT" 
optional="false"/>
+        <attribute name="partiesExist" type="List" mode="OUT" optional="true"/>
     </service>
     <service name="exportVCard" engine="java" 
location="org.apache.ofbiz.sfa.vcard.VCard" invoke="exportVCard">
         <attribute name="partyId" type="String" mode="IN" optional="false"/>

Modified: 
ofbiz/trunk/applications/marketing/src/main/java/org/apache/ofbiz/sfa/vcard/VCard.java
URL: 
http://svn.apache.org/viewvc/ofbiz/trunk/applications/marketing/src/main/java/org/apache/ofbiz/sfa/vcard/VCard.java?rev=1756949&r1=1756948&r2=1756949&view=diff
==============================================================================
--- 
ofbiz/trunk/applications/marketing/src/main/java/org/apache/ofbiz/sfa/vcard/VCard.java
 (original)
+++ 
ofbiz/trunk/applications/marketing/src/main/java/org/apache/ofbiz/sfa/vcard/VCard.java
 Fri Aug 19 17:33:15 2016
@@ -22,21 +22,28 @@ package org.apache.ofbiz.sfa.vcard;
 import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.ByteBuffer;
+import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 
-import javax.mail.internet.AddressException;
-import javax.mail.internet.InternetAddress;
-
+import ezvcard.Ezvcard;
+import ezvcard.io.text.VCardReader;
+import ezvcard.parameter.AddressType;
+import ezvcard.parameter.TelephoneType;
+import ezvcard.parameter.EmailType;
+import ezvcard.property.Address;
+import ezvcard.property.Email;
+import ezvcard.property.FormattedName;
+import ezvcard.property.StructuredName;
+import ezvcard.property.Telephone;
 import org.apache.ofbiz.base.util.Debug;
 import org.apache.ofbiz.base.util.FileUtil;
+import org.apache.ofbiz.base.util.StringUtil;
 import org.apache.ofbiz.base.util.UtilGenerics;
 import org.apache.ofbiz.base.util.UtilMisc;
 import org.apache.ofbiz.base.util.UtilProperties;
@@ -55,142 +62,141 @@ import org.apache.ofbiz.service.GenericS
 import org.apache.ofbiz.service.LocalDispatcher;
 import org.apache.ofbiz.service.ServiceUtil;
 
-import net.wimpi.pim.Pim;
-import net.wimpi.pim.contact.basicimpl.AddressImpl;
-import net.wimpi.pim.contact.basicimpl.EmailAddressImpl;
-import net.wimpi.pim.contact.basicimpl.PhoneNumberImpl;
-import net.wimpi.pim.contact.io.ContactMarshaller;
-import net.wimpi.pim.contact.io.ContactUnmarshaller;
-import net.wimpi.pim.contact.model.Address;
-import net.wimpi.pim.contact.model.Communications;
-import net.wimpi.pim.contact.model.Contact;
-import net.wimpi.pim.contact.model.EmailAddress;
-import net.wimpi.pim.contact.model.Organization;
-import net.wimpi.pim.contact.model.OrganizationalIdentity;
-import net.wimpi.pim.contact.model.PersonalIdentity;
-import net.wimpi.pim.contact.model.PhoneNumber;
-import net.wimpi.pim.factory.ContactIOFactory;
-import net.wimpi.pim.factory.ContactModelFactory;
-
 public class VCard {
     public static final String module = VCard.class.getName();
     public static final String resourceError = "MarketingUiLabels";
 
+    /**
+     * import a vcard from byteBuffer. the reader use is ez-vcard, see 
official site https://github.com/mangstadt/ez-vcard/
+     * @param dctx
+     * @param context
+     * @return
+     */
     public static Map<String, Object> importVCard(DispatchContext dctx, 
Map<String, ? extends Object> context) {
         LocalDispatcher dispatcher = dctx.getDispatcher();
         Delegator delegator = dctx.getDelegator();
         Locale locale = (Locale) context.get("locale");
         Map<String, Object> result = ServiceUtil.returnSuccess();
-        Address workAddress = null;
-        String email = null;
-        String phone = null;
         ByteBuffer byteBuffer = (ByteBuffer) context.get("infile");
         byte[] inputByteArray = byteBuffer.array();
         InputStream in = new ByteArrayInputStream(inputByteArray);
-        String partyType = (String) context.get("partyType");
-        Boolean isGroup =  "PartyGroup".equals(partyType); // By default we 
import a Person.
         Map<String, Object> serviceCtx = new HashMap<String, Object>();
+        boolean isGroup = false;
+        List<Map<String, String>> partiesCreated = new 
ArrayList<Map<String,String>>();
+        List<Map<String, String>> partiesExist = new 
ArrayList<Map<String,String>>();
+        String partyName = "";
 
         try {
-            ContactIOFactory ciof = Pim.getContactIOFactory();
-            ContactUnmarshaller unmarshaller = 
ciof.createContactUnmarshaller();
-            unmarshaller.setStrict(false);
-            Contact[] contacts = unmarshaller.unmarshallContacts(in);
-
-            int contactsCount = 1;
-            for (Contact contact: contacts) {
-                PersonalIdentity pid = contact.getPersonalIdentity();
-                if (!isGroup) {
-                    serviceCtx.put("firstName", pid.getFirstname());
-                    serviceCtx.put("lastName", pid.getLastname());
-                }
-                for (Iterator<?> iter = contact.getAddresses(); 
iter.hasNext();) {
-                    Address address = (AddressImpl) iter.next();
-                    if (contact.isPreferredAddress(address)) {
-                        workAddress = address;
-                        break;
-                    } else if (address.isWork()) {
-                        workAddress = address;
-                        break;
-                    } else { // for now use preferred/work address only
+            VCardReader vCardReader = new VCardReader(in);
+            ezvcard.VCard vcard = null;
+            while ((vcard = vCardReader.readNext()) != null) {
+
+                //Todo create a generic service to resolve duplicate party
+                FormattedName formattedName = vcard.getFormattedName();
+                if (formattedName != null) {
+                    String refCardId = formattedName.getValue();
+                    GenericValue partyIdentification = 
EntityQuery.use(delegator).from("PartyIdentification").where("partyIdentificationTypeId",
 "VCARD_FN_ORIGIN", "idValue", refCardId).queryFirst();
+                    if (partyIdentification != null) {
+                        partiesExist.add(UtilMisc.toMap("partyId", 
(String)partyIdentification.get("partyId")));
                         continue;
                     }
+                    //TODO manage update
                 }
-                if (UtilValidate.isNotEmpty(workAddress)) {
-                    serviceCtx.put("address1", workAddress.getStreet());
-                    serviceCtx.put("city", workAddress.getCity());
-                    serviceCtx.put("postalCode", workAddress.getPostalCode());
+                //check if it's already load
+                isGroup = false;
+                if (vcard.getKind() != null) isGroup = 
vcard.getKind().isGroup();
 
+                StructuredName structuredName = vcard.getStructuredName();
+                if (UtilValidate.isEmpty(structuredName)) continue;
+                if (!isGroup) {
+                    serviceCtx.put("firstName", structuredName.getGiven());
+                    serviceCtx.put("lastName", structuredName.getFamily());
+                    partyName = structuredName.getGiven() + " " + 
structuredName.getFamily();
+                }
+
+                // Resolve all postal Address
+                for (Address address : vcard.getAddresses()) {
+                    boolean workAddress = false;
+                    for (AddressType addressType : address.getTypes()) {
+                        if (AddressType.PREF.equals(addressType) || 
AddressType.WORK.equals(addressType)) {
+                            workAddress = true;
+                            break;
+                        }
+                    }
+                    if (! workAddress) continue;
+
+                    serviceCtx.put("address1", address.getStreetAddressFull());
+                    serviceCtx.put("city", address.getLocality());
+                    serviceCtx.put("postalCode", address.getPostalCode());
                     GenericValue countryGeo = 
EntityQuery.use(delegator).from("Geo")
                             .where(EntityCondition.makeCondition("geoTypeId", 
EntityOperator.EQUALS, "COUNTRY"),
-                                    EntityCondition.makeCondition("geoName", 
EntityOperator.LIKE, workAddress.getCountry()))
+                                    EntityCondition.makeCondition("geoName", 
EntityOperator.LIKE, address.getCountry()))
                             .cache().queryFirst();
                     if (countryGeo != null) {
                         serviceCtx.put("countryGeoId", 
countryGeo.get("geoId"));
                     }
-
                     GenericValue stateGeo = 
EntityQuery.use(delegator).from("Geo")
                             .where(EntityCondition.makeCondition("geoTypeId", 
EntityOperator.EQUALS, "STATE"),
-                            EntityCondition.makeCondition("geoName", 
EntityOperator.LIKE, workAddress.getRegion()))
+                                    EntityCondition.makeCondition("geoName", 
EntityOperator.LIKE, address.getRegion()))
                             .cache().queryFirst();
                     if (stateGeo != null) {
                         serviceCtx.put("stateProvinceGeoId", 
stateGeo.get("geoId"));
                     }
                 }
 
-                if (!isGroup) {
-                    Communications communications = 
contact.getCommunications();
-                    if (UtilValidate.isNotEmpty(communications)) {
-                        for (Iterator<?> iter = 
communications.getEmailAddresses(); iter.hasNext();) {
-                            EmailAddress emailAddress = (EmailAddressImpl) 
iter.next();
-                            if 
(communications.isPreferredEmailAddress(emailAddress)) {
-                                email = emailAddress.getAddress();
-                                break;
-                            } else {
-                                email = emailAddress.getAddress();
+                int nbEmailAddr = (vcard.getEmails() != null) ? 
vcard.getEmails().size() : 0;
+                for (Email email : vcard.getEmails()) {
+                    if (nbEmailAddr > 1) {
+                        boolean workEmail = false;
+                        for (EmailType emailType : email.getTypes()) {
+                            if (EmailType.PREF.equals(emailType) || 
EmailType.WORK.equals(emailType)) {
+                                workEmail = true;
                                 break;
                             }
                         }
-                        if (UtilValidate.isNotEmpty(email)) {
-                                  InternetAddress emailAddr;
-                                try {
-                                    emailAddr = new InternetAddress(email);
-                                    emailAddr.validate();
-                                } catch (AddressException e) {
-                                    String emailFOrmatErrMsg = 
UtilProperties.getMessage(resourceError, "SfaImportVCardEmailFormatError", 
locale);
-                                    return 
ServiceUtil.returnError(pid.getFirstname() + " " + pid.getLastname() + " has " 
+ emailFOrmatErrMsg);
-                                }
-                            serviceCtx.put("emailAddress", email);
-                        }
-                        for (Iterator<?> iter = 
communications.getPhoneNumbers(); iter.hasNext();) {
-                            PhoneNumber phoneNumber = (PhoneNumberImpl) 
iter.next();
-                            if (phoneNumber.isPreferred()) {
-                                phone = phoneNumber.getNumber();
-                                break;
-                            } else if (phoneNumber.isWork()) {
-                                phone = phoneNumber.getNumber();
+                        if (! workEmail) continue;
+                    }
+                    String emailAddr = email.getValue();
+                    if (UtilValidate.isEmail(emailAddr)) {
+                        serviceCtx.put("emailAddress", emailAddr);
+                    } else {
+                        //TODO change uncorrect labellisation
+                        String emailFormatErrMsg = 
UtilProperties.getMessage(resourceError, "SfaImportVCardEmailFormatError", 
locale);
+                        return 
ServiceUtil.returnError(structuredName.getGiven() + " " + 
structuredName.getFamily() + " has " + emailFormatErrMsg);
+                    }
+                }
+
+                int nbPhone = (vcard.getTelephoneNumbers() != null) ? 
vcard.getTelephoneNumbers().size() : 0;
+                for (Telephone phone : vcard.getTelephoneNumbers()) {
+                    if (nbPhone > 1) {
+                        boolean workPhone = false;
+                        for (TelephoneType phoneType : phone.getTypes()) {
+                            if (TelephoneType.PREF.equals(phoneType) || 
TelephoneType.WORK.equals(phoneType)) {
+                                workPhone = true;
                                 break;
-                            } else { // for now use only preferred/work phone 
numbers
-                                continue;
                             }
                         }
-                        if (UtilValidate.isNotEmpty(phone)) {
-                            String[] numberParts = phone.split("\\D");
-                            StringBuilder telNumber = new StringBuilder("");
-                            for (String number: numberParts) {
-                                if (number != "") {
-                                    telNumber.append(number);
-                                }
-                            }
-                            serviceCtx.put("areaCode", telNumber.substring(0, 
3));
-                            serviceCtx.put("contactNumber", 
telNumber.substring(3));
+                        if (! workPhone) continue;
+                    }
+                    String phoneAddr = phone.getText();
+                    boolean internationalPhone = phoneAddr.startsWith("+") || 
phoneAddr.startsWith("00");
+                    phoneAddr = StringUtil.removeNonNumeric(phoneAddr);
+                    int indexLocal = 0;
+                    if (internationalPhone) {
+                        indexLocal = 4;
+                        if (!phoneAddr.startsWith("00")) {
+                            phoneAddr = phoneAddr.concat("00");
                         }
+                        serviceCtx.put("areaCode", phoneAddr.substring(0, 
indexLocal));
                     }
+                    serviceCtx.put("contactNumber", 
phoneAddr.substring(indexLocal));
                 }
-                OrganizationalIdentity  oid = 
contact.getOrganizationalIdentity();
+
+                /* TODO improve this part to manage party organization
+                Organization organization = vcard.getOrganization();
                 // Useful when creating a contact with more than OOTB
-                if (!isGroup && oid != null && oid.getTitle() != null) {
-                    String personalTitle = 
oid.getTitle().replace("\\","").replaceAll("\uFFFD", " ");
+                if (!isGroup && organization != null && oid.getTitle() != 
null) {
+                    String personalTitle = 
organization..getTitle().replace("\\","").replaceAll("\uFFFD", " ");
                     if (personalTitle.length() > 100) {
                         personalTitle = oid.getTitle().replace("\\", 
"").replaceAll("\uFFFD", " ").substring(0, 100);
                     }
@@ -204,55 +210,37 @@ public class VCard {
                         Organization org = oid.getOrganization();
                         serviceCtx.put("groupName", 
org.getName().replace("\\", ""));
                     }
-                }
+                }*/
 
                 GenericValue userLogin = (GenericValue) 
context.get("userLogin");
                 serviceCtx.put("userLogin", userLogin);
                 String serviceName = (String) context.get("serviceName");
                 Map<String, Object> serviceContext = 
UtilGenerics.cast(context.get("serviceContext"));
-                if(UtilValidate.isNotEmpty(serviceContext)) {
+                if (UtilValidate.isNotEmpty(serviceContext)) {
                     for (Map.Entry<String, Object> entry : 
serviceContext.entrySet()) {
                         serviceCtx.put(entry.getKey(), entry.getValue());
                     }
                 }
-                List<GenericValue> persons = 
EntityQuery.use(delegator).from("Person").where(
-                        "firstName", serviceCtx.get("firstName"),
-                        "lastName", serviceCtx.get("lastName")
-                        ).queryList();
-                boolean blockPerson = false;
-                for (GenericValue person: persons) {
-                    GenericValue partyStatus = 
EntityQuery.use(delegator).from("PartyStatus").where(
-                            "partyId", 
person.get("partyId")).orderBy("-statusDate").queryFirst();
-                    if (!partyStatus.get("statusId").equals("PARTY_DISABLED")) 
{
-                        blockPerson = true;
-                    }
-                }
-                if (!blockPerson) {
-                    String nameMissingErrMsg = 
UtilProperties.getMessage(resourceError, "SfaImportVcardNameMissingError", 
locale);
-                    if (!isGroup && serviceCtx.get("lastName") == null) {
-                        return 
ServiceUtil.returnError(serviceCtx.get("firstName") + " " + nameMissingErrMsg);
-                    }
-                    if (!isGroup && serviceCtx.get("firstName") == null) {
-                        return 
ServiceUtil.returnError(serviceCtx.get("lastName") + " " + nameMissingErrMsg);
-                    }
-                    Map<String, Object> resp = dispatcher.runSync(serviceName, 
serviceCtx);
-                    result.put("partyId", resp.get("partyId"));
-                }
-                if (result.get("partyId") == null && contactsCount == 
contacts.length) {
-                    String duplicatedErrMsg = 
UtilProperties.getMessage(resourceError, "SfaImportVcardDuplicatedVcardError", 
locale);
-                    return ServiceUtil.returnError(duplicatedErrMsg);
+                Map<String, Object> resp = dispatcher.runSync(serviceName, 
serviceCtx);
+                partiesCreated.add(UtilMisc.toMap("partyId", (String) 
resp.get("partyId")));
+
+                if (formattedName != null) {
+                    //store the origin creation
+                    Map<String, Object> createPartyIdentificationMap = 
dctx.makeValidContext("createPartyIdentification", "IN", context);
+                    createPartyIdentificationMap.put("partyId", 
resp.get("partyId"));
+                    
createPartyIdentificationMap.put("partyIdentificationTypeId", 
"VCARD_FN_ORIGIN");
+                    createPartyIdentificationMap.put("idValue", 
formattedName.getValue());
+                    resp = dispatcher.runSync("createPartyIdentification", 
createPartyIdentificationMap);
                 }
-                contactsCount++;
             }
-        } catch (GenericEntityException e) {
-            Debug.logError(e, module);
-            return 
ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
-                    "SfaImportVCardError", UtilMisc.toMap("errorString", 
e.getMessage()), locale));
-        } catch (GenericServiceException e) {
+            vCardReader.close();
+        } catch (IOException | GenericEntityException | 
GenericServiceException e) {
             Debug.logError(e, module);
-            return 
ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
+            return 
ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
                     "SfaImportVCardError", UtilMisc.toMap("errorString", 
e.getMessage()), locale));
         }
+        result.put("partiesCreated", partiesCreated);
+        result.put("partiesExist", partiesExist);
         return result;
     }
 
@@ -262,61 +250,60 @@ public class VCard {
         Locale locale = (Locale) context.get("locale");
         File file = null;
         try {
-            ContactModelFactory cmf = Pim.getContactModelFactory();
-            Contact contact = cmf.createContact();
-
-            PersonalIdentity pid = cmf.createPersonalIdentity();
+            ezvcard.VCard vcard = new ezvcard.VCard();
+            StructuredName structuredName = new StructuredName();
+            GenericValue person = 
EntityQuery.use(delegator).from("Person").where("partyId", partyId).queryOne();
+            if (person != null) {
+                if (UtilValidate.isNotEmpty(person.getString("firstName")))
+                    structuredName.setGiven(person.getString("firstName"));
+                if (UtilValidate.isNotEmpty(person.getString("lastName")))
+                    structuredName.setFamily(person.getString("lastName"));
+                vcard.setStructuredName(structuredName);
+            }
             String fullName = PartyHelper.getPartyName(delegator, partyId, 
false);
-            String[] name = fullName.split("\\s");
-            pid.setFirstname(name[0]);
-            pid.setLastname(name[1]);
-            contact.setPersonalIdentity(pid);
+            vcard.setFormattedName(fullName);
 
             GenericValue postalAddress = 
PartyWorker.findPartyLatestPostalAddress(partyId, delegator);
-            Address address = cmf.createAddress();
-            address.setStreet(postalAddress.getString("address1"));
-            address.setCity(postalAddress.getString("city"));
-
-            address.setPostalCode(postalAddress.getString("postalCode"));
-            GenericValue state = 
postalAddress.getRelatedOne("StateProvinceGeo", false);
-            if (UtilValidate.isNotEmpty(state)) {
-                address.setRegion(state.getString("geoName"));
-            }
-            GenericValue countryGeo = 
postalAddress.getRelatedOne("CountryGeo", false);
-            if (UtilValidate.isNotEmpty(countryGeo)) {
-                String country = postalAddress.getRelatedOne("CountryGeo", 
false).getString("geoName");
-                address.setCountry(country);
-                address.setWork(true); // this can be better set by checking 
contactMechPurposeTypeId
+            if (postalAddress != null) {
+                Address address =  new Address();
+                address.setStreetAddress(postalAddress.getString("address1"));
+                address.setLocality(postalAddress.getString("city"));
+                address.setPostalCode(postalAddress.getString("postalCode"));
+                GenericValue state = 
postalAddress.getRelatedOne("StateProvinceGeo", false);
+                if (UtilValidate.isNotEmpty(state)) {
+                    address.setRegion(state.getString("geoName"));
+                }
+                GenericValue countryGeo = 
postalAddress.getRelatedOne("CountryGeo", false);
+                if (UtilValidate.isNotEmpty(countryGeo)) {
+                    String country = postalAddress.getRelatedOne("CountryGeo", 
false).getString("geoName");
+                    address.setCountry(country);
+                    address.getTypes().add(AddressType.WORK);;
+                    //TODO : this can be better set by checking 
contactMechPurposeTypeId
+                }
+                vcard.addAddress(address);
             }
-            contact.addAddress(address);
-
-            Communications communication = cmf.createCommunications();
-            contact.setCommunications(communication);
 
-            PhoneNumber number = cmf.createPhoneNumber();
             GenericValue telecomNumber = 
PartyWorker.findPartyLatestTelecomNumber(partyId, delegator);
             if (UtilValidate.isNotEmpty(telecomNumber)) {
-                number.setNumber(telecomNumber.getString("areaCode") + 
telecomNumber.getString("contactNumber"));
-                number.setWork(true); // this can be better set by checking 
contactMechPurposeTypeId
-                communication.addPhoneNumber(number);
+                Telephone tel = new 
Telephone(telecomNumber.getString("areaCode") + 
telecomNumber.getString("contactNumber"));
+                tel.getTypes().add(TelephoneType.WORK);
+                vcard.addTelephoneNumber(tel);
+                //TODO : this can be better set by checking 
contactMechPurposeTypeId
             }
-            EmailAddress email = cmf.createEmailAddress();
+
             GenericValue emailAddress = 
PartyWorker.findPartyLatestContactMech(partyId, "EMAIL_ADDRESS", delegator);
-            if (UtilValidate.isNotEmpty(emailAddress.getString("infoString"))) 
{
-                email.setAddress(emailAddress.getString("infoString"));
-                communication.addEmailAddress(email);
+            if (emailAddress != null && 
UtilValidate.isNotEmpty(emailAddress.getString("infoString"))) {
+                vcard.addEmail(new 
Email(emailAddress.getString("infoString")));
             }
-            ContactIOFactory ciof = Pim.getContactIOFactory();
-            ContactMarshaller marshaller = ciof.createContactMarshaller();
+
+            //TODO : convert to directdownload of a vcf file
             String saveToDirectory = 
EntityUtilProperties.getPropertyValue("sfa", "save.outgoing.directory", "", 
delegator);
             if (UtilValidate.isEmpty(saveToDirectory)) {
                 saveToDirectory = System.getProperty("ofbiz.home");
             }
             String saveToFilename = fullName + ".vcf";
             file = FileUtil.getFile(saveToDirectory + "/" + saveToFilename);
-            FileOutputStream outputStream = new FileOutputStream(file);
-            marshaller.marshallContact(outputStream, contact);
-            outputStream.close();
+            Ezvcard.write(vcard).go(file);
         } catch (FileNotFoundException e) {
             Debug.logError(e, module);
             return 
ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 

Modified: ofbiz/trunk/applications/marketing/webapp/sfa/WEB-INF/controller.xml
URL: 
http://svn.apache.org/viewvc/ofbiz/trunk/applications/marketing/webapp/sfa/WEB-INF/controller.xml?rev=1756949&r1=1756948&r2=1756949&view=diff
==============================================================================
--- ofbiz/trunk/applications/marketing/webapp/sfa/WEB-INF/controller.xml 
(original)
+++ ofbiz/trunk/applications/marketing/webapp/sfa/WEB-INF/controller.xml Fri 
Aug 19 17:33:15 2016
@@ -131,7 +131,7 @@ under the License.
     <request-map uri="createLeadFromVCard">
         <security https="true" auth="true"/>
         <event type="service" invoke="importVCard"/>
-        <response name="success" type="request" value="viewprofile"/><!-- What 
would be the view in case a vCard has more than one contact -->
+        <response name="success" type="view" 
value="ViewPartiesCreatedByVCard"/>
         <response name="error" type="view" value="NewLeadFromVCard"/>
     </request-map>
     <request-map uri="quickAddLead">
@@ -180,7 +180,7 @@ under the License.
     <request-map uri="createContactFromVCard">
         <security https="true" auth="true"/>
         <event type="service" invoke="importVCard"/>
-        <response name="success" type="request" value="viewprofile"/><!-- What 
would be the view in case a vCard contains more than one contact -->
+        <response name="success" type="view" 
value="ViewPartiesCreatedByVCard"/>
         <response name="error" type="view" value="NewContactFromVCard"/>
     </request-map>
     <request-map uri="createVCardFromContact">
@@ -276,6 +276,7 @@ under the License.
     <!-- View Mappings -->
     <view-map name="main" type="screen" 
page="component://marketing/widget/sfa/CommonScreens.xml#main"/>
     <view-map name="viewprofile" type="screen" 
page="component://marketing/widget/sfa/CommonScreens.xml#ViewProfile"/>
+    <view-map name="ViewPartiesCreatedByVCard" type="screen" 
page="component://marketing/widget/sfa/CommonScreens.xml#ViewPartiesCreatedByVCard"/>
 
     <view-map name="FindSalesOpportunity" type="screen" 
page="component://marketing/widget/sfa/OpportunityScreens.xml#FindSalesOpportunity"/>
     <view-map name="ViewSalesOpportunity" type="screen" 
page="component://marketing/widget/sfa/OpportunityScreens.xml#ViewSalesOpportunity"/>

Modified: ofbiz/trunk/applications/marketing/widget/sfa/CommonScreens.xml
URL: 
http://svn.apache.org/viewvc/ofbiz/trunk/applications/marketing/widget/sfa/CommonScreens.xml?rev=1756949&r1=1756948&r2=1756949&view=diff
==============================================================================
--- ofbiz/trunk/applications/marketing/widget/sfa/CommonScreens.xml (original)
+++ ofbiz/trunk/applications/marketing/widget/sfa/CommonScreens.xml Fri Aug 19 
17:33:15 2016
@@ -60,7 +60,7 @@ under the License.
                 <decorator-screen name="main-decorator" 
location="${parameters.mainDecoratorLocation}">
                     <decorator-section name="left-column">
                         <include-screen name="leftbar"/>
-                    </decorator-section>                    
+                    </decorator-section>
                     <decorator-section name="body">
                         <include-portal-page id="${parameters.portalPageId}"/>
                     </decorator-section>
@@ -96,7 +96,7 @@ under the License.
                     </decorator-section>
                     <decorator-section name="left-column">
                         <include-screen name="leftbar"/>
-                    </decorator-section>                    
+                    </decorator-section>
                     <decorator-section name="body">
                         <decorator-section-include name="body"/>
                     </decorator-section>
@@ -344,6 +344,41 @@ under the License.
             </widgets>
         </section>
     </screen>
+    <screen name="ViewPartiesCreatedByVCard">
+        <section>
+            <widgets>
+                <decorator-screen name="CommonPartyDecorator" 
location="${parameters.mainDecoratorLocation}">
+                    <decorator-section name="body">
+                        <section>
+                            <condition>
+                                <or>
+                                    <not><if-empty 
field="parameters.partiesCreated"/></not>
+                                    <not><if-empty 
field="parameters.partiesExist"/></not>
+                                </or>
+                            </condition>
+                            <actions>
+                                <set field="partiesCreated" 
from-field="parameters.partiesCreated"/>
+                                <set field="partiesExist" 
from-field="parameters.partiesExist"/>
+                            </actions>
+                            <widgets>
+                                <screenlet 
title="${uiLabelMap.MarketingPartiesLoaded}">
+                                    <include-grid 
name="ViewPartiesCreatedByVCard" 
location="component://marketing/widget/sfa/forms/CommonForms.xml"/>
+                                </screenlet>
+                                <screenlet 
title="${uiLabelMap.MarketingPartiesNoLoadedAlreadyExist}">
+                                    <include-grid 
name="ViewPartiesExistInVCard" 
location="component://marketing/widget/sfa/forms/CommonForms.xml"/>
+                                </screenlet>
+                            </widgets>
+                            <fail-widgets>
+                                <container>
+                                    <label 
style="h3">${uiLabelMap.MarketingNoPartyLoad}</label>
+                                </container>
+                            </fail-widgets>
+                        </section>
+                    </decorator-section>
+                </decorator-screen>
+            </widgets>
+        </section>
+    </screen>
     <screen name="CommonCommunicationEventDecorator">
         <section>
             <actions>
@@ -381,7 +416,7 @@ under the License.
                             </decorator-section>
                             <decorator-section name="left-column">
                                 <include-screen name="leftbar"/>
-                            </decorator-section>                    
+                            </decorator-section>
                             <decorator-section name="body">
                                 <include-menu name="OpportunitySubTabBar" 
location="component://marketing/widget/sfa/SfaMenus.xml"/>
                                 <decorator-section-include name="body"/>
@@ -401,7 +436,7 @@ under the License.
                     </decorator-section>
                     <decorator-section name="left-column">
                         <include-screen name="leftbar"/>
-                    </decorator-section>                    
+                    </decorator-section>
                     <decorator-section name="body">
                         <include-menu name="AccountSubTabBar" 
location="component://marketing/widget/sfa/SfaMenus.xml"/>
                         <decorator-section-include name="body"/>
@@ -419,7 +454,7 @@ under the License.
                     </decorator-section>
                     <decorator-section name="left-column">
                         <include-screen name="leftbar"/>
-                    </decorator-section>                    
+                    </decorator-section>
                     <decorator-section name="body">
                         <include-menu name="ContactSubTabBar" 
location="component://marketing/widget/sfa/SfaMenus.xml"/>
                         <decorator-section-include name="body"/>
@@ -463,7 +498,7 @@ under the License.
                     </decorator-section>
                     <decorator-section name="left-column">
                         <include-screen name="leftbar"/>
-                    </decorator-section>                    
+                    </decorator-section>
                     <decorator-section name="body">
                         <include-menu name="EventSubTabBar" 
location="component://marketing/widget/sfa/SfaMenus.xml"/>
                         <decorator-section-include name="body"/>

Added: ofbiz/trunk/applications/marketing/widget/sfa/forms/CommonForms.xml
URL: 
http://svn.apache.org/viewvc/ofbiz/trunk/applications/marketing/widget/sfa/forms/CommonForms.xml?rev=1756949&view=auto
==============================================================================
--- ofbiz/trunk/applications/marketing/widget/sfa/forms/CommonForms.xml (added)
+++ ofbiz/trunk/applications/marketing/widget/sfa/forms/CommonForms.xml Fri Aug 
19 17:33:15 2016
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+
+<forms xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
+        xmlns="http://ofbiz.apache.org/Widget-Form"; 
xsi:schemaLocation="http://ofbiz.apache.org/Widget-Form 
http://ofbiz.apache.org/dtds/widget-form.xsd";>
+
+    <grid name="ViewPartiesCreatedByVCard" list-name="partiesCreated" 
header-row-style="header-row" default-table-style="basic-table">
+        <row-actions>
+            <entity-one entity-name="Party" value-field="party" 
use-cache="true"/>
+            <set field="partyName" 
value="${groovy:org.apache.ofbiz.party.party.PartyHelper.getPartyName(party, 
true)}"/>
+            <entity-and entity-name="PartyAndContactMech" 
list="emailAddresses">
+                <field-map field-name="partyId"/>
+                <field-map field-name="contactMechTypeId" 
value="EMAIL_ADDRESS"/>
+            </entity-and>
+            <entity-and entity-name="PartyAndContactMech" 
list="telecomNumbers">
+                <field-map field-name="partyId"/>
+                <field-map field-name="contactMechTypeId" 
value="TELECOM_NUMBER"/>
+            </entity-and>
+            <set field="telecomNumber" from-field="telecomNumbers[0]" 
type="Object"/>
+            <entity-and entity-name="PartyAndContactMech" 
list="postalAddresses">
+                <field-map field-name="partyId"/>
+                <field-map field-name="contactMechTypeId" 
value="POSTAL_ADDRESS"/>
+            </entity-and>
+            <set field="postalAddress" from-field="postalAddresses[0]" 
type="Object"/>
+        </row-actions>
+        <field name="partyId" title="${uiLabelMap.PartyPartyId}">
+            <hyperlink target="viewprofile" description="${partyName} 
[${partyId}]" target-window="_blank">
+                <parameter param-name="partyId"/>
+                <parameter param-name="roleTypeId"/>
+            </hyperlink>
+        </field>
+        <field name="emailAddress"><display 
description="${emailAddresses[0].infoString}"/></field>
+        <field name="telecomNumber" title="${uiLabelMap.PartyPhoneNumber}">
+            <display description="${telecomNumber.tnCountryCode} 
${telecomNumber.tnAreaCode} ${telecomNumber.tnContactNumber} 
${telecomNumber.tnAskForName}"/>
+        </field>
+        <field name="city"><display 
description="${postalAddress.paCity}"/></field>
+    </grid>
+    <grid name="ViewPartiesExistInVCard" list-name="partiesExist" 
extends="ViewPartiesCreatedByVCard"/>
+
+</forms>

Propchange: ofbiz/trunk/applications/marketing/widget/sfa/forms/CommonForms.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: ofbiz/trunk/applications/marketing/widget/sfa/forms/CommonForms.xml
------------------------------------------------------------------------------
    svn:keywords = Date Rev Author URL Id

Propchange: ofbiz/trunk/applications/marketing/widget/sfa/forms/CommonForms.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml

Modified: ofbiz/trunk/build.gradle
URL: 
http://svn.apache.org/viewvc/ofbiz/trunk/build.gradle?rev=1756949&r1=1756948&r2=1756949&view=diff
==============================================================================
--- ofbiz/trunk/build.gradle (original)
+++ ofbiz/trunk/build.gradle Fri Aug 19 17:33:15 2016
@@ -66,6 +66,7 @@ configurations {
 dependencies {
     // general framework compile libs
     compile 'apache-xerces:xercesImpl:2.9.1'
+    compile 'com.googlecode.ez-vcard:ez-vcard:0.9.10'
     compile 'com.google.zxing:core:3.2.1'
     compile 
'com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.0'
     compile 
'com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer:20160628.1'
@@ -770,6 +771,7 @@ def createOfbizCommandTask(taskName, arg
         arguments.each { argument ->
             args argument
         }
+
     }
 }
 



Reply via email to