package com.limegroup.gnutella.gui.search;
import java.util.MissingResourceException;
import com.limegroup.gnutella.gui.GUIMediator;
import com.limegroup.gnutella.gui.xml.XMLUtils;
import com.limegroup.gnutella.util.StringUtils;
/**
* Represents a single selector.
*/
class Selector {
/**
* A SCHEMA selector.
*/
public static final int SCHEMA = 1;
/**
* A FIELD selector.
*/
public static final int FIELD = 2;
/**
* A PROPERTY selector.
*/
public static final int PROPERTY = 3;
/**
* The value for the selector if it represents listing all schemas.
*/
private static final String S_SCHEMA = "schema";
/**
* The value for the selector if it represents a specific field within
* a schema.
*/
private static final String S_FIELD = "field";
/**
* The value for the selector if it represents a property, such as
* "extension", "quality", "speed", etc.
*/
private static final String S_PROPERTY = "property";
/**
* The schema of this selector.
*/
private final String _SCHEMA;
/**
* The value of this selector.
*/
private final String _VALUE;
/**
* The type of this selector.
*/
private final int _TYPE;
/**
* Whether or not this selector is minimized.
*/
private boolean _minimized = false;
/**
* Stores the once computed hash code of this selector. This works as long
* as the Selector class stays immutable, as it is now.
*/
private int cachedHashCode;
/**
* Constructs a new selector.
*/
private Selector(String schema, String value, int type) {
this._SCHEMA = schema;
this._VALUE = value;
this._TYPE = type;
}
/**
* Creates a new schema selector.
*/
public static Selector createSchemaSelector() {
return new Selector("", "", SCHEMA);
}
/**
* Creates a new selector for the specified field within a schema.
*/
public static Selector createFieldSelector(String schema, String field) {
return new Selector(schema, field, FIELD);
}
/**
* Creates a new selector for the specified property.
*/
public static Selector createPropertySelector(String property) {
return new Selector("", property, PROPERTY);
}
/**
* Creates a selector from a string.
*
* Valid strings are:
* schema | <true|false>
* field, <schema>, <value> | <true|false>
* property, <value> | <true|false>
*
* All other strings will throw an IllegalArgumentException
*/
public static Selector createFromString(String value) {
if(value == null)
throw new IllegalArgumentException("null value");
value = value.toLowerCase();
String left, right;
int pipe = value.indexOf("|");
if(pipe == -1 || pipe == value.length()) {
left = value.trim();
right = "";
} else {
left = value.substring(0, pipe).trim();
right = value.substring(pipe+1).trim();
}
String[] data = StringUtils.split(left, ",");
if(data.length == 0)
throw new IllegalArgumentException(value);
for(int i = 0; i < data.length; i++)
data[i] = data[i].trim();
Selector selector;
// First parse the 'data'
if(S_SCHEMA.equals(data[0])) {
selector = createSchemaSelector();
// must have nothing else
if(data.length != 1)
throw new IllegalArgumentException(value);
} else if(S_FIELD.equals(data[0])) {
// Must have schema & value
if(data.length != 3)
throw new IllegalArgumentException(value);
String schema = data[1];
String info = data[2];
selector = createFieldSelector(schema, info);
} else if(S_PROPERTY.equals(data[0])) {
// must have value.
if(data.length != 2)
throw new IllegalArgumentException(value);
String info = data[1].toUpperCase();
selector = createPropertySelector(info);
} else {
throw new IllegalArgumentException(value);
}
// Then process the additional fields
data = StringUtils.split(right, ",");
for(int i = 0; i < data.length; i++)
data[i] = data[i].trim();
if(data.length > 0)
selector.setMinimized(data[0].equals("true"));
// as more fields are added, process them here, ala:
// if(data.length > 1)
// selector.setNewData(data[1].equals("data"));
return selector;
}
/**
* Writes the selector out in the specified format.
*/
public String toString() {
String value;
switch(_TYPE) {
case SCHEMA: value = S_SCHEMA; break;
case FIELD: value = S_FIELD + ", " + _SCHEMA + ", " + _VALUE; break;
case PROPERTY: value = S_PROPERTY + ", " + _VALUE; break;
default:
throw new IllegalStateException("invalid type: " + _TYPE);
}
return value + " | " + _minimized;
}
/**
* Determines if this is minimized.
*/
public boolean isMinimized() {
return _minimized;
}
/**
* Sets the minimized status.
*/
public void setMinimized(boolean minimized) {
_minimized = minimized;
}
/**
* Determines the title of this selector.
*
* TODO: Move somewhere else? Don't want to have dependencies...
*/
public String getTitle() {
switch(_TYPE) {
case Selector.SCHEMA:
return GUIMediator.getStringResource("SEARCH_FILTER_MEDIA");
case Selector.FIELD:
return XMLUtils.getResource(_VALUE);
case Selector.PROPERTY:
try {
return GUIMediator.getStringResource(_VALUE);
} catch(MissingResourceException mse) {
return _VALUE;
}
default:
throw new IllegalArgumentException("invalid type: " + _TYPE);
}
}
/**
* Determines if this is a schema selector.
*/
public boolean isSchemaSelector() {
return _TYPE == SCHEMA;
}
/**
* Determines if this is a field selector.
*/
public boolean isFieldSelector() {
return _TYPE == FIELD;
}
/**
* Determines if this is a property selector.
*/
public boolean isPropertySelector() {
return _TYPE == PROPERTY;
}
/**
* Determines the type of selector.
*/
public int getSelectorType() {
return _TYPE;
}
/**
* Determines the schema of this selector. Only valid
* if the type is a field.
*/
public String getSchema() {
if(_TYPE != FIELD)
throw new IllegalStateException("invalid type: " + _TYPE);
return _SCHEMA;
}
/**
* Determines the value of this schema. Only valid if the type
* is a field or property.
*/
public String getValue() {
if(_TYPE != FIELD && _TYPE != PROPERTY)
throw new IllegalStateException("invalid type: " + _TYPE);
return _VALUE;
}
/**
* Determines whether or not the specified selector is the same as this one.
*/
public boolean equals(Object o) {
if(o == this)
return true;
if(o instanceof Selector) {
Selector f = (Selector)o;
return f._TYPE == _TYPE &&
f._SCHEMA.equals(_SCHEMA) &&
f._VALUE.equals(_VALUE);
} else {
return false;
}
}
/**
* Returns the hash code of this object.
*/
public int hashCode() {
if (cachedHashCode == 0) {
cachedHashCode = _TYPE + 31 * _SCHEMA.hashCode() + 31 * 31 * _VALUE.hashCode();
}
return cachedHashCode;
}
}