Project

General

Profile

Download (11.9 KB) Statistics
| Branch: | Tag: | Revision:
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
package eu.etaxonomy.cdm.model.agent;
10

    
11
import java.io.Serializable;
12
import java.util.ArrayList;
13
import java.util.Collection;
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.persistence.Transient;
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.lang3.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
import org.hibernate.search.annotations.FieldBridge;
38

    
39
import eu.etaxonomy.cdm.common.URI;
40
import eu.etaxonomy.cdm.hibernate.search.UriBridge;
41
import eu.etaxonomy.cdm.model.location.Country;
42
import eu.etaxonomy.cdm.model.location.Point;
43
import eu.etaxonomy.cdm.strategy.merge.MergeException;
44

    
45
/**
46
 * The class for information on how to approach a {@link Person person} or an {@link Institution institution}.
47
 * It includes telecommunication data and an electronic as well as
48
 * multiple postal addresses.
49
* <P>
50
 * This class corresponds to: <ul>
51
 * <li> ContactDetails according to the TDWG ontology
52
 * <li> Contact (partially) according to the ABCD schema
53
 * </ul>
54
 *
55
 * @author m.doering
56
 * @since 08-Nov-2007 13:06:18
57
 */
58
@XmlAccessorType(XmlAccessType.FIELD)
59
@XmlType(name = "Contact", propOrder = {
60
    "emailAddresses",
61
    "urls",
62
    "phoneNumbers",
63
    "faxNumbers",
64
    "addresses"
65
})
66
@XmlRootElement(name = "Contact")
67
@Embeddable
68
@Audited
69
public class Contact implements Serializable, Cloneable {
70
	private static final long serialVersionUID = -1851305307069277625L;
71
	private static final Logger logger = Logger.getLogger(Contact.class);
72

    
73

    
74
	@XmlElementWrapper(name = "EmailAddresses", nillable = true)
75
	@XmlElement(name = "EmailAddress")
76
	@ElementCollection(fetch = FetchType.LAZY)
77
	@Column(name = "contact_emailaddresses_element")
78
	private List<String> emailAddresses = new ArrayList<>();
79

    
80
	@XmlElementWrapper(name = "URLs", nillable = true)
81
	@XmlElement(name = "URL")
82
    @XmlSchemaType(name = "anyURI")
83
    @FieldBridge(impl = UriBridge.class)
84
	@ElementCollection(fetch = FetchType.LAZY)
85
    @Column(name = "contact_urls_element" /*, length=330  */)  //length >255 does not work in InnoDB AUD tables for Key length of (REV, id, url) key
86
	private final List<String> urls = new ArrayList<>();
87

    
88
	@XmlElementWrapper(name = "PhoneNumbers", nillable = true)
89
	@XmlElement(name = "PhoneNumber")
90
	@ElementCollection(fetch = FetchType.LAZY)
91
    @Column(name = "contact_phonenumbers_element")
92
	@Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.DELETE})
93
	private List<String> phoneNumbers = new ArrayList<>();
94

    
95
	@XmlElementWrapper(name = "FaxNumbers", nillable = true)
96
	@XmlElement(name = "FaxNumber")
97
	@ElementCollection(fetch = FetchType.LAZY)
98
    @Column(name = "contact_faxnumbers_element")
99
	private List<String> faxNumbers = new ArrayList<>();
100

    
101
    @XmlElementWrapper(name = "Addresses", nillable = true)
102
    @XmlElement(name = "Address")
103
    @OneToMany(fetch = FetchType.LAZY, orphanRemoval=true)
104
	@Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE})
105
	protected Set<Address> addresses = new HashSet<>();
106

    
107
	public static Contact NewInstance() {
108
		return new Contact();
109
	}
110

    
111
	/**
112
	 * Creates a new contact
113
	 * @param street
114
	 * @param postcode
115
	 * @param locality
116
	 * @param country
117
	 * @param pobox
118
	 * @param region
119
	 * @param email
120
	 * @param faxNumber
121
	 * @param phoneNumber
122
	 * @param url
123
	 * @param location
124
	 * @return
125
	 */
126
	public static Contact NewInstance(String street, String postcode, String locality,
127
			Country country, String pobox, String region,
128
			String email, String faxNumber, String phoneNumber, URI url, Point location) {
129
		Contact result = new Contact();
130
		if (country != null || StringUtils.isNotBlank(locality) || StringUtils.isNotBlank(pobox) || StringUtils.isNotBlank(postcode) ||
131
				StringUtils.isNotBlank(region) || StringUtils.isNotBlank(street) ){
132
			Address newAddress = Address.NewInstance(country, locality, pobox, postcode, region, street, location);
133
			result.addAddress(newAddress);
134
		}
135
		if (email != null){
136
			result.addEmailAddress(email);
137
		}
138
		if (faxNumber != null){
139
			result.addFaxNumber(faxNumber);
140
		}
141
		if (phoneNumber != null){
142
			result.addPhoneNumber(phoneNumber);
143
		}
144
		if (url != null){
145
			result.addUrl(url);
146
		}
147
		return result;
148
	}
