From c214b398aaa6429304865442217ad2e351e8f5bd Mon Sep 17 00:00:00 2001
From: Raphael Girardot <raphael.girardot@synchrotron-soleil.fr>
Date: Fri, 14 May 2021 07:42:01 +0000
Subject: [PATCH] - some code refactoring - respect java standards - No more
 use of DbData.splitDbData: directly return the expected data array at
 extraction (TANGOARCH-715)

---
 pom.xml                                       | 302 ++++---
 .../extractor/convert/DefaultConverter.java   | 819 ++++++++++--------
 .../api/extractor/convert/IConverter.java     |  39 +-
 3 files changed, 618 insertions(+), 542 deletions(-)

diff --git a/pom.xml b/pom.xml
index b4951e9..f1fca77 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,159 +1,157 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<project
-	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
-	xmlns="http://maven.apache.org/POM/4.0.0"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
-	<modelVersion>4.0.0</modelVersion>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+  xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <modelVersion>4.0.0</modelVersion>
 
-	<parent>
-		<artifactId>java-updated-versions</artifactId>
-		<groupId>fr.soleil.maven.parent</groupId>
-		<version>0-SNAPSHOT</version>
-	</parent>
+  <parent>
+    <artifactId>java-updated-versions</artifactId>
+    <groupId>fr.soleil.maven.parent</groupId>
+    <version>0-SNAPSHOT</version>
+  </parent>
 
-	<groupId>fr.soleil.lib</groupId>
-	<artifactId>snapArchivingApi</artifactId>
-	<version>1.8.6</version>
-	<name>snapArchivingApi</name>
-	<description>Snap Archiving API</description>
-	<developers>
-		<developer>
-			<id>abeille</id>
-			<name>Gwenaelle Abeille</name>
-			<email>gwenaelle.abeille@synchrotron-soleil.fr</email>
-			<organization>Synchrotron Soleil</organization>
-			<organizationUrl>http://www.synchrotron-soleil.fr</organizationUrl>
-			<roles>
-				<role>Java Developer</role>
-			</roles>
-			<timezone>1</timezone>
-		</developer>
-		<developer>
-			<id>girardot</id>
-			<name>Raphaël GIRARDOT</name>
-			<email>raphael.girardot@synchrotron-soleil.fr</email>
-			<organization>Synchrotron Soleil</organization>
-			<organizationUrl>http://www.synchrotron-soleil.fr</organizationUrl>
-			<roles>
-				<role>Java Developer</role>
-			</roles>
-			<timezone>1</timezone>
-		</developer>
-	</developers>
+  <groupId>fr.soleil.lib</groupId>
+  <artifactId>snapArchivingApi</artifactId>
+  <version>1.8.6</version>
+  <name>snapArchivingApi</name>
+  <description>Snap Archiving API</description>
+  <developers>
+    <developer>
+      <id>abeille</id>
+      <name>Gwenaelle Abeille</name>
+      <email>gwenaelle.abeille@synchrotron-soleil.fr</email>
+      <organization>Synchrotron Soleil</organization>
+      <organizationUrl>http://www.synchrotron-soleil.fr</organizationUrl>
+      <roles>
+        <role>Java Developer</role>
+      </roles>
+      <timezone>1</timezone>
+    </developer>
+    <developer>
+      <id>girardot</id>
+      <name>Raphaël GIRARDOT</name>
+      <email>raphael.girardot@synchrotron-soleil.fr</email>
+      <organization>Synchrotron Soleil</organization>
+      <organizationUrl>http://www.synchrotron-soleil.fr</organizationUrl>
+      <roles>
+        <role>Java Developer</role>
+      </roles>
+      <timezone>1</timezone>
+    </developer>
+  </developers>
 
-	<scm>
-		<connection>${scm.connection.svn.tango-cs}:archiving/api/snapArchivingApi/trunk</connection>
-		<developerConnection>${scm.developerConnection.svn.tango-cs}:archiving/api/snapArchivingApi/trunk</developerConnection>
-		<url>${scm.url.svn.tango-cs}/archiving/api/snapArchivingApi/trunk</url>
-	</scm>
+  <scm>
+    <connection>${scm.connection.svn.tango-cs}:archiving/api/snapArchivingApi/trunk</connection>
+    <developerConnection>${scm.developerConnection.svn.tango-cs}:archiving/api/snapArchivingApi/trunk</developerConnection>
+    <url>${scm.url.svn.tango-cs}/archiving/api/snapArchivingApi/trunk</url>
+  </scm>
 
-	<dependencies>
-		<dependency>
-			<groupId>org.slf4j</groupId>
-			<artifactId>slf4j-api</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.tango-controls</groupId>
-			<artifactId>JTangoCommons</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>fr.soleil.lib</groupId>
-			<artifactId>commonArchivingApi</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.springframework</groupId>
-			<artifactId>spring-core</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.springframework</groupId>
-			<artifactId>spring-beans</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.springframework</groupId>
-			<artifactId>spring-orm</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.springframework</groupId>
-			<artifactId>spring-context</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.springframework</groupId>
-			<artifactId>spring-test</artifactId>
-			<scope>test</scope>
-		</dependency>
-		<dependency>
-			<groupId>org.hibernate</groupId>
-			<artifactId>hibernate-core</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.hibernate</groupId>
-			<artifactId>hibernate-entitymanager</artifactId>
-			<version>5.4.2.Final</version>
-		</dependency>
-		<!-- http://mvnrepository.com/artifact/org.hibernate/hibernate-c3p0 -->
-		<dependency>
-			<groupId>org.hibernate</groupId>
-			<artifactId>hibernate-c3p0</artifactId>
-			<version>5.4.2.Final</version>
-		</dependency>
-		<dependency>
-			<groupId>aspectj</groupId>
-			<artifactId>aspectjweaver</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>javassist</groupId>
-			<artifactId>javassist</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>com.googlecode.log4jdbc</groupId>
-			<artifactId>log4jdbc</artifactId>
-		</dependency>		
-		<!--  Test  -->
-		<dependency>
-			<groupId>junit</groupId>
-			<artifactId>junit</artifactId>
-			<scope>test</scope>
-		</dependency>
-		<dependency>
-		    <groupId>org.liquibase</groupId>
-		    <artifactId>liquibase-core</artifactId>
-		    <version>3.4.2</version>
-		</dependency>
-		<dependency>
-		    <groupId>com.h2database</groupId>
-		    <artifactId>h2</artifactId>
-		    <version>1.4.200</version>
-		    <scope>test</scope>
-		</dependency>
-		<dependency>
-		  <groupId>org.testcontainers</groupId>
-		  <artifactId>oracle-xe</artifactId>
-		  <version>1.15.1</version>
-		  <scope>test</scope>
-		</dependency>
-	</dependencies>
+  <dependencies>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.tango-controls</groupId>
+      <artifactId>JTangoCommons</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>fr.soleil.lib</groupId>
+      <artifactId>commonArchivingApi</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-beans</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-orm</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-context</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-test</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.hibernate</groupId>
+      <artifactId>hibernate-core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.hibernate</groupId>
+      <artifactId>hibernate-entitymanager</artifactId>
+      <version>5.4.2.Final</version>
+    </dependency>
+    <!-- http://mvnrepository.com/artifact/org.hibernate/hibernate-c3p0 -->
+    <dependency>
+      <groupId>org.hibernate</groupId>
+      <artifactId>hibernate-c3p0</artifactId>
+      <version>5.4.2.Final</version>
+    </dependency>
+    <dependency>
+      <groupId>aspectj</groupId>
+      <artifactId>aspectjweaver</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>javassist</groupId>
+      <artifactId>javassist</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.googlecode.log4jdbc</groupId>
+      <artifactId>log4jdbc</artifactId>
+    </dependency>
+    <!-- Test -->
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.liquibase</groupId>
+      <artifactId>liquibase-core</artifactId>
+      <version>3.4.2</version>
+    </dependency>
+    <dependency>
+      <groupId>com.h2database</groupId>
+      <artifactId>h2</artifactId>
+      <version>1.4.200</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.testcontainers</groupId>
+      <artifactId>oracle-xe</artifactId>
+      <version>1.15.1</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
 
