1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package de.fu_berlin.ties.classify.feature;
23
24 import org.apache.commons.lang.StringUtils;
25 import org.apache.commons.lang.builder.ToStringBuilder;
26
27 import de.fu_berlin.ties.ProcessingException;
28 import de.fu_berlin.ties.TiesConfiguration;
29 import de.fu_berlin.ties.util.Util;
30
31 /***
32 * An feature transformer transforms a feature vector in a suitable way.
33 * Feature transformer can be used for feature selection (discarding irrelevant
34 * features), for combining features etc. Feature transforms can be
35 * <em>chained</em> -- in this case each feature transformer will work on the
36 * featured returned by the previous one.
37 *
38 * @author Christian Siefkes
39 * @version $Revision: 1.3 $, $Date: 2004/07/08 08:42:18 $, $Author: siefkes $
40 */
41 public abstract class FeatureTransformer {
42
43 /***
44 * Configuration key specifying the list of transformers to chain.
45 */
46 public static final String CONFIG_TRANSFORMERS = "transformer.chain";
47
48 /***
49 * Factory method that delegates to {@link #createTransformer()} using the
50 * {@linkplain TiesConfiguration#CONF standard configuration}.
51 *
52 * @return the last transformer in the created transformer chain; or
53 * <code>null</code> is no transformers are specified (parameter value is
54 * <code>null</code> or empty)
55 * @throws IllegalArgumentException if the value of the
56 * {@link #CONFIG_TRANSFORMERS} key is invalid
57 * @throws ProcessingException if an error occurred while creating the
58 * transformer
59 */
60 public static FeatureTransformer createTransformer()
61 throws IllegalArgumentException, ProcessingException {
62 return createTransformer(TiesConfiguration.CONF);
63 }
64
65 /***
66 * Factory method that creates a feature transformer based on the
67 * {@link #CONFIG_TRANSFORMERS} key in the provided configuration.
68 * This parameter must contain a list fully specified names of subclasses
69 * of this class) used in a chain.
70 *
71 * <p>Eeach specified transformer must provide a constructor accepting a
72 * preceding {@link FeatureTransformer} as first argument and a
73 * {@link TiesConfiguration} as second argument.
74 *
75 * @param config the configuration to use
76 * @return the last transformer in the created transformer chain; or
77 * <code>null</code> is no transformers are specified (parameter value is
78 * <code>null</code> or empty)
79 * @throws IllegalArgumentException if the value of the
80 * {@link #CONFIG_TRANSFORMERS} key is invalid
81 * @throws ProcessingException if an error occurred while creating the
82 * transformer
83 */
84 public static FeatureTransformer createTransformer(
85 final TiesConfiguration config)
86 throws IllegalArgumentException, ProcessingException {
87 final String[] paramValue = config.getStringArray(CONFIG_TRANSFORMERS);
88 FeatureTransformer transformer = null;
89 int i = 0;
90
91 try {
92 for (; i < paramValue.length; i++) {
93
94
95
96 if (StringUtils.isNotEmpty(paramValue[i])) {
97 transformer = (FeatureTransformer) Util.createObject(
98 Class.forName(paramValue[i]),
99 new Object[] {transformer, config},
100 new Class[] {FeatureTransformer.class,
101 TiesConfiguration.class});
102 }
103 }
104 } catch (ClassNotFoundException cnfe) {
105
106 throw new ProcessingException(
107 "Cannot create transformer chain from key "
108 + CONFIG_TRANSFORMERS + " because the class " + paramValue[i]
109 + " is missing: " + cnfe.toString());
110 } catch (InstantiationException ie) {
111
112 throw new ProcessingException(
113 "Cannot create transformer chain from key "
114 + CONFIG_TRANSFORMERS + " because instantation of the class "
115 + paramValue[i] + " failed: ", ie);
116 }
117
118
119 return transformer;
120 }
121
122 /***
123 * The preceding transformer used if this transformer is part of a
124 * <em>chain</em>; <code>null</code> otherwise.
125 */
126 private final FeatureTransformer precedingTransformer;
127
128 /***
129 * Creates a new instance.
130 *
131 * @param precTrans the preceding transformer to use if this transformer
132 * is part of a <em>chain</em>; <code>null</code> otherwise
133 */
134 public FeatureTransformer(final FeatureTransformer precTrans) {
135 super();
136 precedingTransformer = precTrans;
137 }
138
139 /***
140 * Transforms a feature vector.
141 *
142 * @param orgFeatures the original feature vector to transform
143 * @return a new feature vector containing the transformed features
144 */
145 protected abstract FeatureVector doTransform(
146 final FeatureVector orgFeatures);
147
148 /***
149 * Returns the preceding transformer used if this transformer is part of a
150 * <em>chain</em>.
151 *
152 * @return the preceding transformer, if any; or <code>null</code> if this
153 * transformer is not part of a chain resp. is the first transformer in a
154 * chain
155 */
156 public FeatureTransformer getPrecedingTransformer() {
157 return precedingTransformer;
158 }
159
160 /***
161 * Returns a string representation of this object.
162 *
163 * @return a textual representation
164 */
165 public String toString() {
166 final ToStringBuilder builder = new ToStringBuilder(this);
167
168 if (precedingTransformer != null) {
169 builder.append("preceding transformer", precedingTransformer);
170 }
171 return builder.toString();
172 }
173
174 /***
175 * Transforms a feature vector. This method calls itself on the
176 * {@linkplain #getPrecedingTransformer() preceding transformer} (if any)
177 * prior to delegating to the abstract {@link #doTransform(FeatureVector)}
178 * method.
179 *
180 * @param orgFeatures the original feature vector to transform
181 * @return a new feature vector containing the transformed features
182 */
183 public FeatureVector transform(final FeatureVector orgFeatures) {
184 final FeatureVector result;
185
186 if (precedingTransformer != null) {
187
188 result = doTransform(precedingTransformer.transform(orgFeatures));
189 } else {
190
191 result = doTransform(orgFeatures);
192 }
193
194
195
196 return result;
197 }
198
199 }