ref #6190 removing svn property place holder in first line of code
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / model / agent / Contact.java
1 /**
2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
8 */
9
10 package eu.etaxonomy.cdm.model.agent;
11
12 import java.io.Serializable;
13 import java.net.URI;
14 import java.util.ArrayList;
15 import java.util.HashSet;
16 import java.util.List;
17 import java.util.Set;
18
19 import javax.persistence.Column;
20 import javax.persistence.ElementCollection;
21 import javax.persistence.Embeddable;
22 import javax.persistence.FetchType;
23 import javax.persistence.OneToMany;
24 import javax.xml.bind.annotation.XmlAccessType;
25 import javax.xml.bind.annotation.XmlAccessorType;
26 import javax.xml.bind.annotation.XmlElement;
27 import javax.xml.bind.annotation.XmlElementWrapper;
28 import javax.xml.bind.annotation.XmlRootElement;
29 import javax.xml.bind.annotation.XmlSchemaType;
30 import javax.xml.bind.annotation.XmlType;
31
32 import org.apache.commons.lang.StringUtils;
33 import org.apache.log4j.Logger;
34 import org.hibernate.annotations.Cascade;
35 import org.hibernate.annotations.CascadeType;
36 import org.hibernate.envers.Audited;
37
38 import eu.etaxonomy.cdm.model.location.Country;
39 import eu.etaxonomy.cdm.model.location.Point;
40 import eu.etaxonomy.cdm.strategy.merge.MergeException;
41
42 /**
43 * The class for information on how to approach a {@link Person person} or an {@link Institution institution}.
44 * It includes telecommunication data and an electronic as well as
45 * multiple postal addresses.
46 * <P>
47 * This class corresponds to: <ul>
48 * <li> ContactDetails according to the TDWG ontology
49 * <li> Contact (partially) according to the ABCD schema
50 * </ul>
51 *
52 * @author m.doering
53 * @version 1.0
54 * @created 08-Nov-2007 13:06:18
55 */
56 @XmlAccessorType(XmlAccessType.FIELD)
57 @XmlType(name = "Contact", propOrder = {
58 "emailAddresses",
59 "urls",
60 "phoneNumbers",
61 "faxNumbers",
62 "addresses"
63 })
64 @XmlRootElement(name = "Contact")
65 @Embeddable
66 @Audited
67 public class Contact implements Serializable, Cloneable {
68 private static final long serialVersionUID = -1851305307069277625L;
69 private static final Logger logger = Logger.getLogger(Contact.class);
70
71
72 @XmlElementWrapper(name = "EmailAddresses", nillable = true)
73 @XmlElement(name = "EmailAddress")
74 @ElementCollection(fetch = FetchType.LAZY)
75 @Column(name = "contact_emailaddresses_element")
76 private List<String> emailAddresses;
77
78 @XmlElementWrapper(name = "URLs", nillable = true)
79 @XmlElement(name = "URL")
80 @XmlSchemaType(name = "anyURI")
81 @ElementCollection(fetch = FetchType.LAZY)
82 @Column(name = "contact_urls_element" /*, length=330 */) //length >255 does not work in InnoDB AUD tables for Key length of (REV, id, url) key
83 private final List<String> urls = new ArrayList<String>();
84
85 @XmlElementWrapper(name = "PhoneNumbers", nillable = true)
86 @XmlElement(name = "PhoneNumber")
87 @ElementCollection(fetch = FetchType.LAZY)
88 @Column(name = "contact_phonenumbers_element")
89 @Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.DELETE})
90 private List<String> phoneNumbers;
91
92 @XmlElementWrapper(name = "FaxNumbers", nillable = true)
93 @XmlElement(name = "FaxNumber")
94 @ElementCollection(fetch = FetchType.LAZY)
95 @Column(name = "contact_faxnumbers_element")
96 private List<String> faxNumbers;
97
98 @XmlElementWrapper(name = "Addresses", nillable = true)
99 @XmlElement(name = "Address")
100 @OneToMany(fetch = FetchType.LAZY, orphanRemoval=true)
101 @Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE})
102 protected Set<Address> addresses = new HashSet<Address>();
103
104 public static Contact NewInstance() {
105 return new Contact();
106 }
107
108 /**
109 * Creates a new contact
110 * @param street
111 * @param postcode
112 * @param locality
113 * @param country
114 * @param pobox
115 * @param region
116 * @param email
117 * @param faxNumber
118 * @param phoneNumber
119 * @param url
120 * @param location
121 * @return
122 */
123 public static Contact NewInstance(String street, String postcode, String locality,
124 Country country, String pobox, String region,
125 String email, String faxNumber, String phoneNumber, URI url, Point location) {
126 Contact result = new Contact();
127 if (country != null || StringUtils.isNotBlank(locality) || StringUtils.isNotBlank(pobox) || StringUtils.isNotBlank(postcode) ||
128 StringUtils.isNotBlank(region) || StringUtils.isNotBlank(street) ){
129 Address newAddress = Address.NewInstance(country, locality, pobox, postcode, region, street, location);
130 result.addAddress(newAddress);
131 }
132 if (email != null){
133 result.addEmailAddress(email);
134 }
135 if (faxNumber != null){
136 result.addFaxNumber(faxNumber);
137 }
138 if (phoneNumber != null){
139 result.addPhoneNumber(phoneNumber);
140 }
141 if (url != null){
142 result.addUrl(url);
143 }
144 return result;
145 }
146
147
148 public static Contact NewInstance(Set<Address> addresses, List<String> emailAddresses,
149 List<String> faxNumbers, List<String> phoneNumbers, List<URI> urls) {
150 Contact result = new Contact();
151 if (addresses != null){
152 result.addresses = addresses;
153 }
154 if (emailAddresses != null){
155 result.emailAddresses = emailAddresses;
156 }
157 if (faxNumbers != null){
158 result.faxNumbers = faxNumbers;
159 }
160 if (phoneNumbers != null){
161 result.phoneNumbers = phoneNumbers;
162 }
163 if (urls != null){
164 for (URI uri : urls){
165 result.urls.add(uri.toString());
166 }
167 }
168 return result;
169 }
170
171
172 /**
173 * Class constructor.
174 */
175 public Contact() {
176 }
177
178
179 public void merge(Contact contact2) throws MergeException{
180 if (contact2 != null){
181 mergeList(this.getEmailAddresses(), contact2.getEmailAddresses());
182 mergeList(this.getFaxNumbers(), contact2.getFaxNumbers());
183 mergeList(this.getPhoneNumbers(), contact2.getPhoneNumbers());
184 mergeList(this.getUrls(), contact2.getUrls());
185 for (Address address : contact2.getAddresses()){
186 try {
187 if (this.addresses == null){
188 this.addresses = new HashSet<Address>();
189 }
190 this.addresses.add((Address)address.clone());
191 } catch (CloneNotSupportedException e) {
192 throw new MergeException("Address must implement Cloneable");
193 }
194 }
195 }
196 }
197
198 private void mergeList(List list1, List list2){
199 for (Object obj2 : list2){
200 if (! list1.contains(obj2)){
201 list1.add(obj2);
202 }
203 }
204 }
205
206
207 /**
208 * Returns the set of postal {@link Address addresses} belonging to <i>this</i> contact.
209 * A {@link Person person} or an {@link Institution institution} cannot have more than one contact,
210 * but a contact may include several postal addresses.
211 *
212 * @return the set of postal addresses
213 * @see Address
214 */
215 public Set<Address> getAddresses(){
216 return this.addresses;
217 }
218
219 /**
220 * Adds a new postal {@link Address address} to the set of postal addresses of <i>this</i> contact.
221 *
222 * @param address the address to be added
223 * @see #getAddresses()
224 * @see Address
225 */
226 public void addAddress(Address address){
227 if (address != null){
228 getAddresses().add(address);
229 }
230 }
231
232 public Address addAddress(String street, String postcode, String locality,
233 Country country, String pobox, String region, Point location){
234 Address newAddress = Address.NewInstance(country, locality, pobox, postcode, region, street, location);
235 getAddresses().add(newAddress);
236 return newAddress;
237 }
238
239 /**
240 * Removes one element from the set of postal addresses of <i>this</i> contact.
241 *
242 * @param address the postal address of <i>this</i> contact which should be deleted
243 * @see #getAddresses()
244 */
245 public void removeAddress(Address address){
246 getAddresses().remove(address);
247 }
248
249
250 /**
251 * Returns the List of strings representing the electronic mail addresses
252 * included in <i>this</i> contact.
253 */
254 public List<String> getEmailAddresses(){
255 if(this.emailAddresses == null) {
256 this.emailAddresses = new ArrayList<String>();
257 }
258 return this.emailAddresses;
259 }
260
261 /**
262 * @see #getEmailAddress()
263 */
264 public void addEmailAddress(String emailAddress){
265 getEmailAddresses().add(emailAddress);
266 }
267
268 /**
269 * Removes one element from the list of email addresses of <i>this</i> contact.
270 *
271 * @param emailAddress the email address of <i>this</i> contact which should be deleted
272 * @see #getEmailAddresses()
273 */
274 public void removeEmailAddress(String emailAddress){
275 getEmailAddresses().remove(emailAddress);
276 }
277
278 // /**
279 // * Returns the list of {@link URI URIs} representing this contact
280 // * included in <i>this</i> contact.
281 // */
282 // @Transient //TODO preliminary workaround as we get LazyInit Exception in JSON #4444
283 // public List<URI> getUrls(){
284 // List<URI> result = new ArrayList<URI>();
285 // if(this.urls != null) {
286 // for (String uri : this.urls){
287 // result.add(URI.create(uri));
288 // }
289 // }
290 // return result;
291 // }
292
293 /**
294 * Returns the list of {@link URI URIs} representing this contact
295 * included in <i>this</i> contact.
296 */
297 public List<String> getUrls(){
298 return this.urls;
299 }
300
301 /**
302 * @see #getUrls()
303 */
304 public void addUrl(URI url){
305 this.urls.add(url.toString());
306 }
307
308 /**
309 * Removes one element from the list of urls of <i>this</i> contact.
310 *
311 * @param url the url of <i>this</i> contact which should be deleted
312 * @see #getUrls()
313 */
314 public void removeUrl(URI url){
315 this.urls.remove(url.toString());
316 }
317
318
319 /**
320 * Returns the list of strings representing the phone numbers
321 * included in <i>this</i> contact.
322 */
323 public List<String> getPhoneNumbers(){
324 if(this.phoneNumbers == null) {
325 this.phoneNumbers = new ArrayList<String>();
326 }
327 return this.phoneNumbers;
328 }
329
330 /**
331 * @see #getPhone()
332 */
333 public void addPhoneNumber(String phoneNumber){
334 getPhoneNumbers().add(phoneNumber);
335 }
336
337 /**
338 * Removes one element from the list of phone numbers of <i>this</i> contact.
339 *
340 * @param phoneNumber the phone number of <i>this</i> contact which should be deleted
341 * @see #getPhoneNumber()
342 */
343 public void removePhoneNumber(String phoneNumber){
344 getPhoneNumbers().remove(phoneNumber);
345 }
346
347 /**
348 * Returns the list of strings representing the telefax numbers
349 * included in <i>this</i> contact.
350 */
351 public List<String> getFaxNumbers(){
352 if(this.faxNumbers == null) {
353 this.faxNumbers = new ArrayList<String>();
354 }
355 return this.faxNumbers;
356 }
357
358 /**
359 * @see #getFaxNumbers()
360 */
361 public void addFaxNumber(String faxNumber){
362 getFaxNumbers().add(faxNumber);
363 }
364
365 /**
366 * Removes one element from the list of telefax numbers of <i>this</i> contact.
367 *
368 * @param faxNumber the telefax number of <i>this</i> contact which should be deleted
369 * @see #getFaxNumber()
370 */
371 public void removeFaxNumber(String faxNumber){
372 getFaxNumbers().remove(faxNumber);
373 }
374
375 //*********************** CLONE ********************************************************/
376
377 /**
378 * Clones <i>this</i> Contact. This is a shortcut that enables to create
379 * a new instance that differs only slightly from <i>this</i> Contact.
380 *
381 *
382 * @see java.lang.Object#clone()
383 */
384 @Override
385 public Object clone() {
386 try{
387 Contact result = (Contact) super.clone();
388 result.addresses = new HashSet<Address>();
389 for (Address adr : this.addresses){
390 result.addAddress((Address)adr.clone());
391 }
392 //no changes to emailAdresses, faxnumbers, phonenumbers, urls
393 return result;
394 }catch (CloneNotSupportedException e){
395 logger.warn("Object does not implement cloneable");
396 e.printStackTrace();
397 return null;
398 }
399 }
400 }