-	<build>
-		<pluginManagement>
-			<plugins>
-				<plugin>
-					<groupId>org.liquibase</groupId>
-					<artifactId>liquibase-maven-plugin</artifactId>
-					<version>3.5.3</version>
-					<configuration>
-						<changeLogFile>src/main/resources/liquibase/master.xml</changeLogFile>
-						<diffChangeLogFile>src/main/resources/liquibase/changelog/20190411-103909_changelog.xml</diffChangeLogFile>
-						<driver>org.h2.Driver</driver>
-						<url>jdbc:h2:mem:SNAP;DB_CLOSE_DELAY=-1;INIT=CREATE	SCHEMA IF NOT EXISTS SNAP\;SET SCHEMA SNAP;</url>
-						<defaultSchemaName>SNAP</defaultSchemaName>
-						<contexts>test</contexts>
-						<username>snap</username>
-						<password>snap</password>
-						<outputChangeLogFile>myGenChangeLog.xml</outputChangeLogFile>
-						<logging>debug</logging>
-					</configuration>
-				</plugin>
-			</plugins>
-		</pluginManagement>
-	</build>
+  <build>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.liquibase</groupId>
+          <artifactId>liquibase-maven-plugin</artifactId>
+          <version>3.5.3</version>
+          <configuration>
+            <changeLogFile>src/main/resources/liquibase/master.xml</changeLogFile>
+            <diffChangeLogFile>src/main/resources/liquibase/changelog/20190411-103909_changelog.xml</diffChangeLogFile>
+            <driver>org.h2.Driver</driver>
+            <url>jdbc:h2:mem:SNAP;DB_CLOSE_DELAY=-1;INIT=CREATE SCHEMA IF NOT EXISTS SNAP\;SET SCHEMA SNAP;</url>
+            <defaultSchemaName>SNAP</defaultSchemaName>
+            <contexts>test</contexts>
+            <username>snap</username>
+            <password>snap</password>
+            <outputChangeLogFile>myGenChangeLog.xml</outputChangeLogFile>
+            <logging>debug</logging>
+          </configuration>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+  </build>
 </project>
diff --git a/src/main/java/fr/soleil/archiving/snap/api/extractor/convert/DefaultConverter.java b/src/main/java/fr/soleil/archiving/snap/api/extractor/convert/DefaultConverter.java
index fba8847..0458708 100644
--- a/src/main/java/fr/soleil/archiving/snap/api/extractor/convert/DefaultConverter.java
+++ b/src/main/java/fr/soleil/archiving/snap/api/extractor/convert/DefaultConverter.java
@@ -25,6 +25,7 @@
 package fr.soleil.archiving.snap.api.extractor.convert;
 
 import java.lang.reflect.Array;
+import java.util.Arrays;
 
 import fr.esrf.Tango.AttrDataFormat;
 import fr.esrf.Tango.AttrWriteType;
@@ -34,51 +35,60 @@ import fr.soleil.archiving.common.api.tools.DbData;
 import fr.soleil.archiving.common.api.tools.NullableTimedData;
 import fr.soleil.archiving.snap.api.tools.SnapAttributeExtract;
 import fr.soleil.lib.project.math.MathConst;
