001 package org.maltparser.core.feature;
002
003
004 import java.util.ArrayList;
005 import java.util.HashMap;
006 import java.util.Stack;
007 import java.util.regex.Pattern;
008
009 import org.maltparser.core.config.ConfigurationRegistry;
010 import org.maltparser.core.exception.MaltChainedException;
011 import org.maltparser.core.feature.function.AddressFunction;
012 import org.maltparser.core.feature.function.FeatureFunction;
013 import org.maltparser.core.feature.function.Function;
014 import org.maltparser.core.feature.spec.SpecificationModel;
015 import org.maltparser.core.feature.spec.SpecificationSubModel;
016 import org.maltparser.core.feature.system.FeatureEngine;
017
018 /**
019 *
020 *
021 * @author Johan Hall
022 */
023 public class FeatureModel extends HashMap<String, FeatureVector> {
024 public final static long serialVersionUID = 3256444702936019250L;
025 protected SpecificationModel specModel;
026 protected final ArrayList<AddressFunction> addressFunctionCache;
027 protected final ArrayList<FeatureFunction> featureFunctionCache;
028 protected ConfigurationRegistry registry;
029 protected FeatureEngine featureEngine;
030 protected FeatureVector mainFeatureVector = null;
031 protected final Pattern splitPattern;
032
033 public FeatureModel(SpecificationModel specModel, ConfigurationRegistry registry, FeatureEngine engine) throws MaltChainedException {
034 setSpecModel(specModel);
035 setRegistry(registry);
036 setFeatureEngine(engine);
037 addressFunctionCache = new ArrayList<AddressFunction>();
038 featureFunctionCache = new ArrayList<FeatureFunction>();
039 splitPattern = Pattern.compile("\\(|\\)|\\[|\\]|,");
040 for (SpecificationSubModel subModel : specModel) {
041 FeatureVector fv = new FeatureVector(this, subModel);
042 if (mainFeatureVector == null) {
043 if (subModel.getSubModelName().equals("MAIN")) {
044 mainFeatureVector = fv;
045 } else {
046 mainFeatureVector = fv;
047 put(subModel.getSubModelName(), fv);
048 }
049 } else {
050 put(subModel.getSubModelName(), fv);
051 }
052 }
053 }
054
055 public SpecificationModel getSpecModel() {
056 return specModel;
057 }
058
059 public void setSpecModel(SpecificationModel specModel) {
060 this.specModel = specModel;
061 }
062
063 public ArrayList<AddressFunction> getAddressFunctionCache() {
064 return addressFunctionCache;
065 }
066
067 public ArrayList<FeatureFunction> getFeatureFunctionCache() {
068 return featureFunctionCache;
069 }
070
071 public ConfigurationRegistry getRegistry() {
072 return registry;
073 }
074
075 public void setRegistry(ConfigurationRegistry registry) {
076 this.registry = registry;
077 }
078
079 public FeatureEngine getFeatureEngine() {
080 return featureEngine;
081 }
082
083 public void setFeatureEngine(FeatureEngine featureEngine) {
084 this.featureEngine = featureEngine;
085 }
086
087 public FeatureVector getMainFeatureVector() {
088 return mainFeatureVector;
089 }
090
091 public FeatureVector getFeatureVector(String subModelName) {
092 return get(subModelName);
093 }
094
095 public void update() throws MaltChainedException {
096 for (int i = 0, n = addressFunctionCache.size(); i < n; i++) {
097 addressFunctionCache.get(i).update();
098 }
099
100 for (int i = 0, n = featureFunctionCache.size(); i < n; i++) {
101 featureFunctionCache.get(i).update();
102 }
103 }
104
105 public void update(Object[] arguments) throws MaltChainedException {
106 for (int i = 0, n = addressFunctionCache.size(); i < n; i++) {
107 addressFunctionCache.get(i).update(arguments);
108 }
109
110 for (int i = 0, n = featureFunctionCache.size(); i < n; i++) {
111 featureFunctionCache.get(i).update();
112 }
113 }
114
115 public void updateCardinality() throws MaltChainedException {
116 for (int i = 0, n = featureFunctionCache.size(); i < n; i++) {
117 featureFunctionCache.get(i).updateCardinality();
118 }
119 }
120
121 public FeatureFunction identifyFeature(String spec) throws MaltChainedException {
122 String[] items =splitPattern.split(spec);
123 Stack<Object> objects = new Stack<Object>();
124 for (int i = items.length-1; i >= 0; i--) {
125 if (items[i].trim().length() != 0) {
126 objects.push(items[i].trim());
127 }
128 }
129 identifyFeatureFunction(objects);
130 if (objects.size() != 1 || !(objects.peek() instanceof FeatureFunction) || (objects.peek() instanceof AddressFunction)) {
131 throw new FeatureException("The feature specification '"+spec+"' were not recognized properly. ");
132 }
133 return (FeatureFunction)objects.pop();
134 }
135
136 protected void identifyFeatureFunction(Stack<Object> objects) throws MaltChainedException {
137 Function function = featureEngine.newFunction(objects.peek().toString(), registry);
138 if (function != null) {
139 objects.pop();
140 if (!objects.isEmpty()) {
141 identifyFeatureFunction(objects);
142 }
143 initializeFunction(function, objects);
144 } else {
145 if (!objects.isEmpty()) {
146 Object o = objects.pop();
147 if (!objects.isEmpty()) {
148 identifyFeatureFunction(objects);
149 }
150 objects.push(o);
151 }
152 }
153 }
154
155 protected void initializeFunction(Function function, Stack<Object> objects) throws MaltChainedException {
156 Class<?>[] paramTypes = function.getParameterTypes();
157 Object[] arguments = new Object[paramTypes.length];
158 for (int i = 0; i < paramTypes.length; i++) {
159 if (paramTypes[i] == java.lang.Integer.class) {
160 if (objects.peek() instanceof String) {
161 try {
162 objects.push(Integer.parseInt(((String)objects.pop())));
163 } catch (NumberFormatException e) {
164 throw new FeatureException("Could not cast string to integer. ", e);
165 }
166 } else {
167 throw new FeatureException("Could not cast string to integer. ");
168 }
169 } else if (paramTypes[i] == java.lang.Double.class) {
170 if (objects.peek() instanceof String) {
171 try {
172 objects.push(Double.parseDouble(((String)objects.pop())));
173 } catch (NumberFormatException e) {
174 throw new FeatureException("Could not cast string to double. ", e);
175 }
176 } else {
177 throw new FeatureException("Could not cast string to double. ");
178 }
179 } else if (paramTypes[i] == java.lang.Boolean.class) {
180 if (objects.peek() instanceof String) {
181 objects.push(Boolean.parseBoolean(((String)objects.pop())));
182 } else {
183 throw new FeatureException("Could not cast string to boolean. ");
184 }
185 }
186 if (!paramTypes[i].isInstance(objects.peek())) {
187 throw new FeatureException("The function cannot be initialized. " + "(" + paramTypes[i] + ")(" + objects.peek() + ")(" + function + ")(" + objects + ")");
188 }
189 arguments[i] = objects.pop();
190 }
191 function.initialize(arguments);
192 if (function instanceof AddressFunction) {
193 int index = getAddressFunctionCache().indexOf(function);
194 if (index != -1) {
195 function = getAddressFunctionCache().get(index);
196 } else {
197 getAddressFunctionCache().add((AddressFunction)function);
198 }
199 } else if (function instanceof FeatureFunction) {
200 int index = getFeatureFunctionCache().indexOf(function);
201 if (index != -1) {
202 function = getFeatureFunctionCache().get(index);
203 } else {
204 getFeatureFunctionCache().add((FeatureFunction)function);
205 }
206 }
207 objects.push(function);
208 }
209
210 public String toString() {
211 return specModel.toString();
212 }
213 }