Location.java
package org.example.customer.utility;
/*
* This is free and unencumbered software released into the public domain.
* Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software,
* either in source code form or as a compiled binary, for any purpose, commercial or
* non-commercial, and by any means.
*
* In jurisdictions that recognize copyright laws, the author or authors of this
* software dedicate any and all copyright interest in the software to the public domain.
* We make this dedication for the benefit of the public at large and to the detriment of
* our heirs and successors. We intend this dedication to be an overt act of relinquishment in
* perpetuity of all present and future rights to this software under copyright law.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* For more information, please refer to: https://unlicense.org/
*/
import java.io.Serializable;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.example.websecurity.XssSanitizer;
import org.example.websecurity.XssSanitizerImpl;
/**
* The Customer Location for the Customer application.
<br>
<br>
* This class represents the common City and Country fields in the Customer Database
*
* @author Jonathan Earl
* @version 1.0
*
*/
public class Location
implements Serializable
{
private static final long serialVersionUID = 1L;
private static final Logger LOG = LogManager.getLogger();
private String myCity;
private String myCountry;
private XssSanitizer mySanitizer;
/**
* The default constructor for the Location class.
* <p>
* The initial values are:
* <ul>
* <li>city: New York City</li>
* <li>country: United States of America</li>
* </ul>
*/
public Location()
{
this(new XssSanitizerImpl());
LOG.debug("Finishing the default Constructor");
}
/**
* The overloaded constructor for the Location class that takes an XssSanitizer as input.
* <p>
* The initial values are:
* <ul>
* <li>city: New York City</li>
* <li>country: United States of America</li>
* </ul>
*
* @param sanitizer the XssSanitizer used by this instance
*/
public Location(final XssSanitizer sanitizer)
{
LOG.debug("Starting the overloaded Constructor");
final String initialCity = "New York City";
final String initialCountry = "United States of America";
mySanitizer = sanitizer;
setCity(initialCity);
setCountry(initialCountry);
}
/**
* Returns the city value for the Location.
*
* @return the city value for the location
*/
public String getCity()
{
LOG.debug("returning the City: " + myCity);
return myCity;
}
/**
* Sets the city value for the Location.
* <p>
* The business rules are:
* <ul>
* <li>the city <strong>may</strong> be null</li>
* <li>the city must <strong>not</strong> be empty</li>
* <li>the city must min length of 2 chars</li>
* <li>the city must max length of 40 chars</li>
* <li>XSS strings within the city will be removed</li>
* </ul>
*
* @param city the value to set into the location city field
* @throws IllegalArgumentException if the city is invalid
*/
public void setCity(final String city)
{
LOG.debug("setting the City");
final int max = 40;
final int min = 2;
if (city == null)
{
LOG.debug("City is set to null");
this.myCity = null;
return;
}
String safeCity = mySanitizer.sanitizeInput(city);
if (safeCity.isEmpty())
{
LOG.error("City must not be empty");
throw new IllegalArgumentException("City must not be empty");
}
if (safeCity.length() > max || safeCity.length() < min)
{
LOG.error("City must be between 2 and 40 chars in length");
throw new IllegalArgumentException("City must be between 2 and 40 chars in length");
}
LOG.debug("setting the City to: " + safeCity);
this.myCity = safeCity;
}
/**
* Returns the country value for the Location.
*
* @return the country value for the location
*/
public String getCountry()
{
LOG.debug("returning the Country: " + myCountry);
return myCountry;
}
/**
* Sets the country value for the Location.
* <p>
* The business rules are:
* <ul>
* <li>the country <strong>may</strong> be null</li>
* <li>the country must <strong>not</strong> be empty</li>
* <li>the country must min length of 2 chars</li>
* <li>the country must max length of 40 chars</li>
* <li>XSS strings within the country will be removed</li>
* </ul>
*
* @param country the value to set into the location country field
* @throws IllegalArgumentException if the country is invalid
*/
public void setCountry(final String country)
{
LOG.debug("setting the Country");
final int max = 40;
final int min = 2;
if (country == null)
{
LOG.debug("Country is set to null");
this.myCountry = null;
return;
}
String safeCountry = mySanitizer.sanitizeInput(country);
if (safeCountry.isEmpty())
{
LOG.error("Country must not be empty");
throw new IllegalArgumentException("Country must not be empty");
}
if (safeCountry.length() > max || safeCountry.length() < min)
{
LOG.error("Country must be between 2 and 40 chars in length");
throw new IllegalArgumentException("Country must be between 2 and 40 chars in length");
}
LOG.debug("setting the Country to: " + safeCountry);
this.myCountry = safeCountry;
}
/**
* The hashCode() method of the Location class.
* <p>
* <strong>This method uses:</strong>
* <ul>
* <li>city</li>
* <li>country</li>
* </ul>
*
* @see java.lang.Object#hashCode()
* @return the hashCode value for this Location object
*/
@Override
public int hashCode()
{
LOG.debug("building HashCode");
return new HashCodeBuilder()
.append(getCity())
.append(getCountry())
.toHashCode();
}
/**
* The equals() method of the Location class.
* <p>
* <strong>This method uses:</strong>
* <ul>
* <li>city</li>
* <li>country</li>
* </ul>
*
* @see java.lang.Object#equals(Object obj)
* @param obj the incoming object to compare against
* @return true if the fields being compared are equal
*/
@Override
public boolean equals(final Object obj)
{
LOG.debug("checking equals");
if (obj instanceof Location)
{
final Location other = (Location) obj;
return new EqualsBuilder()
.append(getCity(), other.getCity())
.append(getCountry(), other.getCountry())
.isEquals();
}
else
{
return false;
}
}
/**
* The toString method for the Location class.
*
* this method will return:<br>
* Location [City=xxx Country=XXX]
*/
@Override
public String toString()
{
return "Location [City=" + myCity + ", Country=" + myCountry + "]";
}
}