All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.openimaj.picslurper.DatabaseStatusFeeder Maven / Gradle / Ivy

/**
 *
 */
package org.openimaj.picslurper;

import java.io.IOException;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;

import twitter4j.GeoLocation;
import twitter4j.HashtagEntity;
import twitter4j.MediaEntity;
import twitter4j.Place;
import twitter4j.RateLimitStatus;
import twitter4j.Status;
import twitter4j.URLEntity;
import twitter4j.User;
import twitter4j.UserMentionEntity;

import com.mysql.jdbc.Connection;

/**
 *	This class is a status feeder for picslurper that takes statuses from a database.
 *	The default database driver is the MySQL driver and expects a mysql URL in the constructor;
 *	e.g.
 *		jdbc:mysql://localhost/database
 *	

* The class connects to the database lazily (that is, only when the feed is started), so the * driver can be changed after construction using {@link #setDriver(String)}. *

* The schema of the table must include at least two columns: one that contains the tweet text * and one that contains the created time. The default column names are expected to be * text and created_at respectively. These can be changed by passing * in a map, where the key is the expected column name and the value is the actual column name; * e.g. text -> tweet_text *

* The results are paged through in steps of 25 by default, so the database must support the * LIMIT command. * * @author David Dupplaw ([email protected]) * @created 18 Sep 2013 */ public class DatabaseStatusFeeder implements StatusFeeder { protected static class DatabaseFeederStatus implements Status { private final XMLGregorianCalendar cal; private final String text; public DatabaseFeederStatus( final String text, final XMLGregorianCalendar cal ) { this.text = text; this.cal = cal; } /** */ private static final long serialVersionUID = 1L; @Override public int compareTo( final Status o ) { return 0; } @Override public RateLimitStatus getRateLimitStatus() { return null; } @Override public int getAccessLevel() { return 0; } @Override public UserMentionEntity[] getUserMentionEntities() { return null; } @Override public URLEntity[] getURLEntities() { return null; } @Override public HashtagEntity[] getHashtagEntities() { return null; } @Override public MediaEntity[] getMediaEntities() { return null; } @Override public Date getCreatedAt() { return this.cal.toGregorianCalendar().getTime(); } @Override public long getId() { return 0; } @Override public String getText() { return this.text; } @Override public String getSource() { return null; } @Override public boolean isTruncated() { return false; } @Override public long getInReplyToStatusId() { return 0; } @Override public long getInReplyToUserId() { return 0; } @Override public String getInReplyToScreenName() { return null; } @Override public GeoLocation getGeoLocation() { return null; } @Override public Place getPlace() { return null; } @Override public boolean isFavorited() { return false; } @Override public User getUser() { return null; } @Override public boolean isRetweet() { return false; } @Override public Status getRetweetedStatus() { return null; } @Override public long[] getContributors() { return null; } @Override public long getRetweetCount() { return 0; } @Override public boolean isRetweetedByMe() { return false; } @Override public long getCurrentUserRetweetId() { return 0; } @Override public boolean isPossiblySensitive() { return false; } } /** The map of column names */ private Map columnNames = new HashMap(); /** The username to connect to the database */ private final String username; /** The password to connect to the database */ private final String password; /** The database table where the tweets are stored */ private final String table; /** The database connection that is created */ private Connection connection; /** The URL to the database */ private final String url; /** The database driver to use */ private String databaseDriver = "com.mysql.jdbc.Driver"; /** The size of each page of results to retrieve from the database */ private final int pageSize = 25; /** * Create a database status feeder using the database, table, * username and password provided. * * @param databaseURL The URL to the database * @param table The table to use * @param username The user name * @param password The password */ public DatabaseStatusFeeder( final String databaseURL, final String table, final String username, final String password ) { this.url = databaseURL; this.table = table; this.username = username; this.password = password; } /** * Create a database status feeder using the database, table, * username and password provided with the given column mapping * * @param databaseURL The URL to the database * @param table The table to use * @param username The user name * @param password The password * @param columnNames The column mapping */ public DatabaseStatusFeeder( final String databaseURL, final String table, final String username, final String password, final Map columnNames ) { this( databaseURL, table, username, password ); this.columnNames = columnNames; } /** * Create a connection using the given driver for the given database. * * @param driver The driver * @param url The URL to the database * @param username The username * @param password The password * @return The database connection * @throws ClassNotFoundException If the driver cannot be found * @throws SQLException If the connection could not be created */ private static Connection createConnection( final String driver, final String url, final String username, final String password ) throws ClassNotFoundException, SQLException { Class.forName(driver); if( username == null || password == null || username.trim().length() == 0 || password.trim().length() == 0 ) return (Connection) DriverManager.getConnection( url ); else return (Connection) DriverManager.getConnection( url, username, password ); } /** * {@inheritDoc} * @see org.openimaj.picslurper.StatusFeeder#feedStatus(org.openimaj.picslurper.PicSlurper) */ @Override public void feedStatus( final PicSlurper slurper ) throws IOException { try { // Create the connection to the database this.connection = DatabaseStatusFeeder.createConnection( this.databaseDriver, this.url, this.username, this.password ); // Create a scrolling result set type final Statement s = this.connection.createStatement( ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY ); s.setFetchSize( this.pageSize ); s.setMaxRows( this.pageSize ); // First count how many rows there are so we know how many // pages there will be. String sql = "SELECT COUNT(*) FROM "+this.table; ResultSet r = s.executeQuery( sql ); r.next(); final int rows = r.getInt( 1 ); final int pages = (int)Math.ceil(rows/(double)this.pageSize); for( int pageNumber = 1; pageNumber <= pages; pageNumber++ ) { sql = "SELECT "+ this.getColumn("created_at",true)+", "+ this.getColumn("text",true)+ " from "+this.table+ " LIMIT "+(pageNumber*this.pageSize) +","+this.pageSize; r = s.executeQuery( sql ); // Read the results sets while( r.next() ) { try { final String createdAt = r.getString(1); final XMLGregorianCalendar cal = DatatypeFactory.newInstance() .newXMLGregorianCalendar(createdAt); final String text = r.getString(2); final DatabaseFeederStatus status = new DatabaseFeederStatus( text, cal ); slurper.handleStatus( status ); } catch( final DatatypeConfigurationException e ) { e.printStackTrace(); } } } } catch( final ClassNotFoundException e ) { e.printStackTrace(); } catch( final SQLException e ) { e.printStackTrace(); } } /** * Get a column name through the column name mapping, if one exists. * @param defaultName The name to look up * @param tf Whether to enclose in back-ticks * @return The column name to use */ private String getColumn( final String defaultName, final boolean tf ) { if( this.columnNames.get(defaultName) != null ) return tf ? "`"+this.columnNames.get(defaultName)+"`" : this.columnNames.get(defaultName); return tf ? "`"+defaultName+"`" : defaultName; } /** * Set the database driver to use. * @param driverName The driver name. */ public void setDriver( final String driverName ) { this.databaseDriver = driverName; } /** * @param args */ public static void main( final String[] args ) { try { // Connect to local database final DatabaseStatusFeeder dbsf = new DatabaseStatusFeeder( "jdbc:mysql://localhost:3306/swr", "tweets", "swr", "swr" ); final PicSlurper ps = new PicSlurper(); dbsf.feedStatus( ps ); } catch( final IOException e ) { e.printStackTrace(); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy