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
6 * Copyright (C) 2012 - 2016 - Scilab Enterprises
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.
17 package org.scilab.modules.xcos.io.codec;
19 import java.lang.reflect.Constructor;
20 import java.lang.reflect.Field;
21 import java.lang.reflect.Method;
23 import java.util.WeakHashMap;
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;
32 import com.mxgraph.io.mxCellCodec;
33 import com.mxgraph.io.mxCodec;
34 import com.mxgraph.model.mxICell;
35 import com.mxgraph.util.mxConstants;
36 import org.scilab.modules.xcos.utils.XcosConstants;
39 * Codec for any xcos object
41 public class XcosObjectCodec extends mxCellCodec {
43 * Refs field for codecs
45 protected static final String[] REFS = { "parent", "source", "target" };
48 * Cache fields and accessors
50 protected Map<Class<?>, Map<String, Field>> fields = new WeakHashMap<>();
51 protected Map<Class<?>, Map<Field, Method>> getters = new WeakHashMap<>();
52 protected Map<Class<?>, Map<Field, Method>> setters = new WeakHashMap<>();
55 * Attribute name containing {@link com.mxgraph.model.mxCell} style.
57 protected static final String STYLE = "style";
58 private static final String DIRECTION = "direction";
59 private static final String WEST = "west";
60 private static final String SOUTH = "south";
61 private static final String EAST = "east";
63 private static final int DIRECTION_STEP = 90;
66 * The constructor used on for configuration
69 * Prototypical instance of the object to be encoded/decoded.
71 * Optional array of fieldnames to be ignored.
73 * Optional array of fieldnames to be converted to/from
76 * Optional mapping from field- to attributenames.
78 public XcosObjectCodec(Object template, String[] exclude, String[] idrefs, Map<String, String> mapping) {
79 super(template, exclude, idrefs, mapping);
86 * Overridden for performance issues.
89 protected Method getAccessor(Object obj, Field field, boolean isGetter) {
93 final Class<?> type = obj.getClass();
95 Map<Field, Method> map;
97 map = getters.get(type);
99 map = setters.get(type);
102 map = new WeakHashMap<Field, Method>();
104 getters.put(type, map);
106 setters.put(type, map);
110 Method m = map.get(field);
116 * Cache is empty, look for the accessor
118 m = super.getAccessor(obj, field, isGetter);
129 * Overridden for performance issues.
132 protected Field getField(Object obj, String fieldname) {
136 final Class<?> type = obj.getClass();
138 Map<String, Field> map = fields.get(type);
140 map = new WeakHashMap<String, Field>();
141 fields.put(type, map);
144 Field f = map.get(fieldname);
150 * Cache is empty, look for the field
152 f = super.getField(obj, fieldname);
154 map.put(fieldname, f);
163 * Clone the object while preserving UID / Kind allocation
167 protected Object cloneTemplate(Node node) {
171 if (template.getClass().isEnum()) {
172 obj = template.getClass().getEnumConstants()[0];
174 if (XcosCell.class.isAssignableFrom(template.getClass())) {
175 JavaController controller = new JavaController();
176 Kind kind = ((XcosCell) template).getKind();
178 Constructor<? extends Object> cstrs = template.getClass().getConstructor(Long.TYPE);
179 obj = cstrs.newInstance(controller.createObject(kind));
181 obj = template.getClass().newInstance();
185 } catch (ReflectiveOperationException e) {
188 } catch (SecurityException e) {
198 * Apply compatibility pattern to the decoded object
201 * Codec that controls the decoding process.
203 * XML node to decode the object from.
206 * @return The Object transformed
207 * @see org.scilab.modules.xcos.io.codec.XcosObjectCodec#afterDecode(com.mxgraph.io.mxCodec,
208 * org.w3c.dom.Node, java.lang.Object)
211 public Object afterDecode(mxCodec dec, Node node, Object obj) {
212 if (obj instanceof mxICell) {
213 final mxICell cell = (mxICell) obj;
215 final Node id = node.getAttributes().getNamedItem("id");
217 cell.setId(id.getNodeValue());
221 return super.afterDecode(dec, node, obj);
226 * the style to be formatted
228 public void formatStyle(StyleMap style) {
229 if (style.containsKey(DIRECTION)) {
230 String direction = style.get(DIRECTION);
234 if (direction.compareTo(EAST) == 0) {
237 angle += DIRECTION_STEP;
238 if (direction.compareTo(SOUTH) == 0) {
241 angle += DIRECTION_STEP;
242 if (direction.compareTo(WEST) == 0) {
245 angle += DIRECTION_STEP;
248 style.remove(DIRECTION);
249 style.put(XcosConstants.STYLE_ROTATION, Integer.toString(angle));
253 if (!style.containsKey(ScilabGraphConstants.STYLE_FLIP)) {
254 style.put(XcosConstants.STYLE_FLIP, Boolean.FALSE.toString());
257 if (!style.containsKey(ScilabGraphConstants.STYLE_MIRROR)) {
258 style.put(XcosConstants.STYLE_MIRROR, Boolean.FALSE.toString());
263 * Trace any msg to the xml document.
266 * the current encoder
274 protected void trace(mxCodec enc, Node node, String msg, Object... format) {
275 node.appendChild(enc.getDocument().createComment(String.format(msg, format)));