149

    
150

    
151
	public static Contact NewInstance(Set<Address> addresses, List<String> emailAddresses,
152
			List<String> faxNumbers, List<String> phoneNumbers, List<URI> urls) {
153
		Contact result = new Contact();
154
		if (addresses != null){
155
			result.addresses = addresses;
156
		}
157
		if (emailAddresses != null){
158
			result.emailAddresses = emailAddresses;
159
		}
160
		if (faxNumbers != null){
161
			result.faxNumbers = faxNumbers;
162
		}
163
		if (phoneNumbers != null){
164
			result.phoneNumbers = phoneNumbers;
165
		}
166
		if (urls != null){
167
			for (URI uri : urls){
168
				result.urls.add(uri.toString());
169
			}
170
		}
171
		return result;
172
	}
173

    
174
// ************************ CONSTRUCTOR **************************/
175
	/**
176
	 * Class constructor.
177
	 */
178
	public Contact() {
179
	}
180

    
181
// ************************ MERGE /MATCH ***************************/
182

    
183
	public void merge(Contact contact2) throws MergeException{
184
		if (contact2 != null){
185
			mergeList(this.getEmailAddresses(), contact2.getEmailAddresses());
186
			mergeList(this.getFaxNumbers(), contact2.getFaxNumbers());
187
			mergeList(this.getPhoneNumbers(), contact2.getPhoneNumbers());
188
			mergeList(this.getUrls(), contact2.getUrls());
189
			for (Address address : contact2.getAddresses()){
190
				try {
191
					if (this.addresses == null){
192
						this.addresses = new HashSet<>();
193
					}
194
					this.addresses.add(address.clone());
195
				} catch (CloneNotSupportedException e) {
196
					throw new MergeException("Address must implement Cloneable");
197
				}
198
			}
199
		}
200
	}
201

    
202
	private void mergeList(List list1, List list2){
203
		for (Object obj2 : list2){
204
			if (! list1.contains(obj2)){
205
				list1.add(obj2);
206
			}
207
		}
208
	}
209

    
210
    /**
211
     * True, if no contact data exists in any of the lists (email, phone, ...).
212
     */
213
    @Transient
214
    public boolean isEmpty(){
215
        if (isEmpty(emailAddresses) && isEmpty(faxNumbers) && isEmpty(phoneNumbers)
216
                && isEmpty(urls) && isEmpty(addresses)){
217
            return true;
218
        }else{
219
            return false;
220
        }
221
    }
222

    
223
    private boolean isEmpty(Collection<? extends Object> collection) {
224
        return collection == null || collection.isEmpty();
225
    }
226

    
227
    /**
228
	 * Returns the set of postal {@link Address addresses} belonging to <i>this</i> contact.
229
	 * A {@link Person person} or an {@link Institution institution} cannot have more than one contact,
230
	 * but a contact may include several postal addresses.
231
	 *
232
	 * @return	the set of postal addresses
233
	 * @see     Address
234
	 */
235
	public Set<Address> getAddresses(){
236
		return this.addresses;
237
	}
238

    
239
	/**
240
	 * Adds a new postal {@link Address address} to the set of postal addresses of <i>this</i> contact.
241
	 *
242
	 * @param  address  the address to be added
243
	 * @see     		#getAddresses()
244
	 * @see 			Address
245
	 */
246
	public void addAddress(Address address){
247
		if (address != null){
248
			getAddresses().add(address);
249
		}
250
	}
251

    
252
	public Address addAddress(String street, String postcode, String locality,
253
			Country country, String pobox, String region, Point location){
254
		Address newAddress = Address.NewInstance(country, locality, pobox, postcode, region, street, location);
255
		getAddresses().add(newAddress);
256
		return newAddress;
257
	}
258

    
259
	/**
260
	 * Removes one element from the set of postal addresses of <i>this</i> contact.
261
	 *
262
	 * @param  address  the postal address of <i>this</i> contact which should be deleted
263
	 * @see     		#getAddresses()
264
	 */
265
	public void removeAddress(Address address){
266
		getAddresses().remove(address);
267
	}
268

    
269

    
270
	/**
271
	 * Returns the List of strings representing the electronic mail addresses
272
	 * included in <i>this</i> contact.
273
	 */
274
	public List<String> getEmailAddresses(){
275
		if(this.emailAddresses == null) {
276
			this.emailAddresses = new ArrayList<>();
277
		}
278
		return this.emailAddresses;
279
	}
