package com.limegroup.gnutella.settings;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import java.util.StringTokenizer;
import com.limegroup.gnutella.util.FileUtils;
/**
* Class for an Array of Files setting.
*/
public class FileArraySetting extends Setting {
private File[] value;
/**
* Creates a new <tt>FileArraySetting</tt> instance with the specified
* key and default value.
*
* @param key the constant key to use for the setting
* @param defaultInt the default value to use for the setting
*/
FileArraySetting(Properties defaultProps, Properties props, String key,
File[] defaultValue) {
this(defaultProps, props, key, defaultValue, null);
}
FileArraySetting(Properties defaultProps, Properties props, String key,
File[] defaultValue, String simppKey) {
super(defaultProps, props, key, decode(defaultValue), simppKey);
setPrivate(true);
}
/**
* Accessor for the value of this setting.
*
* @return the value of this setting
*/
public File[] getValue() {
return value;
}
/**
* Mutator for this setting.
*
* @param value the value to store
*/
public synchronized void setValue(File[] value) {
super.setValue(decode(value));
}
/**
* Mutator for this setting.
*
* @param Adds file to the array.
*/
public synchronized void add(File file) {
if (file == null)
return;
File[] newValue = new File[value.length+1];
System.arraycopy(value, 0, newValue, 0, value.length);
newValue[value.length] = file;
setValue(newValue);
}
/**
* Mutator for this setting.
*
* @param Remove file from the array, if it exists.
* @return false when the array does not contain the file or when the
* file is <code>null</code>
*/
public synchronized boolean remove(File file) {
if (file == null)
return false;
int index = indexOf(file);
if (index == -1) {
return false;
}
File[] newValue = new File[value.length-1];
// copy first half, up to first occurrence's index
System.arraycopy(value, 0, newValue, 0, index);
// copy second half, for the length of the rest of the array
System.arraycopy(value, index+1, newValue, index, value.length - index - 1);
setValue(newValue);
return true;
}
/**
* Returns true if the given file is contained in this array.
*/
public synchronized boolean contains(File file) {
return indexOf(file) >= 0;
}
/**
* Returns the index of the given file in this array, -1 if file is not found.
*/
public synchronized int indexOf(File file) {
if (file == null)
return -1;
List list = Arrays.asList(value);
Iterator it = list.iterator();
for (int i = 0; it.hasNext(); i++) {
try {
if ((FileUtils.getCanonicalFile((File)it.next())).equals(FileUtils.getCanonicalFile(file)))
return i;
} catch(IOException ioe) {
continue;
}
}
return -1;
}
/**
* Returns the length of the array.
*/
public synchronized int length() {
return value.length;
}
/** Load value from property string value
* @param sValue property string value
*
*/
protected synchronized void loadValue(String sValue) {
value = encode(sValue);
}
/**
* Splits the string into an Array
*/
private static final File[] encode(String src) {
if (src == null || src.length()==0) {
return (new File[0]);
}
StringTokenizer tokenizer = new StringTokenizer(src, ";");
File[] dirs = new File[tokenizer.countTokens()];
for(int i = 0; i < dirs.length; i++) {
dirs[i] = new File(tokenizer.nextToken());
}
return dirs;
}
/**
* Separates each field of the array by a semicolon
*/
private static final String decode(File[] src) {
if (src == null || src.length==0) {
return "";
}
StringBuffer buffer = new StringBuffer();
for(int i = 0; i < src.length; i++) {
buffer.append(src[i].getAbsolutePath());
if (i < src.length-1)
buffer.append(';');
}
return buffer.toString();
}
/**
* Removes non-existent members from this.
*/
public synchronized void clean() {
List list = new LinkedList();
File file = null;
for (int i = 0; i < value.length; i++) {
file = value[i];
if (file == null)
continue;
if (!file.exists())
continue;
list.add(file);
}
setValue((File[])list.toArray(new File[0]));
}
}