2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2009 - DIGITEO - Clement DAVID
4 * Copyright (C) 2011-2015 - 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.block.io;
19 import com.mxgraph.model.mxGeometry;
20 import java.beans.PropertyChangeEvent;
21 import java.beans.PropertyChangeListener;
22 import java.io.Serializable;
23 import java.lang.reflect.Constructor;
24 import java.util.ArrayList;
25 import java.util.EnumMap;
26 import java.util.List;
28 import java.util.logging.Logger;
29 import java.util.regex.Pattern;
31 import org.scilab.modules.types.ScilabDouble;
32 import org.scilab.modules.types.ScilabString;
33 import org.scilab.modules.types.ScilabType;
34 import org.scilab.modules.xcos.JavaController;
35 import org.scilab.modules.xcos.Kind;
36 import org.scilab.modules.xcos.Xcos;
37 import org.scilab.modules.xcos.XcosView;
38 import org.scilab.modules.xcos.block.BasicBlock;
39 import org.scilab.modules.xcos.block.SuperBlock;
40 import org.scilab.modules.xcos.port.BasicPort;
41 import org.scilab.modules.xcos.port.command.CommandPort;
42 import org.scilab.modules.xcos.port.control.ControlPort;
43 import org.scilab.modules.xcos.port.input.ExplicitInputPort;
44 import org.scilab.modules.xcos.port.input.ImplicitInputPort;
45 import org.scilab.modules.xcos.port.input.InputPort;
46 import org.scilab.modules.xcos.port.output.ExplicitOutputPort;
47 import org.scilab.modules.xcos.port.output.ImplicitOutputPort;
48 import org.scilab.modules.xcos.port.output.OutputPort;
50 import com.mxgraph.model.mxICell;
51 import java.rmi.server.UID;
52 import org.scilab.modules.xcos.ObjectProperties;
55 * Common class for the SuperBlock I/O blocks (represent ports)
57 public abstract class ContextUpdate extends BasicBlock {
59 private static final Logger LOG_LOCAL = Logger.getLogger(ContextUpdate.class.getName());
60 private static final long serialVersionUID = 6076826729067963560L;
62 private static final double DEFAULT_WIDTH = 20.0;
63 private static final double DEFAULT_HEIGHT = 20.0;
66 * Implement a listener which update the value and refresh the view when the
67 * index of the port change.
69 @SuppressWarnings(value = { "serial" })
70 private static final class IndexChangeAdapter implements PropertyChangeListener, Serializable {
71 private static IndexChangeAdapter instance;
74 * Default constructor.
76 private IndexChangeAdapter() {
80 * @return the instance
82 public static synchronized IndexChangeAdapter getInstance() {
83 if (instance == null) {
84 instance = new IndexChangeAdapter();
90 * Update the value and refresh the graph view.
94 * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
97 public void propertyChange(PropertyChangeEvent evt) {
98 ScilabType data = (ScilabType) evt.getNewValue();
99 ContextUpdate ioBlock = (ContextUpdate) evt.getSource();
101 if (!data.isEmpty()) {
102 int newIndex = (int) ((ScilabDouble) data).getRealPart()[0][0];
105 if (evt.getOldValue() instanceof ScilabDouble && !((ScilabDouble) evt.getOldValue()).isEmpty()) {
106 oldIndex = (int) ((ScilabDouble) evt.getOldValue()).getRealPart()[0][0];
111 ioBlock.setValue(newIndex);
118 * Implement a listener to update the
119 * {@link ContextUpdate#isContextDependent} flag.
121 * @SuppressWarnings(value = { "serial" })
123 private static final class ExprsChangeAdapter implements PropertyChangeListener, Serializable {
124 private static final Pattern INTEGER_PATTERN = Pattern.compile("\\d+");
126 private static ExprsChangeAdapter instance;
129 * Default constructor
131 public ExprsChangeAdapter() {
135 * @return the shared instance
137 public static ExprsChangeAdapter getInstance() {
138 if (instance == null) {
139 instance = new ExprsChangeAdapter();
145 * isContextDependant field
149 * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
152 public void propertyChange(final PropertyChangeEvent evt) {
153 final ScilabType data = (ScilabType) evt.getNewValue();
154 final ContextUpdate ioBlock = (ContextUpdate) evt.getSource();
156 if (!data.isEmpty()) {
157 final String newIndex = ((ScilabString) data).getData()[0][0];
159 if (!INTEGER_PATTERN.matcher(newIndex).matches()) {
160 ioBlock.isContextDependent = true;
162 ioBlock.isContextDependent = false;
169 * This enum represent all the subclasses of ContextUpdate .
171 * It is used to easily loop over a BasicBlock I/O blocks
173 public static enum IOBlocks {
174 /** Map a control port to an event input block */
175 EventInBlock(EventInBlock.class, ControlPort.class, CommandPort.class, ControlPort.class),
176 /** Map a command port to an event output block */
177 EventOutBlock(EventOutBlock.class, CommandPort.class, ControlPort.class, CommandPort.class),
178 /** Map an explicit input port to an explicit input block */
179 ExplicitInBlock(ExplicitInBlock.class, ExplicitInputPort.class, ExplicitOutputPort.class, InputPort.class),
180 /** Map an explicit output port to an explicit output block */
181 ExplicitOutBlock(ExplicitOutBlock.class, ExplicitOutputPort.class, ExplicitInputPort.class, OutputPort.class),
182 /** Map an implicit input port to an implicit input block */
183 ImplicitInBlock(ImplicitInBlock.class, ImplicitInputPort.class, ImplicitOutputPort.class, InputPort.class),
184 /** Map an implicit output port to an implicit output block */
185 ImplicitOutBlock(ImplicitOutBlock.class, ImplicitOutputPort.class, ImplicitInputPort.class, OutputPort.class);
187 private final Class<? extends ContextUpdate> ioBlock;
188 private final Class<? extends BasicPort> port;
189 private final Class<? extends BasicPort> opposite;
190 private final Class<? extends BasicPort> assignement;
196 * the associated port class
198 * the opposite port class
200 private IOBlocks(Class<? extends ContextUpdate> ioBlock, Class<? extends BasicPort> port, Class<? extends BasicPort> opposite,
201 Class<? extends BasicPort> assignement) {
202 this.ioBlock = ioBlock;
204 this.opposite = opposite;
205 this.assignement = assignement;
209 * Get all the port of the SuperBlock parent.
213 * @return the port list mapped by port type
215 public static Map<IOBlocks, List<mxICell>> getAllPorts(SuperBlock parent) {
216 final EnumMap<IOBlocks, List<mxICell>> ret = new EnumMap<IOBlocks, List<mxICell>>(IOBlocks.class);
219 for (IOBlocks b : IOBlocks.values()) {
220 ret.put(b, new ArrayList<mxICell>());
223 /* Loop all over the children */
224 final int childCount = parent.getChildCount();
226 for (int i = 0; i < childCount; i++) {
227 final mxICell child = parent.getChildAt(i);
229 /* if compatible add it to the list */
230 for (IOBlocks b : IOBlocks.values()) {
231 if (child.getClass().equals(b.getReferencedPortClass())) {
232 ret.get(b).add(child);
241 * Get the ports of the super blocks with kind klass
244 * the parent {@link SuperBlock}
247 * @return the list of ports
249 public static List<mxICell> getPorts(SuperBlock parent, Class<? extends ContextUpdate> klass) {
250 List<mxICell> ret = new ArrayList<mxICell>();
252 /* Get the corresponding klass */
253 Class<? extends BasicPort> portKlass = null;
254 for (IOBlocks b : IOBlocks.values()) {
255 if (b.getReferencedClass().equals(klass)) {
256 portKlass = b.getAssignementCompatiblePortClass();
261 /* Loop all over the children */
262 final int childCount = parent.getChildCount();
264 for (int i = 0; i < childCount; i++) {
265 final mxICell child = parent.getChildAt(i);
267 if (portKlass.isInstance(child)) {
276 * Return the opposite of the port
280 * @return the opposite of klass
282 public static Class<? extends BasicPort> getOpposite(Class<? extends BasicPort> klass) {
283 for (IOBlocks b : IOBlocks.values()) {
284 if (b.getReferencedPortClass() == klass) {
285 return b.getOppositeClass();
292 * Create a corresponding I/O block
295 * the port used as an output
296 * @return the corresponding block
298 public static ContextUpdate createBlock(BasicPort port) {
299 for (IOBlocks io : IOBlocks.values()) {
300 if (io.getReferencedPortClass().isInstance(port)) {
302 JavaController controller = new JavaController();
304 // create the Input/Output block
305 Constructor<? extends ContextUpdate> blockCstr = io.getReferencedClass().getConstructor(JavaController.class);
306 ContextUpdate block = blockCstr.newInstance(controller);
308 // create the single port of the block
309 Constructor<? extends BasicPort> portCstr = io.getOppositeClass().getConstructor(
310 JavaController.class, Long.TYPE, Kind.class, Object.class, String.class, String.class);
311 BasicPort blockPort = portCstr.newInstance(
312 controller, controller.createObject(Kind.PORT), Kind.PORT, null, null, new UID().toString());
314 // inser the port into the newly created block
315 block.insert(blockPort);
318 } catch (ReflectiveOperationException e) {
319 Logger.getLogger(IOBlocks.class.getName()).severe(e.toString());
328 * @return referenced class
330 public Class<? extends ContextUpdate> getReferencedClass() {
335 * @return the port referenced class
337 public Class<? extends BasicPort> getReferencedPortClass() {
341 public Class<? extends BasicPort> getAssignementCompatiblePortClass() {
346 * @return the port opposite class
348 public Class<? extends BasicPort> getOppositeClass() {
353 private transient boolean isContextDependent;
358 public ContextUpdate(JavaController controller, long uid, Kind kind, Object value, mxGeometry geometry, String style, String id) {
359 super(controller, uid, kind, value, geometry, style, id);
363 * Constructor used to allocate a new block on the Java side
365 * The caller should add a port child and setup the simulation function accordingly to the style.
366 * @param controller the controller used to allocate the block
367 * @param blockName the interface function and style applied on the block
369 protected ContextUpdate(JavaController controller, String blockName) {
370 super(controller, controller.createObject(Kind.BLOCK), Kind.BLOCK, null, new mxGeometry(0, 0, DEFAULT_WIDTH, DEFAULT_HEIGHT), blockName, new UID().toString());
372 controller.setObjectProperty(getUID(), Kind.BLOCK, ObjectProperties.INTERFACE_FUNCTION, blockName);
381 public void onContextChange(String[] context) {
382 // prevent to open twice
387 // do not evaluate context is the block is not context dependent.
388 if (!isContextDependent) {
392 LOG_LOCAL.finest("Update the I/O value from the context");
394 // final ScilabDirectHandler handler = ScilabDirectHandler.acquire();
395 // if (handler == null) {
401 // handler.writeBlock(this);
403 // handler.writeContext(context);
405 // String cmd = ScilabInterpreterManagement.buildCall("blk =
406 // xcosBlockEval", getInterfaceFunctionName().toCharArray(),
407 // ScilabDirectHandler.BLK.toCharArray(),
408 // ScilabDirectHandler.CONTEXT.toCharArray());
411 // ScilabInterpreterManagement.synchronousScilabExec(cmd);
412 // } catch (InterpreterException e) {
413 // e.printStackTrace();
415 // BasicBlock modifiedBlock = handler.readBlock();
416 // updateBlockSettings(modifiedBlock);
418 // } catch (ScicosFormatException e) {
419 // LOG_LOCAL.severe(e.toString());
421 // handler.release();