package com.onaro.util.jfc.tables.filter; import java.net.URL; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.lang3.StringUtils; import com.onaro.util.enumeration.EnumPresentation; import com.onaro.util.jfc.tables.FilterTable; /** * Enumeration based filter. * the patterns can be of either the values (returned from the server) or the 'name' - mapped presentation text configured in the enumeration.properties file. */ public class EnumFilter extends AbstractFilter implements FilterEditorProvider { //when selecting this item in the enum filter combo box, the enum filter is cancelled private static final EnumPresentation.Attributes CLEAR_FILTER_ATTRIBUTE = new EnumPresentation.Attributes("1", Messages.INSTANCE.getAllText()); //$NON-NLS-1$ //when selecting this item in the enum filter combo box, empty and null values will be accepted by the filter private static final EnumPresentation.Attributes EMPTY_FILTER_ATTRIBUTE = new EnumPresentation.Attributes("2", Messages.INSTANCE.getEmptyText()); //$NON-NLS-1$ /** * Holds a list of the possible enumeration values */ private List attributes; /** * Holds an instance of the enum attributes selected as a pattern. If the selected pattern is not an enum and * is one of the values in the table, this field should be null */ private EnumPresentation.Attributes enumPattern = null; /** * Contains all the enums (the other list does not hold enums with the same name and icon */ private Set attributesSet = new HashSet(); public EnumFilter(EnumPresentation.Attributes[] legalAttributes) { Map map = new LinkedHashMap(); for (int i = 0; i < legalAttributes.length; i++) { EnumPresentation.Attributes legalAttribute = legalAttributes[i]; if ((legalAttribute.name == null || legalAttribute.name.length() == 0) && legalAttribute.smallIcon == null) continue; attributesSet.add(legalAttribute); //add also the name of the attribute in lower case to match cases where the actuall name is sent from the server attributesSet.add(legalAttribute.name.toLowerCase()); map.put(new EnumKey(legalAttribute), legalAttribute); } LinkedList list = new LinkedList(map.values()); //sort the attributes according to their value Collections.sort(list, new Comparator() { public int compare(EnumPresentation.Attributes att1, EnumPresentation.Attributes att2) { if (att1.ordinal != null && att2.ordinal != null) { return att1.ordinal.compareTo(att2.ordinal); } return att1.value.compareToIgnoreCase(att2.value); } }); // Including these two enums after the sorting is done guarantees that always you have // "All" and "Empty" at the top of the combo-box. list.addFirst(EMPTY_FILTER_ATTRIBUTE); list.addFirst(CLEAR_FILTER_ATTRIBUTE); attributes = Collections.unmodifiableList(list); } /** * @return the possible enum attributes */ public List getAttributes() { return attributes; } /** * @return a set of all the enum attributes and the attribute names. * This set contains both {@link EnumPresentation.Attributes} and {@link String} objects * including ones with the same name and icon but different value. * */ public Set getAttributesSet() { return attributesSet; } protected void parsePattern() throws FilterException{ //first reset the enum pattern enumPattern = null; if(isActive()){ assert pattern != null: "isactive should check that the pattern is not null"; //$NON-NLS-1$ if (pattern instanceof String){ enumPattern = findAttributeByName((String)pattern); // Special handling of empty string ("") values as EMPTY if (enumPattern == null && StringUtils.isBlank((String)pattern)) { enumPattern = EMPTY_FILTER_ATTRIBUTE; } }else{ enumPattern = (EnumPresentation.Attributes) pattern; } pattern = enumPattern.name; //if the item with the empty string is selected, cancel the filter if(CLEAR_FILTER_ATTRIBUTE.equals(enumPattern)) { pattern = null; } } } /** * Returns an instance of {@link EnumPresentation.Attributes} that matches a passed in * attribute name.

* * This method is used during the loading of a Profile that contains Enum type of filters */ private EnumPresentation.Attributes findAttributeByName(final String attrName){ List attts = getAttributes(); for (EnumPresentation.Attributes attribute : attts) { if (pattern.equals(attribute.name) || pattern.equals(attribute.value)) return attribute; } return null; } /** * Tests if a value is the enum that was defined in the pattern * * @param value the value to test * @return true if the value matches this filter */ public boolean isAccepted(Object value) { assert pattern != null: "this method should not be called if the isActive() is false - pattern==null"; //$NON-NLS-1$ if (enumPattern == EMPTY_FILTER_ATTRIBUTE) { if (value instanceof EnumPresentation.Attributes) { EnumPresentation.Attributes attributes = ((EnumPresentation.Attributes) value); return (attributes.name == null || attributes.name.length() == 0) && attributes.smallIcon == null; } else { return value == null || value.toString().length() == 0; } } else { // pattern is a value from the enumeration (not EMPTY_FILTER_ATTRIBUTE) if (value == null) return false; //if both the pattern and the value are enumeration attributes, compare the name and the icon. else do normal equals(). if (value instanceof EnumPresentation.Attributes) { EnumPresentation.Attributes attributes = ((EnumPresentation.Attributes) value); //some of the different values have the same enumeration name and icon. //make sure that they are all accepted if(enumPattern.name.equals(attributes.name)){ URL iconUrl = enumPattern.smallIconUrl; if(iconUrl != null) { return iconUrl.toString().equals(attributes.smallIconUrl == null ? null : attributes.smallIconUrl.toString()); }else { return attributes.smallIconUrl == null; } } else{ return false; } } else { //try to match the value to the name of the enumPattern, as this is what is displayed return enumPattern.name.equalsIgnoreCase(value.toString()); } } } @Override public String getUsageTooltip() { return(Messages.INSTANCE.getEnumFilterUsageTooltip()); } private static class EnumKey{ private String name; private URL iconUrl; public EnumKey(EnumPresentation.Attributes att) { this.iconUrl = att.smallIconUrl; this.name = att.name; } public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; final EnumKey enumKey = (EnumKey) o; if (iconUrl != null ? !iconUrl.toString().equals(enumKey.iconUrl.toString()) : enumKey.iconUrl != null) return false; if (name != null ? !name.equals(enumKey.name) : enumKey.name != null) return false; return true; } public int hashCode() { int result; result = (name != null ? name.hashCode() : 0); result = 29 * result + (iconUrl != null ? iconUrl.toString().hashCode() : 0); return result; } } public AbstractFilterEditor createEditor(FilterTable table, int selectedColumnInModel) { return new EnumComboBoxFilterEditor(table, this, selectedColumnInModel); } }