CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-twitter4j--twitter4j-core

A 100% pure Java library for the Twitter API with no extra dependency

Overview
Eval results
Files

places.mddocs/

Geographic and Places

Location-based functionality including places, geocoding, and geographic search.

Places and Geographic Data

Place Search and Discovery

Search for places and geographic locations.

interface PlacesGeoResources {
    /**
     * Search for places matching query
     * @param query Geographic query with location and search parameters
     * @return List of matching places
     */
    ResponseList<Place> searchPlaces(GeoQuery query) throws TwitterException;
    
    /**
     * Find similar places to a location
     * @param location Geographic coordinates
     * @param name Place name to search for
     * @param containedWithin Place ID that should contain the result
     * @param streetAddress Street address for more precise matching
     * @return List of similar places
     */
    ResponseList<Place> getSimilarPlaces(GeoLocation location, String name, 
                                       String containedWithin, String streetAddress) throws TwitterException;
    
    /**
     * Reverse geocoding - find places near coordinates
     * @param query Geographic query with coordinates
     * @return List of places near the coordinates
     */
    ResponseList<Place> reverseGeoCode(GeoQuery query) throws TwitterException;
    
    /**
     * Get detailed information about a specific place
     * @param placeId Twitter place ID
     * @return Detailed place information
     */
    Place getGeoDetails(String placeId) throws TwitterException;
}

Usage Examples:

TwitterV1 v1 = twitter.v1();

// Search for places by name
GeoQuery query = GeoQuery.of("San Francisco")
    .accuracy(GeoQuery.Accuracy.city)
    .granularity("city")
    .maxResults(10);
    
ResponseList<Place> places = v1.placesGeo().searchPlaces(query);
for (Place place : places) {
    System.out.println(place.getFullName() + " (" + place.getId() + ")");
}

// Reverse geocoding - find places near coordinates
GeoLocation sanFrancisco = new GeoLocation(37.7749, -122.4194);
GeoQuery reverseQuery = GeoQuery.of(sanFrancisco)
    .accuracy("1km")
    .granularity("neighborhood");
    
ResponseList<Place> nearbyPlaces = v1.placesGeo().reverseGeoCode(reverseQuery);
for (Place place : nearbyPlaces) {
    System.out.println("Nearby: " + place.getName());
}

// Get details for a specific place
Place placeDetails = v1.placesGeo().getGeoDetails("5a110d312052166f");
System.out.println("Full name: " + placeDetails.getFullName());
System.out.println("Country: " + placeDetails.getCountry());
System.out.println("Place type: " + placeDetails.getPlaceType());

Geographic Query Building

GeoQuery Class

Construct geographic search queries with location and filtering parameters.

class GeoQuery {
    /**
     * Create query with place name
     * @param query Place name or address to search for
     * @return GeoQuery with search term
     */
    static GeoQuery of(String query);
    
    /**
     * Create query with coordinates
     * @param location Geographic coordinates
     * @return GeoQuery with location
     */
    static GeoQuery of(GeoLocation location);
    
    /**
     * Create query with coordinates and IP address
     * @param location Geographic coordinates
     * @param ip IP address for additional context
     * @return GeoQuery with location and IP
     */
    static GeoQuery of(GeoLocation location, String ip);
    
    /**
     * Set search accuracy
     * @param accuracy Accuracy level or distance (e.g., "1km", "5mi")
     * @return GeoQuery with accuracy setting
     */
    GeoQuery accuracy(String accuracy);
    
    /**
     * Set search accuracy using predefined levels
     * @param accuracy Predefined accuracy level
     * @return GeoQuery with accuracy setting
     */
    GeoQuery accuracy(Accuracy accuracy);
    
    /**
     * Set place granularity
     * @param granularity Granularity level ("poi", "neighborhood", "city", "admin", "country")
     * @return GeoQuery with granularity setting
     */
    GeoQuery granularity(String granularity);
    
    /**
     * Set maximum number of results
     * @param maxResults Maximum number of places to return
     * @return GeoQuery with max results setting
     */
    GeoQuery maxResults(int maxResults);
    
