c521c927b6a198c3c42032398edf4e7ee14a94ae
[scilab.git] / scilab / modules / xcos / src / java / org / scilab / modules / xcos / graph / model / XcosCellFactory.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2009 - DIGITEO - Clement DAVID
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.xcos.graph.model;
14
15 import java.lang.reflect.InvocationTargetException;
16 import java.util.Arrays;
17 import java.util.EnumSet;
18
19 import org.scilab.modules.xcos.JavaController;
20 import org.scilab.modules.xcos.Kind;
21 import org.scilab.modules.xcos.ObjectProperties;
22 import org.scilab.modules.xcos.VectorOfScicosID;
23 import org.scilab.modules.xcos.block.AfficheBlock;
24 import org.scilab.modules.xcos.block.BasicBlock;
25 import org.scilab.modules.xcos.block.SplitBlock;
26 import org.scilab.modules.xcos.block.SuperBlock;
27 import org.scilab.modules.xcos.block.TextBlock;
28 import org.scilab.modules.xcos.block.io.EventInBlock;
29 import org.scilab.modules.xcos.block.io.EventOutBlock;
30 import org.scilab.modules.xcos.block.io.ExplicitInBlock;
31 import org.scilab.modules.xcos.block.io.ExplicitOutBlock;
32 import org.scilab.modules.xcos.block.io.ImplicitInBlock;
33 import org.scilab.modules.xcos.block.io.ImplicitOutBlock;
34 import org.scilab.modules.xcos.block.positionning.BigSom;
35 import org.scilab.modules.xcos.block.positionning.GroundBlock;
36 import org.scilab.modules.xcos.block.positionning.Product;
37 import org.scilab.modules.xcos.block.positionning.RoundBlock;
38 import org.scilab.modules.xcos.block.positionning.Summation;
39 import org.scilab.modules.xcos.block.positionning.VoltageSensorBlock;
40 import org.scilab.modules.xcos.graph.XcosDiagram;
41 import org.scilab.modules.xcos.port.BasicPort;
42 import org.scilab.modules.xcos.port.command.CommandPort;
43 import org.scilab.modules.xcos.port.control.ControlPort;
44 import org.scilab.modules.xcos.port.input.ExplicitInputPort;
45 import org.scilab.modules.xcos.port.input.ImplicitInputPort;
46 import org.scilab.modules.xcos.port.output.ExplicitOutputPort;
47 import org.scilab.modules.xcos.port.output.ImplicitOutputPort;
48 import com.mxgraph.model.mxCell;
49 import com.mxgraph.model.mxICell;
50
51 /**
52  * Ease the creation of any {@link Kind} of graphical object
53  */
54 public final class XcosCellFactory {
55
56     // DAC: As this is the constructor for all the block classes, this class is
57     // very coupled with *Block classes
58     // CSOFF: ClassDataAbstractionCoupling
59     /**
60      * List the specific block interface function name. <BR>
61      * <BR>
62      * <EM>Specific instance must be registered before generic ones in order
63      * to serialized all the non-default values.</EM>
64      */
65     public static enum BlockInterFunction {
66         /** @see TextBlock */
67         TEXT_f(TextBlock.class),
68         /** @see SuperBlock */
69         DSUPER(SuperBlock.class),
70         /** @see SuperBlock */
71         SUPER_f(SuperBlock.class),
72         /** @see AfficheBlock */
73         AFFICH_m(AfficheBlock.class),
74         /** @see AfficheBlock */
75         AFFICH_f(AfficheBlock.class),
76         /** @see ExplicitInBlock */
77         IN_f(ExplicitInBlock.class),
78         /** @see ExplicitOutBlock */
79         OUT_f(ExplicitOutBlock.class),
80         /** @see ImplicitInBlock */
81         INIMPL_f(ImplicitInBlock.class),
82         /** @see ImplicitOutBlock */
83         OUTIMPL_f(ImplicitOutBlock.class),
84         /** @see EventInBlock */
85         CLKINV_f(EventInBlock.class),
86         /** @see EventOutBlock */
87         CLKOUTV_f(EventOutBlock.class),
88         /** @see EventOutBlock */
89         CLKOUT_f(EventOutBlock.class),
90         /** @see SplitBlock */
91         SPLIT_f(SplitBlock.class),
92         /** @see SplitBlock */
93         IMPSPLIT_f(SplitBlock.class),
94         /** @see SplitBlock */
95         CLKSPLIT_f(SplitBlock.class),
96         /** @see GroundBlock */
97         Ground(GroundBlock.class),
98         /** @see VoltageSensorBlock */
99         VoltageSensor(VoltageSensorBlock.class),
100         /** @see RoundBlock */
101         SUM_f(RoundBlock.class),
102         /** @see RoundBlock */
103         PROD_f(RoundBlock.class),
104         /** @see RoundBlock */
105         CLKSOM_f(RoundBlock.class),
106         /** @see RoundBlock */
107         CLKSOMV_f(RoundBlock.class),
108         /** @see BigSom */
109         BIGSOM_f(BigSom.class),
110         /** @see Summation */
111         SUMMATION(Summation.class),
112         /** @see Product */
113         PRODUCT(Product.class),
114         /** @see BasicBlock */
115         BASIC_BLOCK(BasicBlock.class);
116
117         private final Class<? extends BasicBlock> klass;
118
119         /**
120          * Default constructor
121          *
122          * @param block
123          *            The reference instance
124          */
125         private BlockInterFunction(Class<? extends BasicBlock> klass) {
126             this.klass = klass;
127         }
128
129         /**
130          * @return the class to instantiate
131          */
132         public Class<? extends BasicBlock> getKlass() {
133             return klass;
134         }
135     }
136
137     // CSON: ClassDataAbstractionCoupling
138
139     /** Default singleton constructor */
140     private XcosCellFactory() {
141         // This class is a static singleton
142     }
143
144     /*
145      * Block and Annotation management
146      */
147
148     /**
149      * Instantiate a new block with the specified UID value.
150      *
151      * @param uid
152      *            The associated UID value
153      * @return A new instance of a block.
154      */
155     public static BasicBlock createBlock(long uid) {
156         BasicBlock block = null;
157
158         JavaController controller = new JavaController();
159         String[] interfaceFunction = new String[1];
160         controller.getObjectProperty(uid, Kind.BLOCK, ObjectProperties.INTERFACE_FUNCTION, interfaceFunction);
161
162         for (BlockInterFunction func : BlockInterFunction.values()) {
163             if (func.name().equals(interfaceFunction)) {
164                 block = createBlock(controller, func, uid);
165                 break;
166             }
167         }
168
169         if (block == null) {
170             block = createBlock(controller, BlockInterFunction.BASIC_BLOCK, uid);
171             block.setStyle(interfaceFunction[0]);
172         }
173
174         return block;
175     }
176
177     /**
178      * Instantiate a new block with the specified interface function.
179      *
180      * @param func
181      *            the interface function
182      * @return A new instance of a block.
183      */
184     public static BasicBlock createBlock(BlockInterFunction func) {
185         JavaController controller = new JavaController();
186
187         long uid = controller.createObject(Kind.BLOCK);
188         return createBlock(controller, func, uid);
189     }
190
191     /**
192      * Instantiate a new block with the specified interface function and uid.
193      *
194      * @param controller the Java controller to use
195      * @param func the interface function
196      * @param uid the allocated uid
197      * @return A new instance of a block.
198      */
199     public static BasicBlock createBlock(final JavaController controller, BlockInterFunction func, long uid) {
200         BasicBlock block = null;
201         try {
202             block = func.getKlass().getConstructor(Long.TYPE).newInstance(uid);
203         } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) {
204             // Something goes wrong, print it.
205             e.printStackTrace();
206             return block;
207         }
208
209         insertPortChildren(controller, block);
210         return block;
211     }
212
213     /*
214      * Port management
215      */
216
217
218     /**
219      * Helper used to create port children on a parent block.
220      *
221      * This method does not manage the model transaction and should be used to preset the children of a block out of an {@link XcosDiagram}.
222      *
223      * @param controller is the shared controller instance
224      * @param parent is the parent {@link mxCell} to modify
225      */
226     public static void insertPortChildren(final JavaController controller, final XcosCell parent) {
227         final EnumSet<ObjectProperties> properties = EnumSet.of(ObjectProperties.INPUTS, ObjectProperties.OUTPUTS, ObjectProperties.EVENT_INPUTS, ObjectProperties.EVENT_OUTPUTS);
228         insertPortChildren(controller, properties, parent);
229     }
230
231
232     /**
233      * Helper used to create port children on a parent block.
234      *
235      * This method does not manage the model transaction and should be used to preset the children of a block out of an {@link XcosDiagram}.
236      *
237      * @param controller is the shared controller instance
238      * @param properties specify the kind of port to insert and should be some of : <UL>
239      *        <LI>{@link ObjectProperties#INPUTS}
240      *        <LI>{@link ObjectProperties#OUTPUTS}
241      *        <LI>{@link ObjectProperties#EVENT_INPUTS}
242      *        <LI>{@link ObjectProperties#EVENT_OUTPUTS}
243      * @param parent is the parent {@link mxCell} to modify
244      */
245     public static void insertPortChildren(final JavaController controller, final EnumSet<ObjectProperties> properties, final XcosCell parent) {
246         for (ObjectProperties property : properties) {
247             insertPortChildren(controller, property, parent);
248         }
249     }
250
251     /**
252      * Helper used to create port children on a parent block.
253      *
254      * This method does not manage the model transaction and should be used to preset the children of a block out of an {@link XcosDiagram}.
255      *
256      * @param controller is the shared controller instance
257      * @param property specify the kind of port to insert and should be one of : <UL>
258      *        <LI>{@link ObjectProperties#INPUTS}
259      *        <LI>{@link ObjectProperties#OUTPUTS}
260      *        <LI>{@link ObjectProperties#EVENT_INPUTS}
261      *        <LI>{@link ObjectProperties#EVENT_OUTPUTS}
262      * @param parent is the parent {@link mxCell} to modify
263      */
264     public static void insertPortChildren(final JavaController controller, final ObjectProperties property, final XcosCell parent) {
265         if (parent.getKind() != Kind.BLOCK) {
266             return;
267         }
268
269         VectorOfScicosID modelChildren = new VectorOfScicosID();
270         controller.getObjectProperty(parent.getUID(), parent.getKind(), property, modelChildren);
271
272         mxICell[] children = new mxICell[modelChildren.size()];
273         for (int i = 0; i < children.length; i++) {
274             children[i] = createPort(controller, modelChildren.get(i), property);
275         }
276         Arrays.stream(children).forEach(c -> parent.insert(c));
277     }
278
279     /**
280      * Create a port for a specific uid
281      *
282      * @param controller is the shared controller instance
283      * @param uid represent the allocated UID on the MVC
284      * @param property specify the kind of port to create and should be one of : <UL>
285      *        <LI>{@link ObjectProperties#INPUTS}
286      *        <LI>{@link ObjectProperties#OUTPUTS}
287      *        <LI>{@link ObjectProperties#EVENT_INPUTS}
288      *        <LI>{@link ObjectProperties#EVENT_OUTPUTS}
289      * @return a newly allocated port
290      */
291     private static final BasicPort createPort(final JavaController controller, long uid, final ObjectProperties property) {
292         boolean[] isImplicit = {false};
293
294         switch (property) {
295             case INPUTS:
296                 controller.getObjectProperty(uid, Kind.PORT, ObjectProperties.IMPLICIT, isImplicit);
297                 if (isImplicit[0]) {
298                     return new ImplicitInputPort(uid);
299                 } else {
300                     return new ExplicitInputPort(uid);
301                 }
302             case OUTPUTS:
303                 controller.getObjectProperty(uid, Kind.PORT, ObjectProperties.IMPLICIT, isImplicit);
304                 if (isImplicit[0]) {
305                     return new ImplicitOutputPort(uid);
306                 } else {
307                     return new ExplicitOutputPort(uid);
308                 }
309             case EVENT_INPUTS:
310                 return new ControlPort(uid);
311             case EVENT_OUTPUTS:
312                 return new CommandPort(uid);
313             default:
314                 return null;
315         }
316     }
317 }