+import fr.soleil.lib.project.math.NumberArrayUtils;
 
 /**
  * 
  * @author CLAISSE
  */
 public class DefaultConverter implements IConverter {
-    DefaultConverter() {
+
+    public DefaultConverter() {
         super();
     }
 
+    protected void fillDbData(DbData dbData, NullableTimedData[] timedAttrDatas) {
+        if ((dbData != null) && (timedAttrDatas != null)) {
+            dbData.setTimedData(timedAttrDatas);
+            NullableTimedData theTimedAttrData = timedAttrDatas[0];
+            dbData.setMaxX(theTimedAttrData.getX());
+            dbData.setMaxY(theTimedAttrData.getY());
+        }
+    }
+
+    // TODO maybe return DbData[] (TANGOARCH-715)
     @Override
-    public synchronized DbData convert(SnapAttributeExtract currentExtract) throws DevFailed {
-        DbData dbData = new DbData(currentExtract.getAttributeCompleteName());
-        dbData.setDataFormat(currentExtract.getDataFormat());
-        dbData.setDataType(currentExtract.getDataType());
-        dbData.setWritable(currentExtract.getWritable());
+    public synchronized DbData[] convert(SnapAttributeExtract currentExtract) throws DevFailed {
+        DbData[] dbData = DbData.initExtractionResult(currentExtract.getAttributeCompleteName(),
+                currentExtract.getDataType(), currentExtract.getDataFormat(), currentExtract.getWritable());
 
-        NullableTimedData[] timedAttrDatas = null;
+        NullableTimedData[][] timedAttrDatas = null;
         try {
-            timedAttrDatas = this.convertData(currentExtract);
+            timedAttrDatas = convertData(currentExtract);
 
             if (timedAttrDatas == null) {
-                return null;
+                dbData = null;
             }
         } catch (IllegalArgumentException iae) {
             DevFailed devFailed = new DevFailed();
             devFailed.initCause(iae);
             throw devFailed;
         }
-        dbData.setTimedData(timedAttrDatas);
-
-        NullableTimedData theTimedAttrData = timedAttrDatas[0];
-        dbData.setMaxX(theTimedAttrData.getX());
-        dbData.setMaxY(theTimedAttrData.getY());
-
+        if (dbData != null) {
+            fillDbData(dbData[READ_INDEX], timedAttrDatas[READ_INDEX]);
+            fillDbData(dbData[WRITE_INDEX], timedAttrDatas[WRITE_INDEX]);
+            Arrays.fill(timedAttrDatas, null);
+        }
         return dbData;
     }
 
-    private NullableTimedData[] convertData(SnapAttributeExtract currentExtract) throws IllegalArgumentException {
+    private NullableTimedData[][] convertData(SnapAttributeExtract currentExtract) throws IllegalArgumentException {
         Object value = currentExtract.getValue();
         int dataType = currentExtract.getDataType();
         int dataFormat = currentExtract.getDataFormat();
         boolean isScalar = (dataFormat == AttrDataFormat._SCALAR);
-        boolean hasBothReadAndWriteValues = ((currentExtract.getWritable() == AttrWriteType._READ_WITH_WRITE) || (currentExtract
-                .getWritable() == AttrWriteType._READ_WRITE));
+        boolean hasBothReadAndWriteValues = ((currentExtract.getWritable() == AttrWriteType._READ_WITH_WRITE)
+                || (currentExtract.getWritable() == AttrWriteType._READ_WRITE));
 
         long when;
         if (currentExtract.getSnapDate() == null) {
@@ -87,21 +97,27 @@ public class DefaultConverter implements IConverter {
             when = currentExtract.getSnapDate().getTime();
         }
 
-        NullableTimedData[] ret = new NullableTimedData[1];
-        NullableTimedData theTimedAttrData;
+        NullableTimedData[][] ret = new NullableTimedData[2][1];
+        NullableTimedData[] theTimedAttrData;
         try {
             if (isScalar) {
                 if (hasBothReadAndWriteValues) {
                     theTimedAttrData = buildDataScalarRW(value, dataType, when);
                 } else {
-                    theTimedAttrData = buildDataScalarR(value, dataType, when);
+                    theTimedAttrData = buildDataScalarR(value, dataType,
+                            currentExtract.getWritable() == AttrWriteType._WRITE, when);
                 }
             } else {
                 if (hasBothReadAndWriteValues) {
                     theTimedAttrData = buildDataSpectrumRW(value, dataType, when);
-                    theTimedAttrData.setX(currentExtract.getDimX());
+                    for (NullableTimedData data : theTimedAttrData) {
+                        if (data != null) {
+                            data.setX(currentExtract.getDimX());
+                        }
+                    }
                 } else {
-                    theTimedAttrData = buildDataSpectrumR(value, dataType, when);
+                    theTimedAttrData = buildDataSpectrumR(value, dataType,
+                            currentExtract.getWritable() == AttrWriteType._WRITE, when);
                 }
             }
         } catch (IllegalArgumentException iae) {
@@ -109,11 +125,13 @@ public class DefaultConverter implements IConverter {
         }
 
         if (theTimedAttrData == null) {
-            return null;
+            ret = null;
+        } else {
+            ret[READ_INDEX][0] = theTimedAttrData[READ_INDEX];
+            ret[WRITE_INDEX][0] = theTimedAttrData[WRITE_INDEX];
+            Arrays.fill(theTimedAttrData, null);
         }
 
-        ret[0] = theTimedAttrData;
-
         return ret;
     }
 
@@ -132,300 +150,351 @@ public class DefaultConverter implements IConverter {
         return result;
     }
 
-    /**
-     * @param value
-     * @param dataType
-     * @param when
-     * @return
-     */
-    private NullableTimedData buildDataScalarRW(Object value, int dataType, long when) throws IllegalArgumentException {
-        // String[] valueTab = this.castObjectTableToString ( (Object []) value
-        // , true );
-        String[] valueTab = this.castObjectTableToString(value, false);
-        if (valueTab == null) {
-            return null;
+    protected NullableTimedData[] treatScalarBooleanCase(String[] valueTab, NullableTimedData[] timedAttrDatas,
+            int index) {
+        NullableTimedData[] result = timedAttrDatas;
+        boolean[] data = new boolean[1];
+        boolean[] nullElements = new boolean[1];
+        if (isNullOrNaN(valueTab[index])) {
+            data[0] = false;
+            nullElements[0] = true;
+        } else {
+            data[0] = Boolean.parseBoolean(valueTab[index]);
         }
-
-        NullableTimedData theTimedAttrData = null;
-
-        final boolean[] nullElements = new boolean[2];
-
-        switch (dataType) {
-            case TangoConst.Tango_DEV_LONG:
-            case TangoConst.Tango_DEV_ULONG:
-                int[] dataL = new int[2];
-                if (isNullOrNaN(valueTab[0])) {
-                    dataL[0] = 0;
-                    nullElements[0] = true;
-                } else {
-                    double theDataL_R_D = Double.parseDouble(valueTab[0]);
-                    dataL[0] = (int) Math.round(theDataL_R_D);
-                }
-                if (isNullOrNaN(valueTab[1])) {
-                    dataL[1] = 0;
-                    nullElements[1] = true;
-                } else {
-                    double theDataL_W_D = Double.parseDouble(valueTab[1]);
-                    dataL[1] = (int) Math.round(theDataL_W_D);
-                }
-
-                theTimedAttrData = new NullableTimedData();
-                theTimedAttrData.setValue(dataL, nullElements);
-                break;
-
-            case TangoConst.Tango_DEV_SHORT:
-            case TangoConst.Tango_DEV_USHORT:
-                short[] dataS = new short[2];
-                if (isNullOrNaN(valueTab[0])) {
-                    dataS[0] = 0;
-                    nullElements[0] = true;
-                } else {
-                    double theDataS_R_D = Double.parseDouble(valueTab[0]);
-                    dataS[0] = (short) Math.round(theDataS_R_D);
-                }
-                if (isNullOrNaN(valueTab[1])) {
-                    dataS[1] = 0;
-                    nullElements[1] = true;
-                } else {
-                    double theDataS_W_D = Double.parseDouble(valueTab[1]);
-                    dataS[1] = (short) Math.round(theDataS_W_D);
-                }
-
-                theTimedAttrData = new NullableTimedData();
-                theTimedAttrData.setValue(dataS, nullElements);
-                break;
-
-            case TangoConst.Tango_DEV_DOUBLE:
-                double[] dataD = new double[2];
-                if (isNullOrNaN(valueTab[0])) {
-                    dataD[0] = MathConst.NAN_FOR_NULL;
-                    nullElements[0] = true;
-                } else {
-                    dataD[0] = Double.parseDouble(valueTab[0]);
-                }
-                if (isNullOrNaN(valueTab[1])) {
-                    dataD[1] = MathConst.NAN_FOR_NULL;
-                    nullElements[1] = true;
-                } else {
-                    dataD[1] = Double.parseDouble(valueTab[1]);
-                }
-
-                theTimedAttrData = new NullableTimedData();
-                theTimedAttrData.setValue(dataD, nullElements);
-                break;
-
-            case TangoConst.Tango_DEV_BOOLEAN:
-                boolean[] dataB = new boolean[2];
-                if (isNullOrNaN(valueTab[0])) {
-                    dataB[0] = false;
-                    nullElements[0] = true;
-                } else {
-                    dataB[0] = Boolean.parseBoolean(valueTab[0]);
-                }
-                if (isNullOrNaN(valueTab[1])) {
-                    dataB[1] = false;
-                    nullElements[1] = true;
-                } else {
-                    dataB[1] = Boolean.parseBoolean(valueTab[1]);
-                }
-
-                theTimedAttrData = new NullableTimedData();
-                theTimedAttrData.setValue(dataB, nullElements);
-                break;
-
-            case TangoConst.Tango_DEV_FLOAT:
-                float[] dataF = new float[2];
-                if (isNullOrNaN(valueTab[0])) {
-                    dataF[0] = Float.NaN;
-                    nullElements[0] = true;
-                } else {
-                    dataF[0] = Float.parseFloat(valueTab[0]);
-                }
-                if (isNullOrNaN(valueTab[1])) {
-                    dataF[1] = Float.NaN;
-                    nullElements[1] = true;
-                } else {
-                    dataF[1] = Float.parseFloat(valueTab[1]);
-                }
-
-                theTimedAttrData = new NullableTimedData();
-                theTimedAttrData.setValue(dataF, nullElements);
-                break;
-
-            case TangoConst.Tango_DEV_STRING:
-                String[] dataStr = new String[2];
-                if (isNullOrNaN(valueTab[0])) {
-                    dataStr[0] = null;
-                    nullElements[0] = true;
-                } else {
-                    dataStr[0] = valueTab[0];
-                }
-                if (isNullOrNaN(valueTab[1])) {
-                    dataStr[1] = null;
-                    nullElements[1] = true;
-                } else {
-                    dataStr[1] = valueTab[1];
-                }
-
-                theTimedAttrData = new NullableTimedData();
-                theTimedAttrData.setValue(dataStr, nullElements);
-                break;
-
-            case TangoConst.Tango_DEV_STATE:
-                int[] dataI = new int[2];
-                if (isNullOrNaN(valueTab[0])) {
-                    dataI[0] = 0;
-                    nullElements[0] = true;
-                } else {
-                    dataI[0] = Integer.parseInt(valueTab[0]);
-                }
-                if (isNullOrNaN(valueTab[1])) {
-                    dataI[1] = 0;
-                    nullElements[1] = true;
-                } else {
-                    dataI[1] = Integer.parseInt(valueTab[1]);
-                }
-
-                theTimedAttrData = new NullableTimedData();
-                theTimedAttrData.setValue(dataI, nullElements);
-                break;
-
-            default:
-                throw new IllegalArgumentException("DefaultConverter/Data type not supported: " + dataType);
+        NullableTimedData timedAttrData = new NullableTimedData();
+        timedAttrData.setValue(data, nullElements);
+        if (result == null) {
+            result = new NullableTimedData[2];
         }
-
-        theTimedAttrData.setDataType(dataType);
-        theTimedAttrData.setTime(when);
-        theTimedAttrData.setX(1);
-        theTimedAttrData.setY(0);
-
-        return theTimedAttrData;
+        result[index] = timedAttrData;
+        return result;
     }
 
-    private NullableTimedData buildDataSpectrumRW(Object value, int dataType, long when)
-            throws IllegalArgumentException {
-        if (isNullOrNaNArray(value)) {
-            return null;
+    protected NullableTimedData[] treatScalarShortCase(String[] valueTab, NullableTimedData[] timedAttrDatas,
+            int index) {
+        NullableTimedData[] result = timedAttrDatas;
+        short[] data = new short[1];
+        boolean[] nullElements = new boolean[1];
+        if (isNullOrNaN(valueTab[index])) {
+            data[0] = 0;
+            nullElements[0] = true;
+        } else {
+            double theDataL_W_D = Double.parseDouble(valueTab[index]);
+            data[0] = (short) Math.round(theDataL_W_D);
         }
-        Object[] valueTab = (Object[]) value;
-        if (valueTab.length != 2) {
-            return null;
+        NullableTimedData timedAttrData = new NullableTimedData();
+        timedAttrData.setValue(data, nullElements);
+        if (result == null) {
+            result = new NullableTimedData[2];
         }
-        if (isNullOrNaNArray(valueTab[0])) {
-            return null;
+        result[index] = timedAttrData;
+        return result;
+    }
+
+    protected NullableTimedData[] treatScalarIntCase(String[] valueTab, NullableTimedData[] timedAttrDatas, int index) {
+        NullableTimedData[] result = timedAttrDatas;
+        int[] data = new int[1];
+        boolean[] nullElements = new boolean[1];
+        if (isNullOrNaN(valueTab[index])) {
+            data[0] = 0;
+            nullElements[0] = true;
+        } else {
+            double theDataL_W_D = Double.parseDouble(valueTab[index]);
+            data[0] = (int) Math.round(theDataL_W_D);
         }
-        if (isNullOrNaNArray(valueTab[1])) {
-            return null;
+        NullableTimedData timedAttrData = new NullableTimedData();
+        timedAttrData.setValue(data, nullElements);
+        if (result == null) {
+            result = new NullableTimedData[2];
         }
+        result[index] = timedAttrData;
+        return result;
+    }
 
-        NullableTimedData theTimedAttrData = null;
-        int x;
-
-        switch (dataType) {
-            case TangoConst.Tango_DEV_LONG:
-            case TangoConst.Tango_DEV_ULONG:
-                int[] dataL_Read = (int[]) valueTab[0];
-                int[] dataL_Write = (int[]) valueTab[1];
-                x = dataL_Read.length + dataL_Write.length;
-                int[] dataL = new int[x];
-
-                System.arraycopy(dataL_Read, 0, dataL, 0, dataL_Read.length);
-                System.arraycopy(dataL_Write, 0, dataL, dataL_Read.length, dataL_Write.length);
-
-                theTimedAttrData = new NullableTimedData();
-                theTimedAttrData.setValue(dataL, null);
-                break;
-
-            case TangoConst.Tango_DEV_SHORT:
-            case TangoConst.Tango_DEV_USHORT:
-                short[] dataS_Read = (short[]) valueTab[0];
-                short[] dataS_Write = (short[]) valueTab[1];
-                x = dataS_Read.length + dataS_Write.length;
-                short[] dataS = new short[x];
-
-                System.arraycopy(dataS_Read, 0, dataS, 0, dataS_Read.length);
-                System.arraycopy(dataS_Write, 0, dataS, dataS_Read.length, dataS_Write.length);
-
-                theTimedAttrData = new NullableTimedData();
-                theTimedAttrData.setValue(dataS, null);
-                break;
+    protected NullableTimedData[] treatScalarFloatCase(String[] valueTab, NullableTimedData[] timedAttrDatas,
+            int index) {
+        NullableTimedData[] result = timedAttrDatas;
+        float[] data = new float[1];
+        boolean[] nullElements = new boolean[1];
+        if (isNullOrNaN(valueTab[index])) {
+            data[0] = Float.NaN;
+            nullElements[0] = true;
+        } else {
+            data[0] = Float.parseFloat(valueTab[index]);
+        }
+        NullableTimedData timedAttrData = new NullableTimedData();
+        timedAttrData.setValue(data, nullElements);
+        if (result == null) {
+            result = new NullableTimedData[2];
+        }
+        result[index] = timedAttrData;
+        return result;
+    }
 
-            case TangoConst.Tango_DEV_DOUBLE:
-                double[] dataD_Read = (double[]) valueTab[0];
-                double[] dataD_Write = (double[]) valueTab[1];
-                x = dataD_Read.length + dataD_Write.length;
-                double[] dataD = new double[x];
+    protected NullableTimedData[] treatScalarDoubleCase(String[] valueTab, NullableTimedData[] timedAttrDatas,
+            int index) {
+        NullableTimedData[] result = timedAttrDatas;
+        double[] data = new double[1];
+        boolean[] nullElements = new boolean[1];
+        if (isNullOrNaN(valueTab[index])) {
+            data[0] = MathConst.NAN_FOR_NULL;
+            nullElements[0] = true;
+        } else {
+            data[0] = Double.parseDouble(valueTab[index]);
+        }
+        NullableTimedData timedAttrData = new NullableTimedData();
+        timedAttrData.setValue(data, nullElements);
+        if (result == null) {
+            result = new NullableTimedData[2];
+        }
+        result[index] = timedAttrData;
+        return result;
+    }
 
-                System.arraycopy(dataD_Read, 0, dataD, 0, dataD_Read.length);
-                System.arraycopy(dataD_Write, 0, dataD, dataD_Read.length, dataD_Write.length);
+    protected NullableTimedData[] treatScalarStringCase(String[] valueTab, NullableTimedData[] timedAttrDatas,
+            int index) {
+        NullableTimedData[] result = timedAttrDatas;
+        String[] data = new String[1];
+        boolean[] nullElements = new boolean[1];
+        if (isNullOrNaN(valueTab[index])) {
+            data[0] = null;
+            nullElements[0] = true;
+        } else {
+            data[0] = valueTab[index];
+        }
+        NullableTimedData timedAttrData = new NullableTimedData();
+        timedAttrData.setValue(data, nullElements);
+        if (result == null) {
+            result = new NullableTimedData[2];
+        }
+        result[index] = timedAttrData;
+        return result;
+    }
 
-                theTimedAttrData = new NullableTimedData();
-                theTimedAttrData.setValue(dataD, null);
-                break;
+    protected NullableTimedData[] treatSpectrumBooleanCase(Object[] valueTab, NullableTimedData[] timedAttrDatas,
+            int index) {
+        NullableTimedData[] result = timedAttrDatas;
+        // TODO maybe clone
+        boolean[] data = (boolean[]) valueTab[index];
+        NullableTimedData timedAttrData = new NullableTimedData();
+        timedAttrData.setValue(data, null);
+        timedAttrData.setX(data == null ? 0 : data.length);
+        if (result == null) {
+            result = new NullableTimedData[2];
+        }
+        result[index] = timedAttrData;
+        return result;
+    }
 
-            case TangoConst.Tango_DEV_BOOLEAN:
-                boolean[] dataB_Read = (boolean[]) valueTab[0];
-                boolean[] dataB_Write = (boolean[]) valueTab[1];
-                x = dataB_Read.length + dataB_Write.length;
-                boolean[] dataB = new boolean[x];
+    protected NullableTimedData[] treatSpectrumShortCase(Object[] valueTab, NullableTimedData[] timedAttrDatas,
+            int index) {
+        NullableTimedData[] result = timedAttrDatas;
+        // TODO maybe use NumberArrayUtils.extractShortArray(valueTab[index]), true);
+        short[] data = NumberArrayUtils.extractShortArray(valueTab[index]);
+
+        NullableTimedData timedAttrData = new NullableTimedData();
+        timedAttrData.setValue(data, null);
+        timedAttrData.setX(data == null ? 0 : data.length);
+        if (result == null) {
+            result = new NullableTimedData[2];
+        }
+        result[index] = timedAttrData;
+        return result;
+    }
 
-                System.arraycopy(dataB_Read, 0, dataB, 0, dataB_Read.length);
-                System.arraycopy(dataB_Write, 0, dataB, dataB_Read.length, dataB_Write.length);
+    protected NullableTimedData[] treatSpectrumIntCase(Object[] valueTab, NullableTimedData[] timedAttrDatas,
+            int index) {
+        NullableTimedData[] result = timedAttrDatas;
+        // TODO maybe use NumberArrayUtils.extractIntArray(valueTab[index]), true);
+        int[] data = NumberArrayUtils.extractIntArray(valueTab[index]);
+
+        NullableTimedData timedAttrData = new NullableTimedData();
+        timedAttrData.setValue(data, null);
+        timedAttrData.setX(data == null ? 0 : data.length);
+        if (result == null) {
+            result = new NullableTimedData[2];
+        }
+        result[index] = timedAttrData;
+        return result;
+    }
 
-                theTimedAttrData = new NullableTimedData();
-                theTimedAttrData.setValue(dataB, null);
-                break;
+    protected NullableTimedData[] treatSpectrumFloatCase(Object[] valueTab, NullableTimedData[] timedAttrDatas,
+            int index) {
+        NullableTimedData[] result = timedAttrDatas;
+        // TODO maybe use NumberArrayUtils.extractFloatArray(valueTab[index]), true);
+        float[] data = NumberArrayUtils.extractFloatArray(valueTab[index]);
+
+        NullableTimedData timedAttrData = new NullableTimedData();
+        timedAttrData.setValue(data, null);
+        timedAttrData.setX(data == null ? 0 : data.length);
+        if (result == null) {
+            result = new NullableTimedData[2];
+        }
+        result[index] = timedAttrData;
+        return result;
+    }
 
-            case TangoConst.Tango_DEV_FLOAT:
-                float[] dataF_Read = (float[]) valueTab[0];
-                float[] dataF_Write = (float[]) valueTab[1];
-                x = dataF_Read.length + dataF_Write.length;
-                float[] dataF = new float[x];
+    protected NullableTimedData[] treatSpectrumDoubleCase(Object[] valueTab, NullableTimedData[] timedAttrDatas,
+            int index) {
+        NullableTimedData[] result = timedAttrDatas;
+        // TODO maybe use NumberArrayUtils.extractDoubleArray(valueTab[index]), true);
+        double[] data = NumberArrayUtils.extractDoubleArray(valueTab[index]);
+
+        NullableTimedData timedAttrData = new NullableTimedData();
+        timedAttrData.setValue(data, null);
+        timedAttrData.setX(data == null ? 0 : data.length);
+        if (result == null) {
+            result = new NullableTimedData[2];
+        }
+        result[index] = timedAttrData;
+        return result;
+    }
 
-                System.arraycopy(dataF_Read, 0, dataF, 0, dataF_Read.length);
-                System.arraycopy(dataF_Write, 0, dataF, dataF_Read.length, dataF_Write.length);
+    protected NullableTimedData[] treatSpectrumStringCase(Object[] valueTab, NullableTimedData[] timedAttrDatas,
+            int index) {
+        NullableTimedData[] result = timedAttrDatas;
+        // TODO maybe clone
+        String[] data = (String[]) valueTab[index];
+        NullableTimedData timedAttrData = new NullableTimedData();
+        timedAttrData.setValue(data, null);
+        timedAttrData.setX(data == null ? 0 : data.length);
+        if (result == null) {
+            result = new NullableTimedData[2];
+        }
+        result[index] = timedAttrData;
+        return result;
+    }
 
-                theTimedAttrData = new NullableTimedData();
-                theTimedAttrData.setValue(dataF, null);
-                break;
+    /**
+     * @param value
+     * @param dataType
+     * @param when
+     * @return
+     */
+    private NullableTimedData[] buildDataScalarRW(Object value, int dataType, long when)
+            throws IllegalArgumentException {
+        NullableTimedData[] result = null;
+        // String[] valueTab = this.castObjectTableToString ( (Object []) value
+        // , true );
+        String[] valueTab = this.castObjectTableToString(value, false);
+        if (valueTab == null) {
+            result = null;
+        } else {
+            switch (dataType) {
+                case TangoConst.Tango_DEV_LONG:
+                case TangoConst.Tango_DEV_ULONG:
+                    result = treatScalarIntCase(valueTab, result, READ_INDEX);
+                    result = treatScalarIntCase(valueTab, result, WRITE_INDEX);
+                    break;
+
+                case TangoConst.Tango_DEV_SHORT:
+                case TangoConst.Tango_DEV_USHORT:
+                    result = treatScalarShortCase(valueTab, result, READ_INDEX);
+                    result = treatScalarShortCase(valueTab, result, WRITE_INDEX);
+                    break;
+
+                case TangoConst.Tango_DEV_DOUBLE:
+                    result = treatScalarDoubleCase(valueTab, result, READ_INDEX);
+                    result = treatScalarDoubleCase(valueTab, result, WRITE_INDEX);
+                    break;
+
+                case TangoConst.Tango_DEV_BOOLEAN:
+                    result = treatScalarBooleanCase(valueTab, result, READ_INDEX);
+                    result = treatScalarBooleanCase(valueTab, result, WRITE_INDEX);
+                    break;
+
+                case TangoConst.Tango_DEV_FLOAT:
+                    result = treatScalarFloatCase(valueTab, result, READ_INDEX);
+                    result = treatScalarFloatCase(valueTab, result, WRITE_INDEX);
+                    break;
+
+                case TangoConst.Tango_DEV_STRING:
+                    result = treatScalarStringCase(valueTab, result, READ_INDEX);
+                    result = treatScalarStringCase(valueTab, result, WRITE_INDEX);
+                    break;
+
+                case TangoConst.Tango_DEV_STATE:
+                    result = treatScalarIntCase(valueTab, result, READ_INDEX);
+                    result = treatScalarIntCase(valueTab, result, WRITE_INDEX);
+                    break;
+
+                default:
+                    throw new IllegalArgumentException("DefaultConverter/Data type not supported: " + dataType);
+            }
+            if (result != null) {
+                for (NullableTimedData theTimedAttrData : result) {
+                    if (theTimedAttrData != null) {
+                        theTimedAttrData.setDataType(dataType);
+                        theTimedAttrData.setTime(when);
+                        theTimedAttrData.setX(1);
+                        theTimedAttrData.setY(0);
+                    }
+                }
+            }
+        }
+        return result;
+    }
 
-            case TangoConst.Tango_DEV_STRING:
-                String[] dataStr_Read = (String[]) valueTab[0];
-                String[] dataStr_Write = (String[]) valueTab[1];
-                x = dataStr_Read.length + dataStr_Write.length;
-                String[] dataStr = new String[x];
+    private NullableTimedData[] buildDataSpectrumRW(Object value, int dataType, long when)
+            throws IllegalArgumentException {
+        NullableTimedData[] result = null;
+        if (!isNullOrNaNArray(value)) {
+            Object[] valueTab = (Object[]) value;
+            if ((valueTab.length == 2) && (!isNullOrNaNArray(valueTab[0])) && (!isNullOrNaNArray(valueTab[1]))) {
+
+                switch (dataType) {
+                    case TangoConst.Tango_DEV_LONG:
+                    case TangoConst.Tango_DEV_ULONG:
+                    case TangoConst.Tango_DEV_STATE:
+                        result = treatSpectrumIntCase(valueTab, result, READ_INDEX);
+                        result = treatSpectrumIntCase(valueTab, result, WRITE_INDEX);
+                        break;
 
-                System.arraycopy(dataStr_Read, 0, dataStr, 0, dataStr_Read.length);
-                System.arraycopy(dataStr_Write, 0, dataStr, dataStr_Read.length, dataStr_Write.length);
+                    case TangoConst.Tango_DEV_SHORT:
+                    case TangoConst.Tango_DEV_USHORT:
+                        result = treatSpectrumShortCase(valueTab, result, READ_INDEX);
+                        result = treatSpectrumShortCase(valueTab, result, WRITE_INDEX);
+                        break;
 
-                theTimedAttrData = new NullableTimedData();
-                theTimedAttrData.setValue(dataStr, null);
-                break;
+                    case TangoConst.Tango_DEV_DOUBLE:
+                        result = treatSpectrumDoubleCase(valueTab, result, READ_INDEX);
+                        result = treatSpectrumDoubleCase(valueTab, result, WRITE_INDEX);
+                        break;
 
-            case TangoConst.Tango_DEV_STATE:
-                int[] dataI_Read = (int[]) valueTab[0];
-                int[] dataI_Write = (int[]) valueTab[1];
-                x = dataI_Read.length + dataI_Write.length;
-                int[] dataI = new int[x];
+                    case TangoConst.Tango_DEV_BOOLEAN:
+                        result = treatSpectrumBooleanCase(valueTab, result, READ_INDEX);
+                        result = treatSpectrumBooleanCase(valueTab, result, WRITE_INDEX);
+                        break;
 
-                System.arraycopy(dataI_Read, 0, dataI, 0, dataI_Read.length);
-                System.arraycopy(dataI_Write, 0, dataI, dataI_Read.length, dataI_Write.length);
+                    case TangoConst.Tango_DEV_FLOAT:
+                        result = treatSpectrumFloatCase(valueTab, result, READ_INDEX);
+                        result = treatSpectrumFloatCase(valueTab, result, WRITE_INDEX);
+                        break;
 
-                theTimedAttrData = new NullableTimedData();
-                theTimedAttrData.setValue(dataI, null);
-                break;
+                    case TangoConst.Tango_DEV_STRING:
+                        result = treatSpectrumStringCase(valueTab, result, READ_INDEX);
+                        result = treatSpectrumStringCase(valueTab, result, WRITE_INDEX);
+                        break;
 
-            default:
-                throw new IllegalArgumentException("DefaultConverter/Data type not supported: " + dataType);
+                    default:
+                        throw new IllegalArgumentException("DefaultConverter/Data type not supported: " + dataType);
+                }
+                if (result != null) {
+                    for (NullableTimedData theTimedAttrData : result) {
+                        if (theTimedAttrData != null) {
+                            theTimedAttrData.setDataType(dataType);
+                            theTimedAttrData.setTime(when);
+                        }
+                    }
+                }
+            }
         }
-
-        theTimedAttrData.setDataType(dataType);
-        theTimedAttrData.setTime(when);
-        theTimedAttrData.setX(x);
-        return theTimedAttrData;
+        return result;
     }
 
-    private NullableTimedData buildDataScalarR(Object value, int dataType, long when) throws IllegalArgumentException {
+    private NullableTimedData[] buildDataScalarR(Object value, int dataType, boolean write, long when)
+            throws IllegalArgumentException {
+        NullableTimedData[] result = null;
         NullableTimedData theTimedAttrData = null;
 
         final boolean[] nullElements = new boolean[1];
@@ -531,89 +600,95 @@ public class DefaultConverter implements IConverter {
             default:
                 throw new IllegalArgumentException("DefaultConverter/Data type not supported: " + dataType);
         }
-
-        theTimedAttrData.setDataType(dataType);
-        theTimedAttrData.setTime(when);
-        theTimedAttrData.setX(1);
-        theTimedAttrData.setY(0);
-        return theTimedAttrData;
-    }
-
-    private NullableTimedData buildDataSpectrumR(Object value, int dataType, long when) throws IllegalArgumentException {
-        if (isNullOrNaNArray(value)) {
-            return null;
+        if (theTimedAttrData != null) {
+            theTimedAttrData.setDataType(dataType);
+            theTimedAttrData.setTime(when);
+            theTimedAttrData.setX(1);
+            theTimedAttrData.setY(0);
+            result = new NullableTimedData[2];
+            result[write ? WRITE_INDEX : READ_INDEX] = theTimedAttrData;
         }
+        return result;
+    }
 
-        int x;
-        NullableTimedData theTimedAttrData = null;
-
-        switch (dataType) {
-            case TangoConst.Tango_DEV_LONG:
-            case TangoConst.Tango_DEV_ULONG:
-                int[] dataL = (int[]) value;
-                x = dataL.length;
-
-                theTimedAttrData = new NullableTimedData();
-                theTimedAttrData.setValue(dataL, null);
-                break;
-
-            case TangoConst.Tango_DEV_SHORT:
-            case TangoConst.Tango_DEV_USHORT:
-                short[] dataS = (short[]) value;
-                x = dataS.length;
-
-                theTimedAttrData = new NullableTimedData();
-                theTimedAttrData.setValue(dataS, null);
-                break;
-
-            case TangoConst.Tango_DEV_DOUBLE:
-                double[] dataD = (double[]) value;
-                x = dataD.length;
-
-                theTimedAttrData = new NullableTimedData();
-                theTimedAttrData.setValue(dataD, null);
-                break;
-
-            case TangoConst.Tango_DEV_BOOLEAN:
-                boolean[] dataB = (boolean[]) value;
-                x = dataB.length;
-
-                theTimedAttrData = new NullableTimedData();
-                theTimedAttrData.setValue(dataB, null);
-                break;
-
-            case TangoConst.Tango_DEV_FLOAT:
-                float[] dataF = (float[]) value;
-                x = dataF.length;
-
-                theTimedAttrData = new NullableTimedData();
-                theTimedAttrData.setValue(dataF, null);
-                break;
-
-            case TangoConst.Tango_DEV_STRING:
-                String[] dataStr = (String[]) value;
-                x = dataStr.length;
-
-                theTimedAttrData = new NullableTimedData();
-                theTimedAttrData.setValue(dataStr, null);
-                break;
-
-            case TangoConst.Tango_DEV_STATE:
-                int[] dataI = (int[]) value;
-                x = dataI.length;
-
-                theTimedAttrData = new NullableTimedData();
-                theTimedAttrData.setValue(dataI, null);
-                break;
-
-            default:
-                throw new IllegalArgumentException("DefaultConverter/Data type not supported: " + dataType);
+    private NullableTimedData[] buildDataSpectrumR(Object value, int dataType, boolean write, long when)
+            throws IllegalArgumentException {
+        NullableTimedData[] result = null;
+        if (!isNullOrNaNArray(value)) {
+            int x;
+            NullableTimedData theTimedAttrData = null;
+
+            switch (dataType) {
+                case TangoConst.Tango_DEV_LONG:
+                case TangoConst.Tango_DEV_ULONG:
+                    int[] dataL = (int[]) value;
+                    x = dataL.length;
+
+                    theTimedAttrData = new NullableTimedData();
+                    theTimedAttrData.setValue(dataL, null);
+                    break;
+
+                case TangoConst.Tango_DEV_SHORT:
+                case TangoConst.Tango_DEV_USHORT:
+                    short[] dataS = (short[]) value;
+                    x = dataS.length;
+
+                    theTimedAttrData = new NullableTimedData();
+                    theTimedAttrData.setValue(dataS, null);
+                    break;
+
+                case TangoConst.Tango_DEV_DOUBLE:
+                    double[] dataD = (double[]) value;
+                    x = dataD.length;
+
+                    theTimedAttrData = new NullableTimedData();
+                    theTimedAttrData.setValue(dataD, null);
+                    break;
+
+                case TangoConst.Tango_DEV_BOOLEAN:
+                    boolean[] dataB = (boolean[]) value;
+                    x = dataB.length;
+
+                    theTimedAttrData = new NullableTimedData();
+                    theTimedAttrData.setValue(dataB, null);
+                    break;
+
+                case TangoConst.Tango_DEV_FLOAT:
+                    float[] dataF = (float[]) value;
+                    x = dataF.length;
+
+                    theTimedAttrData = new NullableTimedData();
+                    theTimedAttrData.setValue(dataF, null);
+                    break;
+
+                case TangoConst.Tango_DEV_STRING:
+                    String[] dataStr = (String[]) value;
+                    x = dataStr.length;
+
+                    theTimedAttrData = new NullableTimedData();
+                    theTimedAttrData.setValue(dataStr, null);
+                    break;
+
+                case TangoConst.Tango_DEV_STATE:
+                    int[] dataI = (int[]) value;
+                    x = dataI.length;
+
+                    theTimedAttrData = new NullableTimedData();
+                    theTimedAttrData.setValue(dataI, null);
+                    break;
+
+                default:
+                    throw new IllegalArgumentException("DefaultConverter/Data type not supported: " + dataType);
+            }
+            if (theTimedAttrData != null) {
+                theTimedAttrData.setDataType(dataType);
+                theTimedAttrData.setTime(when);
+                theTimedAttrData.setX(x);
+                result = new NullableTimedData[2];
+                result[write ? WRITE_INDEX : READ_INDEX] = theTimedAttrData;
+            }
         }
-
-        theTimedAttrData.setDataType(dataType);
-        theTimedAttrData.setTime(when);
-        theTimedAttrData.setX(x);
-        return theTimedAttrData;
+        return result;
     }
 
     @Override
diff --git a/src/main/java/fr/soleil/archiving/snap/api/extractor/convert/IConverter.java b/src/main/java/fr/soleil/archiving/snap/api/extractor/convert/IConverter.java
index 4086e7e..49e9cc4 100644
--- a/src/main/java/fr/soleil/archiving/snap/api/extractor/convert/IConverter.java
+++ b/src/main/java/fr/soleil/archiving/snap/api/extractor/convert/IConverter.java
@@ -1,19 +1,20 @@
-/*	Synchrotron Soleil 
- *  
- *   File          :  IConverter.java
- *  
- *   Project       :  snapExtractorAPI
- *  
- *   Description   :  
- *  
- *   Author        :  CLAISSE
- *  
- *   Original      :  24 janv. 2006 
- *  
- *   Revision:  					Author:  
- *   Date: 							State:  
- *  
- *   Log: IConverter.java,v 
+/*
+ * Synchrotron Soleil
+ * 
+ * File : IConverter.java
+ * 
+ * Project : snapExtractorAPI
+ * 
+ * Description :
+ * 
+ * Author : CLAISSE
+ * 
+ * Original : 24 janv. 2006
+ * 
+ * Revision: Author:
+ * Date: State:
+ * 
+ * Log: IConverter.java,v
  *
  */
 /*
@@ -27,6 +28,7 @@ package fr.soleil.archiving.snap.api.extractor.convert;
 import fr.esrf.Tango.DevFailed;
 import fr.soleil.archiving.common.api.tools.DbData;
 import fr.soleil.archiving.snap.api.tools.SnapAttributeExtract;
+import fr.soleil.database.DBExtractionConst;
 
 /**
  * Converts data from the format returned by the Database API to a format usable
@@ -34,14 +36,15 @@ import fr.soleil.archiving.snap.api.tools.SnapAttributeExtract;
  * 
  * @author CLAISSE
  */
-public interface IConverter {
+public interface IConverter extends DBExtractionConst {
+
     /**
      * @param currentExtract
      *            The data in its Database API format
      * @return The data in its usable format
      * @throws DevFailed
      */
-    public DbData convert(SnapAttributeExtract currentExtract) throws DevFailed;
+    public DbData[] convert(SnapAttributeExtract currentExtract) throws DevFailed;
 
     /**
      * Converts raw array input to a more palatable String[] output
-- 
GitLab