package org.jboss.as.logging.logmanager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.jboss.logmanager.config.PropertyConfigurable;
import org.jboss.logmanager.config.ValueExpression;
/**
* An interfaced used to determine if properties should be resorted and if so sort them.
* <p/>
* This is useful when certain properties need to be configured before others. For example a {@code FileHandler} may
* allow for an {@code append} property that needs to be set before the file is set.
*
* @author <a href="mailto:jperkins@redhat.com">James R. Perkins</a>
*/
public interface PropertySorter {
/**
* Checks the properties and returns {@code true} if the properties should be sorted by invoking {@link
* #sort(org.jboss.logmanager.config.PropertyConfigurable)}, otherwise {@code false}.
*
* @param configurable the configurable to check
*
* @return {@code true} if the properties should be sorted, otherwise {@code false}
*/
boolean isReorderRequired(PropertyConfigurable configurable);
/**
* Sorts the properties.
*
* @param configurable the configurable to sort the properties on
*/
void sort(PropertyConfigurable configurable);
/**
* A default no-op sorter that always returns {@code false} on the {@link #isReorderRequired(org.jboss.logmanager.config.PropertyConfigurable)}
* method. The {@link #sort(org.jboss.logmanager.config.PropertyConfigurable)} does nothing.
*/
PropertySorter NO_OP = new PropertySorter() {
@Override
public boolean isReorderRequired(final PropertyConfigurable configurable) {
return false;
}
@Override
public void sort(final PropertyConfigurable configurable) {
}
};
/**
* A default configurator that uses a {@link Comparator comparator} to determine whether the properties should be
* sorted and the sort order.
* <p/>
* <i>Note: In most cases the {@link Comparator comparator} will impose orderings consistent with equals which is
* acceptable usage for this sorter</i>
*/
public static class DefaultPropertySorter implements PropertySorter {
private final Comparator<String> comparator;
public DefaultPropertySorter(final Comparator<String> comparator) {
this.comparator = comparator;
}
@Override
public boolean isReorderRequired(final PropertyConfigurable configurable) {
// Get the current property names
final List<String> names = configurable.getPropertyNames();
final List<String> sortedNames = new ArrayList<String>(names);
Collections.sort(sortedNames, comparator);
return !names.equals(sortedNames);
}
@Override
public void sort(final PropertyConfigurable configurable) {
final List<String> sortedNames = new ArrayList<String>(configurable.getPropertyNames());
Collections.sort(sortedNames, comparator);
final Map<String, ValueExpression<String>> orderedValues = new LinkedHashMap<String, ValueExpression<String>>(sortedNames.size());
// The properties need to be reordered
for (String name : sortedNames) {
orderedValues.put(name, configurable.getPropertyValueExpression(name));
// Remove the value
configurable.removeProperty(name);
}
// All values should be removed and now need to be added back
for (String name : orderedValues.keySet()) {
final ValueExpression<String> value = orderedValues.get(name);
configurable.setPropertyValueExpression(name, value.getValue());
}
}
}
}