001 package org.maltparser.core.feature;
002
003
004 import java.util.ArrayList;
005 import java.util.Stack;
006 import java.util.regex.Pattern;
007
008 import org.maltparser.core.config.ConfigurationRegistry;
009 import org.maltparser.core.exception.MaltChainedException;
010 import org.maltparser.core.feature.function.AddressFunction;
011 import org.maltparser.core.feature.function.FeatureFunction;
012 import org.maltparser.core.feature.function.Function;
013 import org.maltparser.core.feature.spec.SpecificationModel;
014 import org.maltparser.core.feature.spec.SpecificationSubModel;
015 import org.maltparser.core.feature.system.FeatureEngine;
016 import org.maltparser.core.helper.HashMap;
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 String object = (String)objects.pop();
162 try {
163 objects.push(Integer.parseInt(object));
164 } catch (NumberFormatException e) {
165 throw new FeatureException("The function '"+function.getClass()+"' cannot be initialized with argument '"+object+"'" + ", expect an integer value. ", e);
166 }
167 } else {
168 throw new FeatureException("The function '"+function.getClass()+"' cannot be initialized with argument '"+objects.peek()+"'" + ", expect an integer value. ");
169 }
170 } else if (paramTypes[i] == java.lang.Double.class) {
171 if (objects.peek() instanceof String) {
172 String object = (String)objects.pop();
173 try {
174 objects.push(Double.parseDouble(object));
175 } catch (NumberFormatException e) {
176 throw new FeatureException("The function '"+function.getClass()+"' cannot be initialized with argument '"+object+"'" + ", expect a numeric value. ", e);
177 }
178 } else {
179 throw new FeatureException("The function '"+function.getClass()+"' cannot be initialized with argument '"+objects.peek()+"'" + ", expect a numeric value. ");
180 }
181 } else if (paramTypes[i] == java.lang.Boolean.class) {
182 if (objects.peek() instanceof String) {
183 objects.push(Boolean.parseBoolean(((String)objects.pop())));
184 } else {
185 throw new FeatureException("The function '"+function.getClass()+"' cannot be initialized with argument '"+objects.peek()+"'" + ", expect a boolean value. ");
186
187 }
188 }
189 if (!paramTypes[i].isInstance(objects.peek())) {
190 throw new FeatureException("The function '"+function.getClass()+"' cannot be initialized with argument '"+objects.peek()+"'");
191 }
192 arguments[i] = objects.pop();
193 }
194 function.initialize(arguments);
195 if (function instanceof AddressFunction) {
196 int index = getAddressFunctionCache().indexOf(function);
197 if (index != -1) {
198 function = getAddressFunctionCache().get(index);
199 } else {
200 getAddressFunctionCache().add((AddressFunction)function);
201 }
202 } else if (function instanceof FeatureFunction) {
203 int index = getFeatureFunctionCache().indexOf(function);
204 if (index != -1) {
205 function = getFeatureFunctionCache().get(index);
206 } else {
207 getFeatureFunctionCache().add((FeatureFunction)function);
208 }
209 }
210 objects.push(function);
211 }
212
213 public String toString() {
214 return specModel.toString();
215 }
216 }