Xcos java: remove unnecessary imports
[scilab.git] / scilab / modules / xcos / src / java / org / scilab / modules / xcos / io / codec / XcosObjectCodec.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2009 - DIGITEO - Bruno JOFRET
4  * Copyright (C) 2014 - Scilab Enterprises - Clement DAVID
5  *
6  * Copyright (C) 2012 - 2016 - Scilab Enterprises
7  *
8  * This file is hereby licensed under the terms of the GNU GPL v2.0,
9  * pursuant to article 5.3.4 of the CeCILL v.2.1.
10  * This file was originally licensed under the terms of the CeCILL v2.1,
11  * and continues to be available under such terms.
12  * For more information, see the COPYING file which you should have received
13  * along with this program.
14  *
15  */
16
17 package org.scilab.modules.xcos.io.codec;
18
19 import java.lang.reflect.Constructor;
20 import java.lang.reflect.Field;
21 import java.lang.reflect.Method;
22 import java.util.Map;
23 import java.util.WeakHashMap;
24
25 import org.scilab.modules.graph.utils.ScilabGraphConstants;
26 import org.scilab.modules.graph.utils.StyleMap;
27 import org.scilab.modules.xcos.JavaController;
28 import org.scilab.modules.xcos.Kind;
29 import org.scilab.modules.xcos.graph.model.XcosCell;
30 import org.w3c.dom.Node;
31
32 import com.mxgraph.io.mxCellCodec;
33 import com.mxgraph.io.mxCodec;
34 import com.mxgraph.model.mxICell;
35 import org.scilab.modules.xcos.utils.XcosConstants;
36
37 /**
38  * Codec for any xcos object
39  */
40 public class XcosObjectCodec extends mxCellCodec {
41     /**
42      * Refs field for codecs
43      */
44     protected static final String[] REFS = { "parent", "source", "target" };
45
46     /*
47      * Cache fields and accessors
48      */
49     protected Map<Class<?>, Map<String, Field>> fields = new WeakHashMap<>();
50     protected Map<Class<?>, Map<Field, Method>> getters = new WeakHashMap<>();
51     protected Map<Class<?>, Map<Field, Method>> setters = new WeakHashMap<>();
52
53     /**
54      * Attribute name containing {@link com.mxgraph.model.mxCell} style.
55      */
56     protected static final String STYLE = "style";
57     private static final String DIRECTION = "direction";
58     private static final String WEST = "west";
59     private static final String SOUTH = "south";
60     private static final String EAST = "east";
61
62     private static final int DIRECTION_STEP = 90;
63
64     /**
65      * The constructor used on for configuration
66      *
67      * @param template
68      *            Prototypical instance of the object to be encoded/decoded.
69      * @param exclude
70      *            Optional array of fieldnames to be ignored.
71      * @param idrefs
72      *            Optional array of fieldnames to be converted to/from
73      *            references.
74      * @param mapping
75      *            Optional mapping from field- to attributenames.
76      */
77     public XcosObjectCodec(Object template, String[] exclude, String[] idrefs, Map<String, String> mapping) {
78         super(template, exclude, idrefs, mapping);
79
80     }
81
82     /**
83      * {@inheritDoc}
84      *
85      * Overridden for performance issues.
86      */
87     @Override
88     protected Method getAccessor(Object obj, Field field, boolean isGetter) {
89         /*
90          * Cache the object
91          */
92         final Class<?> type = obj.getClass();
93
94         Map<Field, Method> map;
95         if (isGetter) {
96             map = getters.get(type);
97         } else {
98             map = setters.get(type);
99         }
100         if (map == null) {
101             map = new WeakHashMap<Field, Method>();
102             if (isGetter) {
103                 getters.put(type, map);
104             } else {
105                 setters.put(type, map);
106             }
107         }
108
109         Method m = map.get(field);
110         if (m != null) {
111             return m;
112         }
113
114         /*
115          * Cache is empty, look for the accessor
116          */
117         m = super.getAccessor(obj, field, isGetter);
118         if (m != null) {
119             map.put(field, m);
120         }
121
122         return m;
123     }
124
125     /**
126      * {@inheritDoc}
127      *
128      * Overridden for performance issues.
129      */
130     @Override
131     protected Field getField(Object obj, String fieldname) {
132         /*
133          * Cache the object
134          */
135         final Class<?> type = obj.getClass();
136
137         Map<String, Field> map = fields.get(type);
138         if (map == null) {
139             map = new WeakHashMap<String, Field>();
140             fields.put(type, map);
141         }
142
143         Field f = map.get(fieldname);
144         if (f != null) {
145             return f;
146         }
147
148         /*
149          * Cache is empty, look for the field
150          */
151         f = super.getField(obj, fieldname);
152         if (f != null) {
153             map.put(fieldname, f);
154         }
155
156         return f;
157     }
158
159     /**
160      * {@inheritDoc}
161      *
162      * Clone the object while preserving UID / Kind allocation
163      *
164      */
165     @Override
166     protected Object cloneTemplate(Node node) {
167         Object obj = null;
168
169         try {
170             if (template.getClass().isEnum()) {
171                 obj = template.getClass().getEnumConstants()[0];
172             } else {
173                 if (XcosCell.class.isAssignableFrom(template.getClass())) {
174                     JavaController controller = new JavaController();
175                     Kind kind = ((XcosCell) template).getKind();
176
177                     Constructor<? extends Object> cstrs = template.getClass().getConstructor(Long.TYPE);
178                     obj = cstrs.newInstance(controller.createObject(kind));
179                 } else {
180                     obj = template.getClass().newInstance();
181                 }
182             }
183
184         } catch (ReflectiveOperationException e) {
185             // ignore
186             e.printStackTrace();
187         } catch (SecurityException e) {
188             // ignore
189             e.printStackTrace();
190         }
191
192         return obj;
193
194     }
195
196     /**
197      * Apply compatibility pattern to the decoded object
198      *
199      * @param dec
200      *            Codec that controls the decoding process.
201      * @param node
202      *            XML node to decode the object from.
203      * @param obj
204      *            Object decoded.
205      * @return The Object transformed
206      * @see org.scilab.modules.xcos.io.codec.XcosObjectCodec#afterDecode(com.mxgraph.io.mxCodec,
207      *      org.w3c.dom.Node, java.lang.Object)
208      */
209     @Override
210     public Object afterDecode(mxCodec dec, Node node, Object obj) {
211         if (obj instanceof mxICell) {
212             final mxICell cell = (mxICell) obj;
213
214             final Node id = node.getAttributes().getNamedItem("id");
215             if (id != null) {
216                 cell.setId(id.getNodeValue());
217             }
218
219         }
220         return super.afterDecode(dec, node, obj);
221     }
222
223     /**
224      * @param style
225      *            the style to be formatted
226      */
227     public void formatStyle(StyleMap style) {
228         if (style.containsKey(DIRECTION)) {
229             String direction = style.get(DIRECTION);
230
231             int angle = 0;
232             do {
233                 if (direction.compareTo(EAST) == 0) {
234                     break;
235                 }
236                 angle += DIRECTION_STEP;
237                 if (direction.compareTo(SOUTH) == 0) {
238                     break;
239                 }
240                 angle += DIRECTION_STEP;
241                 if (direction.compareTo(WEST) == 0) {
242                     break;
243                 }
244                 angle += DIRECTION_STEP;
245             } while (false);
246
247             style.remove(DIRECTION);
248             style.put(XcosConstants.STYLE_ROTATION, Integer.toString(angle));
249
250         }
251
252         if (!style.containsKey(ScilabGraphConstants.STYLE_FLIP)) {
253             style.put(XcosConstants.STYLE_FLIP, Boolean.FALSE.toString());
254         }
255
256         if (!style.containsKey(ScilabGraphConstants.STYLE_MIRROR)) {
257             style.put(XcosConstants.STYLE_MIRROR, Boolean.FALSE.toString());
258         }
259     }
260
261     /**
262      * Trace any msg to the xml document.
263      *
264      * @param enc
265      *            the current encoder
266      * @param node
267      *            the current node
268      * @param msg
269      *            the message
270      * @param format
271      *            the format
272      */
273     protected void trace(mxCodec enc, Node node, String msg, Object... format) {
274         node.appendChild(enc.getDocument().createComment(String.format(msg, format)));
275     }
276 }