move fields up
[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.Country;
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 @XmlElementWrapper(name = "EmailAddresses", nillable = true)
72 @XmlElement(name = "EmailAddress")
73 @ElementCollection(fetch = FetchType.LAZY)
74 @Column(name = "contact_emailaddresses_element")
75 private List<String> emailAddresses;
76
77 @XmlElementWrapper(name = "URLs", nillable = true)
78 @XmlElement(name = "URL")
79 @XmlSchemaType(name = "anyURI")
80 @ElementCollection(fetch = FetchType.LAZY)
81 @Column(name = "contact_urls_element")
82 private List<String> urls;
83
84 @XmlElementWrapper(name = "PhoneNumbers", nillable = true)
85 @XmlElement(name = "PhoneNumber")
86 @ElementCollection(fetch = FetchType.LAZY)
87 @Column(name = "contact_phonenumbers_element")
88 private List<String> phoneNumbers;
89
90 @XmlElementWrapper(name = "FaxNumbers", nillable = true)
91 @XmlElement(name = "FaxNumber")
92 @ElementCollection(fetch = FetchType.LAZY)
93 @Column(name = "contact_faxnumbers_element")
94 private List<String> faxNumbers;
95
96 @XmlElementWrapper(name = "Addresses", nillable = true)
97 @XmlElement(name = "Address")
98 @OneToMany(fetch = FetchType.LAZY, orphanRemoval=true)
99 @Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE})
100 protected Set<Address> addresses;
101
102
103 public static Contact NewInstance() {
104 return new Contact();
105 }
106
107 /**
108 * Creates a new contact
109 * @param street
110 * @param postcode
111 * @param locality
112 * @param country
113 * @param pobox
114 * @param region
115 * @param email
116 * @param faxNumber
117 * @param phoneNumber
118 * @param url
119 * @param location
120 * @return
121 */
122 public static Contact NewInstance(String street, String postcode, String locality,
123 Country country, String pobox, String region,
124 String email, String faxNumber, String phoneNumber, String url, Point location) {
125 Contact result = new Contact();
126 if (country != null || StringUtils.isNotBlank(locality) || StringUtils.isNotBlank(pobox) || StringUtils.isNotBlank(postcode) ||
127 StringUtils.isNotBlank(region) || StringUtils.isNotBlank(street) ){
128 Address newAddress = Address.NewInstance(country, locality, pobox, postcode, region, street, location);
129 result.addAddress(newAddress);
130 }
131 if (email != null){
132 result.addEmailAddress(email);
133 }
134 if (faxNumber != null){
135 result.addFaxNumber(faxNumber);
136 }
137 if (phoneNumber != null){
138 result.addPhoneNumber(phoneNumber);
139 }
140 if (url != null){
141 result.addUrl(url);
142 }
143 return result;
144 }
145
146
147 public static Contact NewInstance(Set<Address> addresses, List<String> emailAdresses,
148 List<String> faxNumbers, List<String> phoneNumbers, List<String> urls) {
149 Contact result = new Contact();
150 if (addresses != null){
151 result.addresses = addresses;
152 }
153 if (emailAdresses != null){
154 result.emailAddresses = emailAdresses;
155 }
156 if (faxNumbers != null){
157 result.faxNumbers = faxNumbers;
158 }
159 if (phoneNumbers != null){
160 result.phoneNumbers = phoneNumbers;
161 }
162 if (urls != null){
163 result.urls = urls;
164 }
165 return result;
166 }
167
168
169 /**
170 * Class constructor.
171 */
172 public Contact() {
173 }
174
175
176 public void merge(Contact contact2) throws MergeException{
177 if (contact2 != null){
178 mergeList(this.getEmailAddresses(), contact2.getEmailAddresses());
179 mergeList(this.getFaxNumbers(), contact2.getFaxNumbers());
180 mergeList(this.getPhoneNumbers(), contact2.getPhoneNumbers());
181 mergeList(this.getUrls(), contact2.getUrls());
182 for (Address address : contact2.getAddresses()){
183 try {
184 this.addresses.add((Address)address.clone());
185 } catch (CloneNotSupportedException e) {
186 throw new MergeException("Address must implement Cloneable");
187 }
188 }
189 }
190 }
191
192 private void mergeList(List list1, List list2){
193 for (Object obj2 : list2){
194 if (! list1.contains(obj2)){
195 list1.add(obj2);
196 }
197 }
198 }
199
200
201 /**
202 * Returns the set of postal {@link Address addresses} belonging to <i>this</i> contact.
203 * A {@link Person person} or an {@link Institution institution} cannot have more than one contact,
204 * but a contact may include several postal addresses.
205 *
206 * @return the set of postal addresses
207 * @see Address
208 */
209 public Set<Address> getAddresses(){
210 if(this.addresses == null) {
211 this.addresses = new HashSet<Address>();
212 }
213 return this.addresses;
214 }
215
216 /**
217 * Adds a new postal {@link Address address} to the set of postal addresses of <i>this</i> contact.
218 *
219 * @param address the address to be added
220 * @see #getAddresses()
221 * @see Address
222 */
223 public void addAddress(Address address){
224 if (address != null){
225 getAddresses().add(address);
226 }
227 }
228
229 public void addAddress(String street, String postcode, String locality,
230 Country country, String pobox, String region, Point location){
231 Address newAddress = Address.NewInstance(country, locality, pobox, postcode, region, street, location);
232 getAddresses().add(newAddress);
233 }
234
235 /**
236 * Removes one element from the set of postal addresses of <i>this</i> contact.
237 *
238 * @param address the postal address of <i>this</i> contact which should be deleted
239 * @see #getAddresses()
240 */
241 public void removeAddress(Address address){
242 getAddresses().remove(address);
243 }
244
245
246 /**
247 * Returns the List of strings representing the electronic mail addresses
248 * included in <i>this</i> contact.
249 */
250 public List<String> getEmailAddresses(){
251 if(this.emailAddresses == null) {
252 this.emailAddresses = new ArrayList<String>();
253 }
254 return this.emailAddresses;
255 }
256
257 /**
258 * @see #getEmailAddress()
259 */
260 public void addEmailAddress(String emailAddress){
261 getEmailAddresses().add(emailAddress);
262 }
263
264 /**
265 * Removes one element from the list of email addresses of <i>this</i> contact.
266 *
267 * @param emailAddress the email address of <i>this</i> contact which should be deleted
268 * @see #getEmailAddresses()
269 */
270 public void removeEmailAddress(String emailAddress){
271 getEmailAddresses().remove(emailAddress);
272 }
273
274 /**
275 * Returns the list of strings representing the "Uniform Resource Locators" (urls)
276 * included in <i>this</i> contact.
277 */
278 public List<String> getUrls(){
279 if(this.urls == null) {
280 this.urls = new ArrayList<String>();
281 }
282 return this.urls;
283 }
284
285 /**
286 * @see #getUrls()
287 */
288 public void addUrl(String url){
289 getUrls().add(url);
290 }
291
292 /**
293 * Removes one element from the list of urls of <i>this</i> contact.
294 *
295 * @param url the url of <i>this</i> contact which should be deleted
296 * @see #getUrls()
297 */
298 public void removeUrl(String url){
299 getUrls().remove(url);
300 }
301
302 /**
303 * Returns the list of strings representing the phone numbers
304 * included in <i>this</i> contact.
305 */
306 public List<String> getPhoneNumbers(){
307 if(this.phoneNumbers == null) {
308 this.phoneNumbers = new ArrayList<String>();
309 }
310 return this.phoneNumbers;
311 }
312
313 /**
314 * @see #getPhone()
315 */
316 public void addPhoneNumber(String phoneNumber){
317 getPhoneNumbers().add(phoneNumber);
318 }
319
320 /**
321 * Removes one element from the list of phone numbers of <i>this</i> contact.
322 *
323 * @param phoneNumber the phone number of <i>this</i> contact which should be deleted
324 * @see #getPhoneNumber()
325 */
326 public void removePhoneNumber(String phoneNumber){
327 getPhoneNumbers().remove(phoneNumber);
328 }
329
330 /**
331 * Returns the list of strings representing the telefax numbers
332 * included in <i>this</i> contact.
333 */
334 public List<String> getFaxNumbers(){
335 if(this.faxNumbers == null) {
336 this.faxNumbers = new ArrayList<String>();
337 }
338 return this.faxNumbers;
339 }
340
341 /**
342 * @see #getFaxNumbers()
343 */
344 public void addFaxNumber(String faxNumber){
345 getFaxNumbers().add(faxNumber);
346 }
347
348 /**
349 * Removes one element from the list of telefax numbers of <i>this</i> contact.
350 *
351 * @param faxNumber the telefax number of <i>this</i> contact which should be deleted
352 * @see #getFaxNumber()
353 */
354 public void removeFaxNumber(String faxNumber){
355 getFaxNumbers().remove(faxNumber);
356 }
357
358 //*********************** CLONE ********************************************************/
359
360 /**
361 * Clones <i>this</i> Contact. This is a shortcut that enables to create
362 * a new instance that differs only slightly from <i>this</i> Contact.
363 *
364 *
365 * @see java.lang.Object#clone()
366 */
367 @Override
368 public Object clone() {
369 try{
370 Contact result = (Contact) super.clone();
371 result.addresses = new HashSet<Address>();
372 for (Address adr : this.addresses){
373 result.addAddress((Address)adr.clone());
374 }
375 //no changes to emailAdresses, faxNumbers, phoneNumbers, urls
376 return result;
377 }catch (CloneNotSupportedException e){
378 logger.warn("Object does not implement cloneable");
379 e.printStackTrace();
380 return null;
381 }
382 }
383 }