280

    
281
	/**
282
	 * @see  #getEmailAddress()
283
	 */
284
	public void addEmailAddress(String emailAddress){
285
		getEmailAddresses().add(emailAddress);
286
	}
287

    
288
	/**
289
	 * Removes one element from the list of email addresses of <i>this</i> contact.
290
	 *
291
	 * @param  emailAddress  the email address of <i>this</i> contact which should be deleted
292
	 * @see     		#getEmailAddresses()
293
	 */
294
	public void removeEmailAddress(String emailAddress){
295
		getEmailAddresses().remove(emailAddress);
296
	}
297

    
298
//	/**
299
//	 * Returns the list of {@link URI URIs} representing this contact
300
//	 * included in <i>this</i> contact.
301
//	 */
302
//	@Transient   //TODO preliminary workaround as we get LazyInit Exception in JSON #4444
303
//	public List<URI> getUrls(){
304
//		List<URI> result = new ArrayList<URI>();
305
//		if(this.urls != null) {
306
//			for (String uri : this.urls){
307
//				result.add(URI.create(uri));
308
//			}
309
//		}
310
//		return result;
311
//	}
312

    
313
	/**
314
	 * Returns the list of {@link URI URIs} representing this contact
315
	 * included in <i>this</i> contact.
316
	 */
317
	public List<String> getUrls(){
318
		return this.urls;
319
	}
320

    
321
	/**
322
	 * @see  #getUrls()
323
	 */
324
	public void addUrl(URI url){
325
		this.urls.add(url.toString());
326
	}
327

    
328
	/**
329
	 * Removes one element from the list of urls of <i>this</i> contact.
330
	 *
331
	 * @param  url  the url of <i>this</i> contact which should be deleted
332
	 * @see     		#getUrls()
333
	 */
334
	public void removeUrl(URI url){
335
		this.urls.remove(url.toString());
336
	}
337

    
338

    
339
	/**
340
	 * Returns the list of strings representing the phone numbers
341
	 * included in <i>this</i> contact.
342
	 */
343
	public List<String> getPhoneNumbers(){
344
		if(this.phoneNumbers == null) {
345
			this.phoneNumbers = new ArrayList<>();
346
		}
347
		return this.phoneNumbers;
348
	}
349

    
350
	/**
351
	 * @see  #getPhone()
352
	 */
353
	public void addPhoneNumber(String phoneNumber){
354
		getPhoneNumbers().add(phoneNumber);
355
	}
356

    
357
	/**
358
	 * Removes one element from the list of phone numbers of <i>this</i> contact.
359
	 *
360
	 * @param  phoneNumber  the phone number of <i>this</i> contact which should be deleted
361
	 * @see     		#getPhoneNumber()
362
	 */
363
	public void removePhoneNumber(String phoneNumber){
364
		getPhoneNumbers().remove(phoneNumber);
365
	}
366

    
367
	/**
368
	 * Returns the list of strings representing the telefax numbers
369
	 * included in <i>this</i> contact.
370
	 */
371
	public List<String> getFaxNumbers(){
372
		if(this.faxNumbers == null) {
373
			this.faxNumbers = new ArrayList<>();
374
		}
375
		return this.faxNumbers;
376
	}
377

    
378
	/**
379
	 * @see  #getFaxNumbers()
380
	 */
381
	public void addFaxNumber(String faxNumber){
382
		getFaxNumbers().add(faxNumber);
383
	}
384

    
385
	/**
386
	 * Removes one element from the list of telefax numbers of <i>this</i> contact.
387
	 *
388
	 * @param  faxNumber  the telefax number of <i>this</i> contact which should be deleted
389
	 * @see     		#getFaxNumber()
390
	 */
391
	public void removeFaxNumber(String faxNumber){
392
		getFaxNumbers().remove(faxNumber);
393
	}
394

    
395
//*********************** CLONE ********************************************************/
396

    
397
	/**
398
	 * Clones <i>this</i> Contact. This is a shortcut that enables to create
399
	 * a new instance that differs only slightly from <i>this</i> Contact.
400
	 *
401
	 *
402
	 * @see java.lang.Object#clone()
403
	 */
404
	@Override
405
	public Contact clone() {
406
		try{
407
			Contact result = (Contact) super.clone();
408
			result.addresses = new HashSet<>();
409
			for (Address adr : this.addresses){
410
				result.addAddress(adr.clone());
411
			}
412
			//no changes to emailAdresses, faxnumbers, phonenumbers, urls
413
			return result;
414
		}catch (CloneNotSupportedException e){
415
			logger.warn("Object does not implement cloneable");
416
			e.printStackTrace();
417
			return null;
418
		}
419
	}
420
}
(3-3/12)