/* * Created on 26/09/2005 * Created by Paul Duran * Copyright (C) 2004 Aelitis, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SARL au capital de 30,000 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package org.gudy.azureus2.ui.console.commands; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.gudy.azureus2.core3.download.DownloadManager; import com.aelitis.azureus.core.AzureusCoreException; public class TorrentFilter { private static final Pattern rangePattern = Pattern.compile("([0-9]+)\\s*((-)|(-\\s*([0-9]+)))?"); public TorrentFilter() { super(); } /** * matches a range of torrents. eg: 3-5 or a single torrent. eg: 3. or from 3 onwards: 3- * @param torrents torrents to match * @param filter range expression * @return list of matched DownloadManager objects */ private List matchRange( List torrents, String filter ) { Matcher matcher = rangePattern.matcher(filter); List list = new ArrayList(); if( matcher.matches() ) { int minId = Integer.parseInt(matcher.group(1)); if( minId == 0 ) throw new AzureusCoreException("lower range must be greater than 0"); if( minId > torrents.size() ) throw new AzureusCoreException("lower range specified (" + minId + ") is outside number of torrents (" + torrents.size() + ")"); if( matcher.group(2) == null ) { // received a single number. eg: 3 list.add(torrents.get(minId-1)); return list; } int maxId; if( matcher.group(3) == null ) // received bound range. eg: 3-5 maxId = Integer.parseInt(matcher.group(5)); else // received open ended range. eg: 3- maxId = torrents.size(); if( minId > maxId ) throw new AzureusCoreException("when specifying a range, the max value must be greater than or equal to the min value"); for( int i = (minId-1) ; i < maxId && i < torrents.size() ; i++ ) { list.add(torrents.get(i)); } } return list; } /** * attempst to match a wildcard against the list of torrents by * checking their display name * @param torrents list of available torrents to match * @param filter wildcard (glob) filter * @return list of matched DownloadManager objects */ private List matchWildcard( List torrents, String filter ) { Pattern pattern = Pattern.compile(wildcardToPattern(filter), Pattern.CASE_INSENSITIVE); List list = new ArrayList(); for (Iterator iter = torrents.iterator(); iter.hasNext();) { DownloadManager dm = (DownloadManager) iter.next(); if( pattern.matcher(dm.getDisplayName()).matches() ) list.add(dm); } return list; } /** * converts the wildcard (eg: tran*) into a regular expression - (tran.*) * @param wild wildcard (glob) expression * @return regular expression string */ private String wildcardToPattern(String wild) { if (wild == null) return null; StringBuffer buffer = new StringBuffer(); char[] chars = wild.toCharArray(); for (int i = 0; i < chars.length; ++i) { if (chars[i] == '*') buffer.append(".*"); else if (chars[i] == '?') buffer.append("."); else if ("+()^$.{}[]|\\".indexOf(chars[i]) != -1) buffer.append('\\').append(chars[i]); // prefix all metacharacters // with backslash else buffer.append(chars[i]); } return buffer.toString().toLowerCase(); } /** * tries our two different matching algorithms using the * supplied filter against the list of torrents in the ConsoleInput object * @param torrentsToMatch list of DownloadManager objects to attempt to match against * @param filter filter - eg: range or glob filter * @return list of matched DownloadManager objects */ public List getTorrents(List torrentsToMatch, String filter) { List torrents = new ArrayList(); torrents.addAll(matchRange(torrentsToMatch, filter) ); torrents.addAll(matchWildcard(torrentsToMatch, filter) ); return torrents; } /** * first tries to match torrents by concatenating all of the arguments. * if that doesn't work, attempts to match each argument individually. * @param torrentsToMatch list of DownloadManager objects to attempt to match against * @param args arguments to try to match * @return list of matched DownloadManager objects */ public List getTorrents(List torrentsToMatch, List args) { // first, try to match the whole list concatenated as a string StringBuffer allArgs = new StringBuffer(); boolean first = true; for (Iterator iter = args.iterator(); iter.hasNext();) { if( ! first ) allArgs.append(","); else first = false; allArgs.append(iter.next()); } List torrents; torrents = matchWildcard(torrentsToMatch, allArgs.toString()); if( torrents.size() > 0 ) return torrents; torrents = matchRange(torrentsToMatch, allArgs.toString()); if( torrents.size() > 0 ) return torrents; // if no torrents then handle each argument individually for (Iterator iter = args.iterator(); iter.hasNext();) { torrents.addAll(getTorrents(torrentsToMatch, (String)iter.next()) ); } return torrents; } }