001    package org.maltparser.core.feature.system;
002    
003    import java.io.IOException;
004    import java.io.InputStream;
005    import java.net.MalformedURLException;
006    import java.net.URL;
007    import java.util.HashMap;
008    
009    import javax.xml.parsers.DocumentBuilder;
010    import javax.xml.parsers.DocumentBuilderFactory;
011    import javax.xml.parsers.ParserConfigurationException;
012    
013    import org.maltparser.core.config.ConfigurationRegistry;
014    import org.maltparser.core.exception.MaltChainedException;
015    import org.maltparser.core.feature.FeatureException;
016    import org.maltparser.core.feature.function.Function;
017    import org.maltparser.core.helper.Util;
018    import org.maltparser.core.plugin.Plugin;
019    import org.maltparser.core.plugin.PluginLoader;
020    import org.w3c.dom.Element;
021    import org.w3c.dom.NodeList;
022    import org.xml.sax.SAXException;
023    /**
024     *  
025     *
026     * @author Johan Hall
027     * @since 1.0
028    **/
029    public class FeatureEngine extends HashMap<String, FunctionDescription> {
030            public final static long serialVersionUID = 3256444702936019250L;
031            
032            public FeatureEngine() {
033                    super();
034            }
035    
036            public Function newFunction(String functionName, ConfigurationRegistry registry) throws MaltChainedException {
037                    int i = 0;
038                    Function func = null;
039                    while (true) {
040                            FunctionDescription funcDesc = get(functionName + "~~" + i);
041                            if (funcDesc == null) {
042                                    break;
043                            }
044                            func = funcDesc.newFunction(registry);
045                            if (func != null) {
046                                    break;
047                            }
048                            i++;
049                    }
050                    return func;
051            }
052            
053            public void load(String urlstring) throws MaltChainedException {
054                    load(Util.findURL(urlstring));
055            }
056            
057            public void load(PluginLoader plugins) throws MaltChainedException {
058                     for (Plugin plugin : plugins) {
059                            URL url = null;
060                            try {
061                                    url = new URL("jar:"+plugin.getUrl() + "!/appdata/plugin.xml");
062                            } catch (MalformedURLException e) {
063                                    throw new FeatureException("Malformed URL: 'jar:"+plugin.getUrl() + "!plugin.xml'", e);
064                            }
065                            try { 
066                                    InputStream is = url.openStream();
067                                    is.close();
068                            } catch (IOException e) {
069                                    continue;
070                            }
071    
072                            load(url);
073                    }
074            }
075            
076            public void load(URL specModelURL) throws MaltChainedException {
077            try {
078                DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
079                DocumentBuilder db = dbf.newDocumentBuilder();
080                Element root = null;
081    
082                root = db.parse(specModelURL.openStream()).getDocumentElement();
083    
084                if (root == null) {
085                    throw new FeatureException("The feature system file '"+specModelURL.getFile()+"' cannot be found. ");
086                }
087                
088                readFeatureSystem(root);
089            } catch (IOException e) {
090                    throw new FeatureException("The feature system file '"+specModelURL.getFile()+"' cannot be found. ", e);
091            } catch (ParserConfigurationException e) {
092                    throw new FeatureException("Problem parsing the file "+specModelURL.getFile()+". ", e);
093            } catch (SAXException e) {
094                    throw new FeatureException("Problem parsing the file "+specModelURL.getFile()+". ", e);
095            }
096            }
097            
098            public void readFeatureSystem(Element system) throws MaltChainedException {
099                    NodeList functions = system.getElementsByTagName("function");
100                    for (int i = 0; i < functions.getLength(); i++) {
101                            readFunction((Element)functions.item(i));
102                    }
103            }
104            
105            public void readFunction(Element function) throws MaltChainedException {
106                    boolean hasSubFunctions = function.getAttribute("hasSubFunctions").equalsIgnoreCase("true");
107                    
108                    boolean hasFactory = false;
109                    if (function.getAttribute("hasFactory").length() > 0) {
110                            hasFactory = function.getAttribute("hasFactory").equalsIgnoreCase("true");
111                    }
112                    Class<?> clazz = null;
113                    try {
114                            if (PluginLoader.instance() != null) {
115                                    clazz = PluginLoader.instance().getClass(function.getAttribute("class"));
116                            }
117                            if (clazz == null) {
118                                    clazz = Class.forName(function.getAttribute("class"));
119                            }
120                    } catch (ClassNotFoundException e) { 
121                            throw new FeatureException("The feature system could not find the function class"+function.getAttribute("class")+".", e);
122                    }
123                    if (hasSubFunctions) {
124                            NodeList subfunctions = function.getElementsByTagName("subfunction");
125                            for (int i = 0; i < subfunctions.getLength(); i++) {
126                                    readSubFunction((Element)subfunctions.item(i), clazz, hasFactory);
127                            }
128                    } else {
129                            int i = 0;
130                            String n = null;
131                            while (true) {
132                                    n = function.getAttribute("name") + "~~" + i;
133                                    if (!containsKey(n)) {
134                                            break;
135                                    }
136                                    i++;
137                            }
138                            put(n, new FunctionDescription(function.getAttribute("name"), clazz, false, hasFactory));
139                    }
140            }
141            
142            public void readSubFunction(Element subfunction, Class<?> clazz, boolean hasFactory) throws MaltChainedException {
143                    int i = 0;
144                    String n = null;
145                    while (true) {
146                            n = subfunction.getAttribute("name") + "~~" + i;
147                            if (!containsKey(n)) {
148                                    break;
149                            }
150                            i++;
151                    }
152                    put(n, new FunctionDescription(subfunction.getAttribute("name"), clazz, true, hasFactory));
153            }
154    
155            public boolean equals(Object obj) {
156                    if (this == obj)
157                            return true;
158                    if (obj == null)
159                            return false;
160                    if (getClass() != obj.getClass())
161                            return false;
162                    if (this.size() != ((FeatureEngine)obj).size()) {
163                            return false;
164                    }
165                    for (String name : keySet()) {
166                            if (!get(name).equals(((FeatureEngine)obj).get(name))) {
167                                    return false;
168                            }
169                    }
170                    return true;
171            }
172    
173            public String toString() {
174                    StringBuilder sb = new StringBuilder();
175                    for (String name : keySet()) {
176                            sb.append(name);
177                            sb.append('\t');
178                            sb.append(get(name));
179                            sb.append('\n');
180                    }
181                    return sb.toString();
182            }
183    }