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