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

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

Add new java codebase.

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