    /**
     * Set contained within constraint
     * @param containedWithin Place ID that should contain results
     * @return GeoQuery with containment constraint
     */
    GeoQuery containedWithin(String containedWithin);
    
    /**
     * Set street address for more precise matching
     * @param streetAddress Street address
     * @return GeoQuery with address constraint
     */
    GeoQuery streetAddress(String streetAddress);
    
    /**
     * Predefined accuracy levels
     */
    enum Accuracy {
        /** Point of interest level */
        poi,
        /** Neighborhood level */
        neighborhood,
        /** City level */
        city,
        /** Administrative level */
        admin,
        /** Country level */
        country
    }
}

GeoLocation Class

Represent geographic coordinates.

class GeoLocation {
    /**
     * Create location with latitude and longitude
     * @param latitude Latitude in decimal degrees
     * @param longitude Longitude in decimal degrees
     */
    GeoLocation(double latitude, double longitude);
    
    /**
     * Get latitude
     * @return Latitude in decimal degrees
     */
    double getLatitude();
    
    /**
     * Get longitude
     * @return Longitude in decimal degrees
     */
    double getLongitude();
    
    /**
     * Calculate distance to another location
     * @param other Other location
     * @return Distance in kilometers
     */
    double distanceTo(GeoLocation other);
    
    /**
     * Get string representation in "lat,lon" format
     */
    @Override
    String toString();
}

Geographic Query Examples:

// Search for coffee shops in New York
GeoQuery coffeeQuery = GeoQuery.of("coffee")
    .containedWithin("01a9a39529b27f36") // New York City place ID
    .granularity("poi")
    .maxResults(20);
    
ResponseList<Place> coffeeShops = v1.placesGeo().searchPlaces(coffeeQuery);

// Find neighborhoods within 2km of coordinates
GeoLocation myLocation = new GeoLocation(40.7128, -74.0060);
GeoQuery neighborhoodQuery = GeoQuery.of(myLocation)
    .accuracy("2km")
    .granularity("neighborhood");
    
ResponseList<Place> neighborhoods = v1.placesGeo().reverseGeoCode(neighborhoodQuery);

// Search for places with specific address
GeoQuery addressQuery = GeoQuery.of("Twitter HQ")
    .streetAddress("1355 Market St, San Francisco, CA")
    .granularity("poi");
    
ResponseList<Place> locations = v1.placesGeo().searchPlaces(addressQuery);

Place Data Model

Place Interface

Complete place information and geographic metadata.

interface Place extends TwitterResponse {
    /**
     * Unique place identifier
     */
    String getId();
    
    /**
     * Place name
     */
    String getName();
    
    /**
     * Full place name (includes parent places)
     */
    String getFullName();
    
    /**
     * Country where place is located
     */
    String getCountry();
    
    /**
     * Country code (ISO 3166-1 alpha-2)
     */
    String getCountryCode();
    
    /**
     * Place type ("poi", "neighborhood", "city", "admin", "country")
     */
    String getPlaceType();
    
    /**
     * URL for place information
     */
    String getURL();
    
    /**
     * Geographic bounding box for place
     * @return Array of coordinate pairs defining the bounding box
     */
    GeoLocation[][] getBoundingBoxCoordinates();
    
    /**
     * Bounding box type (usually "Polygon")
     */
    String getBoundingBoxType();
    
    /**
     * Places that contain this place
     * @return Array of parent/containing places
     */
    Place[] getContainedWithin();
    
    /**
     * Additional place attributes
     * @return Map of attribute keys to values
     */
    Map<String, String> getAttributes();
    
    /**
     * Street address (if available)
     */
    String getStreetAddress();
    
    /**
     * Locality/city name
     */
    String getLocality();
    
    /**
     * Administrative region (state/province)
     */
    String getRegion();
    
    /**
     * ISO country code
     */
    String getIso3();
    
    /**
     * Postal code
     */
    String getPostalCode();
    
    /**
     * Phone number (if available)
     */
    String getPhone();
    
