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    
008    import javax.xml.parsers.DocumentBuilder;
009    import javax.xml.parsers.DocumentBuilderFactory;
010    import javax.xml.parsers.ParserConfigurationException;
011    
012    import org.maltparser.core.config.ConfigurationRegistry;
013    import org.maltparser.core.exception.MaltChainedException;
014    import org.maltparser.core.feature.FeatureException;
015    import org.maltparser.core.feature.function.Function;
016    import org.maltparser.core.helper.HashMap;
017    import org.maltparser.core.helper.URLFinder;
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                    final URLFinder f = new URLFinder();
055                    load(f.findURL(urlstring));
056            }
057            
058            public void load(PluginLoader plugins) throws MaltChainedException {
059                     for (Plugin plugin : plugins) {
060                            URL url = null;
061                            try {
062                                    url = new URL("jar:"+plugin.getUrl() + "!/appdata/plugin.xml");
063                            } catch (MalformedURLException e) {
064                                    throw new FeatureException("Malformed URL: 'jar:"+plugin.getUrl() + "!plugin.xml'", e);
065                            }
066                            try { 
067                                    InputStream is = url.openStream();
068                                    is.close();
069                            } catch (IOException e) {
070                                    continue;
071                            }
072    
073                            load(url);
074                    }
075            }
076            
077            public void load(URL specModelURL) throws MaltChainedException {
078            try {
079                DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
080                DocumentBuilder db = dbf.newDocumentBuilder();
081                Element root = null;
082    
083                root = db.parse(specModelURL.openStream()).getDocumentElement();
084    
085                if (root == null) {
086                    throw new FeatureException("The feature system file '"+specModelURL.getFile()+"' cannot be found. ");
087                }
088                
089                readFeatureSystem(root);
090            } catch (IOException e) {
091                    throw new FeatureException("The feature system file '"+specModelURL.getFile()+"' cannot be found. ", e);
092            } catch (ParserConfigurationException e) {
093                    throw new FeatureException("Problem parsing the file "+specModelURL.getFile()+". ", e);
094            } catch (SAXException e) {
095                    throw new FeatureException("Problem parsing the file "+specModelURL.getFile()+". ", e);
096            }
097            }
098            
099            public void readFeatureSystem(Element system) throws MaltChainedException {
100                    NodeList functions = system.getElementsByTagName("function");
101                    for (int i = 0; i < functions.getLength(); i++) {
102                            readFunction((Element)functions.item(i));
103                    }
104            }
105            
106            public void readFunction(Element function) throws MaltChainedException {
107                    boolean hasSubFunctions = function.getAttribute("hasSubFunctions").equalsIgnoreCase("true");
108                    
109                    boolean hasFactory = false;
110                    if (function.getAttribute("hasFactory").length() > 0) {
111                            hasFactory = function.getAttribute("hasFactory").equalsIgnoreCase("true");
112                    }
113                    Class<?> clazz = null;
114                    try {
115                            if (PluginLoader.instance() != null) {
116                                    clazz = PluginLoader.instance().getClass(function.getAttribute("class"));
117                            }
118                            if (clazz == null) {
119                                    clazz = Class.forName(function.getAttribute("class"));
120                            }
121                    } catch (ClassNotFoundException e) { 
122                            throw new FeatureException("The feature system could not find the function class"+function.getAttribute("class")+".", e);
123                    }
124                    if (hasSubFunctions) {
125                            NodeList subfunctions = function.getElementsByTagName("subfunction");
126                            for (int i = 0; i < subfunctions.getLength(); i++) {
127                                    readSubFunction((Element)subfunctions.item(i), clazz, hasFactory);
128                            }
129                    } else {
130                            int i = 0;
131                            String n = null;
132                            while (true) {
133                                    n = function.getAttribute("name") + "~~" + i;
134                                    if (!containsKey(n)) {
135                                            break;
136                                    }
137                                    i++;
138                            }
139                            put(n, new FunctionDescription(function.getAttribute("name"), clazz, false, hasFactory));
140                    }
141            }
142            
143            public void readSubFunction(Element subfunction, Class<?> clazz, boolean hasFactory) throws MaltChainedException {
144                    int i = 0;
145                    String n = null;
146                    while (true) {
147                            n = subfunction.getAttribute("name") + "~~" + i;
148                            if (!containsKey(n)) {
149                                    break;
150                            }
151                            i++;
152                    }
153                    put(n, new FunctionDescription(subfunction.getAttribute("name"), clazz, true, hasFactory));
154            }
155    
156            public boolean equals(Object obj) {
157                    if (this == obj)
158                            return true;
159                    if (obj == null)
160                            return false;
161                    if (getClass() != obj.getClass())
162                            return false;
163                    if (this.size() != ((FeatureEngine)obj).size()) {
164                            return false;
165                    }
166                    for (String name : keySet()) {
167                            if (!get(name).equals(((FeatureEngine)obj).get(name))) {
168                                    return false;
169                            }
170                    }
171                    return true;
172            }
173    
174            public String toString() {
175                    final StringBuilder sb = new StringBuilder();
176                    for (String name : keySet()) {
177                            sb.append(name);
178                            sb.append('\t');
179                            sb.append(get(name));
180                            sb.append('\n');
181                    }
182                    return sb.toString();
183            }
184    }