/******************************************************************************* * Copyright 2012 Christian Ternes and Thorsten Volland * * Licensed 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.businessmanager.service; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.net.URI; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; import net.fortuna.ical4j.model.Date; import net.fortuna.ical4j.model.ValidationException; import net.fortuna.ical4j.vcard.Group; import net.fortuna.ical4j.vcard.Property; import net.fortuna.ical4j.vcard.VCard; import net.fortuna.ical4j.vcard.VCardOutputter; import net.fortuna.ical4j.vcard.parameter.Type; import net.fortuna.ical4j.vcard.property.BDay; import net.fortuna.ical4j.vcard.property.Fn; import net.fortuna.ical4j.vcard.property.N; import net.fortuna.ical4j.vcard.property.Note; import net.fortuna.ical4j.vcard.property.Org; import net.fortuna.ical4j.vcard.property.ProdId; import net.fortuna.ical4j.vcard.property.SortString; import net.fortuna.ical4j.vcard.property.Title; import net.fortuna.ical4j.vcard.property.Url; import net.fortuna.ical4j.vcard.property.Version; import org.apache.commons.lang3.Validate; import org.businessmanager.dao.ContactDao; import org.businessmanager.domain.Activity; import org.businessmanager.domain.Activity.ActivityType; import org.businessmanager.domain.Address; import org.businessmanager.domain.Contact; import org.businessmanager.domain.ContactItem; import org.businessmanager.domain.ContactItem.Scope; import org.businessmanager.domain.Email; import org.businessmanager.domain.Fax; import org.businessmanager.domain.ModificationType; import org.businessmanager.domain.Phone; import org.businessmanager.domain.Website; import org.businessmanager.domain.security.User; import org.businessmanager.service.security.SpringSecurityService; import org.businessmanager.web.bean.ContactActivityBean; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service @Transactional public class ContactServiceImpl implements ContactService { private Logger logger = LoggerFactory.getLogger(getClass()); @Autowired private ContactDao contactDao; @Autowired private ActivityService activityService; @Autowired private SpringSecurityService securityService; private VCardOutputter vcardWriter = new VCardOutputter(); @Override public Contact saveContact(Contact contact) { Validate.notNull(contact, "Parameter contact must not be null!"); if (contact.getId() == null) { contact = contactDao.save(contact); saveActivity(contact.getId(), ModificationType.CREATE, contact.getFullname()); return contact; } else { contact = contactDao.update(contact); saveActivity(contact.getId(), ModificationType.UPDATE, contact.getFullname()); return contact; } } @Override public List<Contact> getContacts() { return contactDao.findAll(); } @Override public void deleteContact(Contact contact) { Validate.notNull(contact, "Parameter contact must not be null!"); saveActivity(contact.getId(), ModificationType.DELETE, contact.getFullname()); contactDao.remove(contact); } @Override public ContactItem mergeContactItem(ContactItem contactItem) { Validate.notNull(contactItem); if (contactItem instanceof Email) { return contactDao.mergeEmail((Email) contactItem); } else if (contactItem instanceof Phone) { return contactDao.mergePhone((Phone) contactItem); } else if (contactItem instanceof Fax) { return contactDao.mergeFax((Fax) contactItem); } else if (contactItem instanceof Website) { return contactDao.mergeWebsite((Website) contactItem); } return null; } @Override public void removeContactItem(Long id) { contactDao.removeContactItem(id); } @Override public Contact getContactById(Long id) { return contactDao.findById(id); } @Override public List<Contact> fullTextSearchContact(String searchString) { return contactDao.fullTextSearchContact(searchString); } private void saveActivity(Long sourceId, ModificationType modType, String contactName) { User currentUser = securityService.getLoggedInUser(); ContactActivityBean activityData = new ContactActivityBean(currentUser.getUsername(), modType, contactName); Activity activity = new Activity(currentUser.getId(), ActivityType.CONTACT); activity.setSourceId(sourceId); activity.setData(activityData.toJson()); activityService.saveActivity(activity); } @Override public OutputStream getAsVCard(Contact contact) { Validate.notNull(contact); List<Property> props = new ArrayList<Property>(); props.add(new Version("2.1")); props.add(new N(contact.getLastname(), contact.getFirstname(), null, null, null)); props.add(new Fn(contact.getFullname())); props.add(new SortString(contact.getLastname())); List<Email> emailList = contact.getEmailList(); for (Email email : emailList) { if(Scope.PRIVATE.equals(email.getScope())) { props.add(new net.fortuna.ical4j.vcard.property.Email(Group.HOME, email.getEmail())); } else if(Scope.COMMERCIAL.equals(email.getScope())) { props.add(new net.fortuna.ical4j.vcard.property.Email(Group.WORK, email.getEmail())); } } if(contact.getBirthday() != null) { Date iCalDate = new Date(contact.getBirthday().getTime()); props.add(new BDay(iCalDate)); } List<Address> addressList = contact.getAddresses(); for (Address address : addressList) { props.add(new net.fortuna.ical4j.vcard.property.Address(Group.WORK, address.getPostOfficeBox(), null, address.getStreet() + " " +address.getHousenumber(), address.getCity(), null, address.getZipCode(), address.getCountry(), Type.WORK)); } if(contact.getCompany() != null) { props.add(new Org(contact.getCompany())); } List<Website> websiteList = contact.getWebsiteList(); for (Website website : websiteList) { props.add(new Url(URI.create(website.getWebsite()))); } if(contact.getJobTitle() != null) { props.add(new Title(contact.getJobTitle())); } if(contact.getNotes() != null) { props.add(new Note(contact.getNotes())); } props.add(new ProdId("Business Manager")); VCard vCard = new VCard(props); OutputStream out = new ByteArrayOutputStream(); try { OutputStreamWriter writer = new OutputStreamWriter(out, Charset.forName("UTF-8")); vcardWriter.output(vCard, writer); } catch (IOException e) { logger.error("Could not write vcard to outputstream. Error was: ", e); } catch (ValidationException e) { logger.error("Found validation errors in vcard. Aborting.", e); } return out; } }