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