    /**
     * Twitter handle (if place has associated account)
     */
    String getTwitter();
    
    /**
     * App ID that created this place (if applicable)
     */
    String getAppId();
}

Location-based Tweet Operations

Geotagging Tweets

Add location information to tweets.

// Create status update with location
GeoLocation tweetLocation = new GeoLocation(37.7749, -122.4194);
StatusUpdate statusWithLocation = StatusUpdate.of("Tweeting from San Francisco!")
    .location(tweetLocation)
    .displayCoordinates(true)
    .placeId("5a110d312052166f"); // San Francisco place ID
    
Status geoTaggedTweet = v1.tweets().updateStatus(statusWithLocation);

System.out.println("Tweet location: " + geoTaggedTweet.getGeoLocation());
System.out.println("Tweet place: " + geoTaggedTweet.getPlace().getFullName());

Location-based Search

Search for tweets near specific locations.

// Search for tweets near San Francisco
GeoLocation sf = new GeoLocation(37.7749, -122.4194);
String geocode = sf.getLatitude() + "," + sf.getLongitude() + ",10km";

Query locationQuery = Query.of("food")
    .geocode(geocode)
    .count(100);
    
QueryResult results = v1.search().search(locationQuery);

for (Status tweet : results.getTweets()) {
    if (tweet.getGeoLocation() != null) {
        System.out.println("@" + tweet.getUser().getScreenName() + " from " + 
                          tweet.getGeoLocation().toString() + ": " + tweet.getText());
    }
    
    if (tweet.getPlace() != null) {
        System.out.println("Place: " + tweet.getPlace().getFullName());
    }
}

Advanced Geographic Operations

Place Hierarchy Navigation

public class PlaceHierarchy {
    private final TwitterV1 v1;
    
    public List<Place> getPlaceHierarchy(String placeId) throws TwitterException {
        List<Place> hierarchy = new ArrayList<>();
        Place currentPlace = v1.placesGeo().getGeoDetails(placeId);
        
        hierarchy.add(currentPlace);
        
        // Walk up the containment hierarchy
        while (currentPlace.getContainedWithin() != null && 
               currentPlace.getContainedWithin().length > 0) {
            Place parent = currentPlace.getContainedWithin()[0];
            hierarchy.add(parent);
            
            // Get full details for parent
            currentPlace = v1.placesGeo().getGeoDetails(parent.getId());
        }
        
        return hierarchy;
    }
    
    public void printPlaceHierarchy(String placeId) throws TwitterException {
        List<Place> hierarchy = getPlaceHierarchy(placeId);
        
        System.out.println("Place hierarchy (specific to general):");
        for (int i = 0; i < hierarchy.size(); i++) {
            Place place = hierarchy.get(i);
            String indent = "  ".repeat(i);
            System.out.println(indent + place.getName() + " (" + place.getPlaceType() + ")");
        }
    }
}

Geographic Bounding Box Operations

public class GeoBoundingBox {
    
    public static boolean isLocationInPlace(GeoLocation location, Place place) {
        GeoLocation[][] boundingBox = place.getBoundingBoxCoordinates();
        if (boundingBox == null || boundingBox.length == 0) {
            return false;
        }
        
        // Simple bounding box check (assumes rectangular box)
        GeoLocation[] box = boundingBox[0];
        if (box.length < 2) return false;
        
        double minLat = Math.min(box[0].getLatitude(), box[1].getLatitude());
        double maxLat = Math.max(box[0].getLatitude(), box[1].getLatitude());
        double minLon = Math.min(box[0].getLongitude(), box[1].getLongitude());
        double maxLon = Math.max(box[0].getLongitude(), box[1].getLongitude());
        
        return location.getLatitude() >= minLat && location.getLatitude() <= maxLat &&
               location.getLongitude() >= minLon && location.getLongitude() <= maxLon;
    }
    
