source: java/main/src/main/java/com/framsticks/parsers/Schema.java @ 78

Last change on this file since 78 was 78, checked in by psniegowski, 11 years ago

Add f0 parsing and f0->Model transformation.

File size: 10.0 KB
Line 
1package com.framsticks.parsers;
2
3import java.io.File;
4import java.io.FileInputStream;
5import java.io.IOException;
6import java.io.InputStream;
7import java.util.Collections;
8import java.util.HashMap;
9import java.util.Map;
10import java.util.Map.Entry;
11
12import com.framsticks.params.*;
13import com.framsticks.params.types.DecimalParam;
14import com.framsticks.params.types.FloatParam;
15import com.framsticks.params.types.StringParam;
16import org.apache.log4j.Logger;
17
18import javax.xml.parsers.DocumentBuilder;
19import javax.xml.parsers.DocumentBuilderFactory;
20import javax.xml.parsers.ParserConfigurationException;
21
22import com.framsticks.leftovers.f0.NeuroClass;
23import org.w3c.dom.Document;
24import org.w3c.dom.NamedNodeMap;
25import org.w3c.dom.Node;
26import org.w3c.dom.NodeList;
27import org.xml.sax.SAXException;
28
29/**
30 * The Class Schema, which represent f0 schema (it contains all the possible
31 * classes definitions that can be used in f0 representation). Definitions are
32 * loaded from XML stream.
33 *
34 * @author Jarek Szymczak <name.surname@gmail.com>
35 * (please replace name and surname with my personal data)
36 */
37public class Schema {
38
39        private final static Logger logger = Logger.getLogger(Schema.class);
40
41        protected final Registry registry = new Registry();
42
43        /** The neuro classes (classess representing different types of neurons). */
44        private Map<String, NeuroClass> neuroClasses = new HashMap<String, NeuroClass>();
45
46        public static InputStream getDefaultDefinitionAsStream() {
47                //return new FileInputStream(new File(Schema.class.getResource("/parsers/f0def.xml").getPath()));
48                return Schema.class.getResourceAsStream("/parsers/f0def.xml");
49        }
50
51        /**
52         * Instantiates a new schema.
53         *
54         * @param inputStream
55         *            the xml stream with schema
56         * @throws Exception
57         *             the exception if one occurred while reading the stream
58         */
59        public Schema(InputStream inputStream) throws Exception {
60
61                DocumentBuilderFactory factory;
62                DocumentBuilder db;
63
64                try {
65                        factory = javax.xml.parsers.DocumentBuilderFactory.newInstance();
66                        db = factory.newDocumentBuilder();
67
68                        Document document = db.parse(inputStream);
69                        NodeList classes = document.getElementsByTagName("CLASS");
70
71                        for (int i = 0; i < classes.getLength(); i++) {
72                                Node classNode = classes.item(i);
73                                FramsClass framsClass = processClass(classNode);
74                                registry.putInfoIntoCache(framsClass);
75                        }
76
77                        classes = document.getElementsByTagName("NEUROCLASS");
78
79                        for (int i = 0; i < classes.getLength(); i++) {
80                                Node classNode = classes.item(i);
81                                FramsClass framsClass = processClass(classNode);
82
83                                NamedNodeMap attributes = classNode.getAttributes();
84                                int prefInputs = getIntAttribute(attributes, "INPUTS");
85                                int prefOutput = getIntAttribute(attributes, "OUTPUT");
86                                int prefLocation = getIntAttribute(attributes, "LOCATION");
87                                int visualHints = getIntAttribute(attributes, "VISUALHINTS");
88                                String symbolGlymphString = getAttribute(attributes, "SYMBOL");
89                                int[] symbolGlymph = null;
90
91                                if (symbolGlymphString != null) {
92                                        String[] sgha = symbolGlymphString.split(",");
93                                        int length = sgha.length;
94                                        symbolGlymph = new int[length];
95                                        for (int j = 0; j < length; j++) {
96                                                try {
97                                                        symbolGlymph[j] = Integer.parseInt(sgha[j]);
98                                                } catch (NumberFormatException e) {
99                                                        logger.error("an error occurred while parsing symbol glymph, class getId: "
100                                                                        + framsClass.getId()
101                                                                        + ", glymph offset: " + j);
102                                                }
103                                        }
104                                }
105
106                                neuroClasses.put(framsClass.getId(), new NeuroClass(
107                                                framsClass, prefInputs, prefOutput, prefLocation,
108                                                visualHints, symbolGlymph));
109                        }
110
111                } catch (IOException e) {
112                        logger.fatal("unexpected exception occurred: ", e);
113                        throw e;
114                } catch (ParserConfigurationException e) {
115                        logger.fatal("unexpected exception occurred: ", e);
116                        throw e;
117                } catch (SAXException e) {
118                        logger.fatal("unexpected exception occurred: ", e);
119                        throw e;
120                }
121
122        }
123
124        /**
125         * Method used for convenience, it retrieves the Integer value stored in
126         * node under certain attribute getName. If value is not present or is other
127         * getType than integer 0 is returned.
128         *
129         * @return attribute value if value exists and it's integer (0 otherwise)
130         *
131         */
132        private static int getIntAttribute(NamedNodeMap attributes, String name) {
133                String v = getAttribute(attributes, name);
134                if (v == null) {
135                        return 0;
136                }
137                try {
138                        return Integer.parseInt(v);
139                } catch (NullPointerException e) {
140                        return 0;
141                } catch (NumberFormatException e) {
142                        logger.fatal("attribute " + name
143                                        + " should be numeric: " + v);
144                        return 0;
145                }
146        }
147
148        private static String getAttribute(NamedNodeMap attributes, String name) {
149                Node item = attributes.getNamedItem(name);
150                if (item == null) {
151                        return null;
152                }
153                return item.getNodeValue();
154        }
155
156        /**
157         * Method used for convenience, it retrieves the value stored in node under
158         * certain attribute getName. If value is not present method returns null.
159         *
160         * @param attributeName
161         *            the attribute getName
162         * @param node
163         *            the node
164         * @return attribute value if value exists (null otherwise)
165         *
166         */
167        private static String getAttributeFromNode(String attributeName, Node node) {
168                if (node == null) {
169                        return null;
170                }
171                return getAttribute(node.getAttributes(), attributeName);
172        }
173
174        /**
175         * In this method analysis of single class is performed.
176         *
177         * @param classNode
178         *            the class node
179         * @return the param entry list as a class schema
180         * @throws Exception
181         *             the exception in case of any error
182         */
183        private static FramsClass processClass(Node classNode) throws Exception {
184                String classId = null;
185                String className = "";
186                String classDescription = "";
187                try {
188                        classId = classNode.getAttributes().getNamedItem("ID")
189                                        .getNodeValue();
190                } catch (NullPointerException e) {
191                        throw new Exception("Class getId is not defined!");
192                }
193
194                className = getAttributeFromNode("NAME", classNode);
195                classDescription = getAttributeFromNode("DESCRIPTION", classNode);
196
197                FramsClass framsClass = new FramsClass(classId, className, classDescription);
198
199                NodeList classProperties = classNode.getChildNodes();
200
201                for (int j = 0; j < classProperties.getLength(); j++) {
202                        Node node = classProperties.item(j);
203
204                        if ("GROUP".equals(node.getNodeName())) {
205                                NamedNodeMap attributes = node.getAttributes();
206                                String name = getAttribute(attributes, "NAME");
207                                if (name == null) {
208                                        logger.warn("Group name in class \"" + classId + "\" ("
209                                                        + className + ") is undefined");
210                                } else {
211                                        framsClass.appendGroup(new Group(name));
212                                }
213                        } else if ("PROP".equals(node.getNodeName())
214                                        || "NEUROPROP".equals(node.getNodeName())) {
215
216                                NamedNodeMap attributes = node.getAttributes();
217                                Param param = processParameter(attributes, classId);
218                                framsClass.append(param);
219                        }
220
221                }
222
223                return framsClass;
224        }
225
226        /**
227         * It analyses the single property within the class
228         *
229         * @param attributes
230         *            the attributes of property
231         * @param classId
232         *            the class getId
233         * @return the param entry representing single parameter
234         * @throws Exception
235         *             the exception in case of any error
236         */
237        private static Param processParameter(NamedNodeMap attributes, String classId)
238                        throws Exception {
239
240                String id = getAttribute(attributes, "ID");
241                if (id == null)
242                        throw new Exception("Property ID in class \"" + classId
243                                        + "\" is undefined");
244                String type = getAttribute(attributes, "TYPE");
245                if (type == null)
246                        throw new Exception("TYPE of property \"" + id + "\" is undefined");
247
248                String name = getAttribute(attributes, "NAME");
249                String description = getAttribute(attributes, "DESCRIPTION");
250                int group = getIntAttribute(attributes, "GROUP");
251                String flagsString = getAttribute(attributes, "FLAGS");
252
253                Integer flags = 0;
254
255                try {
256                        if (flagsString != null)
257                                for (String flag : flagsString.split("[^0-9]")) {
258                                        if (flag.trim().equals(""))
259                                                continue;
260                                        flags |= Integer.parseInt(flag);
261                                }
262                } catch (NumberFormatException e) {
263                        logger.warn("FLAGS parameter should be an Integer value or separated Integer values. FLAGS are set to: "
264                                        + flags);
265                }
266
267                Map<String, String> minMaxDef = new HashMap<String, String>();
268
269                for (String key : new String[] { "MIN", "MAX", "DEF" }) {
270                        String value = getAttribute(attributes, key);
271                        if (value != null && !value.trim().equals(""))
272                                minMaxDef.put(key, value);
273                }
274
275                ParamBuilder builder = new ParamBuilder();
276                builder.setId(id).setName(name).setHelp(description).setGroup(group).setFlags(flags);
277
278                if ("d".equals(type)) {
279
280                        Map<String, Integer> minMaxDefInt = new HashMap<String, Integer>();
281                        for (Entry<String, String> entry : minMaxDef.entrySet()) {
282                                try {
283                                        minMaxDefInt.put(entry.getKey(),
284                                                        Integer.parseInt(entry.getValue()));
285                                } catch (NumberFormatException e) {
286                                        logger.warn(entry.getKey() + " attribute in property \""
287                                                        + id + "\" getId in class \"" + classId
288                                                        + "\" should be an integer value");
289                                }
290                        }
291
292                        builder.setType(DecimalParam.class);
293                        builder.setMin(minMaxDefInt.get("MIN"));
294                        builder.setMax(minMaxDefInt.get("MAX"));
295                        builder.setDef(minMaxDefInt.get("DEF"));
296
297                } else if ("f".equals(type)) {
298
299                        Map<String, Double> minMaxDefDouble = new HashMap<String, Double>();
300                        for (Entry<String, String> entry : minMaxDef.entrySet()) {
301                                try {
302                                        minMaxDefDouble.put(entry.getKey(),
303                                                        Double.parseDouble(entry.getValue()));
304                                } catch (NumberFormatException e) {
305                                        logger.warn(entry.getKey() + " attribute in property \""
306                                                        + id + "\" getId in class \"" + classId
307                                                        + "\" should be a double value");
308                                }
309                        }
310                        builder.setType(FloatParam.class);
311                        builder.setMin(minMaxDefDouble.get("MIN"));
312                        builder.setMax(minMaxDefDouble.get("MAX"));
313                        builder.setDef(minMaxDefDouble.get("DEF"));
314
315
316                } else if ("s".equals(type)) {
317                        builder.setType(StringParam.class);
318                        builder.setDef(minMaxDef.get("DEF"));
319                } else {
320                        builder.setType(type);
321                }
322                return builder.build();
323        }
324
325
326        public Map<String, NeuroClass> getNeuroClasses() {
327                return Collections.unmodifiableMap(neuroClasses);
328        }
329
330        public final Registry getRegistry() {
331                return registry;
332        }
333
334
335}
Note: See TracBrowser for help on using the repository browser.