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 }