View Javadoc

    1   package org.example.customer;
    2
    3   /*
    4    * This is free and unencumbered software released into the public domain.
    5    * Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software,
    6    * either in source code form or as a compiled binary, for any purpose, commercial or
    7    * non-commercial, and by any means.
    8    *
    9    * In jurisdictions that recognize copyright laws, the author or authors of this
    10   * software dedicate any and all copyright interest in the software to the public domain.
    11   * We make this dedication for the benefit of the public at large and to the detriment of
    12   * our heirs and successors. We intend this dedication to be an overt act of relinquishment in
    13   * perpetuity of all present and future rights to this software under copyright law.
    14   *
    15   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
    16   * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
    17   * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES
    18   * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    20   *
    21   * For more information, please refer to: https://unlicense.org/
    22  */
    23
    24  import java.io.Serializable;
    25
    26  import org.apache.commons.lang3.builder.EqualsBuilder;
    27  import org.apache.commons.lang3.builder.HashCodeBuilder;
    28  import org.apache.logging.log4j.LogManager;
    29  import org.apache.logging.log4j.Logger;
    30  import org.example.customer.utility.CustomerEntity;
    31  import org.example.customer.utility.Location;
    32  import org.example.customer.utility.Phone;
    33  import org.example.websecurity.XssSanitizer;
    34  import org.example.websecurity.XssSanitizerImpl;
    35
    36  /**
    37   * The Customer Entity for the Customer application.
    38   * <br>
    39   * <br>
    40   * This class represents the following DB Table:
    41   *
    42   * <pre>
    43   * CREATE TABLE CUSTOMER (
    44   *      ID INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1),
    45   *      FIRST_NAME VARCHAR(40) NOT NULL,
    46   *      LAST_NAME VARCHAR(40) NOT NULL,
    47   *      CITY VARCHAR(40),
    48   *      COUNTRY VARCHAR(40),
    49   *      PHONE VARCHAR(20),
    50   *      CONSTRAINT PK_CUSTOMER PRIMARY KEY (ID)
    51   *   );
    52   * </pre>
    53   *
    54   * @author Jonathan Earl
    55   * @version 1.0
    56   *
    57   */
    58  public final class Customer extends CustomerEntity
    59      implements Serializable, Comparable<Customer>
    60  {
    61      private static final long serialVersionUID = 1L;
    62
    63      private static final Logger LOG = LogManager.getLogger();
    64
    65      private String myFirstName;
    66      private String myLastName;
    67      private Location myLocation;
    68      private Phone myPhone;
    69
    70      private XssSanitizer mySanitizer;
    71
    72      /**
    73       * The default constructor for the Customer class.
    74       * <p>
    75       * The initial values are:
    76       * <ul>
    77       *   <li>id: 1</li>
    78       *   <li>first name: John</li>
    79       *   <li>last name: Smith</li>
    80       *   <li>city: New York City</li>
    81       *   <li>country: United States of America</li>
    82       *   <li>phone: null</li>
    83       * </ul>
    84       */
    85      public Customer()
    86      {
    87          this(new XssSanitizerImpl());
    88          LOG.debug("Finishing the default Constructor");
    89      }
    90
    91      /**
    92       * The overloaded constructor for the Customer class that takes an XssSanitizer as input.
    93       * <p>
    94       * The initial values are:
    95       * <ul>
    96       *   <li>id: 1</li>
    97       *   <li>first name: John</li>
    98       *   <li>last name: Smith</li>
    99       *   <li>city: New York City</li>
    100      *   <li>country: United States of America</li>
    101      *   <li>phone: null</li>
    102      * </ul>
    103      *
    104      * @param sanitizer the XssSanitizer used by this instance
    105      */
    106     public Customer(final XssSanitizer sanitizer)
    107     {
    108         LOG.debug("Starting the overloaded Constructor");
    109         final int initialId = 1;
    110         final String initialFirstName = "John";
    111         final String initialLastName = "Smith";
    112         final String initialNumber = null;
    113
    114         mySanitizer = sanitizer;
    115
    116         setId(initialId);
    117         setFirstName(initialFirstName);
    118         setLastName(initialLastName);
    119         setLocation(new Location());
    120         Phone temp2 = new Phone();
    121         temp2.setNumber(initialNumber);
    122         setPhone(temp2);
    123     }
    124
    125     /**
    126      * This will enable sorting of Customers by full name.
    127      * <br>
    128      * <br>
    129      * @param other the Customer object to compare with
    130      * @return the sort value of negative/zero/positive
    131      */
    132     @Override
    133     public int compareTo(Customer other)
    134     {
    135         String thisFullName = this.getFirstName() + " "
    136                 + this.getLastName();
    137         String otherFullName = other.getFirstName() + " "
    138                 + other.getLastName();
    139         return thisFullName.compareToIgnoreCase(otherFullName);
    140     }
    141
    142     /**
    143      * Returns the first name value for the Customer.
    144      *
    145      * @return the first name value for the customer
    146      */
    147     public String getFirstName()
    148     {
    149         LOG.debug("returning the First Name: " + myFirstName);
    150         return myFirstName;
    151     }
    152
    153     /**
    154      * Sets the first name value for the Customer.
    155      * <br>
    156      * <br>
    157      * The business rules are:
    158      * <ul>
    159      *   <li>the first name must <strong>not</strong> be null</li>
    160      *   <li>the first name must <strong>not</strong> be empty</li>
    161      *   <li>the first name must max length of 40 chars</li>
    162      *   <li>XSS strings within the first name will be removed</li>
    163      * </ul>
    164      *
    165      * @param firstName the value to set into the customer first name field
    166      * @throws IllegalArgumentException if the first name is invalid
    167      */
    168     public void setFirstName(final String firstName)
    169     {
    170         LOG.debug("setting the First Name");
    171         final int max = 40;
    172
    173         if (firstName == null)
    174         {
    175             LOG.error("First Name must not be null");
    176             throw new IllegalArgumentException("First Name must not be null");
    177         }
    178
    179         String safeFirstName = mySanitizer.sanitizeInput(firstName);
    180         if (safeFirstName.isEmpty())
    181         {
    182             LOG.error("First Name must not be empty");
    183             throw new IllegalArgumentException("First Name must not be empty");
    184         }
    185         if (safeFirstName.length() > max)
    186         {
    187             LOG.error("First Name must be up to 40 chars in length");
    188             throw new IllegalArgumentException("First Name must be up to 40 chars in length");
    189         }
    190         LOG.debug("setting the First Name to: " + safeFirstName);
    191         this.myFirstName = safeFirstName;
    192     }
    193
    194     /**
    195      * Returns the last name value for the Customer.
    196      *
    197      * @return the last name value for the customer
    198      */
    199     public String getLastName()
    200     {
    201         LOG.debug("returning the Last Name: " + myLastName);
    202         return myLastName;
    203     }
    204
    205     /**
    206      * Sets the last name value for the Customer.
    207      * <p>
    208      * The business rules are:
    209      * <ul>
    210      *   <li>the last name must <strong>not</strong> be null</li>
    211      *   <li>the last name must <strong>not</strong> be empty</li>
    212      *   <li>the last name must min length of 2 chars</li>
    213      *   <li>the last name must max length of 40 chars</li>
    214      *   <li>XSS strings within the last name will be removed</li>
    215      * </ul>
    216      *
    217      * @param lastName the value to set into the customer last name field
    218      * @throws IllegalArgumentException if the last name is invalid
    219      */
    220     public void setLastName(final String lastName)
    221     {
    222         LOG.debug("setting the Last Name");
    223         final int max = 40;
    224         final int min = 2;
    225
    226         if (lastName == null)
    227         {
    228             LOG.error("Last Name must not be null");
    229             throw new IllegalArgumentException("Last Name must not be null");
    230         }
    231
    232         String safeLastName = mySanitizer.sanitizeInput(lastName);
    233         if (safeLastName.isEmpty())
    234         {
    235             LOG.error("Last Name must not be empty");
    236             throw new IllegalArgumentException("Last Name must not be empty");
    237         }
    238         if (safeLastName.length() > max || safeLastName.length() < min)
    239         {
    240             LOG.error("Last Name must be between 2 and 40 chars in length");
    241             throw new IllegalArgumentException("Last Name must be between 2 and 40 chars in length");
    242         }
    243         LOG.debug("setting the Last Name to: " + safeLastName);
    244         this.myLastName = safeLastName;
    245     }
    246
    247     /**
    248      * Return the Location for the Customer.
    249      * <p>
    250      * @return the myLocation
    251      */
    252     public Location getLocation()
    253     {
    254         LOG.debug("returning the Location: " + myLocation);
    255         return myLocation;
    256     }
    257
    258     /**
    259      * Sets the location value for the Customer.
    260      * <p>
    261      * The business rules are:
    262      * <ul>
    263      *   <li>the location <strong>may</strong> be null</li>
    264      * </ul>
    265      *
    266      * @param location the value to set into the customer location field
    267      * @throws IllegalArgumentException if the location is invalid
    268      */
    269     public void setLocation(final Location location)
    270     {
    271         LOG.debug("setting the Location");
    272         if (location == null)
    273         {
    274             LOG.error("Location must not be null");
    275             throw new IllegalArgumentException("Location must not be null");
    276         }
    277         this.myLocation = location;
    278     }
    279
    280     /**
    281      * Returns the phone value for the Customer.
    282      *
    283      * @return the phone value for the customer
    284      */
    285     public Phone getPhone()
    286     {
    287         LOG.debug("returning the Phone: " + myPhone);
    288         return myPhone;
    289     }
    290
    291     /**
    292      * Sets the phone value for the Customer.
    293      * <p>
    294      * The business rules are:
    295      * <ul>
    296      *   <li>the phone <strong>may</strong> be null</li>
    297      * </ul>
    298      *
    299      * @param phone the value to set into the customer phone field
    300      * @throws IllegalArgumentException if the phone is invalid
    301      */
    302     public void setPhone(final Phone phone)
    303     {
    304         LOG.debug("setting the Phone");
    305         this.myPhone = phone;
    306     }
    307
    308     /**
    309      * The hashCode() method of the Customer class.
    310      * <p>
    311      * <strong>This method uses:</strong>
    312      * <ul>
    313      *  <li>id</li>
    314      *  <li>first name</li>
    315      *  <li>last name</li>
    316      *  <li>city</li>
    317      *  <li>country</li>
    318      * </ul>
    319      *
    320      * @see java.lang.Object#hashCode()
    321      * @return the hashCode value for this Customer object
    322      */
    323     @Override
    324     public int hashCode()
    325     {
    326         LOG.debug("building HashCode");
    327         return new HashCodeBuilder()
    328                 .append(getId())
    329                 .append(myFirstName)
    330                 .append(myLastName)
    331                 .append(myLocation.hashCode())
    332                 .toHashCode();
    333     }
    334
    335     /**
    336      * The equals() method of the Customer class.
    337      * <p>
    338      * <strong>This method uses:</strong>
    339      * <ul>
    340      *  <li>id</li>
    341      *  <li>first name</li>
    342      *  <li>last name</li>
    343      *  <li>city</li>
    344      *  <li>country</li>
    345      * </ul>
    346      *
    347      * @see java.lang.Object#equals(Object obj)
    348      * @param obj the incoming object to compare against
    349      * @return true if the fields being compared are equal
    350      */
    351     @Override
    352     public boolean equals(final Object obj)
    353     {
    354         LOG.debug("checking equals");
    355         if (obj instanceof Customer)
    356         {
    357             final Customer other = (Customer) obj;
    358             return new EqualsBuilder()
    359                     .append(getId(), other.getId())
    360                     .append(myFirstName, other.myFirstName)
    361                     .append(myLastName, other.myLastName)
    362                     .append(myLocation.getCity(), other.myLocation.getCity())
    363                     .append(myLocation.getCountry(), other.myLocation.getCountry())
    364                     .isEquals();
    365         }
    366         else
    367         {
    368             return false;
    369         }
    370     }
    371
    372     /**
    373      * The toString method for the Customer class.
    374      *
    375      * this method will return:<br>
    376      * Customer [Id=xxx, FirstName=xxx, LastName=xxx, City=xxx,
    377      *      Country=xxx, Phone=xxx]
    378      */
    379     @Override
    380     public String toString()
    381     {
    382         return "Customer [Id=" + getId() + ", FirstName=" + myFirstName
    383                 + ", LastName=" + myLastName + ", City="
    384                 + myLocation.getCity() + ", Country=" + myLocation.getCountry()
    385                 + ", Phone=" + myPhone.getNumber() + "]";
    386     }
    387
    388 }