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