1 package com.xtremelabs.robolectric.shadows;
2 
3 import android.location.Address;
4 import android.location.Geocoder;
5 import com.xtremelabs.robolectric.internal.Implementation;
6 import com.xtremelabs.robolectric.internal.Implements;
7 
8 import java.io.IOException;
9 import java.util.ArrayList;
10 import java.util.List;
11 import java.util.Locale;
12 
13 import static com.xtremelabs.robolectric.Robolectric.shadowOf;
14 
15 /**
16  * A shadow for Geocoder that supports simulated responses and failures
17  */
18 @SuppressWarnings({"UnusedDeclaration"})
19 @Implements(Geocoder.class)
20 public class ShadowGeocoder {
21     private String addressLine1;
22     private String city;
23     private String state;
24     private String zip;
25     private String countryCode;
26     private boolean wasCalled;
27     private double lastLatitude;
28     private double lastLongitude;
29     private String lastLocationName;
30     private double simulatedLatitude;
31     private double simulatedLongitude;
32     private boolean shouldSimulateGeocodeException;
33     private boolean hasLatitude;
34     private boolean hasLongitude;
35     private boolean returnNoResults = false;
36     private boolean didResolution;
37 
38     @Implementation
getFromLocation(double latitude, double longitude, int maxResults)39     public List<Address> getFromLocation(double latitude, double longitude, int maxResults) throws IOException {
40         wasCalled = true;
41         this.lastLatitude = latitude;
42         this.lastLongitude = longitude;
43         if (shouldSimulateGeocodeException) {
44             throw new IOException("Simulated geocode exception");
45         }
46         Address address = makeAddress();
47         address.setAddressLine(0, addressLine1);
48         address.setLocality(city);
49         address.setAdminArea(state);
50         address.setPostalCode(zip);
51         address.setCountryCode(countryCode);
52         return oneElementList(address);
53     }
54 
55     @Implementation
getFromLocationName(String locationName, int maxResults)56     public List<Address> getFromLocationName(String locationName, int maxResults) throws IOException {
57         didResolution = true;
58         this.lastLocationName = locationName;
59         if (shouldSimulateGeocodeException) {
60             throw new IOException("Simulated geocode exception");
61         }
62         if (returnNoResults) {
63             return new ArrayList<Address>();
64         } else {
65             Address address = makeAddress();
66             address.setLatitude(simulatedLatitude);
67             address.setLongitude(simulatedLongitude);
68             return oneElementList(address);
69         }
70     }
71 
makeAddress()72     private Address makeAddress() {
73         Address address = new Address(Locale.getDefault());
74         shadowOf(address).setSimulatedHasLatLong(hasLatitude, hasLongitude);
75         return address;
76     }
77 
78     /**
79      * Sets up a simulated response for {@link #getFromLocation(double, double, int)}
80      *
81      * @param address     the address for the response
82      * @param city        the city for the response
83      * @param state       the state for the response
84      * @param zip         the zip code for the response
85      * @param countryCode the country code for the response
86      */
setSimulatedResponse(String address, String city, String state, String zip, String countryCode)87     public void setSimulatedResponse(String address, String city, String state, String zip, String countryCode) {
88         this.addressLine1 = address;
89         this.city = city;
90         this.state = state;
91         this.zip = zip;
92         this.countryCode = countryCode;
93     }
94 
95 
96     /**
97      * Sets up a simulated response for {@link #getFromLocationName(String, int)}}
98      *
99      * @param lat latitude for simulated response
100      * @param lng longitude for simulated response
101      */
setSimulatedLatLong(double lat, double lng)102     public void setSimulatedLatLong(double lat, double lng) {
103         this.simulatedLatitude = lat;
104         this.simulatedLongitude = lng;
105     }
106 
107     /**
108      * Sets a flag to indicate whether or not {@link #getFromLocationName(String, int)} should throw an exception to
109      * simulate a failure.
110      *
111      * @param shouldSimulateException whether or not an exception should be thrown from {@link #getFromLocationName(String, int)}
112      */
setShouldSimulateGeocodeException(boolean shouldSimulateException)113     public void setShouldSimulateGeocodeException(boolean shouldSimulateException) {
114         this.shouldSimulateGeocodeException = true;
115     }
116 
117     /**
118      * Non-Android accessor that indicates whether {@link #getFromLocation(double, double, int)} was called.
119      *
120      * @return whether {@link #getFromLocation(double, double, int)} was called.
121      */
wasGetFromLocationCalled()122     public boolean wasGetFromLocationCalled() {
123         return wasCalled;
124     }
125 
getLastLongitude()126     public double getLastLongitude() {
127         return lastLongitude;
128     }
129 
getLastLatitude()130     public double getLastLatitude() {
131         return lastLatitude;
132     }
133 
getLastLocationName()134     public String getLastLocationName() {
135         return lastLocationName;
136     }
137 
oneElementList(Address address)138     private List<Address> oneElementList(Address address) {
139         ArrayList<Address> addresses = new ArrayList<Address>();
140         addresses.add(address);
141         return addresses;
142     }
143 
setSimulatedHasLatLong(boolean hasLatitude, boolean hasLongitude)144     public void setSimulatedHasLatLong(boolean hasLatitude, boolean hasLongitude) {
145         this.hasLatitude = hasLatitude;
146         this.hasLongitude = hasLongitude;
147     }
148 
setReturnNoResults(boolean returnNoResults)149     public void setReturnNoResults(boolean returnNoResults) {
150         this.returnNoResults = returnNoResults;
151     }
152 
didResolution()153     public boolean didResolution() {
154         return didResolution;
155     }
156 }