package com.pugh.sockso.web; import com.pugh.sockso.Constants; import com.pugh.sockso.Properties; import com.pugh.sockso.Utils; import com.pugh.sockso.db.Database; import com.pugh.sockso.music.Track; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * This object wraps a request for some tracks and allows a central way of * resolving track queries. * */ public class TracksRequest { private final Request req; private final Database db; private final Properties p; public TracksRequest( final Request req, final Database db, final Properties p ) { this.req = req; this.db = db; this.p = p; } /** * Returns any requested tracks from URL params, or a path argument. * * @return * * @throws SQLException * @throws BadRequestException * */ public Track[] getRequestedTracks() throws SQLException, BadRequestException { final List<Track> allTracks = new ArrayList<Track>(); final List<Track> urlParamTracks = getUrlParamTracks(); final List<Track> pathTracks = getPathTracks(); allTracks.addAll( urlParamTracks ); allTracks.addAll( pathTracks ); if ( isRandomRequest() ) { Collections.shuffle( allTracks ); } return allTracks.toArray( new Track[] {} ); } /** * returns a where clause filtering tracks by the file types specified * by the trackType argument from the request. if no filter was specified * then the empty string is returned (ie. no filter) * * @return where sql filter if any was specified, empty string otherwise * */ protected String getTrackTypeSqlFilter() { final StringBuffer filterBuffer = new StringBuffer( "" ); final String trackTypes = req.getArgument( "trackType" ); // track types can be a commer seperated string of file types for ( final String type : trackTypes.split(",") ) { if ( !type.equals("") ) { final int length = type.length(); filterBuffer.append(" and lower(substr(t.path,length(t.path)-") .append(length - 1) .append(",") .append(length) .append(")) = '") .append(type).append("' "); } } final String filter = filterBuffer.toString(); return filter.equals( "" ) ? "" : " where " + filter.substring( 4 ); } /** * Returns a random array of Track objects from the collection. The number * of tracks returned is specified by the Constants.WWW_RANDOM_TRACK_LIMIT * property. * * @return * * @throws java.sql.SQLException * */ public Track[] getRandomTracks() throws SQLException { final String limit = p.get( Constants.WWW_RANDOM_TRACK_LIMIT, "100" ); final String sql = Track.getSelectFromSql() + getTrackTypeSqlFilter() + " order by " +db.getRandomFunction()+ "() " + " limit ? "; PreparedStatement st = null; try { st = db.prepare( sql ); st.setInt( 1, Integer.parseInt(limit) ); return Track.createListFromResultSet( st.executeQuery() ) .toArray( new Track[] {} ); } finally { Utils.close( st ); } } /** * Returns tracks specified via play args in the request resource * * @return * * @throws SQLException * @throws BadRequestException * */ protected List<Track> getUrlParamTracks() throws SQLException, BadRequestException { final String orderBySql = isRandomRequest() ? " order by " +db.getRandomFunction()+ "() " : ""; final List<Track> tracks = Track.getTracksFromPlayArgs( db, getUrlParams(), orderBySql ); return tracks; } /** * Indicates if the request is for a random ordering of tracks * * @return * */ protected boolean isRandomRequest() { return req.getArgument( "orderBy" ).equals( "random" ); } /** * Returns any tracks specified by the "folder=XXX" parameter * * @return * */ protected List<Track> getPathTracks() throws SQLException { if ( Utils.isFeatureEnabled(p,Constants.WWW_BROWSE_FOLDERS_ENABLED) ) { final String path = req.getArgument( "path" ); if ( path.length() > 0 ) { return Track.getTracksFromPath( db, path ); } } return new ArrayList<Track>(); } /** * Returns and parameters from the resource part of the request URL that * look like play parameters (eg. tr123) * * @return * */ protected String[] getUrlParams() { final ArrayList<String> params = new ArrayList<String>(); final int paramCount = req.getParamCount(); for ( int i=0; i<paramCount; i++ ) { final String param = req.getUrlParam( i ); if ( param.matches("(tr|al|ar|pl)\\d+") ) { params.add( param ); } } return params.toArray( new String[] {} ); } }