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