/*******************************************************************************
* Copyright 2012 Geoscience Australia
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package au.gov.ga.earthsci.worldwind.common.layers.styled;
import gov.nasa.worldwind.avlist.AVList;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Pattern;
/**
* An attribute represents a column in tabular data. It could be an attribute
* within a shapefile DBF file, a column in a CSV file, etc. It allows matching
* of attribute values to an associated {@link Style} name, using exact
* matching, regex matching, and in-range matching.
*
* @author Michael de Hoog (michael.dehoog@ga.gov.au)
*/
public class Attribute
{
protected String name;
protected Map<String, String> switches = new HashMap<String, String>();
protected Map<String, String> regexes = new HashMap<String, String>();
protected Map<Range, String> ranges = new HashMap<Range, String>();
protected StringWithPlaceholder textString;
protected StringWithPlaceholder linkString;
/**
* Create a new attribute.
*
* @param name
* Name of the attribute
*/
public Attribute(String name)
{
setName(name);
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
/**
* Add an exact match case.
*
* @param value
* Attribute value to match
* @param style
* Style to return if match is found
*/
public void addCase(String value, String style)
{
switches.put(value, style);
}
/**
* Add a regular expression match case.
*
* @param regex
* Regular expression pattern
* @param style
* Style to return if the attribute value matches the regex
*/
public void addRegex(String regex, String style)
{
regexes.put(regex, style);
}
/**
* Add a in-range match case.
*
* @param min
* Minimum for the attribute value (inclusive)
* @param max
* Maximum for the attribute value (inclusive)
* @param style
* Style to return if the value is in range
*/
public void addRange(double min, double max, String style)
{
Range range = new Range();
range.min = min;
range.max = max;
ranges.put(range, style);
}
/**
* Make this attribute contribute to the text of the object.
*
* @param value
* Text to append
* @param placeholder
* Text in <code>value</code> to replace with the attribute value
*/
public void addText(String value, String placeholder)
{
textString = new StringWithPlaceholder(value, placeholder);
}
/**
* This attribute will be used to create the object's link.
*
* @param url
* URL link
* @param placeholder
* Text in <code>url</code> to replace with the attribute value
*/
public void addLink(String url, String placeholder)
{
linkString = new StringWithPlaceholder(url, placeholder);
}
/**
* Create the text contributed by this attribute, using the attribute value
* in the provided {@link AVList}.
*
* @param attributeValues
* Attribute values to replace any text placeholders with
* @return
*/
public String getText(AVList attributeValues)
{
return getPlaceholderString(textString, attributeValues);
}
/**
* Create the link for this attribute, using the attribute value in the
* provided {@link AVList}.
*
* @param attributeValues
* Attribute values to replace any link placeholders with
* @return
*/
public String getLink(AVList attributeValues)
{
return getPlaceholderString(linkString, attributeValues);
}
protected String getPlaceholderString(StringWithPlaceholder string, AVList attributeValues)
{
if (string == null || attributeValues.getValue(name) == null)
return null;
String stringValue = attributeValues.getValue(name).toString();
return string.replacePlaceholder(stringValue);
}
/**
* Find a matching {@link Style} string for the provided attributes.
*
* @param attributeValues
* Attribute values to use when searching for matching cases
* @return
*/
public String getMatchingStyle(AVList attributeValues)
{
if (attributeValues.getValue(name) == null)
return null;
String stringValue = attributeValues.getValue(name).toString();
if (switches.containsKey(stringValue))
return switches.get(stringValue);
for (Entry<String, String> regex : regexes.entrySet())
{
if (Pattern.matches(regex.getKey(), stringValue))
return regex.getValue();
}
Double doubleValue = null;
try
{
doubleValue = Double.valueOf(stringValue);
}
catch (Exception e)
{
}
if (doubleValue != null)
{
for (Entry<Range, String> range : ranges.entrySet())
{
if (range.getKey().contains(doubleValue))
return range.getValue();
}
}
return null;
}
/**
* Helper class for storing and testing a double range.
*/
protected class Range
{
public double min;
public double max;
public boolean contains(double value)
{
return min <= value && value <= max;
}
}
/**
* Helper class for storing a string/placeholder pair.
*/
protected class StringWithPlaceholder
{
public final String string;
public final String placeholder;
public StringWithPlaceholder(String string, String placeholder)
{
this.string = string;
this.placeholder = placeholder;
}
public String replacePlaceholder(String with)
{
return string.replaceAll(placeholder, with);
}
}
}