1 /* Copyright (c) 2008 Sascha Kohlmann
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU Affero General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Affero General Public License for more details.
12 *
13 * You should have received a copy of the GNU Affero General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16 package net.sf.eos.util.functions;
17
18 import org.apache.commons.logging.Log;
19 import org.apache.commons.logging.LogFactory;
20
21 import java.lang.reflect.Field;
22 import java.lang.reflect.Modifier;
23
24 import net.sf.eos.Experimental;
25 import net.sf.eos.Function;
26 import net.sf.eos.Nullable;
27 import net.sf.eos.config.ConfigurationKey;
28
29 import net.sf.eos.util.functions.ConfigurationKeyIntrospectorFunction.ConfigurationKeySupport;
30
31 /**
32 * Extracts a {@link ConfigurationKey} from a given type with a specified value.
33 * The implementation only intrspects field which are {@code public}, {@code final}
34 * and {@code static}. Otherwise the key will be ignored. Use this function with
35 * {@link DefaultValueConfigurationKeyFunction} to get the default value
36 * of a {@code ConfigurationKey}.
37 * @author Sascha Kohlmann
38 * @since 0.1.0
39 * @version 0.1.0
40 */
41 @Experimental
42 public class ConfigurationKeyIntrospectorFunction
43 implements Function<ConfigurationKeySupport, ConfigurationKey> {
44
45 /** for logging */
46 static final Log LOG = LogFactory.getLog(ConfigurationKeyIntrospectorFunction.class.getName());
47
48 /**
49 * Simple holder for reflection data.
50 * @author Sascha Kohlmann
51 * @since 0.1.0
52 */
53 public static class ConfigurationKeySupport {
54
55 /** The class to introspect. */
56 final Class<?> clazz;
57 /** The value of the field. */
58 final String configKeyValue;
59
60 /**
61 * Creates a new instance.
62 * @param clazz the {@code class} to introspect
63 * @param configKeyValue the value of the configuration key field
64 */
65 public ConfigurationKeySupport(
66 @SuppressWarnings("hiding") @Nullable final Class<?> clazz,
67 @SuppressWarnings("hiding") @Nullable final String configKeyValue) {
68 this.clazz = clazz;
69 this.configKeyValue = configKeyValue;
70 }
71
72 /**
73 * Returns the class to refelect.
74 * @return the class to refelect. May be {@code null}
75 */
76 public Class<?> getConfigKeyHolderClass() {
77 return this.clazz;
78 }
79
80 /**
81 * Returns the value of the configuration key field.
82 * @return the value of the configuration key field. May be {@code null}
83 */
84 public String getConfigKeyValue() {
85 return this.configKeyValue;
86 }
87
88 /** {@inheritDoc} */
89 @SuppressWarnings("nls")
90 @Override
91 public String toString() {
92 final StringBuilder sb = new StringBuilder();
93 sb.append("ConfigurationKeySupport[configKeyHolderClass=");
94 sb.append(this.getConfigKeyHolderClass());
95 sb.append("|configKeyValue=");
96 sb.append(this.getConfigKeyValue());
97 sb.append("]");
98
99 return sb.toString();
100 }
101 }
102
103 /**
104 * Extracts the {@code ConfigurationKey} from the given {@code class}
105 * with the specified value of the key.
106 * @param from the instance holds the data to refelect the
107 * {@code ConfigurationKey}
108 * @return a {@code ConfigurationKey} if the function is able to reflect
109 * it. Otherwise {@code null}.
110 */
111 @SuppressWarnings("nls")
112 public ConfigurationKey apply(@Nullable ConfigurationKeySupport from) {
113 if (from == null
114 || from.getConfigKeyHolderClass() == null
115 || from.getConfigKeyValue() == null) {
116 if (LOG.isDebugEnabled()) {
117 LOG.debug("from value or values of from are null: " + from);
118 }
119 return null;
120 }
121
122 ConfigurationKey retval = null;
123
124 final Field[] fields = from.getConfigKeyHolderClass().getFields();
125 for (final Field field : fields) {
126
127 final ConfigurationKey fieldKey =
128 field.getAnnotation(ConfigurationKey.class);
129
130 if (fieldKey != null) {
131 final int modifiers = field.getModifiers();
132 if (Modifier.isStatic(modifiers)
133 && Modifier.isFinal(modifiers)
134 && Modifier.isPublic(modifiers)) {
135 try {
136 final Object o = field.get(null);
137 if (from.getConfigKeyValue().equals(o)) {
138 retval = fieldKey;
139 // Found, nothing elese todo.
140 break;
141 }
142 } catch (final IllegalAccessException e) {
143 // Never happen causse rules for this block demands
144 // for 'public final static'
145 }
146 }
147 }
148 }
149
150 if (LOG.isDebugEnabled()) {
151 if (retval != null) {
152 LOG.debug("found configuration key " + retval + " for " + from);
153 } else {
154 LOG.debug("No configuration key found for " + from);
155 }
156 }
157
158 return retval;
159 }
160 }