f18552c150c55a824f759339ef87eedc23748f68
[scilab.git] / scilab / modules / graphic_objects / src / java / org / scilab / modules / graphic_objects / xmlloader / XmlLoader.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2010-2011 - DIGITEO - Manuel JULIACHS
4  *
5  * This file must be used under the terms of the CeCILL.
6  * This source file is licensed as described in the file COPYING, which
7  * you should have received as part of this distribution.  The terms
8  * are also available at
9  * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
10  *
11  */
12
13 package org.scilab.modules.graphic_objects.xmlloader;
14
15 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UI_ENABLE__;
16 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_TAG__;
17 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_CHILDREN__;
18 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_AXES__;
19 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_CHILDREN__;
20 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_FIGURE__;
21 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_TYPE__;
22 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UIMENU__;
23 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UI_CHECKBOX__;
24 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UI_EDIT__;
25 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UI_FRAME__;
26 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UI_IMAGE__;
27 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UI_LAYER__;
28 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UI_LISTBOX__;
29 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UI_POPUPMENU__;
30 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UI_PUSHBUTTON__;
31 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UI_RADIOBUTTON__;
32 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UI_SLIDER__;
33 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UI_SPINNER__;
34 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UI_TAB__;
35 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UI_TEXT__;
36
37 import java.io.File;
38 import java.io.FileInputStream;
39 import java.io.FileNotFoundException;
40 import java.io.IOException;
41 import java.util.AbstractMap.SimpleEntry;
42 import java.util.HashMap;
43 import java.util.Map;
44 import java.util.Map.Entry;
45 import java.util.Set;
46 import java.util.Stack;
47
48 import javax.xml.parsers.SAXParser;
49 import javax.xml.parsers.SAXParserFactory;
50
51 import org.scilab.modules.commons.CommonFileUtils;
52 import org.scilab.modules.commons.gui.FindIconHelper;
53 import org.scilab.modules.graphic_objects.ScilabNativeView;
54 import org.scilab.modules.graphic_objects.builder.Builder;
55 import org.scilab.modules.graphic_objects.graphicController.GraphicController;
56 import org.scilab.modules.graphic_objects.graphicModel.GraphicModel;
57 import org.scilab.modules.graphic_objects.graphicObject.GraphicObject.Type;
58 import org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties;
59 import org.xml.sax.Attributes;
60 import org.xml.sax.Locator;
61 import org.xml.sax.SAXException;
62 import org.xml.sax.helpers.DefaultHandler;
63
64 public class XmlLoader extends DefaultHandler {
65
66     private String filename = "";
67     private Locator locator;
68     private Integer uid = 0;
69     private String namespace = null;
70     private boolean isWaitingModelName = true;
71     private String myURI = "";
72     private boolean isFirst = false;
73
74     private static HashMap<String, Integer> nameToGO = new HashMap<String, Integer>();
75     private static HashMap<String, HashMap<String, Entry<Integer, Map<String, String>>>> models = new HashMap<String, HashMap<String, Entry<Integer, Map<String, String>>>>();
76     private Stack<Integer> stackGO = new Stack<Integer>();
77     private String currentPath = "";
78
79     private GraphicController controller;
80
81     static {
82         // init map to convert control name to id
83         nameToGO.put("UIScilabWindow", __GO_FIGURE__);
84
85         nameToGO.put("UIPanel", __GO_UI_FRAME__);
86         nameToGO.put("UIFrame", __GO_UI_FRAME__);
87         nameToGO.put("UILayer", __GO_UI_LAYER__);
88         nameToGO.put("UIButton", __GO_UI_PUSHBUTTON__);
89         nameToGO.put("UILabel", __GO_UI_TEXT__);
90         nameToGO.put("UILaTeXLabel", -1);
91         nameToGO.put("UICheckbox", __GO_UI_CHECKBOX__);
92         nameToGO.put("UITextfield", __GO_UI_EDIT__);
93         nameToGO.put("UISplashScreen", __GO_UI_IMAGE__);
94         nameToGO.put("UIList", __GO_UI_LISTBOX__);
95         nameToGO.put("UIComboBox", __GO_UI_POPUPMENU__);
96         nameToGO.put("UIComboColor", __GO_UI_POPUPMENU__);
97         nameToGO.put("UIRadio", __GO_UI_RADIOBUTTON__);
98         nameToGO.put("UISlider", __GO_UI_SLIDER__);
99         nameToGO.put("UITab", __GO_UI_TAB__);
100         nameToGO.put("UIScilabPlot", __GO_AXES__);
101         nameToGO.put("UINumberSpinner", __GO_UI_SPINNER__);
102
103
104         /** sdsdf*/
105         nameToGO.put("UITextarea", __GO_UI_EDIT__);
106
107         nameToGO.put("UIMenu", __GO_UIMENU__);
108         nameToGO.put("UIMenuItem", __GO_UIMENU__);
109
110     }
111
112     public XmlLoader(String filename) {
113         controller = GraphicController.getController();
114         this.filename = filename;
115     }
116
117     public int parse() throws SAXException {
118         int ret = 0;
119         if (filename != null && filename.equals("") == false) {
120             ret = parse(filename);
121         }
122
123         // clean model before leave.
124         Set<String> entries = models.keySet();
125         for (String key : entries) {
126             HashMap<String, Entry<Integer, Map<String, String>>> map = models.get(key);
127             Set<String> entries2 = map.keySet();
128             for (String key2 : entries2) {
129                 deleteObject(map.get(key2).getKey());
130             }
131         }
132
133         return ret;
134     }
135
136     public int parse(String filename) throws SAXException {
137         this.filename = filename;
138         File f = new File(filename);
139         if (f.exists()) {
140             //add filename filepath in ScilabSwingUtilities paths
141             if (f.isAbsolute()) {
142                 String filePath = f.getAbsolutePath();
143                 currentPath = filePath.substring(0, filePath.lastIndexOf(File.separator));
144                 FindIconHelper.addThemePath(currentPath);
145             } else {
146                 String initialDirectoryPath = CommonFileUtils.getCWD();
147                 String filePath = "";
148                 Integer index = filename.lastIndexOf(File.separator);
149                 if (index != -1) {
150                     filePath = filename.substring(0, index);
151                 }
152                 currentPath = initialDirectoryPath + File.separator + filePath;
153                 FindIconHelper.addThemePath(currentPath);
154             }
155         } else {
156             //try to find file in currentPath
157             if (f.isAbsolute()) {
158                 //failed
159                 return 1;
160             }
161
162             f = new File(currentPath + File.separator + filename);
163             if (f.exists() == false) {
164                 return 1;
165             }
166         }
167
168         FileInputStream in = null;
169         try {
170             in = new FileInputStream(f);
171         } catch (FileNotFoundException e1) {
172             e1.printStackTrace();
173             return 1;
174         }
175
176         SAXParser parser;
177         try {
178             SAXParserFactory factory;
179             factory = SAXParserFactory.newInstance();
180             factory.setValidating(false);
181             factory.setNamespaceAware(true);
182             factory.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
183             parser = factory.newSAXParser();
184         } catch (Exception e) {
185             try {
186                 in.close();
187             } catch (IOException e1) {
188                 e1.printStackTrace();
189                 return 1;
190             }
191             throw new SAXException(String.format("Cannot initialize the XML parser: %s", e.getMessage()));
192         }
193
194         try {
195             parser.parse(in, this);
196         } catch (SAXException e) {
197             if (locator != null) {
198                 throw new SAXException(String.format("Parse error at line %d: %s", locator.getLineNumber(), e.getMessage()));
199             } else {
200                 throw new SAXException(String.format("Parse error: %s", e.getMessage()));
201             }
202         } catch (IOException e) {
203             e.printStackTrace();
204         } finally {
205             try {
206                 in.close();
207             } catch (IOException e) {
208             }
209         }
210
211         return uid;
212     }
213
214     public void characters(char[] ch, int start, int length) throws SAXException {
215         super.characters(ch, start, length);
216     }
217
218     public void endDocument() throws SAXException {
219     }
220
221     public void endElement(String uri, String localName, String qName) throws SAXException {
222
223         if (localName.equals("modele")) {
224             namespace = null;
225             isWaitingModelName = false;
226         }
227
228         if (stackGO.size() != 0) {
229             Integer go = stackGO.pop();
230             if (go == null) {
231                 //nothing to do
232             } else if (stackGO.size() > 0) {
233                 Integer parent = stackGO.peek();
234
235                 controller.setGraphicObjectRelationship(parent, go);
236                 //controller.setProperty(go, __GO_VISIBLE__, true);
237             } else {
238                 uid = go;
239             }
240         }
241     }
242
243     public void setDocumentLocator(Locator locator) {
244         this.locator = locator;
245     }
246
247     public void startDocument() throws SAXException {
248         isFirst = true;
249     }
250
251     public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
252         if (localName.equals("interface")) {
253             if (isFirst) {
254                 myURI = attributes.getValue("xmlns");
255                 isFirst = false;
256             }
257         } else if (localName.equals("include")) {
258             String path = attributes.getValue("path");
259             parse(path);
260         } else if (localName.equals("modele")) {
261             namespace = attributes.getValue("namespace");
262             isWaitingModelName = true;
263         } else {
264             Integer uitype = getTypeFromName(localName);
265             Integer go = 0;
266             if (uitype != null) {
267                 if (uitype == __GO_FIGURE__) {
268                     // never create a new figure, clone figure model !
269                     go = GOBuilder.figureBuilder(controller, attributes);
270                 } else if (uitype == __GO_AXES__) {
271                     go = GraphicController.getController().askObject(Type.AXES);
272                 } else if (uitype == __GO_UIMENU__) {
273                     Integer parent = 0;
274                     if (stackGO.isEmpty() == false) {
275                         parent = stackGO.peek();
276                     }
277
278                     go = GOBuilder.uimenuBuilder(controller, attributes, parent);
279                 } else {
280                     Integer parent = 0;
281                     if (stackGO.isEmpty() == false) {
282                         parent = stackGO.peek();
283                     }
284
285                     go = GOBuilder.uicontrolBuilder(controller, uitype, attributes, parent);
286                 }
287             } else { // namespace or bad name ...
288                 if (myURI.equals(uri)) {
289                     // bad name
290                 } else {
291                     HashMap<String, Entry<Integer, Map<String, String>>> m = models.get(uri);
292                     if (m == null) {
293                         // bad namespace
294                     } else {
295                         Entry<Integer, Map<String, String>> entry = m.get(localName);
296                         go = entry.getKey();
297                         // need to clone object and children
298                         Integer newgo = cloneObject(go);
299                         GOBuilder.uicontrolUpdater(controller, newgo, attributes, stackGO.peek(), entry.getValue());
300                         go = newgo;
301
302                     }
303                 }
304             }
305
306             // we are in a model
307             // the first child must have field "model-name"
308             if (namespace != null) {
309                 if (isWaitingModelName) {
310                     String name = attributes.getValue("modele-name");
311                     if (name == null) {
312                         // unmaned model ? :s
313                     } else {
314                         if (models.get(namespace) == null) {
315                             models.put(namespace, new HashMap<String, Entry<Integer, Map<String, String>>>());
316                         }
317
318                         // copy attributes to a Map, i do not know why a can use
319                         // attributes ? Oo
320                         Map<String, String> attrib = new HashMap<String, String>();
321                         for (int i = 0; i < attributes.getLength(); i++) {
322                             attrib.put(attributes.getLocalName(i), attributes.getValue(i));
323                         }
324
325                         // add root element in map model
326                         models.get(namespace).put(name, new SimpleEntry<Integer, Map<String, String>>(go, attrib));
327                     }
328                 }
329             }
330
331             stackGO.add(go);
332         }
333     }
334
335     Integer cloneObject(Integer root) {
336         Integer newGo = controller.cloneObject(root);
337         Integer[] children = (Integer[]) controller.getProperty(root, __GO_CHILDREN__);
338         for (int i = children.length - 1; i >= 0 ; i--) {
339             if ((Integer)controller.getProperty(children[i], __GO_TYPE__) == __GO_AXES__) {
340                 Integer go = controller.cloneObject(GraphicModel.getAxesModel().getIdentifier());
341                 Builder.createLabel(go, GraphicObjectProperties.__GO_X_AXIS_LABEL__);
342                 Builder.createLabel(go, GraphicObjectProperties.__GO_Y_AXIS_LABEL__);
343                 Builder.createLabel(go, GraphicObjectProperties.__GO_Z_AXIS_LABEL__);
344                 Builder.createLabel(go, GraphicObjectProperties.__GO_TITLE__);
345
346                 controller.setGraphicObjectRelationship(newGo, go);
347                 controller.setProperty(newGo, GraphicObjectProperties.__GO_SELECTED_CHILD__, go);
348
349                 ScilabNativeView.ScilabNativeView__setCurrentSubWin(go);
350                 ScilabNativeView.ScilabNativeView__setCurrentObject(go);
351             } else {
352                 Integer newChild = cloneObject(children[i]);
353                 controller.setGraphicObjectRelationship(newGo, newChild);
354             }
355         }
356
357         return newGo;
358     }
359
360     private void deleteObject(Integer root) {
361         Integer[] children = (Integer[]) controller.getProperty(root, __GO_CHILDREN__);
362         for (int i = 0; i < children.length; i++) {
363             deleteObject(children[i]);
364         }
365
366         controller.deleteObject(root);
367     }
368
369     private Integer getTypeFromName(String localName) {
370         return nameToGO.get(localName);
371     }
372 }