View Javadoc

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 }