| /******************************************************************************* |
| * 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. |
| *******************************************************************************/ |
| |
| package org.apache.ofbiz.sfa.vcard; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.File; |
| import java.io.FileNotFoundException; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.nio.ByteBuffer; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Locale; |
| import java.util.Map; |
| |
| 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; |
| import org.apache.ofbiz.base.util.UtilValidate; |
| import org.apache.ofbiz.entity.Delegator; |
| import org.apache.ofbiz.entity.GenericEntityException; |
| import org.apache.ofbiz.entity.GenericValue; |
| import org.apache.ofbiz.entity.condition.EntityCondition; |
| import org.apache.ofbiz.entity.condition.EntityOperator; |
| import org.apache.ofbiz.entity.util.EntityQuery; |
| import org.apache.ofbiz.entity.util.EntityUtilProperties; |
| import org.apache.ofbiz.party.party.PartyHelper; |
| import org.apache.ofbiz.party.party.PartyWorker; |
| import org.apache.ofbiz.service.DispatchContext; |
| import org.apache.ofbiz.service.GenericServiceException; |
| import org.apache.ofbiz.service.LocalDispatcher; |
| import org.apache.ofbiz.service.ServiceUtil; |
| |
| import ezvcard.Ezvcard; |
| import ezvcard.io.text.VCardReader; |
| import ezvcard.parameter.AddressType; |
| import ezvcard.parameter.EmailType; |
| import ezvcard.parameter.TelephoneType; |
| import ezvcard.property.Address; |
| import ezvcard.property.Email; |
| import ezvcard.property.FormattedName; |
| import ezvcard.property.StructuredName; |
| import ezvcard.property.Telephone; |
| |
| 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 |
| * @throws IOException |
| */ |
| public static Map<String, Object> importVCard(DispatchContext dctx, Map<String, ? extends Object> context) throws IOException { |
| LocalDispatcher dispatcher = dctx.getDispatcher(); |
| Delegator delegator = dctx.getDelegator(); |
| Locale locale = (Locale) context.get("locale"); |
| Map<String, Object> result = ServiceUtil.returnSuccess(); |
| ByteBuffer byteBuffer = (ByteBuffer) context.get("infile"); |
| byte[] inputByteArray = byteBuffer.array(); |
| InputStream in = new ByteArrayInputStream(inputByteArray); |
| 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 = ""; // TODO this is not used yet |
| |
| try (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 |
| } |
| //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, 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, address.getRegion())) |
| .cache().queryFirst(); |
| if (stateGeo != null) { |
| serviceCtx.put("stateProvinceGeoId", stateGeo.get("geoId")); |
| } |
| } |
| |
| 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 (! 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); |
| vCardReader.close(); |
| return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, "MarketingEmailFormatError", UtilMisc.toMap("firstName", structuredName.getGiven(), "lastName", structuredName.getFamily(), "emailFOrmatErrMsg", emailFormatErrMsg), locale)); |
| |
| } |
| } |
| |
| 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; |
| } |
| } |
| 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)); |
| } |
| |
| /* TODO improve this part to manage party organization */ |
| |
| 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)) { |
| for (Map.Entry<String, Object> entry : serviceContext.entrySet()) { |
| serviceCtx.put(entry.getKey(), entry.getValue()); |
| } |
| } |
| 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); |
| } |
| } |
| } catch (IOException | GenericEntityException | GenericServiceException e) { |
| Debug.logError(e, module); |
| return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, |
| "SfaImportVCardError", UtilMisc.toMap("errorString", e.getMessage()), locale)); |
| } |
| result.put("partiesCreated", partiesCreated); |
| result.put("partiesExist", partiesExist); |
| return result; |
| } |
| |
| public static Map<String, Object> exportVCard(DispatchContext dctx, Map<String, ? extends Object> context) { |
| Delegator delegator = dctx.getDelegator(); |
| String partyId = (String) context.get("partyId"); |
| Locale locale = (Locale) context.get("locale"); |
| File file = null; |
| try { |
| 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); |
| vcard.setFormattedName(fullName); |
| |
| GenericValue postalAddress = PartyWorker.findPartyLatestPostalAddress(partyId, delegator); |
| 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 (state != null) { |
| address.setRegion(state.getString("geoName")); |
| } |
| GenericValue countryGeo = postalAddress.getRelatedOne("CountryGeo", false); |
| if (countryGeo != null) { |
| 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); |
| } |
| |
| GenericValue telecomNumber = PartyWorker.findPartyLatestTelecomNumber(partyId, delegator); |
| if (telecomNumber != null) { |
| 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 |
| } |
| |
| GenericValue emailAddress = PartyWorker.findPartyLatestContactMech(partyId, "EMAIL_ADDRESS", delegator); |
| if (emailAddress != null && UtilValidate.isNotEmpty(emailAddress.getString("infoString"))) { |
| vcard.addEmail(new Email(emailAddress.getString("infoString"))); |
| } |
| |
| //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); |
| Ezvcard.write(vcard).go(file); |
| } catch (FileNotFoundException e) { |
| Debug.logError(e, module); |
| return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, |
| "SfaExportVCardErrorOpeningFile", UtilMisc.toMap("errorString", file.getAbsolutePath()), locale)); |
| } catch (IOException e) { |
| Debug.logError(e, module); |
| return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, |
| "SfaExportVCardErrorWritingFile", UtilMisc.toMap("errorString", file.getAbsolutePath()), locale)); |
| } catch (GenericEntityException e) { |
| return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, |
| "SfaExportVCardError", UtilMisc.toMap("errorString", e.getMessage()), locale)); |
| } |
| return ServiceUtil.returnSuccess(); |
| } |
| } |