├── .gitignore ├── lib ├── .gnupg │ ├── pubring.kbx │ ├── trustdb.gpg │ └── private-keys-v1.d │ │ └── 583C2B738106FEB6CC4DA0E65FDD4A57D6688BC2.key └── settings.xml ├── CHANGELOG.md ├── src ├── main │ └── java │ │ ├── com │ │ └── smartystreets │ │ │ └── api │ │ │ ├── Logger.java │ │ │ ├── Sleeper.java │ │ │ ├── us_enrichment │ │ │ ├── result_types │ │ │ │ ├── Attributes.java │ │ │ │ ├── risk │ │ │ │ │ └── RiskResponse.java │ │ │ │ ├── property_principal │ │ │ │ │ ├── PrincipalResponse.java │ │ │ │ │ └── PrincipalFinancialHistoryEntry.java │ │ │ │ ├── MatchedAddress.java │ │ │ │ ├── georeference │ │ │ │ │ ├── GeoReferenceResponse.java │ │ │ │ │ └── GeoReferenceAttributes.java │ │ │ │ ├── secondary │ │ │ │ │ ├── SecondaryCountResponse.java │ │ │ │ │ ├── Secondary.java │ │ │ │ │ ├── SecondaryResponse.java │ │ │ │ │ ├── Alias.java │ │ │ │ │ └── RootAddress.java │ │ │ │ ├── Result.java │ │ │ │ ├── EnrichmentToStringer.java │ │ │ │ └── AddressSearch.java │ │ │ └── lookup_types │ │ │ │ ├── risk │ │ │ │ └── RiskLookup.java │ │ │ │ ├── secondary │ │ │ │ ├── SecondaryLookup.java │ │ │ │ └── SecondaryCountLookup.java │ │ │ │ ├── property_principal │ │ │ │ └── PropertyPrincipalLookup.java │ │ │ │ └── georeference │ │ │ │ └── GeoReferenceLookup.java │ │ │ ├── Version.java │ │ │ ├── MyLogger.java │ │ │ ├── Credentials.java │ │ │ ├── MySleeper.java │ │ │ ├── Sender.java │ │ │ ├── exceptions │ │ │ ├── SmartyException.java │ │ │ ├── BatchFullException.java │ │ │ ├── ForbiddenException.java │ │ │ ├── NotModifiedException.java │ │ │ ├── BadRequestException.java │ │ │ ├── BadCredentialsException.java │ │ │ ├── GatewayTimeoutException.java │ │ │ ├── PaymentRequiredException.java │ │ │ ├── InternalServerErrorException.java │ │ │ ├── ServiceUnavailableException.java │ │ │ ├── UnprocessableEntityException.java │ │ │ └── RequestEntityTooLargeException.java │ │ │ ├── us_reverse_geo │ │ │ ├── SmartyResponse.java │ │ │ ├── Result.java │ │ │ ├── Coordinate.java │ │ │ ├── Address.java │ │ │ ├── Lookup.java │ │ │ └── Client.java │ │ │ ├── us_street │ │ │ ├── CountySource.java │ │ │ ├── MatchType.java │ │ │ ├── OutputFormat.java │ │ │ ├── MatchInfo.java │ │ │ ├── Analysis.java │ │ │ ├── Batch.java │ │ │ ├── Candidate.java │ │ │ ├── ComponentAnalysis.java │ │ │ ├── Metadata.java │ │ │ ├── Client.java │ │ │ └── Components.java │ │ │ ├── InternationalGeolocateType.java │ │ │ ├── international_autocomplete │ │ │ ├── Result.java │ │ │ ├── Candidate.java │ │ │ ├── Client.java │ │ │ └── Lookup.java │ │ │ ├── us_autocomplete_pro │ │ │ ├── Result.java │ │ │ ├── Suggestion.java │ │ │ └── Client.java │ │ │ ├── international_street │ │ │ ├── Changes.java │ │ │ ├── LanguageMode.java │ │ │ ├── Candidate.java │ │ │ ├── Analysis.java │ │ │ ├── Metadata.java │ │ │ ├── RootLevel.java │ │ │ └── Client.java │ │ │ ├── TooManyRequestsResponse.java │ │ │ ├── Serializer.java │ │ │ ├── GeolocateType.java │ │ │ ├── SharedCredentials.java │ │ │ ├── SigningSender.java │ │ │ ├── URLPrefixSender.java │ │ │ ├── us_extract │ │ │ ├── Result.java │ │ │ ├── Address.java │ │ │ ├── Metadata.java │ │ │ ├── Client.java │ │ │ └── Lookup.java │ │ │ ├── CustomHeaderSender.java │ │ │ ├── StaticCredentials.java │ │ │ ├── CustomQuerySender.java │ │ │ ├── Response.java │ │ │ ├── LicenseSender.java │ │ │ ├── us_zipcode │ │ │ ├── AlternateCounty.java │ │ │ ├── City.java │ │ │ ├── Result.java │ │ │ ├── ZipCode.java │ │ │ ├── Batch.java │ │ │ ├── Client.java │ │ │ └── Lookup.java │ │ │ ├── SmartySerializer.java │ │ │ ├── international_postal_code │ │ │ ├── Candidate.java │ │ │ ├── Lookup.java │ │ │ └── Client.java │ │ │ ├── StatusCodeSender.java │ │ │ ├── RetrySender.java │ │ │ └── Request.java │ │ └── examples │ │ ├── InternationalPostalCodeExample.java │ │ ├── UsZipCodeSingleLookupExample.java │ │ ├── UsReverseGeoExample.java │ │ ├── InternationalAutocompleteExample.java │ │ ├── UsStreetComponentAnalysisExample.java │ │ ├── UsAutocompleteProExample.java │ │ ├── InternationalExample.java │ │ ├── UsExtractExample.java │ │ └── UsStreetSingleAddressExample.java └── test │ └── java │ └── com │ └── smartystreets │ └── api │ ├── mocks │ ├── FakeLogger.java │ ├── FakeSleeper.java │ ├── RequestCapturingSender.java │ ├── MockStatusCodeSender.java │ ├── MockSender.java │ ├── FakeDeserializer.java │ ├── FakeSerializer.java │ └── MockCrashingSender.java │ ├── us_zipcode │ ├── ResultTest.java │ └── BatchTest.java │ ├── SharedCredentialsTest.java │ ├── us_autocomplete_pro │ ├── SuggestionTest.java │ └── ClientTest.java │ ├── CustomHeaderSenderTest.java │ ├── us_reverse_geo │ └── ClientTest.java │ ├── XForwardedForTest.java │ ├── StaticCredentialsTest.java │ ├── LicenseSenderTest.java │ ├── SigningSenderTest.java │ ├── us_street │ └── BatchTest.java │ ├── URLPrefixSenderTest.java │ ├── us_extract │ └── ResultTest.java │ ├── StatusCodeSenderTest.java │ ├── CustomQuerySenderTest.java │ ├── international_autocomplete │ └── CandidateTest.java │ ├── SmartySerializerTest.java │ └── RetrySenderTest.java ├── README.md ├── .github └── workflows │ └── publish.yml └── Makefile /.gitignore: -------------------------------------------------------------------------------- 1 | *DS_Store* 2 | *.swp 3 | *.iml 4 | __MACOSX 5 | **/.idea/ 6 | /target/ 7 | -------------------------------------------------------------------------------- /lib/.gnupg/pubring.kbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartystreets/smartystreets-java-sdk/HEAD/lib/.gnupg/pubring.kbx -------------------------------------------------------------------------------- /lib/.gnupg/trustdb.gpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartystreets/smartystreets-java-sdk/HEAD/lib/.gnupg/trustdb.gpg -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | See the changelog repository: 4 | 5 | github.com/smartystreets/changelog/blob/master/sdk/java.md -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/Logger.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api; 2 | 3 | 4 | public interface Logger { 5 | void log(String message); 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/Sleeper.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api; 2 | 3 | 4 | public interface Sleeper { 5 | void sleep(long seconds) throws InterruptedException; 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_enrichment/result_types/Attributes.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_enrichment.result_types; 2 | 3 | public class Attributes extends EnrichmentToStringer { 4 | } 5 | -------------------------------------------------------------------------------- /lib/.gnupg/private-keys-v1.d/583C2B738106FEB6CC4DA0E65FDD4A57D6688BC2.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartystreets/smartystreets-java-sdk/HEAD/lib/.gnupg/private-keys-v1.d/583C2B738106FEB6CC4DA0E65FDD4A57D6688BC2.key -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/Version.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api; 2 | 3 | public class Version { 4 | static final String CURRENT = "0.0.0"; // DO NOT EDIT (this is updated by a build job when a new release is published) 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/MyLogger.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api; 2 | 3 | 4 | public class MyLogger implements Logger{ 5 | @Override 6 | public void log(String message) { 7 | System.out.println(message); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/Credentials.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api; 2 | 3 | /** 4 | * Credentials are classes that 'sign' requests by adding SmartyStreets authentication keys. 5 | */ 6 | public interface Credentials { 7 | void sign(Request request); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/MySleeper.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api; 2 | 3 | 4 | public class MySleeper implements Sleeper{ 5 | 6 | public void sleep(long seconds) throws InterruptedException { 7 | Thread.sleep(seconds * 1000); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/Sender.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api; 2 | 3 | import com.smartystreets.api.exceptions.SmartyException; 4 | 5 | import java.io.IOException; 6 | 7 | public interface Sender { 8 | Response send(Request request) throws SmartyException, IOException, InterruptedException; 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/exceptions/SmartyException.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.exceptions; 2 | 3 | public class SmartyException extends Exception { 4 | public SmartyException() { 5 | super(); 6 | } 7 | 8 | public SmartyException(String message) { 9 | super(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_reverse_geo/SmartyResponse.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_reverse_geo; 2 | 3 | import java.io.Serializable; 4 | 5 | public class SmartyResponse implements Serializable { 6 | 7 | private Result[] results; 8 | 9 | public Result[] getResults() { return this.results; } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/exceptions/BatchFullException.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.exceptions; 2 | 3 | public class BatchFullException extends SmartyException { 4 | public BatchFullException() { 5 | super(); 6 | } 7 | 8 | public BatchFullException(String message) { 9 | super(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/exceptions/ForbiddenException.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.exceptions; 2 | 3 | public class ForbiddenException extends SmartyException{ 4 | public ForbiddenException() { 5 | super(); 6 | } 7 | 8 | public ForbiddenException(String message) { 9 | super(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/exceptions/NotModifiedException.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.exceptions; 2 | 3 | public class NotModifiedException extends SmartyException { 4 | public NotModifiedException(){ 5 | super(); 6 | } 7 | public NotModifiedException(String message){ 8 | super(message); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/exceptions/BadRequestException.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.exceptions; 2 | 3 | public class BadRequestException extends SmartyException { 4 | public BadRequestException() { 5 | super(); 6 | } 7 | 8 | public BadRequestException(String message) { 9 | super(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/exceptions/BadCredentialsException.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.exceptions; 2 | 3 | public class BadCredentialsException extends SmartyException { 4 | public BadCredentialsException() { 5 | super(); 6 | } 7 | 8 | public BadCredentialsException(String message) { 9 | super(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/exceptions/GatewayTimeoutException.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.exceptions; 2 | 3 | public class GatewayTimeoutException extends SmartyException{ 4 | public GatewayTimeoutException() { 5 | super(); 6 | } 7 | 8 | public GatewayTimeoutException(String message) { 9 | super(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/exceptions/PaymentRequiredException.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.exceptions; 2 | 3 | public class PaymentRequiredException extends SmartyException { 4 | public PaymentRequiredException() { 5 | super(); 6 | } 7 | 8 | public PaymentRequiredException(String message) { 9 | super(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/exceptions/InternalServerErrorException.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.exceptions; 2 | 3 | public class InternalServerErrorException extends SmartyException { 4 | public InternalServerErrorException() { 5 | super(); 6 | } 7 | 8 | public InternalServerErrorException(String message) { 9 | super(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/exceptions/ServiceUnavailableException.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.exceptions; 2 | 3 | public class ServiceUnavailableException extends SmartyException { 4 | public ServiceUnavailableException() { 5 | super(); 6 | } 7 | 8 | public ServiceUnavailableException(String message) { 9 | super(message); 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/exceptions/UnprocessableEntityException.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.exceptions; 2 | 3 | public class UnprocessableEntityException extends SmartyException{ 4 | public UnprocessableEntityException() { 5 | super(); 6 | } 7 | 8 | public UnprocessableEntityException(String message) { 9 | super(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/exceptions/RequestEntityTooLargeException.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.exceptions; 2 | 3 | public class RequestEntityTooLargeException extends SmartyException { 4 | public RequestEntityTooLargeException() { 5 | super(); 6 | } 7 | 8 | public RequestEntityTooLargeException(String message) { 9 | super(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_street/CountySource.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_street; 2 | 3 | public enum CountySource { 4 | POSTAL("postal"), GEOGRAPHIC("geographic"); 5 | 6 | private final String name; 7 | 8 | CountySource(String name){ 9 | this.name = name; 10 | } 11 | 12 | public String getName(){ 13 | return name; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_street/MatchType.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_street; 2 | 3 | public enum MatchType { 4 | STRICT("strict"), INVALID("invalid"), ENHANCED("enhanced"); 5 | 6 | private final String name; 7 | 8 | MatchType(String name){ 9 | this.name = name; 10 | } 11 | 12 | public String getName(){ 13 | return name; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_street/OutputFormat.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_street; 2 | 3 | public enum OutputFormat { 4 | DEFAULT("default"), PROJECT_USA("project-usa"); 5 | 6 | private final String name; 7 | 8 | OutputFormat(String name){ 9 | this.name = name; 10 | } 11 | 12 | public String getName(){ 13 | return name; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_enrichment/result_types/risk/RiskResponse.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_enrichment.result_types.risk; 2 | 3 | import com.smartystreets.api.us_enrichment.result_types.Result; 4 | 5 | public class RiskResponse extends Result { 6 | private RiskAttributes attributes; 7 | 8 | public RiskAttributes getAttributes() { 9 | return attributes; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_enrichment/result_types/property_principal/PrincipalResponse.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_enrichment.result_types.property_principal; 2 | 3 | import com.smartystreets.api.us_enrichment.result_types.Result; 4 | 5 | public class PrincipalResponse extends Result { 6 | private PrincipalAttributes attributes; 7 | 8 | public PrincipalAttributes getAttributes() { 9 | return attributes; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_enrichment/result_types/MatchedAddress.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_enrichment.result_types; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import com.smartystreets.api.us_enrichment.result_types.EnrichmentToStringer; 5 | 6 | public class MatchedAddress extends EnrichmentToStringer { 7 | public String street; 8 | public String city; 9 | public String state; 10 | public String zipcode; 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/InternationalGeolocateType.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api; 2 | 3 | public enum InternationalGeolocateType { 4 | 5 | ADMIN_AREA("adminarea"), LOCALITY("locality"), POSTAL_CODE("postalcode"), GEOCODES("geocodes"), NONE(""); 6 | private final String name; 7 | 8 | InternationalGeolocateType(String name){ 9 | this.name = name; 10 | } 11 | 12 | public String getName(){ 13 | return name; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/international_autocomplete/Result.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.international_autocomplete; 2 | 3 | import java.io.Serializable; 4 | 5 | public class Result implements Serializable { 6 | private Candidate[] candidates; 7 | 8 | public Candidate[] getCandidates() { 9 | return this.candidates; 10 | } 11 | 12 | public Candidate getCandidate(int index) { 13 | return this.candidates[index]; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_autocomplete_pro/Result.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_autocomplete_pro; 2 | 3 | 4 | import java.io.Serializable; 5 | 6 | public class Result implements Serializable { 7 | private Suggestion[] suggestions; 8 | 9 | public Suggestion[] getSuggestions() { 10 | return this.suggestions; 11 | } 12 | 13 | public Suggestion getSuggestion(int index) { 14 | return this.suggestions[index]; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/test/java/com/smartystreets/api/mocks/FakeLogger.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.mocks; 2 | 3 | 4 | import com.smartystreets.api.Logger; 5 | 6 | import java.util.ArrayList; 7 | 8 | public class FakeLogger implements Logger{ 9 | private ArrayList log = new ArrayList<>(); 10 | 11 | public void log(String message) { 12 | this.log.add(message); 13 | } 14 | 15 | public ArrayList getLog() { 16 | return log; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/international_street/Changes.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.international_street; 2 | 3 | import java.io.Serializable; 4 | 5 | public class Changes extends RootLevel implements Serializable { 6 | 7 | //region [ Fields ] 8 | 9 | private Components components; 10 | 11 | //endregion 12 | 13 | //region [ Getters ] 14 | 15 | public Components getComponents() { 16 | return components; 17 | } 18 | 19 | //endregion 20 | } -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/TooManyRequestsResponse.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api; 2 | 3 | import okhttp3.Headers; 4 | 5 | public class TooManyRequestsResponse extends Response { 6 | 7 | private Headers headers; 8 | 9 | public TooManyRequestsResponse(Headers headers, int statusCode, byte[] payload) { 10 | super(statusCode, payload); 11 | this.headers = headers; 12 | } 13 | 14 | public Headers getHeaders() { 15 | return headers; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/Serializer.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api; 2 | 3 | import com.smartystreets.api.us_reverse_geo.SmartyResponse; 4 | import okhttp3.Headers; 5 | 6 | import java.io.IOException; 7 | 8 | public interface Serializer { 9 | byte[] serialize(Object obj) throws IOException; 10 | 11 | T deserialize(byte[] payload, Class type, Headers headers) throws IOException; 12 | 13 | T deserialize(byte[] payload, Class type) throws IOException; 14 | 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/test/java/com/smartystreets/api/mocks/FakeSleeper.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.mocks; 2 | 3 | 4 | import com.smartystreets.api.Sleeper; 5 | 6 | import java.util.ArrayList; 7 | 8 | public class FakeSleeper implements Sleeper{ 9 | private ArrayList sleepDurations = new ArrayList<>(); 10 | 11 | public void sleep(long seconds) throws InterruptedException { 12 | this.sleepDurations.add(seconds); 13 | } 14 | 15 | public ArrayList getSleepDurations() { 16 | return this.sleepDurations; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/GeolocateType.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api; 2 | 3 | /** 4 | * This field corresponds to the geolocate_precision field in the US Autocomplete Pro API. 5 | * 6 | * @see "https://smartystreets.com/docs/cloud/us-autocomplete-pro-api#http-request-input-fields" 7 | */ 8 | public enum GeolocateType { 9 | CITY("city"), NONE("none"); 10 | 11 | private final String name; 12 | 13 | GeolocateType(String name){ 14 | this.name = name; 15 | } 16 | 17 | public String getName(){ 18 | return name; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_street/MatchInfo.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_street; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | import java.io.Serializable; 6 | import java.util.List; 7 | 8 | public class MatchInfo implements Serializable { 9 | private String status; 10 | private List change; 11 | 12 | @JsonProperty("status") 13 | public String getStatus() { 14 | return status; 15 | } 16 | 17 | @JsonProperty("change") 18 | public List getChange() { 19 | return change; 20 | } 21 | } 22 | 23 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_reverse_geo/Result.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_reverse_geo; 2 | 3 | import java.io.Serializable; 4 | 5 | public class Result implements Serializable { 6 | //region [ Fields ] 7 | 8 | private Address address; 9 | private Coordinate coordinate; 10 | private double distance; 11 | 12 | //endregion 13 | 14 | public Address getAddress() { 15 | return this.address; 16 | } 17 | 18 | public Coordinate getCoordinate() { return this.coordinate; } 19 | 20 | public Double getDistance() { return this.distance; } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/SharedCredentials.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api; 2 | 3 | /** 4 | * SharedCredentials is useful if you want to use a website key. 5 | */ 6 | public class SharedCredentials implements Credentials { 7 | private String id; 8 | private String hostname; 9 | 10 | public SharedCredentials(String id, String hostname) { 11 | this.id = id; 12 | this.hostname = hostname; 13 | } 14 | 15 | public void sign(Request request) { 16 | request.putParameter("key", this.id); 17 | request.putHeader("Referer", this.hostname); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/SigningSender.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api; 2 | 3 | import com.smartystreets.api.exceptions.SmartyException; 4 | 5 | import java.io.IOException; 6 | 7 | public class SigningSender implements Sender { 8 | private final Credentials signer; 9 | private final Sender inner; 10 | 11 | public SigningSender(Credentials signer, Sender inner) { 12 | this.signer = signer; 13 | this.inner = inner; 14 | } 15 | 16 | public Response send(Request request) throws SmartyException, IOException, InterruptedException { 17 | this.signer.sign(request); 18 | return this.inner.send(request); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/URLPrefixSender.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api; 2 | 3 | 4 | import com.smartystreets.api.exceptions.SmartyException; 5 | 6 | import java.io.IOException; 7 | 8 | public class URLPrefixSender implements Sender{ 9 | private String urlPrefix; 10 | private Sender inner; 11 | 12 | public URLPrefixSender(String urlPrefix, Sender inner) { 13 | this.urlPrefix = urlPrefix; 14 | this.inner = inner; 15 | } 16 | 17 | public Response send(Request request) throws IOException, SmartyException, InterruptedException { 18 | request.setUrlPrefix(this.urlPrefix); 19 | 20 | return this.inner.send(request); 21 | } 22 | } -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_enrichment/result_types/georeference/GeoReferenceResponse.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_enrichment.result_types.georeference; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import com.smartystreets.api.us_enrichment.result_types.Result; 5 | 6 | public class GeoReferenceResponse extends Result { 7 | @JsonProperty("data_set_version") 8 | private String dataSetVersion; 9 | 10 | private GeoReferenceAttributes attributes; 11 | public GeoReferenceAttributes getAttributes() { 12 | return attributes; 13 | } 14 | 15 | public String getDataSetVersion() { 16 | return this.dataSetVersion; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/international_street/LanguageMode.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.international_street; 2 | 3 | /** 4 | * When not set, the output language will match the language of the input values. When set to NATIVE the
5 | * results will always be in the language of the output country. When set to LATIN the results
6 | * will always be provided using a Latin character set. 7 | */ 8 | public enum LanguageMode { 9 | NATIVE("native"), LATIN("latin"); 10 | 11 | private final String name; 12 | 13 | LanguageMode(String name){ 14 | this.name = name; 15 | } 16 | 17 | public String getName(){ 18 | return name; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/test/java/com/smartystreets/api/mocks/RequestCapturingSender.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.mocks; 2 | 3 | import com.smartystreets.api.Request; 4 | import com.smartystreets.api.Response; 5 | import com.smartystreets.api.Sender; 6 | import com.smartystreets.api.exceptions.SmartyException; 7 | 8 | import java.io.IOException; 9 | 10 | public class RequestCapturingSender implements Sender { 11 | private Request request; 12 | 13 | @Override 14 | public Response send(Request request) throws SmartyException, IOException { 15 | this.request = request; 16 | 17 | return new Response(200, "[]".getBytes()); 18 | } 19 | 20 | public Request getRequest() { 21 | return this.request; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_extract/Result.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_extract; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * @see SmartyStreets US Extract API docs 9 | */ 10 | public class Result implements Serializable { 11 | private Metadata metadata; 12 | private Address[] addresses; 13 | 14 | 15 | @JsonProperty("meta") 16 | public Metadata getMetadata() { 17 | return metadata; 18 | } 19 | 20 | public Address[] getAddresses() { 21 | return addresses; 22 | } 23 | 24 | public Address getAddress(int index) { 25 | return addresses[index]; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/test/java/com/smartystreets/api/mocks/MockStatusCodeSender.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.mocks; 2 | 3 | import com.smartystreets.api.Request; 4 | import com.smartystreets.api.Response; 5 | import com.smartystreets.api.Sender; 6 | import com.smartystreets.api.exceptions.SmartyException; 7 | 8 | import java.io.IOException; 9 | 10 | public class MockStatusCodeSender implements Sender { 11 | private final int statusCode; 12 | 13 | public MockStatusCodeSender(int statusCode) { 14 | this.statusCode = statusCode; 15 | } 16 | 17 | @Override 18 | public Response send(Request request) throws SmartyException, IOException { 19 | if (this.statusCode == 0) 20 | return null; 21 | 22 | return new Response(this.statusCode, null); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /lib/settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ossrh 6 | smartystreets 7 | PASSWORD 8 | 9 | 10 | 11 | 12 | ossrh 13 | 14 | true 15 | 16 | 17 | gpg 18 | 27097914F39CD1E9 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/test/java/com/smartystreets/api/us_zipcode/ResultTest.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_zipcode; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | public class ResultTest { 8 | @Test 9 | public void isValid() throws Exception { 10 | 11 | /**Case 1: test to make sure that isValid returns true when input is valid*/ 12 | Result result = new Result(); 13 | 14 | boolean isValid = result.isValid(); 15 | 16 | assertEquals(true, isValid); 17 | 18 | /**Case 2: test to make sure that isValid returns false when input is not valid*/ 19 | result.status = "invalid_zipcode"; 20 | result.reason = "invalid_reason"; 21 | 22 | isValid = result.isValid(); 23 | 24 | assertEquals(false, isValid); 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /src/test/java/com/smartystreets/api/mocks/MockSender.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.mocks; 2 | 3 | import com.smartystreets.api.Request; 4 | import com.smartystreets.api.Response; 5 | import com.smartystreets.api.Sender; 6 | import com.smartystreets.api.exceptions.SmartyException; 7 | 8 | import java.io.IOException; 9 | 10 | public class MockSender implements Sender { 11 | private final Response response; 12 | private Request request; 13 | 14 | public MockSender(Response response) { 15 | this.response = response; 16 | } 17 | 18 | @Override 19 | public Response send(Request request) throws SmartyException, IOException { 20 | this.request = request; 21 | return this.response; 22 | } 23 | 24 | public Request getRequest() { 25 | return this.request; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/CustomHeaderSender.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api; 2 | 3 | import com.smartystreets.api.exceptions.SmartyException; 4 | 5 | import java.io.IOException; 6 | import java.util.Map; 7 | 8 | public class CustomHeaderSender implements Sender { 9 | private Map headers; 10 | private Sender inner; 11 | 12 | public CustomHeaderSender(Map headers, Sender inner){ 13 | this.headers = headers; 14 | this.inner = inner; 15 | } 16 | 17 | @Override 18 | public Response send(Request request) throws SmartyException, IOException, InterruptedException { 19 | for (Map.Entry entry : this.headers.entrySet()) { 20 | request.putHeader((String)entry.getKey(), entry.getValue()); 21 | } 22 | 23 | return this.inner.send(request); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/StaticCredentials.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api; 2 | 3 | /** 4 | * StaticCredentials takes a SmartyStreets Secret Key Pair, and 'signs' the request with it so the
5 | * SmartyStreets API knows which SmartyStreets account and subscription is sending it. 6 | *

Look on the API Keys tab of your SmartyStreets account page to find/generate your keys.

7 | */ 8 | public class StaticCredentials implements Credentials { 9 | private String authId; 10 | private String authToken; 11 | 12 | public StaticCredentials(String authId, String authToken) { 13 | this.authId = authId; 14 | this.authToken = authToken; 15 | } 16 | 17 | public void sign(Request request) { 18 | request.putParameter("auth-id", this.authId); 19 | request.putParameter("auth-token", this.authToken); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_enrichment/result_types/secondary/SecondaryCountResponse.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_enrichment.result_types.secondary; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import com.smartystreets.api.us_enrichment.result_types.Result; 5 | 6 | public class SecondaryCountResponse extends Result { 7 | private String smartyKey; 8 | private int count; 9 | 10 | @JsonProperty("smarty_key") 11 | public String getSmartyKey() { 12 | return smartyKey; 13 | } 14 | 15 | @JsonProperty("count") 16 | public int getCount() { 17 | return count; 18 | } 19 | 20 | @Override 21 | public String toString() { 22 | return "SecondaryCountResponse{" + 23 | "smartyKey='" + smartyKey + '\'' + 24 | ", count=" + count + 25 | '}'; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/international_street/Candidate.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.international_street; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * A candidate is a possible match for an address that was submitted.
7 | * A lookup can have multiple candidates if the address was ambiguous. 8 | * 9 | * @see "https://smartystreets.com/docs/cloud/international-street-api#root" 10 | */ 11 | public class Candidate extends RootLevel implements Serializable { 12 | //region [ Fields ] 13 | 14 | private Components components; 15 | private Metadata metadata; 16 | private Analysis analysis; 17 | 18 | //endregion 19 | 20 | //region [ Getters ] 21 | 22 | public Components getComponents() { 23 | return components; 24 | } 25 | 26 | public Metadata getMetadata() { 27 | return metadata; 28 | } 29 | 30 | public Analysis getAnalysis() { 31 | return analysis; 32 | } 33 | 34 | //endregion 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/CustomQuerySender.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api; 2 | 3 | import com.smartystreets.api.exceptions.SmartyException; 4 | 5 | import java.io.IOException; 6 | import java.util.Map; 7 | 8 | public class CustomQuerySender implements Sender{ 9 | private Map queries; 10 | private Sender inner; 11 | 12 | public CustomQuerySender(Map queries, Sender inner){ 13 | this.queries = queries; 14 | this.inner = inner; 15 | } 16 | 17 | @Override 18 | public Response send(Request request) throws SmartyException, IOException, InterruptedException { 19 | if (this.queries == null || this.queries.isEmpty()) { 20 | return this.inner.send(request); 21 | } 22 | for (Map.Entry entry : this.queries.entrySet()) { 23 | request.putParameter(entry.getKey(), entry.getValue()); 24 | } 25 | 26 | return this.inner.send(request); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/Response.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api; 2 | 3 | import okhttp3.Headers; 4 | 5 | import java.net.http.HttpHeaders; 6 | 7 | public class Response { 8 | private int statusCode; 9 | private byte[] payload; 10 | private Headers headers; 11 | 12 | 13 | public Response(int statusCode, byte[] payload) { 14 | this.statusCode = statusCode; 15 | this.payload = payload; 16 | } 17 | 18 | 19 | public Response(int statusCode, byte[] payload, Headers httpHeaders) { 20 | this.statusCode = statusCode; 21 | this.payload = payload; 22 | this.headers = httpHeaders; 23 | } 24 | 25 | 26 | //region [ Getters ] 27 | 28 | public Headers getHeaders() { 29 | return headers; 30 | } 31 | 32 | public int getStatusCode() { 33 | return this.statusCode; 34 | } 35 | 36 | public byte[] getPayload() { 37 | return this.payload; 38 | } 39 | 40 | //endregion 41 | } 42 | 43 | 44 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/LicenseSender.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api; 2 | 3 | 4 | import com.smartystreets.api.exceptions.SmartyException; 5 | 6 | import java.io.IOException; 7 | import java.util.List; 8 | 9 | public class LicenseSender implements Sender{ 10 | private List licenses; 11 | private Sender inner; 12 | 13 | public LicenseSender(List licenses, Sender inner) { 14 | this.licenses = licenses; 15 | this.inner = inner; 16 | } 17 | 18 | public Response send(Request request) throws IOException, SmartyException, InterruptedException { 19 | if (!this.licenses.isEmpty()) { 20 | StringBuilder licenses = new StringBuilder(); 21 | for (String license : this.licenses) 22 | { 23 | licenses.append(license); 24 | licenses.append(","); 25 | } 26 | request.putParameter("license", licenses.toString()); 27 | } 28 | return this.inner.send(request); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_reverse_geo/Coordinate.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_reverse_geo; 2 | 3 | import java.io.Serializable; 4 | 5 | public class Coordinate implements Serializable { 6 | //region [ Fields ] 7 | 8 | private double latitude; 9 | private double longitude; 10 | private int license; 11 | private String zipcode; 12 | private String accuracy; 13 | 14 | //endregion 15 | 16 | public double getLatitude() { 17 | return this.latitude; 18 | } 19 | 20 | public double getLongitude() { 21 | return this.longitude; 22 | } 23 | 24 | public String getLicense() { 25 | switch (this.license) { 26 | case 1: 27 | return "SmartyStreets Proprietary"; 28 | default: 29 | return "SmartyStreets"; 30 | 31 | } 32 | } 33 | 34 | public String getZipCode() { 35 | return this.zipcode; 36 | } 37 | 38 | public String getAccuracy() { 39 | return this.accuracy; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/international_street/Analysis.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.international_street; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * @see "https://smartystreets.com/docs/cloud/international-street-api#analysis" 9 | */ 10 | public class Analysis implements Serializable { 11 | private String verificationStatus; 12 | private String addressPrecision; 13 | private String maxAddressPrecision; 14 | private Changes changes; 15 | 16 | 17 | @JsonProperty("verification_status") 18 | public String getVerificationStatus() { 19 | return verificationStatus; 20 | } 21 | 22 | @JsonProperty("address_precision") 23 | public String getAddressPrecision() { 24 | return addressPrecision; 25 | } 26 | 27 | @JsonProperty("max_address_precision") 28 | public String getMaxAddressPrecision() { 29 | return maxAddressPrecision; 30 | } 31 | 32 | public Changes getChanges() { 33 | return changes; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/test/java/com/smartystreets/api/SharedCredentialsTest.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | public class SharedCredentialsTest { 8 | @Test 9 | public void assertSignedRequest() { 10 | Request request = this.createSignedRequest(); 11 | String expected = "https://us-street.api.smarty.com/street-address?key=3516378604772256"; 12 | 13 | assertEquals(expected, request.getUrl()); 14 | } 15 | 16 | @Test public void assertReferringHeader() { 17 | Request request = this.createSignedRequest(); 18 | 19 | assertEquals("https://example.com", request.getHeaders().get("Referer")); 20 | } 21 | 22 | private Request createSignedRequest() { 23 | Credentials mobile = new SharedCredentials("3516378604772256", "https://example.com"); 24 | Request request = new Request(); 25 | request.setUrlPrefix("https://us-street.api.smarty.com/street-address?"); 26 | mobile.sign(request); 27 | return request; 28 | } 29 | } -------------------------------------------------------------------------------- /src/test/java/com/smartystreets/api/us_autocomplete_pro/SuggestionTest.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_autocomplete_pro; 2 | 3 | 4 | import com.smartystreets.api.SmartySerializer; 5 | import org.junit.Test; 6 | 7 | import java.io.IOException; 8 | 9 | import static org.junit.Assert.assertEquals; 10 | import static org.junit.Assert.assertNotNull; 11 | 12 | public class SuggestionTest { 13 | private final SmartySerializer smartySerializer = new SmartySerializer(); 14 | private static final String responsePayload = "{\"suggestions\":[{\"street_line\":\"2\",\"city\":\"3\",\"state\":\"4\"}]}"; 15 | 16 | @Test 17 | public void testAllFieldGetFilledInCorrectly() throws IOException { 18 | Result result = smartySerializer.deserialize(responsePayload.getBytes(), Result.class); 19 | 20 | assertNotNull(result.getSuggestions()[0]); 21 | assertEquals("2", result.getSuggestion(0).getStreetLine()); 22 | assertEquals("3", result.getSuggestion(0).getCity()); 23 | assertEquals("4", result.getSuggestion(0).getState()); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_reverse_geo/Address.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_reverse_geo; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | import java.io.Serializable; 6 | 7 | public class Address implements Serializable { 8 | //region [ Fields ] 9 | 10 | private String street; 11 | private String city; 12 | private String stateAbbreviation; 13 | private String zipCode; 14 | private String source; 15 | private String smartykey; 16 | 17 | //endregion 18 | 19 | public String getStreet() { return this.street; } 20 | 21 | public String getCity() { return this.city; } 22 | 23 | @JsonProperty("state_abbreviation") 24 | public String getStateAbbreviation() { return this.stateAbbreviation; } 25 | 26 | @JsonProperty("zipcode") 27 | public String getZipCode() { return this.zipCode; } 28 | 29 | @JsonProperty("source") 30 | public String getSource() { return this.source; } 31 | 32 | @JsonProperty("smarty_key") 33 | public String getSmartykey() { return this.smartykey; } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/test/java/com/smartystreets/api/mocks/FakeDeserializer.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.mocks; 2 | 3 | import com.smartystreets.api.Serializer; 4 | import okhttp3.Headers; 5 | 6 | import java.io.IOException; 7 | 8 | public class FakeDeserializer implements Serializer { 9 | 10 | private final Object deserialized; 11 | private byte[] payload; 12 | 13 | public FakeDeserializer(Object deserialized) { 14 | this.deserialized = deserialized; 15 | } 16 | 17 | @Override 18 | public byte[] serialize(Object obj) throws IOException { 19 | return new byte[0]; 20 | } 21 | 22 | @Override 23 | public T deserialize(byte[] payload, Class type, Headers headers) throws IOException { 24 | this.payload = payload; 25 | return (T)deserialized; 26 | } 27 | 28 | @Override 29 | public T deserialize(byte[] payload, Class type) throws IOException { 30 | this.payload = payload; 31 | return (T)deserialized; 32 | } 33 | 34 | public byte[] getPayload() { 35 | return this.payload; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_reverse_geo/Lookup.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_reverse_geo; 2 | 3 | import java.io.Serializable; 4 | 5 | public class Lookup implements Serializable { 6 | 7 | //region [ Fields ] 8 | 9 | private double latitude; 10 | private double longitude; 11 | private String source; 12 | 13 | private SmartyResponse response; 14 | 15 | //endregion 16 | 17 | public Lookup() { this.response = new SmartyResponse(); } 18 | 19 | public Lookup(double latitude, double longitude) { 20 | this(); 21 | this.latitude = latitude; 22 | this.longitude = longitude; 23 | } 24 | 25 | public Double getLatitude() { return this.latitude; } 26 | 27 | public Double getLongitude() { return this.longitude; } 28 | 29 | public String getSource() { return this.source; } 30 | 31 | public void setSource(String source) { this.source = source; } 32 | 33 | public SmartyResponse getResponse() { return this.response; } 34 | 35 | public void setResponse(SmartyResponse response) { 36 | this.response = response; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #### SMARTY DISCLAIMER: Subject to the terms of the associated license agreement, this software is freely available for your use. This software is FREE, AS IN PUPPIES, and is a gift. Enjoy your new responsibility. This means that while we may consider enhancement requests, we may or may not choose to entertain requests at our sole and absolute discretion. 2 | 3 | # SmartyStreets Java SDK 4 | 5 | The official client libraries for accessing SmartyStreets APIs from Java (and JRE-based languages) 6 | 7 | Compatible with Java 11 and later. Earlier Java versions supported by SDK version 3.10.7 and earlier. 8 | 9 | You may have noticed this page is curiously sparse. Don't panic, there's [documentation](https://smartystreets.com/docs/sdk/java) and [examples](src/main/java/examples). 10 | 11 | When using this library in an Android project, be sure to exclude commons-logging and httpclient as they will conflict with classes provided by Android. 12 | 13 | [Apache 2.0 License](src/main/resources/LICENSE.txt) 14 | 15 | --- 16 | 17 | [![asciicast](https://asciinema.org/a/122130.png)](https://asciinema.org/a/122130) 18 | 19 | --- 20 | -------------------------------------------------------------------------------- /src/test/java/com/smartystreets/api/CustomHeaderSenderTest.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api; 2 | 3 | import com.smartystreets.api.mocks.RequestCapturingSender; 4 | import org.junit.Test; 5 | 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | import static org.junit.Assert.assertEquals; 10 | import static org.junit.Assert.assertNotNull; 11 | 12 | public class CustomHeaderSenderTest { 13 | 14 | @Test 15 | public void testAllCustomHeadersAreAddedToTheRequest() throws Exception { 16 | HashMap headers = new HashMap<>(); 17 | headers.put("A", "1"); 18 | headers.put("B", "2"); 19 | RequestCapturingSender inner = new RequestCapturingSender(); 20 | CustomHeaderSender sender = new CustomHeaderSender(headers, inner); 21 | Request request = new Request(); 22 | sender.send(request); 23 | 24 | Map requestHeaders = inner.getRequest().getHeaders(); 25 | assertNotNull("There should be headers here.", requestHeaders); 26 | assertEquals(headers.get("A"), inner.getRequest().getHeaders().get("A")); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/test/java/com/smartystreets/api/us_reverse_geo/ClientTest.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_reverse_geo; 2 | 3 | import com.smartystreets.api.URLPrefixSender; 4 | import com.smartystreets.api.mocks.FakeSerializer; 5 | import com.smartystreets.api.mocks.RequestCapturingSender; 6 | import org.junit.Test; 7 | 8 | import static org.junit.Assert.assertEquals; 9 | 10 | public class ClientTest { 11 | //region [ Single Lookup ] 12 | 13 | @Test 14 | public void testAddressLookupSerializedAndSentWithContext() throws Exception { 15 | RequestCapturingSender capturingSender = new RequestCapturingSender(); 16 | URLPrefixSender sender = new URLPrefixSender("http://localhost/lookup", capturingSender); 17 | FakeSerializer serializer = new FakeSerializer(null); 18 | Client client = new Client(sender, serializer); 19 | 20 | Lookup lookup = new Lookup(44.888888888, -111.111111111); 21 | client.send(lookup); 22 | 23 | assertEquals("http://localhost/lookup?latitude=44.88888889&longitude=-111.11111111", capturingSender.getRequest().getUrl()); 24 | } 25 | 26 | //endregion 27 | } -------------------------------------------------------------------------------- /src/test/java/com/smartystreets/api/XForwardedForTest.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | import static org.junit.Assert.assertNotNull; 5 | 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | import org.junit.Test; 10 | 11 | import com.smartystreets.api.mocks.RequestCapturingSender; 12 | 13 | public class XForwardedForTest { 14 | @Test 15 | public void testAllCustomHeadersAreAddedToTheRequest() throws Exception { 16 | HashMap headers = new HashMap<>(); 17 | headers.put("X-Forwarded-For", "ip"); 18 | RequestCapturingSender inner = new RequestCapturingSender(); 19 | CustomHeaderSender sender = new CustomHeaderSender(headers, inner); 20 | Request request = new Request(); 21 | 22 | sender.send(request); 23 | 24 | Map requestHeaders = inner.getRequest().getHeaders(); 25 | assertNotNull("Headers here.", requestHeaders); 26 | assertEquals(headers.get("X-Forwarded-For"), inner.getRequest().getHeaders().get("X-Forwarded-For")); 27 | 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_zipcode/AlternateCounty.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_zipcode; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * @see "https://smartystreets.com/docs/cloud/us-zipcode-api#zipcodes" 9 | */ 10 | public class AlternateCounty implements Serializable { 11 | 12 | //region [ Fields ] 13 | 14 | private String countyFips; 15 | private String countyName; 16 | private String stateAbbreviation; 17 | private String state; 18 | 19 | //endregion 20 | 21 | //region [ Getters ] 22 | 23 | @JsonProperty("county_fips") 24 | public String getCountyFips() { 25 | return countyFips; 26 | } 27 | 28 | @JsonProperty("county_name") 29 | public String getCountyName() { 30 | return countyName; 31 | } 32 | 33 | @JsonProperty("state_abbreviation") 34 | public String getStateAbbreviation() { 35 | return stateAbbreviation; 36 | } 37 | 38 | @JsonProperty("state") 39 | public String getState() { 40 | return state; 41 | } 42 | 43 | //endregion 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_enrichment/result_types/Result.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_enrichment.result_types; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | public class Result extends EnrichmentToStringer { 6 | @JsonProperty("smarty_key") 7 | private String smartyKey; 8 | @JsonProperty("data_set_name") 9 | private String datasetName; 10 | @JsonProperty("data_subset_name") 11 | private String dataSubsetName; 12 | @JsonProperty("matched_address") 13 | private MatchedAddress matchedAddress; 14 | 15 | private String etag; 16 | 17 | public void setEtag(String etag) { 18 | this.etag = etag; 19 | } 20 | 21 | public String getSmartyKey() { 22 | return smartyKey; 23 | } 24 | 25 | public String getDatasetName() { 26 | return datasetName; 27 | } 28 | 29 | public String getDataSubsetName() { 30 | return dataSubsetName; 31 | } 32 | 33 | public MatchedAddress getMatchedAddress() { 34 | return matchedAddress; 35 | } 36 | 37 | public String getEtag() { 38 | return etag; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_autocomplete_pro/Suggestion.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_autocomplete_pro; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * @see "https://smartystreets.com/docs/cloud/us-autocomplete-pro-api#http-response" 9 | */ 10 | public class Suggestion implements Serializable { 11 | //region [ Fields ] 12 | 13 | private String streetLine; 14 | private String secondary; 15 | private String city; 16 | private String state; 17 | private String zipcode; 18 | private Integer entries; 19 | 20 | //region [ Fields ] 21 | 22 | //region [ Getters ] 23 | 24 | @JsonProperty("street_line") 25 | public String getStreetLine() { 26 | return streetLine; 27 | } 28 | 29 | public String getSecondary() { return secondary; } 30 | 31 | public String getCity() { 32 | return city; 33 | } 34 | 35 | public String getState() { 36 | return state; 37 | } 38 | 39 | public String getZipcode() { return zipcode; } 40 | 41 | public Integer getEntries() { return entries; } 42 | 43 | //endregion 44 | } 45 | -------------------------------------------------------------------------------- /src/test/java/com/smartystreets/api/mocks/FakeSerializer.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.mocks; 2 | 3 | import com.smartystreets.api.Serializer; 4 | import com.smartystreets.api.us_enrichment.result_types.Result; 5 | import okhttp3.Headers; 6 | 7 | import java.io.IOException; 8 | 9 | public class FakeSerializer implements Serializer { 10 | 11 | private final byte[] bytes; 12 | private Object result; 13 | 14 | public String[] headers; 15 | 16 | public FakeSerializer(byte[] bytes) { 17 | this.bytes = bytes; 18 | } 19 | 20 | public FakeSerializer(Object result) { 21 | this.result = result; 22 | this.headers = new String[1]; 23 | this.bytes = null; 24 | } 25 | 26 | @Override 27 | public byte[] serialize(Object obj) throws IOException { 28 | return this.bytes; 29 | } 30 | 31 | @Override 32 | public T deserialize(byte[] payload, Class type, Headers headers) throws IOException { 33 | return (T) this.result; 34 | } 35 | 36 | @Override 37 | public T deserialize(byte[] payload, Class type) throws IOException { 38 | return (T) this.result; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_zipcode/City.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_zipcode; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * Known in the SmartyStreets US ZIP Code API documentation as a city_state 9 | * @see "https://smartystreets.com/docs/cloud/us-zipcode-api#cities" 10 | */ 11 | public class City implements Serializable { 12 | //region [ Fields ] 13 | 14 | private String city; 15 | private boolean mailableCity; 16 | private String stateAbbreviation; 17 | private String state; 18 | 19 | //endregion 20 | 21 | //region [ Getters ] 22 | 23 | @JsonProperty("city") 24 | public String getCity() { 25 | return this.city; 26 | } 27 | 28 | @JsonProperty("mailable_city") 29 | public boolean getMailableCity() { 30 | return this.mailableCity; 31 | } 32 | 33 | @JsonProperty("state_abbreviation") 34 | public String getStateAbbreviation() { 35 | return this.stateAbbreviation; 36 | } 37 | 38 | @JsonProperty("state") 39 | public String getState() { 40 | return this.state; 41 | } 42 | 43 | //endregion 44 | } 45 | -------------------------------------------------------------------------------- /src/test/java/com/smartystreets/api/StaticCredentialsTest.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | public class StaticCredentialsTest { 8 | @Test 9 | public void testStandardCredentials() throws Exception { 10 | assertSignedRequest("f83280df-s83d-f82j-d829-kd02l9tis7ek", "S9Djk63k2Ilj67vN82Km", 11 | "https://us-street.api.smarty.com/street-address?auth-id=f83280df-s83d-f82j-d829-kd02l9tis7ek&auth-token=S9Djk63k2Ilj67vN82Km"); 12 | } 13 | 14 | @Test 15 | public void testUrlEncoding() { 16 | assertSignedRequest("as3$d8+56d9", "d8j#ds'dfe2", 17 | "https://us-street.api.smarty.com/street-address?auth-id=as3%24d8%2B56d9&auth-token=d8j%23ds%27dfe2"); 18 | } 19 | 20 | private static void assertSignedRequest(String id, String secret, String expected) { 21 | StaticCredentials credentials = new StaticCredentials(id, secret); 22 | Request request = new Request(); 23 | request.setUrlPrefix("https://us-street.api.smarty.com/street-address?"); 24 | credentials.sign(request); 25 | assertEquals(expected, request.getUrl()); 26 | } 27 | } -------------------------------------------------------------------------------- /src/test/java/com/smartystreets/api/LicenseSenderTest.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api; 2 | 3 | 4 | import com.smartystreets.api.mocks.MockSender; 5 | import org.junit.Test; 6 | 7 | import java.util.ArrayList; 8 | 9 | import static org.junit.Assert.assertEquals; 10 | 11 | public class LicenseSenderTest { 12 | 13 | @Test 14 | public void testSetsLicenses() throws Exception { 15 | Request request = new Request(); 16 | ArrayList licenses = new ArrayList<>(); 17 | licenses.add("one"); 18 | licenses.add("two"); 19 | licenses.add("three"); 20 | Sender inner = new MockSender(new Response(123, null)); 21 | Sender sender = new LicenseSender(licenses, inner); 22 | 23 | Response response = sender.send(request); 24 | 25 | assertEquals("?license=one%2Ctwo%2Cthree%2C", request.getUrl()); 26 | } 27 | 28 | @Test 29 | public void testLicensesNotSet() throws Exception { 30 | Request request = new Request(); 31 | ArrayList licenses = new ArrayList<>(); 32 | Sender inner = new MockSender(new Response(123, null)); 33 | Sender sender = new LicenseSender(licenses, inner); 34 | 35 | Response response = sender.send(request); 36 | 37 | assertEquals("?", request.getUrl()); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_enrichment/result_types/secondary/Secondary.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_enrichment.result_types.secondary; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | public class Secondary { 6 | 7 | private String smartyKey; 8 | 9 | private String secondaryDesignator; 10 | 11 | private String secondaryNumber; 12 | 13 | private String plus4Code; 14 | 15 | @JsonProperty("smarty_key") 16 | public String getSmartyKey() { 17 | return smartyKey; 18 | } 19 | 20 | @JsonProperty("secondary_designator") 21 | public String getSecondaryDesignator() { 22 | return secondaryDesignator; 23 | } 24 | 25 | @JsonProperty("secondary_number") 26 | public String getSecondaryNumber() { 27 | return secondaryNumber; 28 | } 29 | 30 | @JsonProperty("plus4_code") 31 | public String getPlus4Code() { 32 | return plus4Code; 33 | } 34 | 35 | @Override 36 | public String toString() { 37 | return "Secondary{" + 38 | "smarty_key='" + getSmartyKey() + '\'' + 39 | ", secondary_designator='" + getSecondaryDesignator() + '\'' + 40 | ", secondary_number='" + getSecondaryNumber() + '\'' + 41 | ", plus4_code='" + getPlus4Code() + '\'' + 42 | '}'; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_extract/Address.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_extract; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import com.smartystreets.api.us_street.Candidate; 5 | 6 | import java.io.Serializable; 7 | 8 | /** 9 | * @see SmartyStreets US Extract API docs 10 | */ 11 | public class Address implements Serializable { 12 | //region [ Fields ] 13 | 14 | private String text; 15 | private boolean verified; 16 | private int line; 17 | private int start; 18 | private int end; 19 | private Candidate[] candidates; 20 | 21 | //endregion 22 | 23 | //region [ Getters ] 24 | 25 | public String getText() { 26 | return text; 27 | } 28 | 29 | public boolean isVerified() { 30 | return verified; 31 | } 32 | 33 | public int getLine() { 34 | return line; 35 | } 36 | 37 | public int getStart() { 38 | return start; 39 | } 40 | 41 | public int getEnd() { 42 | return end; 43 | } 44 | 45 | @JsonProperty("api_output") 46 | public Candidate[] getCandidates() { 47 | return candidates; 48 | } 49 | 50 | public Candidate getCandidate(int index) { 51 | return candidates[index]; 52 | } 53 | 54 | //endregion 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_reverse_geo/Client.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_reverse_geo; 2 | 3 | import com.smartystreets.api.Request; 4 | import com.smartystreets.api.Response; 5 | import com.smartystreets.api.Sender; 6 | import com.smartystreets.api.Serializer; 7 | import com.smartystreets.api.exceptions.SmartyException; 8 | 9 | import java.io.IOException; 10 | import java.text.DecimalFormat; 11 | 12 | public class Client { 13 | private final Sender sender; 14 | private final Serializer serializer; 15 | 16 | public Client(Sender sender, Serializer serializer) { 17 | this.sender = sender; 18 | this.serializer = serializer; 19 | } 20 | 21 | public void send(Lookup lookup) throws SmartyException, IOException, InterruptedException { 22 | Request request = new Request(); 23 | 24 | DecimalFormat decimalFormat = new DecimalFormat("#.########"); 25 | request.putParameter("latitude", decimalFormat.format(lookup.getLatitude())); 26 | request.putParameter("longitude", decimalFormat.format(lookup.getLongitude())); 27 | request.putParameter("source", lookup.getSource()); 28 | 29 | Response httpResponse = this.sender.send(request); 30 | 31 | SmartyResponse response = this.serializer.deserialize(httpResponse.getPayload(), SmartyResponse.class); 32 | lookup.setResponse(response); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_enrichment/result_types/secondary/SecondaryResponse.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_enrichment.result_types.secondary; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import com.smartystreets.api.us_enrichment.result_types.Result; 5 | import java.util.ArrayList; 6 | 7 | public class SecondaryResponse extends Result { 8 | private String smartyKey; 9 | private RootAddress rootAddress; 10 | private ArrayList aliases; 11 | private ArrayList secondaries; 12 | 13 | @JsonProperty("smarty_key") 14 | public String getSmartyKey() { 15 | return smartyKey; 16 | } 17 | 18 | @JsonProperty("root_address") 19 | public RootAddress getRootAddress() { 20 | return rootAddress; 21 | } 22 | 23 | @JsonProperty("aliases") 24 | public ArrayList getAliases() { 25 | return aliases; 26 | } 27 | 28 | @JsonProperty("secondaries") 29 | public ArrayList getSecondaries() { 30 | return secondaries; 31 | } 32 | 33 | @Override 34 | public String toString() { 35 | return "SecondaryResponse{" + 36 | "smartyKey='" + getSmartyKey() + '\'' + 37 | ", rootAddress=" + getRootAddress() + 38 | ", aliases=" + getAliases() + 39 | ", secondaries=" + getSecondaries() + 40 | '}'; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_extract/Metadata.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_extract; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * @see SmartyStreets US Extract API docs 9 | */ 10 | public class Metadata implements Serializable { 11 | //region [ Fields ] 12 | 13 | private int lines; 14 | private boolean unicode; 15 | private int addressCount; 16 | private int verifiedCount; 17 | private int bytes; 18 | private int characterCount; 19 | 20 | //endregion 21 | 22 | //region [ Getters ] 23 | 24 | @JsonProperty("lines") 25 | public int getLines() { 26 | return lines; 27 | } 28 | 29 | @JsonProperty("unicode") 30 | public boolean isUnicode() { 31 | return unicode; 32 | } 33 | 34 | @JsonProperty("address_count") 35 | public int getAddressCount() { 36 | return addressCount; 37 | } 38 | 39 | @JsonProperty("verified_count") 40 | public int getVerifiedCount() { 41 | return verifiedCount; 42 | } 43 | 44 | @JsonProperty("bytes") 45 | public int getBytes() { 46 | return bytes; 47 | } 48 | 49 | @JsonProperty("character_count") 50 | public int getCharacterCount() { 51 | return characterCount; 52 | } 53 | 54 | //endregion 55 | } 56 | -------------------------------------------------------------------------------- /src/test/java/com/smartystreets/api/SigningSenderTest.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api; 2 | 3 | import com.smartystreets.api.mocks.MockSender; 4 | import org.junit.Test; 5 | 6 | import static org.junit.Assert.assertEquals; 7 | 8 | public class SigningSenderTest { 9 | 10 | @Test 11 | public void testSigningOfRequest() throws Exception { 12 | StaticCredentials signer = new StaticCredentials("id", "secret"); 13 | MockSender mockSender = new MockSender(null); 14 | URLPrefixSender urlPrefixSender = new URLPrefixSender("http://localhost/", mockSender); 15 | SigningSender sender = new SigningSender(signer, urlPrefixSender); 16 | 17 | sender.send(new Request()); 18 | 19 | Request request = mockSender.getRequest(); 20 | assertEquals("http://localhost/?auth-id=id&auth-token=secret", request.getUrl()); 21 | } 22 | 23 | @Test 24 | public void testResponseReturnedCorrectly() throws Exception { 25 | StaticCredentials signer = new StaticCredentials("id", "secret"); 26 | Response expectedResponse = new Response(200, null); 27 | MockSender mockSender = new MockSender(expectedResponse); 28 | URLPrefixSender urlPrefixSender = new URLPrefixSender("http://localhost/", mockSender); 29 | SigningSender sender = new SigningSender(signer, urlPrefixSender); 30 | 31 | Response actualResponse = sender.send(new Request()); 32 | 33 | assertEquals(expectedResponse, actualResponse); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_enrichment/lookup_types/risk/RiskLookup.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_enrichment.lookup_types.risk; 2 | 3 | import com.smartystreets.api.Serializer; 4 | import com.smartystreets.api.us_enrichment.lookup_types.Lookup; 5 | import com.smartystreets.api.us_enrichment.result_types.risk.RiskResponse; 6 | import okhttp3.Headers; 7 | 8 | import java.io.IOException; 9 | 10 | import static com.smartystreets.api.us_enrichment.lookup_types.Lookup.emptyDataSubset; 11 | import static com.smartystreets.api.us_enrichment.lookup_types.Lookup.geoReferenceDataSet; 12 | 13 | public class RiskLookup extends Lookup { 14 | private RiskResponse[] results; 15 | 16 | public RiskLookup() { 17 | } 18 | 19 | public RiskResponse[] getResults() { 20 | return results; 21 | } 22 | 23 | public void setResults(RiskResponse[] results) { 24 | this.results = results; 25 | } 26 | 27 | @Override 28 | public void deserializeAndSetResults(Serializer serializer, byte[] payload, Headers headers) throws IOException { 29 | this.results = serializer.deserialize(payload, RiskResponse[].class, headers); 30 | if (headers != null) { 31 | this.results[0].setEtag(headers.get("etag")); 32 | } 33 | } 34 | 35 | @Override 36 | public String getDataSetName() { 37 | return riskDataSet; 38 | } 39 | 40 | @Override 41 | public String getDataSubsetName() { 42 | return emptyDataSubset; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/SmartySerializer.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.core.JsonProcessingException; 5 | import com.fasterxml.jackson.databind.DeserializationFeature; 6 | import com.fasterxml.jackson.databind.ObjectMapper; 7 | import okhttp3.Headers; 8 | 9 | import java.io.*; 10 | 11 | public class SmartySerializer implements Serializer { 12 | 13 | public SmartySerializer() {} 14 | 15 | public byte[] serialize(Object obj) throws IOException { 16 | ObjectMapper mapper = new ObjectMapper(); 17 | mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); 18 | return mapper.writeValueAsBytes(obj); 19 | } 20 | 21 | @Override 22 | public T deserialize(byte[] payload, Class type, Headers headers) throws IOException { 23 | ObjectMapper mapper = new ObjectMapper(); 24 | mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); 25 | mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 26 | return mapper.readValue(payload, type); 27 | 28 | } 29 | 30 | public T deserialize(byte[] payload, Class type) throws IOException { 31 | ObjectMapper mapper = new ObjectMapper(); 32 | mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); 33 | mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 34 | return mapper.readValue(payload, type); 35 | } 36 | } -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_enrichment/result_types/georeference/GeoReferenceAttributes.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_enrichment.result_types.georeference; 2 | 3 | import com.smartystreets.api.us_enrichment.result_types.Attributes; 4 | import com.smartystreets.api.us_enrichment.result_types.EnrichmentToStringer; 5 | 6 | public class GeoReferenceAttributes extends Attributes{ 7 | public CensusBlock census_block; 8 | public CensusCountyDivision census_county_division; 9 | public CensusTract censusTract; 10 | public CoreBasedStatArea core_based_stat_area; 11 | public Place place; 12 | 13 | public static class CensusBlock extends EnrichmentToStringer { 14 | public String accuracy; 15 | public String geoid; 16 | } 17 | 18 | public static class CensusCountyDivision extends EnrichmentToStringer{ 19 | public String accuracy; 20 | public String code; 21 | public String name; 22 | } 23 | public static class CensusTract extends EnrichmentToStringer{ 24 | public String code; 25 | } 26 | 27 | public static class CoreBasedStatArea extends EnrichmentToStringer { 28 | public String code; 29 | public String name; 30 | } 31 | 32 | public static class Place extends EnrichmentToStringer{ 33 | public String accuracy; 34 | public String code; 35 | public String name; 36 | public String type; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/test/java/com/smartystreets/api/us_street/BatchTest.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_street; 2 | 3 | import com.smartystreets.api.exceptions.BatchFullException; 4 | import org.junit.Test; 5 | 6 | import static org.junit.Assert.assertEquals; 7 | import static org.junit.Assert.assertThrows; 8 | 9 | public class BatchTest { 10 | 11 | @Test 12 | public void testGetsLookupByInputId() throws Exception { 13 | Batch batch = new Batch(); 14 | Lookup lookup = new Lookup().setInputId("hasInputId"); 15 | 16 | batch.add(lookup); 17 | 18 | assertEquals(lookup, batch.get("hasInputId")); 19 | } 20 | 21 | @Test 22 | public void testGetsLookupByIndex() throws Exception { 23 | Batch batch = new Batch(); 24 | Lookup lookup = new Lookup(); 25 | 26 | batch.add(lookup); 27 | 28 | assertEquals(lookup, batch.getAllLookups().get(0)); 29 | } 30 | 31 | @Test 32 | public void testReturnsCorrectSize() throws Exception { 33 | Batch batch = new Batch(); 34 | 35 | batch.add(new Lookup()); 36 | batch.add(new Lookup()); 37 | batch.add(new Lookup()); 38 | 39 | assertEquals(3, batch.size()); 40 | } 41 | 42 | @Test 43 | public void testAddingALookupWhenBatchIsFullThrowsException() { 44 | Batch batch = new Batch(); 45 | Lookup lookup = new Lookup(); 46 | 47 | assertThrows(BatchFullException.class, () -> { 48 | for (int i = 0; i < Batch.MAX_BATCH_SIZE + 1; i++) { 49 | batch.add(lookup); 50 | } 51 | }); 52 | } 53 | 54 | } -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/international_street/Metadata.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.international_street; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * @see "https://smartystreets.com/docs/cloud/international-street-api#metadata" 9 | */ 10 | public class 11 | Metadata implements Serializable { 12 | //region [ Fields ] 13 | 14 | private double latitude; 15 | private double longitude; 16 | private String geocodePrecision; 17 | private String geocodeClassification; 18 | private String maxGeocodePrecision; 19 | private String addressFormat; 20 | private String occupantUse; 21 | 22 | //endregion 23 | 24 | // [ Getters ] 25 | 26 | public double getLatitude() { 27 | return latitude; 28 | } 29 | 30 | public double getLongitude() { 31 | return longitude; 32 | } 33 | 34 | @JsonProperty("geocode_precision") 35 | public String getGeocodePrecision() { 36 | return geocodePrecision; 37 | } 38 | 39 | @JsonProperty("geocode_classification") 40 | public String getGeocodeClassification() { 41 | return geocodeClassification; 42 | } 43 | 44 | @JsonProperty("max_geocode_precision") 45 | public String getMaxGeocodePrecision() { 46 | return maxGeocodePrecision; 47 | } 48 | 49 | @JsonProperty("address_format") 50 | public String getAddressFormat() { 51 | return addressFormat; 52 | } 53 | 54 | @JsonProperty("occupant_use") 55 | public String getOccupantUse() { 56 | return occupantUse; 57 | } 58 | 59 | //endregion 60 | } 61 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish Java 2 | 3 | on: 4 | push: 5 | tags: 6 | - '*' 7 | - '!**-dev**' 8 | 9 | jobs: 10 | release: 11 | runs-on: ubuntu-latest 12 | needs: publish 13 | permissions: 14 | contents: write 15 | steps: 16 | - name: Checkout code 17 | uses: actions/checkout@v2 18 | 19 | - name: Set Version 20 | id: set_version 21 | run: | 22 | echo "VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV 23 | shell: bash 24 | 25 | - name: Create Release 26 | run: | 27 | gh release create ${{ env.VERSION }} --title "Release ${{ env.VERSION }}" 28 | env: 29 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 30 | 31 | publish: 32 | runs-on: ubuntu-latest 33 | steps: 34 | - name: Checkout code 35 | uses: actions/checkout@v3 36 | 37 | - name: Setup Java 38 | uses: actions/setup-java@v3 39 | with: 40 | java-version: '19' 41 | distribution: 'adopt' 42 | server-id: central 43 | server-username: OSSRH_USERNAME 44 | server-password: OSSRH_PASSWORD 45 | gpg-private-key: ${{env.GPG_SECRET_KEY}} 46 | gpg-passphrase: GPG_PASSPHRASE 47 | 48 | - name: Publish 49 | run : | 50 | echo -e "${{ secrets.OSSRH_GPG_SECRET_KEY }}" | gpg --batch --import 51 | VERSION="${GITHUB_REF#refs/*/}" make publish 52 | env: 53 | GPG_SECRET_KEY: ${{ secrets.OSSRH_GPG_SECRET_KEY }} 54 | GPG_PASSPHRASE: ${{ secrets.OSSRH_GPG_SECRET_KEY_PASSPHRASE }} 55 | OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }} 56 | OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }} 57 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_enrichment/result_types/EnrichmentToStringer.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_enrichment.result_types; 2 | 3 | import java.lang.reflect.Array; 4 | import java.lang.reflect.Field; 5 | 6 | public class EnrichmentToStringer { 7 | @Override 8 | public String toString() { 9 | Class clazz = getClass(); 10 | StringBuilder sb = new StringBuilder(); 11 | sb.append(clazz.getSimpleName()).append(":\n"); 12 | 13 | while (clazz != null) { 14 | for (Field field : clazz.getDeclaredFields()) { 15 | field.setAccessible(true); 16 | try { 17 | Object value = field.get(this); 18 | if (value != null) { 19 | if (value.getClass().isArray()) { 20 | value = arrayToString(value); 21 | } 22 | sb.append(field.getName()).append(": ").append(value).append("\n"); 23 | } 24 | } catch (IllegalAccessException e) { 25 | e.printStackTrace(); 26 | } 27 | } 28 | clazz = clazz.getSuperclass(); 29 | } 30 | 31 | return sb.toString(); 32 | } 33 | 34 | private String arrayToString(Object array) { 35 | int length = Array.getLength(array); 36 | StringBuilder sb = new StringBuilder("["); 37 | for (int i = 0; i < length; i++) { 38 | Object element = Array.get(array, i); 39 | sb.append(element); 40 | if (i < length - 1) { 41 | sb.append(", "); 42 | } 43 | } 44 | sb.append("]"); 45 | return sb.toString(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/test/java/com/smartystreets/api/URLPrefixSenderTest.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api; 2 | 3 | 4 | import com.smartystreets.api.mocks.MockSender; 5 | import org.junit.Test; 6 | 7 | import static org.junit.Assert.assertEquals; 8 | 9 | public class URLPrefixSenderTest { 10 | 11 | @Test 12 | public void testRequestURLPresent() throws Exception { 13 | Request request = new Request(); 14 | request.setUrlComponents("/jimbo"); 15 | Sender inner = new MockSender(new Response(123, null)); 16 | Sender sender = new URLPrefixSender("http://mysite.com/lookup", inner); 17 | 18 | Response response = sender.send(request); 19 | 20 | assertEquals("http://mysite.com/lookup/jimbo?", request.getUrl()); 21 | } 22 | 23 | @Test 24 | public void testRequestURLNotPresent() throws Exception { 25 | Request request = new Request(); 26 | Sender inner = new MockSender(new Response(123, null)); 27 | Sender sender = new URLPrefixSender("http://mysite.com/lookup", inner); 28 | 29 | Response response = sender.send(request); 30 | 31 | assertEquals("http://mysite.com/lookup?", request.getUrl()); 32 | } 33 | 34 | @Test 35 | public void testMultipleSends() throws Exception { 36 | Request request = new Request(); 37 | request.setUrlComponents("/jimbo"); 38 | Sender inner = new MockSender(new Response(123, null)); 39 | Sender sender = new URLPrefixSender("http://mysite.com/lookup", inner); 40 | 41 | Response response = sender.send(request); 42 | response = sender.send(request); 43 | response = sender.send(request); 44 | 45 | assertEquals("http://mysite.com/lookup/jimbo?", request.getUrl()); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_zipcode/Result.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_zipcode; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * @see "https://smartystreets.com/docs/cloud/us-zipcode-api#root" 9 | */ 10 | public class Result implements Serializable { 11 | //region [ Fields ] 12 | 13 | String status; 14 | String reason; 15 | private String inputId; 16 | private int inputIndex; 17 | private City[] cities; 18 | private ZipCode[] zipCodes; 19 | 20 | //endregion 21 | 22 | public Result() { 23 | } 24 | 25 | public boolean isValid() { 26 | return (this.status == null && this.reason == null); 27 | } 28 | 29 | public City getCity(int index) { 30 | return this.cities[index]; 31 | } 32 | 33 | public ZipCode getZipCode(int index) { 34 | return this.zipCodes[index]; 35 | } 36 | 37 | //region [ Getters ] 38 | 39 | /** 40 | * 41 | * @return Returns a status if there was no match 42 | */ 43 | 44 | @JsonProperty("input_id") 45 | public String getInputId() { return this.inputId; } 46 | 47 | @JsonProperty("status") 48 | public String getStatus() { 49 | return this.status; 50 | } 51 | 52 | @JsonProperty("reason") 53 | public String getReason() { 54 | return this.reason; 55 | } 56 | 57 | @JsonProperty("input_index") 58 | public int getInputIndex() { 59 | return this.inputIndex; 60 | } 61 | 62 | @JsonProperty("city_states") 63 | public City[] getCities() { 64 | return this.cities; 65 | } 66 | 67 | @JsonProperty("zipcodes") 68 | public ZipCode[] getZipCodes() { 69 | return this.zipCodes; 70 | } 71 | 72 | //endregion 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_enrichment/lookup_types/secondary/SecondaryLookup.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_enrichment.lookup_types.secondary; 2 | 3 | import com.smartystreets.api.Serializer; 4 | import com.smartystreets.api.us_enrichment.result_types.AddressSearch; 5 | import com.smartystreets.api.us_enrichment.lookup_types.Lookup; 6 | import com.smartystreets.api.us_enrichment.result_types.secondary.SecondaryResponse; 7 | import okhttp3.Headers; 8 | import java.io.IOException; 9 | 10 | public class SecondaryLookup extends Lookup { 11 | private SecondaryResponse[] results; 12 | 13 | public SecondaryLookup() { 14 | } 15 | 16 | // legacy constructor - we recommend using the empty constructor and set parameters afterward 17 | public SecondaryLookup(String smartyKey) { 18 | super(smartyKey, ""); 19 | } 20 | 21 | // legacy constructor - we recommend using the empty constructor and set parameters afterward 22 | public SecondaryLookup(AddressSearch addressSearch) { 23 | super(addressSearch, "", ""); 24 | } 25 | 26 | public SecondaryResponse[] getResults() { 27 | return results; 28 | } 29 | 30 | public void setResults(SecondaryResponse[] results) { 31 | this.results = results; 32 | } 33 | 34 | @Override 35 | public void deserializeAndSetResults(Serializer serializer, byte[] payload, Headers headers) throws IOException { 36 | this.results = serializer.deserialize(payload, SecondaryResponse[].class, headers); 37 | if (headers != null) { 38 | this.results[0].setEtag(headers.get("etag")); 39 | } 40 | } 41 | 42 | @Override 43 | public String getDataSetName() { 44 | return secondaryDataSet; 45 | } 46 | 47 | @Override 48 | public String getDataSubsetName() { 49 | return emptyDataSubset; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_enrichment/lookup_types/secondary/SecondaryCountLookup.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_enrichment.lookup_types.secondary; 2 | 3 | import com.smartystreets.api.Serializer; 4 | import com.smartystreets.api.us_enrichment.result_types.AddressSearch; 5 | import com.smartystreets.api.us_enrichment.lookup_types.Lookup; 6 | import com.smartystreets.api.us_enrichment.result_types.secondary.SecondaryCountResponse; 7 | import okhttp3.Headers; 8 | import java.io.IOException; 9 | 10 | public class SecondaryCountLookup extends Lookup { 11 | 12 | private SecondaryCountResponse[] results; 13 | 14 | public SecondaryCountLookup() { 15 | } 16 | 17 | // legacy constructor - we recommend using the empty constructor and set parameters afterward 18 | public SecondaryCountLookup(String smartyKey) { 19 | super(smartyKey, ""); 20 | } 21 | 22 | // legacy constructor - we recommend using the empty constructor and set parameters afterward 23 | public SecondaryCountLookup(AddressSearch addressSearch) { 24 | super(addressSearch, "", ""); 25 | } 26 | 27 | public SecondaryCountResponse[] getResults() { 28 | return results; 29 | } 30 | 31 | public void setResults(SecondaryCountResponse[] results) { 32 | this.results = results; 33 | } 34 | 35 | @Override 36 | public void deserializeAndSetResults(Serializer serializer, byte[] payload, Headers headers) throws IOException { 37 | this.results = serializer.deserialize(payload, SecondaryCountResponse[].class, headers); 38 | if (headers != null) { 39 | this.results[0].setEtag(headers.get("etag")); 40 | } 41 | } 42 | 43 | @Override 44 | public String getDataSetName() { 45 | return secondaryDataSet; 46 | } 47 | 48 | @Override 49 | public String getDataSubsetName() { 50 | return secondaryCountDataSubset; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/test/java/com/smartystreets/api/us_extract/ResultTest.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_extract; 2 | 3 | import com.smartystreets.api.SmartySerializer; 4 | import com.smartystreets.api.us_street.Candidate; 5 | import org.junit.Test; 6 | 7 | import java.io.IOException; 8 | 9 | import static org.junit.Assert.assertEquals; 10 | import static org.junit.Assert.assertNotNull; 11 | 12 | public class ResultTest { 13 | private final SmartySerializer smartySerializer = new SmartySerializer(); 14 | private static final String responsePayload = "{\"meta\":{\"lines\":1,\"unicode\":true,\"address_count\":2," + 15 | "\"verified_count\":3,\"bytes\":4,\"character_count\":5},\"addresses\":[{\"text\":\"6\"," + 16 | "\"verified\":true,\"line\":7,\"start\":8,\"end\":9,\"api_output\":[{}]},{\"text\":\"10\"}]}"; 17 | 18 | @Test 19 | public void testAllFieldsFilledCorrectly() throws IOException { 20 | Result result = this.smartySerializer.deserialize(responsePayload.getBytes(), Result.class); 21 | 22 | Metadata metadata = result.getMetadata(); 23 | assertNotNull(metadata); 24 | assertEquals(1, metadata.getLines()); 25 | assertEquals(true, metadata.isUnicode()); 26 | assertEquals(2, metadata.getAddressCount()); 27 | assertEquals(3, metadata.getVerifiedCount()); 28 | assertEquals(4, metadata.getBytes()); 29 | assertEquals(5, metadata.getCharacterCount()); 30 | 31 | Address address = result.getAddress(0); 32 | assertNotNull(address); 33 | assertEquals("6", address.getText()); 34 | assertEquals(true, address.isVerified()); 35 | assertEquals(7, address.getLine()); 36 | assertEquals(8, address.getStart()); 37 | assertEquals(9, address.getEnd()); 38 | assertEquals("10", result.getAddresses()[1].getText()); 39 | 40 | Candidate[] candidates = address.getCandidates(); 41 | assertNotNull(candidates); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/test/java/com/smartystreets/api/mocks/MockCrashingSender.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.mocks; 2 | 3 | import com.smartystreets.api.Request; 4 | import com.smartystreets.api.Response; 5 | import com.smartystreets.api.Sender; 6 | import com.smartystreets.api.TooManyRequestsResponse; 7 | import com.smartystreets.api.exceptions.SmartyException; 8 | import okhttp3.Headers; 9 | 10 | import java.io.IOException; 11 | 12 | public class MockCrashingSender implements Sender { 13 | private int sendCount = 0; 14 | private final static int STATUS_CODE = 200; 15 | 16 | @Override 17 | public Response send(Request request) throws SmartyException, IOException { 18 | this.sendCount++; 19 | 20 | Response response = new Response(STATUS_CODE, new byte[]{}); 21 | 22 | if (request.getUrl().contains("TooManyRequests")) { 23 | if (this.sendCount <= 2) { 24 | response = new TooManyRequestsResponse(Headers.of("Retry-After", "7"), STATUS_CODE, new byte[]{}); 25 | } 26 | } 27 | 28 | if (request.getUrl().contains("RetryThreeTimes")) { 29 | if (this.sendCount <= 3) { 30 | throw new IOException("You need to retry"); 31 | } 32 | } 33 | 34 | if (request.getUrl().contains("RetryMaxTimes")) { 35 | throw new IOException("Retrying won't help"); 36 | } 37 | 38 | if (request.getUrl().contains("RetryFifteenTimes") ) { 39 | if (this.sendCount <= 14) 40 | throw new IOException("You need to retry"); 41 | } 42 | 43 | if (request.getUrl().contains("WaitTimeTooLong") ) { 44 | if (this.sendCount <= 2) { 45 | response = new TooManyRequestsResponse(Headers.of("Retry-After", "4"), STATUS_CODE, new byte[]{}); 46 | } 47 | } 48 | 49 | return response; 50 | } 51 | 52 | public int getSendCount() { 53 | return this.sendCount; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_enrichment/lookup_types/property_principal/PropertyPrincipalLookup.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_enrichment.lookup_types.property_principal; 2 | 3 | import com.smartystreets.api.Serializer; 4 | import com.smartystreets.api.us_enrichment.result_types.AddressSearch; 5 | import com.smartystreets.api.us_enrichment.lookup_types.Lookup; 6 | import com.smartystreets.api.us_enrichment.result_types.property_principal.PrincipalResponse; 7 | import okhttp3.Headers; 8 | 9 | import java.io.IOException; 10 | 11 | public class PropertyPrincipalLookup extends Lookup { 12 | private PrincipalResponse[] results; 13 | 14 | public PropertyPrincipalLookup() { 15 | } 16 | 17 | // legacy constructor - we recommend using the empty constructor and set parameters afterward 18 | public PropertyPrincipalLookup(String smartyKey, String include, String exclude, String etag) { 19 | super(smartyKey, include, exclude, etag); 20 | } 21 | 22 | // legacy constructor - we recommend using the empty constructor and set parameters afterward 23 | public PropertyPrincipalLookup(AddressSearch addressSearch) { 24 | super(addressSearch, "", ""); 25 | } 26 | 27 | public PrincipalResponse[] getResults() { 28 | return results; 29 | } 30 | 31 | public void setResults(PrincipalResponse[] results) { 32 | this.results = results; 33 | } 34 | 35 | @Override 36 | public void deserializeAndSetResults(Serializer serializer, byte[] payload, Headers headers) throws IOException { 37 | this.results = serializer.deserialize(payload, PrincipalResponse[].class, headers); 38 | if (headers != null) { 39 | this.results[0].setEtag(headers.get("etag")); 40 | } 41 | } 42 | 43 | @Override 44 | public String getDataSetName() { 45 | return propertyDataSet; 46 | } 47 | 48 | @Override 49 | public String getDataSubsetName() { 50 | return principalDataSubset; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_extract/Client.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_extract; 2 | 3 | import com.smartystreets.api.Request; 4 | import com.smartystreets.api.Response; 5 | import com.smartystreets.api.Sender; 6 | import com.smartystreets.api.Serializer; 7 | import com.smartystreets.api.exceptions.SmartyException; 8 | 9 | import java.io.IOException; 10 | 11 | /** 12 | * This client sends lookups to the SmartyStreets US Extract API,
13 | * and attaches the results to the Lookup objects. 14 | */ 15 | public class Client { 16 | private Sender sender; 17 | private Serializer serializer; 18 | 19 | public Client(Sender sender, Serializer serializer) { 20 | this.sender = sender; 21 | this.serializer = serializer; 22 | } 23 | 24 | public Result send(Lookup lookup) throws IOException, SmartyException, InterruptedException { 25 | if (lookup == null || lookup.getText() == null || lookup.getText().isEmpty()) 26 | throw new SmartyException("Client.send() requires a Lookup with the 'text' field set"); 27 | 28 | Request request = this.buildRequest(lookup); 29 | Response response = this.sender.send(request); 30 | Result result = this.serializer.deserialize(response.getPayload(), Result.class); 31 | 32 | lookup.setResult(result); 33 | return result; 34 | } 35 | 36 | private Request buildRequest(Lookup lookup) { 37 | Request request = new Request(); 38 | request.setContentType("text/plain"); 39 | request.setPayload(lookup.getText().getBytes()); 40 | 41 | request.putParameter("html", lookup.isHtml()); 42 | request.putParameter("aggressive", String.valueOf(lookup.isAggressive())); 43 | request.putParameter("addr_line_breaks", String.valueOf(lookup.addressesHaveLineBreaks())); 44 | request.putParameter("addr_per_line", String.valueOf(lookup.getAddressesPerLine())); 45 | request.putParameter("match", lookup.getMatch()); 46 | 47 | return request; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/examples/InternationalPostalCodeExample.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | import com.smartystreets.api.ClientBuilder; 4 | import com.smartystreets.api.international_postal_code.Candidate; 5 | import com.smartystreets.api.international_postal_code.Client; 6 | import com.smartystreets.api.international_postal_code.Lookup; 7 | 8 | public class InternationalPostalCodeExample { 9 | public static void main(String[] args) throws Exception { 10 | // To run: set environment variables or replace with your credentials. 11 | String authId = System.getenv("SMARTY_AUTH_ID"); 12 | String authToken = System.getenv("SMARTY_AUTH_TOKEN"); 13 | 14 | Client client = new ClientBuilder(authId, authToken) 15 | .buildInternationalPostalCodeApiClient(); 16 | 17 | Lookup lookup = new Lookup(); 18 | lookup.setInputId("ID-8675309"); 19 | lookup.setLocality("Sao Paulo"); 20 | lookup.setAdministrativeArea("SP"); 21 | lookup.setCountry("Brazil"); 22 | lookup.setPostalCode("02516"); 23 | 24 | client.send(lookup); 25 | 26 | System.out.println("Results:"); 27 | System.out.println(); 28 | for (Candidate candidate : lookup.getResult()) { 29 | display(candidate.getInputId()); 30 | display(candidate.getCountryIso3()); 31 | display(candidate.getLocality()); 32 | display(candidate.getDependentLocality()); 33 | display(candidate.getDoubleDependentLocality()); 34 | display(candidate.getSubAdministrativeArea()); 35 | display(candidate.getAdministrativeArea()); 36 | display(candidate.getSuperAdministrativeArea()); 37 | display(candidate.getPostalCode()); 38 | System.out.println(); 39 | } 40 | System.out.println("OK"); 41 | } 42 | private static void display(String value) { 43 | if (value != null && value.length() > 0) { 44 | System.out.printf(" %s\n", value); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/international_street/RootLevel.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.international_street; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | import java.io.Serializable; 6 | 7 | public class RootLevel implements Serializable { 8 | 9 | //region [ Fields ] 10 | 11 | private String inputId; 12 | private String organization; 13 | private String address1; 14 | private String address2; 15 | private String address3; 16 | private String address4; 17 | private String address5; 18 | private String address6; 19 | private String address7; 20 | private String address8; 21 | private String address9; 22 | private String address10; 23 | private String address11; 24 | private String address12; 25 | 26 | //endregion 27 | 28 | //region [ Getters ] 29 | 30 | @JsonProperty("input_id") 31 | public String getInputId() { return inputId; } 32 | 33 | public String getOrganization() { 34 | return organization; 35 | } 36 | 37 | public String getAddress1() { 38 | return address1; 39 | } 40 | 41 | public String getAddress2() { 42 | return address2; 43 | } 44 | 45 | public String getAddress3() { 46 | return address3; 47 | } 48 | 49 | public String getAddress4() { 50 | return address4; 51 | } 52 | 53 | public String getAddress5() { 54 | return address5; 55 | } 56 | 57 | public String getAddress6() { 58 | return address6; 59 | } 60 | 61 | public String getAddress7() { 62 | return address7; 63 | } 64 | 65 | public String getAddress8() { 66 | return address8; 67 | } 68 | 69 | public String getAddress9() { 70 | return address9; 71 | } 72 | 73 | public String getAddress10() { 74 | return address10; 75 | } 76 | 77 | public String getAddress11() { 78 | return address11; 79 | } 80 | 81 | public String getAddress12() { 82 | return address12; 83 | } 84 | 85 | //endregion 86 | } 87 | -------------------------------------------------------------------------------- /src/test/java/com/smartystreets/api/StatusCodeSenderTest.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api; 2 | 3 | import com.smartystreets.api.exceptions.*; 4 | import com.smartystreets.api.mocks.MockStatusCodeSender; 5 | import org.junit.Test; 6 | 7 | import static org.junit.Assert.assertEquals; 8 | import static org.junit.Assert.assertThrows; 9 | 10 | public class StatusCodeSenderTest { 11 | 12 | @Test 13 | public void test200Response() throws Exception { 14 | StatusCodeSender sender = new StatusCodeSender(new MockStatusCodeSender(200)); 15 | 16 | Response response = sender.send(new Request()); 17 | 18 | assertEquals(200, response.getStatusCode()); 19 | } 20 | 21 | @Test 22 | public void test401ResponseThrowsBadCredentialsException() throws Exception { 23 | this.assertSend(401, BadCredentialsException.class); 24 | } 25 | 26 | @Test 27 | public void test402ResponsePThrowsPaymentRequiredException() throws Exception { 28 | this.assertSend(402, PaymentRequiredException.class); 29 | } 30 | 31 | @Test 32 | public void test413ResponseThrowsRequestEntityTooLargeException() throws Exception { 33 | this.assertSend(413, RequestEntityTooLargeException.class); 34 | } 35 | 36 | @Test 37 | public void test400ResponseThrowsBadRequestException() throws Exception { 38 | this.assertSend(400, BadRequestException.class); 39 | } 40 | 41 | @Test 42 | public void test500ResponseThrowsInternalServerErrorException() throws Exception { 43 | this.assertSend(500, InternalServerErrorException.class); 44 | } 45 | 46 | @Test 47 | public void test503ResponseThrowsServiceUnavailableException() throws Exception { 48 | this.assertSend(503, ServiceUnavailableException.class); 49 | } 50 | 51 | private void assertSend(int statusCode, Class exceptionType) throws Exception { 52 | StatusCodeSender sender = new StatusCodeSender(new MockStatusCodeSender(statusCode)); 53 | 54 | assertThrows(SmartyException.class, () -> sender.send(new Request())); 55 | } 56 | } -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_enrichment/result_types/property_principal/PrincipalFinancialHistoryEntry.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_enrichment.result_types.property_principal; 2 | 3 | import com.smartystreets.api.us_enrichment.result_types.EnrichmentToStringer; 4 | 5 | public class PrincipalFinancialHistoryEntry extends EnrichmentToStringer { 6 | 7 | public String code_title_company; 8 | public String document_type_description; 9 | public String instrument_date; 10 | public String interest_rate_type_2; 11 | public String lender_address; 12 | public String lender_address_2; 13 | public String lender_city; 14 | public String lender_city_2; 15 | public String lender_code_2; 16 | public String lender_first_name; 17 | public String lender_first_name_2; 18 | public String lender_last_name; 19 | public String lender_last_name_2; 20 | public String lender_name; 21 | public String lender_name_2; 22 | public String lender_seller_carry_back; 23 | public String lender_seller_carry_back_2; 24 | public String lender_state; 25 | public String lender_state_2; 26 | public String lender_zip; 27 | public String lender_zip_2; 28 | public String lender_zip_extended; 29 | public String lender_zip_extended_2; 30 | public String mortgage_amount; 31 | public String mortgage_amount_2; 32 | public String mortgage_due_date; 33 | public String mortgage_due_date_2; 34 | public String mortgage_interest_rate; 35 | public String mortgage_interest_rate_type; 36 | public String mortgage_lender_code; 37 | public String mortgage_rate_2; 38 | public String mortgage_recording_date; 39 | public String mortgage_recording_date_2; 40 | public String mortgage_term; 41 | public String mortgage_term_2; 42 | public String mortgage_term_type; 43 | public String mortgage_term_type_2; 44 | public String mortgage_type; 45 | public String mortgage_type_2; 46 | public String multi_parcel_flag; 47 | public String name_title_company; 48 | public String recording_date; 49 | public String transfer_amount; 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/international_autocomplete/Candidate.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.international_autocomplete; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * @see "https://smartystreets.com/docs/cloud/international-address-autocomplete-api#http-response" 9 | */ 10 | public class Candidate implements Serializable { 11 | //region [ Fields ] 12 | 13 | private String street; 14 | private String locality; 15 | private String administrativeArea; 16 | private String administrativeAreaShort; 17 | private String administrativeAreaLong; 18 | private String postalCode; 19 | private String countryISO3; 20 | 21 | private int entries; 22 | private String addressText; 23 | private String addressID; 24 | 25 | //region [ Fields ] 26 | 27 | //region [ Getters ] 28 | 29 | public String getStreet() { 30 | return street; 31 | } 32 | 33 | public String getLocality() { 34 | return locality; 35 | } 36 | 37 | @JsonProperty("administrative_area") 38 | public String getAdministrativeArea() { 39 | return administrativeArea; 40 | } 41 | 42 | @JsonProperty("administrative_area_short") 43 | public String getAdministrativeAreaShort() { 44 | return administrativeAreaShort; 45 | } 46 | 47 | @JsonProperty("administrative_area_long") 48 | public String getAdministrativeAreaLong() { 49 | return administrativeAreaLong; 50 | } 51 | 52 | @JsonProperty("postal_code") 53 | public String getPostalCode() { 54 | return postalCode; 55 | } 56 | 57 | @JsonProperty("country_iso3") 58 | public String getCountryISO3() { 59 | return countryISO3; 60 | } 61 | 62 | @JsonProperty("entries") 63 | public int getEntries() { 64 | return entries; 65 | } 66 | 67 | @JsonProperty("address_text") 68 | public String getAddressText() { 69 | return addressText; 70 | } 71 | 72 | @JsonProperty("address_id") 73 | public String getAddressID() { 74 | return addressID; 75 | } 76 | 77 | //endregion 78 | } 79 | -------------------------------------------------------------------------------- /src/test/java/com/smartystreets/api/CustomQuerySenderTest.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api; 2 | 3 | import com.smartystreets.api.mocks.MockSender; 4 | import org.junit.Test; 5 | 6 | import java.util.HashMap; 7 | 8 | import static org.junit.Assert.assertEquals; 9 | 10 | public class CustomQuerySenderTest { 11 | 12 | @Test 13 | public void testAllCustomQueriesAreAddedToTheRequest() throws Exception { 14 | Request request = new Request(); 15 | HashMap queries = new HashMap<>(); 16 | queries.put("query", "1,2,3"); 17 | queries.put("test", "2"); 18 | Sender inner = new MockSender(new Response(123, null)); 19 | Sender sender = new CustomQuerySender(queries, inner); 20 | 21 | sender.send(request); 22 | 23 | assertEquals("?test=2&query=1%2C2%2C3", request.getUrl()); 24 | } 25 | 26 | @Test 27 | public void testNoCustomQueries() throws Exception { 28 | Request request = new Request(); 29 | HashMap queries = new HashMap<>(); 30 | Sender inner = new MockSender(new Response(123, null)); 31 | Sender sender = new CustomQuerySender(queries, inner); 32 | 33 | sender.send(request); 34 | 35 | assertEquals("?", request.getUrl()); 36 | } 37 | 38 | @Test 39 | public void testEmptyCustomQueries() throws Exception { 40 | Request request = new Request(); 41 | Sender inner = new MockSender(new Response(123, null)); 42 | HashMap queries = new HashMap<>(); 43 | queries.put("query", ""); 44 | queries.put("", "test"); 45 | Sender sender = new CustomQuerySender(queries, inner); 46 | 47 | sender.send(request); 48 | 49 | assertEquals("?query=", request.getUrl()); 50 | } 51 | 52 | @Test 53 | public void testNullCustomQueries() throws Exception { 54 | Request request = new Request(); 55 | Sender inner = new MockSender(new Response(123, null)); 56 | Sender sender = new CustomQuerySender(null, inner); 57 | 58 | sender.send(request); 59 | 60 | assertEquals("?", request.getUrl()); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/international_autocomplete/Client.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.international_autocomplete; 2 | 3 | import com.smartystreets.api.*; 4 | import com.smartystreets.api.exceptions.SmartyException; 5 | 6 | import java.io.IOException; 7 | 8 | /** 9 | * This client sends lookups to the SmartyStreets US Autocomplete Pro API,
10 | * and attaches the results to the appropriate Lookup objects. 11 | */ 12 | public class Client { 13 | private final Sender sender; 14 | private final Serializer serializer; 15 | 16 | public Client(Sender sender, Serializer serializer) { 17 | this.sender = sender; 18 | this.serializer = serializer; 19 | } 20 | 21 | public Candidate[] send(Lookup lookup) throws SmartyException, IOException, InterruptedException { 22 | if (lookup == null || lookup.getSearch() == null || (lookup.getSearch().isEmpty() && lookup.getAddressID().isEmpty())) 23 | throw new SmartyException("Send() must be passed a Lookup with the prefix field set."); 24 | 25 | Request request = this.buildRequest(lookup); 26 | 27 | Response response = this.sender.send(request); 28 | 29 | //Need to go through and fix all of these 30 | Result result = this.serializer.deserialize(response.getPayload(), Result.class); 31 | Candidate[] candidates = result.getCandidates(); 32 | lookup.setResult(candidates); 33 | 34 | return candidates; 35 | } 36 | 37 | private Request buildRequest(Lookup lookup) { 38 | Request request = new Request(); 39 | 40 | if(lookup.getAddressID() != null && !lookup.getAddressID().isEmpty()) { 41 | request.setUrlComponents("/" + lookup.getAddressID()); 42 | } 43 | 44 | request.putParameter("country", lookup.getCountry()); 45 | request.putParameter("search", lookup.getSearch()); 46 | request.putParameter("max_results", String.valueOf(lookup.getMaxResults())); 47 | request.putParameter("include_only_locality", lookup.getLocality()); 48 | request.putParameter("include_only_postal_code", lookup.getPostalCode()); 49 | 50 | return request; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | 3 | VERSION_FILE1 := pom.xml 4 | VERSION_FILE2 := src/main/java/com/smartystreets/api/Version.java 5 | 6 | clean: 7 | git checkout "$(VERSION_FILE1)" "$(VERSION_FILE2)" 8 | mvn clean 9 | 10 | test: 11 | mvn test 12 | 13 | integration-test: 14 | mvn integration-test 15 | 16 | compile: clean test 17 | mvn compile 18 | 19 | publish: compile 20 | sed -i -r "s/0\.0\.0/${VERSION}/g" "$(VERSION_FILE1)" && sed -i -r "s/0\.0\.0/${VERSION}/g" "$(VERSION_FILE2)" \ 21 | && mvn \ 22 | --batch-mode \ 23 | --no-transfer-progress \ 24 | -DskipITs \ 25 | -Dgpg.passphrase=${GPG_PASSPHRASE} \ 26 | deploy 27 | 28 | international_autocomplete_api: 29 | mvn exec:java -Dexec.mainClass="examples.InternationalAutocompleteExample" 30 | 31 | international_street_api: 32 | mvn exec:java -Dexec.mainClass="examples.InternationalExample" 33 | 34 | international_postal_code_api: 35 | mvn exec:java -Dexec.mainClass="examples.InternationalPostalCodeExample" 36 | 37 | us_autocomplete_pro_api: 38 | mvn exec:java -Dexec.mainClass="examples.UsAutocompleteProExample" 39 | 40 | us_enrichment_api: 41 | mvn exec:java -Dexec.mainClass="examples.UsEnrichmentExample" 42 | 43 | us_extract_api: 44 | mvn exec:java -Dexec.mainClass="examples.UsExtractExample" 45 | 46 | us_reverse_geo_api: 47 | mvn exec:java -Dexec.mainClass="examples.UsReverseGeoExample" 48 | 49 | us_street_api: 50 | mvn exec:java -Dexec.mainClass="examples.UsStreetSingleAddressExample" && mvn exec:java -Dexec.mainClass="examples.UsStreetMultipleAddressesExample" && mvn exec:java -Dexec.mainClass="examples.UsStreetComponentAnalysisExample" 51 | 52 | us_zipcode_api: 53 | mvn exec:java -Dexec.mainClass="examples.UsZipCodeSingleLookupExample" && mvn exec:java -Dexec.mainClass="examples.UsZipCodeMultipleLookupsExample" 54 | 55 | examples: international_autocomplete_api international_street_api us_autocomplete_pro_api us_enrichment_api us_extract_api us_reverse_geo_api us_street_api us_zipcode_api 56 | 57 | .PHONY: clean test integration-test compile publish examples international_autocomplete_api international_street_api us_autocomplete_pro_api us_enrichment_api us_extract_api us_reverse_geo_api us_street_api us_zipcode_api -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/international_postal_code/Candidate.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.international_postal_code; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import java.io.Serializable; 5 | 6 | /** 7 | * Represents a single result candidate for an international postal code lookup. 8 | * @see "https://smartystreets.com/docs/international-postal-code-api" 9 | */ 10 | public class Candidate implements Serializable { 11 | @JsonProperty("input_id") 12 | private String inputId; 13 | @JsonProperty("administrative_area") 14 | private String administrativeArea; 15 | @JsonProperty("sub_administrative_area") 16 | private String subAdministrativeArea; 17 | @JsonProperty("super_administrative_area") 18 | private String superAdministrativeArea; 19 | @JsonProperty("country_iso_3") 20 | private String countryIso3; 21 | @JsonProperty("locality") 22 | private String locality; 23 | @JsonProperty("dependent_locality") 24 | private String dependentLocality; 25 | @JsonProperty("dependent_locality_name") 26 | private String dependentLocalityName; 27 | @JsonProperty("double_dependent_locality") 28 | private String doubleDependentLocality; 29 | @JsonProperty("postal_code") 30 | private String postalCode; 31 | @JsonProperty("postal_code_extra") 32 | private String postalCodeExtra; 33 | 34 | // region [Getters] 35 | public String getInputId() { return inputId; } 36 | public String getAdministrativeArea() { return administrativeArea; } 37 | public String getSubAdministrativeArea() { return subAdministrativeArea; } 38 | public String getSuperAdministrativeArea() { return superAdministrativeArea; } 39 | public String getCountryIso3() { return countryIso3; } 40 | public String getLocality() { return locality; } 41 | public String getDependentLocality() { return dependentLocality; } 42 | public String getDependentLocalityName() { return dependentLocalityName; } 43 | public String getDoubleDependentLocality() { return doubleDependentLocality; } 44 | public String getPostalCode() { return postalCode; } 45 | public String getPostalCodeExtra() { return postalCodeExtra; } 46 | // endregion 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_enrichment/lookup_types/georeference/GeoReferenceLookup.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_enrichment.lookup_types.georeference; 2 | 3 | import com.smartystreets.api.Serializer; 4 | import com.smartystreets.api.us_enrichment.lookup_types.Lookup; 5 | import com.smartystreets.api.us_enrichment.result_types.georeference.GeoReferenceResponse; 6 | import com.smartystreets.api.us_enrichment.result_types.property_principal.PrincipalResponse; 7 | import okhttp3.Headers; 8 | 9 | import java.io.IOException; 10 | 11 | import static com.smartystreets.api.us_enrichment.lookup_types.Lookup.emptyDataSubset; 12 | import static com.smartystreets.api.us_enrichment.lookup_types.Lookup.geoReferenceDataSet; 13 | 14 | public class GeoReferenceLookup extends Lookup { 15 | private GeoReferenceResponse[] results; 16 | private String subset; 17 | 18 | public GeoReferenceLookup(String subset) { 19 | this.subset = subset; 20 | } 21 | 22 | // This legacy constructor is inadequate as it will only query the lastest census version of the data because there is not a way to set the data subset. 23 | // Use GeoReferenceLookup(String subset) to set the data subset then set all other applicable lookup fields manually. 24 | public GeoReferenceLookup(String smartyKey, String etag) { 25 | super(smartyKey, etag); 26 | } 27 | 28 | public GeoReferenceResponse[] getResults() { 29 | return results; 30 | } 31 | 32 | public void setResults(GeoReferenceResponse[] results) { 33 | this.results = results; 34 | } 35 | 36 | @Override 37 | public void deserializeAndSetResults(Serializer serializer, byte[] payload, Headers headers) throws IOException { 38 | this.results = serializer.deserialize(payload, GeoReferenceResponse[].class, headers); 39 | if (headers != null) { 40 | this.results[0].setEtag(headers.get("etag")); 41 | } 42 | } 43 | 44 | @Override 45 | public String getDataSetName() { 46 | return geoReferenceDataSet; 47 | } 48 | 49 | @Override 50 | public String getDataSubsetName() { 51 | if (this.subset == null) { 52 | this.subset = ""; 53 | } 54 | return this.subset; 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/test/java/com/smartystreets/api/international_autocomplete/CandidateTest.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.international_autocomplete; 2 | 3 | import com.smartystreets.api.SmartySerializer; 4 | import org.junit.Test; 5 | 6 | import static org.junit.Assert.assertEquals; 7 | 8 | public class CandidateTest { 9 | 10 | 11 | @Test 12 | public void testFullJSONDeserialization() throws Exception { 13 | 14 | String rawJSON = "{\n" + 15 | "\"candidates\": [\n" + 16 | "{\n" + 17 | "\"street\": \"12TH AV\",\n" + 18 | "\"locality\": \"OCEAN GROVE\",\n" + 19 | "\"administrative_area\": \"VIC\",\n" + 20 | "\"postal_code\": \"3226\",\n" + 21 | "\"country_iso3\": \"AUS\"\n" + 22 | "},\n" + 23 | "{\n" + 24 | "\"street\": \"MONG FAT STREET\",\n" + 25 | "\"locality\": \"TUEN MUN\",\n" + 26 | "\"administrative_area\": \"TUEN MUN DISTRICT\",\n" + 27 | "\"country_iso3\": \"HKG\"\n" + 28 | "},\n" + 29 | "{\n" + 30 | "\"entries\": 54,\n" + 31 | "\"address_text\": \"11 Laguna Pky Brechin, ON, L0K 1B0\",\n" + 32 | "\"address_id\": \"HB5SHA8DBQ8QKS0mED0nRykgGEctOhM2LRs\"\n" + 33 | "}\n" + 34 | "]\n" + 35 | "}"; 36 | 37 | byte[] bytes = rawJSON.getBytes(); 38 | 39 | Result result = new SmartySerializer().deserialize(bytes, Result.class); 40 | Candidate[] candidates = result.getCandidates(); 41 | 42 | assertEquals("12TH AV", candidates[0].getStreet()); 43 | assertEquals("OCEAN GROVE", candidates[0].getLocality()); 44 | assertEquals("VIC", candidates[0].getAdministrativeArea()); 45 | assertEquals("3226", candidates[0].getPostalCode()); 46 | assertEquals("AUS", candidates[0].getCountryISO3()); 47 | assertEquals("MONG FAT STREET", candidates[1].getStreet()); 48 | assertEquals("TUEN MUN", candidates[1].getLocality()); 49 | assertEquals("TUEN MUN DISTRICT", candidates[1].getAdministrativeArea()); 50 | assertEquals("HKG", candidates[1].getCountryISO3()); 51 | assertEquals(54, candidates[2].getEntries()); 52 | assertEquals("11 Laguna Pky Brechin, ON, L0K 1B0", candidates[2].getAddressText()); 53 | assertEquals("HB5SHA8DBQ8QKS0mED0nRykgGEctOhM2LRs", candidates[2].getAddressID()); 54 | } 55 | } -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/international_postal_code/Lookup.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.international_postal_code; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | /** 6 | * Lookup input for International Postal Code API (see Go Lookup struct/docs) 7 | * Holds input data and the resulting candidates. 8 | * @see "https://smartystreets.com/docs/cloud/international-postal-code-api" 9 | */ 10 | public class Lookup { 11 | @JsonProperty("input_id") 12 | private String inputId; 13 | @JsonProperty("country") 14 | private String country; 15 | //private Language language; // future 16 | //private String features; // future 17 | @JsonProperty("locality") 18 | private String locality; 19 | @JsonProperty("administrative_area") 20 | private String administrativeArea; 21 | @JsonProperty("postal_code") 22 | private String postalCode; 23 | 24 | // Result set after API call 25 | private Candidate[] result; 26 | 27 | public Lookup() { 28 | this.result = new Candidate[0]; 29 | } 30 | 31 | // region [Getters] 32 | public String getInputId() { return inputId; } 33 | public String getCountry() { return country; } 34 | //public Language getLanguage() { return language; } // future 35 | //public String getFeatures() { return features; } // future 36 | public String getLocality() { return locality; } 37 | public String getAdministrativeArea() { return administrativeArea; } 38 | public String getPostalCode() { return postalCode; } 39 | public Candidate[] getResult() { return result; } 40 | public Candidate getResult(int i) { return result[i]; } 41 | // endregion 42 | 43 | // region [Setters] 44 | public void setInputId(String inputId) { this.inputId = inputId; } 45 | public void setCountry(String country) { this.country = country; } 46 | //public void setLanguage(Language language) { this.language = language; } // future 47 | //public void setFeatures(String features) { this.features = features; } // future 48 | public void setLocality(String locality) { this.locality = locality; } 49 | public void setAdministrativeArea(String administrativeArea) { this.administrativeArea = administrativeArea; } 50 | public void setPostalCode(String postalCode) { this.postalCode = postalCode; } 51 | public void setResult(Candidate[] candidates) { this.result = candidates; } 52 | // endregion 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_enrichment/result_types/AddressSearch.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_enrichment.result_types; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | import java.net.URLEncoder; 5 | import java.nio.charset.StandardCharsets; 6 | 7 | public class AddressSearch { 8 | private String freeform; 9 | private String street; 10 | private String city; 11 | private String state; 12 | private String zipcode; 13 | 14 | public String freeform() { 15 | return freeform; 16 | } 17 | 18 | public AddressSearch withFreeform(String freeform) { 19 | this.freeform = freeform; 20 | return this; 21 | } 22 | 23 | public String street() { 24 | return street; 25 | } 26 | 27 | public AddressSearch withStreet(String street) { 28 | this.street = street; 29 | return this; 30 | } 31 | 32 | public String city() { 33 | return this.city; 34 | } 35 | 36 | public AddressSearch withCity(String city) { 37 | this.city = city; 38 | return this; 39 | } 40 | 41 | public String state() { 42 | return this.state; 43 | } 44 | 45 | public AddressSearch withState(String state) { 46 | this.state = state; 47 | return this; 48 | } 49 | 50 | public String zipcode() { 51 | return this.zipcode; 52 | } 53 | 54 | public AddressSearch withZipcode(String zipcode) { 55 | this.zipcode = zipcode; 56 | return this; 57 | } 58 | 59 | public String toSearchString() throws UnsupportedEncodingException { 60 | StringBuilder sb = new StringBuilder(); 61 | if (this.freeform == null || this.freeform.isEmpty()) { 62 | sb.append("?street="); 63 | sb.append(this.encode(this.street)); 64 | sb.append("&city="); 65 | sb.append(this.encode(this.city)); 66 | sb.append("&state="); 67 | sb.append(this.encode(this.state)); 68 | sb.append("&zipcode="); 69 | sb.append(this.encode(this.zipcode)); 70 | } else { 71 | sb.append("?freeform="); 72 | sb.append(this.encode(this.freeform)); 73 | } 74 | return sb.toString(); 75 | } 76 | 77 | private String encode(String part) throws UnsupportedEncodingException { 78 | return URLEncoder.encode(part, StandardCharsets.UTF_8.toString()); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_zipcode/ZipCode.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_zipcode; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * @see "https://smartystreets.com/docs/cloud/us-zipcode-api#zipcodes" 9 | */ 10 | public class ZipCode implements Serializable { 11 | //region [ fields ] 12 | 13 | private String zipCode; 14 | private String zipCodeType; 15 | private String defaultCity; 16 | private String countyFips; 17 | private String countyName; 18 | private String stateAbbreviation; 19 | private String state; 20 | private double latitude; 21 | private double longitude; 22 | private String precision; 23 | private AlternateCounty[] alternateCounties; 24 | 25 | //endregion 26 | 27 | //region [ Getter ] 28 | 29 | @JsonProperty("zipcode") 30 | public String getZipCode() { 31 | return this.zipCode; 32 | } 33 | 34 | @JsonProperty("zipcode_type") 35 | public String getZipCodeType() { 36 | return this.zipCodeType; 37 | } 38 | 39 | @JsonProperty("default_city") 40 | public String getDefaultCity() { 41 | return this.defaultCity; 42 | } 43 | 44 | @JsonProperty("county_fips") 45 | public String getCountyFips() { 46 | return this.countyFips; 47 | } 48 | 49 | @JsonProperty("county_name") 50 | public String getCountyName() { 51 | return this.countyName; 52 | } 53 | 54 | @JsonProperty("state_abbreviation") 55 | public String getStateAbbreviation() { 56 | return stateAbbreviation; 57 | } 58 | 59 | @JsonProperty("state") 60 | public String getState() { 61 | return state; 62 | } 63 | 64 | @JsonProperty("latitude") 65 | public double getLatitude() { 66 | return this.latitude; 67 | } 68 | 69 | @JsonProperty("longitude") 70 | public double getLongitude() { 71 | return this.longitude; 72 | } 73 | 74 | @JsonProperty("precision") 75 | public String getPrecision() { 76 | return this.precision; 77 | } 78 | 79 | @JsonProperty("alternate_counties") 80 | public AlternateCounty[] getAlternateCounties() { 81 | return alternateCounties; 82 | } 83 | 84 | @JsonProperty("alternate_county") 85 | public AlternateCounty getAlternateCounty(int index) { 86 | return alternateCounties[index]; 87 | } 88 | 89 | //endregion 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/examples/UsZipCodeSingleLookupExample.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | import com.smartystreets.api.SharedCredentials; 4 | import com.smartystreets.api.exceptions.SmartyException; 5 | import com.smartystreets.api.us_zipcode.*; 6 | import com.smartystreets.api.ClientBuilder; 7 | 8 | import java.io.IOException; 9 | 10 | public class UsZipCodeSingleLookupExample { 11 | public static void main(String[] args) { 12 | // We recommend storing your authentication credentials in environment variables. 13 | // for server-to-server requests, use this code: 14 | //StaticCredentials credentials = new StaticCredentials(System.getenv("SMARTY_AUTH_ID"), System.getenv("SMARTY_AUTH_TOKEN")); 15 | 16 | // for client-side requests (browser/mobile), use this code: 17 | SharedCredentials credentials = new SharedCredentials(System.getenv("SMARTY_AUTH_WEB"), System.getenv("SMARTY_AUTH_REFERER")); 18 | 19 | Client client = new ClientBuilder(credentials).buildUsZipCodeApiClient(); 20 | 21 | // Documentation for input fields can be found at: 22 | // https://smartystreets.com/docs/us-zipcode-api#input-fields 23 | 24 | Lookup lookup = new Lookup(); 25 | lookup.setInputId("dfc33cb6-829e-4fea-aa1b-b6d6580f0817"); // Optional ID from your system 26 | lookup.setCity("Mountain View"); 27 | lookup.setState("California"); 28 | lookup.setZipCode("94043"); 29 | 30 | try { 31 | client.send(lookup); 32 | } 33 | catch (SmartyException | IOException | InterruptedException ex) { 34 | System.out.println(ex.getMessage()); 35 | ex.printStackTrace(); 36 | } 37 | 38 | Result result = lookup.getResult(); 39 | ZipCode[] zipCodes = result.getZipCodes(); 40 | City[] cities = result.getCities(); 41 | 42 | System.out.println("Input ID: " + result.getInputId()); 43 | 44 | for (City city : cities) { 45 | System.out.println("\nCity: " + city.getCity()); 46 | System.out.println("State: " + city.getState()); 47 | System.out.println("Mailable City: " + city.getMailableCity()); 48 | } 49 | 50 | for (ZipCode zip : zipCodes) { 51 | System.out.println("\nZIP Code: " + zip.getZipCode()); 52 | System.out.println("Latitude: " + zip.getLatitude()); 53 | System.out.println("Longitude: " + zip.getLongitude()); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_zipcode/Batch.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_zipcode; 2 | 3 | import com.smartystreets.api.exceptions.BatchFullException; 4 | 5 | import java.util.Iterator; 6 | import java.util.LinkedHashMap; 7 | import java.util.Map; 8 | import java.util.Vector; 9 | 10 | /** 11 | * This class contains a collection of up to 100 lookups to be sent to the SmartyStreets US ZIP Code API
12 | * all at once. This is more efficient than sending them one at a time. 13 | */ 14 | public class Batch { 15 | public static final int MAX_BATCH_SIZE = 100; 16 | private Map namedLookups; 17 | private Vector allLookups; 18 | 19 | public Batch() { 20 | this.namedLookups = new LinkedHashMap<>(); 21 | this.allLookups = new Vector<>(); 22 | } 23 | 24 | public void add(Lookup lookup) throws BatchFullException { 25 | if (this.isFull()) 26 | throw new BatchFullException("Batch size cannot exceed " + MAX_BATCH_SIZE); 27 | 28 | String key = lookup.getInputId(); 29 | 30 | if (key != null) 31 | this.namedLookups.put(key, lookup); 32 | 33 | this.allLookups.add(lookup); 34 | } 35 | 36 | /** 37 | * Clears the lookups stored in the batch so it can be used again.
38 | * This helps avoid the overhead of building a new Batch object for each group of lookups. 39 | */ 40 | public void clear() { 41 | this.namedLookups.clear(); 42 | this.allLookups.clear(); 43 | } 44 | 45 | //region [ Helpers ] 46 | 47 | /** 48 | * @return The number of lookups currently in this batch. 49 | */ 50 | public int size() { 51 | return this.allLookups.size(); 52 | } 53 | 54 | public boolean isFull() { 55 | return (this.size() >= MAX_BATCH_SIZE); 56 | } 57 | 58 | public Iterator iterator() { 59 | return this.allLookups.iterator(); 60 | } 61 | 62 | //endregion 63 | 64 | //region [ Getters ] 65 | 66 | public Map getNamedLookups() { 67 | return this.namedLookups; 68 | } 69 | 70 | public Vector getAllLookups() { 71 | return this.allLookups; 72 | } 73 | 74 | public Lookup get(String inputId) { 75 | return this.namedLookups.get(inputId); 76 | } 77 | 78 | public Lookup get(int inputIndex) { 79 | return this.allLookups.get(inputIndex); 80 | } 81 | 82 | //endregion 83 | } 84 | -------------------------------------------------------------------------------- /src/test/java/com/smartystreets/api/us_zipcode/BatchTest.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_zipcode; 2 | 3 | import com.smartystreets.api.exceptions.BatchFullException; 4 | import org.junit.Test; 5 | 6 | import static org.junit.Assert.assertEquals; 7 | import static org.junit.Assert.assertNotNull; 8 | 9 | public class BatchTest { 10 | @Test 11 | public void testGetsLookupsByInputId() throws Exception { 12 | Batch batch = new Batch(); 13 | Lookup lookup = new Lookup().setInputId("hasInputId"); 14 | 15 | batch.add(lookup); 16 | 17 | assertNotNull(batch.get("hasInputId")); 18 | } 19 | 20 | @Test 21 | public void testGetsLookupsByIndex() throws Exception { 22 | Batch batch = new Batch(); 23 | Lookup lookup = new Lookup(); 24 | lookup.setCity("Provo"); 25 | 26 | batch.add(lookup); 27 | 28 | // assertNull(batch.get(1)); 29 | assertEquals("Provo", batch.get(0).getCity()); 30 | } 31 | 32 | @Test 33 | public void testReturnsCorrectSize() throws Exception { 34 | Batch batch = new Batch(); 35 | 36 | Lookup lookup = new Lookup().setInputId("inputId"); 37 | Lookup lookup1 = new Lookup(); 38 | Lookup lookup2 = new Lookup(); 39 | 40 | batch.add(lookup); 41 | batch.add(lookup1); 42 | batch.add(lookup2); 43 | 44 | assertEquals(3, batch.size()); 45 | } 46 | 47 | @Test 48 | public void testAddingALookupWhenBatchIsFullThrowsException() { 49 | Batch batch = new Batch(); 50 | Lookup lookup = new Lookup(); 51 | 52 | String exMessage = ""; 53 | try { 54 | for (int i = 0; i < Batch.MAX_BATCH_SIZE + 1; i++) { 55 | batch.add(lookup); 56 | } 57 | } catch (BatchFullException ex) { 58 | exMessage = ex.getMessage(); 59 | } finally { 60 | assertEquals(batch.MAX_BATCH_SIZE, batch.size()); 61 | assertEquals("Batch size cannot exceed " + batch.MAX_BATCH_SIZE, exMessage); 62 | } 63 | } 64 | 65 | @Test 66 | public void testClearMethodClearsBothLookupCollections() throws Exception { 67 | Batch batch = new Batch(); 68 | Lookup lookup = new Lookup(); 69 | batch.add(lookup); 70 | batch.add(lookup); 71 | 72 | batch.clear(); 73 | 74 | assertEquals(0, batch.getAllLookups().size()); 75 | assertEquals(0, batch.getNamedLookups().size()); 76 | } 77 | } -------------------------------------------------------------------------------- /src/main/java/examples/UsReverseGeoExample.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | import com.smartystreets.api.ClientBuilder; 4 | import com.smartystreets.api.SharedCredentials; 5 | import com.smartystreets.api.exceptions.SmartyException; 6 | import com.smartystreets.api.us_reverse_geo.*; 7 | 8 | import java.io.IOException; 9 | 10 | public class UsReverseGeoExample { 11 | public static void main(String[] args) { 12 | // We recommend storing your authentication credentials in environment variables. 13 | // for server-to-server requests, use this code: 14 | //StaticCredentials credentials = new StaticCredentials(System.getenv("SMARTY_AUTH_ID"), System.getenv("SMARTY_AUTH_TOKEN")); 15 | 16 | // for client-side requests (browser/mobile), use this code: 17 | SharedCredentials credentials = new SharedCredentials(System.getenv("SMARTY_AUTH_WEB"), System.getenv("SMARTY_AUTH_REFERER")); 18 | 19 | Client client = new ClientBuilder(credentials) 20 | // .withProxy(Proxy.Type.HTTP, "localhost", 8080) // Uncomment this line to try it with a proxy 21 | .buildUsReverseGeoClient(); 22 | 23 | Lookup lookup = new Lookup(40.27644, -111.65747); 24 | 25 | try { 26 | client.send(lookup); 27 | } catch (SmartyException | IOException | InterruptedException ex) { 28 | System.out.println(ex.getMessage()); 29 | ex.printStackTrace(); 30 | } 31 | 32 | Result[] results = lookup.getResponse().getResults(); 33 | 34 | System.out.printf("Results for input: (%f, %f)\n\n", lookup.getLatitude(), lookup.getLongitude()); 35 | for (Result result : results) { 36 | Coordinate coordinate = result.getCoordinate(); 37 | Address address = result.getAddress(); 38 | System.out.println("Latitude: " + coordinate.getLatitude()); 39 | System.out.println("Longitude: " + coordinate.getLongitude()); 40 | System.out.println("Distance: " + result.getDistance().toString()); 41 | System.out.println("Street: " + address.getStreet()); 42 | System.out.println("City: " + address.getCity()); 43 | System.out.println("State Abbreviation: " + address.getStateAbbreviation()); 44 | System.out.println("ZIP Code: " + address.getZipCode()); 45 | System.out.println("License: " + coordinate.getLicense()); 46 | System.out.println("Smartykey: " + address.getSmartykey()); 47 | System.out.println(); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/StatusCodeSender.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api; 2 | 3 | import com.smartystreets.api.exceptions.*; 4 | 5 | import java.io.IOException; 6 | 7 | public class StatusCodeSender implements Sender { 8 | private final Sender inner; 9 | 10 | public StatusCodeSender(Sender inner) { 11 | this.inner = inner; 12 | } 13 | 14 | public Response send(Request request) throws SmartyException, IOException, InterruptedException { 15 | Response response = this.inner.send(request); 16 | 17 | switch (response.getStatusCode()) { 18 | case 200: 19 | case 429: // Too Many Requests - Rate Limit reached. We handle this with the response, not a throwable 20 | return response; 21 | case 401: 22 | throw new BadCredentialsException("Unauthorized: The credentials were provided incorrectly or did not match any existing, active credentials."); 23 | case 304: 24 | throw new NotModifiedException("Record has not been modified since the last request."); 25 | case 402: 26 | throw new PaymentRequiredException("Payment Required: There is no active subscription for the account associated with the credentials submitted with the request."); 27 | case 403: 28 | throw new ForbiddenException("Forbidden: The request contained valid data and was understood by the server, but the server is refusing action."); 29 | case 413: 30 | throw new RequestEntityTooLargeException("Request Entity Too Large: The request body has exceeded the maximum size."); 31 | case 400: 32 | throw new BadRequestException("Bad Request (Malformed Payload): A GET request lacked a street field or the request body of a POST request contained malformed JSON."); 33 | case 422: 34 | throw new UnprocessableEntityException("GET request lacked required fields."); 35 | case 500: 36 | throw new InternalServerErrorException("Internal Server Error."); 37 | case 503: 38 | throw new ServiceUnavailableException("Service Unavailable. Try again later."); 39 | case 504: 40 | throw new GatewayTimeoutException("The upstream data provider did not respond in a timely fashion and the request failed. A serious, yet rare occurrence indeed."); 41 | default: 42 | throw new SmartyException("Unexpected response code: " + response.getStatusCode()); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_street/Analysis.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_street; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * @see "https://smartystreets.com/docs/cloud/us-street-api#analysis" 9 | */ 10 | public class Analysis implements Serializable { 11 | //region [ Fields ] 12 | 13 | private String dpvMatchCode; 14 | private String dpvFootnotes; 15 | private String cmra; 16 | private String vacant; 17 | private String no_stat; 18 | private String active; 19 | private boolean ewsMatch; 20 | private String footnotes; 21 | private String lacsLinkCode; 22 | private String lacsLinkIndicator; 23 | private boolean suiteLinkMatch; 24 | private String enhancedMatch; 25 | private ComponentAnalysis components; 26 | 27 | //endregion 28 | 29 | //region [ Getters ] 30 | 31 | @JsonProperty("dpv_match_code") 32 | public String getDpvMatchCode() { 33 | return this.dpvMatchCode; 34 | } 35 | 36 | @JsonProperty("dpv_footnotes") 37 | public String getDpvFootnotes() { 38 | return this.dpvFootnotes; 39 | } 40 | 41 | @JsonProperty("dpv_cmra") 42 | public String getCmra() { 43 | return this.cmra; 44 | } 45 | 46 | @JsonProperty("dpv_vacant") 47 | public String getVacant() { 48 | return this.vacant; 49 | } 50 | 51 | @JsonProperty("dpv_no_stat") 52 | public String getNo_stat() { return this.no_stat; } 53 | 54 | @JsonProperty("active") 55 | public String getActive() { 56 | return this.active; 57 | } 58 | 59 | @JsonProperty("enhanced_match") 60 | public String getEnhancedMatch() { 61 | return this.enhancedMatch; 62 | } 63 | 64 | //@deprecated moved to metadata field 65 | @Deprecated 66 | @JsonProperty("ews_match") 67 | public boolean isEwsMatch() { 68 | return false; 69 | } 70 | 71 | @JsonProperty("footnotes") 72 | public String getFootnotes() { 73 | return this.footnotes; 74 | } 75 | 76 | @JsonProperty("lacslink_code") 77 | public String getLacsLinkCode() { 78 | return this.lacsLinkCode; 79 | } 80 | 81 | @JsonProperty("lacslink_indicator") 82 | public String getLacsLinkIndicator() { 83 | return this.lacsLinkIndicator; 84 | } 85 | 86 | @JsonProperty("suitelink_match") 87 | public boolean isSuiteLinkMatch() { 88 | return this.suiteLinkMatch; 89 | } 90 | 91 | @JsonProperty("components") 92 | public ComponentAnalysis getComponents() { 93 | return this.components; 94 | } 95 | 96 | //endregion 97 | } 98 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_street/Batch.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_street; 2 | 3 | import com.smartystreets.api.exceptions.BatchFullException; 4 | 5 | import java.util.Iterator; 6 | import java.util.LinkedHashMap; 7 | import java.util.Map; 8 | import java.util.Vector; 9 | 10 | /** 11 | * This class contains a collection of lookups to be sent to the
12 | * SmartyStreets US Street API all at once. This is more efficient than sending them
13 | * one at a time. Maximum batch size is 100. 14 | */ 15 | public class Batch { 16 | public static final int MAX_BATCH_SIZE = 100; 17 | private Map namedLookups; 18 | private Vector allLookups; 19 | 20 | public Batch() { 21 | this.namedLookups = new LinkedHashMap<>(); 22 | this.allLookups = new Vector<>(); 23 | } 24 | 25 | /** 26 | * Adds a lookup to the batch, as long as there are less than 100 lookup in the batch already. 27 | * @param newAddress 28 | * @throws BatchFullException Batch size cannot exceed 100 29 | */ 30 | public void add(Lookup newAddress) throws BatchFullException { 31 | if (this.isFull()) 32 | throw new BatchFullException("Batch size cannot exceed " + MAX_BATCH_SIZE); 33 | 34 | this.allLookups.add(newAddress); 35 | 36 | String key = newAddress.getInputId(); 37 | if (key == null) 38 | return; 39 | 40 | this.namedLookups.put(key, newAddress); 41 | 42 | } 43 | 44 | /** 45 | * Clears the lookups stored in the batch so it can be used again.
46 | * This helps avoid the overhead of building a new Batch object for each group of lookups. 47 | */ 48 | public void clear() { 49 | this.namedLookups.clear(); 50 | this.allLookups.clear(); 51 | } 52 | 53 | //region [ Helpers ] 54 | 55 | /** 56 | * @return The number of lookups currently in this batch. 57 | */ 58 | public int size() { 59 | return this.allLookups.size(); 60 | } 61 | 62 | public boolean isFull() { 63 | return (this.size() >= MAX_BATCH_SIZE); 64 | } 65 | 66 | public Iterator iterator() { 67 | return this.allLookups.iterator(); 68 | } 69 | 70 | //endregion 71 | 72 | //region [ Getters ] 73 | 74 | public Map getNamedLookups() { 75 | return this.namedLookups; 76 | } 77 | 78 | public Lookup get(String inputId) { 79 | return this.namedLookups.get(inputId); 80 | } 81 | 82 | public Lookup get(int inputIndex) { 83 | return this.allLookups.get(inputIndex); 84 | } 85 | 86 | public Vector getAllLookups() { 87 | return this.allLookups; 88 | } 89 | 90 | //endregion 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/international_postal_code/Client.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.international_postal_code; 2 | 3 | import com.smartystreets.api.Request; 4 | import com.smartystreets.api.Response; 5 | import com.smartystreets.api.Sender; 6 | import com.smartystreets.api.Serializer; 7 | import com.smartystreets.api.exceptions.SmartyException; 8 | import com.smartystreets.api.exceptions.UnprocessableEntityException; 9 | import java.io.IOException; 10 | 11 | /** 12 | * Client for the International Postal Code API. Sends Lookup objects and populates results. 13 | * @see "https://smartystreets.com/docs/cloud/international-postal-code-api" 14 | */ 15 | public class Client { 16 | private final Sender sender; 17 | private final Serializer serializer; 18 | 19 | public Client(Sender sender, Serializer serializer) { 20 | this.sender = sender; 21 | this.serializer = serializer; 22 | } 23 | 24 | public Candidate[] send(Lookup lookup) throws IOException, SmartyException, InterruptedException { 25 | this.ensureEnoughInfo(lookup); 26 | Request request = this.buildRequest(lookup); 27 | Response response = this.sender.send(request); 28 | Candidate[] candidates = this.serializer.deserialize(response.getPayload(), Candidate[].class); 29 | lookup.setResult(candidates); 30 | return candidates; 31 | } 32 | 33 | private Request buildRequest(Lookup lookup) { 34 | Request request = new Request(); 35 | request.putParameter("input_id", lookup.getInputId()); 36 | request.putParameter("country", lookup.getCountry()); 37 | request.putParameter("locality", lookup.getLocality()); 38 | //request.putParameter("language", lookup.getLanguage()); // future 39 | //request.putParameter("features", lookup.getFeatures()); // future 40 | request.putParameter("administrative_area", lookup.getAdministrativeArea()); 41 | request.putParameter("postal_code", lookup.getPostalCode()); 42 | return request; 43 | } 44 | 45 | private void ensureEnoughInfo(Lookup lookup) throws SmartyException { 46 | if (lookup == null) 47 | throw new UnprocessableEntityException("Lookup cannot be null."); 48 | if (isMissing(lookup.getCountry())) 49 | throw new UnprocessableEntityException("Country field is required."); 50 | if (!isMissing(lookup.getLocality()) || !isMissing(lookup.getAdministrativeArea()) || !isMissing(lookup.getPostalCode())) 51 | return; 52 | throw new UnprocessableEntityException("At least one of locality, administrative_area, or postal_code must be set."); 53 | } 54 | 55 | private boolean isMissing(String value) { 56 | return value == null || value.isEmpty(); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_enrichment/result_types/secondary/Alias.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_enrichment.result_types.secondary; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | public class Alias { 6 | 7 | private String smartyKey; 8 | 9 | private String primaryNumber; 10 | 11 | private String streetPredirection; 12 | 13 | private String streetName; 14 | 15 | private String streetSuffix; 16 | 17 | private String streetPostdirection; 18 | 19 | private String cityName; 20 | 21 | private String stateAbbreviation; 22 | 23 | private String zipcode; 24 | 25 | private String plus4Code; 26 | 27 | @JsonProperty("smarty_key") 28 | public String getSmartyKey() { 29 | return smartyKey; 30 | } 31 | 32 | @JsonProperty("primary_number") 33 | public String getPrimaryNumber() { 34 | return primaryNumber; 35 | } 36 | 37 | @JsonProperty("street_predirection") 38 | public String getStreetPredirection() { 39 | return streetPredirection; 40 | } 41 | 42 | @JsonProperty("street_name") 43 | public String getStreetName() { 44 | return streetName; 45 | } 46 | 47 | @JsonProperty("street_suffix") 48 | public String getStreetSuffix() { 49 | return streetSuffix; 50 | } 51 | 52 | @JsonProperty("street_postdirection") 53 | public String getStreetPostdirection() { 54 | return streetPostdirection; 55 | } 56 | 57 | @JsonProperty("city_name") 58 | public String getCityName() { 59 | return cityName; 60 | } 61 | 62 | @JsonProperty("state_abbreviation") 63 | public String getStateAbbreviation() { 64 | return stateAbbreviation; 65 | } 66 | 67 | @JsonProperty("zipcode") 68 | public String getZipcode() { 69 | return zipcode; 70 | } 71 | 72 | @JsonProperty("plus4_code") 73 | public String getPlus4Code() { 74 | return plus4Code; 75 | } 76 | 77 | @Override 78 | public String toString() { 79 | return "Alias{" + 80 | "smarty_key='" + getSmartyKey() + '\'' + 81 | ", primary_number='" + getPrimaryNumber() + '\'' + 82 | ", street_predirection='" + getStreetPredirection() + '\'' + 83 | ", street_name='" + getStreetName() + '\'' + 84 | ", street_suffix='" + getStreetSuffix() + '\'' + 85 | ", street_postdirection='" + getStreetPostdirection() + '\'' + 86 | ", city_name='" + getCityName() + '\'' + 87 | ", state_abbreviation='" + getStateAbbreviation() + '\'' + 88 | ", zipcode='" + getZipcode() + '\'' + 89 | ", plus4_code='" + getPlus4Code() + '\'' + 90 | '}'; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/examples/InternationalAutocompleteExample.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | import com.smartystreets.api.ClientBuilder; 4 | import com.smartystreets.api.StaticCredentials; 5 | import com.smartystreets.api.exceptions.SmartyException; 6 | import com.smartystreets.api.international_autocomplete.Client; 7 | import com.smartystreets.api.international_autocomplete.Lookup; 8 | import com.smartystreets.api.international_autocomplete.Candidate; 9 | 10 | import java.io.IOException; 11 | 12 | public class InternationalAutocompleteExample { 13 | public static void main(String[] args) { 14 | // We recommend storing your authentication credentials in environment variables. 15 | // for server-to-server requests, use this code: 16 | StaticCredentials credentials = new StaticCredentials(System.getenv("SMARTY_AUTH_ID"), System.getenv("SMARTY_AUTH_TOKEN")); 17 | 18 | // for client-side requests (browser/mobile), use this code: 19 | //SharedCredentials credentials = new SharedCredentials(System.getenv("SMARTY_AUTH_WEB"), System.getenv("SMARTY_AUTH_REFERER")); 20 | 21 | Client client = new ClientBuilder(credentials).buildInternationalAutcompleteApiClient(); 22 | Lookup lookup = new Lookup("Louis"); 23 | 24 | // Documentation for input fields can be found at: 25 | // https://smartystreets.com/docs/cloud/international-address-autocomplete-api#pro-http-request-url 26 | 27 | 28 | lookup.setCountry("FRA"); 29 | lookup.setLocality("Paris"); 30 | 31 | try { 32 | client.send(lookup); 33 | 34 | System.out.println("*** Result ***"); 35 | System.out.println(); 36 | printResult(lookup); 37 | } catch (SmartyException | IOException | InterruptedException ex) { 38 | System.out.println(ex.getMessage()); 39 | ex.printStackTrace(); 40 | } 41 | } 42 | 43 | private static void printResult(Lookup lookup) { 44 | for (Candidate candidate : lookup.getResult()) { 45 | if(candidate.getAddressText() != null) { 46 | System.out.println("Entries: " + candidate.getEntries()); 47 | System.out.println("Address Text: " + candidate.getAddressText()); 48 | System.out.println("Address ID: " + candidate.getAddressID() + "\n"); 49 | } else { 50 | System.out.println("Street: " + candidate.getStreet()); 51 | System.out.println("Locality: " + candidate.getLocality()); 52 | System.out.println("Administrative Area: " + candidate.getAdministrativeArea()); 53 | System.out.println("Postal Code: " + candidate.getPostalCode()); 54 | System.out.println("Country: " + candidate.getCountryISO3()); 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/examples/UsStreetComponentAnalysisExample.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | import com.smartystreets.api.StaticCredentials; 4 | import com.smartystreets.api.exceptions.SmartyException; 5 | import com.smartystreets.api.us_street.*; 6 | import com.fasterxml.jackson.annotation.JsonInclude; 7 | import com.fasterxml.jackson.core.JsonProcessingException; 8 | import com.fasterxml.jackson.databind.ObjectMapper; 9 | import com.smartystreets.api.ClientBuilder; 10 | 11 | import java.io.IOException; 12 | import java.util.List; 13 | 14 | public class UsStreetComponentAnalysisExample { 15 | public static void main(String[] args) { 16 | // We recommend storing your authentication credentials in environment variables. 17 | // for server-to-server requests, use this code: 18 | StaticCredentials credentials = new StaticCredentials(System.getenv("SMARTY_AUTH_ID"), System.getenv("SMARTY_AUTH_TOKEN")); 19 | 20 | // for client-side requests (browser/mobile), use this code: 21 | // SharedCredentials credentials = new SharedCredentials(System.getenv("SMARTY_AUTH_WEB"), System.getenv("SMARTY_AUTH_REFERER")); 22 | 23 | Client client = new ClientBuilder(credentials) 24 | .withFeatureComponentAnalysis() // To add component analysis feature you need to specify when you create the client. 25 | .buildUsStreetApiClient(); 26 | 27 | Lookup lookup = new Lookup(); 28 | lookup.setStreet("1 Rosedale"); 29 | lookup.setSecondary("APT 2"); 30 | lookup.setCity("Baltimore"); 31 | lookup.setState("MD"); 32 | lookup.setZipCode("21229"); 33 | lookup.setMatch(MatchType.ENHANCED); // Enhanced matching is required to return component analysis results. 34 | 35 | try { 36 | client.send(lookup); 37 | } 38 | catch (SmartyException | IOException | InterruptedException ex) { 39 | System.out.println(ex.getMessage()); 40 | ex.printStackTrace(); 41 | } 42 | 43 | List results = lookup.getResult(); 44 | 45 | if (results.isEmpty()) { 46 | return; 47 | } 48 | 49 | Candidate firstCandidate = results.get(0); 50 | 51 | // Here is an example of how to access component analysis 52 | ComponentAnalysis componentAnalysis = firstCandidate.getAnalysis().getComponents(); 53 | 54 | ObjectMapper mapper = new ObjectMapper() 55 | .setSerializationInclusion(JsonInclude.Include.NON_NULL); 56 | 57 | try { 58 | System.out.println("Component Analysis Results:\n" + mapper.writeValueAsString(componentAnalysis)); 59 | } 60 | catch ( JsonProcessingException ex ) { 61 | System.out.println(ex.getMessage()); 62 | ex.printStackTrace(); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_zipcode/Client.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_zipcode; 2 | 3 | import com.smartystreets.api.Request; 4 | import com.smartystreets.api.Response; 5 | import com.smartystreets.api.Sender; 6 | import com.smartystreets.api.Serializer; 7 | import com.smartystreets.api.exceptions.SmartyException; 8 | 9 | import java.io.IOException; 10 | 11 | /** 12 | * This client sends lookups to the SmartyStreets US ZIP Code API,
13 | * and attaches the results to the appropriate Lookup objects. 14 | */ 15 | public class Client { 16 | private final Sender sender; 17 | private final Serializer serializer; 18 | 19 | public Client(Sender sender, Serializer serializer) { 20 | this.sender = sender; 21 | this.serializer = serializer; 22 | } 23 | 24 | public void send(Lookup lookup) throws SmartyException, IOException, InterruptedException { 25 | Batch batch = new Batch(); 26 | batch.add(lookup); 27 | send(batch); 28 | } 29 | 30 | /** 31 | * Sends a batch of up to 100 lookups for validation. 32 | * @param batch Batch must contain between 1 and 100 Lookup objects 33 | * @throws SmartyException 34 | * @throws IOException 35 | */ 36 | public void send(Batch batch) throws SmartyException, IOException, InterruptedException { 37 | Request request = new Request(); 38 | 39 | if (batch.size() == 0) 40 | throw new SmartyException("Batch must contain between 1 and 100 lookups"); 41 | 42 | if (batch.size() == 1) 43 | this.populateQueryString(batch.get(0), request); 44 | else 45 | request.setPayload(this.serializer.serialize(batch.getAllLookups())); 46 | 47 | Response response = this.sender.send(request); 48 | 49 | Result[] results = this.serializer.deserialize(response.getPayload(), Result[].class); 50 | if (results == null) 51 | results = new Result[0]; 52 | this.assignResultsToLookups(batch, results); 53 | } 54 | 55 | private void populateQueryString(Lookup lookup, Request request) { 56 | request.putParameter("input_id", lookup.getInputId()); 57 | request.putParameter("city", lookup.getCity()); 58 | request.putParameter("state", lookup.getState()); 59 | request.putParameter("zipcode", lookup.getZipCode()); 60 | //This is a temporary flag meant to fix an intermittent data issue 61 | //Unless explicitly instructed by the Smarty Tech Support team, DO NOT use this parameter 62 | request.putParameter("compatibility", lookup.getCompatibility()); 63 | } 64 | 65 | 66 | private void assignResultsToLookups(Batch batch, Result[] results) { 67 | for (int i = 0; i < results.length; i++) { 68 | batch.get(i).setResult(results[i]); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/examples/UsAutocompleteProExample.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | import com.smartystreets.api.SharedCredentials; 4 | import com.smartystreets.api.StaticCredentials; 5 | import com.smartystreets.api.exceptions.SmartyException; 6 | import com.smartystreets.api.us_autocomplete_pro.*; 7 | import com.smartystreets.api.ClientBuilder; 8 | 9 | import java.io.IOException; 10 | 11 | import java.util.ArrayList; 12 | 13 | public class UsAutocompleteProExample { 14 | public static void main(String[] args) { 15 | // We recommend storing your authentication credentials in environment variables. 16 | // for server-to-server requests, use this code: 17 | StaticCredentials credentials = new StaticCredentials(System.getenv("SMARTY_AUTH_ID"), System.getenv("SMARTY_AUTH_TOKEN")); 18 | 19 | // for client-side requests (browser/mobile), use this code: 20 | // SharedCredentials credentials = new SharedCredentials(System.getenv("SMARTY_AUTH_WEB"), System.getenv("SMARTY_AUTH_REFERER")); 21 | 22 | Client client = new ClientBuilder(credentials).buildUsAutocompleteProApiClient(); 23 | Lookup lookup = new Lookup("1042 W Center"); 24 | lookup.setMaxResults(5); 25 | 26 | try { 27 | client.send(lookup); 28 | 29 | System.out.println("*** Result with no filter ***"); 30 | System.out.println(); 31 | printResult(lookup); 32 | 33 | // Documentation for input fields can be found at: 34 | // https://smartystreets.com/docs/cloud/us-autocomplete-pro-api#pro-http-request-url 35 | 36 | lookup.addCityFilter("Denver,Aurora,CO"); 37 | lookup.addCityFilter("Orem,UT"); 38 | lookup.addPreferState("CO"); 39 | lookup.setPreferRatio(33); 40 | lookup.setSource("all"); 41 | 42 | client.send(lookup); // The client will also return the suggestions directly 43 | 44 | System.out.println(); 45 | System.out.println("*** Result with some filters ***"); 46 | printResult(lookup); 47 | } catch (SmartyException | IOException | InterruptedException ex) { 48 | System.out.println(ex.getMessage()); 49 | ex.printStackTrace(); 50 | } 51 | } 52 | 53 | private static void printResult(Lookup lookup) { 54 | for (Suggestion suggestion : lookup.getResult()) { 55 | System.out.print(suggestion.getStreetLine()); 56 | System.out.print(" "); 57 | System.out.print(suggestion.getSecondary()); 58 | System.out.print(" "); 59 | System.out.print(suggestion.getCity()); 60 | System.out.print(", "); 61 | System.out.print(suggestion.getState()); 62 | System.out.print(", "); 63 | System.out.println(suggestion.getZipcode()); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/test/java/com/smartystreets/api/SmartySerializerTest.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api; 2 | 3 | import com.smartystreets.api.us_zipcode.Lookup; 4 | import com.smartystreets.api.us_zipcode.Result; 5 | import org.junit.Test; 6 | 7 | import java.util.ArrayList; 8 | 9 | import static org.junit.Assert.*; 10 | 11 | public class SmartySerializerTest { 12 | private static final String expectedJsonInput = "[{\"city\":\"Washington\",\"state\":\"District of Columbia\",\"zipcode\":\"20500\"},{\"city\":\"Provo\",\"state\":\"Utah\"},{\"zipcode\":\"54321\"}]"; 13 | private static final String expectedJsonOutput = "[{\"input_index\":0,\"city_states\":[{\"city\":\"Washington\",\"state_abbreviation\":\"DC\",\"state\":\"District of Columbia\",\"mailable_city\":true}],\"zipcodes\":[{\"zipcode\":\"20500\",\"zipcode_type\":\"S\",\"default_city\":\"Washington\",\"county_fips\":\"11001\",\"county_name\":\"District of Columbia\",\"latitude\":38.89769,\"longitude\":-77.03869}]},{\"input_index\":1,\"input_id\":\"test id\",\"city_states\":[{\"city\":\"Provo\",\"state_abbreviation\":\"UT\",\"state\":\"Utah\",\"mailable_city\":true}],\"zipcodes\":[{\"zipcode\":\"84606\",\"zipcode_type\":\"S\",\"county_fips\":\"11501\",\"county_name\":\"Utah\",\"latitude\":38.89769,\"longitude\":-77.03869}]},{\"input_index\":2,\"status\":\"invalid_zipcode\",\"reason\":\"Invalid ZIP Code.\"}]"; 14 | private final SmartySerializer smartySerializer = new SmartySerializer(); 15 | 16 | @Test 17 | public void testSerialize() throws Exception { 18 | ArrayList lookups = new ArrayList<>(); 19 | byte[] lookupBytes; 20 | lookups.add(new Lookup("Washington", "District of Columbia", "20500")); 21 | lookups.add(new Lookup("Provo", "Utah")); 22 | lookups.add(new Lookup("54321")); 23 | 24 | lookupBytes = smartySerializer.serialize(lookups); 25 | assertEquals(expectedJsonInput, new String(lookupBytes)); 26 | } 27 | 28 | @Test 29 | public void testDeserialize() throws Exception { 30 | Result[] results = smartySerializer.deserialize(expectedJsonOutput.getBytes(), Result[].class); 31 | 32 | assertNotNull(results[0]); 33 | assertEquals(0, results[0].getInputIndex()); 34 | assertNotNull(results[0].getCity(0)); 35 | assertEquals("Washington", results[0].getCity(0).getCity()); 36 | assertEquals("20500", results[0].getZipCode(0).getZipCode()); 37 | 38 | assertNotNull(results[1]); 39 | assertNull(results[1].getStatus()); 40 | assertEquals("Utah", results[1].getCity(0).getState()); 41 | assertEquals(38.89769, results[1].getZipCode(0).getLatitude(), .00001); 42 | 43 | assertNotNull(results[2]); 44 | assertNull(results[2].getCities()); 45 | assertEquals("invalid_zipcode", results[2].getStatus()); 46 | assertEquals("Invalid ZIP Code.", results[2].getReason()); 47 | } 48 | } -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_street/Candidate.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_street; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * A candidate is a possible match for an address that was submitted.
9 | * A lookup can have multiple candidates if the address was ambiguous, and
10 | * the maxCandidates field is set higher than 1. 11 | * 12 | * @see "https://smartystreets.com/docs/cloud/us-street-api#root" 13 | */ 14 | public class Candidate implements Serializable { 15 | //region [ Fields ] 16 | 17 | private String inputId; 18 | private int inputIndex; 19 | private int candidateIndex; 20 | private String addressee; 21 | private String deliveryLine1; 22 | private String deliveryLine2; 23 | private String lastLine; 24 | private String deliveryPointBarcode; 25 | private String smartyKey; 26 | private Components components; 27 | private Metadata metadata; 28 | private Analysis analysis; 29 | 30 | //endregion 31 | 32 | 33 | public Candidate() { 34 | } 35 | 36 | public Candidate(int inputIndex) { 37 | this.inputIndex = inputIndex; 38 | } 39 | 40 | 41 | //region [ Getters ] 42 | 43 | @JsonProperty("components") 44 | public Components getComponents() { 45 | return this.components; 46 | } 47 | 48 | @JsonProperty("metadata") 49 | public Metadata getMetadata() { 50 | return this.metadata; 51 | } 52 | 53 | @JsonProperty("analysis") 54 | public Analysis getAnalysis() { 55 | return this.analysis; 56 | } 57 | 58 | @JsonProperty("input_id") 59 | public String getInputId() { return this.inputId; } 60 | 61 | @JsonProperty("input_index") 62 | public int getInputIndex() { 63 | return this.inputIndex; 64 | } 65 | 66 | @JsonProperty("candidate_index") 67 | public int getCandidateIndex() { 68 | return this.candidateIndex; 69 | } 70 | 71 | @JsonProperty("addressee") 72 | public String getAddressee() { 73 | return this.addressee; 74 | } 75 | 76 | @JsonProperty("delivery_line_1") 77 | public String getDeliveryLine1() { 78 | return this.deliveryLine1; 79 | } 80 | 81 | @JsonProperty("delivery_line_2") 82 | public String getDeliveryLine2() { 83 | return this.deliveryLine2; 84 | } 85 | 86 | @JsonProperty("last_line") 87 | public String getLastLine() { 88 | return this.lastLine; 89 | } 90 | 91 | @JsonProperty("delivery_point_barcode") 92 | public String getDeliveryPointBarcode() { 93 | return this.deliveryPointBarcode; 94 | } 95 | 96 | @JsonProperty("smarty_key") 97 | public String getSmartyKey() { 98 | return this.smartyKey; 99 | } 100 | 101 | //endregion 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/international_autocomplete/Lookup.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.international_autocomplete; 2 | 3 | /** 4 | * In addition to holding all of the input data for this lookup, this class also
5 | * will contain the result of the lookup after it comes back from the API. 6 | * 7 | * @see "https://smartystreets.com/docs/cloud/international-address-autocomplete-api#http-request-input-fields" 8 | */ 9 | public class Lookup { 10 | static final int MAX_RESULTS_DEFAULT = 5; 11 | static final int DISTANCE_DEFAULT = 5; 12 | 13 | //region [ Fields ] 14 | 15 | private Candidate[] result; 16 | private String country; 17 | private String search; 18 | private String addressID; 19 | private int maxResults; 20 | private String locality; 21 | private String postalCode; 22 | 23 | //endregion 24 | 25 | //region [ Constructors ] 26 | 27 | /** 28 | * If you use this constructor, don't forget to set the prefix. It is required. 29 | */ 30 | public Lookup() { 31 | this.maxResults = MAX_RESULTS_DEFAULT; 32 | } 33 | 34 | /** 35 | * @param search The beginning of an address 36 | */ 37 | public Lookup(String search) { 38 | this(); 39 | this.search = search; 40 | } 41 | 42 | //endregion 43 | 44 | //region [ Getters ] 45 | 46 | public Candidate[] getResult() { 47 | return this.result; 48 | } 49 | 50 | public Candidate getResult(int index) { 51 | return this.result[index]; 52 | } 53 | 54 | public String getCountry() { 55 | return this.country; 56 | } 57 | 58 | public String getSearch() { 59 | return this.search; 60 | } 61 | 62 | public String getAddressID() { 63 | return addressID; 64 | } 65 | 66 | public int getMaxResults() { 67 | return this.maxResults; 68 | } 69 | 70 | public String getLocality() { 71 | return this.locality; 72 | } 73 | 74 | public String getPostalCode() { 75 | return this.postalCode; 76 | } 77 | 78 | //endregion 79 | 80 | //region [ Setters ] 81 | public void setResult(Candidate[] result) { 82 | this.result = result; 83 | } 84 | 85 | public void setCountry(String country) { 86 | this.country = country; 87 | } 88 | 89 | public void setSearch(String search) { 90 | this.search = search; 91 | } 92 | 93 | public void setAddressID(String addressID) { 94 | this.addressID = addressID; 95 | } 96 | 97 | public void setMaxResults(int maxResults) { 98 | this.maxResults = maxResults; 99 | } 100 | 101 | public void setLocality(String locality) { 102 | this.locality = locality; 103 | } 104 | 105 | public void setPostalCode(String postalCode) { 106 | this.postalCode = postalCode; 107 | } 108 | 109 | //endregion 110 | } 111 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/RetrySender.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api; 2 | 3 | import com.smartystreets.api.exceptions.SmartyException; 4 | 5 | import java.io.IOException; 6 | 7 | public class RetrySender implements Sender { 8 | public final int MAX_BACKOFF_DURATION = 10; 9 | private long maxWaitTime; 10 | private Sender inner; 11 | private int maxRetries; 12 | private Sleeper sleeper; 13 | private Logger logger; 14 | 15 | public RetrySender(int maxRetries, Sleeper sleeper, Logger logger, Sender inner) { 16 | this.maxRetries = maxRetries; 17 | this.maxWaitTime = 0; 18 | this.sleeper = sleeper; 19 | this.logger = logger; 20 | this.inner = inner; 21 | } 22 | 23 | public RetrySender WithMaxWaitTime(long maxWaitTime) { 24 | this.maxWaitTime = maxWaitTime; 25 | return this; 26 | } 27 | 28 | public Response send(Request request) throws SmartyException, IOException, InterruptedException { 29 | int totalWaitTime = 0; 30 | for (int i = 0; i <= this.maxRetries; i++) { 31 | Response response = this.trySend(request, i); 32 | if (response instanceof TooManyRequestsResponse) { 33 | long wait = 10L; 34 | String retryAfter = ((TooManyRequestsResponse) response).getHeaders().get("Retry-After"); 35 | if (retryAfter != null && retryAfter.length() > 0) { 36 | wait = Long.parseLong(retryAfter); 37 | } 38 | if (wait < 1) { 39 | wait = 1L; 40 | } 41 | totalWaitTime += wait; 42 | if (maxWaitTime > 0 && totalWaitTime > maxWaitTime) { 43 | throw new SmartyException("In RetrySender, the wait time is longer than the maxWaitTime."); 44 | } 45 | //this.logger.log("The rate limit for requests has been exceeded. Sleeping " + wait + " seconds..."); 46 | this.sleeper.sleep(wait); 47 | i = 0; 48 | response = null; 49 | } 50 | 51 | if (response != null) { 52 | return response; 53 | } 54 | } 55 | return null; 56 | } 57 | 58 | private Response trySend(Request request, int attempt) throws SmartyException, IOException, InterruptedException { 59 | try { 60 | return this.inner.send(request); 61 | } catch (IOException ex) { 62 | if (attempt >= this.maxRetries) 63 | throw ex; 64 | } 65 | 66 | this.backoff(attempt); 67 | 68 | return null; 69 | } 70 | 71 | private void backoff(int attempt) throws InterruptedException { 72 | long backoffDuration = Math.min(attempt, MAX_BACKOFF_DURATION); 73 | 74 | this.logger.log("There was an error processing the request. Retrying in "+backoffDuration+" seconds..."); 75 | this.sleeper.sleep(backoffDuration); 76 | 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_street/ComponentAnalysis.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_street; 2 | 3 | import java.io.Serializable; 4 | 5 | import com.fasterxml.jackson.annotation.JsonProperty; 6 | 7 | public class ComponentAnalysis implements Serializable { 8 | 9 | private MatchInfo primaryNumber; 10 | 11 | private MatchInfo streetPredirection; 12 | 13 | private MatchInfo streetName; 14 | 15 | private MatchInfo streetPostdirection; 16 | 17 | private MatchInfo streetSuffix; 18 | 19 | private MatchInfo secondaryNumber; 20 | 21 | private MatchInfo secondaryDesignator; 22 | 23 | private MatchInfo extraSecondaryNumber; 24 | 25 | private MatchInfo extraSecondaryDesignator; 26 | 27 | private MatchInfo cityName; 28 | 29 | private MatchInfo stateAbbreviation; 30 | 31 | private MatchInfo zipCode; 32 | 33 | private MatchInfo plus4Code; 34 | 35 | private MatchInfo urbanization; 36 | 37 | @JsonProperty("primary_number") 38 | public MatchInfo getPrimaryNumber() { 39 | return primaryNumber; 40 | } 41 | 42 | @JsonProperty("street_predirection") 43 | public MatchInfo getStreetPredirection() { 44 | return streetPredirection; 45 | } 46 | 47 | @JsonProperty("street_name") 48 | public MatchInfo getStreetName() { 49 | return streetName; 50 | } 51 | 52 | @JsonProperty("street_postdirection") 53 | public MatchInfo getStreetPostdirection() { 54 | return streetPostdirection; 55 | } 56 | 57 | @JsonProperty("street_suffix") 58 | public MatchInfo getStreetSuffix() { 59 | return streetSuffix; 60 | } 61 | 62 | @JsonProperty("secondary_number") 63 | public MatchInfo getSecondaryNumber() { 64 | return secondaryNumber; 65 | } 66 | 67 | @JsonProperty("secondary_designator") 68 | public MatchInfo getSecondaryDesignator() { 69 | return secondaryDesignator; 70 | } 71 | 72 | @JsonProperty("extra_secondary_number") 73 | public MatchInfo getExtraSecondaryNumber() { 74 | return extraSecondaryNumber; 75 | } 76 | 77 | @JsonProperty("extra_secondary_designator") 78 | public MatchInfo getExtraSecondaryDesignator() { 79 | return extraSecondaryDesignator; 80 | } 81 | 82 | @JsonProperty("city_name") 83 | public MatchInfo getCityName() { 84 | return cityName; 85 | } 86 | 87 | @JsonProperty("state_abbreviation") 88 | public MatchInfo getStateAbbreviation() { 89 | return stateAbbreviation; 90 | } 91 | 92 | @JsonProperty("zipcode") 93 | public MatchInfo getZipCode() { 94 | return zipCode; 95 | } 96 | 97 | @JsonProperty("plus4_code") 98 | public MatchInfo getPlus4Code() { 99 | return plus4Code; 100 | } 101 | 102 | @JsonProperty("urbanization") 103 | public MatchInfo getUrbanization() { 104 | return urbanization; 105 | } 106 | 107 | 108 | } 109 | 110 | -------------------------------------------------------------------------------- /src/main/java/examples/InternationalExample.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | import com.smartystreets.api.ClientBuilder; 4 | import com.smartystreets.api.SharedCredentials; 5 | import com.smartystreets.api.exceptions.SmartyException; 6 | import com.smartystreets.api.international_street.*; 7 | 8 | import java.io.IOException; 9 | 10 | public class InternationalExample { 11 | public static void main(String[] args) { 12 | // We recommend storing your authentication credentials in environment variables. 13 | // for server-to-server requests, use this code: 14 | //StaticCredentials credentials = new StaticCredentials(System.getenv("SMARTY_AUTH_ID"), System.getenv("SMARTY_AUTH_TOKEN")); 15 | 16 | // for client-side requests (browser/mobile), use this code: 17 | SharedCredentials credentials = new SharedCredentials(System.getenv("SMARTY_AUTH_WEB"), System.getenv("SMARTY_AUTH_REFERER")); 18 | 19 | Client client = new ClientBuilder(credentials) 20 | .buildInternationalStreetApiClient(); 21 | 22 | // Documentation for input fields can be found at: 23 | // https://smartystreets.com/docs/cloud/international-street-api#http-input-fields 24 | 25 | Lookup lookup = new Lookup("Rua Padre Antonio D'Angelo 121 Casa Verde, Sao Paulo", "Brazil"); 26 | lookup.setInputId("ID-8675309"); // Optional ID from your system 27 | lookup.setOrganization("John Doe"); 28 | lookup.setAddress1("Rua Padre Antonio D'Angelo 121"); 29 | lookup.setAddress2("Casa Verde"); 30 | lookup.setLocality("Sao Paulo"); 31 | lookup.setAdministrativeArea("SP"); 32 | lookup.setCountry("Brazil"); 33 | lookup.setPostalCode("02516-050"); 34 | lookup.setGeocode(true); // Must be expressly set to get latitude and longitude. 35 | 36 | try { 37 | Candidate[] candidates = client.send(lookup); // The candidates are also stored in the lookup's 'result' field. 38 | 39 | Candidate firstCandidate = candidates[0]; 40 | System.out.println("Input ID: " + firstCandidate.getInputId()); 41 | System.out.println("Address is " + firstCandidate.getAnalysis().getVerificationStatus()); 42 | System.out.println("Address precision: " + firstCandidate.getAnalysis().getAddressPrecision() + "\n"); 43 | 44 | System.out.println("First Line: " + firstCandidate.getAddress1()); 45 | System.out.println("Second Line: " + firstCandidate.getAddress2()); 46 | System.out.println("Third Line: " + firstCandidate.getAddress3()); 47 | System.out.println("Fourth Line: " + firstCandidate.getAddress4()); 48 | System.out.println("Latitude: " + firstCandidate.getMetadata().getLatitude()); 49 | System.out.println("Longitude: " + firstCandidate.getMetadata().getLongitude()); 50 | } catch (SmartyException | IOException | InterruptedException ex) { 51 | System.out.println(ex.getMessage()); 52 | ex.printStackTrace(); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/Request.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api; 2 | 3 | import java.net.URLEncoder; 4 | import java.util.HashMap; 5 | import java.util.LinkedHashMap; 6 | import java.util.Map; 7 | 8 | public class Request { 9 | private static final String CHARSET = "UTF-8"; 10 | private final Map headers; 11 | private final Map parameters; 12 | private String urlPrefix; 13 | private String method; 14 | private String urlComponents; 15 | private String contentType; 16 | private byte[] payload; 17 | 18 | public Request() { 19 | this.urlPrefix = ""; 20 | this.urlComponents = ""; 21 | this.method = "GET"; 22 | this.headers = new HashMap<>(); 23 | this.parameters = new LinkedHashMap<>(); 24 | this.contentType = "application/json"; 25 | } 26 | 27 | void putHeader(String name, Object value) { 28 | this.headers.put(name, value); 29 | } 30 | 31 | public void putParameter(String name, String value) { 32 | if (name == null || value == null || name.length() == 0) 33 | return; 34 | 35 | parameters.put(name, value); 36 | } 37 | 38 | private static String urlEncode(String value) { 39 | try { 40 | return URLEncoder.encode(value, CHARSET); 41 | } catch (Exception ex) { 42 | return ""; 43 | } 44 | } 45 | 46 | //region [ Getters ] 47 | 48 | public String getUrl() { 49 | String url = this.urlPrefix; 50 | 51 | this.headers.put("content-type", this.contentType); 52 | 53 | if (!url.contains("?")) 54 | url += "?"; 55 | 56 | for (String value : parameters.keySet()) { 57 | if (!url.endsWith("?")) 58 | url += "&"; 59 | 60 | String encodedName = urlEncode(value); 61 | String encodedValue = urlEncode(parameters.get(value)); 62 | url += encodedName + "=" + encodedValue; 63 | } 64 | 65 | return url; 66 | } 67 | 68 | public String getMethod() { 69 | return method; 70 | } 71 | 72 | public Map getHeaders() { 73 | return this.headers; 74 | } 75 | 76 | public byte[] getPayload() { 77 | return this.payload; 78 | } 79 | 80 | public String getContentType() { 81 | return contentType; 82 | } 83 | 84 | //endregion 85 | 86 | //region [ Setters ] 87 | 88 | public void setPayload(byte[] payload) { 89 | this.method = "POST"; 90 | this.payload = payload; 91 | } 92 | 93 | public void setUrlPrefix(String urlPrefix) { 94 | this.urlPrefix = urlPrefix + urlComponents; 95 | } 96 | 97 | public void setUrlComponents(String urlComponents) { 98 | this.urlComponents = urlComponents; 99 | } 100 | 101 | public void setContentType(String contentType) { 102 | this.contentType = contentType; 103 | } 104 | 105 | //endregion 106 | } 107 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_enrichment/result_types/secondary/RootAddress.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_enrichment.result_types.secondary; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | public class RootAddress { 6 | 7 | private int secondaryCount; 8 | 9 | private String smartyKey; 10 | 11 | private String primaryNumber; 12 | 13 | private String streetPredirection; 14 | 15 | private String streetName; 16 | 17 | private String streetSuffix; 18 | 19 | private String streetPostdirection; 20 | 21 | private String cityName; 22 | 23 | private String stateAbbreviation; 24 | 25 | private String zipcode; 26 | 27 | private String plus4Code; 28 | 29 | @JsonProperty("secondary_count") 30 | public int getSecondaryCount() { 31 | return secondaryCount; 32 | } 33 | 34 | @JsonProperty("smarty_key") 35 | public String getSmartyKey() { 36 | return smartyKey; 37 | } 38 | 39 | @JsonProperty("primary_number") 40 | public String getPrimaryNumber() { 41 | return primaryNumber; 42 | } 43 | 44 | @JsonProperty("street_predirection") 45 | public String getStreetPredirection() { 46 | return streetPredirection; 47 | } 48 | 49 | @JsonProperty("street_name") 50 | public String getStreetName() { 51 | return streetName; 52 | } 53 | 54 | @JsonProperty("street_suffix") 55 | public String getStreetSuffix() { 56 | return streetSuffix; 57 | } 58 | 59 | @JsonProperty("street_postdirection") 60 | public String getStreetPostdirection() { 61 | return streetPostdirection; 62 | } 63 | 64 | @JsonProperty("city_name") 65 | public String getCityName() { 66 | return cityName; 67 | } 68 | 69 | @JsonProperty("state_abbreviation") 70 | public String getStateAbbreviation() { 71 | return stateAbbreviation; 72 | } 73 | 74 | @JsonProperty("zipcode") 75 | public String getZipcode() { 76 | return zipcode; 77 | } 78 | 79 | @JsonProperty("plus4_code") 80 | public String getPlus4Code() { 81 | return plus4Code; 82 | } 83 | 84 | @Override 85 | public String toString() { 86 | return "RootAddress{" + 87 | "secondary_count=" + getSecondaryCount() + 88 | ", smarty_key='" + getSmartyKey() + '\'' + 89 | ", primary_number='" + getPrimaryNumber() + '\'' + 90 | ", street_predirection='" + getStreetPredirection() + '\'' + 91 | ", street_name='" + getStreetName() + '\'' + 92 | ", street_suffix='" + getStreetSuffix() + '\'' + 93 | ", street_postdirection='" + getStreetPostdirection() + '\'' + 94 | ", city_name='" + getCityName() + '\'' + 95 | ", state_abbreviation='" + getStateAbbreviation() + '\'' + 96 | ", zipcode='" + getZipcode() + '\'' + 97 | ", plus4_code='" + getPlus4Code() + '\'' + 98 | '}'; 99 | } 100 | } 101 | 102 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_extract/Lookup.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_extract; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import com.smartystreets.api.us_street.MatchType; 5 | 6 | /** 7 | * In addition to holding all of the input data for this lookup, this class also
8 | * will contain the result of the lookup after it comes back from the API. 9 | * @see "https://smartystreets.com/docs/cloud/us-extract-api#http-request-input-fields" 10 | */ 11 | public class Lookup { 12 | //region [ Fields ] 13 | 14 | private Result result; 15 | private String html; 16 | private boolean aggressive; 17 | private boolean addressesHaveLineBreaks; 18 | private int addressesPerLine; 19 | private String text; 20 | 21 | private String match; 22 | 23 | //endregion 24 | 25 | public Lookup() { 26 | this.result = new Result(); 27 | this.addressesHaveLineBreaks = true; 28 | } 29 | 30 | /** 31 | * @param text The text that is to have addresses extracted out of it for verification 32 | */ 33 | public Lookup(String text) { 34 | this(); 35 | this.text = text; 36 | } 37 | 38 | //region [ Getters ] 39 | 40 | public Result getResult() { 41 | return result; 42 | } 43 | 44 | public String isHtml() { 45 | return html; 46 | } 47 | 48 | public boolean isAggressive() { 49 | return aggressive; 50 | } 51 | 52 | public boolean addressesHaveLineBreaks() { 53 | return addressesHaveLineBreaks; 54 | } 55 | 56 | public int getAddressesPerLine() { 57 | return addressesPerLine; 58 | } 59 | 60 | public String getText() { 61 | return text; 62 | } 63 | 64 | @JsonProperty("match") 65 | public String getMatch() { 66 | if (this.match == null) 67 | return null; 68 | if (this.match.equals("strict") ) 69 | return "strict"; 70 | if (this.match.equals("invalid") ) 71 | return "invalid"; 72 | if (this.match.equals("enhanced") ) 73 | return "enhanced"; 74 | return null; 75 | } 76 | 77 | //endregion 78 | 79 | //region [ Setters ] 80 | 81 | public void setResult(Result result) { 82 | this.result = result; 83 | } 84 | 85 | public void specifyHtmlInput(boolean html) { 86 | this.html = String.valueOf(html); 87 | } 88 | 89 | public void isAggressive(boolean aggressive) { 90 | this.aggressive = aggressive; 91 | } 92 | 93 | public void setAddressesHaveLineBreaks(boolean addressesHaveLineBreaks) { 94 | this.addressesHaveLineBreaks = addressesHaveLineBreaks; 95 | } 96 | 97 | public void setAddressesPerLine(int addressesPerLine) { 98 | this.addressesPerLine = addressesPerLine; 99 | } 100 | 101 | public void setText(String text) { 102 | this.text = text; 103 | } 104 | 105 | public void setMatch(MatchType match) { 106 | this.match = match.getName(); 107 | } 108 | 109 | //endregion 110 | } 111 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/international_street/Client.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.international_street; 2 | 3 | import com.smartystreets.api.Request; 4 | import com.smartystreets.api.Response; 5 | import com.smartystreets.api.Sender; 6 | import com.smartystreets.api.Serializer; 7 | import com.smartystreets.api.exceptions.SmartyException; 8 | import com.smartystreets.api.exceptions.UnprocessableEntityException; 9 | 10 | import java.io.IOException; 11 | 12 | /** 13 | * This client sends lookups to the SmartyStreets International Street API,
14 | * and attaches the results to the appropriate Lookup objects. 15 | */ 16 | public class Client { 17 | private final Sender sender; 18 | private final Serializer serializer; 19 | 20 | public Client(Sender sender, Serializer serializer) { 21 | this.sender = sender; 22 | this.serializer = serializer; 23 | } 24 | 25 | public Candidate[] send(Lookup lookup) throws IOException, SmartyException, InterruptedException { 26 | this.ensureEnoughInfo(lookup); 27 | Request request = this.buildRequest(lookup); 28 | 29 | Response response = this.sender.send(request); 30 | 31 | Candidate[] candidates = this.serializer.deserialize(response.getPayload(), Candidate[].class); 32 | lookup.setResult(candidates); 33 | return candidates; 34 | } 35 | 36 | private Request buildRequest(Lookup lookup) { 37 | Request request = new Request(); 38 | 39 | request.putParameter("input_id", lookup.getInputId()); 40 | request.putParameter("country", lookup.getCountry()); 41 | request.putParameter("geocode", lookup.getGeocode()); 42 | if (lookup.getLanguage() != null) 43 | request.putParameter("language", lookup.getLanguage().getName()); 44 | request.putParameter("freeform", lookup.getFreeform()); 45 | request.putParameter("address1", lookup.getAddress1()); 46 | request.putParameter("address2", lookup.getAddress2()); 47 | request.putParameter("address3", lookup.getAddress3()); 48 | request.putParameter("address4", lookup.getAddress4()); 49 | request.putParameter("organization", lookup.getOrganization()); 50 | request.putParameter("locality", lookup.getLocality()); 51 | request.putParameter("administrative_area", lookup.getAdministrativeArea()); 52 | request.putParameter("postal_code", lookup.getPostalCode()); 53 | request.putParameter("features", lookup.getFeatures()); 54 | 55 | return request; 56 | } 57 | 58 | private void ensureEnoughInfo(Lookup lookup) throws SmartyException { 59 | if (lookup.missingCountry()) 60 | throw new UnprocessableEntityException("Country field is required."); 61 | 62 | if (lookup.hasFreeform()) 63 | return; 64 | 65 | if (lookup.missingAddress1()) 66 | throw new UnprocessableEntityException("Either freeform or address1 is required."); 67 | 68 | if (lookup.hasPostalCode()) 69 | return; 70 | 71 | if (lookup.missingLocalityOrAdministrativeArea()) 72 | throw new UnprocessableEntityException("Insufficient information: One or more required fields were not set on the lookup."); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/examples/UsExtractExample.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | import com.smartystreets.api.ClientBuilder; 4 | import com.smartystreets.api.SharedCredentials; 5 | import com.smartystreets.api.exceptions.SmartyException; 6 | import com.smartystreets.api.us_extract.*; 7 | import com.smartystreets.api.us_street.Candidate; 8 | import com.smartystreets.api.us_street.MatchType; 9 | 10 | import java.io.IOException; 11 | 12 | public class UsExtractExample { 13 | public static void main(String[] args) { 14 | // We recommend storing your authentication credentials in environment variables. 15 | // for server-to-server requests, use this code: 16 | //StaticCredentials credentials = new StaticCredentials(System.getenv("SMARTY_AUTH_ID"), System.getenv("SMARTY_AUTH_TOKEN")); 17 | 18 | // for client-side requests (browser/mobile), use this code: 19 | SharedCredentials credentials = new SharedCredentials(System.getenv("SMARTY_AUTH_WEB"), System.getenv("SMARTY_AUTH_REFERER")); 20 | 21 | Client client = new ClientBuilder(credentials).buildUsExtractApiClient(); 22 | String text = "Here is some text.\r\nMy address is 3785 Las Vegs Av." + 23 | "\r\nLos Vegas, Nevada." + 24 | "\r\nMeet me at 1 Rosedale Baltimore Maryland, not at 123 Phony Street, Boise Idaho." + 25 | "\r\n808 County Road 408 Brady, Tx."; 26 | 27 | // Documentation for input fields can be found at: 28 | // https://smartystreets.com/docs/cloud/us-extract-api#http-request-input-fields 29 | 30 | Lookup lookup = new Lookup(text); 31 | lookup.isAggressive(true); 32 | lookup.addressesHaveLineBreaks(); 33 | lookup.getAddressesPerLine(); 34 | lookup.setMatch(MatchType.ENHANCED); 35 | 36 | try { 37 | Result result = client.send(lookup); 38 | 39 | Metadata metadata = result.getMetadata(); 40 | System.out.println("Found " + metadata.getAddressCount() + " addresses."); 41 | System.out.println(metadata.getVerifiedCount() + " of them were valid."); 42 | System.out.println(); 43 | 44 | Address[] addresses = result.getAddresses(); 45 | 46 | System.out.println("Addresses: \r\n**********************\r\n"); 47 | for (Address address : addresses) { 48 | System.out.println("\"" + address.getText() + "\"\n"); 49 | System.out.println("Verified? " + address.isVerified()); 50 | if (address.getCandidates().length > 0) { 51 | System.out.println("\nMatches:"); 52 | 53 | for (Candidate candidate : address.getCandidates()) { 54 | System.out.println(candidate.getDeliveryLine1()); 55 | System.out.println(candidate.getLastLine()); 56 | System.out.println(candidate.getAnalysis().getEnhancedMatch()); 57 | System.out.println(); 58 | } 59 | } else System.out.println(); 60 | 61 | System.out.println("**********************\n"); 62 | } 63 | } catch (SmartyException | IOException | InterruptedException ex) { 64 | System.out.println(ex.getMessage()); 65 | ex.printStackTrace(); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_autocomplete_pro/Client.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_autocomplete_pro; 2 | 3 | 4 | import com.smartystreets.api.*; 5 | import com.smartystreets.api.exceptions.SmartyException; 6 | 7 | import java.io.IOException; 8 | import java.util.List; 9 | 10 | /** 11 | * This client sends lookups to the SmartyStreets US Autocomplete Pro API,
12 | * and attaches the results to the appropriate Lookup objects. 13 | */ 14 | public class Client { 15 | private final Sender sender; 16 | private final Serializer serializer; 17 | 18 | public Client(Sender sender, Serializer serializer) { 19 | this.sender = sender; 20 | this.serializer = serializer; 21 | } 22 | 23 | public Suggestion[] send(Lookup lookup) throws SmartyException, IOException, InterruptedException { 24 | if (lookup == null || lookup.getSearch() == null || lookup.getSearch().length() == 0) 25 | throw new SmartyException("Send() must be passed a Lookup with the prefix field set."); 26 | 27 | Request request = this.buildRequest(lookup); 28 | 29 | Response response = this.sender.send(request); 30 | 31 | Result result = this.serializer.deserialize(response.getPayload(), Result.class); 32 | Suggestion[] suggestions = result.getSuggestions(); 33 | lookup.setResult(suggestions); 34 | 35 | return suggestions; 36 | } 37 | 38 | private Request buildRequest(Lookup lookup) { 39 | Request request = new Request(); 40 | 41 | request.putParameter("search", lookup.getSearch()); 42 | request.putParameter("max_results", lookup.getMaxSuggestionsStringIfSet()); 43 | request.putParameter("include_only_cities", this.buildString(lookup.getCityFilter())); 44 | request.putParameter("include_only_states", this.buildString(lookup.getStateFilter())); 45 | request.putParameter("include_only_zip_codes", this.buildString(lookup.getZipcodeFilter())); 46 | request.putParameter("exclude_states", this.buildString(lookup.getExcludeStates())); 47 | request.putParameter("prefer_cities", this.buildString(lookup.getPreferCity())); 48 | request.putParameter("prefer_states", this.buildString(lookup.getPreferState())); 49 | request.putParameter("prefer_zip_codes", this.buildString(lookup.getPreferZipcode())); 50 | request.putParameter("prefer_ratio", lookup.getPreferRatioStringIfSet()); 51 | if (lookup.getGeolocateType() != null) { 52 | request.putParameter("prefer_geolocation", lookup.getGeolocateType().getName()); 53 | } 54 | request.putParameter("selected", lookup.getSelected()); 55 | request.putParameter("source", lookup.getSource()); 56 | 57 | return request; 58 | } 59 | 60 | private String buildString(List list) { 61 | return buildStringFromList(list, ";"); 62 | } 63 | 64 | private String buildStringFromList(List list, String separator) { 65 | if (list.isEmpty()) 66 | return null; 67 | 68 | String filterList = ""; 69 | 70 | for (String item : list) { 71 | filterList += (item + separator); 72 | } 73 | 74 | if (filterList.endsWith(separator)) 75 | filterList = filterList.substring(0, filterList.length()-1); 76 | 77 | return filterList; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/examples/UsStreetSingleAddressExample.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | import com.smartystreets.api.StaticCredentials; 4 | import com.smartystreets.api.exceptions.SmartyException; 5 | import com.smartystreets.api.us_street.*; 6 | import com.smartystreets.api.ClientBuilder; 7 | 8 | import java.io.IOException; 9 | import java.util.List; 10 | 11 | public class UsStreetSingleAddressExample { 12 | public static void main(String[] args) { 13 | // We recommend storing your authentication credentials in environment variables. 14 | // for server-to-server requests, use this code: 15 | StaticCredentials credentials = new StaticCredentials(System.getenv("SMARTY_AUTH_ID"), System.getenv("SMARTY_AUTH_TOKEN")); 16 | 17 | // for client-side requests (browser/mobile), use this code: 18 | // SharedCredentials credentials = new SharedCredentials(System.getenv("SMARTY_AUTH_WEB"), System.getenv("SMARTY_AUTH_REFERER")); 19 | 20 | Client client = new ClientBuilder(credentials) 21 | // .withProxy(Proxy.Type.HTTP, "localhost", 8080) // Uncomment this line to try it with a proxy 22 | .buildUsStreetApiClient(); 23 | 24 | // Documentation for input fields can be found at: 25 | // https://smartystreets.com/docs/us-street-api#input-fields 26 | 27 | Lookup lookup = new Lookup(); 28 | lookup.setInputId("24601"); // Optional ID from your system 29 | lookup.setAddressee("John Doe"); 30 | lookup.setStreet("1600 Amphitheatre Pkwy"); 31 | lookup.setStreet2("closet under the stairs"); 32 | lookup.setSecondary("APT 2"); 33 | lookup.setUrbanization(""); // Only applies to Puerto Rico addresses 34 | lookup.setCity("Mountain View"); 35 | lookup.setState("CA"); 36 | lookup.setZipCode("94043"); 37 | lookup.setCountySource(CountySource.GEOGRAPHIC); 38 | lookup.setMaxCandidates(3); 39 | lookup.setMatch(MatchType.INVALID); // "invalid" is the most permissive match, 40 | // this will always return at least one result even if the address is invalid. 41 | // Refer to the documentation for additional MatchStrategy options. 42 | 43 | try { 44 | client.send(lookup); 45 | } 46 | catch (SmartyException | IOException | InterruptedException ex) { 47 | System.out.println(ex.getMessage()); 48 | ex.printStackTrace(); 49 | } 50 | 51 | List results = lookup.getResult(); 52 | 53 | if (results.isEmpty()) { 54 | System.out.println("No candidates. This means the address is not valid."); 55 | return; 56 | } 57 | 58 | Candidate firstCandidate = results.get(0); 59 | 60 | System.out.println("There is at least one candidate.\n If the match parameter is set to STRICT, the address is valid.\n Otherwise, check the Analysis output fields to see if the address is valid.\n"); 61 | System.out.println("Input ID: " + firstCandidate.getInputId()); 62 | System.out.println("ZIP Code: " + firstCandidate.getComponents().getZipCode()); 63 | System.out.println("County: " + firstCandidate.getMetadata().getCountyName()); 64 | System.out.println("Latitude: " + firstCandidate.getMetadata().getLatitude()); 65 | System.out.println("Longitude: " + firstCandidate.getMetadata().getLongitude()); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_street/Metadata.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_street; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * @see "https://smartystreets.com/docs/cloud/us-street-api#metadata" 9 | */ 10 | public class Metadata implements Serializable { 11 | //region [ Fields ] 12 | 13 | private String recordType; 14 | private String zipType; 15 | private String countyFips; 16 | private String countyName; 17 | private String carrierRoute; 18 | private String congressionalDistrict; 19 | private String buildingDefaultIndicator; 20 | private String rdi; 21 | private String elotSequence; 22 | private String elotSort; 23 | private double latitude; 24 | private double longitude; 25 | private int coordinateLicense; 26 | private String precision; 27 | private String timeZone; 28 | private double utcOffset; 29 | private boolean obeysDst; 30 | private boolean ewsMatch; 31 | 32 | //endregion 33 | 34 | //region [ Getters ] 35 | 36 | @JsonProperty("record_type") 37 | public String getRecordType() { 38 | return this.recordType; 39 | } 40 | 41 | @JsonProperty("zip_type") 42 | public String getZipType() { 43 | return this.zipType; 44 | } 45 | 46 | @JsonProperty("county_fips") 47 | public String getCountyFips() { 48 | return this.countyFips; 49 | } 50 | 51 | @JsonProperty("county_name") 52 | public String getCountyName() { 53 | return this.countyName; 54 | } 55 | 56 | @JsonProperty("carrier_route") 57 | public String getCarrierRoute() { 58 | return this.carrierRoute; 59 | } 60 | 61 | @JsonProperty("congressional_district") 62 | public String getCongressionalDistrict() { 63 | return this.congressionalDistrict; 64 | } 65 | 66 | @JsonProperty("building_default_indicator") 67 | public String getBuildingDefaultIndicator() { 68 | return this.buildingDefaultIndicator; 69 | } 70 | 71 | @JsonProperty("rdi") 72 | public String getRdi() { 73 | return this.rdi; 74 | } 75 | 76 | @JsonProperty("elot_sequence") 77 | public String getElotSequence() { 78 | return this.elotSequence; 79 | } 80 | 81 | @JsonProperty("elot_sort") 82 | public String getElotSort() { 83 | return this.elotSort; 84 | } 85 | 86 | @JsonProperty("latitude") 87 | public double getLatitude() { 88 | return this.latitude; 89 | } 90 | 91 | @JsonProperty("longitude") 92 | public double getLongitude() { 93 | return this.longitude; 94 | } 95 | 96 | @JsonProperty("coordinate_license") 97 | public int getCoordinateLicense() { return this.coordinateLicense; } 98 | 99 | @JsonProperty("precision") 100 | public String getPrecision() { 101 | return this.precision; 102 | } 103 | 104 | @JsonProperty("time_zone") 105 | public String getTimeZone() { 106 | return this.timeZone; 107 | } 108 | 109 | // TODO: Coordinate Licensei 110 | 111 | @JsonProperty("utc_offset") 112 | public double getUtcOffset() { 113 | return this.utcOffset; 114 | } 115 | 116 | @JsonProperty("dst") 117 | public boolean obeysDst() { 118 | return this.obeysDst; 119 | } 120 | 121 | @JsonProperty("ews_match") 122 | public boolean isEwsMatch() { 123 | return this.ewsMatch; 124 | } 125 | 126 | 127 | //endregion 128 | } 129 | -------------------------------------------------------------------------------- /src/test/java/com/smartystreets/api/us_autocomplete_pro/ClientTest.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_autocomplete_pro; 2 | 3 | import com.smartystreets.api.GeolocateType; 4 | import com.smartystreets.api.Response; 5 | import com.smartystreets.api.URLPrefixSender; 6 | import com.smartystreets.api.mocks.FakeDeserializer; 7 | import com.smartystreets.api.mocks.FakeSerializer; 8 | import com.smartystreets.api.mocks.MockSender; 9 | import com.smartystreets.api.mocks.RequestCapturingSender; 10 | import org.junit.Test; 11 | 12 | import static org.junit.Assert.assertArrayEquals; 13 | import static org.junit.Assert.assertEquals; 14 | 15 | public class ClientTest { 16 | //region [ Single Lookup ] 17 | 18 | @Test 19 | public void testSendingSinglePrefixOnlyLookup() throws Exception { 20 | RequestCapturingSender capturingSender = new RequestCapturingSender(); 21 | URLPrefixSender sender = new URLPrefixSender("http://localhost/", capturingSender); 22 | FakeSerializer serializer = new FakeSerializer(new Result()); 23 | Client client = new Client(sender, serializer); 24 | 25 | client.send(new Lookup("1")); 26 | 27 | assertEquals("http://localhost/?search=1&prefer_geolocation=city", capturingSender.getRequest().getUrl()); 28 | } 29 | 30 | @Test 31 | public void testSendingSingleFullyPopulatedLookup() throws Exception { 32 | RequestCapturingSender capturingSender = new RequestCapturingSender(); 33 | URLPrefixSender sender = new URLPrefixSender("http://localhost/", capturingSender); 34 | FakeSerializer serializer = new FakeSerializer(new Result()); 35 | Client client = new Client(sender, serializer); 36 | String expectedURL = "http://localhost/?search=1&max_results=2&include_only_cities=3&include_only_states=4&prefer_ratio=60&prefer_geolocation=city"; 37 | Lookup lookup = new Lookup(); 38 | lookup.setSearch("1"); 39 | lookup.setMaxResults(2); 40 | lookup.addCityFilter("3"); 41 | lookup.addStateFilter("4"); 42 | lookup.setPreferRatio(60); 43 | lookup.setGeolocateType(GeolocateType.CITY); 44 | 45 | client.send(lookup); 46 | 47 | assertEquals(expectedURL, capturingSender.getRequest().getUrl()); 48 | } 49 | 50 | //endregion 51 | 52 | //region [ Response Handling ] 53 | 54 | @Test 55 | public void testDeserializeCalledWithResponseBody() throws Exception { 56 | Response response = new Response(0, "Hello, World!".getBytes()); 57 | MockSender mockSender = new MockSender(response); 58 | URLPrefixSender sender = new URLPrefixSender("http://localhost/", mockSender); 59 | FakeDeserializer deserializer = new FakeDeserializer(new Result()); 60 | Client client = new Client(sender, deserializer); 61 | 62 | client.send(new Lookup("1")); 63 | 64 | assertEquals(response.getPayload(), deserializer.getPayload()); 65 | } 66 | 67 | @Test 68 | public void testResultCorrectlyAssignedToCorrespondingLookup() throws Exception { 69 | Lookup lookup = new Lookup("1"); 70 | Result expectedResult = new Result(); 71 | 72 | MockSender mockSender = new MockSender(new Response(0, "{[]}".getBytes())); 73 | URLPrefixSender sender = new URLPrefixSender("http://localhost/", mockSender); 74 | FakeDeserializer deserializer = new FakeDeserializer(expectedResult); 75 | Client client = new Client(sender, deserializer); 76 | 77 | client.send(lookup); 78 | 79 | assertArrayEquals(expectedResult.getSuggestions(), lookup.getResult()); 80 | } 81 | 82 | //endregion 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_zipcode/Lookup.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_zipcode; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | 6 | import java.io.Serializable; 7 | 8 | /** 9 | * In addition to holding all of the input data for this lookup, this class also
10 | * will contain the result of the lookup after it comes back from the API. 11 | * @see "https://smartystreets.com/docs/cloud/us-zipcode-api#http-request-input-fields" 12 | */ 13 | public class Lookup implements Serializable { 14 | //region [ Fields ] 15 | 16 | //private static final long serialVersionUID = 1L; 17 | private Result result; 18 | private String inputId; 19 | private String city; 20 | private String state; 21 | private String zipcode; 22 | 23 | //This is a temporary flag meant to fix an intermittent data issue 24 | //Unless explicitly instructed by the Smarty Tech Support team, DO NOT use this parameter 25 | private String compatibility; 26 | 27 | 28 | //endregion 29 | 30 | public Lookup() { 31 | this.result = new Result(); 32 | } 33 | 34 | public Lookup(String zipcode) { 35 | this(); 36 | this.zipcode = zipcode; 37 | } 38 | 39 | public Lookup(String city, String state) { 40 | this(); 41 | this.city = city; 42 | this.state = state; 43 | } 44 | 45 | public Lookup(String city, String state, String zipcode) { 46 | this(); 47 | this.city = city; 48 | this.state = state; 49 | this.zipcode = zipcode; 50 | } 51 | 52 | //region [ Getters ] 53 | 54 | @JsonIgnore 55 | public Result getResult() { 56 | return this.result; 57 | } 58 | 59 | public String getCity() { 60 | return this.city; 61 | } 62 | 63 | public String getState() { 64 | return this.state; 65 | } 66 | 67 | public String getZipCode() { 68 | return this.zipcode; 69 | } 70 | 71 | public String getInputId() { 72 | return this.inputId; 73 | } 74 | 75 | /** 76 | * This is a temporary flag meant to fix an intermittent data issue 77 | * Unless explicitly instructed by the Smarty Tech Support team, DO NOT use this parameter 78 | * 79 | * @deprecated - Temporary - will be removed in a future release. 80 | */ 81 | public String getCompatibility() { 82 | return this.compatibility; 83 | } 84 | 85 | //endregion 86 | 87 | //region [ Setters ] 88 | 89 | @JsonProperty("result") 90 | public void setResult(Result result) { 91 | this.result = result; 92 | } 93 | 94 | @JsonProperty("city") 95 | public void setCity(String city) { 96 | this.city = city; 97 | } 98 | 99 | @JsonProperty("state") 100 | public void setState(String state) { 101 | this.state = state; 102 | } 103 | 104 | @JsonProperty("zipcode") 105 | public void setZipCode(String zipcode) { 106 | this.zipcode = zipcode; 107 | } 108 | 109 | /** 110 | * This is a temporary flag meant to fix an intermittent data issue 111 | * Unless explicitly instructed by the Smarty Tech Support team, DO NOT use this parameter 112 | * 113 | * * @deprecated - Temporary - will be removed in a future release. 114 | */ 115 | public void setCompatibility(String compatibility) { 116 | this.compatibility = compatibility; 117 | } 118 | 119 | public Lookup setInputId(String inputId) { 120 | this.inputId = inputId; 121 | return this; 122 | } 123 | 124 | //endregion 125 | } 126 | -------------------------------------------------------------------------------- /src/test/java/com/smartystreets/api/RetrySenderTest.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api; 2 | 3 | import com.smartystreets.api.exceptions.SmartyException; 4 | import com.smartystreets.api.mocks.FakeLogger; 5 | import com.smartystreets.api.mocks.FakeSleeper; 6 | import com.smartystreets.api.mocks.MockCrashingSender; 7 | import org.junit.Before; 8 | import org.junit.Test; 9 | 10 | import java.io.IOException; 11 | 12 | import static org.junit.Assert.*; 13 | 14 | public class RetrySenderTest { 15 | private FakeSleeper fakeSleeper; 16 | private FakeLogger fakeLogger; 17 | 18 | private MockCrashingSender mockCrashingSender; 19 | 20 | @Before 21 | public void setup() { 22 | this.mockCrashingSender = new MockCrashingSender(); 23 | this.fakeSleeper = new FakeSleeper(); 24 | this.fakeLogger = new FakeLogger(); 25 | } 26 | 27 | @Test 28 | public void testSuccessDoesNotRetry() throws Exception { 29 | this.sendRequest("DoNotRetry"); 30 | 31 | assertEquals(1, this.mockCrashingSender.getSendCount()); 32 | } 33 | 34 | @Test 35 | public void testRetryUntilSuccess() throws Exception { 36 | this.sendRequest("RetryThreeTimes"); 37 | 38 | assertEquals(4, this.mockCrashingSender.getSendCount()); 39 | } 40 | 41 | @Test 42 | public void testRetryUntilMaxAttempts() throws Exception { 43 | assertThrows(IOException.class, () -> this.sendRequest("RetryMaxTimes")); 44 | } 45 | 46 | @Test 47 | public void testBackoffDoesNotExceedMax() throws Exception { 48 | Long[] expectedDurations = new Long[] {0L,1L,2L,3L,4L,5L,6L,7L,8L,9L,10L,10L,10L,10L}; 49 | 50 | this.sendRequest("RetryFifteenTimes"); 51 | 52 | assertEquals(15, this.mockCrashingSender.getSendCount()); 53 | assertArrayEquals(expectedDurations, this.fakeSleeper.getSleepDurations().toArray()); 54 | } 55 | 56 | @Test 57 | public void testSleepOnRateLimit() throws Exception { 58 | Long[] expectedDurations = new Long[] {7L,7L}; 59 | 60 | this.sendRequest("TooManyRequests"); 61 | 62 | assertEquals(3, this.mockCrashingSender.getSendCount()); 63 | assertArrayEquals(expectedDurations, this.fakeSleeper.getSleepDurations().toArray()); 64 | } 65 | 66 | @Test 67 | public void testWaitLongerThanMaxWaitTime() throws Exception { 68 | // The maxWaitTime is less than the total wait time of the sendRequest 69 | assertThrows(SmartyException.class, () -> this.sendRequest("WaitTimeTooLong", 7)); 70 | assertEquals(2, this.mockCrashingSender.getSendCount()); 71 | 72 | // // The maxWaitTime is negative so it is ignored 73 | this.sendRequest("WaitTimeTooLong", -1); 74 | assertEquals(3, this.mockCrashingSender.getSendCount()); 75 | 76 | // The maxWaitTime is larger than the total wait time, no exception thrown 77 | this.sendRequest("WaitTimeTooLong", 9); 78 | assertEquals(4, this.mockCrashingSender.getSendCount()); 79 | } 80 | 81 | private void sendRequest(String requestBehavior) throws Exception { 82 | Request request = new Request(); 83 | request.setUrlPrefix(requestBehavior); 84 | RetrySender retrySender = new RetrySender(15, this.fakeSleeper, this.fakeLogger, this.mockCrashingSender); 85 | 86 | retrySender.send(request); 87 | } 88 | 89 | private void sendRequest(String requestBehavior, long maxWaitTime) throws Exception { 90 | Request request = new Request(); 91 | request.setUrlPrefix(requestBehavior); 92 | RetrySender retrySender = new RetrySender(15, this.fakeSleeper, this.fakeLogger, this.mockCrashingSender); 93 | 94 | retrySender.WithMaxWaitTime(maxWaitTime); 95 | 96 | retrySender.send(request); 97 | } 98 | } -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_street/Client.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_street; 2 | 3 | import com.smartystreets.api.Request; 4 | import com.smartystreets.api.Response; 5 | import com.smartystreets.api.Sender; 6 | import com.smartystreets.api.Serializer; 7 | import com.smartystreets.api.exceptions.SmartyException; 8 | 9 | import java.io.IOException; 10 | 11 | /** 12 | * This client sends lookups to the SmartyStreets US Street API,
13 | * and attaches the results to the appropriate Lookup objects. 14 | */ 15 | public class Client { 16 | private final Sender sender; 17 | private final Serializer serializer; 18 | 19 | public Client(Sender sender, Serializer serializer) { 20 | this.sender = sender; 21 | this.serializer = serializer; 22 | } 23 | 24 | public void send(Lookup lookup) throws SmartyException, IOException, InterruptedException { 25 | Batch batch = new Batch(); 26 | batch.add(lookup); 27 | this.send(batch); 28 | } 29 | 30 | /** 31 | * Sends a batch of up to 100 lookups for validation. 32 | * 33 | * @param batch Batch must contain between 1 and 100 Lookup objects 34 | * @throws SmartyException 35 | * @throws IOException 36 | */ 37 | public void send(Batch batch) throws SmartyException, IOException, InterruptedException { 38 | Request request = new Request(); 39 | 40 | if (batch.size() == 0) 41 | throw new SmartyException("Batch must contain between 1 and 100 lookups"); 42 | 43 | if (batch.size() == 1) 44 | this.populateQueryString(batch.getAllLookups().get(0), request); 45 | else 46 | request.setPayload(this.serializer.serialize(batch.getAllLookups())); 47 | 48 | Response response = this.sender.send(request); 49 | 50 | Candidate[] candidates = null; 51 | 52 | if (response != null) { 53 | candidates = this.serializer.deserialize(response.getPayload(), Candidate[].class); 54 | } 55 | 56 | if (candidates == null) 57 | candidates = new Candidate[0]; 58 | this.assignCandidatesToLookups(batch, candidates); 59 | } 60 | 61 | private void populateQueryString(Lookup address, Request request) { 62 | request.putParameter("input_id", address.getInputId()); 63 | request.putParameter("street", address.getStreet()); 64 | request.putParameter("street2", address.getStreet2()); 65 | request.putParameter("secondary", address.getSecondary()); 66 | request.putParameter("city", address.getCity()); 67 | request.putParameter("state", address.getState()); 68 | request.putParameter("zipcode", address.getZipCode()); 69 | request.putParameter("lastline", address.getLastline()); 70 | request.putParameter("addressee", address.getAddressee()); 71 | request.putParameter("urbanization", address.getUrbanization()); 72 | request.putParameter("county_source", address.getCountySource()); 73 | request.putParameter("match", address.getMatch()); 74 | request.putParameter("format", address.getFormat()); 75 | 76 | if (address.getMaxCandidates() == 1 && (address.getMatch() != null && address.getMatch().equals("enhanced"))) 77 | request.putParameter("candidates", "5"); 78 | else 79 | request.putParameter("candidates", Integer.toString(address.getMaxCandidates())); 80 | 81 | //This is a temporary flag meant to fix an intermittent data issue 82 | //Unless explicitly instructed by the Smarty Tech Support team, DO NOT use this parameter 83 | request.putParameter("compatibility", address.getCompatibility()); 84 | 85 | } 86 | 87 | 88 | private void assignCandidatesToLookups(Batch batch, Candidate[] candidates) { 89 | for (Candidate candidate : candidates) 90 | batch.get(candidate.getInputIndex()).addToResult(candidate); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/com/smartystreets/api/us_street/Components.java: -------------------------------------------------------------------------------- 1 | package com.smartystreets.api.us_street; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * This class contains the matched address broken down into its
9 | * fundamental pieces. 10 | * @see "https://smartystreets.com/docs/cloud/us-street-api#components" 11 | */ 12 | public class Components implements Serializable { 13 | 14 | //region [ Fields ] 15 | 16 | private String urbanization; 17 | private String primaryNumber; 18 | private String streetName; 19 | private String streetPredirection; 20 | private String streetPostdirection; 21 | private String streetSuffix; 22 | private String secondaryNumber; 23 | private String secondaryDesignator; 24 | private String extraSecondaryNumber; 25 | private String extraSecondaryDesignator; 26 | private String pmbDesignator; 27 | private String pmbNumber; 28 | private String cityName; 29 | private String defaultCityName; 30 | private String state; 31 | private String zipCode; 32 | private String plus4Code; 33 | private String deliveryPoint; 34 | private String deliveryPointCheckDigit; 35 | 36 | //endregion 37 | 38 | //region [ Getters ] 39 | 40 | @JsonProperty("urbanization") 41 | public String getUrbanization() { 42 | return this.urbanization; 43 | } 44 | 45 | @JsonProperty("primary_number") 46 | public String getPrimaryNumber() { 47 | return this.primaryNumber; 48 | } 49 | 50 | @JsonProperty("street_name") 51 | public String getStreetName() { 52 | return this.streetName; 53 | } 54 | 55 | @JsonProperty("street_predirection") 56 | public String getStreetPredirection() { 57 | return this.streetPredirection; 58 | } 59 | 60 | @JsonProperty("street_postdirection") 61 | public String getStreetPostdirection() { 62 | return this.streetPostdirection; 63 | } 64 | 65 | @JsonProperty("street_suffix") 66 | public String getStreetSuffix() { 67 | return this.streetSuffix; 68 | } 69 | 70 | @JsonProperty("secondary_number") 71 | public String getSecondaryNumber() { 72 | return this.secondaryNumber; 73 | } 74 | 75 | @JsonProperty("secondary_designator") 76 | public String getSecondaryDesignator() { 77 | return this.secondaryDesignator; 78 | } 79 | 80 | @JsonProperty("extra_secondary_number") 81 | public String getExtraSecondaryNumber() { 82 | return this.extraSecondaryNumber; 83 | } 84 | 85 | @JsonProperty("extra_secondary_designator") 86 | public String getExtraSecondaryDesignator() { 87 | return this.extraSecondaryDesignator; 88 | } 89 | 90 | @JsonProperty("pmb_designator") 91 | public String getPmbDesignator() { 92 | return this.pmbDesignator; 93 | } 94 | 95 | @JsonProperty("pmb_number") 96 | public String getPmbNumber() { 97 | return this.pmbNumber; 98 | } 99 | 100 | @JsonProperty("city_name") 101 | public String getCityName() { 102 | return this.cityName; 103 | } 104 | 105 | @JsonProperty("default_city_name") 106 | public String getDefaultCityName() { 107 | return this.defaultCityName; 108 | } 109 | 110 | @JsonProperty("state_abbreviation") 111 | public String getState() { 112 | return this.state; 113 | } 114 | 115 | @JsonProperty("zipcode") 116 | public String getZipCode() { 117 | return this.zipCode; 118 | } 119 | 120 | @JsonProperty("plus4_code") 121 | public String getPlus4Code() { 122 | return this.plus4Code; 123 | } 124 | 125 | @JsonProperty("delivery_point") 126 | public String getDeliveryPoint() { 127 | return this.deliveryPoint; 128 | } 129 | 130 | @JsonProperty("delivery_point_check_digit") 131 | public String getDeliveryPointCheckDigit() { 132 | return this.deliveryPointCheckDigit; 133 | } 134 | 135 | //endregion 136 | } 137 | --------------------------------------------------------------------------------