1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.loganalysis.util.config; 18 19 import java.lang.reflect.Field; 20 import java.util.Collection; 21 import java.util.Map; 22 23 /** 24 * Controls the behavior when an option is specified multiple times. Note that this enum assumes 25 * that the values to be set are not {@link Collection}s or {@link Map}s. 26 */ 27 //TODO: Use libTF once this is copied over. 28 public enum OptionUpdateRule { 29 /** once an option is set, subsequent attempts to update it should be ignored. */ 30 FIRST { 31 @Override update(String optionName, Object current, Object update)32 Object update(String optionName, Object current, Object update) 33 throws ConfigurationException { 34 if (current == null) return update; 35 return current; 36 } 37 }, 38 39 /** if an option is set multiple times, ignore all but the last value. */ 40 LAST { 41 @Override update(String optionName, Object current, Object update)42 Object update(String optionName, Object current, Object update) 43 throws ConfigurationException { 44 return update; 45 } 46 }, 47 48 /** for {@link Comparable} options, keep the one that compares as the greatest. */ 49 GREATEST { 50 @Override update(String optionName, Object current, Object update)51 Object update(String optionName, Object current, Object update) 52 throws ConfigurationException { 53 if (current == null) return update; 54 if (compare(optionName, current, update) < 0) { 55 // current < update; so use the update 56 return update; 57 } else { 58 // current >= update; so keep current 59 return current; 60 } 61 } 62 }, 63 64 /** for {@link Comparable} options, keep the one that compares as the least. */ 65 LEAST { 66 @Override update(String optionName, Object current, Object update)67 Object update(String optionName, Object current, Object update) 68 throws ConfigurationException { 69 if (current == null) return update; 70 if (compare(optionName, current, update) > 0) { 71 // current > update; so use the update 72 return update; 73 } else { 74 // current <= update; so keep current 75 return current; 76 } 77 } 78 }, 79 80 /** throw a {@link ConfigurationException} if this option is set more than once. */ 81 IMMUTABLE { 82 @Override update(String optionName, Object current, Object update)83 Object update(String optionName, Object current, Object update) 84 throws ConfigurationException { 85 if (current == null) return update; 86 throw new ConfigurationException(String.format( 87 "Attempted to update immutable value (%s) for option \"%s\"", optionName, 88 optionName)); 89 } 90 }; 91 update(String optionName, Object current, Object update)92 abstract Object update(String optionName, Object current, Object update) 93 throws ConfigurationException; 94 95 /** 96 * Takes the current value and the update value, and returns the value to be set. Assumes 97 * that <code>update</code> is never null. 98 */ update(String optionName, Object optionSource, Field field, Object update)99 public Object update(String optionName, Object optionSource, Field field, Object update) 100 throws ConfigurationException { 101 Object current; 102 try { 103 current = field.get(optionSource); 104 } catch (IllegalAccessException e) { 105 throw new ConfigurationException(String.format( 106 "internal error when setting option '%s'", optionName), e); 107 } 108 return update(optionName, current, update); 109 } 110 111 /** 112 * Check if the objects are {@link Comparable}, and if so, compare them using 113 * {@see Comparable#compareTo}. 114 */ 115 @SuppressWarnings({"unchecked", "rawtypes"}) compare(String optionName, Object current, Object update)116 private static int compare(String optionName, Object current, Object update) 117 throws ConfigurationException { 118 Comparable compCurrent; 119 if (current instanceof Comparable) { 120 compCurrent = (Comparable) current; 121 } else { 122 throw new ConfigurationException(String.format( 123 "internal error: Class %s for option %s was used with GREATEST or LEAST " + 124 "updateRule, but does not implement Comparable.", 125 current.getClass().getSimpleName(), optionName)); 126 } 127 128 try { 129 return compCurrent.compareTo(update); 130 } catch (ClassCastException e) { 131 throw new ConfigurationException(String.format( 132 "internal error: Failed to compare %s (%s) and %s (%s)", 133 current.getClass().getName(), current, update.getClass().getName(), update), e); 134 } 135 } 136 } 137 138