2 * Copyright (C) 2016 - 2024 Free Software Foundation
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 package org.mxchange.jcontacts.model.contact;
19 import java.text.MessageFormat;
20 import java.util.Date;
21 import java.util.Objects;
22 import javax.persistence.Basic;
23 import javax.persistence.CascadeType;
24 import javax.persistence.Column;
25 import javax.persistence.Entity;
26 import javax.persistence.EnumType;
27 import javax.persistence.Enumerated;
28 import javax.persistence.GeneratedValue;
29 import javax.persistence.GenerationType;
30 import javax.persistence.Id;
31 import javax.persistence.Index;
32 import javax.persistence.JoinColumn;
33 import javax.persistence.Lob;
34 import javax.persistence.NamedQueries;
35 import javax.persistence.NamedQuery;
36 import javax.persistence.OneToOne;
37 import javax.persistence.Table;
38 import javax.persistence.Temporal;
39 import javax.persistence.TemporalType;
40 import javax.persistence.Transient;
41 import org.apache.commons.lang3.StringUtils;
42 import org.mxchange.jcontacts.model.contact.title.PersonalTitle;
43 import org.mxchange.jcontacts.model.utils.PersonalTitleUtils;
44 import org.mxchange.jcoreutils.bool.BooleanUtils;
45 import org.mxchange.jcoreutils.comparable.ComparableUtils;
46 import org.mxchange.jcoreutils.dates.DateUtils;
47 import org.mxchange.jcoreutils.number.SafeNumberUtils;
48 import org.mxchange.jcountry.model.data.Country;
49 import org.mxchange.jcountry.model.data.CountryData;
50 import org.mxchange.jcountry.model.utils.CountryUtils;
51 import org.mxchange.jphone.model.phonenumbers.fax.DialableFaxNumber;
52 import org.mxchange.jphone.model.phonenumbers.fax.FaxNumber;
53 import org.mxchange.jphone.model.phonenumbers.landline.DialableLandLineNumber;
54 import org.mxchange.jphone.model.phonenumbers.landline.LandLineNumber;
55 import org.mxchange.jphone.model.phonenumbers.mobile.DialableMobileNumber;
56 import org.mxchange.jphone.model.phonenumbers.mobile.MobileNumber;
59 * A general contact class which serves as an entity.
61 * @author Roland Häder<roland@mxchange.org>
64 @Entity (name = "contacts")
69 name = "contact_personal_title",
70 columnList = "contact_personal_title"
76 @NamedQuery (name = "AllContacts", query = "SELECT c FROM contacts AS c ORDER BY c.contactId ASC")
79 @SuppressWarnings ("PersistenceUnitPresent")
80 public class UserContact implements Contact {
86 private static final long serialVersionUID = 58_744_284_981_863L;
91 @Column (name = "contact_birthday")
92 @Temporal (TemporalType.DATE)
93 private Date contactBirthday;
98 @Column (name = "contact_city", length = 100)
99 private String contactCity;
105 @Column (name = "contact_comment")
106 private String contactComment;
111 @JoinColumn (name = "contact_country_id", nullable = false, referencedColumnName = "country_id")
112 @OneToOne (targetEntity = CountryData.class, cascade = CascadeType.REFRESH, optional = false)
113 private Country contactCountry;
118 @Column (name = "contact_email_address", length = 100, unique = true)
119 private String contactEmailAddress;
122 * When the contact has been created
124 @Basic (optional = false)
125 @Temporal (TemporalType.TIMESTAMP)
126 @Column (name = "contact_entry_created", updatable = false, nullable = false)
127 private Date contactEntryCreated;
130 * When the contact has been updated
132 @Temporal (TemporalType.TIMESTAMP)
133 @Column (name = "contact_entry_updated", insertable = false)
134 private Date contactEntryUpdated;
139 @Basic (optional = false)
140 @Column (name = "contact_family_name", length = 100, nullable = false)
141 private String contactFamilyName;
146 @JoinColumn (name = "contact_fax_number_id", referencedColumnName = "fax_id", unique = true)
147 @OneToOne (targetEntity = FaxNumber.class, cascade = CascadeType.ALL)
148 private DialableFaxNumber contactFaxNumber;
153 @Basic (optional = false)
154 @Column (name = "contact_first_name", length = 100, nullable = false)
155 private String contactFirstName;
160 @Column (name = "contact_house_number")
161 private Short contactHouseNumber;
164 * House number extension
166 @Column (name = "contact_house_number_extension", length = 5)
167 private String contactHouseNumberExtension;
173 @GeneratedValue (strategy = GenerationType.IDENTITY)
174 @Column (name = "contact_id", nullable = false, updatable = false)
175 private Long contactId;
180 @JoinColumn (name = "contact_mobile_number_id", referencedColumnName = "mobile_id", unique = true)
181 @OneToOne (targetEntity = MobileNumber.class, cascade = CascadeType.ALL)
182 private DialableMobileNumber contactMobileNumber;
185 * Flag whether this contact is user's own data
187 @Basic (optional = false)
188 @Column (name = "contact_own_contact", nullable = false)
189 private Boolean contactOwnContact;
192 * Contact's personal title (Mr./Mrs.)
194 @Basic (optional = false)
195 @Column (name = "contact_personal_title", nullable = false)
196 @Enumerated (EnumType.STRING)
197 private PersonalTitle contactPersonalTitle;
202 @JoinColumn (name = "contact_landline_number_id", referencedColumnName = "landline_id", unique = true)
203 @OneToOne (targetEntity = LandLineNumber.class, cascade = CascadeType.ALL)
204 private DialableLandLineNumber contactPhoneNumber;
209 @Column (name = "contact_street")
210 private String contactStreet;
213 * Title (Doctor, etc)
215 @Column (name = "contact_title")
216 private String contactTitle;
221 @Column (name = "contact_zip_code")
222 private Integer contactZipCode;
225 * Default constructor
227 public UserContact () {
231 * Constructor for title and names
233 * @param personalTitle Personal title
234 * @param firstName First name
235 * @param familyName Family name
236 * @param country Country instance
237 * @param isOwnContact Whether this is own contact
239 public UserContact (final PersonalTitle personalTitle, final String firstName, final String familyName, final Country country, final Boolean isOwnContact) {
240 // Invoke default constructor
243 // Are all parameter set?
244 if (null == personalTitle) {
246 throw new NullPointerException("personalTitle is null"); //NOI18N
247 } else if (null == firstName) {
249 throw new NullPointerException("firstName is null"); //NOI18N
250 } else if (firstName.isEmpty()) {
252 throw new IllegalArgumentException("firstName is empty"); //NOI18N
253 } else if (null == familyName) {
255 throw new NullPointerException("familyName is null"); //NOI18N
256 } else if (familyName.isEmpty()) {
258 throw new IllegalArgumentException("familyName is empty"); //NOI18N
259 } else if (null == country) {
261 throw new NullPointerException("country is null"); //NOI18N
262 } else if (country.getCountryId() == null) {
264 throw new NullPointerException("country.countryId is null"); //NOI18N
265 } else if (country.getCountryId() < 1) {
267 throw new IllegalArgumentException(MessageFormat.format("contactCountry.countryId={0} is not valid", country.getCountryId())); //NOI18N
268 } else if (null == isOwnContact) {
270 throw new NullPointerException("isOwnContact is null"); // NOI18N
274 this.contactPersonalTitle = personalTitle;
275 this.contactFirstName = firstName;
276 this.contactFamilyName = familyName;
277 this.contactCountry = country;
278 this.contactOwnContact = isOwnContact;
282 * Constructor with all fields, except created/updated and primary key
284 * @param personalTitle Personal title (Mr./Mrs.)
285 * @param firstName First name
286 * @param familyName Family name
287 * @param country Country (e.g. current)
288 * @param isOwnContact Whether this is own contact
289 * @param street Street name
290 * @param houseNumber House number
291 * @param houseNumberExtension Extension to house number (e.g. a in 12a)
292 * @param zipCode ZIP code
294 * @param emailAddress email address
295 * @param academicTitle Academic title
296 * @param birthday Birthday
297 * @param comment Comment
299 * @todo Find a way to stop 0000-00-00 as birthdays to be entered
301 public UserContact (final PersonalTitle personalTitle, final String firstName, final String familyName, final Country country, final Boolean isOwnContact, final String street, final Short houseNumber, final String houseNumberExtension, final Integer zipCode, final String city, final String emailAddress, final String academicTitle, final Date birthday, final String comment) {
302 // Call other constructor first
303 this(personalTitle, firstName, familyName, country, isOwnContact);
305 // Validate parameter
306 if (street != null && street.isEmpty()) {
308 throw new IllegalArgumentException("street is empty"); // NOI18N
309 } else if (houseNumber != null && houseNumber < 1) {
310 // No zero house numbers exist
311 throw new IllegalArgumentException(MessageFormat.format("houseNumber={0} is not valid", houseNumber)); // NOI18N
312 } else if (houseNumberExtension != null && houseNumberExtension.isEmpty()) {
314 throw new IllegalArgumentException("houseNumberExtension is empty"); // NOI18N
315 } else if (zipCode != null && zipCode < 1) {
316 // No zero house numbers exist
317 throw new IllegalArgumentException(MessageFormat.format("zipCode={0} is not valid", zipCode)); // NOI18N
318 } else if (city != null && city.isEmpty()) {
320 throw new IllegalArgumentException("city is empty"); // NOI18N
321 } else if (emailAddress != null && emailAddress.isEmpty()) {
323 throw new IllegalArgumentException("emailAddress is empty"); // NOI18N
324 } else if (academicTitle != null && academicTitle.isEmpty()) {
326 throw new IllegalArgumentException("academicTitle is empty"); // NOI18N
327 } else if (comment != null && comment.isEmpty()) {
329 throw new IllegalArgumentException("comment is empty"); // NOI18N
333 this.contactStreet = street;
334 this.contactHouseNumber = houseNumber;
335 this.contactHouseNumberExtension = houseNumberExtension;
336 this.contactZipCode = zipCode;
337 this.contactCity = city;
338 this.contactEmailAddress = emailAddress;
339 this.contactTitle = academicTitle;
340 this.contactBirthday = birthday;
341 this.contactComment = comment;
345 public int compareTo (final Contact contact) {
346 // Checkparameter and return 0 if equal
347 if (null == contact) {
349 throw new NullPointerException("contact is null"); //NOI18N
350 } else if (contact.equals(this)) {
356 final int comparators[] = {
357 // First check country
358 CountryUtils.compare(this.getContactCountry(), contact.getContactCountry()),
360 SafeNumberUtils.compare(this.getContactZipCode(), contact.getContactZipCode()),
362 StringUtils.compare(this.getContactCity(), contact.getContactCity()),
364 StringUtils.compareIgnoreCase(this.getContactStreet(), contact.getContactStreet()),
366 SafeNumberUtils.compare(this.getContactHouseNumber(), contact.getContactHouseNumber()),
368 StringUtils.compareIgnoreCase(this.getContactHouseNumberExtension(), contact.getContactHouseNumberExtension()),
369 // ... now it is sure that address is different/same, continue with personal title
370 PersonalTitleUtils.compare(this.getContactPersonalTitle(), contact.getContactPersonalTitle()),
371 // ... academical title
372 StringUtils.compareIgnoreCase(this.getContactTitle(), contact.getContactTitle()),
373 // .. family name ...
374 StringUtils.compareIgnoreCase(this.getContactFamilyName(), contact.getContactFamilyName()),
375 // .. next is first...
376 StringUtils.compareIgnoreCase(this.getContactFirstName(), contact.getContactFirstName()),
377 // ... next is email address
378 StringUtils.compareIgnoreCase(this.getContactEmailAddress(), contact.getContactEmailAddress()),
379 // ... next birthday - year
380 DateUtils.compareYearMonthDay(this.getContactBirthday(), contact.getContactBirthday()),
381 // ... next "is own" flag
382 BooleanUtils.compare(this.isOwnContact(), contact.isOwnContact()),
384 StringUtils.compare(this.getContactComment(), contact.getContactComment())
388 final int comparison = ComparableUtils.checkAll(comparators);
395 public boolean equals (final Object object) {
396 if (this == object) {
398 } else if (null == object) {
400 } else if (this.getClass() != object.getClass()) {
404 final Contact contact = (Contact) object;
406 if (!Objects.equals(this.getContactBirthday(), contact.getContactBirthday())) {
408 } else if (!Objects.equals(this.getContactCity(), contact.getContactCity())) {
410 } else if (!Objects.equals(this.getContactComment(), contact.getContactComment())) {
412 } else if (!Objects.equals(this.getContactCountry(), contact.getContactCountry())) {
414 } else if (!Objects.equals(this.getContactEmailAddress(), contact.getContactEmailAddress())) {
416 } else if (!Objects.equals(this.getContactFamilyName(), contact.getContactFamilyName())) {
418 } else if (!Objects.equals(this.getContactFaxNumber(), contact.getContactFaxNumber())) {
420 } else if (!Objects.equals(this.getContactFirstName(), contact.getContactFirstName())) {
422 } else if (!Objects.equals(this.getContactHouseNumber(), contact.getContactHouseNumber())) {
424 } else if (!Objects.equals(this.getContactHouseNumberExtension(), contact.getContactHouseNumberExtension())) {
426 } else if (!Objects.equals(this.getContactId(), contact.getContactId())) {
428 } else if (!Objects.equals(this.getContactLandLineNumber(), contact.getContactLandLineNumber())) {
430 } else if (!Objects.equals(this.getContactMobileNumber(), contact.getContactMobileNumber())) {
432 } else if (this.getContactPersonalTitle() != contact.getContactPersonalTitle()) {
434 } else if (!Objects.equals(this.getContactStreet(), contact.getContactStreet())) {
436 } else if (!Objects.equals(this.getContactTitle(), contact.getContactTitle())) {
438 } else if (!Objects.equals(this.getContactZipCode(), contact.getContactZipCode())) {
440 } else if (!Objects.equals(this.isOwnContact(), contact.isOwnContact())) {
448 @SuppressWarnings ("ReturnOfDateField")
449 public Date getContactBirthday () {
450 return this.contactBirthday;
454 @SuppressWarnings ("AssignmentToDateFieldFromParameter")
455 public void setContactBirthday (final Date contactBirthday) {
456 this.contactBirthday = contactBirthday;
460 public String getContactCity () {
461 return this.contactCity;
465 public void setContactCity (final String contactCity) {
466 this.contactCity = contactCity;
470 public String getContactComment () {
471 return this.contactComment;
475 public void setContactComment (final String contactComment) {
476 this.contactComment = contactComment;
480 public Country getContactCountry () {
481 return this.contactCountry;
485 public void setContactCountry (final Country contactCountry) {
486 this.contactCountry = contactCountry;
490 public String getContactEmailAddress () {
491 return this.contactEmailAddress;
495 public void setContactEmailAddress (final String contactEmailAddress) {
496 this.contactEmailAddress = contactEmailAddress;
500 @SuppressWarnings ("ReturnOfDateField")
501 public Date getContactEntryCreated () {
502 return this.contactEntryCreated;
506 @SuppressWarnings ("AssignmentToDateFieldFromParameter")
507 public void setContactEntryCreated (final Date contactEntryCreated) {
508 this.contactEntryCreated = contactEntryCreated;
512 @SuppressWarnings ("ReturnOfDateField")
513 public Date getContactEntryUpdated () {
514 return this.contactEntryUpdated;
518 @SuppressWarnings ("AssignmentToDateFieldFromParameter")
519 public void setContactEntryUpdated (final Date contactEntryUpdated) {
520 this.contactEntryUpdated = contactEntryUpdated;
524 public String getContactFamilyName () {
525 //* NOISY-DEBUG: */ this.getLogger().logTrace("CALLED!");
526 return this.contactFamilyName;
530 public void setContactFamilyName (final String contactFamilyName) {
531 this.contactFamilyName = contactFamilyName;
535 public DialableFaxNumber getContactFaxNumber () {
536 return this.contactFaxNumber;
540 public void setContactFaxNumber (final DialableFaxNumber contactFaxNumber) {
541 this.contactFaxNumber = contactFaxNumber;
545 public String getContactFirstName () {
546 return this.contactFirstName;
550 public void setContactFirstName (final String contactFirstName) {
551 this.contactFirstName = contactFirstName;
555 public Short getContactHouseNumber () {
556 return this.contactHouseNumber;
560 public void setContactHouseNumber (final Short contactHouseNumber) {
561 this.contactHouseNumber = contactHouseNumber;
565 public String getContactHouseNumberExtension () {
566 return this.contactHouseNumberExtension;
570 public void setContactHouseNumberExtension (final String contactHouseNumberExtension) {
571 this.contactHouseNumberExtension = contactHouseNumberExtension;
575 public Long getContactId () {
576 return this.contactId;
580 public void setContactId (final Long contactId) {
581 this.contactId = contactId;
585 public DialableLandLineNumber getContactLandLineNumber () {
586 return this.contactPhoneNumber;
590 public void setContactLandLineNumber (final DialableLandLineNumber contactPhoneNumber) {
591 this.contactPhoneNumber = contactPhoneNumber;
595 public DialableMobileNumber getContactMobileNumber () {
596 return this.contactMobileNumber;
600 public void setContactMobileNumber (final DialableMobileNumber contactMobileNumber) {
601 this.contactMobileNumber = contactMobileNumber;
605 public void setContactOwnContact (final Boolean contactOwnContact) {
606 this.contactOwnContact = contactOwnContact;
610 public PersonalTitle getContactPersonalTitle () {
611 return this.contactPersonalTitle;
615 public void setContactPersonalTitle (final PersonalTitle contactPersonalTitle) {
616 this.contactPersonalTitle = contactPersonalTitle;
620 public String getContactStreet () {
621 return this.contactStreet;
625 public void setContactStreet (final String contactStreet) {
626 this.contactStreet = contactStreet;
630 public String getContactTitle () {
631 return this.contactTitle;
635 public void setContactTitle (final String contactTitle) {
636 this.contactTitle = contactTitle;
640 public Integer getContactZipCode () {
641 return this.contactZipCode;
645 public void setContactZipCode (final Integer contactZipCode) {
646 this.contactZipCode = contactZipCode;
650 public int hashCode () {
653 hash = 29 * hash + Objects.hashCode(this.getContactBirthday());
654 hash = 29 * hash + Objects.hashCode(this.getContactCity());
655 hash = 29 * hash + Objects.hashCode(this.getContactComment());
656 hash = 29 * hash + Objects.hashCode(this.getContactCountry());
657 hash = 29 * hash + Objects.hashCode(this.getContactEmailAddress());
658 hash = 29 * hash + Objects.hashCode(this.getContactFamilyName());
659 hash = 29 * hash + Objects.hashCode(this.getContactFaxNumber());
660 hash = 29 * hash + Objects.hashCode(this.getContactFirstName());
661 hash = 29 * hash + Objects.hashCode(this.getContactHouseNumber());
662 hash = 29 * hash + Objects.hashCode(this.getContactHouseNumberExtension());
663 hash = 29 * hash + Objects.hashCode(this.getContactId());
664 hash = 29 * hash + Objects.hashCode(this.getContactLandLineNumber());
665 hash = 29 * hash + Objects.hashCode(this.getContactMobileNumber());
666 hash = 29 * hash + Objects.hashCode(this.getContactPersonalTitle());
667 hash = 29 * hash + Objects.hashCode(this.getContactStreet());
668 hash = 29 * hash + Objects.hashCode(this.getContactTitle());
669 hash = 29 * hash + Objects.hashCode(this.getContactZipCode());
670 hash = 29 * hash + Objects.hashCode(this.isOwnContact());
676 public Boolean isOwnContact () {
677 return this.contactOwnContact;