2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2010 - DIGITEO - Clément DAVID
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-en.txt
13 package org.scilab.modules.xcos.io.scicos;
15 import static java.util.Arrays.asList;
17 import java.util.List;
19 import org.scilab.modules.types.ScilabBoolean;
20 import org.scilab.modules.types.ScilabDouble;
21 import org.scilab.modules.types.ScilabList;
22 import org.scilab.modules.types.ScilabMList;
23 import org.scilab.modules.types.ScilabString;
24 import org.scilab.modules.types.ScilabTList;
25 import org.scilab.modules.types.ScilabType;
26 import org.scilab.modules.xcos.block.BasicBlock;
27 import org.scilab.modules.xcos.block.BasicBlock.SimulationFunctionType;
28 import org.scilab.modules.xcos.io.scicos.ScicosFormatException.WrongElementException;
29 import org.scilab.modules.xcos.io.scicos.ScicosFormatException.WrongStructureException;
30 import org.scilab.modules.xcos.io.scicos.ScicosFormatException.WrongTypeException;
31 import org.scilab.modules.xcos.port.BasicPort;
32 import org.scilab.modules.xcos.port.command.CommandPort;
33 import org.scilab.modules.xcos.port.control.ControlPort;
36 * Protected class which decode model fields of a block.
38 * This class is intentionally package-protected to prevent external use.
40 //CSOFF: ClassDataAbstractionCoupling
41 class BlockModelElement extends BlockPartsElement {
42 private static final List<String> DATA_FIELD_NAMES = asList("model", "sim",
43 "in", "in2", "intyp", "out", "out2", "outtyp", "evtin", "evtout",
44 "state", "dstate", "odstate", "rpar", "ipar", "opar", "blocktype",
45 "firing", "dep_ut", "label", "nzcross", "nmode", "equations");
47 private static final int CTRL_PORT_INDEX = 8;
48 private static final int CMD_PORT_INDEX = 9;
49 private static final int STATE_INDEX = 10;
50 private static final int FIRING_INDEX = 17;
51 private static final int DEPENDU_INDEX = 18;
53 /** Mutable field to easily get the data through methods */
54 private ScilabMList data;
59 public BlockModelElement() { }
62 * Decode Scicos element into the block.
64 * This decode method doesn't coverage Port management because we need
65 * graphics informations to handle it.
70 * the previously instantiated block.
71 * @return the modified into block.
72 * @throws ScicosFormatException
74 * @see org.scilab.modules.xcos.io.scicos.Element#decode(org.scilab.modules.types.ScilabType,
78 public BasicBlock decode(ScilabType element, BasicBlock into)
79 throws ScicosFormatException {
82 throw new IllegalArgumentException();
85 data = (ScilabMList) element;
86 BasicBlock local = into;
90 local = beforeDecode(element, local);
95 fillSimulationFunction(local);
96 fillControlCommandPorts(local);
97 fillFirstRawParameters(local);
98 fillFiringParameters(local);
99 fillSecondRawParameters(local);
101 local = afterDecode(element, local);
107 * Fill the simulation data into the block
110 * the target instance
112 private void fillSimulationFunction(BasicBlock into) {
113 String functionName = into.getSimulationFunctionName();
114 SimulationFunctionType functionType = into.getSimulationFunctionType();
116 if (data.get(1) instanceof ScilabString) {
117 functionName = ((ScilabString) data.get(1)).getData()[0][0];
118 } else if ((data.get(1) instanceof ScilabList)) {
119 functionName = ((ScilabString) ((ScilabList) data.get(1)).get(0))
121 functionType = SimulationFunctionType
122 .convertScilabValue((int) ((ScilabDouble) ((ScilabList) data
123 .get(1)).get(1)).getRealPart()[0][0]);
126 into.setSimulationFunctionName(functionName);
127 into.setSimulationFunctionType(functionType);
131 * Fill the block with the control and command ports
134 * the target instance
136 private void fillControlCommandPorts(BasicBlock into) {
137 ScilabDouble dataNbControlPort = (ScilabDouble) data
138 .get(CTRL_PORT_INDEX);
139 ScilabDouble dataNbCommandPort = (ScilabDouble) data
140 .get(CMD_PORT_INDEX);
142 if (dataNbControlPort.getRealPart() != null) {
143 int nbControlPort = dataNbControlPort.getHeight();
144 for (int i = 0; i < nbControlPort; i++) {
145 final BasicPort port = new ControlPort();
147 // do not use BasicPort#addPort() to avoid the view update
148 port.setOrdering(i + 1);
149 into.insert(port, i);
153 if (dataNbCommandPort.getRealPart() != null) {
154 int nbCommandPort = dataNbCommandPort.getHeight();
155 for (int i = 0; i < nbCommandPort; i++) {
156 final BasicPort port = new CommandPort();
158 // do not use BasicPort#addPort() to avoid the view update
159 port.setOrdering(i + 1);
160 into.insert(port, i);
166 * Fill the block with the first raw parameters
169 * the target instance
171 private void fillFirstRawParameters(BasicBlock into) {
173 int field = STATE_INDEX;
174 into.setState(data.get(field));
178 into.setDState(data.get(field));
182 into.setODState(data.get(field));
186 into.setRealParameters(data.get(field));
190 into.setIntegerParameters(data.get(field));
194 into.setObjectsParameters(data.get(field));
198 into.setBlockType(((ScilabString) data.get(field)).getData()[0][0]);
202 * Fill the block with the firing parameters
205 * the target instance
207 private void fillFiringParameters(BasicBlock into) {
209 * A boolean can be used to indicate that no initial event will be emitted.
211 if (data.get(FIRING_INDEX) instanceof ScilabBoolean) {
218 final ScilabDouble firing = (ScilabDouble) data.get(FIRING_INDEX);
220 if (!isEmptyField(firing)) {
221 final List<CommandPort> allCommandPorts = BasicBlockInfo
222 .getAllTypedPorts(into, false, CommandPort.class);
224 final boolean isColumnDominant = firing.getHeight() >= firing
226 final double[][] values = firing.getRealPart();
227 final int[] indexes = {0, 0};
229 for (int i = 0; i < allCommandPorts.size(); i++) {
230 allCommandPorts.get(i).setInitialState(
231 values[indexes[0]][indexes[1]]);
232 incrementIndexes(indexes, isColumnDominant);
238 * Fill the block with the second raw parameters
241 * the target instance
243 private void fillSecondRawParameters(BasicBlock into) {
245 int field = DEPENDU_INDEX;
246 into.setDependsOnU(((ScilabBoolean) data.get(field)).getData()[0][0]);
247 into.setDependsOnT(((ScilabBoolean) data.get(field)).getData()[0][1]);
255 into.setNbZerosCrossing(data.get(field));
259 into.setNmode(data.get(field));
263 into.setEquations(data.get(field));
267 * Validate the current data.
269 * This method doesn't pass the metrics because it perform many test.
270 * Therefore all these tests are trivial and the conditioned action only
271 * throw an exception.
273 * @throws ScicosFormatException
274 * when there is a validation error.
276 // CSOFF: CyclomaticComplexity
277 // CSOFF: NPathComplexity
279 // CSOFF: MethodLength
280 private void validate() throws ScicosFormatException {
281 if (!canDecode(data)) {
282 throw new WrongElementException();
287 // we test if the structure as enough field
288 if (data.size() != DATA_FIELD_NAMES.size()) {
289 throw new WrongStructureException(DATA_FIELD_NAMES);
293 * Checking the MList header
296 // Check the first field
297 if (!(data.get(field) instanceof ScilabString)) {
298 throw new WrongTypeException(DATA_FIELD_NAMES, field);
300 final String[] header = ((ScilabString) data.get(field)).getData()[0];
302 // Checking for the field names
303 if (header.length != DATA_FIELD_NAMES.size()) {
304 throw new WrongStructureException(DATA_FIELD_NAMES);
306 for (int i = 0; i < header.length; i++) {
307 if (!header[i].equals(DATA_FIELD_NAMES.get(i))) {
308 throw new WrongStructureException(DATA_FIELD_NAMES);
316 // sim : String or list(String, int)
318 if (!(data.get(field) instanceof ScilabString)
319 && !(data.get(field) instanceof ScilabList)) {
320 throw new WrongTypeException(DATA_FIELD_NAMES, field);
325 if (!(data.get(field) instanceof ScilabDouble)) {
326 throw new WrongTypeException(DATA_FIELD_NAMES, field);
331 if (!(data.get(field) instanceof ScilabDouble)) {
332 throw new WrongTypeException(DATA_FIELD_NAMES, field);
337 if (!(data.get(field) instanceof ScilabDouble)) {
338 throw new WrongTypeException(DATA_FIELD_NAMES, field);
343 if (!(data.get(field) instanceof ScilabDouble)) {
344 throw new WrongTypeException(DATA_FIELD_NAMES, field);
349 if (!(data.get(field) instanceof ScilabDouble)) {
350 throw new WrongTypeException(DATA_FIELD_NAMES, field);
355 if (!(data.get(field) instanceof ScilabDouble)) {
356 throw new WrongTypeException(DATA_FIELD_NAMES, field);
361 if (!(data.get(field) instanceof ScilabDouble)) {
362 throw new WrongTypeException(DATA_FIELD_NAMES, field);
367 if (!(data.get(field) instanceof ScilabDouble)) {
368 throw new WrongTypeException(DATA_FIELD_NAMES, field);
373 if (!(data.get(field) instanceof ScilabDouble)) {
374 throw new WrongTypeException(DATA_FIELD_NAMES, field);
378 // TODO: the ScilabString value is undocumented
380 if (!(data.get(field) instanceof ScilabDouble)
381 && !(data.get(field) instanceof ScilabString)) {
382 throw new WrongTypeException(DATA_FIELD_NAMES, field);
387 if (!(data.get(field) instanceof ScilabDouble)
388 && !(data.get(field) instanceof ScilabList)) {
389 throw new WrongTypeException(DATA_FIELD_NAMES, field);
393 // SuperBlocks store all "included" data in rpar field.
395 if (!(data.get(field) instanceof ScilabDouble)
396 && !(data.get(field) instanceof ScilabMList)
397 && !(data.get(field) instanceof ScilabString)) {
398 throw new WrongTypeException(DATA_FIELD_NAMES, field);
402 // !! WARNING !! scifunc_block_m ipar = list(...)
404 if (!(data.get(field) instanceof ScilabDouble)
405 && !(data.get(field) instanceof ScilabList)) {
406 throw new WrongTypeException(DATA_FIELD_NAMES, field);
411 if (!(data.get(field) instanceof ScilabDouble)
412 && !(data.get(field) instanceof ScilabList)) {
413 throw new WrongTypeException(DATA_FIELD_NAMES, field);
418 if (!(data.get(field) instanceof ScilabString)) {
419 throw new WrongTypeException(DATA_FIELD_NAMES, field);
424 if (!(data.get(field) instanceof ScilabDouble)
425 && !(data.get(field) instanceof ScilabBoolean)) {
426 throw new WrongTypeException(DATA_FIELD_NAMES, field);
431 if (!(data.get(field) instanceof ScilabBoolean)) {
432 throw new WrongTypeException(DATA_FIELD_NAMES, field);
437 if (!(data.get(field) instanceof ScilabString)) {
438 throw new WrongTypeException(DATA_FIELD_NAMES, field);
443 if (!(data.get(field) instanceof ScilabDouble)) {
444 throw new WrongTypeException(DATA_FIELD_NAMES, field);
449 if (!(data.get(field) instanceof ScilabDouble)) {
450 throw new WrongTypeException(DATA_FIELD_NAMES, field);
455 if (!(data.get(field) instanceof ScilabTList)
456 && !isEmptyField(data.get(field))) {
457 throw new WrongTypeException(DATA_FIELD_NAMES, field);
460 // CSON: CyclomaticComplexity
461 // CSON: NPathComplexity
463 // CSON: MethodLength
466 * Check if the element can be decoded.
470 * @return true, if the Scicos types match.
471 * @see org.scilab.modules.xcos.io.scicos.Element#canDecode(org.scilab.modules.types.ScilabType)
474 public boolean canDecode(ScilabType element) {
475 data = (ScilabMList) element;
477 final String type = ((ScilabString) data.get(0)).getData()[0][0];
478 return type.equals(DATA_FIELD_NAMES.get(0));
482 * Encode the instance into the element
484 * @param from the source instance
485 * @param element must be null.
486 * @return the element parameter
487 * @see org.scilab.modules.xcos.io.scicos.Element#encode(java.lang.Object, org.scilab.modules.types.ScilabType)
491 public ScilabType encode(BasicBlock from, ScilabType element) {
492 data = (ScilabMList) element;
497 data = allocateElement();
499 throw new IllegalArgumentException("The element parameter must be null.");
502 data = (ScilabMList) beforeEncode(from, data);
508 data.set(field, from.getSimulationFunctionNameAndType());
511 * Fields managed by specific elements :
518 * see InputPortElement and OutputPortElement.
531 final List<ControlPort> ctrlPorts = BasicBlockInfo.getAllTypedPorts(from, false, ControlPort.class);
532 data.set(field, BasicBlockInfo.getAllPortsDataLines(ctrlPorts));
534 final List<CommandPort> cmdPorts = BasicBlockInfo.getAllTypedPorts(from, false, CommandPort.class);
535 data.set(field, BasicBlockInfo.getAllPortsDataLines(cmdPorts));
541 data.set(field, from.getState());
543 data.set(field, from.getDState());
545 data.set(field, from.getODState());
551 property = from.getRealParameters();
552 if (property == null) {
553 property = new ScilabDouble();
555 data.set(field, property);
558 property = from.getIntegerParameters();
559 if (property == null) {
560 property = new ScilabDouble();
562 data.set(field, property);
565 property = from.getObjectsParameters();
566 if (property == null) {
567 property = new ScilabDouble();
569 data.set(field, property);
571 field++; // blocktype
572 data.set(field, new ScilabString(from.getBlockType()));
575 property = from.getAllCommandPortsInitialStates();
576 if (property == null) {
577 property = new ScilabDouble();
579 data.set(field, property);
582 boolean[][] dependsOnUandT = {{from.isDependsOnU() , from.isDependsOnT()}};
583 data.set(field, new ScilabBoolean(dependsOnUandT));
586 data.set(field, new ScilabString(from.getId()));
589 property = from.getNbZerosCrossing();
590 if (property == null) {
591 property = new ScilabDouble();
593 data.set(field, property);
596 property = from.getNmode();
597 if (property == null) {
598 property = new ScilabDouble();
600 data.set(field, property);
602 field++; // equations
603 property = from.getEquations();
604 if (property == null) {
605 property = new ScilabList();
607 data.set(field, property);
609 data = (ScilabMList) afterEncode(from, data);
616 * Allocate a new element
617 * @return the new element
619 private ScilabMList allocateElement() {
620 ScilabMList element = new ScilabMList(DATA_FIELD_NAMES.toArray(new String[0]));
621 element.add(new ScilabList()); // sim
622 addSizedPortVector(element, ScilabDouble.class, getInSize()); // in
623 addSizedPortVector(element, ScilabDouble.class, getInSize()); // in2
624 addSizedPortVector(element, ScilabDouble.class, getInSize()); // intyp
625 addSizedPortVector(element, ScilabDouble.class, getOutSize()); // out
626 addSizedPortVector(element, ScilabDouble.class, getOutSize()); // out2
627 addSizedPortVector(element, ScilabDouble.class, getOutSize()); // outtyp
628 addSizedPortVector(element, ScilabDouble.class, getEinSize()); // evtin
629 addSizedPortVector(element, ScilabDouble.class, getEoutSize()); // evtout
630 element.add(new ScilabDouble()); // state
631 element.add(new ScilabDouble()); // dstate
632 element.add(new ScilabDouble()); // ostate
633 element.add(new ScilabDouble()); // rpar
634 element.add(new ScilabDouble()); // ipar
635 element.add(new ScilabDouble()); // opar
636 element.add(new ScilabString()); // blocktype
637 element.add(new ScilabDouble()); // firing
638 element.add(new ScilabDouble()); // dep_ut
639 element.add(new ScilabString("")); // label
640 element.add(new ScilabDouble()); // nzcross
641 element.add(new ScilabDouble()); // nmode
642 element.add(new ScilabList()); // equations
646 //CSON: ClassDataAbstractionCoupling