    public static GeoLocation getBoundingBoxCenter(Place place) {
        GeoLocation[][] boundingBox = place.getBoundingBoxCoordinates();
        if (boundingBox == null || boundingBox.length == 0) {
            return null;
        }
        
        GeoLocation[] box = boundingBox[0];
        if (box.length < 2) return null;
        
        double centerLat = (box[0].getLatitude() + box[1].getLatitude()) / 2;
        double centerLon = (box[0].getLongitude() + box[1].getLongitude()) / 2;
        
        return new GeoLocation(centerLat, centerLon);
    }
}

Location-based Analytics

public class LocationAnalytics {
    private final TwitterV1 v1;
    
    public Map<String, Integer> analyzeTweetsByLocation(String searchQuery, 
                                                       GeoLocation center, 
                                                       String radius) throws TwitterException {
        String geocode = center.getLatitude() + "," + center.getLongitude() + "," + radius;
        
        Query query = Query.of(searchQuery)
            .geocode(geocode)
            .count(100)
            .resultType(Query.ResultType.recent);
            
        QueryResult results = v1.search().search(query);
        Map<String, Integer> locationCounts = new HashMap<>();
        
        for (Status tweet : results.getTweets()) {
            String location = "Unknown";
            
            if (tweet.getPlace() != null) {
                location = tweet.getPlace().getFullName();
            } else if (tweet.getUser().getLocation() != null && 
                      !tweet.getUser().getLocation().trim().isEmpty()) {
                location = tweet.getUser().getLocation();
            }
            
            locationCounts.merge(location, 1, Integer::sum);
        }
        
        return locationCounts.entrySet().stream()
            .sorted(Map.Entry.<String, Integer>comparingByValue().reversed())
            .collect(Collectors.toMap(
                Map.Entry::getKey,
                Map.Entry::getValue,
                (e1, e2) -> e1,
                LinkedHashMap::new
            ));
    }
    
    public List<Place> findPopularPlacesNear(GeoLocation location, String radius) 
            throws TwitterException {
        GeoQuery query = GeoQuery.of(location)
            .accuracy(radius)
            .granularity("poi")
            .maxResults(50);
            
        ResponseList<Place> places = v1.placesGeo().reverseGeoCode(query);
        
        // Sort by some popularity metric (you might need additional data)
        return places.stream()
            .sorted((p1, p2) -> p1.getName().compareTo(p2.getName()))
            .collect(Collectors.toList());
    }
}

Error Handling

Common geographic API errors and handling:

try {
    GeoQuery query = GeoQuery.of("Unknown Place Name");
    ResponseList<Place> places = v1.placesGeo().searchPlaces(query);
    
    if (places.isEmpty()) {
        System.out.println("No places found matching the query");
    }
} catch (TwitterException e) {
    switch (e.getStatusCode()) {
        case 400:
            System.out.println("Invalid geographic query parameters");
            break;
        case 404:
            System.out.println("Place not found");
            break;
        case 429:
            System.out.println("Rate limit exceeded for geo API");
            break;
        default:
            System.out.println("Geo API error: " + e.getMessage());
    }
}

try {
    Place place = v1.placesGeo().getGeoDetails("invalid_place_id");
} catch (TwitterException e) {
    if (e.getStatusCode() == 404) {
        System.out.println("Place ID does not exist");
    }
}

Best Practices

Geographic Data Privacy

  • Always respect user privacy when handling location data
  • Check if users have enabled geotagging before using location info
  • Be aware that precise coordinates may be sensitive information
  • Consider using place-level location instead of exact coordinates

Performance Optimization

  • Cache place lookups to avoid repeated API calls
  • Use appropriate granularity levels for your use case
  • Batch geographic queries when possible
  • Consider using bounding boxes for area-based searches

Data Quality

  • Validate coordinates before making API calls
  • Handle cases where geographic data may be incomplete
  • Cross-reference place data with user-provided location strings
  • Be prepared for varying levels of geographic precision

Install with Tessl CLI

npx tessl i tessl/maven-org-twitter4j--twitter4j-core

docs

core-auth.md

direct-messages.md

favorites.md

index.md

lists.md

places.md

search.md

streaming.md

timelines.md

tweets.md

users.md

tile.json