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 (AddressFunction func : addressFunctionCache) { 097 func.update(); 098 } 099 for (FeatureFunction func : featureFunctionCache) { 100 func.update(); 101 } 102 } 103 104 public void updateCardinality() throws MaltChainedException { 105 for (FeatureFunction func : featureFunctionCache) { 106 func.updateCardinality(); 107 } 108 } 109 110 public FeatureFunction identifyFeature(String spec) throws MaltChainedException { 111 String[] items =splitPattern.split(spec); 112 Stack<Object> objects = new Stack<Object>(); 113 for (int i = items.length-1; i >= 0; i--) { 114 if (items[i].trim().length() != 0) { 115 objects.push(items[i].trim()); 116 } 117 } 118 identifyFeatureFunction(objects); 119 if (objects.size() != 1 || !(objects.peek() instanceof FeatureFunction) || (objects.peek() instanceof AddressFunction)) { 120 throw new FeatureException("The feature specification '"+spec+"' were not recognized properly. "); 121 } 122 return (FeatureFunction)objects.pop(); 123 } 124 125 protected void identifyFeatureFunction(Stack<Object> objects) throws MaltChainedException { 126 Function function = featureEngine.newFunction(objects.peek().toString(), registry); 127 128 if (function != null) { 129 objects.pop(); 130 if (!objects.isEmpty()) { 131 identifyFeatureFunction(objects); 132 } 133 initializeFunction(function, objects); 134 } else { 135 if (!objects.isEmpty()) { 136 Object o = objects.pop(); 137 if (!objects.isEmpty()) { 138 identifyFeatureFunction(objects); 139 } 140 objects.push(o); 141 } 142 } 143 } 144 145 protected void initializeFunction(Function function, Stack<Object> objects) throws MaltChainedException { 146 Class<?>[] paramTypes = function.getParameterTypes(); 147 Object[] arguments = new Object[paramTypes.length]; 148 for (int i = 0; i < paramTypes.length; i++) { 149 if (paramTypes[i] == java.lang.Integer.class) { 150 if (objects.peek() instanceof String) { 151 try { 152 objects.push(Integer.parseInt(((String)objects.pop()))); 153 } catch (NumberFormatException e) { 154 throw new FeatureException("Could not cast string to integer. ", e); 155 } 156 } else { 157 throw new FeatureException("Could not cast string to integer. "); 158 } 159 } else if (paramTypes[i] == java.lang.Double.class) { 160 if (objects.peek() instanceof String) { 161 try { 162 objects.push(Double.parseDouble(((String)objects.pop()))); 163 } catch (NumberFormatException e) { 164 throw new FeatureException("Could not cast string to double. ", e); 165 } 166 } else { 167 throw new FeatureException("Could not cast string to double. "); 168 } 169 } else if (paramTypes[i] == java.lang.Boolean.class) { 170 if (objects.peek() instanceof String) { 171 objects.push(Boolean.parseBoolean(((String)objects.pop()))); 172 } else { 173 throw new FeatureException("Could not cast string to boolean. "); 174 } 175 } 176 if (!paramTypes[i].isInstance(objects.peek())) { 177 throw new FeatureException("The function cannot be initialized. "); 178 } 179 arguments[i] = objects.pop(); 180 } 181 function.initialize(arguments); 182 if (function instanceof AddressFunction) { 183 int index = getAddressFunctionCache().indexOf(function); 184 if (index != -1) { 185 function = getAddressFunctionCache().get(index); 186 } else { 187 getAddressFunctionCache().add((AddressFunction)function); 188 } 189 } else if (function instanceof FeatureFunction) { 190 int index = getFeatureFunctionCache().indexOf(function); 191 if (index != -1) { 192 function = getFeatureFunctionCache().get(index); 193 } else { 194 getFeatureFunctionCache().add((FeatureFunction)function); 195 } 196 } 197 objects.push(function); 198 } 199 200 public String toString() { 201 return specModel.toString(); 202 } 203 }