blob: 76b9b286c1612975ec7c9aafc437c5086995b30b [file] [log] [blame]
/*
* Copyright (C) 2010 The Android Open Source Project
*
* 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 com.android.tradefed.config;
import java.lang.reflect.Field;
import java.util.Collection; // imported for javadoc
import java.util.Map; // imported for javadoc
/**
* Controls the behavior when an option is specified multiple times. Note that this enum assumes
* that the values to be set are not {@link Collection}s or {@link Map}s.
*/
public enum OptionUpdateRule {
/** once an option is set, subsequent attempts to update it should be ignored. */
FIRST {
@Override
boolean shouldUpdate(String optionName, Object current, Object update)
throws ConfigurationException {
return current == null;
}
},
/** if an option is set multiple times, ignore all but the last value. */
LAST {
@Override
boolean shouldUpdate(String optionName, Object current, Object update)
throws ConfigurationException {
return true;
}
},
/** for {@link Comparable} options, keep the one that compares as the greatest. */
GREATEST {
@Override
boolean shouldUpdate(String optionName, Object current, Object update)
throws ConfigurationException {
return current == null || compare(optionName, current, update) < 0;
}
},
/** for {@link Comparable} options, keep the one that compares as the least. */
LEAST {
@Override
boolean shouldUpdate(String optionName, Object current, Object update)
throws ConfigurationException {
return current == null || compare(optionName, current, update) > 0;
}
},
/** throw a {@link ConfigurationException} if this option is set more than once. */
IMMUTABLE {
@Override
boolean shouldUpdate(String optionName, Object current, Object update)
throws ConfigurationException {
if (current != null) {
throw new ConfigurationException(String.format(
"Attempted to update immutable value (%s) for option \"%s\"", optionName,
optionName));
}
return true;
}
};
abstract boolean shouldUpdate(String optionName, Object current, Object update)
throws ConfigurationException;
/**
* Takes the current value and the update value, and returns whether the value should be
* updated. Assumes that <code>update</code> is never null.
*/
public boolean shouldUpdate(String optionName, Object optionSource, Field field, Object update)
throws ConfigurationException {
Object current;
try {
current = field.get(optionSource);
} catch (IllegalAccessException e) {
throw new ConfigurationException(String.format(
"internal error when setting option '%s'", optionName), e);
}
return shouldUpdate(optionName, current, update);
}
/**
* Check if the objects are {@link Comparable}, and if so, compare them using
* {@see Comparable#compareTo}.
*/
@SuppressWarnings({"unchecked", "rawtypes"})
private static int compare(String optionName, Object current, Object update)
throws ConfigurationException {
Comparable compCurrent;
if (current instanceof Comparable) {
compCurrent = (Comparable) current;
} else {
throw new ConfigurationException(String.format(
"internal error: Class %s for option %s was used with GREATEST or LEAST " +
"updateRule, but does not implement Comparable.",
current.getClass().getSimpleName(), optionName));
}
try {
return compCurrent.compareTo(update);
} catch (ClassCastException e) {
throw new ConfigurationException(String.format(
"internal error: Failed to compare %s (%s) and %s (%s)",
current.getClass().getName(), current, update.getClass().getName(), update), e);
}
}
}