commit 779bac699980d1a6215864bf441065d922ec9293
Author: Marc NICOLAS <marc.nicolas@ias.u-psud.fr>
Date:   Fri Jan 15 14:59:43 2016 +0100

    Ajout derniere version de TAP

diff --git a/sitools-idoc/hesiod/README.txt b/sitools-idoc/hesiod/README.txt
new file mode 100644
index 0000000..fbc7ac9
--- /dev/null
+++ b/sitools-idoc/hesiod/README.txt
@@ -0,0 +1 @@
+This folder contains the developments of HESIOD.
diff --git a/sitools-idoc/hesiod/astronmy-extension/src/fr/cnes/sitools/astro/vo/conesearch/ConeSearchInputParameters.java b/sitools-idoc/hesiod/astronmy-extension/src/fr/cnes/sitools/astro/vo/conesearch/ConeSearchInputParameters.java
new file mode 100644
index 0000000..6ed5128
--- /dev/null
+++ b/sitools-idoc/hesiod/astronmy-extension/src/fr/cnes/sitools/astro/vo/conesearch/ConeSearchInputParameters.java
@@ -0,0 +1,241 @@
+ /*******************************************************************************
+ * Copyright 2010-2013 CNES - CENTRE NATIONAL d'ETUDES SPATIALES
+ *
+ * This file is part of SITools2.
+ *
+ * SITools2 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * SITools2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with SITools2.  If not, see <http://www.gnu.org/licenses/>.
+ ******************************************************************************/
+package fr.cnes.sitools.astro.vo.conesearch;
+
+import fr.cnes.sitools.dataset.DataSetApplication;
+import fr.cnes.sitools.extensions.common.InputsValidation;
+import fr.cnes.sitools.extensions.common.NotNullAndNotEmptyValidation;
+import fr.cnes.sitools.extensions.common.RangeValidation;
+import fr.cnes.sitools.extensions.common.StatusValidation;
+import fr.cnes.sitools.extensions.common.Validation;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import net.ivoa.xml.votable.v1.Info;
+import org.restlet.Context;
+import org.restlet.Request;
+
+/**
+ * This object provides methods to handle input parameters for the cone search protocol.
+ *
+ * @author Jean-Christophe Malapert
+ */
+public class ConeSearchInputParameters implements ConeSearchDataModelInterface {
+
+  /**
+   * Logger.
+   */
+  private static final Logger LOG = Logger.getLogger(ConeSearchInputParameters.class.getName());
+  /**
+   * Default verbosity mode.
+   */
+  private static final int DEFAULT_VERBOSITY_MODE = 0;
+  /**
+   * Verbosity mode.
+   */
+  private transient int verb = DEFAULT_VERBOSITY_MODE;
+  /**
+   * Data model.
+   */
+  private final transient Map dataModel = new HashMap();
+  /**
+   * User request.
+   */
+  private final transient Request request;
+  /**
+   * Application context.
+   */
+  private final transient Context context;
+  /**
+   * Application.
+   */
+  private final transient DataSetApplication datasetApp;
+  /**
+   * Right ascension of the cone center.
+   */
+  private transient double rightAscension;
+  /**
+   * Declination of the cone center.
+   */
+  private transient double declination;
+  /**
+   * Radius of the cone.
+   */
+  private transient double radius;
+
+  /**
+   * Constructor.
+   *
+   * @param datasetAppVal dataset application
+   * @param requestVal Request
+   * @param contextVal Context
+   * @param maxSr maxSr for the cone search
+   * @param verbosity verbosity
+   * @param verbVal verbosity level
+   */
+  public ConeSearchInputParameters(final DataSetApplication datasetAppVal, final Request requestVal, final Context contextVal,
+          final double maxSr, final boolean verbosity, final int verbVal) {
+    this.datasetApp = datasetAppVal;
+    this.context = contextVal;
+    this.request = requestVal;
+    final String raInput = this.request.getResourceRef().getQueryAsForm().getFirstValue(ConeSearchProtocolLibrary.RA);
+    final String decInput = this.request.getResourceRef().getQueryAsForm().getFirstValue(ConeSearchProtocolLibrary.DEC);
+    final String srInput = this.request.getResourceRef().getQueryAsForm().getFirstValue(ConeSearchProtocolLibrary.SR);
+    final String verbInput = this.request.getResourceRef().getQueryAsForm().getFirstValue(ConeSearchProtocolLibrary.VERB);
+    if(raInput == null && decInput == null && srInput == null){
+        Info info = new Info();
+        info.setName("QUERY_STATUS");
+        info.setValueAttribute("ERROR");
+        info.setValue("RA, DEC and SR must be not null");
+        final List<Info> listInfos = new ArrayList<Info>();
+        listInfos.add(info);
+        this.dataModel.put("infos", listInfos);
+    }else{
+        checkInputParameters(raInput, decInput, srInput, maxSr, verbInput, verbosity, verbVal);
+    }
+  }
+
+  /**
+   * Check input parameters.
+   *
+   * @param raInput Ra
+   * @param decInput Dec
+   * @param srInput Sr
+   * @param maxSr maxSr
+   * @param verbosity verbosity
+   * @param verbInput user inpur verb
+   * @param verbVal verbosity from admin
+   */
+  private void checkInputParameters(final String raInput, final String decInput, final String srInput, final double maxSr,
+          final String verbInput, final boolean verbosity, final int verbVal) {
+    final List<Info> infos = new ArrayList<Info>();
+    final Map<String, String> validationMap = new HashMap<String, String>();
+    validationMap.put(ConeSearchProtocolLibrary.RA, raInput);
+    validationMap.put(ConeSearchProtocolLibrary.DEC, decInput);
+    validationMap.put(ConeSearchProtocolLibrary.SR, srInput);
+    validationMap.put(ConeSearchProtocolLibrary.VERB, verbInput);
+    validationMap.put(ConeSearchProtocolLibrary.VERBOSITY, String.valueOf(verbosity));
+    Validation validation = new InputsValidation(validationMap);
+    validation = new RangeValidation(validation, ConeSearchProtocolLibrary.RA, ConeSearchProtocolLibrary.RA_MIN, ConeSearchProtocolLibrary.RA_MAX);
+    validation = new RangeValidation(validation, ConeSearchProtocolLibrary.DEC, ConeSearchProtocolLibrary.DEC_MIN, ConeSearchProtocolLibrary.DEC_MAX);
+    validation = new RangeValidation(validation, ConeSearchProtocolLibrary.SR, 0, maxSr);
+    validation = new NotNullAndNotEmptyValidation(validation, ConeSearchProtocolLibrary.VERBOSITY);
+    validation = new NotNullAndNotEmptyValidation(validation, ConeSearchProtocolLibrary.VERB, String.valueOf(verbVal));
+    final StatusValidation status = validation.validate();
+    if (status.isValid()) {
+        final Map<String, String> input = validation.getMap();
+        this.rightAscension = Double.valueOf(input.get(ConeSearchProtocolLibrary.RA));
+        this.declination = Double.valueOf(input.get(ConeSearchProtocolLibrary.DEC));
+        this.radius = Double.valueOf(input.get(ConeSearchProtocolLibrary.SR));
+        this.verb = Integer.valueOf(input.get(ConeSearchProtocolLibrary.VERB));
+    } else {
+        Info infoError = new Info();
+        infoError.setName("QUERY_STATUS");
+        infoError.setValueAttribute("ERROR");
+        infos.add(infoError);
+        final Map<String, String> errors = status.getMessages();
+        final Set<Entry<String, String>> entries = errors.entrySet();
+        for (Entry<String, String> entry : entries) {
+            final Info info = new Info();
+            info.setID(entry.getKey());
+            info.setName("Error in " + entry.getKey());
+            info.setValueAttribute("Error in input " + entry.getKey() + ": " + entry.getValue());
+            infos.add(info);
+            LOG.log(Level.FINEST, "{0}: {1}", new Object[]{entry.getKey(), entry.getValue()});
+        }
+    }
+    if (!infos.isEmpty()) {
+      this.dataModel.put("infos", infos);
+    }
+  }
+
+  /**
+   * Get Ra.
+   *
+   * @return Ra
+   */
+  public final double getRa() {
+    return this.rightAscension;
+  }
+
+  /**
+   * Get Dec.
+   *
+   * @return Dec
+   */
+  public final double getDec() {
+    return this.declination;
+  }
+
+  /**
+   * Get Sr.
+   *
+   * @return Sr
+   */
+  public final double getSr() {
+    return this.radius;
+  }
+
+  /**
+   * Get verbosity level.
+   *
+   * @return verbosity level
+   */
+  public final int getVerb() {
+    return this.verb;
+  }
+
+  @Override
+  public final Map getDataModel() {
+    return Collections.unmodifiableMap(this.dataModel);
+  }
+
+  /**
+   * Returns the request.
+   *
+   * @return Request
+   */
+  public final Request getRequest() {
+    return this.request;
+  }
+
+  /**
+   * Returns the context.
+   *
+   * @return Context
+   */
+  public final Context getContext() {
+    return this.context;
+  }
+
+  /**
+   * Get DatasetApplication.
+   *
+   * @return Dataset application
+   */
+  public final DataSetApplication getDatasetApplication() {
+    return this.datasetApp;
+  }
+}
\ No newline at end of file
diff --git a/sitools-idoc/hesiod/astronmy-extension/src/fr/cnes/sitools/astro/vo/sia/SimpleImageAccessInputParameters.java b/sitools-idoc/hesiod/astronmy-extension/src/fr/cnes/sitools/astro/vo/sia/SimpleImageAccessInputParameters.java
new file mode 100644
index 0000000..a4c1f7e
--- /dev/null
+++ b/sitools-idoc/hesiod/astronmy-extension/src/fr/cnes/sitools/astro/vo/sia/SimpleImageAccessInputParameters.java
@@ -0,0 +1,474 @@
+ /*******************************************************************************
+ * Copyright 2010-2013 CNES - CENTRE NATIONAL d'ETUDES SPATIALES
+ *
+ * This file is part of SITools2.
+ *
+ * SITools2 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * SITools2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with SITools2.  If not, see <http://www.gnu.org/licenses/>.
+ ******************************************************************************/
+package fr.cnes.sitools.astro.vo.sia;
+
+import fr.cnes.sitools.dataset.DataSetApplication;
+import fr.cnes.sitools.dataset.dto.ColumnConceptMappingDTO;
+import fr.cnes.sitools.dictionary.model.Concept;
+import fr.cnes.sitools.extensions.common.InputsValidation;
+import fr.cnes.sitools.extensions.common.NotNullAndNotEmptyValidation;
+import fr.cnes.sitools.extensions.common.NumberArrayValidation;
+import fr.cnes.sitools.extensions.common.SpatialGeoValidation; 
+import fr.cnes.sitools.extensions.common.StatusValidation;
+import fr.cnes.sitools.extensions.common.Validation;
+import fr.cnes.sitools.plugins.resources.model.ResourceModel;
+import fr.cnes.sitools.util.Util;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import net.ivoa.xml.votable.v1.AnyTEXT;
+import net.ivoa.xml.votable.v1.DataType;
+import net.ivoa.xml.votable.v1.Field;
+import net.ivoa.xml.votable.v1.Info;
+import net.ivoa.xml.votable.v1.Option;
+import net.ivoa.xml.votable.v1.Param;
+import net.ivoa.xml.votable.v1.Values;
+import org.restlet.Context;
+import org.restlet.Request;
+
+
+/**
+ * Input parameters for SIA.
+ *
+ * @author Jean-Crhistophe Malapert <jean-christophe.malapert@cnes.fr>
+ */
+import fr.cnes.sitools.common.exception.SitoolsException;
+import fr.cnes.sitools.dataset.dto.DictionaryMappingDTO;
+public class SimpleImageAccessInputParameters implements DataModelInterface {
+  /**
+   * Logger.
+   */
+  private static final Logger LOG = Logger.getLogger(SimpleImageAccessInputParameters.class.getName());
+  /**
+   * Init value for right ascension parameter of the user input.
+   */
+  private transient double ra = 0.0;
+  /**
+   * Init value for declination parameter of the user input.
+   */
+  private transient double dec = 0.0;
+  /**
+   * Array that stores the size parameter of the user input.
+   */
+  private transient double[] size;
+  /**
+   * Default value for the verb parameter of the user input.
+   */
+  private transient int verb = 0;
+  /**
+   * Data model that stores the metadata response of the service.
+   */
+  private final transient Map dataModel = new HashMap();
+  /**
+   * Request.
+   */
+  private final transient Request request;
+  /**
+   * Context.
+   */
+  private final transient Context context;
+  /**
+   * Application where this resources is linked.
+   */
+  private final transient DataSetApplication datasetApp;
+  /**
+   * Configuration parameters of this resource.
+   */
+  private final transient ResourceModel resourceModel;
+
+  /**
+   * Constructs the objet that returns the metadata of the service.
+   * @param datasetAppVal application
+   * @param requestVal request
+   * @param contextVal context
+   * @param resourceModelVal configuration parameters
+   */
+  public SimpleImageAccessInputParameters(final DataSetApplication datasetAppVal, final Request requestVal, final Context contextVal, final ResourceModel resourceModelVal) {
+    this.datasetApp = datasetAppVal;
+    this.context = contextVal;
+    this.request = requestVal;
+    this.resourceModel = resourceModelVal;
+    final String posInput = this.request.getResourceRef().getQueryAsForm().getFirstValue(SimpleImageAccessProtocolLibrary.POS);
+    final String sizeInput = this.request.getResourceRef().getQueryAsForm().getFirstValue(SimpleImageAccessProtocolLibrary.SIZE);
+    final String format = this.request.getResourceRef().getQueryAsForm().getFirstValue(SimpleImageAccessProtocolLibrary.FORMAT);
+    final String intersect = this.request.getResourceRef().getQueryAsForm().getFirstValue(SimpleImageAccessProtocolLibrary.INTERSECT);
+    final String verbosity = this.request.getResourceRef().getQueryAsForm().getFirstValue(SimpleImageAccessProtocolLibrary.VERB);
+    //TODO check the differentParameters
+    if(posInput == null && sizeInput == null){
+        Info info = new Info();
+        info.setName("QUERY_STATUS");
+        info.setValueAttribute("ERROR");
+        final List<Info> listInfos = new ArrayList<Info>();
+        listInfos.add(info);
+        this.dataModel.put("infos", listInfos);
+        if(format.equalsIgnoreCase("METADATA")){
+            fillMetadataFormat();
+        }
+    }else{
+        if (Util.isSet(format) && format.equals(SimpleImageAccessProtocolLibrary.ParamStandardFormat.METADATA.name())) {
+            fillMetadataFormat();
+        } else {
+            checkInputParameters(posInput, sizeInput);
+        }
+    }
+  }
+
+  /**
+   * Fills metadata response.
+   */
+  private void fillMetadataFormat() {
+      
+    this.dataModel.put("description", this.resourceModel.getParameterByName(SimpleImageAccessProtocolLibrary.DESCRIPTION).getValue());
+
+    final Info info = new Info();
+    info.setName("QUERY_STATUS");
+    info.setValueAttribute("OK");
+    final List<Info> listInfos = new ArrayList<Info>();
+    listInfos.add(info);
+    this.dataModel.put("infos", listInfos);
+   
+    final List<Param> listParam = new ArrayList<Param>();
+    Param param = new Param();
+    param.setName("INPUT:POS");
+    param.setValue("0,0");
+    param.setDatatype(DataType.DOUBLE);
+    AnyTEXT anyText = new AnyTEXT();
+    anyText.getContent().add("Search Position in the form ra,dec where ra and dec are given in decimal degrees in the ICRS coordinate system.");
+    param.setDESCRIPTION(anyText);
+    listParam.add(param);
+
+    param = new Param();
+    param.setName("INPUT:SIZE");
+    param.setValue("0.05");
+    param.setDatatype(DataType.DOUBLE);
+    anyText = new AnyTEXT();
+    anyText.getContent().add("Size of search region in the RA and Dec directions.");
+    param.setDESCRIPTION(anyText);
+    listParam.add(param);
+
+    param = new Param();
+    param.setName("INPUT:FORMAT");
+    param.setValue(SimpleImageAccessProtocolLibrary.ParamStandardFormat.ALL.name());
+    param.setDatatype(DataType.CHAR);
+    param.setArraysize("*");
+    anyText = new AnyTEXT();
+    anyText.getContent().add("Requested format of images.");
+    param.setDESCRIPTION(anyText);
+    final List<String> formatList = SimpleImageAccessProtocolLibrary.ParamStandardFormat.getCtes();
+    final Values values = new Values();
+    for (String formatIter : formatList) {
+      final Option option = new Option();
+      option.setValue(formatIter);
+      values.getOPTION().add(option);
+    }
+    param.setVALUES(values);
+    //TODO : le faire pour chaque format
+    listParam.add(param);
+    
+    param = new Param();
+    param.setName("INPUT:INTERSECT");
+    param.setValue(this.resourceModel.getParameterByName(SimpleImageAccessProtocolLibrary.INTERSECT).getValue());
+    param.setDatatype(DataType.CHAR);
+    anyText = new AnyTEXT();
+    anyText.getContent().add("Choice of overlap with requested region.");
+    param.setDESCRIPTION(anyText);
+    listParam.add(param);
+
+    param = new Param();
+    param.setName("INPUT:VERB");
+    param.setValue(this.resourceModel.getParameterByName(SimpleImageAccessProtocolLibrary.VERB).getValue());
+    param.setDatatype(DataType.INT);
+    anyText = new AnyTEXT();
+    anyText.getContent().add("Verbosity level, controlling the number of columns returned.");
+    param.setDESCRIPTION(anyText);
+    listParam.add(param);
+
+    dataModel.put("params", listParam);
+    //******************************************************************************************************************
+    //******************************************************************************************************************
+    //******************************************************************************************************************
+    String dictionaryName = resourceModel.getParameterByName(SimpleImageAccessProtocolLibrary.DICTIONARY).getValue();
+    final List<String> columnList = new ArrayList<String>();
+    List<Field> fieldList = new ArrayList<Field>();
+    try {
+        List<ColumnConceptMappingDTO> mappingList = getDicoFromConfiguration(datasetApp, dictionaryName);
+        setFields(fieldList, columnList, mappingList);
+    }catch (SitoolsException ex) {
+             
+    }
+    
+  }
+
+  /**
+   * Checks input parameters.
+   * @param posInput input parameter for POS
+   * @param sizeInput input parameter for SIZE
+   */
+  private void checkInputParameters(final String posInput, final String sizeInput) {
+    final List<Info> infos = new ArrayList<Info>();
+    final Map<String, String> validationMap = new HashMap<String, String>();
+    validationMap.put(SimpleImageAccessProtocolLibrary.POS, posInput);
+    validationMap.put(SimpleImageAccessProtocolLibrary.SIZE, sizeInput);    
+    Validation validation = new InputsValidation(validationMap);
+    validation = new NotNullAndNotEmptyValidation(validation, SimpleImageAccessProtocolLibrary.POS);
+    validation = new NotNullAndNotEmptyValidation(validation, SimpleImageAccessProtocolLibrary.SIZE);
+    if(validation.validate().isValid()){
+        validation = new SpatialGeoValidation(validation, SimpleImageAccessProtocolLibrary.POS, 0, 1, new double[]{0.0, 360.0}, new double[]{-90.0, 90.0});
+        // LA LIGNE SUIVANTE A ETE AJOUTEE POUR VERIFIER QUE LA SIZE EST BIEN UN ARRAY DE NOMBRE
+        validation = new NumberArrayValidation(validation, SimpleImageAccessProtocolLibrary.SIZE, ",", 1, 2);
+        //-----------------------------------------------------------------------------------------------
+    }  
+    StatusValidation status = validation.validate();
+    if (status.isValid()) {
+        final String pos = validation.getMap().get(SimpleImageAccessProtocolLibrary.POS);
+        final String[] arrayPos = pos.split(",");
+        this.ra = Double.valueOf(arrayPos[0]);
+        this.dec = Double.valueOf(arrayPos[1]);
+        final String size = validation.getMap().get(SimpleImageAccessProtocolLibrary.SIZE);
+        final String[] arraySize = size.split(",");
+        if(arraySize.length == 1) {
+            this.size = new double[1];
+            this.size[0] = Double.valueOf(arraySize[0]);
+        } else {
+            this.size = new double[2];
+            this.size[0] = Double.valueOf(arraySize[0]);
+            this.size[1] = Double.valueOf(arraySize[1]);
+        }
+        
+    } else {
+        Info info = new Info();
+        info.setName("QUERY_STATUS");
+        info.setValueAttribute("ERROR");
+        infos.add(info);
+        final Map<String, String> errors = status.getMessages();
+        final Set<Map.Entry<String, String>> entries = errors.entrySet();        
+        for (Map.Entry<String, String> entry : entries) {
+            info = new Info();
+            info.setID(entry.getKey());
+            info.setName("Error in " + entry.getKey());
+            info.setValueAttribute("Error in input " + entry.getKey() + ": " + entry.getValue());
+            infos.add(info);
+            LOG.log(Level.FINEST, "{0}: {1}", new Object[]{entry.getKey(), entry.getValue()});            
+        }
+        
+    }
+    
+    if (!infos.isEmpty()) {
+      this.dataModel.put("infos", infos);
+    }
+  }
+
+  @Override
+  public final Map getDataModel() {
+    return Collections.unmodifiableMap(this.dataModel);
+  }
+
+  /**
+   * Get Ra.
+   *
+   * @return Ra
+   */
+  public final double getRa() {
+    return this.ra;
+  }
+
+  /**
+   * Get Dec.
+   *
+   * @return Dec
+   */
+  public final double getDec() {
+    return this.dec;
+  }
+
+  /**
+   * Get Sr.
+   *
+   * @return Sr
+   */
+  public final double[] getSize() {
+      final double[] copySize = new double[this.size.length];
+      System.arraycopy(this.size, 0, copySize, 0, this.size.length);
+      return copySize;
+  }
+
+  /**
+   * Get the request.
+   *
+   * @return Request
+   */
+  public final Request getRequest() {
+    return this.request;
+  }
+
+  /**
+   * Get the context.
+   *
+   * @return Context
+   */
+  public final Context getContext() {
+    return this.context;
+  }
+
+  /**
+   * Get DatasetApplication.
+   *
+   * @return Dataset application
+   */
+  public final DataSetApplication getDatasetApplication() {
+    return this.datasetApp;
+  }
+
+  /**
+   * Get verb.
+   * @return verb
+   */
+  public final int getVerb() {
+    return this.verb;
+  }
+  
+  //----------------------------------------------------------------------------
+  //----------------------------------------------------------------------------
+  //----------------------------------------------------------------------------
+  /**
+   * Set Fields and columnSqlAliasList.
+   *
+   * @param fieldList List of fields to display on the VOTable
+   * @param columnList List of SQL column
+   * @param mappingList List of SQL column/concept
+   */
+  private void setFields(final List<Field> fieldList, final List<String> columnList, final List<ColumnConceptMappingDTO> mappingList) {
+
+    for (ColumnConceptMappingDTO mappingIter : mappingList) {
+
+      String id = null;
+      String name = null;
+      String ucd = null;
+      String utype = null;
+      String ref = null;
+      String datatype = null;
+      String width = null;
+      String precision = null;
+      String unit = null;
+      String type = null;
+      String xtype = null;
+      String arraysize = null;
+      String descriptionValue = null;
+      columnList.add(mappingIter.getColumnAlias());
+      final Concept concept = mappingIter.getConcept();
+      if (concept.getName() != null) {
+        name = concept.getName();
+      }
+      if (concept.getPropertyFromName("ID").getValue() != null) {
+        id = concept.getPropertyFromName("ID").getValue();
+      }
+      if (concept.getPropertyFromName("ucd").getValue() != null) {
+        ucd = concept.getPropertyFromName("ucd").getValue();
+      }
+      if (concept.getPropertyFromName("utype").getValue() != null) {
+        utype = concept.getPropertyFromName("utype").getValue();
+      }
+      if (concept.getPropertyFromName("ref").getValue() != null) {
+        ref = concept.getPropertyFromName("ref").getValue();
+      }
+      if (concept.getPropertyFromName("datatype").getValue() != null) {
+        datatype = concept.getPropertyFromName("datatype").getValue();
+      }
+      if (concept.getPropertyFromName("width").getValue() != null) {
+        width = concept.getPropertyFromName("width").getValue();
+      }
+      if (concept.getPropertyFromName("precision").getValue() != null) {
+        precision = concept.getPropertyFromName("precision").getValue();
+      }
+      if (concept.getPropertyFromName("unit").getValue() != null) {
+        unit = concept.getPropertyFromName("unit").getValue();
+      }
+      if (concept.getPropertyFromName("type").getValue() != null) {
+        type = concept.getPropertyFromName("type").getValue();
+      }
+      if (concept.getPropertyFromName("xtype").getValue() != null) {
+        xtype = concept.getPropertyFromName("xtype").getValue();
+      }
+      if (concept.getPropertyFromName("arraysize").getValue() != null) {
+        arraysize = concept.getPropertyFromName("arraysize").getValue();
+      }
+      if (concept.getDescription() != null) {
+        descriptionValue = concept.getDescription();
+      }
+      final Field field = new Field();
+      field.setID(id);
+      field.setName(name);
+      field.setUcd(ucd);
+      field.setUtype(utype);
+      field.setRef(ref);
+      field.setDatatype(DataType.fromValue(datatype));
+      if (width != null) {
+        field.setWidth(BigInteger.valueOf(Long.valueOf(width)));
+      }
+      field.setPrecision(precision);
+      field.setUnit(unit);
+      field.setType(type);
+      field.setXtype(xtype);
+      field.setArraysize(arraysize);
+      final AnyTEXT anyText = new AnyTEXT();
+      anyText.getContent().add(descriptionValue);
+      field.setDESCRIPTION(anyText);
+      fieldList.add(field);
+    }
+    dataModel.put("fields", fieldList);
+  }
+  
+  /**
+   * Provide the mapping between SQL column/concept for a given dictionary.
+   *
+   * @param datasetApp Application where this service is attached
+   * @param dicoToFind Dictionary name to find
+   * @return Returns a mapping SQL column/Concept
+   * @throws SitoolsException No mapping has been done or cannot find the dico
+   */
+  protected List<ColumnConceptMappingDTO> getDicoFromConfiguration(final DataSetApplication datasetApp,
+          final String dicoToFind) throws SitoolsException {
+    List<ColumnConceptMappingDTO> colConceptMappingDTOList = null;
+
+    // Get the list of dictionnaries related to the datasetApplication
+    final List<DictionaryMappingDTO> dicoMappingList = datasetApp.getDictionaryMappings();
+    if (!Util.isSet(dicoMappingList) || dicoMappingList.isEmpty()) {
+      throw new SitoolsException("No mapping with VO concepts has been done. please contact the administrator");
+    }
+
+    // For each dictionary, find the interesting one and return the mapping SQLcolumn/concept
+    for (DictionaryMappingDTO dicoMappingIter : dicoMappingList) {
+      final String dicoName = dicoMappingIter.getDictionaryName();
+      if (dicoToFind.equals(dicoName)) {
+        colConceptMappingDTOList = dicoMappingIter.getMapping();
+        break;
+      }
+    }
+    return colConceptMappingDTOList;
+  }
+  
+  
+  
+}
diff --git a/sitools-idoc/hesiod/javaExt/README.txt b/sitools-idoc/hesiod/javaExt/README.txt
new file mode 100644
index 0000000..1d1570d
--- /dev/null
+++ b/sitools-idoc/hesiod/javaExt/README.txt
@@ -0,0 +1 @@
+This folder contains the developments of HESIOD in Java.
diff --git a/sitools-idoc/hesiod/javaExt/src/META-INF/services/fr.cnes.sitools.converter.ConverterHelper b/sitools-idoc/hesiod/javaExt/src/META-INF/services/fr.cnes.sitools.converter.ConverterHelper
new file mode 100644
index 0000000..0fe1010
--- /dev/null
+++ b/sitools-idoc/hesiod/javaExt/src/META-INF/services/fr.cnes.sitools.converter.ConverterHelper
@@ -0,0 +1,2 @@
+fr.ias.sitools.converters.FileSizeConverter
+fr.ias.sitools.converters.RaDecToXYZConverter
\ No newline at end of file
diff --git a/sitools-idoc/hesiod/javaExt/src/META-INF/services/fr.cnes.sitools.filter.FilterHelper b/sitools-idoc/hesiod/javaExt/src/META-INF/services/fr.cnes.sitools.filter.FilterHelper
new file mode 100644
index 0000000..fcca242
--- /dev/null
+++ b/sitools-idoc/hesiod/javaExt/src/META-INF/services/fr.cnes.sitools.filter.FilterHelper
@@ -0,0 +1,10 @@
+fr.ias.sitools.filters.basic.BooleanCorotAsteroAndExo
+fr.ias.sitools.filters.basic.BooleanCustom
+fr.ias.sitools.filters.basic.GroupCheckBoxMasterLigthCurves
+fr.ias.sitools.filters.basic.NThreeVariability
+fr.ias.sitools.filters.basic.TextFieldSQLLikeFilter
+fr.ias.sitools.filters.basic.DateBeginEndFilter
+fr.ias.sitools.filters.basic.SingleValueLikeFilter
+fr.ias.sitools.filters.basic.ListBoxSpectralTypeCorot
+fr.ias.sitools.filters.basic.ListBoxLumClassCorot
+fr.ias.sitools.filters.basic.TextAreaCorotFilter
\ No newline at end of file
diff --git a/sitools-idoc/hesiod/javaExt/src/META-INF/services/fr.cnes.sitools.plugins.applications.ApplicationHelper b/sitools-idoc/hesiod/javaExt/src/META-INF/services/fr.cnes.sitools.plugins.applications.ApplicationHelper
new file mode 100644
index 0000000..e69de29
diff --git a/sitools-idoc/hesiod/javaExt/src/META-INF/services/fr.cnes.sitools.plugins.filters.FilterHelper b/sitools-idoc/hesiod/javaExt/src/META-INF/services/fr.cnes.sitools.plugins.filters.FilterHelper
new file mode 100644
index 0000000..e69de29
diff --git a/sitools-idoc/hesiod/javaExt/src/META-INF/services/fr.cnes.sitools.plugins.resources.ResourceHelper b/sitools-idoc/hesiod/javaExt/src/META-INF/services/fr.cnes.sitools.plugins.resources.ResourceHelper
new file mode 100644
index 0000000..0774e94
--- /dev/null
+++ b/sitools-idoc/hesiod/javaExt/src/META-INF/services/fr.cnes.sitools.plugins.resources.ResourceHelper
@@ -0,0 +1,5 @@
+fr.ias.sitools.resources.spectrofits.GetFitsDataSpectroModel
+fr.ias.sitools.resources.fits.ShowHeaderModel
+fr.ias.sitools.astro.resolverName.CorotIdResolverModel
+fr.ias.sitools.resources.vo.SimpleSpectralAccessResourceModel
+fr.ias.sitools.resources.geojson.DatasetToJsonModel
\ No newline at end of file
diff --git a/sitools-idoc/hesiod/javaExt/src/META-INF/services/fr.cnes.sitools.units.UnitsHelper b/sitools-idoc/hesiod/javaExt/src/META-INF/services/fr.cnes.sitools.units.UnitsHelper
new file mode 100644
index 0000000..e69de29
diff --git a/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/converters/FileSizeConverter.java b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/converters/FileSizeConverter.java
new file mode 100644
index 0000000..e032fea
--- /dev/null
+++ b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/converters/FileSizeConverter.java
@@ -0,0 +1,116 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package fr.ias.sitools.converters;
+
+import fr.cnes.sitools.common.validator.ConstraintViolation;
+import fr.cnes.sitools.common.validator.ConstraintViolationLevel;
+import fr.cnes.sitools.common.validator.Validator;
+import fr.cnes.sitools.dataset.converter.business.AbstractConverter;
+import fr.cnes.sitools.dataset.converter.model.ConverterParameter;
+import fr.cnes.sitools.dataset.converter.model.ConverterParameterType;
+import fr.cnes.sitools.datasource.jdbc.model.AttributeValue;
+import fr.cnes.sitools.datasource.jdbc.model.Record;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ *
+ * @author Marc
+ */
+public class FileSizeConverter extends AbstractConverter {
+    
+    /** Class logger */
+    private static final Logger LOGGER = Logger.getLogger(FileSizeConverter.class.getName());
+
+    public FileSizeConverter() {
+        
+        this.setName("FileSizeConverter");
+        this.setDescription("A converter applying an unit conversion from bytes into Kb or Mb or Gb");
+        this.setClassAuthor("Marc NICOLAS");
+        this.setClassOwner("IAS");
+        this.setClassVersion("0.1");
+        
+        ConverterParameter colFileSize = new ConverterParameter("colFileSizeInBytes", "row of dataset with the filesize in bytes",ConverterParameterType.CONVERTER_PARAMETER_IN);
+        ConverterParameter colFileSizeConvert = new ConverterParameter("colFileSizeConvert", "File Size converted", ConverterParameterType.CONVERTER_PARAMETER_OUT);
+        this.addParam(colFileSize);
+        this.addParam(colFileSizeConvert);
+        
+        LOGGER.log(Level.INFO, "Converter :{0} version {1}", new Object[] { this.getName(), this.getClassVersion() });
+    }   
+
+    @Override
+    public Record getConversionOf(Record record) throws Exception {
+        Record out = record;
+        String result = "";
+        
+        AttributeValue attrOut = this.getOutParam("colFileSizeConvert", out); 
+        
+        AttributeValue attrIn = this.getInParam("colFileSizeInBytes", out);
+        
+        if (!isNull(attrIn) && !isNull(attrOut)) {
+            try{
+                double input = Double.parseDouble(attrIn.getValue().toString());
+                if(input>0 && input<1024){
+                    result = (double)Math.round(input*10)/10 +" o";
+                }else if(input >= 1024 && input < Math.pow(1024, 2) ){
+                   result = (double)Math.round((input/1024)*10)/10+" Ko"; 
+                }else if(input >=Math.pow(1024, 2) && input < Math.pow(1024, 3)){
+                    result = (double)Math.round((input/Math.pow(1024, 2))*10)/10+" Mo" ;
+                }else if( input >= Math.pow(1024, 3) && input < Math.pow(1024, 4)){
+                    result = (double)Math.round((input/Math.pow(1024, 3))*10)/10+" Go" ;
+                }
+                
+                if(!result.isEmpty()){
+                    attrOut.setValue(result);
+                }
+            }catch (Exception e) {
+                attrOut.setValue(Double.NaN);
+            }
+        }
+        
+        return out;
+    }
+
+   @Override
+  public Validator<AbstractConverter> getValidator() {
+    // TODO Auto-generated method stub
+    return new Validator<AbstractConverter>() {
+
+      @Override
+      public Set<ConstraintViolation> validate(AbstractConverter item) {
+        Set<ConstraintViolation> constraints = new HashSet<ConstraintViolation>();
+        Map<String, ConverterParameter> params = item.getParametersMap();
+        ConverterParameter param = params.get("colFileSizeInBytes");
+        
+        if(param.getAttachedColumn().isEmpty()){
+          ConstraintViolation constraint = new ConstraintViolation();
+          constraint.setMessage("You must choose the column with filesize in bytes data");
+          constraint.setLevel(ConstraintViolationLevel.CRITICAL);
+          constraint.setValueName(param.getName());
+          constraints.add(constraint);
+        }
+        
+        param = params.get("colFileSizeConvert");
+        
+        if(param.getAttachedColumn().isEmpty()){
+          ConstraintViolation constraint = new ConstraintViolation();
+          constraint.setMessage("You must choose the output column");
+          constraint.setLevel(ConstraintViolationLevel.CRITICAL);
+          constraint.setValueName(param.getName());
+          constraints.add(constraint);
+        }
+        
+        return constraints;
+      }
+    };
+  }
+
+    
+}
diff --git a/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/converters/RaDecToXYZConverter.java b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/converters/RaDecToXYZConverter.java
new file mode 100644
index 0000000..6577318
--- /dev/null
+++ b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/converters/RaDecToXYZConverter.java
@@ -0,0 +1,140 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package fr.ias.sitools.converters;
+
+import fr.cnes.sitools.common.validator.ConstraintViolation;
+import fr.cnes.sitools.common.validator.ConstraintViolationLevel;
+import fr.cnes.sitools.common.validator.Validator;
+import fr.cnes.sitools.dataset.converter.business.AbstractConverter;
+import fr.cnes.sitools.dataset.converter.model.ConverterParameter;
+import fr.cnes.sitools.dataset.converter.model.ConverterParameterType;
+import fr.cnes.sitools.datasource.jdbc.model.AttributeValue;
+import fr.cnes.sitools.datasource.jdbc.model.Record;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ *
+ * @author marc
+ */
+public class RaDecToXYZConverter extends AbstractConverter {
+    
+    /*
+        Formule de changement de coordonée : 
+    
+            X=cos(DEC)*cos(RA)
+            Y=cos(DEC)*sin(RA)
+            Z=sin(DEC) 
+
+    */
+    
+    /** Class logger */
+    private static final Logger LOGGER = Logger.getLogger(RaDecToXYZConverter.class.getName());
+
+    public RaDecToXYZConverter() {
+         
+        this.setName("RaDecToXYZConverter");
+        this.setDescription("A converter applying an unit conversion from Ra and Dec into X, Y and Z coordinates");
+        this.setClassAuthor("Marc NICOLAS");
+        this.setClassOwner("IAS");
+        this.setClassVersion("0.1");
+        
+        ConverterParameter colRa = new ConverterParameter("colRa", "row of dataset with the ra coordinate",ConverterParameterType.CONVERTER_PARAMETER_IN);
+        ConverterParameter colDec = new ConverterParameter("colDec", "row of dataset with the dec coordinate",ConverterParameterType.CONVERTER_PARAMETER_IN);
+        
+        ConverterParameter colX = new ConverterParameter("colX", "Column for coordiante X", ConverterParameterType.CONVERTER_PARAMETER_OUT);
+        ConverterParameter colY = new ConverterParameter("colY", "Column for coordiante Y", ConverterParameterType.CONVERTER_PARAMETER_OUT);
+        ConverterParameter colZ = new ConverterParameter("colZ", "Column for coordiante Z", ConverterParameterType.CONVERTER_PARAMETER_OUT);
+        
+        this.addParam(colRa);
+        this.addParam(colDec);
+        this.addParam(colX);
+        this.addParam(colY);
+        this.addParam(colZ);
+        
+        LOGGER.log(Level.INFO, "Converter :{0} version {1}", new Object[] { this.getName(), this.getClassVersion() });
+    }
+    
+    
+
+    @Override
+    public Record getConversionOf(Record record) throws Exception {
+        Record out = record;
+        Double x, y, z;
+
+        AttributeValue attrOutX = this.getOutParam("colX", out); 
+        AttributeValue attrOutY = this.getOutParam("colY", out); 
+        AttributeValue attrOutZ = this.getOutParam("colZ", out); 
+        
+        AttributeValue attrInRa = this.getInParam("colRa", out);
+        AttributeValue attrInDec = this.getInParam("colDec", out);
+        
+        if(!isNull(attrInRa) && !isNull(attrInRa)/* && !isNull(attrOutX) && !isNull(attrOutY) && !isNull(attrOutZ)*/){
+            try{
+                Double ra = Double.parseDouble(attrInRa.getValue().toString());
+                Double dec = Double.parseDouble(attrInDec.getValue().toString());
+            
+                x = Math.cos(dec)*Math.cos(ra);
+                y = Math.cos(dec)*Math.sin(ra);
+                z = Math.sin(dec);
+                
+               if(!x.isNaN()){
+                   attrOutX.setValue(x);
+               }
+               if(!y.isNaN()){
+                   attrOutY.setValue(y);
+               }
+               if(!z.isNaN()){
+                   
+                   attrOutZ.setValue(z);
+               }
+            }catch(NumberFormatException e){
+                
+            }
+        }
+        
+        return out;
+    }
+
+    @Override
+    public Validator<?> getValidator() {
+        // TODO Auto-generated method stub
+    return new Validator<AbstractConverter>() {
+        
+      @Override
+      public Set<ConstraintViolation> validate(AbstractConverter item) {
+        Set<ConstraintViolation> constraints = new HashSet<ConstraintViolation>();
+        /*Map<String, ConverterParameter> params = item.getParametersMap();
+        ConverterParameter param = params.get("colFileSizeInBytes");
+        
+        if(param.getAttachedColumn().isEmpty()){
+          ConstraintViolation constraint = new ConstraintViolation();
+          constraint.setMessage("You must choose the column with filesize in bytes data");
+          constraint.setLevel(ConstraintViolationLevel.CRITICAL);
+          constraint.setValueName(param.getName());
+          constraints.add(constraint);
+        }
+        
+        param = params.get("colFileSizeConvert");
+        
+        if(param.getAttachedColumn().isEmpty()){
+          ConstraintViolation constraint = new ConstraintViolation();
+          constraint.setMessage("You must choose the output column");
+          constraint.setLevel(ConstraintViolationLevel.CRITICAL);
+          constraint.setValueName(param.getName());
+          constraints.add(constraint);
+        }*/
+        
+        return constraints;
+      }
+    };
+    }
+    
+}
diff --git a/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/filters/basic/DateBeginEndFilter.java b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/filters/basic/DateBeginEndFilter.java
new file mode 100644
index 0000000..a7fd79d
--- /dev/null
+++ b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/filters/basic/DateBeginEndFilter.java
@@ -0,0 +1,203 @@
+/*******************************************************************************
+ * Copyright 2011 CNES - CENTRE NATIONAL d'ETUDES SPATIALES
+ * 
+ * This file is part of SITools2.
+ * 
+ * SITools2 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * SITools2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with SITools2.  If not, see <http://www.gnu.org/licenses/>.
+ ******************************************************************************/
+package fr.ias.sitools.filters.basic;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Set;
+
+import org.restlet.Request;
+import org.restlet.data.Form;
+import org.restlet.ext.wadl.ParameterInfo;
+import org.restlet.ext.wadl.ParameterStyle;
+
+import fr.cnes.sitools.common.validator.ConstraintViolation;
+import fr.cnes.sitools.common.validator.Validator;
+import fr.cnes.sitools.dataset.DataSetApplication;
+import fr.cnes.sitools.dataset.filter.business.AbstractFilter;
+import fr.cnes.sitools.dataset.model.Column;
+import fr.cnes.sitools.dataset.model.DataSet;
+import fr.cnes.sitools.dataset.model.Operator;
+import fr.cnes.sitools.dataset.model.Predicat;
+import fr.cnes.sitools.util.SQLUtils;
+
+/**
+ * Filter defined for Date Between Component
+ * 
+ * 
+ * @author d.arpin
+ * <a href="https://sourceforge.net/tracker/?func=detail&atid=2158259&aid=3411383&group_id=531341">[3411383]</a><br/>
+ * 2011/09/19 d.arpin {add quotes arround date Value}
+ */
+public final class DateBeginEndFilter extends AbstractFilter {
+  /**
+   * The index of TYPE
+   */
+  private static final int TYPE = 0;
+  /**
+   * The index of COLUMN
+   */
+  private static final int COLUMN = 1;
+  /**
+   * The index of Values
+   */
+  private static final int VALUES = 2;
+
+  /** The TEMPLATE_PARAM */
+  private static final String TEMPLATE_PARAM = "p[#]";
+  /**
+   * the values from to
+   */
+  private String[] values;
+
+  /**
+   * The list of component that uses this filter
+   */
+  private enum TYPE_COMPONENT {
+    /** DefaultType */
+    DATE_BEGIN_END
+  }
+
+  /**
+   * Default constructor
+   */
+  public DateBeginEndFilter() {
+
+    super();
+    this.setName("DateBeginEndFilter");
+    this.setDescription("Required when using Date Between Components between 2 columns");
+
+    this.setClassAuthor("HUSSON@IAS");
+    this.setClassAuthor("HUSSON@IAS");
+    this.setClassOwner("IAS");
+    this.setClassVersion("0.1");
+    this.setDefaultFilter(true);
+
+    HashMap<String, ParameterInfo> rpd = new HashMap<String, ParameterInfo>();
+
+    ParameterInfo paramInfo;
+    paramInfo = new ParameterInfo("p[#]", false, "xs:string", ParameterStyle.QUERY,
+    "DATE_BEGIN_END|columnFrom,columnTo|valueFrom|valueTo");
+    rpd.put("0", paramInfo);
+    this.setRequestParamsDescription(rpd);
+    //
+
+  }
+
+  @Override
+  public List<Predicat> createPredicats(Request request, List<Predicat> predicats) throws Exception {
+    // Get the dataset
+    DataSetApplication dsApplication = null;
+    DataSet ds = null;
+
+    Form params = request.getResourceRef().getQueryAsForm();
+    boolean filterExists = true;
+    int i = 0;
+    // Build predicat for filters param
+    while (filterExists) {
+      String index = TEMPLATE_PARAM.replace("#", Integer.toString(i++));
+      String formParam = params.getFirstValue(index);
+      if (formParam != null) {
+        String[] parameters = formParam.split("\\|");
+        TYPE_COMPONENT[] types = TYPE_COMPONENT.values();
+        Boolean trouve = false;
+        for (TYPE_COMPONENT typeCmp : types) {
+          if (typeCmp.name().equals(parameters[TYPE])) {
+            trouve = true;
+          }
+        }
+        if (trouve) {
+          if (dsApplication == null) {
+            dsApplication = (DataSetApplication) getContext().getAttributes().get("DataSetApplication");
+            ds = dsApplication.getDataSet();
+          }
+          String columnfrom = null;
+          String columnto = null;
+          if (parameters.length >= VALUES) {
+            columnfrom = parameters[COLUMN].split(",")[0];
+            columnto = parameters[COLUMN].split(",")[1];
+
+            Column colfrom = ds.findByColumnAlias(columnfrom);
+            Column colto = ds.findByColumnAlias(columnto);
+
+            if (colfrom != null && colfrom.getFilter() != null && colfrom.getFilter() && checkValues(parameters) && colto != null && colto.getFilter() != null && colto.getFilter()) {
+              // escape the values to avoid SQL injection
+              String valuefrom = "'" + SQLUtils.escapeString(values[0]) + "'";
+              String valueto = "'" + SQLUtils.escapeString(values[1]) + "'";
+
+              Predicat predicat = new Predicat();
+              predicat.setLeftAttribute(colfrom);
+              predicat.setNbOpenedParanthesis(1);
+              predicat.setNbClosedParanthesis(0);
+              predicat.setCompareOperator(Operator.GTE);
+              predicat.setRightValue(valuefrom);
+              predicats.add(predicat);
+              predicat = new Predicat();
+              predicat.setLeftAttribute(colto);
+              predicat.setNbOpenedParanthesis(0);
+              predicat.setNbClosedParanthesis(1);
+              predicat.setCompareOperator(Operator.LTE);
+              predicat.setRightValue(valueto);
+              predicats.add(predicat);
+            }
+
+          }
+        }
+      }
+
+      else {
+        filterExists = false;
+      }
+    }
+
+    return predicats;
+  }
+
+  /**
+   * Check values of the form
+   * 
+   * @param parameters
+   *          the parameters of the filter
+   * @return true if values agree
+   */
+  private boolean checkValues(String[] parameters) {
+    values = Arrays.copyOfRange(parameters, VALUES, parameters.length);
+    if (values.length == 2) {
+      return true;
+    }
+    return false;
+  }
+
+  /**
+   * Gets the validator for this Filter
+   * 
+   * @return the validator for the filter
+   */
+  @Override
+  public Validator<AbstractFilter> getValidator() {
+    return new Validator<AbstractFilter>() {
+      @Override
+      public Set<ConstraintViolation> validate(AbstractFilter item) {
+        return null;
+      }
+    };
+  }
+
+}
diff --git a/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/filters/basic/ListBoxMultipleIAS.java b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/filters/basic/ListBoxMultipleIAS.java
new file mode 100644
index 0000000..81b469b
--- /dev/null
+++ b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/filters/basic/ListBoxMultipleIAS.java
@@ -0,0 +1,196 @@
+     /*******************************************************************************
+ * Copyright 2010-2013 CNES - CENTRE NATIONAL d'ETUDES SPATIALES
+ *
+ * This file is part of SITools2.
+ *
+ * SITools2 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * SITools2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with SITools2.  If not, see <http://www.gnu.org/licenses/>.
+ ******************************************************************************/
+package fr.ias.sitools.filters.basic;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Set;
+
+import org.restlet.Request;
+import org.restlet.data.Form;
+import org.restlet.ext.wadl.ParameterInfo;
+import org.restlet.ext.wadl.ParameterStyle;
+
+import fr.cnes.sitools.common.validator.ConstraintViolation;
+import fr.cnes.sitools.common.validator.Validator;
+import fr.cnes.sitools.dataset.DataSetApplication;
+import fr.cnes.sitools.dataset.filter.business.AbstractFilter;
+import fr.cnes.sitools.dataset.model.Column;
+import fr.cnes.sitools.dataset.model.DataSet;
+import fr.cnes.sitools.dataset.model.Operator;
+import fr.cnes.sitools.dataset.model.Predicat;
+import fr.cnes.sitools.dataset.plugins.filters.core.AbstractFormFilter;
+import static fr.cnes.sitools.dataset.plugins.filters.core.AbstractFormFilter.TEMPLATE_PARAM;
+import static fr.cnes.sitools.dataset.plugins.filters.core.AbstractFormFilter.TEMPLATE_PARAM_CONCEPT;
+import static fr.cnes.sitools.dataset.plugins.filters.core.AbstractFormFilter.VALUES;
+import fr.cnes.sitools.util.SQLUtils;
+
+
+/**
+ * Filter defined for Multiple Value Component
+ * 
+ * 
+ * @author d.arpin
+ */
+public final class ListBoxMultipleIAS extends AbstractFormFilter {
+
+  /**
+   * The list of component that uses this filter
+   */
+  private enum TYPE_COMPONENT {
+    /** List box type */
+    LISTBOXMULTIPLE_IAS,
+  }
+
+  /**
+   * Default constructor
+   */
+  public ListBoxMultipleIAS() {
+
+    super();
+    this.setName("ListBoxMultipleIAS");
+    this.setDescription("Required when using Multiple Value Components");
+
+    this.setClassAuthor("Marc NICOLAS");
+    this.setClassOwner("IAS");
+    this.setClassVersion("0.1");
+    this.setDefaultFilter(true);
+
+    HashMap<String, ParameterInfo> rpd = new HashMap<String, ParameterInfo>();
+
+    ParameterInfo paramInfo;
+    paramInfo = new ParameterInfo("p[#]", false, "xs:string", ParameterStyle.QUERY,
+        "LISTBOXMULTIPLE|columnAlias|value1|...|value n");
+    rpd.put("0", paramInfo);
+    paramInfo = new ParameterInfo("p[#]", false, "xs:string", ParameterStyle.QUERY,
+        "CHECKBOX|columnAlias|value1|...|value n");
+    rpd.put("1", paramInfo);
+
+    paramInfo = new ParameterInfo("c[#]", false, "xs:string", ParameterStyle.QUERY,
+        "LISTBOXMULTIPLE|dictionaryName,conceptName|value1|...|value n");
+    rpd.put("2", paramInfo);
+    /*paramInfo = new ParameterInfo("c[#]", false, "xs:string", ParameterStyle.QUERY,
+        "CHECKBOX|dictionaryName,conceptName|value1|...|value n");
+    rpd.put("3", paramInfo);
+    this.setRequestParamsDescription(rpd);*/
+    //
+
+  }
+
+  @Override
+  public List<Predicat> createPredicats(Request request, List<Predicat> predicats) throws Exception {
+    // Get the dataset
+    DataSetApplication dsApplication = null;
+    DataSet ds = null;
+    boolean isConcept = true;
+    Form params = request.getResourceRef().getQueryAsForm();
+    boolean filterExists = true;
+    int i = 0;
+    // Build predicat for filters param
+    while (filterExists) {
+      // first check if the filter is applied on a Concept or not
+      String index = TEMPLATE_PARAM_CONCEPT.replace("#", Integer.toString(i));
+      String formParam = params.getFirstValue(index);
+      if (formParam == null) {
+        isConcept = false;
+        index = TEMPLATE_PARAM.replace("#", Integer.toString(i));
+        formParam = params.getFirstValue(index);
+      }
+      i++;
+      if (formParam != null) {
+        String[] parameters = formParam.split("\\|");
+        TYPE_COMPONENT[] types = TYPE_COMPONENT.values();
+        Boolean trouve = false;
+        for (TYPE_COMPONENT typeCmp : types) {
+          if (typeCmp.name().equals(parameters[TYPE])) {
+            trouve = true;
+          }
+        }
+        if (trouve) {
+          if (dsApplication == null) {
+            dsApplication = (DataSetApplication) getContext().getAttributes().get("DataSetApplication");
+            ds = dsApplication.getDataSet();
+          }
+          String columnAlias = null;
+          if (parameters.length >= VALUES) {
+
+            /*
+             * columnsAlias = parameters[COLUMN].split(","); ArrayList<Column> columns = new ArrayList<Column>(); for
+             * (String columnAlias : columnsAlias) { Column col = ds.findByColumnAlias(columnAlias); if (col != null) {
+             * columns.add(col); }
+             * 
+             * }
+             */
+            columnAlias = getColumnAlias(isConcept, parameters, dsApplication);
+            if (columnAlias != null) {
+              Column col = ds.findByColumnAlias(columnAlias);
+
+              if (col != null && col.getFilter() != null && col.getFilter()) {
+                String[] values = Arrays.copyOfRange(parameters, VALUES, parameters.length);
+                Predicat predicat = new Predicat();
+                if (values != null) {
+                  predicat.setLeftAttribute(col);
+                  predicat.setNbOpenedParanthesis(0);
+                  predicat.setNbClosedParanthesis(0);
+                  predicat.setCompareOperator(Operator.IN);
+
+                  List<String> in = new ArrayList<String>();
+
+                  for (String value : values) {
+                    // escape every value to avoid SQL injections
+                    in.add(SQLUtils.escapeString(value));
+                  }
+                  predicat.setRightValue(in);
+
+                  predicats.add(predicat);
+                }
+              }
+            }
+
+          }
+        }
+      }
+
+      else {
+        filterExists = false;
+      }
+    }
+
+    return predicats;
+  }
+
+  /**
+   * Gets the validator for this Filter
+   * 
+   * @return the validator for the filter
+   */
+  @Override
+  public Validator<AbstractFilter> getValidator() {
+    return new Validator<AbstractFilter>() {
+      @Override
+      public Set<ConstraintViolation> validate(AbstractFilter item) {
+        // TODO Auto-generated method stub
+        return null;
+      }
+    };
+  }
+
+}
diff --git a/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/filters/basic/ListBoxSpectralTypeCorot.java b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/filters/basic/ListBoxSpectralTypeCorot.java
new file mode 100644
index 0000000..ad0b9e5
--- /dev/null
+++ b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/filters/basic/ListBoxSpectralTypeCorot.java
@@ -0,0 +1,207 @@
+     /*******************************************************************************
+ * Copyright 2010-2013 CNES - CENTRE NATIONAL d'ETUDES SPATIALES
+ *
+ * This file is part of SITools2.
+ *
+ * SITools2 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * SITools2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with SITools2.  If not, see <http://www.gnu.org/licenses/>.
+ ******************************************************************************/
+package fr.ias.sitools.filters.basic;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Set;
+
+import org.restlet.Request;
+import org.restlet.data.Form;
+import org.restlet.ext.wadl.ParameterInfo;
+import org.restlet.ext.wadl.ParameterStyle;
+
+import fr.cnes.sitools.common.validator.ConstraintViolation;
+import fr.cnes.sitools.common.validator.Validator;
+import fr.cnes.sitools.dataset.DataSetApplication;
+import fr.cnes.sitools.dataset.filter.business.AbstractFilter;
+import fr.cnes.sitools.dataset.model.Column;
+import fr.cnes.sitools.dataset.model.DataSet;
+import fr.cnes.sitools.dataset.model.Operator;
+import fr.cnes.sitools.dataset.model.Predicat;
+import fr.cnes.sitools.dataset.plugins.filters.core.AbstractFormFilter;
+import static fr.cnes.sitools.dataset.plugins.filters.core.AbstractFormFilter.TEMPLATE_PARAM;
+import static fr.cnes.sitools.dataset.plugins.filters.core.AbstractFormFilter.TEMPLATE_PARAM_CONCEPT;
+import static fr.cnes.sitools.dataset.plugins.filters.core.AbstractFormFilter.VALUES;
+
+/**
+ * Filter defined for Multiple Value Component
+ * 
+ * 
+ * @author d.arpin
+ */
+public final class ListBoxSpectralTypeCorot extends AbstractFormFilter {
+
+  /**
+   * The list of component that uses this filter
+   */
+  private enum TYPE_COMPONENT {
+    /** List box Spectral Type for Corot */
+    LISTBOXSPECTRALTYPECOROT
+  }
+  
+  private final List<String> spectralTypeO = Arrays.asList("O5","O6","O8","O8.5","O9");
+  private final List<String> spectralTypeB = Arrays.asList("B0","B1","B2","B3","B5","B6","B8","B9","B2.5","B.5");
+  private final List<String> spectralTypeA = Arrays.asList("A0","A1","A2","A3","A4","A5","A6","A7","A8","A9");
+  private final List<String> spectralTypeF = Arrays.asList("F0","F1","F2","F3","F4","F5","F6","F7","F8","F9");
+  private final List<String> spectralTypeG = Arrays.asList("G0","G1","G2","G3","G4","G5","G6","G7","G8","G9");
+  private final List<String> spectralTypeK = Arrays.asList("K0","K1","K2","K3","K4","K5","K6","K7","K8","K9");
+  private final List<String> spectralTypeM = Arrays.asList("M","M0","M1","M2","M3","M4","M5","M6","M7","M8","M9");
+  
+  /**
+   * Default constructor
+   */
+  public ListBoxSpectralTypeCorot() {
+
+    super();
+    this.setName("ListBoxSpectralTypeCorot");
+    this.setDescription("Required when using List Box Spectral Type for Corot Components");
+
+    this.setClassAuthor("Mnicolas");
+    this.setClassOwner("IAS");
+    this.setClassVersion("0.1");
+    this.setDefaultFilter(true);
+
+    HashMap<String, ParameterInfo> rpd = new HashMap<String, ParameterInfo>();
+
+    ParameterInfo paramInfo;
+    paramInfo = new ParameterInfo("p[#]", false, "xs:string", ParameterStyle.QUERY,
+        "LISTBOXSPECTRALTYPECOROT|columnAlias|value1|...|value n");
+    rpd.put("0", paramInfo);
+    this.setRequestParamsDescription(rpd);
+
+  }
+
+  @Override
+  public List<Predicat> createPredicats(Request request, List<Predicat> predicats) throws Exception {
+    // Get the dataset
+    DataSetApplication dsApplication = null;
+    DataSet ds = null;
+    boolean isConcept = true;
+    Form params = request.getResourceRef().getQueryAsForm();
+    boolean filterExists = true;
+    int i = 0;
+    // Build predicat for filters param
+    while (filterExists) {
+      // first check if the filter is applied on a Concept or not
+      String index = TEMPLATE_PARAM_CONCEPT.replace("#", Integer.toString(i));
+      String formParam = params.getFirstValue(index);
+      if (formParam == null) {
+        isConcept = false;
+        index = TEMPLATE_PARAM.replace("#", Integer.toString(i));
+        formParam = params.getFirstValue(index);
+      }
+      i++;
+      if (formParam != null) {
+        String[] parameters = formParam.split("\\|");
+        TYPE_COMPONENT[] types = TYPE_COMPONENT.values();
+        Boolean trouve = false;
+        for (TYPE_COMPONENT typeCmp : types) {
+          if (typeCmp.name().equals(parameters[TYPE])) {
+            trouve = true;
+          }
+        }
+        if (trouve) {
+          if (dsApplication == null) {
+            dsApplication = (DataSetApplication) getContext().getAttributes().get("DataSetApplication");
+            ds = dsApplication.getDataSet();
+          }
+          String columnAlias = null;
+          if (parameters.length >= VALUES) {
+
+            /*
+             * columnsAlias = parameters[COLUMN].split(","); ArrayList<Column> columns = new ArrayList<Column>(); for
+             * (String columnAlias : columnsAlias) { Column col = ds.findByColumnAlias(columnAlias); if (col != null) {
+             * columns.add(col); }
+             * 
+             * }
+             */
+            columnAlias = getColumnAlias(isConcept, parameters, dsApplication);
+            if (columnAlias != null) {
+              Column col = ds.findByColumnAlias(columnAlias);
+
+              if (col != null && col.getFilter() != null && col.getFilter()) {
+                String[] values = Arrays.copyOfRange(parameters, VALUES, parameters.length);
+                Predicat predicat = new Predicat();
+                if (values != null) {
+                  predicat.setLeftAttribute(col);
+                  predicat.setNbOpenedParanthesis(0);
+                  predicat.setNbClosedParanthesis(0);
+                  predicat.setCompareOperator(Operator.IN);
+
+                  boolean all = false;
+                  List<String> spectralTypeSeeked = new ArrayList<String>();
+                  for (String value : values) {
+                      if(value.equalsIgnoreCase("O")){
+                          spectralTypeSeeked.addAll(this.spectralTypeO);
+                      }else if(value.equalsIgnoreCase("B")){
+                          spectralTypeSeeked.addAll(this.spectralTypeB);
+                      }else if(value.equalsIgnoreCase("A")){
+                          spectralTypeSeeked.addAll(this.spectralTypeA);
+                      }else if(value.equalsIgnoreCase("F")){
+                          spectralTypeSeeked.addAll(this.spectralTypeF);
+                      }else if(value.equalsIgnoreCase("G")){
+                          spectralTypeSeeked.addAll(this.spectralTypeG);
+                      }else if(value.equalsIgnoreCase("K")){
+                          spectralTypeSeeked.addAll(this.spectralTypeK);
+                      }else if(value.equalsIgnoreCase("M")){
+                          spectralTypeSeeked.addAll(this.spectralTypeM);
+                      }else if(value.equalsIgnoreCase("All")){
+                          all = true;
+                      }
+                      
+                    //in.add(SQLUtils.escapeString(value));
+                  }
+                  if(!spectralTypeSeeked.isEmpty()&& !all) {
+                    predicat.setRightValue(spectralTypeSeeked);
+                    predicats.add(predicat);
+                  }
+                }
+              }
+            }
+
+          }
+        }
+      }else {
+        filterExists = false;
+      }
+    }
+
+    return predicats;
+  }
+
+  /**
+   * Gets the validator for this Filter
+   * 
+   * @return the validator for the filter
+   */
+  @Override
+  public Validator<AbstractFilter> getValidator() {
+    return new Validator<AbstractFilter>() {
+      @Override
+      public Set<ConstraintViolation> validate(AbstractFilter item) {
+        // TODO Auto-generated method stub
+        return null;
+      }
+    };
+  }
+
+}
diff --git a/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/filters/basic/SingleValueLikeFilter.java b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/filters/basic/SingleValueLikeFilter.java
new file mode 100644
index 0000000..00ec973
--- /dev/null
+++ b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/filters/basic/SingleValueLikeFilter.java
@@ -0,0 +1,183 @@
+     /*******************************************************************************
+ * Copyright 2010-2013 CNES - CENTRE NATIONAL d'ETUDES SPATIALES
+ *
+ * This file is part of SITools2.
+ *
+ * SITools2 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * SITools2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with SITools2.  If not, see <http://www.gnu.org/licenses/>.
+ ******************************************************************************/
+package fr.ias.sitools.filters.basic;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Set;
+
+import org.restlet.Request;
+import org.restlet.data.Form;
+import org.restlet.ext.wadl.ParameterInfo;
+import org.restlet.ext.wadl.ParameterStyle;
+
+import fr.cnes.sitools.common.validator.ConstraintViolation;
+import fr.cnes.sitools.common.validator.Validator;
+import fr.cnes.sitools.dataset.DataSetApplication;
+import fr.cnes.sitools.dataset.filter.business.AbstractFilter;
+import fr.cnes.sitools.dataset.model.Column;
+import fr.cnes.sitools.dataset.model.DataSet;
+import fr.cnes.sitools.dataset.model.Operator;
+import fr.cnes.sitools.dataset.model.Predicat;
+import fr.cnes.sitools.dataset.plugins.filters.core.AbstractFormFilter;
+import static fr.cnes.sitools.dataset.plugins.filters.core.AbstractFormFilter.TEMPLATE_PARAM;
+import static fr.cnes.sitools.dataset.plugins.filters.core.AbstractFormFilter.TEMPLATE_PARAM_CONCEPT;
+import static fr.cnes.sitools.dataset.plugins.filters.core.AbstractFormFilter.VALUES;
+import fr.cnes.sitools.util.SQLUtils;
+
+/**
+ * Filter defined for Single Value Component
+ * 
+ * 
+ * @author d.arpin
+ */
+public final class SingleValueLikeFilter extends AbstractFormFilter {
+
+  /**
+   * The list of component that uses this filter
+   */
+  private enum TYPE_COMPONENT {
+    /** Hd Number field type */
+    HDNUMBERFIELD,
+  }
+
+  /**
+   * Default constructor
+   */
+  public SingleValueLikeFilter() {
+
+    super();
+    this.setName("SingleValueLikeFilter");
+    this.setDescription("Required when using Hd Number Text Field Component");
+
+    this.setClassAuthor("MNICOLAS");
+    this.setClassOwner("IAS");
+    this.setClassVersion("0.1");
+    this.setDefaultFilter(true);
+
+    HashMap<String, ParameterInfo> rpd = new HashMap<String, ParameterInfo>();
+
+    ParameterInfo paramInfo;
+    paramInfo = new ParameterInfo("p[#]", false, "xs:string", ParameterStyle.QUERY, "HDNUMBERFIELD|columnAlias|value");
+    rpd.put("0", paramInfo);
+    paramInfo = new ParameterInfo("c[#]", false, "xs:string", ParameterStyle.QUERY,
+        "HDNUMBERFIELD|dictionaryName,conceptName|value");
+    rpd.put("1", paramInfo);
+
+    this.setRequestParamsDescription(rpd);
+    //
+
+  }
+
+  @Override
+  public List<Predicat> createPredicats(Request request, List<Predicat> predicats) throws Exception {
+    DataSetApplication dsApplication = null;
+    DataSet ds = null;
+    boolean isConcept = true;
+    Form params = request.getResourceRef().getQueryAsForm();
+    boolean filterExists = true;
+    int i = 0;
+    // Build predicat for filters param
+    while (filterExists) {
+      // first check if the filter is applied on a Concept or not
+      String index = TEMPLATE_PARAM_CONCEPT.replace("#", Integer.toString(i));
+      String formParam = params.getFirstValue(index);
+      if (formParam == null) {
+        isConcept = false;
+        index = TEMPLATE_PARAM.replace("#", Integer.toString(i));
+        formParam = params.getFirstValue(index);
+      }
+      i++;
+      if (formParam != null) {
+        String[] parameters = formParam.split("\\|");
+        TYPE_COMPONENT[] types = TYPE_COMPONENT.values();
+        Boolean trouve = false;
+        for (TYPE_COMPONENT typeCmp : types) {
+          if (typeCmp.name().equals(parameters[TYPE])) {
+            trouve = true;
+          }
+        }
+        if (trouve) {
+          if (dsApplication == null) {
+            dsApplication = (DataSetApplication) getContext().getAttributes().get("DataSetApplication");
+            ds = dsApplication.getDataSet();
+          }
+          String columnAlias = null;
+          if (parameters.length >= VALUES) {
+
+            columnAlias = getColumnAlias(isConcept, parameters, dsApplication);
+            if (columnAlias != null) {
+              Column col = ds.findByColumnAlias(columnAlias);
+              if (col != null && col.getFilter() != null && col.getFilter()) {
+                // get the value and escape it to avoid SQL injection
+                String value = SQLUtils.escapeString(parameters[VALUES]);
+                Predicat predicat = new Predicat();
+                if (value != null) {
+                  predicat.setLeftAttribute(col);
+                  predicat.setNbOpenedParanthesis(0);
+                  predicat.setNbClosedParanthesis(0);
+                  if (parameters[TYPE].equals(TYPE_COMPONENT.HDNUMBERFIELD.name())) {
+                      if(value.contains("HD")){
+                          if(value.charAt(2) != ' '){
+                              value = value.substring(2);
+                              value = "%"+value+"%";
+                          }
+                          
+                      }else{
+                        value = "%"+value+"%";
+                      }
+                    predicat.setCompareOperator(Operator.LIKE);
+                  }else {
+                    predicat.setCompareOperator(Operator.EQ);
+                  }
+                  predicat.setRightValue("'" + value + "'");
+
+                  predicats.add(predicat);
+                }
+              }
+            }
+          }
+        }
+      }
+
+      else {
+        filterExists = false;
+      }
+    }
+
+    return predicats;
+  }
+
+  /**
+   * Gets the validator for this Filter
+   * 
+   * @return the validator for the filter
+   */
+  @Override
+  public Validator<AbstractFilter> getValidator() {
+    return new Validator<AbstractFilter>() {
+      @Override
+      public Set<ConstraintViolation> validate(AbstractFilter item) {
+        // TODO Auto-generated method stub
+        return null;
+      }
+    };
+  }
+
+}
diff --git a/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/filters/basic/TextFieldSQLLikeFilter.java b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/filters/basic/TextFieldSQLLikeFilter.java
new file mode 100644
index 0000000..9ea6871
--- /dev/null
+++ b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/filters/basic/TextFieldSQLLikeFilter.java
@@ -0,0 +1,128 @@
+package fr.ias.sitools.filters.basic;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.logging.Level;
+
+import org.restlet.Request;
+import org.restlet.data.Form;
+import org.restlet.ext.wadl.ParameterInfo;
+import org.restlet.ext.wadl.ParameterStyle;
+
+import fr.cnes.sitools.common.validator.Validator;
+import fr.cnes.sitools.dataset.DataSetApplication;
+import fr.cnes.sitools.dataset.filter.business.AbstractFilter;
+import fr.cnes.sitools.dataset.model.Column;
+import fr.cnes.sitools.dataset.model.DataSet;
+import fr.cnes.sitools.dataset.model.Operator;
+import fr.cnes.sitools.dataset.model.Predicat;
+import fr.cnes.sitools.util.SQLUtils;
+import fr.cnes.sitools.dataset.plugins.filters.core.AbstractFormFilter;
+
+public class TextFieldSQLLikeFilter extends AbstractFormFilter {
+
+  /**
+   * The list of component that uses this filter
+   */
+  private enum TYPE_COMPONENT {
+    /** DefaultType */
+    TEXTFIELDSQLLIKEINSENSITIVE
+  } 
+
+  public TextFieldSQLLikeFilter() {
+    super();
+    this.setName("TextFieldSQLLikeFilter");
+    this.setDescription("Required when using TextField with a sql like request");
+    this.setClassAuthor("MNICOLAS");
+    this.setClassOwner("IAS");
+    this.setClassVersion("0.1");
+    this.setDefaultFilter(true);
+    
+    HashMap<String, ParameterInfo> rpd = new HashMap<String, ParameterInfo>();
+
+     ParameterInfo param1 = new ParameterInfo("p[#]", false, "xs:string", ParameterStyle.QUERY, "TEXTFIELDSQLLIKEINSENSITIVE|columnAlias|value");
+     rpd.put("0", param1);
+     
+     param1 = new ParameterInfo("c[#]", false, "xs:string", ParameterStyle.QUERY,
+     "TEXTFIELDSQLLIKEINSENSITIVE|dictionaryName,conceptName|value");
+     rpd.put("2", param1);
+  
+     this.setRequestParamsDescription(rpd);
+  }
+
+  @Override
+  public List<Predicat> createPredicats(Request request, List<Predicat> predicats) throws Exception {
+    DataSetApplication dsApplication = null;
+    getContext().getLogger().log(Level.CONFIG,"*********************** Je rentre dans le createPredicats du TEXTFIELDSQLLIKEINSENSITIVE");
+    DataSet ds = null;
+    boolean isConcept = true;
+    Form params = request.getResourceRef().getQueryAsForm();
+    boolean filterExists = true;
+    int i = 0;
+    
+    while (filterExists) {
+      // first check if the filter is applied on a Concept or not
+      String index = TEMPLATE_PARAM_CONCEPT.replace("#", Integer.toString(i));
+      String formParam = params.getFirstValue(index);
+      if (formParam == null) {
+        isConcept = false;
+        index = TEMPLATE_PARAM.replace("#", Integer.toString(i));
+        formParam = params.getFirstValue(index);
+      }
+      i++;
+      if (formParam != null) {
+        String[] parameters = formParam.split("\\|");
+        TYPE_COMPONENT[] types = TYPE_COMPONENT.values();
+        Boolean trouve = false;
+        for (TYPE_COMPONENT typeCmp : types) {
+          if (typeCmp.name().equals(parameters[TYPE])) {
+            trouve = true;
+          }
+        }
+        if (trouve) {
+          if (dsApplication == null) {
+            dsApplication = (DataSetApplication) getContext().getAttributes().get("DataSetApplication");
+            ds = dsApplication.getDataSet();
+          }
+          String columnAlias = null;
+          if (parameters.length >= VALUES) {
+
+           columnAlias = getColumnAlias(isConcept, parameters, dsApplication);
+            if (columnAlias != null) {
+              Column col = ds.findByColumnAlias(columnAlias);
+              if (col != null && col.getFilter() != null && col.getFilter()) {
+                // get the value and escape it to avoid SQL injection
+                String value = SQLUtils.escapeString(parameters[VALUES]);
+                
+                Predicat predicat = new Predicat();
+                if (value != null) {
+                  predicat.setLeftString("UPPER("+col.getColumnAlias()+")");
+                  predicat.setNbOpenedParanthesis(0);
+                  predicat.setNbClosedParanthesis(0);
+                  value = value.replace("*", "%");
+                  
+                  predicat.setCompareOperator(Operator.LIKE);
+                  predicat.setRightValue("'" + value.toUpperCase() + "'");
+
+                  predicats.add(predicat);
+                }
+              }
+            }
+          }
+        }
+      }
+
+      else {
+        filterExists = false;
+      }
+    }
+    
+    return predicats;
+  }
+
+  @Override
+  public Validator<AbstractFilter> getValidator() {
+    // TODO Auto-generated method stub
+    return null;
+  }
+}
diff --git a/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/resources/fits/ShowHeader.java b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/resources/fits/ShowHeader.java
new file mode 100644
index 0000000..39795b1
--- /dev/null
+++ b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/resources/fits/ShowHeader.java
@@ -0,0 +1,240 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package fr.ias.sitools.resources.fits;
+
+import fr.cnes.sitools.common.exception.SitoolsException;
+import fr.cnes.sitools.common.resource.SitoolsParameterizedResource;
+import fr.cnes.sitools.dataset.DataSetApplication;
+import fr.cnes.sitools.dataset.database.DatabaseRequest;
+import fr.cnes.sitools.dataset.database.DatabaseRequestFactory;
+import fr.cnes.sitools.dataset.database.DatabaseRequestParameters;
+import fr.cnes.sitools.dataset.database.common.DataSetExplorerUtil;
+import fr.cnes.sitools.datasource.jdbc.model.AttributeValue;
+import fr.cnes.sitools.datasource.jdbc.model.Record;
+import fr.cnes.sitools.plugins.resources.model.ResourceParameter;
+import fr.cnes.sitools.resources.order.utils.OrderResourceUtils;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import nom.tam.fits.Fits;
+import nom.tam.fits.FitsException;
+import nom.tam.fits.FitsFactory;
+import nom.tam.fits.Header;
+import nom.tam.fits.HeaderCard;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.restlet.data.MediaType;
+import org.restlet.ext.json.JsonRepresentation;
+import org.restlet.ext.wadl.MethodInfo;
+import org.restlet.representation.Representation;
+import org.restlet.representation.Variant;
+import org.restlet.resource.Get;
+
+/**
+ *
+ * @author mnicolas
+ */
+public class ShowHeader extends SitoolsParameterizedResource {
+    
+    @Override
+    public void sitoolsDescribe() {
+        setName("GetFitsDataSpectro");
+        setDescription("Get cube fits file data");
+    }
+
+    @Override
+    public void doInit() {
+        super.doInit();
+    }
+
+    /**
+    * Get HTML
+    * 
+    * @return Representation the HTML result
+    */
+    @Get
+    public Representation get() {
+        return execute();
+    }
+
+    @Override
+    protected void describeGet(MethodInfo info) {
+        this.addInfo(info);
+        info.setIdentifier("retrieve records and extract data and metadata from fits file");
+        info.setDocumentation("Method to get the data and metadata from a fits file");
+        addStandardGetRequestInfo(info);
+        DataSetExplorerUtil.addDatasetExplorerGetRequestInfo(info);
+        DataSetApplication application = (DataSetApplication) getApplication();
+        DataSetExplorerUtil.addDatasetExplorerGetFilterInfo(info, application.getFilterChained());
+        addStandardResponseInfo(info);
+        addStandardInternalServerErrorInfo(info);
+    }
+
+    @Override
+    protected Representation head(Variant variant) {
+        Representation repr = super.head();
+        repr.setMediaType(MediaType.APPLICATION_JSON);
+        return repr;
+    }
+
+    private Representation execute() {
+        Representation repr = null;
+    
+        // generate the DatabaseRequest
+        DataSetApplication datasetApp = (DataSetApplication) getApplication();
+        DataSetExplorerUtil dsExplorerUtil = new DataSetExplorerUtil(datasetApp, getRequest(), getContext());
+
+        // Get request parameters
+        if (datasetApp.getConverterChained() != null) {
+        datasetApp.getConverterChained().getContext().getAttributes().put("REQUEST", getRequest());
+        }
+        // Get DatabaseRequestParameters
+        DatabaseRequestParameters params = dsExplorerUtil.getDatabaseParams();
+
+        DatabaseRequest databaseRequest = DatabaseRequestFactory.getDatabaseRequest(params);
+    
+        if (params.getDistinct()) {
+            try {
+                databaseRequest.createDistinctRequest();
+            }catch (SitoolsException e) {
+                e.printStackTrace();
+            }
+        } else {
+            try {
+                databaseRequest.createRequest();
+            }catch (SitoolsException e) {
+                e.printStackTrace();
+            }
+        }
+    
+        ResourceParameter urlName = this.getModel().getParameterByName("colUrl");
+    
+        if (databaseRequest != null) {
+
+        // Next for reading first record
+        try {
+            databaseRequest.nextResult();
+            Record rec = databaseRequest.getRecord();
+        
+            AttributeValue attributeValueURL = OrderResourceUtils.getInParam(urlName, rec);
+        
+            if (attributeValueURL.getValue() != null){
+                // get the file path
+                String filePath = (String) attributeValueURL.getValue();
+                Fits fits = new Fits(filePath);
+                FitsFactory.setUseHierarch(true);
+                Header.setLongStringsEnabled(true);
+              
+                JSONObject jSON = new JSONObject();
+              
+                int waveHDU = -1;
+              
+                int nberHDUs = fits.size();
+                System.out.println("Number of HDUs: "+nberHDUs);
+                jSON.put("HDUs", nberHDUs);
+              
+                // Headers from fits
+                System.out.println("Getting Headers...");
+                List<String> headers = new ArrayList<String>(nberHDUs);
+                List<List<List<String>>> headersList = new ArrayList<List<List<String>>>(nberHDUs);
+              
+                for (int i=0;i<nberHDUs;i++){
+                
+                    Header header = fits.getHDU(i).getHeader();
+
+                    int nbreCards = header.getNumberOfCards();
+                    String headerStr = "";
+                
+                    //making HIERARCH mapping
+                    HashMap<String,String> mapHierarch = new HashMap<String,String>();                
+                    for (int j=0; j<nbreCards; j++){
+                        String cardStr = header.getCard(j);
+                        if (cardStr.matches("HIERARCH\\s.*\\s(META.*)\\s*=\\s*(.*)")) {
+                            //System.out.println(cardStr);
+                            Pattern p = Pattern.compile("HIERARCH\\s.*\\s(META.*)\\s*=\\s*(.*)");
+                            Matcher m = p.matcher(cardStr);
+                            if (m.find()) {
+                                //System.out.println(m.group(1)+" "+m.group(2));
+                                mapHierarch.put(m.group(1), m.group(2));
+                            }
+                        }
+                        headerStr = headerStr+cardStr+"<br>";
+                    }
+                
+                    //List of extensions -- List of List of Cards
+                    List<List<String>> cardList = new ArrayList<List<String>>(nbreCards);
+                    for (int j=0; j<nbreCards; j++){
+                  
+                        List<String> keyValueComment = new ArrayList<String>(nbreCards); 
+                        HeaderCard card = header.findCard(header.getKey(j));
+                  
+                        if ( card!=null ) {
+                            //key
+                            if (mapHierarch.containsKey(card.getKey())) { 
+                                keyValueComment.add( "HIERARCH "+mapHierarch.get(card.getKey()) );
+                            }else {
+                                keyValueComment.add(card.getKey());
+                            }
+                    
+                            //value
+                            keyValueComment.add(card.getValue());
+                    
+                            if ( card.getKey().contains("EXTNAME") && card.getValue().contains("ImageIndex") ) { 
+                                System.out.println("ImageIndex in HDU "+i);
+                                waveHDU=i;
+                            }
+                    
+                            //comment
+                            String commentCard = card.getComment();
+                            if (commentCard!=null) {
+
+                                if (commentCard.contains("&")) {
+                                    //System.out.println(j+" "+commentCard);
+                                    commentCard = commentCard.substring(0, commentCard.length()-1);
+                                    int jTmp = j;
+                                    while(header.getCard(jTmp+1).startsWith("COMMENT")){
+                                        String commentCardNext = header.getCard(jTmp+1);
+                                        if (commentCardNext.contains("&")) { commentCardNext = commentCardNext.substring(0, commentCardNext.length()-1); }
+                                        commentCard += commentCardNext.split("COMMENT ")[1];
+                                        jTmp++;
+                                    } 
+                                    keyValueComment.add(commentCard);
+                                }else {
+                                    keyValueComment.add(commentCard); 
+                                }
+                            } else {
+                                keyValueComment.add("");
+                            }
+                            cardList.add(keyValueComment);
+                        } 
+                    }
+                    headersList.add(cardList);
+                    headers.add(headerStr);
+                }
+                jSON.put("HEADERSGRID", headersList);
+                getContext().getLogger().log(Level.INFO,"In Show Header Resources : Headers - Done !");
+                repr = new JsonRepresentation(jSON);
+            }
+        } catch (FitsException ex) {
+            Logger.getLogger(ShowHeader.class.getName()).log(Level.SEVERE, null, ex);
+        } catch (JSONException ex) {
+            Logger.getLogger(ShowHeader.class.getName()).log(Level.SEVERE, null, ex);
+        }catch (SitoolsException ex) {
+            Logger.getLogger(ShowHeader.class.getName()).log(Level.SEVERE, null, ex);
+        } catch (IOException ex) {
+            Logger.getLogger(ShowHeader.class.getName()).log(Level.SEVERE, null, ex);
+        }
+    }
+    return repr;
+    }
+    
+}       
diff --git a/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/resources/fits/ShowHeaderModel.java b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/resources/fits/ShowHeaderModel.java
new file mode 100644
index 0000000..d7fb44d
--- /dev/null
+++ b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/resources/fits/ShowHeaderModel.java
@@ -0,0 +1,61 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package fr.ias.sitools.resources.fits;
+
+import fr.cnes.sitools.common.validator.ConstraintViolation;
+import fr.cnes.sitools.common.validator.Validator;
+import fr.cnes.sitools.dataset.DataSetApplication;
+import fr.cnes.sitools.plugins.resources.model.DataSetSelectionType;
+import fr.cnes.sitools.plugins.resources.model.ResourceModel;
+import fr.cnes.sitools.plugins.resources.model.ResourceParameter;
+import fr.cnes.sitools.plugins.resources.model.ResourceParameterType;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ *
+ * @author mnicolas
+ */
+public class ShowHeaderModel extends ResourceModel {
+    
+    public ShowHeaderModel(){
+        super();
+        setClassAuthor("Marc NICOLAS");
+        setClassOwner("IAS");
+        setClassVersion("0.1");
+        setName("ShowHeaderModel");
+        setDescription("Getting metadata from a fits file");
+        setClassName("fr.ias.sitools.resources.spectrofits.ShowHeaderModel");
+        setResourceClassName(fr.ias.sitools.resources.fits.ShowHeader.class.getName());
+        
+        ResourceParameter paramColUrl = new ResourceParameter("colUrl", "Colum containing the url of the fits file.",
+        ResourceParameterType.PARAMETER_INTERN);
+        paramColUrl.setValueType("xs:dataset.columnAlias");
+        this.addParam(paramColUrl);
+        
+        this.setApplicationClassName(DataSetApplication.class.getName());
+        this.setDataSetSelection(DataSetSelectionType.SINGLE);
+        this.getParameterByName("methods").setValue("GET");
+        this.completeAttachUrlWith("/getHeaderFits");
+    }
+    
+    @Override
+  public Validator<ResourceModel> getValidator() {
+      return new Validator<ResourceModel>() {
+    
+      @Override
+      public Set<ConstraintViolation> validate(ResourceModel item) {
+        Set<ConstraintViolation> constraints = new HashSet<ConstraintViolation>();
+        Map<String, ResourceParameter> params = item.getParametersMap();
+        
+        return constraints;
+      }
+    };
+  }
+    
+}
diff --git a/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/resources/geojson/DatasetToJson.java b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/resources/geojson/DatasetToJson.java
new file mode 100644
index 0000000..8f06dca
--- /dev/null
+++ b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/resources/geojson/DatasetToJson.java
@@ -0,0 +1,363 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package fr.ias.sitools.resources.geojson;
+
+import fr.cnes.sitools.common.exception.SitoolsException;
+import fr.cnes.sitools.common.resource.SitoolsParameterizedResource;
+import fr.cnes.sitools.dataset.DataSetApplication;
+import fr.cnes.sitools.dataset.database.DatabaseRequest;
+import fr.cnes.sitools.dataset.database.DatabaseRequestFactory;
+import fr.cnes.sitools.dataset.database.DatabaseRequestParameters;
+import fr.cnes.sitools.dataset.database.common.DataSetExplorerUtil;
+import fr.cnes.sitools.dataset.dto.ColumnConceptMappingDTO;
+import fr.cnes.sitools.dataset.dto.DictionaryMappingDTO;
+import fr.cnes.sitools.datasource.jdbc.model.AttributeValue;
+import fr.cnes.sitools.datasource.jdbc.model.Record;
+import fr.cnes.sitools.dictionary.model.Concept;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.restlet.data.MediaType;
+import org.restlet.ext.wadl.MethodInfo;
+import org.restlet.representation.Representation;
+import org.restlet.representation.Variant;
+import org.restlet.resource.Get;
+// IMPORT POUR LE JSON
+import org.restlet.representation.WriterRepresentation;
+
+//-------------------------
+
+/**
+ *
+ * @author marc
+ */
+public class DatasetToJson extends SitoolsParameterizedResource {
+    
+    private static final Logger LOG = Logger.getLogger(DatasetToJson.class.getName());
+    
+    private String dicoNameString = new String();
+    
+    final private String mimeTypeFits = "application/fits";
+    
+    final private int maxResultsSend = 999999999;
+    
+    final private double ratioSpolyToRaDec = 57.295779513;
+    
+    @Override
+    public void sitoolsDescribe() {
+        setName("DatasetToJson");
+        setDescription("retrieves Dataset to Json file");
+    }
+
+    @Override
+    public void doInit() {
+        super.doInit();
+    }
+
+    /**
+    * Get HTML
+    * 
+    * @return Representation the HTML result
+    */
+    @Get
+    public Representation get() {
+        return execute();
+    }
+
+    @Override
+    protected void describeGet(MethodInfo info) {
+        this.addInfo(info);
+        info.setIdentifier("retrieve records and ");
+        info.setDocumentation("Method to get Json file from a dataset");
+        addStandardGetRequestInfo(info);
+        DataSetExplorerUtil.addDatasetExplorerGetRequestInfo(info);
+        DataSetApplication application = (DataSetApplication) getApplication();
+        DataSetExplorerUtil.addDatasetExplorerGetFilterInfo(info, application.getFilterChained());
+        addStandardResponseInfo(info);
+        addStandardInternalServerErrorInfo(info);
+    }
+
+    @Override
+    protected Representation head(Variant variant) {
+        Representation repr = super.head();
+        //repr.setMediaType(MediaType.APPLICATION_JSON);
+        return repr;
+    }
+
+    private Representation execute() {
+
+        dicoNameString = DatasetToJsonModel.DICO_PARAM_NAME;
+        
+        final Representation repr;
+        repr = new WriterRepresentation(MediaType.APPLICATION_JSON) { ;            
+                //repr =
+                @Override
+                public void write(Writer writer) throws IOException {
+                    boolean jsonP = false;
+                    String cb =  getRequest().getResourceRef().getQueryAsForm().getFirstValue("callback");
+                    String limit = null;
+                    limit = getRequest().getResourceRef().getQueryAsForm().getFirstValue("limit");
+                    
+                    if (cb != null) {
+                        jsonP = true;
+                        //getResponse().set //setContentType("text/javascript");
+                        this.setMediaType(MediaType.TEXT_JAVASCRIPT);
+                    } else {
+                        this.setMediaType(MediaType.APPLICATION_JSON);
+                    }
+                    
+                    
+                    // generate the DatabaseRequest
+                    DataSetApplication datasetApp = (DataSetApplication) getApplication();
+                    DataSetExplorerUtil dsExplorerUtil = new DataSetExplorerUtil(datasetApp, getRequest(), getContext());
+                    DictionaryMappingDTO dico =null;
+                    
+                    String dicoName = getParameterValue(dicoNameString);
+                    // Get the HashMap with as key the concept and value the columnAlias
+                    final HashMap<Concept,String> conceptsColumns = getcolumnAliasFromDico(dicoName, dico, datasetApp);
+                    
+                    // Get request parameters
+                    if (datasetApp.getConverterChained() != null) {
+                        datasetApp.getConverterChained().getContext().getAttributes().put("REQUEST", getRequest());
+                    }
+                    // Get DatabaseRequestParameters
+                    final DatabaseRequestParameters params = dsExplorerUtil.getDatabaseParams();
+                    LOG.log(Level.INFO,"***************************************** limit : "+ limit);
+                    if(limit == null){
+                        LOG.log(Level.INFO," ------------------- JE SUIS DANS LE IF");
+                        params.setPaginationExtend(maxResultsSend);
+                    }else if(limit.equals("25")){
+                        LOG.log(Level.INFO," ------------------- JE SUIS DANS LE ELSE IF");
+                        params.setPaginationExtend(maxResultsSend);
+                    }else{
+                        LOG.log(Level.INFO," ------------------- JE SUIS DANS LE ELSE");
+                        params.setPaginationExtend(Integer.parseInt(limit));
+                    }
+                    //params.setPaginationExtend(maxResultsSend);
+                    //params.setPaginationExtend(datasetApp.getDataSet().getNbRecords());
+                    DatabaseRequest databaseRequest = DatabaseRequestFactory.getDatabaseRequest(params);
+                    
+                    try {
+                        databaseRequest.createRequest();
+                        
+                    }catch (SitoolsException e) {
+                        e.printStackTrace();
+                    }
+                    if(jsonP){
+                        writer.write(cb + "(");
+                    }
+                    String response = "";
+                    //response = "{";
+                    writer.write("{");
+                    //response += "\"type\":\"FeatureCollection\",";
+                    writer.write("\"type\":\"FeatureCollection\",");
+                    // start features
+                    //response +="\"totalResults\":" + databaseRequest.getTotalCount() + ",";
+                    writer.write("\"totalResults\":" + databaseRequest.getTotalCount() + ",");
+                    //response +="\"features\":[";
+                    writer.write("\"features\":[");
+                    // Next for reading first record
+                    
+                    try {
+                        boolean first = true;
+                        while (databaseRequest.nextResult()) {                           
+                            Record rec = databaseRequest.getRecord();                            
+                            if (!first) {
+                                //response += ",";
+                                writer.write(",");
+                            }
+                            else {
+                                first = false;
+                            }
+                            // creates a geometry and a properties string
+                            String geometry = "";
+                            String services = "";
+                            String properties = "";
+                            boolean firstProp = true;
+                            String coords[] = new String[2];
+                            String coordinateReference = "";
+                            String urlDownloadFits = "";
+                            String spoly = "";
+                            
+                            for(Concept concept : conceptsColumns.keySet()){
+                                /*if(cpt%100 == 0){
+                                    LOG.log(Level.INFO, "Je suis dans le DANS la boucle WHILE sur les records, et dans la boucle FOR des concepts et cpt = "+cpt);
+                                }*/
+                                concept.getPropertyFromName("category");
+                                String colAlias = conceptsColumns.get(concept);
+                                for(AttributeValue attr : rec.getAttributeValues()){
+                                    if(attr.getName().equals(colAlias) && attr.getValue() != null && !attr.getValue().equals("")){
+                                        if(concept.getPropertyFromName("category").getValue().contains("properties")){
+                                            if (!firstProp) {
+                                                properties += ",";
+                                            }
+                                            else {
+                                                firstProp = false;
+                                            }
+                                            properties += "\"" + concept.getName().toString() + "\":\"" + attr.getValue() + "\"";
+                                        }
+                                        if(concept.getPropertyFromName("category").getValue().contains("geometry")){
+                                            if(concept.getName().equals("ra")){
+                                                coords[0]= attr.getValue().toString();
+                                            }else if(concept.getName().equals("dec")){
+                                                coords[1]= attr.getValue().toString();
+                                            }
+                                            if(concept.getName().equals("coordref")){
+                                                coordinateReference = attr.getValue().toString();
+                                            }
+                                            if(concept.getName().equals("spoly")){
+                                                spoly = attr.getValue().toString();
+                                            }
+                                        }
+                                        if(concept.getPropertyFromName("category").getValue().contains("services")){
+                                            if(concept.getName().equals("download")){
+                                                urlDownloadFits = attr.getValue().toString();
+                                            }
+                                        }
+
+                                    }
+                                }
+                            }
+                            
+                            // Set the geometry
+                            geometry = setGeometry(coords, coordinateReference, spoly);
+                            // Set The services
+                            if(!urlDownloadFits.isEmpty()){
+                                services = setServices(urlDownloadFits);
+                            }
+                            // start feature
+                            //response += "{";
+                            writer.write("{");
+                            //response += "\"type\":\"feature\",";
+                            writer.write("\"type\":\"feature\",");
+                            // start geometry
+                            //response += "\"geometry\":{";
+                            writer.write("\"geometry\":{");
+                            //response += geometry;
+                            writer.write(geometry);
+                            //response += "}";
+                            writer.write("}");
+                            // end geometry
+                            //response += ",";
+                            writer.write(",");
+                            // start properties
+                            //response += "\"properties\":{";
+                            writer.write("\"properties\":{");
+                            //response += properties;
+                            writer.write(properties);
+                            // end properties
+                            //response += "}";
+                            writer.write("}");
+                            
+                            // start services
+                            if(!services.equals("")){
+                                //response += ",";
+                                writer.write(",");
+                                //response += "\"services\":{";
+                                writer.write("\"services\":{");
+                                //response += services;
+                                writer.write(services);
+                                // end services
+                                //response += "}";
+                                writer.write("}");
+                            }
+                            
+                            // end feature
+                            //response += "}";
+                            writer.write("}");
+                        }
+                        // end features
+                        //response += "]";
+                        writer.write("]");                                                
+                        
+                    }catch (SitoolsException ex) {
+                        Logger.getLogger(DatasetToJson.class.getName()).log(Level.SEVERE, null, ex);
+                    }finally {
+                        //response += "}";
+                        writer.write("}");
+                        if (databaseRequest != null) {
+                            try {
+                                databaseRequest.close();
+                            }catch (SitoolsException e) {
+                                e.printStackTrace();
+                            }
+                        }
+                        if (writer != null) {
+                            //LOG.log(Level.INFO, "Je suis dans le finally avant le if jsonP");
+                            if(jsonP){
+                                //LOG.log(Level.INFO, "Je suis dans le finally dans le IF du if jsonP");
+                                //String response2 = cb + "("+response +");";
+                                writer.write(");");
+                                writer.flush();
+                            }else{
+                                //LOG.log(Level.INFO, "Je suis dans le finally dans le ELSE du if jsonP");
+                                //writer.write(response);
+                                writer.flush();
+                            }
+                        }
+                    }
+                }
+        };
+        return repr;
+        
+    }
+    
+    private HashMap<Concept,String> getcolumnAliasFromDico(String dicoName, DictionaryMappingDTO dico, DataSetApplication datasetApp){
+        
+        dico = datasetApp.getColumnConceptMappingDTO(dicoName);
+        final List<ColumnConceptMappingDTO> colConceptMappingDTOList = dico.getMapping();
+        final HashMap<Concept,String> conceptColumn = new HashMap<Concept,String>();
+        
+        for(ColumnConceptMappingDTO concepts : colConceptMappingDTOList){
+            conceptColumn.put(concepts.getConcept(), concepts.getColumnAlias());
+        }
+        return conceptColumn;
+    }
+    
+    private String setGeometry(String[] coords, String coordRef, String spoly){
+        String geometry = new String();
+        String[] spolyStringTmp = new String[4];
+        String[] spolyConverted = new String[4];
+        if(spoly.equals("")){
+            geometry = "\"coordinates\": ["+coords[0]+","+coords[1]+"],";
+            geometry += "\"referencesystem\": \""+coordRef+"\",\"type\": \"Point\"";
+        }else{
+            
+            String[] tmpString = spoly.split("\\)");
+            //LOG.log(Level.INFO, " SPOLY : "+spoly);
+            tmpString[0] = tmpString[0].substring(2, tmpString[0].length());
+            spolyStringTmp[0] = tmpString[0];
+            //LOG.log(Level.INFO, " i : 0 = "+spolyStringTmp[0]);
+            for(int i=1;i<4;i++){
+                spolyStringTmp[i] = tmpString[i].substring(2, tmpString[i].length());
+                //LOG.log(Level.INFO, "spolyStringTmp  i :"+i+ " = "+spolyStringTmp[i]);
+            }
+            
+            for(int k=0;k<spolyStringTmp.length;k++){
+                spolyConverted[k] = "["+String.valueOf((Double.parseDouble(spolyStringTmp[k].split(",")[0])*ratioSpolyToRaDec))
+                        +" , "+String.valueOf((Double.parseDouble(spolyStringTmp[k].split(",")[1])*ratioSpolyToRaDec))+"]";
+                //LOG.log(Level.INFO, " spolyConverted k :"+k+ " = "+spolyConverted[k]);
+            }
+            
+            geometry = "\"coordinates\":[["+spolyConverted[3]+","+spolyConverted[2]+","+spolyConverted[1]+","+spolyConverted[0]+","+spolyConverted[3]+"]],";
+            geometry += "\"referencesystem\": \""+coordRef+"\",\"type\": \"Polygon\"";
+        }
+        
+        return  geometry;
+    }
+    
+    private String setServices(String urlDownFits){
+        String services = new String();
+        services += "\"download\":{ \"mimetype\":\""+mimeTypeFits+"\",";
+        services += "\"url\":\""+urlDownFits+"\"}";
+        return services;
+    }
+}
\ No newline at end of file
diff --git a/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/resources/geojson/DatasetToJsonModel.java b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/resources/geojson/DatasetToJsonModel.java
new file mode 100644
index 0000000..e59dc14
--- /dev/null
+++ b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/resources/geojson/DatasetToJsonModel.java
@@ -0,0 +1,43 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package fr.ias.sitools.resources.geojson;
+
+import fr.cnes.sitools.dataset.DataSetApplication;
+import fr.cnes.sitools.plugins.resources.model.DataSetSelectionType;
+import fr.cnes.sitools.plugins.resources.model.ResourceModel;
+import fr.cnes.sitools.plugins.resources.model.ResourceParameter;
+import fr.cnes.sitools.plugins.resources.model.ResourceParameterType;
+
+/**
+ *
+ * @author marc
+ */
+public class DatasetToJsonModel extends ResourceModel {
+    
+    public static final String DICO_PARAM_NAME = "dictionary_name";
+    
+    public DatasetToJsonModel(){
+        super();
+        setClassAuthor("IDOC/IAS");
+        setClassOwner("IDOC/IAS");
+        setClassVersion("0.2");
+        setName("DatasetToJsonModel");
+        setDescription("dataset to GeoJson file");
+        setResourceClassName("fr.ias.sitools.resources.geojson.DatasetToJson");
+
+        ResourceParameter param1 = new ResourceParameter(DICO_PARAM_NAME, "The name of the dictionary to use",
+        ResourceParameterType.PARAMETER_INTERN);
+        param1.setValueType("xs:dictionary");
+        this.addParam(param1);
+        
+        this.setApplicationClassName(DataSetApplication.class.getName());
+        this.setDataSetSelection(DataSetSelectionType.MULTIPLE);
+        this.getParameterByName("methods").setValue("GET");
+        this.getParameterByName("url").setValue("/mizar/dstojson");
+    }
+    
+}
diff --git a/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/resources/geojson/DatasetToJsonORIG.java b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/resources/geojson/DatasetToJsonORIG.java
new file mode 100644
index 0000000..d4e2299
--- /dev/null
+++ b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/resources/geojson/DatasetToJsonORIG.java
@@ -0,0 +1,305 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package fr.ias.sitools.resources.geojson;
+
+import fr.cnes.sitools.common.exception.SitoolsException;
+import fr.cnes.sitools.common.resource.SitoolsParameterizedResource;
+import fr.cnes.sitools.dataset.DataSetApplication;
+import fr.cnes.sitools.dataset.database.DatabaseRequest;
+import fr.cnes.sitools.dataset.database.DatabaseRequestFactory;
+import fr.cnes.sitools.dataset.database.DatabaseRequestParameters;
+import fr.cnes.sitools.dataset.database.common.DataSetExplorerUtil;
+import fr.cnes.sitools.dataset.dto.ColumnConceptMappingDTO;
+import fr.cnes.sitools.dataset.dto.DictionaryMappingDTO;
+import fr.cnes.sitools.datasource.jdbc.model.AttributeValue;
+import fr.cnes.sitools.datasource.jdbc.model.Record;
+import fr.cnes.sitools.dictionary.model.Concept;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.HashMap;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.restlet.data.MediaType;
+import org.restlet.ext.wadl.MethodInfo;
+import org.restlet.representation.Representation;
+import org.restlet.representation.Variant;
+import org.restlet.resource.Get;
+// IMPORT POUR LE JSON
+import org.restlet.representation.WriterRepresentation;
+
+//-------------------------
+
+/**
+ *
+ * @author marc
+ */
+public class DatasetToJsonORIG extends SitoolsParameterizedResource {
+    
+    private static final Logger LOG = Logger.getLogger(DatasetToJsonORIG.class.getName());
+    
+    private String dicoNameString = new String();
+    
+    final private String mimeTypeFits = "application/fits";
+    
+    final private int maxResultsSend = 999999999;
+    
+    final private double ratioSpolyToRaDec = 57.295779513;
+    
+    @Override
+    public void sitoolsDescribe() {
+        setName("DatasetToJson");
+        setDescription("retrieves Dataset to Json file");
+    }
+
+    @Override
+    public void doInit() {
+        super.doInit();
+    }
+
+    /**
+    * Get HTML
+    * 
+    * @return Representation the HTML result
+    */
+    @Get
+    public Representation get() {
+        return execute();
+    }
+
+    @Override
+    protected void describeGet(MethodInfo info) {
+        this.addInfo(info);
+        info.setIdentifier("retrieve records and ");
+        info.setDocumentation("Method to get Json file from a dataset");
+        addStandardGetRequestInfo(info);
+        DataSetExplorerUtil.addDatasetExplorerGetRequestInfo(info);
+        DataSetApplication application = (DataSetApplication) getApplication();
+        DataSetExplorerUtil.addDatasetExplorerGetFilterInfo(info, application.getFilterChained());
+        addStandardResponseInfo(info);
+        addStandardInternalServerErrorInfo(info);
+    }
+
+    @Override
+    protected Representation head(Variant variant) {
+        Representation repr = super.head();
+        repr.setMediaType(MediaType.APPLICATION_JSON);
+        return repr;
+    }
+
+    private Representation execute() {
+
+        dicoNameString = DatasetToJsonModel.DICO_PARAM_NAME;
+        
+        Representation repr = new WriterRepresentation(MediaType.APPLICATION_JSON) {
+            
+            @Override
+            public void write(Writer writer) throws IOException {
+                
+                // generate the DatabaseRequest
+                DataSetApplication datasetApp = (DataSetApplication) getApplication();
+                DataSetExplorerUtil dsExplorerUtil = new DataSetExplorerUtil(datasetApp, getRequest(), getContext());
+                DictionaryMappingDTO dico =null;
+
+                String dicoName = getParameterValue(dicoNameString);
+                // Get the HashMap with as key the concept and value the columnAlias
+                final HashMap<Concept,String> conceptsColumns = getcolumnAliasFromDico(dicoName, dico, datasetApp);
+                
+                // Get request parameters
+                if (datasetApp.getConverterChained() != null) {
+                    datasetApp.getConverterChained().getContext().getAttributes().put("REQUEST", getRequest());
+                }
+                // Get DatabaseRequestParameters
+                final DatabaseRequestParameters params = dsExplorerUtil.getDatabaseParams();
+                params.setPaginationExtend(maxResultsSend);
+                //params.setPaginationExtend(datasetApp.getDataSet().getNbRecords());
+                DatabaseRequest databaseRequest = DatabaseRequestFactory.getDatabaseRequest(params);
+               
+                try {
+                    databaseRequest.createRequest();
+                    
+                }catch (SitoolsException e) {
+                    e.printStackTrace();
+                }
+                writer.write("{");
+                writer.write("\"type\":\"FeatureCollection\",");
+                // start features
+                writer.write("\"totalResults\":" + databaseRequest.getTotalCount() + ",");
+                writer.write("\"features\":[");
+                // Next for reading first record
+                
+                try {
+                    boolean first = true;
+                    
+                    while (databaseRequest.nextResult()) {
+                        Record rec = databaseRequest.getRecord();
+                        if (!first) {
+                          writer.write(",");
+                        }
+                        else {
+                          first = false;
+                        }
+                        // creates a geometry and a properties string
+                        String geometry = "";
+                        String services = "";
+                        String properties = "";
+                        boolean firstProp = true;
+                        String coords[] = new String[2];
+                        String coordinateReference = "";
+                        String urlDownloadFits = "";    
+                        String spoly = "";
+                        
+                        for(Concept concept : conceptsColumns.keySet()){
+                            concept.getPropertyFromName("category");                            
+                            String colAlias = conceptsColumns.get(concept);
+                            for(AttributeValue attr : rec.getAttributeValues()){
+                                if(attr.getName().equals(colAlias) && attr.getValue() != null && !attr.getValue().equals("")){
+                                        if(concept.getPropertyFromName("category").getValue().contains("properties")){
+                                            if (!firstProp) {
+                                                properties += ",";
+                                            }
+                                            else {
+                                                firstProp = false;
+                                            }
+                                            properties += "\"" + concept.getName().toString() + "\":\"" + attr.getValue() + "\"";
+                                        }
+                                        if(concept.getPropertyFromName("category").getValue().contains("geometry")){
+                                            if(concept.getName().equals("ra")){
+                                                coords[0]= attr.getValue().toString();
+                                            }else if(concept.getName().equals("dec")){
+                                                coords[1]= attr.getValue().toString();
+                                            }
+                                            if(concept.getName().equals("coordref")){
+                                                coordinateReference = attr.getValue().toString();
+                                            }
+                                            if(concept.getName().equals("spoly")){
+                                                spoly = attr.getValue().toString();
+                                            }
+                                        }
+                                        if(concept.getPropertyFromName("category").getValue().contains("services")){
+                                            if(concept.getName().equals("download")){
+                                                 urlDownloadFits = attr.getValue().toString();
+                                            }
+                                        }
+                                        
+                                }
+                            }  
+                        }
+                        
+                        // Set the geometry
+                        geometry = setGeometry(coords, coordinateReference, spoly);
+                        // Set The services
+                        if(!urlDownloadFits.isEmpty()){
+                            services = setServices(urlDownloadFits);
+                        }
+                        // start feature
+                        writer.write("{");
+                        writer.write("\"type\":\"feature\",");
+                        // start geometry
+                        writer.write("\"geometry\":{");
+                        writer.write(geometry);
+                        writer.write("}");
+                        // end geometry
+                        writer.write(",");
+                        // start properties
+                        writer.write("\"properties\":{");
+                        writer.write(properties);
+                        // end properties
+                        writer.write("}");
+                        
+                        // start services
+                        if(!services.equals("")){
+                            writer.write(",");
+                            writer.write("\"services\":{");
+                        
+                            writer.write(services);
+                             // end services
+                            writer.write("}");
+                        }
+                       
+                        // end feature
+                        writer.write("}");
+
+                    }
+                    
+                    // end features
+                    writer.write("]");
+                    
+                        
+
+                }catch (SitoolsException ex) {
+                    Logger.getLogger(DatasetToJsonORIG.class.getName()).log(Level.SEVERE, null, ex);
+                }finally {
+                    writer.write("}");
+                    if (databaseRequest != null) {
+                      try {
+                        databaseRequest.close();
+                      }catch (SitoolsException e) {
+                        e.printStackTrace();
+                      }
+                    }
+                    if (writer != null) {
+                    writer.flush();
+                    }
+                }
+            }
+        };
+        return repr;
+        
+    }
+    
+    private HashMap<Concept,String> getcolumnAliasFromDico(String dicoName, DictionaryMappingDTO dico, DataSetApplication datasetApp){
+        
+        dico = datasetApp.getColumnConceptMappingDTO(dicoName);
+        final List<ColumnConceptMappingDTO> colConceptMappingDTOList = dico.getMapping();
+        final HashMap<Concept,String> conceptColumn = new HashMap<Concept,String>();
+        
+        for(ColumnConceptMappingDTO concepts : colConceptMappingDTOList){
+            conceptColumn.put(concepts.getConcept(), concepts.getColumnAlias());
+        }
+        return conceptColumn;
+    }
+    
+    private String setGeometry(String[] coords, String coordRef, String spoly){
+        String geometry = new String();
+        String[] spolyStringTmp = new String[4];
+        String[] spolyConverted = new String[4];
+        if(spoly.equals("")){
+            geometry = "\"coordinates\": ["+coords[0]+","+coords[1]+"],";
+            geometry += "\"referencesystem\": \""+coordRef+"\",\"type\": \"Point\"";
+        }else{
+            
+            String[] tmpString = spoly.split("\\)");
+            //LOG.log(Level.INFO, " SPOLY : "+spoly);
+            tmpString[0] = tmpString[0].substring(2, tmpString[0].length());
+            spolyStringTmp[0] = tmpString[0];
+            //LOG.log(Level.INFO, " i : 0 = "+spolyStringTmp[0]);
+            for(int i=1;i<4;i++){
+                spolyStringTmp[i] = tmpString[i].substring(2, tmpString[i].length());
+                //LOG.log(Level.INFO, "spolyStringTmp  i :"+i+ " = "+spolyStringTmp[i]);
+            }
+            
+            for(int k=0;k<spolyStringTmp.length;k++){
+                spolyConverted[k] = "["+String.valueOf((Double.parseDouble(spolyStringTmp[k].split(",")[0])*ratioSpolyToRaDec))
+                        +" , "+String.valueOf((Double.parseDouble(spolyStringTmp[k].split(",")[1])*ratioSpolyToRaDec))+"]";
+                //LOG.log(Level.INFO, " spolyConverted k :"+k+ " = "+spolyConverted[k]);
+            }
+            
+            geometry = "\"coordinates\":[["+spolyConverted[3]+","+spolyConverted[2]+","+spolyConverted[1]+","+spolyConverted[0]+","+spolyConverted[3]+"]],";
+            geometry += "\"referencesystem\": \""+coordRef+"\",\"type\": \"Polygon\"";
+        }
+        
+        return  geometry;
+    }
+    
+    private String setServices(String urlDownFits){
+        String services = new String();
+        services += "\"download\":{ \"mimetype\":\""+mimeTypeFits+"\",";
+        services += "\"url\":\""+urlDownFits+"\"}";
+        return services;
+    }
+}
\ No newline at end of file
diff --git a/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/resources/spectrofits/GetFitsDataSpectro.java b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/resources/spectrofits/GetFitsDataSpectro.java
new file mode 100644
index 0000000..e611480
--- /dev/null
+++ b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/resources/spectrofits/GetFitsDataSpectro.java
@@ -0,0 +1,407 @@
+/*******************************************************************************
+ * Copyright 2010-2013 CNES - CENTRE NATIONAL d'ETUDES SPATIALES
+ *
+ * This file is part of SITools2.
+ *
+ * SITools2 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * SITools2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with SITools2.  If not, see <http://www.gnu.org/licenses/>.
+ ******************************************************************************/
+package fr.ias.sitools.resources.spectrofits;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.restlet.data.MediaType;
+import org.restlet.ext.json.JsonRepresentation;
+import org.restlet.ext.wadl.MethodInfo;
+import org.restlet.representation.Representation;
+import org.restlet.representation.Variant;
+import org.restlet.resource.Get;
+ 
+import fr.cnes.sitools.common.exception.SitoolsException;
+import fr.cnes.sitools.common.resource.SitoolsParameterizedResource;
+import fr.cnes.sitools.dataset.DataSetApplication;
+import fr.cnes.sitools.dataset.database.DatabaseRequestFactory;
+import fr.cnes.sitools.dataset.database.DatabaseRequestParameters;
+import fr.cnes.sitools.dataset.database.common.DataSetExplorerUtil;
+import fr.cnes.sitools.plugins.resources.model.ResourceParameter;
+import fr.cnes.sitools.resources.order.utils.OrderResourceUtils;
+import fr.cnes.sitools.dataset.database.DatabaseRequest;
+import fr.cnes.sitools.datasource.jdbc.model.AttributeValue;
+import fr.cnes.sitools.datasource.jdbc.model.Record;
+
+import nom.tam.fits.*;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+/**
+ * HTML resource
+ * 
+ * 
+ * @author b.hasnoun
+ */
+public class GetFitsDataSpectro extends SitoolsParameterizedResource {
+
+  @Override
+  public void sitoolsDescribe() {
+    setName("GetFitsDataSpectro");
+    setDescription("Get cube fits file data");
+  }
+
+  @Override
+  public void doInit() {
+    super.doInit();
+  }
+
+  /**
+   * Get HTML
+   * 
+   * @return Representation the HTML result
+   */
+  @Get
+  public Representation getCsv() {
+    return execute();
+  }
+ 
+  @Override
+  protected void describeGet(MethodInfo info) {
+    this.addInfo(info);
+    info.setIdentifier("retrieve records and extract data and metadata from fits file");
+    info.setDocumentation("Method to get the data and metadata from a fits file");
+    addStandardGetRequestInfo(info);
+    DataSetExplorerUtil.addDatasetExplorerGetRequestInfo(info);
+    DataSetApplication application = (DataSetApplication) getApplication();
+    DataSetExplorerUtil.addDatasetExplorerGetFilterInfo(info, application.getFilterChained());
+    addStandardResponseInfo(info);
+    addStandardInternalServerErrorInfo(info);
+  }
+
+  @Override
+  protected Representation head(Variant variant) {
+    Representation repr = super.head();
+    repr.setMediaType(MediaType.APPLICATION_JSON);
+    return repr;
+  }
+
+  /**
+   * Execute the request and return a Representation
+   * 
+   * @return the HTML representation
+   */
+  private Representation execute() {
+    
+    Representation repr = null;
+    
+    // generate the DatabaseRequest
+    DataSetApplication datasetApp = (DataSetApplication) getApplication();
+    DataSetExplorerUtil dsExplorerUtil = new DataSetExplorerUtil(datasetApp, getRequest(), getContext());
+
+    // Get request parameters
+    if (datasetApp.getConverterChained() != null) {
+      datasetApp.getConverterChained().getContext().getAttributes().put("REQUEST", getRequest());
+    }
+    // Get DatabaseRequestParameters
+    DatabaseRequestParameters params = dsExplorerUtil.getDatabaseParams();
+
+    DatabaseRequest databaseRequest = DatabaseRequestFactory.getDatabaseRequest(params);
+    
+    if (params.getDistinct()) {
+      try {
+        databaseRequest.createDistinctRequest();
+      }
+      catch (SitoolsException e) {
+        
+        e.printStackTrace();
+      }
+    } else {
+      try {
+        databaseRequest.createRequest();
+      }
+      catch (SitoolsException e) {
+       
+        e.printStackTrace();
+      }
+    }
+    
+    ResourceParameter urlName = this.getModel().getParameterByName("colUrl");
+    int hdu = Integer.parseInt(this.getModel().getParameterByName("hduCube").getValue());
+    String waveLocation = this.getModel().getParameterByName("wave").getValue();
+    
+    if (databaseRequest != null) {
+
+      // Next for reading first record
+      try {
+        databaseRequest.nextResult();
+        Record rec = databaseRequest.getRecord();
+        
+        AttributeValue attributeValueURL = OrderResourceUtils.getInParam(urlName, rec);
+        
+        if (attributeValueURL.getValue() != null){
+            // get the file path
+            String filePath = (String) attributeValueURL.getValue();
+            try {
+              
+              Fits fits = new Fits(filePath);
+              FitsFactory.setUseHierarch(true);
+              Header.setLongStringsEnabled(true);
+              
+              JSONObject jSON = new JSONObject();
+              
+              int waveHDU = -1;
+              
+              int nberHDUs = fits.size();
+              System.out.println("Number of HDUs: "+nberHDUs);
+              jSON.put("HDUs", nberHDUs);
+              
+              // Headers from fits
+              System.out.println("Getting Headers...");
+              List<String> headers = new ArrayList<String>(nberHDUs);
+              List<List<List<String>>> headersList = new ArrayList<List<List<String>>>(nberHDUs);
+              
+              for (int i=0;i<nberHDUs;i++){
+                
+                Header header = fits.getHDU(i).getHeader();
+
+                int nbreCards = header.getNumberOfCards();
+                String headerStr = "";
+                
+                //making HIERARCH mapping
+                HashMap<String,String> mapHierarch = new HashMap<String,String>();                
+                for (int j=0; j<nbreCards; j++){
+                  String cardStr = header.getCard(j);
+                  if (cardStr.matches("HIERARCH\\s.*\\s(META.*)\\s*=\\s*(.*)")) {
+                    //System.out.println(cardStr);
+                    Pattern p = Pattern.compile("HIERARCH\\s.*\\s(META.*)\\s*=\\s*(.*)");
+                    Matcher m = p.matcher(cardStr);
+                    if (m.find()) {
+                      //System.out.println(m.group(1)+" "+m.group(2));
+                      mapHierarch.put(m.group(1), m.group(2));
+                    }
+                  }
+                  headerStr = headerStr+cardStr+"<br>";
+                }
+                
+                //List of extensions -- List of List of Cards
+                List<List<String>> cardList = new ArrayList<List<String>>(nbreCards);
+                for (int j=0; j<nbreCards; j++){
+                  
+                  List<String> keyValueComment = new ArrayList<String>(nbreCards); 
+                  HeaderCard card = header.findCard(header.getKey(j));
+                  
+                  if ( card!=null ) {
+                    
+                    //key
+                    if (mapHierarch.containsKey(card.getKey())) { 
+                      keyValueComment.add( "HIERARCH "+mapHierarch.get(card.getKey()) );
+                      }
+                    else {
+                      keyValueComment.add(card.getKey());
+                    }
+                    
+                    //value
+                    keyValueComment.add(card.getValue());
+                    
+                    if ( card.getKey().contains("EXTNAME") && card.getValue().contains("ImageIndex") ) { 
+                      System.out.println("ImageIndex in HDU "+i);
+                      waveHDU=i;
+                      }
+                    
+                    //comment
+                    String commentCard = card.getComment();
+                    if (commentCard!=null) {
+
+                      if (commentCard.contains("&")) {
+                        //System.out.println(j+" "+commentCard);
+                        commentCard = commentCard.substring(0, commentCard.length()-1);
+                        int jTmp = j;
+                        while(header.getCard(jTmp+1).startsWith("COMMENT")){
+                          String commentCardNext = header.getCard(jTmp+1);
+                          if (commentCardNext.contains("&")) { commentCardNext = commentCardNext.substring(0, commentCardNext.length()-1); }
+                          commentCard += commentCardNext.split("COMMENT ")[1];
+                          jTmp++;
+                          }
+                        keyValueComment.add(commentCard);
+                        }
+                      else { keyValueComment.add(commentCard); }
+                      
+                    } else {keyValueComment.add("");}
+                    
+                    cardList.add(keyValueComment);
+                    
+                  }
+                  
+                }
+                
+                headersList.add(cardList);
+                
+                headers.add(headerStr);
+                
+              }
+
+    
+              jSON.put("HEADERSGRID", headersList);
+              System.out.println("Headers - Done !");
+              
+              
+              System.out.println("Getting Wave...");
+              int hhdduu = -1;
+              for (int i=0;i<nberHDUs;i++){
+                Header header = fits.getHDU(i).getHeader();
+                String a = header.findKey("CDELT3");
+                if(a != null){
+                    System.out.println("CDELT3 find in "+i);
+                    hhdduu = i;
+                }else{
+                    System.out.println("CDELT3 not found in "+i);
+                }
+              }
+              
+              // Wave from fits
+              //if (fits.getHDU(hdu).getHeader().findKey("CDELT3")!=null) {
+              if(hhdduu != -1){
+                System.out.println("... from WCS");
+
+                double naxis3 = fits.getHDU(hdu).getHeader().getDoubleValue("NAXIS3");
+                double crval3 = fits.getHDU(hdu).getHeader().getDoubleValue("CRVAL3");
+                double cdelt3 = fits.getHDU(hdu).getHeader().getDoubleValue("CDELT3");
+                System.out.println(naxis3+" "+crval3+" "+cdelt3);
+                float[] wave = new float[(int)naxis3];
+                for (int i = 0 ; i < wave.length; i++) { wave[i] = (float) (crval3 + i * cdelt3); }
+                jSON.put("WAVE", wave);
+                
+              }else {
+                System.out.println("not from WCS");
+                if (waveHDU!=-1) {
+                  System.out.println("No wave data in the cube WCS - Using wave array from ImageIndex HDU table");
+                  TableHDU cols = (TableHDU) fits.getHDU(waveHDU);
+                  double[] waveD = (double[]) cols.getColumn(0);
+                  float[] wave = new float[waveD.length];
+                  for (int i = 0 ; i < waveD.length; i++) { wave[i] = (float) waveD[i]; }
+                  jSON.put("WAVE", wave);
+                } else {
+                  System.out.println("No wave data in the cube WCS - Using wave array from specific HDU table - "+waveLocation);
+                  if (waveLocation.matches("(\\d+)-(\\d+)")){
+                    int waveTable = Integer.parseInt(waveLocation.split("-")[0]);
+                    int waveColumn = Integer.parseInt(waveLocation.split("-")[1]);
+                    TableHDU cols = (TableHDU) fits.getHDU(waveTable);
+                    
+                    double[] waveD = (double[]) cols.getColumn(waveColumn);
+                    float[] wave = new float[waveD.length];
+                    for (int i = 0 ; i < waveD.length; i++) { wave[i] = (float) waveD[i]; }
+                    jSON.put("WAVE", wave);
+                  } else {
+                    System.out.println("No wave data in "+waveLocation);
+                  }                  
+                } 
+              }
+              System.out.println(" Wave - Done !");
+              
+              System.out.println("Getting Cube Data...");
+              // Spectrum from fits
+              for (int m=1; m<=2; m++) {
+                jSON.put("NAXIS"+m, fits.getHDU(hdu).getHeader().getDoubleValue("NAXIS"+m));
+                jSON.put("CRPIX"+m, fits.getHDU(hdu).getHeader().getDoubleValue("CRPIX"+m));
+                jSON.put("CRVAL"+m, fits.getHDU(hdu).getHeader().getDoubleValue("CRVAL"+m));
+                jSON.put("CDELT"+m, fits.getHDU(hdu).getHeader().getDoubleValue("CDELT"+m));
+                jSON.put("CTYPE"+m, fits.getHDU(hdu).getHeader().getStringValue("CTYPE"+m));
+              }
+              
+              jSON.put("NAXIS3", fits.getHDU(hdu).getHeader().getDoubleValue("NAXIS3"));
+              
+              jSON.put("INFO_QTTY", fits.getHDU(hdu).getHeader().getStringValue("INFO____") );
+              jSON.put("UNIT_QTTY", fits.getHDU(hdu).getHeader().getStringValue("QTTY____") );
+              jSON.put("INFO_WAVE", fits.getHDU(hdu).getHeader().getStringValue("CTYPE3") );
+              jSON.put("UNIT_WAVE", fits.getHDU(hdu).getHeader().getStringValue("CUNIT3") );
+              
+              double[][][] cubeFits = ((double[][][]) fits.getHDU(hdu).getData().getData());
+              int naxis1 = cubeFits[0][0].length;
+              int naxis2 = cubeFits[0].length;
+              int naxis3 = cubeFits.length;
+              
+              //Reorganizing cube
+              List<List<List<Float>>> cube3DL = new ArrayList<List<List<Float>>>(naxis1);  
+              //float cube[][][] = new float[naxis1][naxis2][naxis3];
+              for (int x=0;x<naxis1;x++){
+                List<List<Float>> list2 = new ArrayList<List<Float>>(naxis2);  
+                for (int y=0;y<naxis2;y++){
+                  List<Float> list3 = new ArrayList<Float>(naxis3);  
+                  for (int z=0;z<naxis3;z++){
+                    //cube[x][y][z] = (float) cubeFits[z][y][x];
+                    if (cubeFits[z][y][x] != Double.NaN ) { list3.add( (float) cubeFits[z][y][x] ); }
+                    else { list3.add(null); }
+                  }
+                  list2.add(list3);    
+                }
+                cube3DL.add(list2);  
+              }
+              
+              /*
+              List<List<List<Float>>> cube3DL = new ArrayList<List<List<Float>>>(naxis1);  
+              for (int i = 0; i < naxis1; i++) {  
+                  List<List<Float>> list2 = new ArrayList<List<Float>>(naxis2);  
+                  for (int j = 0; j < naxis2; j++) {  
+                      List<Float> list3 = new ArrayList<Float>(naxis3);  
+                      for (int k = 0; k < naxis3; k++) { 
+                        list3.add(cube[i][j][k]);
+                        }  
+                      list2.add(list3);  
+                      }  
+                  cube3DL.add(list2);  
+                  } 
+              */
+              
+              JSONArray cubeJL= new JSONArray(cube3DL.toString());
+              jSON.put("SPECTRUM", cubeJL);
+              
+              System.out.println(" Cube - Done !");
+             
+              repr = new JsonRepresentation(jSON);
+              
+              
+            }
+            catch (FitsException e) {
+              // TODO Auto-generated catch block
+              e.printStackTrace();
+            }
+            catch (IOException e) {
+              // TODO Auto-generated catch block
+              e.printStackTrace();
+            }
+            
+            catch (JSONException e) {
+              // TODO Auto-generated catch block
+              e.printStackTrace();
+            }
+            
+        }
+        databaseRequest.close();
+        
+      }
+      catch (SitoolsException e) {
+        // TODO Auto-generated catch block
+        e.printStackTrace();
+      }
+      
+    }
+
+    return repr;
+    
+  }
+
+}
diff --git a/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/resources/spectrofits/GetFitsDataSpectroModel.java b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/resources/spectrofits/GetFitsDataSpectroModel.java
new file mode 100644
index 0000000..fbaca64
--- /dev/null
+++ b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/resources/spectrofits/GetFitsDataSpectroModel.java
@@ -0,0 +1,89 @@
+ /*******************************************************************************
+ * Copyright 2010-2013 CNES - CENTRE NATIONAL d'ETUDES SPATIALES
+ *
+ * This file is part of SITools2.
+ *
+ * SITools2 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * SITools2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with SITools2.  If not, see <http://www.gnu.org/licenses/>.
+ ******************************************************************************/
+package fr.ias.sitools.resources.spectrofits;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import fr.cnes.sitools.common.validator.ConstraintViolation;
+import fr.cnes.sitools.common.validator.Validator;
+import fr.cnes.sitools.dataset.DataSetApplication;
+import fr.cnes.sitools.plugins.resources.model.DataSetSelectionType;
+import fr.cnes.sitools.plugins.resources.model.ResourceModel;
+import fr.cnes.sitools.plugins.resources.model.ResourceParameter;
+import fr.cnes.sitools.plugins.resources.model.ResourceParameterType;
+
+/*
+ * The Model for show fits header resource
+ * 
+ * 
+ * @author b.hasnoun
+ */
+public class GetFitsDataSpectroModel extends ResourceModel {
+
+  /**
+   * Constructor
+   */
+  public GetFitsDataSpectroModel() {
+
+    super();
+    setClassAuthor("Boualem HASNOUN");
+    setClassOwner("IAS2");
+    setClassVersion("1.0");
+    setName("GetFitsDataSpectroModel");
+    setDescription("Getting data and metadata from a fits file");
+    setClassName("fr.ias.sitools.resources.spectrofits.GetFitsDataSpectroModel");
+    setResourceClassName(fr.ias.sitools.resources.spectrofits.GetFitsDataSpectro.class.getName());
+    
+    ResourceParameter paramColUrl = new ResourceParameter("colUrl", "Colum containing the url of the fits file.",
+        ResourceParameterType.PARAMETER_INTERN);
+    paramColUrl.setValueType("xs:dataset.columnAlias");
+    this.addParam(paramColUrl);
+    
+    ResourceParameter paramHDU = new ResourceParameter("hduCube", "HDU number where to find the spectral cube.",
+        ResourceParameterType.PARAMETER_INTERN);
+    paramHDU.setValueType("xs:integer");
+    this.addParam(paramHDU);
+    
+    ResourceParameter paramWaveFromWCS = new ResourceParameter("wave", "HDU Table and column number where to find the wave data if you can't build the wave array from the WCS metadata of the spectral cube. Ex: 4-0",
+        ResourceParameterType.PARAMETER_INTERN);
+    paramWaveFromWCS.setValueType("xs:string");
+    this.addParam(paramWaveFromWCS);    
+    
+    this.setApplicationClassName(DataSetApplication.class.getName());
+    this.setDataSetSelection(DataSetSelectionType.SINGLE);
+    this.getParameterByName("methods").setValue("GET");
+    this.completeAttachUrlWith("/getFitsDataSpectro");
+  }
+
+  @Override
+  public Validator<ResourceModel> getValidator() {
+    return new Validator<ResourceModel>() {
+
+      @Override
+      public Set<ConstraintViolation> validate(ResourceModel item) {
+        Set<ConstraintViolation> constraints = new HashSet<ConstraintViolation>();
+        Map<String, ResourceParameter> params = item.getParametersMap();
+        
+        return constraints;
+      }
+    };
+  }
+}
diff --git a/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/resources/vo/SimpleSpectralAccessResource.java b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/resources/vo/SimpleSpectralAccessResource.java
new file mode 100644
index 0000000..2b112d9
--- /dev/null
+++ b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/resources/vo/SimpleSpectralAccessResource.java
@@ -0,0 +1,132 @@
+ /*******************************************************************************
+ * Copyright 2010-2013 CNES - CENTRE NATIONAL d'ETUDES SPATIALES
+ *
+ * This file is part of SITools2.
+ *
+ * SITools2 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * SITools2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with SITools2.  If not, see <http://www.gnu.org/licenses/>.
+ ******************************************************************************/
+package fr.ias.sitools.resources.vo;
+
+import fr.ias.sitools.vo.ssa.SimpleSpectralAccessProtocolLibrary;
+import fr.cnes.sitools.common.resource.SitoolsParameterizedResource;
+import fr.cnes.sitools.dataset.DataSetApplication;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Logger;
+import org.restlet.data.Disposition;
+import org.restlet.data.MediaType;
+import org.restlet.data.Status;
+import org.restlet.ext.wadl.DocumentationInfo;
+import org.restlet.ext.wadl.MethodInfo;
+import org.restlet.ext.wadl.ParameterInfo;
+import org.restlet.ext.wadl.ParameterStyle;
+import org.restlet.ext.wadl.RepresentationInfo;
+import org.restlet.representation.Representation;
+import org.restlet.representation.Variant;
+import org.restlet.resource.Get;
+
+/**
+ * Queries the dataset and retrieves the result using the Simple Image Access Protocol.
+ * @see SimpleImageAccessResourcePlugin the plugin
+ * @see SimpleSpectralAccessProtocolLibrary the library that we use for SIAP.
+ * @author Jean-Christophe Malapert <jean-christophe.malapert@cnes.fr>
+ */
+public class SimpleSpectralAccessResource extends SitoolsParameterizedResource {
+
+  /**
+   * Logger.
+   */
+  private static final Logger LOG = Logger.getLogger(SimpleSpectralAccessResource.class.getName());
+
+  /**
+   * Initialize.
+   */
+  @Override
+  public final void doInit() {
+    super.doInit();
+  }
+
+  /**
+   * Returns the supported representation.
+   *
+   * @param variant variant
+   * @return XML mediaType
+   */
+  @Override
+  protected final Representation head(final Variant variant) {
+    final Representation repr = super.head();
+    repr.setMediaType(MediaType.TEXT_XML);
+    return repr;
+  }
+
+  /**
+   * Returns the VOTable response.
+   *
+   * @return VOTable response
+   */
+  @Get
+  public final Representation getVOResponse() {
+    LOG.finest(String.format("SSA : %s", getRequest()));
+    final SimpleSpectralAccessProtocolLibrary sia = new SimpleSpectralAccessProtocolLibrary((DataSetApplication) this.getApplication(),
+            this.getModel(), this.getRequest(), this.getContext());
+    final Representation rep = sia.getResponse();
+    if (fileName != null && !"".equals(fileName)) {
+      final Disposition disp = new Disposition(Disposition.TYPE_ATTACHMENT);
+      disp.setFilename(fileName);
+      rep.setDisposition(disp);
+    }
+    return rep;
+  }
+
+  /**
+   * Describes SITools2 in the WADL.
+   */
+  @Override
+  public final void sitoolsDescribe() {
+    setName("Simple Spectral Access Protocol");
+    setDescription("This class implements the Simple Spectral Access Protocol for Virtual Observatory. "
+            + "See http://ivoa.net web site for information about this protocol.");
+  }
+
+  /**
+   * Describe GET method in the WADL.
+   *
+   * @param info information
+   */
+  @Override
+  protected final void describeGet(final MethodInfo info) {
+    this.addInfo(info);
+    info.setIdentifier("SimpleSpectralAccessProtocol");
+    info.setDocumentation("Interoperability service to distribute spectrum through the Simple Spectral Access Protocol");
+
+    final List<ParameterInfo> parametersInfo = new ArrayList<ParameterInfo>();
+    parametersInfo.add(new ParameterInfo("POS", true, "string", ParameterStyle.QUERY,
+            "Box Central position (decimal degree) in ICRS such as RA,DEC."));
+    parametersInfo.add(new ParameterInfo("SIZE", true, "string", ParameterStyle.QUERY,
+            "Size of the box in decimal degree such as width,height or width."));
+    info.getRequest().setParameters(parametersInfo);
+
+    info.getResponse().getStatuses().add(Status.SUCCESS_OK);
+
+    final DocumentationInfo documentation = new DocumentationInfo();
+    documentation.setTitle("SIAP");
+    documentation.setTextContent("Simple Spectral Access Protocol");
+
+    final List<RepresentationInfo> representationsInfo = new ArrayList<RepresentationInfo>();
+    final RepresentationInfo representationInfo = new RepresentationInfo(MediaType.TEXT_XML);
+    representationInfo.setDocumentation(documentation);
+    representationsInfo.add(representationInfo);
+    info.getResponse().setRepresentations(representationsInfo);
+  }
+}
diff --git a/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/resources/vo/SimpleSpectralAccessResourceModel.java b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/resources/vo/SimpleSpectralAccessResourceModel.java
new file mode 100644
index 0000000..f940fdb
--- /dev/null
+++ b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/resources/vo/SimpleSpectralAccessResourceModel.java
@@ -0,0 +1,200 @@
+ /*******************************************************************************
+ * Copyright 2010-2013 CNES - CENTRE NATIONAL d'ETUDES SPATIALES
+ *
+ * This file is part of SITools2.
+ *
+ * SITools2 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * SITools2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with SITools2.  If not, see <http://www.gnu.org/licenses/>.
+ ******************************************************************************/
+package fr.ias.sitools.resources.vo;
+
+import fr.ias.sitools.vo.ssa.SimpleSpectralAccessProtocolLibrary;
+import fr.cnes.sitools.common.validator.ConstraintViolation;
+import fr.cnes.sitools.common.validator.ConstraintViolationLevel;
+import fr.cnes.sitools.common.validator.Validator;
+import fr.cnes.sitools.dataset.DataSetApplication;
+import fr.cnes.sitools.plugins.resources.model.DataSetSelectionType;
+import fr.cnes.sitools.plugins.resources.model.ResourceModel;
+import fr.cnes.sitools.plugins.resources.model.ResourceParameter;
+import fr.cnes.sitools.plugins.resources.model.ResourceParameterType;
+import fr.cnes.sitools.util.Util;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Logger;
+
+/**
+ * Plugin for publishing a dataset through the Simple Image Access Protocol.
+ *
+ * <p>
+ * The plugin answers to the need of the following user story:<br/>
+ * As administrator, I publish my data through SIAP so that the users can
+ * request my images by the use of an interoperability standard.
+ * <br/>
+ * <img src="../../../../../../images/SIAP-usecase.png"/>
+ * <br/>
+ * In addition, this plugin has several dependencies with different
+ * components:<br/>
+ * <img src="../../../../../../images/SimpleImageAccessResourcePlugin.png"/>
+ * <br/>
+ * </p>
+ *
+ * @author Jean-Christophe Malapert <jean-christophe.malapert@cnes.fr>
+ * @startuml SIAP-usecase.png title Publishing data through SIAP User --> (SIAP
+ * service) : requests Admin --> (SIAP service) : adds and configures the SIAP
+ * service from the dataset. (SIAP service) .. (dataset) : uses
+ * @enduml
+ * @startuml package "Services" { HTTP - [SimpleImageAccessResourcePlugin] }
+ * database "Database" { frame "Data" { [myData] } } package "Dataset" { HTTP -
+ * [Dataset] [VODictionary] } folder "DataStorage" { HTTP - [directory] }
+ * [SimpleImageAccessResourcePlugin] --> [Dataset] [Dataset] --> [directory]
+ * [Dataset] --> [myData] [Dataset] --> [VODictionary]
+ * @enduml
+ */
+public class SimpleSpectralAccessResourceModel extends ResourceModel {
+
+    /**
+     * Logger.
+     */
+    private static final Logger LOG = Logger.getLogger(SimpleSpectralAccessResourceModel.class.getName());
+
+    /**
+     * Constructs the configuration panel of the plugin.
+     */
+    public SimpleSpectralAccessResourceModel() {
+        super();
+        setClassAuthor("Mnicoals");
+        setClassOwner("IAS");
+        setClassVersion("0.1");
+        setName("Simple Spectral Access Protocol");
+        setDescription("This plugin provides an access to your data through the Simple Image Access Protocol");
+        setResourceClassName(fr.ias.sitools.resources.vo.SimpleSpectralAccessResource.class.getName());
+        
+        this.setApplicationClassName(DataSetApplication.class.getName());
+        this.setDataSetSelection(DataSetSelectionType.SINGLE);
+        this.getParameterByName("methods").setValue("GET");
+        this.completeAttachUrlWith("/services/vo/ssa");
+        setConfiguration();
+        /*
+        this.setApplicationClassName(DataSetApplication.class.getName());
+
+        //we set to NONE because this is a web service for Virtual Observatory
+        // and we do not want to see it in the web user interface
+        this.setDataSetSelection(DataSetSelectionType.NONE);
+        setConfiguration();*/
+    }
+
+    /**
+     * Sets the configuration for the administrator.
+     */
+    private void setConfiguration() {
+        final ResourceParameter dico = new ResourceParameter(fr.ias.sitools.vo.ssa.SimpleSpectralAccessProtocolLibrary.DICTIONARY, "Dictionary name that sets up the service.",
+        ResourceParameterType.PARAMETER_INTERN);
+        dico.setValueType("xs:dictionary");
+        this.addParam(dico);
+        
+        final ResourceParameter intersect = new ResourceParameter(fr.ias.sitools.vo.ssa.SimpleSpectralAccessProtocolLibrary.INTERSECT,
+                "how matched images should intersect the region of interest",
+                ResourceParameterType.PARAMETER_INTERN);
+        //String intersectEnum = "xs:enum[COVERS, ENCLOSED, CENTER, OVERLAPS]";
+        intersect.setValueType("xs:enum[CENTER, OVERLAPS]");
+        intersect.setValue("OVERLAPS");
+        addParam(intersect);
+        
+        final ResourceParameter verb = new ResourceParameter(fr.ias.sitools.vo.ssa.SimpleSpectralAccessProtocolLibrary.VERB,
+                "Verbosity determines how many columns are to be returned in the resulting table",
+                ResourceParameterType.PARAMETER_INTERN);
+        verb.setValueType("xs:enum[0, 1, 2, 3]");
+        verb.setValue("1");
+        addParam(verb);
+        
+        final ResourceParameter responsibleParty = new ResourceParameter(fr.ias.sitools.vo.ssa.SimpleSpectralAccessProtocolLibrary.RESPONSIBLE_PARTY,
+                "The data provider's name and email", ResourceParameterType.PARAMETER_INTERN);
+        addParam(responsibleParty);
+
+        final ResourceParameter serviceName = new ResourceParameter(fr.ias.sitools.vo.ssa.SimpleSpectralAccessProtocolLibrary.SERVICE_NAME,
+                "The name of the service",
+                ResourceParameterType.PARAMETER_INTERN);
+        serviceName.setValueType("xs:enum[Spectral Archive Service, Spectral Cutout Service, Spectral Mosaicing Service, Spectral Extraction Service]");
+        serviceName.setValue("Spectral Archive Service");
+        addParam(serviceName);
+
+        final ResourceParameter description = new ResourceParameter(fr.ias.sitools.vo.ssa.SimpleSpectralAccessProtocolLibrary.DESCRIPTION,
+                "A couple of paragraphs of text that describe the nature of the service and its wider context",
+                ResourceParameterType.PARAMETER_INTERN);
+        addParam(description);
+
+        final ResourceParameter instrument = new ResourceParameter(fr.ias.sitools.vo.ssa.SimpleSpectralAccessProtocolLibrary.INSTRUMENT,
+                "The instrument that made the observations, for example STScI.HST.WFPC2",
+                ResourceParameterType.PARAMETER_INTERN);
+        addParam(instrument);
+        
+        final ResourceParameter maxQuerySize = new ResourceParameter(
+                fr.ias.sitools.vo.ssa.SimpleSpectralAccessProtocolLibrary.MAX_QUERY_SIZE,
+                "The largest search area, given in decimal degrees, that will be accepted by the service without returning an error condition."
+                + " A value of 64800 indicates that there is no restriction",
+                ResourceParameterType.PARAMETER_INTERN);
+        maxQuerySize.setValue("64800");
+        addParam(maxQuerySize);
+
+        final ResourceParameter maxImageSize = new ResourceParameter(
+                fr.ias.sitools.vo.ssa.SimpleSpectralAccessProtocolLibrary.MAX_IMAGE_SIZE,
+                "The largest image area, given in decimal degrees, that will be returned by the service",
+                ResourceParameterType.PARAMETER_INTERN);
+        addParam(maxImageSize);
+
+        final ResourceParameter maxFileSize = new ResourceParameter(
+                fr.ias.sitools.vo.ssa.SimpleSpectralAccessProtocolLibrary.MAX_FILE_SIZE,
+                "The largest file size, given in Bytes, that will be returned by the service",
+                ResourceParameterType.PARAMETER_INTERN);
+        addParam(maxFileSize);
+
+        final ResourceParameter maxRecords = new ResourceParameter(fr.ias.sitools.vo.ssa.SimpleSpectralAccessProtocolLibrary.MAX_RECORDS,
+                "The largest number of records that the service will return", ResourceParameterType.PARAMETER_INTERN);
+        maxRecords.setValue("-1");
+        addParam(maxRecords);
+        
+        final ResourceParameter geoAttribut = new ResourceParameter(fr.ias.sitools.vo.ssa.SimpleSpectralAccessProtocolLibrary.GEO_ATTRIBUT,
+                "Geographical attribut for OVERLAPS mode. The geographical attribut must be spoly datatype from pgsphere",
+                ResourceParameterType.PARAMETER_INTERN);
+        geoAttribut.setValueType("xs:dataset.columnAlias");
+        addParam(geoAttribut);
+
+    }
+
+    /**
+     * Validates the configuration that has been set by the administrator.
+     *
+     * @return the error or warning
+     */
+    @Override
+    public final Validator<ResourceModel> getValidator() {
+        return new Validator<ResourceModel>() {
+            @Override
+            public final Set<ConstraintViolation> validate(final ResourceModel item) {
+                final Set<ConstraintViolation> constraintList = new HashSet<ConstraintViolation>();
+                final Map<String, ResourceParameter> params = item.getParametersMap();
+                final ResourceParameter dico = params.get(fr.ias.sitools.vo.ssa.SimpleSpectralAccessProtocolLibrary.DICTIONARY);
+
+                if (!Util.isNotEmpty(dico.getValue())) {
+                    final ConstraintViolation constraint = new ConstraintViolation();
+                    constraint.setLevel(ConstraintViolationLevel.WARNING);
+                    constraint.setMessage("A dictionary must be set");
+                    constraint.setValueName(fr.ias.sitools.vo.ssa.SimpleSpectralAccessProtocolLibrary.DICTIONARY);
+                    constraintList.add(constraint);
+                }
+                return constraintList;
+            }
+        };
+    }
+}
diff --git a/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/validation/vo/TimeValidation.java b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/validation/vo/TimeValidation.java
new file mode 100644
index 0000000..7edce73
--- /dev/null
+++ b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/validation/vo/TimeValidation.java
@@ -0,0 +1,118 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package fr.ias.sitools.validation.vo;
+
+import fr.cnes.sitools.extensions.common.NumberArrayValidation;
+import fr.cnes.sitools.extensions.common.Validation;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ *
+ * @author marc
+ */
+public class TimeValidation  extends NumberArrayValidation{
+
+    /**
+    * Logger.
+    */
+    private static final Logger LOG = Logger.getLogger(TimeValidation.class.getName());
+    
+    /**
+     * private time to check
+     */
+    private String timeRange;
+    /**
+     * private band to check
+     */
+    private double[] bandRange;
+    /**
+     * Char time split
+     */
+    String timeYearCharSplit = "-";
+    /**
+     * Char Hour split
+     */
+    String timeHourCharSplit = ":";
+    /**
+     * Char Date split
+     */
+    String timeDateCharSplit = "T";
+    /**
+     * 
+     * First element of the range.
+     */
+    private static final int MIN = 0;
+    /**
+     * Last element of the range.
+     */
+    private static final int MAX = 1;
+
+    public TimeValidation(final Validation validation,final String keyword,final String timeToCheck) {
+         super(validation, keyword, ",", 2); 
+         this.timeRange = timeToCheck;
+    }
+    
+  
+
+    @Override
+    protected Map<String, String> localValidation() {
+        final Map<String, String> error = new HashMap<String, String>();
+        if(getTimeRange().split(",").length == 2){
+            String timeMin = getTimeRange().split(",")[MIN];
+            String timeMax = getTimeRange().split(",")[MAX];
+            if(timeMin.contains(timeDateCharSplit)){
+                if(timeMin.split(timeDateCharSplit).length > 2 ){
+                    error.put("Time", "Time value must be in ISO8601 format, eg yyyy-mm-ddThh:mm:ss");
+                }
+                if(!isValidDate(timeMin)){
+                    error.put("Time", timeMin+" is not a valide date ! Time value must be in ISO8601 format, eg yyyy-mm-ddThh:mm:ss");
+                }
+            }
+            if(timeMax.contains(timeDateCharSplit)){
+                if(timeMax.split(timeDateCharSplit).length > 2 ){
+                    error.put("Time", "Time value must be in ISO8601 format, eg yyyy-mm-ddThh:mm:ss");
+                }
+                if(!isValidDate(timeMax)){
+                    error.put("Time", timeMax+" is not a valide date ! Time value must be in ISO8601 format, eg yyyy-mm-ddThh:mm:ss");
+                }
+            }
+        }else{
+            String time = getTimeRange();
+            if(!isValidDate(time)){
+                error.put("Time", time+" is not a valide date ! Time value must be in ISO8601 format, eg yyyy-mm-ddThh:mm:ss");
+            }
+        }
+        return error;
+    }
+
+    /**
+     * @return the timeRange
+     */
+    public String getTimeRange() {
+        return timeRange;
+    }
+
+    public static boolean isValidDate(String text) {
+        if (text == null || !text.matches("\\d{4}-[01]\\d-[0-3]\\dT[0-9]{2}:[0-9]{2}:[0-9]{2}")){
+            return false;
+        }
+        
+        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
+        df.setLenient(false);
+        try {
+            df.parse(text);
+            return true;
+        } catch (ParseException ex) {
+            return false;
+        }
+    }
+}
diff --git a/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/representation/DatabaseRequestIasModel.java b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/representation/DatabaseRequestIasModel.java
new file mode 100644
index 0000000..a799df1
--- /dev/null
+++ b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/representation/DatabaseRequestIasModel.java
@@ -0,0 +1,64 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package fr.ias.sitools.vo.representation;
+
+import fr.cnes.sitools.astro.representation.DatabaseRequestModel;
+import fr.cnes.sitools.common.exception.SitoolsException;
+import fr.cnes.sitools.dataset.converter.business.ConverterChained;
+import fr.cnes.sitools.dataset.database.DatabaseRequest;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ *
+ * @author marc
+ */
+public class DatabaseRequestIasModel extends  DatabaseRequestModel {
+    
+    /**
+   * Logger.
+   */
+    private static final Logger LOG = Logger.getLogger(DatabaseRequestIasModel.class.getName());
+   /**
+     * DB Result set.
+     */
+    private DatabaseRequest request;
+    /**
+     * SITools2 converters.
+     */
+    private ConverterChained converterChained;
+    /**
+     * Number of rows.
+     */
+    private transient int sizeValue;
+
+    /**
+     * Empty constructor.
+     */
+    protected DatabaseRequestIasModel() {
+        setSize(0);
+    }
+
+    public DatabaseRequestIasModel(DatabaseRequest rsVal, ConverterChained converterChainedVal) {
+        super(rsVal, converterChainedVal);
+        int countRowRequest = rsVal.getCount();
+        setSize(countRowRequest);
+
+        // we need to close the connection here
+        // otherwise the connection will not be free.
+        if (this.size() == 0) {
+            try {
+                this.request.close();
+            } catch (SitoolsException ex) {
+                LOG.log(Level.SEVERE, null, ex);
+            }
+        }
+    }
+    
+    
+    
+}
diff --git a/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/representation/VOTableRepresentation.java b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/representation/VOTableRepresentation.java
new file mode 100644
index 0000000..578b435
--- /dev/null
+++ b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/representation/VOTableRepresentation.java
@@ -0,0 +1,191 @@
+ /*******************************************************************************
+ * Copyright 2010-2013 CNES - CENTRE NATIONAL d'ETUDES SPATIALES
+ *
+ * This file is part of SITools2.
+ *
+ * SITools2 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * SITools2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with SITools2.  If not, see <http://www.gnu.org/licenses/>.
+ ******************************************************************************/
+package fr.ias.sitools.vo.representation;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.restlet.data.LocalReference;
+import org.restlet.data.MediaType;
+import org.restlet.ext.freemarker.TemplateRepresentation;
+import org.restlet.representation.OutputRepresentation;
+import org.restlet.representation.Representation;
+import org.restlet.resource.ClientResource;
+
+/**
+ * Creates a VOTable representation with a template and a data model. The data model is the following :
+ * <pre>
+ * root
+ *    |__ description
+ *    |__ infos
+ *    |      |__ id
+ *    |      |__ name (required)
+ *    |      |__ valueAttribute (required)
+ *    |      |__ xtype
+ *    |      |__ ref
+ *    |      |__ unit
+ *    |      |__ ucd
+ *    |      |__ utype
+ *    |      |__ value
+ *    |__ params (List)
+ *    |      |__ param
+ *    |           |__ id
+ *    |           |__ unit
+ *    |           |__ datatype (required)
+ *    |           |__ precision
+ *    |           |__ width
+ *    |           |__ xtype
+ *    |           |__ ref
+ *    |           |__ name (required)
+ *    |           |__ ucd
+ *    |           |__ utype
+ *    |           |__ arraysize
+ *    |           |__ value (required)
+ *    |           |__ DESCRIPTION
+ *    |           |__ VALUES
+ *    |                 |__ id
+ *    |                 |__ type
+ *    |                 |__ null
+ *    |                 |__ ref
+ *    |                 |__ OPTION (List)
+ *    |                        |__ option
+ *    |                               |__ name
+ *    |                               |__ value (required)
+ *    |__ fields (List)
+ *    |      |__ field
+ *    |           |__ DESCRIPTION
+ *    |           |__ id
+ *    |           |__ name (required)
+ *    |           |__ ucd
+ *    |           |__ utype
+ *    |           |__ ref
+ *    |           |__ datatype (required)
+ *    |           |__ width
+ *    |           |__ precision
+ *    |           |__ unit
+ *    |           |__ type
+ *    |           |__ xtype
+ *    |           |__ arraysize
+ *    |__ rows (List) (required)
+ *    |     |__ row (required)
+ *    |
+ *    |__ sqlColAlias (List) (required)
+ *    |      |__ sqlcol (required)
+ *    |__ mappingColAliasConceptSql (Hash) (optional)
+ *    |__ siaCut (boolean, optional)
+ *    |__ nrows (optional)
+ *    |__ mapPartFileCutUrl (Hash) (optional)
+ *    |__ primaryKey (optional)
+ *    |__ queryParams (POS,SIZE,...)
+ *    |__ queryInfos (Query status)
+ *
+ * </pre> Provide a VOTable representation by streaming based on Freemarker To have a dataModel by streaming, dataModel for rows element
+ * must use the DatabaseRequestModel adapter
+ *
+ * @author Jean-Christophe Malapert <jean-christophe.malapert@cnes.fr>
+ */
+public class VOTableRepresentation extends OutputRepresentation {
+
+  /**
+   * Logger.
+   */
+  private static final Logger LOG = Logger.getLogger(VOTableRepresentation.class.getName());
+  /**
+   * Default template file = votable.ftl.
+   */
+  public static final String DEFAULT_TEMPLATE = "votable.ftl";
+  /**
+   * Data model that contains the information to represent.
+   */
+  private Map dataModel;
+  /**
+   * Template file.
+   */
+  private String ftl;
+
+  /**
+   * Creates a VOTableRepresentation based on a dataModel and a templateFile.
+   *
+   * @param dataModelVal DataModel
+   * @param ftlVal template File
+   */
+  public VOTableRepresentation(final Map dataModelVal, final String ftlVal) {
+    super(MediaType.TEXT_XML);
+    setDataModel(dataModelVal);
+    setFtl(ftlVal);
+  }
+  /**
+   * Creates a GeoJson representation with the default template (<code>DEFAULT_TEMPLATE</code>).
+   *
+   * @param dataModelVal the data model
+   */
+  public VOTableRepresentation(final Map dataModelVal) {
+    this(dataModelVal, DEFAULT_TEMPLATE);
+  }
+  /**
+   * Writes the representation.
+   *
+   * @param outputStream output stream
+   * @throws IOException Exception
+   */
+  @Override
+  public final void write(final OutputStream outputStream) throws IOException {
+    final Representation metadataFtl = new ClientResource(LocalReference.createClapReference(getClass().getPackage()) + "/"
+            + getFtl()).get();       
+    final TemplateRepresentation tpl = new TemplateRepresentation(metadataFtl, getDataModel(), getMediaType());    
+    LOG.log(Level.FINEST, getFtl(), tpl);
+    outputStream.write(tpl.getText().getBytes());
+    outputStream.flush();
+  }
+
+
+    /**
+     * Returns the data model.
+     * @return the dataModel
+     */
+    protected final Map getDataModel() {
+        return dataModel;
+    }
+
+    /**
+     * Sets the data model.
+     * @param dataModelVal the dataModel to set
+     */
+    protected final void setDataModel(final Map dataModelVal) {
+        this.dataModel = dataModelVal;
+    }
+
+    /**
+     * Returns the template filename.
+     * @return the ftl
+     */
+    protected final String getFtl() {
+        return ftl;
+    }
+
+    /**
+     * Sets the template filename.
+     * @param ftlVal the ftl to set
+     */
+    protected final void setFtl(final String ftlVal) {
+        this.ftl = ftlVal;
+    }
+}
diff --git a/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/representation/votable.ftl b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/representation/votable.ftl
new file mode 100644
index 0000000..f2d7390
--- /dev/null
+++ b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/representation/votable.ftl
@@ -0,0 +1,78 @@
+<?xml version="1.0" ?>
+<VOTABLE version="1.2" xmlns="http://www.ivoa.net/xml/VOTable/v1.2">
+    <RESOURCE type="results">
+    <#if description?exists><DESCRIPTION>${description}</DESCRIPTION></#if>
+    <#if queryInfos?exists>
+        <#list queryInfos as queryInfo>
+            <INFO<#if queryInfo.id?exists> ID="${queryInfo.id}"</#if> name="${queryInfo.name}" value="${queryInfo.valueAttribute}"<#if queryInfo.xtype?exists> xtype="${queryInfo.xtype}"</#if><#if queryInfo.unit?exists> unit="${queryInfo.unit}"</#if><#if queryInfo.ucd?exists> ucd="${queryInfo.ucd}"</#if><#if queryInfo.utype?exists> utype="${queryInfo.utype}"</#if> />
+        </#list>
+    </#if>
+    <#if queryParams?exists>
+        <#list queryParams as queryParam>
+            <PARAM<#if queryParam.id?exists> ID="${queryParam.id}"</#if> name="${queryParam.name}" datatype="${queryParam.datatype.value()}" <#if queryParam.xtype?exists> xtype="${queryParam.xtype}"</#if><#if queryParam.unit?exists> unit="${queryParam.unit}"</#if><#if queryParam.ucd?exists> ucd="${queryParam.ucd}"</#if><#if queryParam.utype?exists> utype="${queryParam.utype}"</#if> value="${queryParam.value}"/>
+        </#list>
+    </#if>
+    <#if infos?exists>
+        <#list infos as info>
+            <INFO<#if info.id?exists> ID="${info.id}"</#if> name="${info.name}" value="${info.valueAttribute}"<#if info.xtype?exists> xtype="${info.xtype}"</#if><#if info.ref?exists> ref="${info.ref}"</#if><#if info.unit?exists> unit="${info.unit}"</#if><#if info.ucd?exists> ucd="${info.ucd}"</#if><#if info.utype?exists> utype="${info.utype}"</#if> />
+        </#list>
+    </#if>
+    <#if params?exists>
+        <#list params as param>
+            <#if param.DESCRIPTION?exists>
+                <PARAM<#if param.id?exists> ID="${param.id}"</#if> name="${param.name}" <#if param.unit?exists> unit="${param.unit}"</#if> datatype="${param.datatype.value()}"<#if param.precision?exists> precision="${param.precision}"</#if><#if param.width?exists> ID="${param.width}"</#if><#if param.xtype?exists> xtype="${param.xtype}"</#if><#if param.ref?exists> ref="${param.ref}"</#if><#if param.ucd?exists> ucd="${param.ucd}"</#if><#if param.utype?exists> utype="${param.utype}"</#if><#if param.arraysize?exists> arraysize="${param.arraysize}"</#if> value="${param.value}">
+                    <DESCRIPTION>
+                    <#list param.DESCRIPTION.content as description>
+                        ${description}
+                    </#list>
+                    </DESCRIPTION>
+                <#if param.VALUES?exists>
+                    <VALUES<#if param.VALUES.id?exists> ID="${param.VALUES.id}"</#if><#if param.VALUES.type?exists> type="${param.VALUES.type}"</#if><#if param.VALUES.null?exists> null="${param.VALUES.null}"</#if><#if param.VALUES.ref?exists> ref="${param.VALUES.ref}"</#if>>
+                    <#if param.VALUES.OPTION?exists>
+                    <#list param.VALUES.OPTION as option>
+                        <OPTION<#if option.name?exists> name="${option.name}"</#if> value="${option.value}"/>
+                    </#list>
+                    </#if>
+                    </VALUES>
+                </#if>
+                </PARAM>
+            <#else>
+                <PARAM<#if param.id?exists> ID="${param.id}"</#if> name="${param.name}" <#if param.unit?exists> unit="${param.unit}"</#if> datatype="${param.datatype.value()}"<#if param.precision?exists> precision="${param.precision}"</#if><#if param.width?exists> ID="${param.width}"</#if><#if param.xtype?exists> xtype="${param.xtype}"</#if><#if param.ref?exists> ref="${param.ref}"</#if><#if param.ucd?exists> ucd="${param.ucd}"</#if><#if param.utype?exists> utype="${param.utype}"</#if><#if param.arraysize?exists> arraysize="${param.arraysize}"</#if> value="${param.value}"/>
+            </#if>
+        </#list>
+    </#if>
+    <#if fields?exists>
+        <#list fields as field> 
+            <#if field.DESCRIPTION?exists>
+                <FIELD<#if field.id?exists> ID="${field.id}</#if> name="${field.name}"<#if field.ucd?exists> ucd="${field.ucd}"</#if><#if field.utype?exists> utype="${field.utype}"</#if><#if field.ref?exists> ref="${field.ref}"</#if><#if field.datatype?exists> datatype="${field.datatype.value()}"</#if><#if field.width?exists> width="${field.width}"</#if><#if field.precision?exists> precision="${field.precision}"</#if><#if field.unit?exists> unit="${field.unit}"</#if><#if field.type?exists> type="${field.type}"</#if><#if field.xtype?exists> xtype="${field.xtype}"</#if><#if field.arraysize?exists> arraysize="${field.arraysize}"</#if>>
+                    <DESCRIPTION>
+                    <#list field.DESCRIPTION.content as description>
+                        ${description}
+                    </#list>
+                    </DESCRIPTION>
+                </FIELD>
+            <#else>
+                <FIELD<#if field.id?exists> ID="${field.id}</#if> name="${field.name}"<#if field.ucd?exists> ucd="${field.ucd}"</#if><#if field.utype?exists> utype="${field.utype}"</#if><#if field.ref?exists> ref="${field.ref}"</#if><#if field.datatype?exists> datatype="${field.datatype.value()}"</#if><#if field.width?exists> width="${field.width}"</#if><#if field.precision?exists> precision="${field.precision}"</#if><#if field.unit?exists> unit="${field.unit}"</#if><#if field.type?exists> type="${field.type}"</#if><#if field.xtype?exists> xtype="${field.xtype}"</#if><#if field.arraysize?exists> arraysize="${field.arraysize}"</#if> />
+            </#if>
+        </#list>
+    </#if>
+    <#if rows?exists>
+    <#if nrows != 0>
+    <TABLE<#if nrows?exists> nrows="${nrows}"</#if>>
+    <DATA>
+        <TABLEDATA>
+        <#list rows as row>
+        <TR>
+            <#list sqlColAlias as sqlcol>
+            <#if row["${sqlcol}"] == "null"><TD> <#if sqlcol?exists> header : ${sqlcol}</#if></TD><#else><TD>${row["${sqlcol}"]}</TD></#if>
+            </#list>
+        </TR>
+        </#list>
+        </TABLEDATA>
+    </DATA>
+    </TABLE>
+    </#if>
+    </#if>
+    
+    </RESOURCE>
+</VOTABLE>
\ No newline at end of file
diff --git a/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/ssa/AbstractSqlGeometryConstraint.java b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/ssa/AbstractSqlGeometryConstraint.java
new file mode 100644
index 0000000..30f8222
--- /dev/null
+++ b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/ssa/AbstractSqlGeometryConstraint.java
@@ -0,0 +1,229 @@
+ /*******************************************************************************
+ * Copyright 2010-2013 CNES - CENTRE NATIONAL d'ETUDES SPATIALES
+ *
+ * This file is part of SITools2.
+ *
+ * SITools2 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * SITools2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with SITools2.  If not, see <http://www.gnu.org/licenses/>.
+ ******************************************************************************/
+package fr.ias.sitools.vo.ssa;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.logging.Logger;
+
+/**
+ * Interface to define a SQL spatial constraint.
+ * @author Jean-Christophe Malapert <jean-christophe.malapert@cnes.fr>
+ */
+public abstract class AbstractSqlGeometryConstraint {
+    
+    /**
+     * LOGGER
+     */
+     private static final Logger LOG = Logger.getLogger(AbstractSqlGeometryConstraint.class.getName());
+
+  /**
+   * Index where the min value of a range is located.
+   */
+  protected static final int MIN = 0;
+  /**
+   * Index where the max value of a range is located.
+   */
+  protected static final int MAX = 1;
+
+  /**
+   * Size parameter given by the user.
+   */
+  private transient double[] sizeArray = new double[2];
+  /**
+   * Central position along right ascension axis.
+   */
+  private transient double raUser;
+  /**
+   * Central position along declination axis.
+   */
+  private transient double decUser;
+  /**
+   * time.
+   */
+  private transient String[] timeUser = new String[2];
+  /**
+   * band.
+   */
+  private transient double[] bandUser = new double[2];
+
+  /**
+   * Sets the geometry attribute.
+   * @param geometry the geometry attribute
+   */
+  public abstract void setGeometry(final Object geometry);
+
+  /**
+   * Sets user input parameters.
+   * @param inputParameters user input parameters
+   */
+  public final void setInputParameters(final SimpleSpectralAccessInputParameters inputParameters) {
+    this.raUser = inputParameters.getRa();
+    this.decUser = inputParameters.getDec();
+    if (inputParameters.getBand().length == 2) {
+        this.bandUser = inputParameters.getBand();
+    }else{
+        this.bandUser[0] = inputParameters.getBand()[0];
+        this.bandUser[1] = inputParameters.getBand()[0];
+    }
+    if (inputParameters.getTime().length == 2) {
+        this.timeUser = inputParameters.getTime();
+    }else{
+        
+        this.timeUser[0] = inputParameters.getTime()[0];
+        this.timeUser[1] = inputParameters.getTime()[0];
+    }
+    if (inputParameters.getSize().length == 2) {
+      this.sizeArray = inputParameters.getSize();
+    } else { 
+      this.sizeArray[0] = inputParameters.getSize()[0];
+      this.sizeArray[1] = inputParameters.getSize()[0];
+    }
+  }
+
+  /**
+   * Detects when the SSA request has a collition with South pole.
+   * @return True when the SSA request has a collition with South pole otherwise False
+   */
+  protected final boolean isSouthPoleCollision() {
+    return (decUser - sizeArray[1] / 2.0 <= SimpleSpectralAccessProtocolLibrary.MIN_VALUE_FOR_DECLINATION) ? true : false;
+  }
+
+  /**
+   * Detects when the SSA request has a collition with North pole.
+   * @return True when the SSA request has a collition with North pole otherwise False
+   */
+  protected final boolean isNorthPoleCollision() {
+    return (decUser + sizeArray[1] / 2.0 >= SimpleSpectralAccessProtocolLibrary.MAX_VALUE_FOR_DECLINATION) ? true : false;
+  }
+
+  /**
+   * Detects when the SSA request has a collition with both North and South pole.
+   * @return True when the SSA request has a collition with both North and South pole otherwise False
+   */
+  protected final boolean isPolesCollision() {
+    return (isNorthPoleCollision() && isSouthPoleCollision()) ? true : false;
+  }
+
+  /**
+   * Detects when the SSA request is a large polygon.
+   *
+   * <p>
+   * A large polygon is a polygon where two points is separated by MAX_VALUE_FOR_RIGHT_ASCENSION / 2.0
+   * along right ascension axis.
+   * </p>
+   * @return True when the SSA request is a large polygon otherwise False
+   */
+  protected final boolean isLargePolygon() {
+    return (sizeArray[0] >= SimpleSpectralAccessProtocolLibrary.MAX_VALUE_FOR_RIGHT_ASCENSION / 2.0) ? true : false;
+  }
+
+  /**
+   * Detects there is a collision with RA=MAX_VALUE_FOR_RIGHT_ASCENSION.
+   * @return True when there is a collision with RA=MAX_VALUE_FOR_RIGHT_ASCENSION otherwise False
+   */
+  protected final boolean isMaxRaCollision() {
+    return (raUser + sizeArray[0] / 2.0 >= SimpleSpectralAccessProtocolLibrary.MAX_VALUE_FOR_RIGHT_ASCENSION) ? true : false;
+  }
+
+  /**
+   * Detects there is a collision with RA=MIN_VALUE_FOR_RIGHT_ASCENSION.
+   * @return True when there is a collision with RA=MIN_VALUE_FOR_RIGHT_ASCENSION otherwise False
+   */
+  protected final boolean isMinRaCollision() {
+    return (raUser - sizeArray[0] / 2.0 <= SimpleSpectralAccessProtocolLibrary.MIN_VALUE_FOR_RIGHT_ASCENSION) ? true : false;
+  }
+
+  /**
+   * Detects if the SSA request has a collision with the border of CAR projection centered on 0,0.
+   * @return True when the SSA request has a collision with the borders otherwise False
+   */
+  protected final boolean isBorderRaCollision() {
+    return (isMinRaCollision() && isMaxRaCollision()) ? true : false;
+  }
+
+  /**
+   * Detects if the SSA request is a ring on the sphere.
+   * @return True when the SSA request is a ring otherwise False
+   */
+  protected final boolean isRing() {
+    return (sizeArray[0] == SimpleSpectralAccessProtocolLibrary.MAX_VALUE_FOR_RIGHT_ASCENSION) ? true : false;
+  }
+
+  /**
+   * SQL geometry predicat to add to the SQL constraint.
+   * @return SQL geometry predicat
+   */
+  public abstract String getSqlPredicat();
+
+  /**
+   * Computes ranges of the SSA request along right ascension and declination axes.
+   *
+   * <p>
+   * For the declination axis, returns [decmin, decmax].<br/>
+   * For the right ascension axis, returns List<Double[]>. The ranges are computed
+   * based on the CAR projection.
+   * </p>
+   *
+   * @return an array [List<Ra[min,max]>, Dec[min,max])
+   */
+  protected final Object computeRange() {
+    final List<Double[]> raRange = new ArrayList<Double[]>();
+    final double[] decRange = new double[2];
+    if (this.isPolesCollision()) {
+      decRange[MIN] = SimpleSpectralAccessProtocolLibrary.MIN_VALUE_FOR_DECLINATION;
+      decRange[MAX] = SimpleSpectralAccessProtocolLibrary.MAX_VALUE_FOR_DECLINATION;
+      raRange.add(new Double[]{SimpleSpectralAccessProtocolLibrary.MIN_VALUE_FOR_RIGHT_ASCENSION, SimpleSpectralAccessProtocolLibrary.MAX_VALUE_FOR_RIGHT_ASCENSION});
+    } else if (this.isNorthPoleCollision()) {
+      decRange[MIN] = decUser - sizeArray[1] / 2.0;
+      decRange[MAX] = SimpleSpectralAccessProtocolLibrary.MAX_VALUE_FOR_DECLINATION;
+      raRange.add(new Double[]{SimpleSpectralAccessProtocolLibrary.MIN_VALUE_FOR_RIGHT_ASCENSION, SimpleSpectralAccessProtocolLibrary.MAX_VALUE_FOR_RIGHT_ASCENSION});
+    } else if (this.isSouthPoleCollision()) {
+      decRange[MIN] = SimpleSpectralAccessProtocolLibrary.MIN_VALUE_FOR_DECLINATION;
+      decRange[MAX] = decUser + sizeArray[1] / 2.0;
+      raRange.add(new Double[]{SimpleSpectralAccessProtocolLibrary.MIN_VALUE_FOR_RIGHT_ASCENSION, SimpleSpectralAccessProtocolLibrary.MAX_VALUE_FOR_RIGHT_ASCENSION});
+    } else {
+      decRange[MIN] = decUser - sizeArray[1] / 2.0;
+      decRange[MAX] = decUser + sizeArray[1] / 2.0;
+      if (this.isBorderRaCollision()) {
+        raRange.add(new Double[]{SimpleSpectralAccessProtocolLibrary.MIN_VALUE_FOR_RIGHT_ASCENSION,
+                                 SimpleSpectralAccessProtocolLibrary.MAX_VALUE_FOR_RIGHT_ASCENSION});
+      } else if (this.isMaxRaCollision()) {
+        raRange.add(new Double[]{raUser - sizeArray[0] / 2.0,
+                                 SimpleSpectralAccessProtocolLibrary.MAX_VALUE_FOR_RIGHT_ASCENSION});
+        raRange.add(new Double[]{SimpleSpectralAccessProtocolLibrary.MIN_VALUE_FOR_RIGHT_ASCENSION,
+                                (raUser + sizeArray[0] / 2.0 + SimpleSpectralAccessProtocolLibrary.MAX_VALUE_FOR_RIGHT_ASCENSION) % SimpleSpectralAccessProtocolLibrary.MAX_VALUE_FOR_RIGHT_ASCENSION});
+      } else if (this.isMinRaCollision()) {
+        raRange.add(new Double[]{SimpleSpectralAccessProtocolLibrary.MIN_VALUE_FOR_RIGHT_ASCENSION,
+                                raUser + sizeArray[0] / 2.0});
+        raRange.add(new Double[]{(raUser - sizeArray[0] / 2.0 + SimpleSpectralAccessProtocolLibrary.MAX_VALUE_FOR_RIGHT_ASCENSION) % SimpleSpectralAccessProtocolLibrary.MAX_VALUE_FOR_RIGHT_ASCENSION,
+                                  SimpleSpectralAccessProtocolLibrary.MAX_VALUE_FOR_RIGHT_ASCENSION});
+      } else {
+        raRange.add(new Double[]{(raUser - sizeArray[0] / 2.0 + SimpleSpectralAccessProtocolLibrary.MAX_VALUE_FOR_RIGHT_ASCENSION) % SimpleSpectralAccessProtocolLibrary.MAX_VALUE_FOR_RIGHT_ASCENSION,
+                                 (raUser + sizeArray[0] / 2.0 + SimpleSpectralAccessProtocolLibrary.MAX_VALUE_FOR_RIGHT_ASCENSION) % SimpleSpectralAccessProtocolLibrary.MAX_VALUE_FOR_RIGHT_ASCENSION});
+      }
+    }
+    return Arrays.asList(raRange, decRange);
+  }
+  protected final Object computeTimeAndBandRange() {
+   
+   return Arrays.asList(timeUser, bandUser);
+  }
+}
\ No newline at end of file
diff --git a/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/ssa/CenterModeIntersection.java b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/ssa/CenterModeIntersection.java
new file mode 100644
index 0000000..4b933d1
--- /dev/null
+++ b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/ssa/CenterModeIntersection.java
@@ -0,0 +1,125 @@
+ /*******************************************************************************
+ * Copyright 2010-2013 CNES - CENTRE NATIONAL d'ETUDES SPATIALES
+ *
+ * This file is part of SITools2.
+ *
+ * SITools2 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * SITools2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with SITools2.  If not, see <http://www.gnu.org/licenses/>.
+ ******************************************************************************/
+package fr.ias.sitools.vo.ssa;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+  /**
+   * Constructs SQL predicat for Center mode intersection.
+   */
+  public class CenterModeIntersection extends AbstractSqlGeometryConstraint {
+    /**
+     * LOGGER
+     */
+     private static final Logger LOG = Logger.getLogger(CenterModeIntersection.class.getName());
+    /**
+     * Right ascension attribut.
+     */
+    private transient String raCol;
+    /**
+     * Declination attribut.
+     */
+    private transient String decCol;
+    /**
+     * Time attribut.
+     */
+    private transient String timeCol;
+    /**
+     * Band attribut.
+     */
+    private transient String bandCol;
+
+    @Override
+    public final void setGeometry(final Object geometry) {
+
+      if (geometry instanceof String[]) {
+        final String[] geometryArray = (String[]) geometry;
+        
+        if (geometryArray.length != 4) {
+          throw new IllegalArgumentException("geometry must be an array of four elements that contains racolName, decColName, timeColName and bandColName");
+        } else {
+          this.raCol = geometryArray[0];
+          this.decCol = geometryArray[1];
+          this.timeCol = geometryArray[2];
+          this.bandCol = geometryArray[3];
+        }
+      } else {
+        throw new IllegalArgumentException("geometry must be an array of four elements that contains racolName, decColName, timeColName and bandColName");
+      }
+    }
+
+    @Override
+    public final String getSqlPredicat() {
+      if (isPolesCollision()) {
+        return null;
+      }
+      final List rangeSsa = (List) computeTimeAndBandRange();
+      
+      final String[] timeRange = (String[]) rangeSsa.get(0);
+      final double[] bandRange = (double[]) rangeSsa.get(1);
+      
+      
+      final List ranges = (List) computeRange();
+      final List<Double[]> raRanges = (List<Double[]>) ranges.get(0);
+      final double[] decRange = (double[]) ranges.get(1);
+      String predicatDefinition;
+      if (raRanges.size() == 1) {
+        final Double[] raRange = raRanges.get(0);
+        predicatDefinition = String.format(" AND ( %s BETWEEN %s AND %s ) AND ( %s BETWEEN %s AND %s )", decCol, decRange[0], decRange[1], raCol, raRange[0], raRange[1]);
+      } else {
+        final Double[] raRange1 = raRanges.get(0);
+        final Double[] raRange2 = raRanges.get(1);
+        predicatDefinition = String.format(" AND ( %s BETWEEN %s AND %s ) AND (( %s BETWEEN %s AND %s ) OR ( %s BETWEEN %s AND %s ))",
+                                             decCol, decRange[0], decRange[1],
+                                             raCol, raRange1[0], raRange1[1], raCol, raRange2[0], raRange2[1]);
+      }
+      
+      if(timeRange[0].equals(timeRange[1])){
+          timeRange[1] = addHourinTimeRange(timeRange[0]);
+      }
+      predicatDefinition += String.format(" AND ( %s BETWEEN %s AND %s ) AND ( %s BETWEEN '%s' AND '%s' )",
+                                             bandCol, bandRange[0], bandRange[1],timeCol, timeRange[0], timeRange[1]);
+      LOG.log(Level.SEVERE,"predicatDefinition : "+predicatDefinition);
+      return predicatDefinition;
+    }
+    
+    private String addHourinTimeRange(String timeTo){
+        String a = null;
+        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
+         try {
+             Date date = df.parse(timeTo);
+             Date newDate =  new Date(date.getTime()+TimeUnit.HOURS.toMillis(1));
+             a = newDate.toString();
+             LOG.log(Level.INFO," ************************  : newDate.toString : "+a);
+             LOG.log(Level.INFO," ************************  : newDate.toString : "+newDate.toGMTString());
+             LOG.log(Level.INFO," ************************  : newDate.toString : "+newDate.toLocaleString());
+         } catch (ParseException ex) {
+             Logger.getLogger(CenterModeIntersection.class.getName()).log(Level.SEVERE, null, ex);
+             a=timeTo;
+         }
+        
+        return a;
+    }
+  }
diff --git a/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/ssa/DataModelInterface.java b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/ssa/DataModelInterface.java
new file mode 100644
index 0000000..cbefa7f
--- /dev/null
+++ b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/ssa/DataModelInterface.java
@@ -0,0 +1,36 @@
+ /*******************************************************************************
+ * Copyright 2010-2013 CNES - CENTRE NATIONAL d'ETUDES SPATIALES
+ *
+ * This file is part of SITools2.
+ *
+ * SITools2 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * SITools2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with SITools2.  If not, see <http://www.gnu.org/licenses/>.
+ ******************************************************************************/
+package fr.ias.sitools.vo.ssa;
+
+import java.util.Map;
+
+/**
+ * Provides an interface to get the data model.
+ *
+ * @author Jean-Christophe Malapert
+ */
+public interface DataModelInterface {
+
+  /**
+   * Returns the data model.
+   *
+   * @return data model
+   */
+  Map getDataModel();
+}
diff --git a/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/ssa/OverlapsModeIntersection.java b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/ssa/OverlapsModeIntersection.java
new file mode 100644
index 0000000..7460a9b
--- /dev/null
+++ b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/ssa/OverlapsModeIntersection.java
@@ -0,0 +1,193 @@
+ /*******************************************************************************
+ * Copyright 2010-2013 CNES - CENTRE NATIONAL d'ETUDES SPATIALES
+ *
+ * This file is part of SITools2.
+ *
+ * SITools2 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * SITools2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with SITools2.  If not, see <http://www.gnu.org/licenses/>.
+ ******************************************************************************/
+package fr.ias.sitools.vo.ssa;
+
+import fr.cnes.sitools.searchgeometryengine.Resampling;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Constructs SQL predicat for Overlaps mode intersection.
+ * @author Jean-Christophe Malapert <jean-christophe.malapert@cnes.fr>
+ */
+public class OverlapsModeIntersection extends AbstractSqlGeometryConstraint {
+  /**
+   * Logger.
+   */
+  private static final Logger LOG = Logger.getLogger(OverlapsModeIntersection.class.getName());
+  /**
+   * Default value for resampling along right ascension axis.
+   */
+  private static final double DEFAULT_SAMPLING_VALUE_RA = 20;
+  /**
+   * Default value for resampling along declination axis.
+   */
+  private static final double DEFAULT_SAMPLING_VALUE_DEC = 20;
+  /**
+   * geometry attribut.
+   */
+  private transient String geomCol;
+
+  @Override
+  public final void setGeometry(final Object geometry) {
+    if (geometry instanceof String) {
+      this.geomCol = String.valueOf(geometry);
+    }else if(geometry instanceof List) {
+      
+    } else {
+      throw new IllegalArgumentException("geometry must be a String");
+    }
+    /* } else {
+      throw new IllegalArgumentException("geometry must be a String");
+    }*/
+  }
+
+  @Override
+  public final String getSqlPredicat() {
+    if (this.isPolesCollision()) {
+      return null;
+    }
+
+    final List ranges = (List) computeRange();
+    final List<Double[]> raRanges = (List<Double[]>) ranges.get(0);
+    final double[] decRange = (double[]) ranges.get(1);
+
+    String predicatDefinition;
+    if (isNorthPoleCollision()) {
+      LOG.log(Level.FINEST, "North collision case");
+      predicatDefinition = String.format(" AND (spoly_overlap_polygon(%s,'{(%sd,%sd),(%sd,%sd),(%sd,%sd)}')", geomCol, 0.0, decRange[0], 45.0, 90.0, 90.0, decRange[0]);
+      predicatDefinition = predicatDefinition.concat(String.format(" OR spoly_overlap_polygon(%s,'{(%sd,%sd),(%sd,%sd),(%sd,%sd)}')", geomCol, 90.0, decRange[MIN], 135.0, 90.0, 180.0, decRange[MIN]));
+      predicatDefinition = predicatDefinition.concat(String.format(" OR spoly_overlap_polygon(%s,'{(%sd,%sd),(%sd,%sd),(%sd,%sd)}')", geomCol, 180.0, decRange[MIN], 225.0, 90.0, 270.0, decRange[MIN]));
+      predicatDefinition = predicatDefinition.concat(String.format(" OR spoly_overlap_polygon(%s,'{(%sd,%sd),(%sd,%sd),(%sd,%sd)}'))", geomCol, 270.0, decRange[MIN], 325.0, 90.0, 360.0, decRange[MIN]));
+      LOG.log(Level.FINEST, predicatDefinition);
+
+    } else if (isSouthPoleCollision()) {
+      LOG.log(Level.FINEST, "South collision case");
+      predicatDefinition = String.format(" AND (spoly_overlap_polygon(%s,'{(%sd,%sd),(%sd,%sd),(%sd,%sd)}')", geomCol, 0.0, decRange[MAX], 45.0, -90.0, 90.0, decRange[MAX]);
+      predicatDefinition = predicatDefinition.concat(String.format(" OR spoly_overlap_polygon(%s,'{(%sd,%sd),(%sd,%sd),(%sd,%sd)}')", geomCol, 90.0, decRange[MAX], 135.0, -90.0, 180.0, decRange[MAX]));
+      predicatDefinition = predicatDefinition.concat(String.format(" OR spoly_overlap_polygon(%s,'{(%sd,%sd),(%sd,%sd),(%sd,%sd)}')", geomCol, 180.0, decRange[MAX], 225.0, -90.0, 270.0, decRange[MAX]));
+      predicatDefinition = predicatDefinition.concat(String.format(" OR spoly_overlap_polygon(%s,'{(%sd,%sd),(%sd,%sd),(%sd,%sd)}'))", geomCol, 270.0, decRange[MAX], 325.0, -90.0, 360.0, decRange[MAX]));
+      LOG.log(Level.FINEST, predicatDefinition);
+
+    } else if (isRing()) {
+      LOG.log(Level.FINEST, "Ring case");
+      predicatDefinition = String.format(" AND (spoly_overlap_polygon(%s,'{(%sd,%sd),(%sd,%sd),(%sd,%sd), (%sd,%sd)}')", geomCol, 0.0, decRange[MIN], 90.0, decRange[MIN], 90.0, decRange[MAX], 0.0, decRange[MAX]);
+      predicatDefinition = predicatDefinition.concat(String.format(" OR spoly_overlap_polygon(%s,'{(%sd,%sd),(%sd,%sd),(%sd,%sd), (%sd,%sd)}')", geomCol, 90.0, decRange[MIN], 180.0, decRange[MIN], 180.0, decRange[MAX], 90.0, decRange[MAX]));
+      predicatDefinition = predicatDefinition.concat(String.format(" OR spoly_overlap_polygon(%s,'{(%sd,%sd),(%sd,%sd),(%sd,%sd), (%sd,%sd)}')", geomCol, 180.0, decRange[MIN], 270.0, decRange[MIN], 270.0, decRange[MAX], 180.0, decRange[MAX]));
+      predicatDefinition = predicatDefinition.concat(String.format(" OR spoly_overlap_polygon(%s,'{(%sd,%sd),(%sd,%sd),(%sd,%sd), (%sd,%sd)}'))", geomCol, 270.0, decRange[MIN], 0.0, decRange[MIN], 0.0, decRange[MAX], 270.0, decRange[MAX]));
+      LOG.log(Level.FINEST, predicatDefinition);
+
+    } else if (raRanges.size() == 1 && isLargePolygon()) {
+      LOG.log(Level.FINEST, "Large polygon case");
+      final Double[] raRange1 = raRanges.get(0);
+      final double mean = (raRange1[MIN] + raRange1[MAX]) / 2.0;
+      raRanges.add(new Double[]{mean, raRange1[MAX]});
+      raRanges.set(0, new Double[]{raRange1[MIN], mean});
+      predicatDefinition = buildMultiPolygon(raRanges, decRange);
+      LOG.log(Level.FINEST, predicatDefinition);
+    } else {
+      LOG.log(Level.FINEST, "other case");
+      predicatDefinition = buildMultiPolygon(raRanges, decRange);
+      LOG.log(Level.FINEST, predicatDefinition);
+    }
+    return predicatDefinition;
+  }
+
+  /**
+   * Builds a multi-polygon syntax for PgSphere based on a set right ascension ranges and a declination range.
+   *
+   * <p>
+   * A range is an array that is composed of two values : min and max value.
+   * </p>
+   *
+   * @param raRanges set of right ascension ranges
+   * @param decRange declination range
+   * @return the SQL predicat
+   */
+  private String buildMultiPolygon(final List<Double[]> raRanges, final double[] decRange) {
+    final StringBuilder stringBuilder = new StringBuilder(" AND (");
+    buildPolygon(stringBuilder, raRanges.get(0), decRange);
+    if (raRanges.size() == 2) {
+      stringBuilder.append(" OR ");
+      buildPolygon(stringBuilder, raRanges.get(1), decRange);
+    }
+    stringBuilder.append(")");
+    return stringBuilder.toString();
+  }
+
+  /**
+   * Build a polygon syntax for PgSphere based on the SQL predicat to complete, the right ascension and declination range.
+   * <p>
+   * A range is an array that is composed of two values : min and max value.
+   * </p>
+   * @param stringBuilder SQL predicat to complete
+   * @param raRange right ascension range [min,max]
+   * @param decRange declination range [min,max]
+   */
+  private void buildPolygon(final StringBuilder stringBuilder, final Double[] raRange, final double[] decRange) {
+    stringBuilder.append(String.format("spoly_overlap_polygon(%s,'{", geomCol));
+    final double[] pointsRa = Resampling.hourCircle(raRange[MIN], raRange[MAX], DEFAULT_SAMPLING_VALUE_RA);
+    final double[] pointsDec = Resampling.decCircle(decRange[MIN], decRange[MAX], DEFAULT_SAMPLING_VALUE_DEC);
+    buildRaLine(stringBuilder, pointsRa, decRange[MIN], false);
+    buildDecLine(stringBuilder, pointsDec, raRange[MAX], false);
+    buildRaLine(stringBuilder, pointsRa, decRange[MAX], true);
+    buildDecLine(stringBuilder, pointsDec, raRange[MIN], true);
+    stringBuilder.deleteCharAt(stringBuilder.length() - 1);
+    stringBuilder.append("}')");
+  }
+
+  /**
+   * Builds a line of the polygon for the SIAP request along the right ascension axis.
+   * @param stringBuilder polygon to complete
+   * @param raCoordinates values in the line along right ascension axis
+   * @param staticDecCoordinate constant declination.
+   * @param isReverseOrder indicates if the order where <code>raCoordinates</code> array must be read
+   */
+  private void buildRaLine(final StringBuilder stringBuilder, final double[] raCoordinates, final double staticDecCoordinate, final boolean isReverseOrder) {
+    if (isReverseOrder) {
+      for (int i = raCoordinates.length - 1; i > 0; i--) {
+        stringBuilder.append(String.format("(%sd,%sd),", raCoordinates[i], staticDecCoordinate));
+      }
+    } else {
+      for (int i = 0; i < raCoordinates.length - 1; i++) {
+        stringBuilder.append(String.format("(%sd,%sd),", raCoordinates[i], staticDecCoordinate));
+      }
+    }
+  }
+
+    /**
+   * Builds a line of the polygon for the SIAP request along the declination axis.
+   * @param stringBuilder polygon to complete
+   * @param decCoordinates values in the line along declination axis
+   * @param staticRaCoordinate constant right ascension.
+   * @param isReverseOrder indicates if the order where <code>raCoordinates</code> array must be read
+   */
+  private void buildDecLine(final StringBuilder stringBuilder, final double[] decCoordinates, final double staticRaCoordinate, final boolean isReverseOrder) {
+    if (isReverseOrder) {
+      for (int i = decCoordinates.length - 1; i > 0; i--) {
+        stringBuilder.append(String.format("(%sd,%sd),", staticRaCoordinate, decCoordinates[i]));
+      }
+    } else {
+      for (int i = 0; i < decCoordinates.length - 1; i++) {
+        stringBuilder.append(String.format("(%sd,%sd),", staticRaCoordinate, decCoordinates[i]));
+      }
+    }
+  }
+}
diff --git a/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/ssa/SimpleSpectralAccessDataModelInterface.java b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/ssa/SimpleSpectralAccessDataModelInterface.java
new file mode 100644
index 0000000..2069de3
--- /dev/null
+++ b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/ssa/SimpleSpectralAccessDataModelInterface.java
@@ -0,0 +1,33 @@
+ /*******************************************************************************
+ * Copyright 2010-2013 CNES - CENTRE NATIONAL d'ETUDES SPATIALES
+ *
+ * This file is part of SITools2.
+ *
+ * SITools2 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * SITools2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with SITools2.  If not, see <http://www.gnu.org/licenses/>.
+ ******************************************************************************/
+package fr.ias.sitools.vo.ssa;
+
+import java.util.Map;
+
+/**
+ * Interface for the use of a SIA.
+ * @author Jean-Christophe Malapert
+ */
+interface SimpleSpectralAccessDataModelInterface {
+  /**
+   * Returns the data model.
+   * @return the data model
+   */
+    Map getDataModel();
+}
diff --git a/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/ssa/SimpleSpectralAccessException.java b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/ssa/SimpleSpectralAccessException.java
new file mode 100644
index 0000000..e9cdb19
--- /dev/null
+++ b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/ssa/SimpleSpectralAccessException.java
@@ -0,0 +1,54 @@
+ /*******************************************************************************
+ * Copyright 2010-2013 CNES - CENTRE NATIONAL d'ETUDES SPATIALES
+ *
+ * This file is part of SITools2.
+ *
+ * SITools2 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * SITools2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with SITools2.  If not, see <http://www.gnu.org/licenses/>.
+ ******************************************************************************/
+package fr.ias.sitools.vo.ssa;
+
+/**
+ * Exception for graph package.
+ * @author Jean-Christophe Malapert <jean-christophe.malapert@cnes.fr>
+ */
+public class SimpleSpectralAccessException extends Exception {
+    /**
+     * Empty constructor.
+     */
+    public SimpleSpectralAccessException() {
+        super();
+    }
+    /**
+     * Constructs an Exception with a message.
+     * @param message message
+     */
+    public SimpleSpectralAccessException(final String message) {
+        super(message);
+    }
+    /**
+     * Constructs an Exception with a cause.
+     * @param cause cause
+     */
+    public SimpleSpectralAccessException(final Throwable cause) {
+        super(cause);
+    }
+    /**
+     * Constructs an Exception with a message and a cause.
+     * @param message message
+     * @param cause cause
+     */
+    public SimpleSpectralAccessException(final String message, final Throwable cause) {
+        super(message, cause);
+    }
+}
diff --git a/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/ssa/SimpleSpectralAccessInputParameters.java b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/ssa/SimpleSpectralAccessInputParameters.java
new file mode 100644
index 0000000..953f5b7
--- /dev/null
+++ b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/ssa/SimpleSpectralAccessInputParameters.java
@@ -0,0 +1,397 @@
+ /*******************************************************************************
+ * Copyright 2010-2013 CNES - CENTRE NATIONAL d'ETUDES SPATIALES
+ *
+ * This file is part of SITools2.
+ *
+ * SITools2 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * SITools2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with SITools2.  If not, see <http://www.gnu.org/licenses/>.
+ ******************************************************************************/
+package fr.ias.sitools.vo.ssa;
+
+import fr.cnes.sitools.dataset.DataSetApplication;
+import fr.cnes.sitools.extensions.common.InputsValidation;
+import fr.cnes.sitools.extensions.common.NotNullAndNotEmptyValidation;
+import fr.cnes.sitools.extensions.common.NumberArrayValidation;
+import fr.cnes.sitools.extensions.common.NumberValidation;
+import fr.cnes.sitools.extensions.common.SpatialGeoValidation; 
+import fr.cnes.sitools.extensions.common.StatusValidation;
+import fr.cnes.sitools.extensions.common.Validation;
+import fr.cnes.sitools.plugins.resources.model.ResourceModel;
+import fr.cnes.sitools.util.Util;
+import fr.ias.sitools.validation.vo.TimeValidation;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import net.ivoa.xml.votable.v1.AnyTEXT;
+import net.ivoa.xml.votable.v1.DataType;
+import net.ivoa.xml.votable.v1.Info;
+import net.ivoa.xml.votable.v1.Option;
+import net.ivoa.xml.votable.v1.Param;
+import net.ivoa.xml.votable.v1.Values;
+import org.restlet.Context;
+import org.restlet.Request;
+
+/**
+ * Input parameters for SIA.
+ *
+ * @author Jean-Crhistophe Malapert <jean-christophe.malapert@cnes.fr>
+ */
+public class SimpleSpectralAccessInputParameters implements DataModelInterface {
+  /**
+   * Logger.
+   */
+  private static final Logger LOG = Logger.getLogger(SimpleSpectralAccessInputParameters.class.getName());
+  /**
+   * Init value for right ascension parameter of the user input.
+   */
+  private transient double ra = 0.0;
+  /**
+   * Init value for declination parameter of the user input.
+   */
+  private transient double dec = 0.0;
+  /**
+   * Array that stores the size parameter of the user input.
+   */
+  private transient double[] size;
+  /**
+   * Array that stores time paramater of the user input time
+   */
+  private transient String[] time;
+
+ /**
+   * Array that stores time paramater of the user input time
+   */
+  private transient double[] band;
+  /**
+   * Default value for the verb parameter of the user input.
+   */
+  private transient int verb = 0;
+  /**
+   * Data model that stores the metadata response of the service.
+   */
+  private final transient Map dataModel = new HashMap();
+  /**
+   * Request.
+   */
+  private final transient Request request;
+  /**
+   * Context.
+   */
+  private final transient Context context;
+  /**
+   * Application where this resources is linked.
+   */
+  private final transient DataSetApplication datasetApp;
+  /**
+   * Configuration parameters of this resource.
+   */
+  private final transient ResourceModel resourceModel;
+
+  /**
+   * Constructs the objet that returns the metadata of the service.
+   * @param datasetAppVal application
+   * @param requestVal request
+   * @param contextVal context
+   * @param resourceModelVal configuration parameters
+   */
+  public SimpleSpectralAccessInputParameters(final DataSetApplication datasetAppVal, final Request requestVal, final Context contextVal, final ResourceModel resourceModelVal) {
+    this.datasetApp = datasetAppVal;
+    this.context = contextVal;
+    this.request = requestVal;
+    this.resourceModel = resourceModelVal;
+    final String posInput = this.request.getResourceRef().getQueryAsForm().getFirstValue(SimpleSpectralAccessProtocolLibrary.POS);
+    final String sizeInput = this.request.getResourceRef().getQueryAsForm().getFirstValue(SimpleSpectralAccessProtocolLibrary.SIZE);
+    final String format = this.request.getResourceRef().getQueryAsForm().getFirstValue(SimpleSpectralAccessProtocolLibrary.FORMAT);
+    final String intersect = this.request.getResourceRef().getQueryAsForm().getFirstValue(SimpleSpectralAccessProtocolLibrary.INTERSECT);
+    final String verbosity = this.request.getResourceRef().getQueryAsForm().getFirstValue(SimpleSpectralAccessProtocolLibrary.VERB);
+    final String timeInput = this.request.getResourceRef().getQueryAsForm().getFirstValue(SimpleSpectralAccessProtocolLibrary.TIME);
+    final String bandInput = this.request.getResourceRef().getQueryAsForm().getFirstValue(SimpleSpectralAccessProtocolLibrary.BAND);
+    //TODO check the differentParameters
+    if(posInput == null && sizeInput == null){
+        final Info info = new Info();
+        final List<Info> listInfos = new ArrayList<Info>();
+        info.setName("QUERY_STATUS");
+        info.setValueAttribute("ERROR");
+        listInfos.add(info);
+        this.dataModel.put("infos", listInfos);
+    }else{
+        if (Util.isSet(format) && format.equals(SimpleSpectralAccessProtocolLibrary.ParamStandardFormat.METADATA.name())) {
+            fillMetadataFormat();
+        } else {
+            checkInputParameters(posInput, sizeInput, timeInput, bandInput);
+        }
+    }
+  }
+
+  /**
+   * Fills metadata response.
+   */
+  private void fillMetadataFormat() {
+      
+    this.dataModel.put("description", this.resourceModel.getParameterByName(SimpleSpectralAccessProtocolLibrary.DESCRIPTION).getValue());
+    
+    final List<Info> listInfos = new ArrayList<Info>();
+    Info info = new Info();
+    info.setName("QUERY_STATUS");
+    info.setValueAttribute("OK");
+    info = new Info();
+    listInfos.add(info);
+    info.setName("SERVICE_PROTOCOL");
+    info.setValue("1.1");
+    info.setValueAttribute("SSAP");
+    listInfos.add(info);
+    
+    this.dataModel.put("infos", listInfos);
+   
+    final List<Param> listParam = new ArrayList<Param>();
+    Param param = new Param();
+    param.setName("INPUT:POS");
+    param.setValue("0,0");
+    param.setDatatype(DataType.DOUBLE);
+    AnyTEXT anyText = new AnyTEXT();
+    anyText.getContent().add("Search Position in the form ra,dec where ra and dec are given in decimal degrees in the ICRS coordinate system.");
+    param.setDESCRIPTION(anyText);
+    listParam.add(param);
+
+    param = new Param();
+    param.setName("INPUT:SIZE");
+    param.setValue("0.05");
+    param.setDatatype(DataType.DOUBLE);
+    anyText = new AnyTEXT();
+    anyText.getContent().add("Size of search region in the RA and Dec directions.");
+    param.setDESCRIPTION(anyText);
+    listParam.add(param);
+
+    param = new Param();
+    param.setName("INPUT:FORMAT");
+    param.setValue(SimpleSpectralAccessProtocolLibrary.ParamStandardFormat.ALL.name());
+    param.setDatatype(DataType.CHAR);
+    param.setArraysize("*");
+    anyText = new AnyTEXT();
+    anyText.getContent().add("Requested format of images.");
+    param.setDESCRIPTION(anyText);
+    final List<String> formatList = SimpleSpectralAccessProtocolLibrary.ParamStandardFormat.getCtes();
+    final Values values = new Values();
+    for (String formatIter : formatList) {
+      final Option option = new Option();
+      option.setValue(formatIter);
+      values.getOPTION().add(option);
+    }
+    param.setVALUES(values);
+    //TODO : le faire pour chaque format
+    listParam.add(param);
+    
+    param = new Param();
+    param.setName("INPUT:INTERSECT");
+    param.setValue(this.resourceModel.getParameterByName(SimpleSpectralAccessProtocolLibrary.INTERSECT).getValue());
+    param.setDatatype(DataType.CHAR);
+    anyText = new AnyTEXT();
+    anyText.getContent().add("Choice of overlap with requested region.");
+    param.setDESCRIPTION(anyText);
+    listParam.add(param);
+
+    param = new Param();
+    param.setName("INPUT:VERB");
+    param.setValue(this.resourceModel.getParameterByName(SimpleSpectralAccessProtocolLibrary.VERB).getValue());
+    param.setDatatype(DataType.INT);
+    anyText = new AnyTEXT();
+    anyText.getContent().add("Verbosity level, controlling the number of columns returned.");
+    param.setDESCRIPTION(anyText);
+    listParam.add(param);
+
+    dataModel.put("params", listParam);
+  }
+
+  /**
+   * Checks input parameters.
+   * @param posInput input parameter for POS
+   * @param sizeInput input parameter for SIZE
+   */
+  private void checkInputParameters(final String posInput, final String sizeInput, final String timeInput,  final String bandInput) {
+    final List<Info> infos = new ArrayList<Info>();
+    final Map<String, String> validationMap = new HashMap<String, String>();
+    validationMap.put(SimpleSpectralAccessProtocolLibrary.POS, posInput);
+    validationMap.put(SimpleSpectralAccessProtocolLibrary.SIZE, sizeInput); 
+    validationMap.put(SimpleSpectralAccessProtocolLibrary.TIME, timeInput);
+    validationMap.put(SimpleSpectralAccessProtocolLibrary.BAND, bandInput);
+    Validation validation = new InputsValidation(validationMap);
+    validation = new NotNullAndNotEmptyValidation(validation, SimpleSpectralAccessProtocolLibrary.POS);
+    validation = new NotNullAndNotEmptyValidation(validation, SimpleSpectralAccessProtocolLibrary.SIZE);
+    // ------------------------ RAJOUT POUR LE SSA ---------------------------------------
+    if(timeInput!= null){
+        validation = new TimeValidation(validation, SimpleSpectralAccessProtocolLibrary.TIME, timeInput);
+    }
+    if(bandInput != null){
+        validation = new NumberArrayValidation(validation, SimpleSpectralAccessProtocolLibrary.BAND, ",");
+    }
+    //*************** FIN DU RAJOUT *********************************
+    if(validation.validate().isValid()){
+        validation = new SpatialGeoValidation(validation, SimpleSpectralAccessProtocolLibrary.POS, 0, 1, new double[]{0.0, 360.0}, new double[]{-90.0, 90.0});
+        // LA LIGNE SUIVANTE A ETE AJOUTEE POUR VERIFIER QUE LA SIZE EST BIEN UN NOMBRE
+        validation = new NumberValidation(validation, SimpleSpectralAccessProtocolLibrary.SIZE, true);
+        //-----------------------------------------------------------------------------------------------
+    }  
+    StatusValidation status = validation.validate();
+    if (status.isValid()) {
+        final String pos = validation.getMap().get(SimpleSpectralAccessProtocolLibrary.POS);
+        final String[] arrayPos = pos.split(",");
+        
+        this.ra = Double.valueOf(arrayPos[0]);
+        this.dec = Double.valueOf(arrayPos[1]);
+        
+        final String size = validation.getMap().get(SimpleSpectralAccessProtocolLibrary.SIZE);
+        final String[] arraySize = size.split(",");
+        if(arraySize.length == 1) {
+            this.size = new double[1];
+            this.size[0] = Double.valueOf(arraySize[0]);
+        } else {
+            this.size = new double[2];
+            this.size[0] = Double.valueOf(arraySize[0]);
+            this.size[1] = Double.valueOf(arraySize[1]);
+        }
+        //--------------- RAJOUT POUR LE PROTOCOLE SSA -----------------
+        if(timeInput!= null){
+            final String time = timeInput;
+       
+            final String[] arrayTime = time.split(",");
+            if(arrayTime.length == 1) {
+                this.time = new String[1];
+                this.time[0] = arrayTime[0];
+            } else {
+                this.time = new String[2];
+                this.time[0] = arrayTime[0];
+                    this.time[1] = arrayTime[1];
+            }
+        }
+        if(bandInput!= null){
+            final String band = bandInput;
+            final String[] arrayBand = band.split(",");
+            if(arrayBand.length == 1) {
+                this.band = new double[1];
+                this.band[0] = Double.valueOf(arrayBand[0]);
+            } else {
+                this.band = new double[2];
+                this.band[0] = Double.valueOf(arrayBand[0]);
+                this.band[1] = Double.valueOf(arrayBand[1]);
+            }
+        }
+        //*************** FIN DU RAJOUT *********************************
+        
+    } else {
+        Info info = new Info();
+        info.setName("QUERY_STATUS");
+        info.setValueAttribute("ERROR");
+        infos.add(info);
+        final Map<String, String> errors = status.getMessages();
+        final Set<Map.Entry<String, String>> entries = errors.entrySet();        
+        for (Map.Entry<String, String> entry : entries) {
+            info = new Info();
+            info.setID(entry.getKey());
+            info.setName("Error in " + entry.getKey());
+            info.setValueAttribute("Error in input " + entry.getKey() + ": " + entry.getValue());
+            infos.add(info);
+            LOG.log(Level.FINEST, "{0}: {1}", new Object[]{entry.getKey(), entry.getValue()});            
+        }
+        
+    }
+    
+    if (!infos.isEmpty()) {
+      this.dataModel.put("infos", infos);
+    }
+  }
+
+  @Override
+  public final Map getDataModel() {
+    return Collections.unmodifiableMap(this.dataModel);
+  }
+
+  /**
+   * Get Ra.
+   *
+   * @return Ra
+   */
+  public final double getRa() {
+    return this.ra;
+  }
+
+  /**
+   * Get Dec.
+   *
+   * @return Dec
+   */
+  public final double getDec() {
+    return this.dec;
+  }
+
+  /**
+   * Get Sr.
+   *
+   * @return Sr
+   */
+  public final double[] getSize() {
+      final double[] copySize = new double[this.size.length];
+      System.arraycopy(this.size, 0, copySize, 0, this.size.length);
+      return copySize;
+  }
+
+  /**
+   * Get the request.
+   *
+   * @return Request
+   */
+  public final Request getRequest() {
+    return this.request;
+  }
+
+  /**
+   * Get the context.
+   *
+   * @return Context
+   */
+  public final Context getContext() {
+    return this.context;
+  }
+
+  /**
+   * Get DatasetApplication.
+   *
+   * @return Dataset application
+   */
+  public final DataSetApplication getDatasetApplication() {
+    return this.datasetApp;
+  }
+
+  /**
+   * Get verb.
+   * @return verb
+   */
+  public final int getVerb() {
+    return this.verb;
+  }  
+
+    public final String[] getTime() {
+      final String[] copyTime = new String[this.time.length];
+      System.arraycopy(this.time, 0, copyTime, 0,this.time.length);
+      return copyTime;
+  }
+    public final double[] getBand() {
+      final double[] copyBand = new double[this.band.length];
+      System.arraycopy(this.band, 0, copyBand, 0, this.band.length);
+      return copyBand;
+  }
+}
diff --git a/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/ssa/SimpleSpectralAccessProtocolLibrary.java b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/ssa/SimpleSpectralAccessProtocolLibrary.java
new file mode 100644
index 0000000..48391c5
--- /dev/null
+++ b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/ssa/SimpleSpectralAccessProtocolLibrary.java
@@ -0,0 +1,698 @@
+ /*******************************************************************************
+ * Copyright 2010-2013 CNES - CENTRE NATIONAL d'ETUDES SPATIALES
+ *
+ * This file is part of SITools2.
+ *
+ * SITools2 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * SITools2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with SITools2.  If not, see <http://www.gnu.org/licenses/>.
+ ******************************************************************************/
+package fr.ias.sitools.vo.ssa;
+
+import fr.cnes.sitools.astro.representation.VOTableRepresentation;
+import fr.cnes.sitools.dataset.DataSetApplication;
+import fr.cnes.sitools.plugins.resources.model.ResourceModel;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import net.ivoa.xml.votable.v1.DataType;
+import org.restlet.Context;
+import org.restlet.Request;
+
+/**
+ *
+ * @author malapert
+ */
+public class SimpleSpectralAccessProtocolLibrary {
+
+  /**
+   * Logger.
+   */
+  private static final Logger LOG = Logger.getLogger(SimpleSpectralAccessProtocolLibrary.class.getName());
+
+  /**
+   *
+   */
+  public static final String DICTIONARY = "PARAM_Dictionary";
+  /**
+   *
+   */
+  public static final String INTERSECT = "INTERSECT";
+  /**
+   *
+   */
+  public static final String POS = "POS";
+  /**
+   *
+   */
+  public static final String VERB = "VERB";
+  /**
+   *
+   */
+  public static final String SIZE = "SIZE";
+  /**
+   *
+   */
+  public static final String FORMAT = "FORMAT";
+  /**
+   *
+   */
+  public static final String RA_COL = "COLUMN_RA";
+  /**
+   *
+   */
+  public static final String DEC_COL = "COLUMN_DEC";
+  /**
+   *
+   */
+  public static final List REQUIRED_UCD_CONCEPTS = Arrays.asList("VOX:Image_Title",
+                                                    "POS_EQ_RA_MAIN",
+                                                    "POS_EQ_DEC_MAIN",
+                                                    /*"VOX:Image_Naxes",
+                                                    "VOX:Image_Naxis",
+                                                    "VOX:Image_Scale",
+                                                    "VOX:Image_Format",*/
+                                                    "VOX:Image_AccessReference",
+                                                    "TIME_MAIN",
+                                                    "BAND_MAIN");
+  /**
+   *
+   */
+  public static final String RESPONSIBLE_PARTY = "Responsible party";
+  /**
+   *
+   */
+  public static final String SERVICE_NAME = "Image service";
+  /**
+   *
+   */
+  public static final String DESCRIPTION = "Description";
+  /**
+   *
+   */
+  public static final String INSTRUMENT = "Instrument";
+  /**
+   *
+   */
+  public static final String WAVEBAND = "Waveband Coverage";
+  /**
+   *
+   */
+  public static final String COVERAGE = "Spatial Coverage";
+  /**
+   *
+   */
+  public static final String TEMPORAL = "Temporal Coverage";
+  /**
+   *
+   */
+  public static final String MAX_QUERY_SIZE = "Max query size";
+  /**
+   *
+   */
+  public static final String MAX_IMAGE_SIZE = "Max image size";
+  /**
+   *
+   */
+  public static final String MAX_FILE_SIZE = "Max file size";
+  /**
+   *
+   */
+  public static final String MAX_RECORDS = "Max records";
+  /**
+   * spoly column from pgsphere.
+   */
+  
+  // ********************************************   RAJOUTER POUR SSAP   ***********************************
+  public static final String SERVICE_PROTOCOL = "SERVICE PROTOCOL";
+  
+  public static final String TIME = "TIME";
+  
+  public static final String BAND = "BAND";
+  
+  
+  //--------------------------------------------------------------------------------------------------------
+  public static final String GEO_ATTRIBUT = "geoAttribut";
+  private transient DataSetApplication datasetApp;
+  private transient ResourceModel resourceModel;
+  private transient Request request;
+  private transient Context context;
+
+  /**
+   * Maximum value of the declination axis.
+   */
+  public static final double MAX_VALUE_FOR_DECLINATION = 90.0;
+  /**
+   * Minimum value of the declination axis.
+   */  
+  public static final double MIN_VALUE_FOR_DECLINATION = -90.0;
+  /**
+   * Maximum value of the right ascension axis.
+   */  
+  public static final double MAX_VALUE_FOR_RIGHT_ASCENSION = 360.0;
+  /**
+   * Minimum value of the right ascension axis.
+   */  
+  public static final double MIN_VALUE_FOR_RIGHT_ASCENSION = 0.0;
+  /**
+   *
+   */
+  public enum Intersect {
+
+    /**
+     *
+     */
+    COVERS, /* The candidate image covers or includes the entire ROI */
+    /**
+     *
+     */
+    ENCLOSED, /* The candidate image is entirely enclosed by the ROI */
+    /**
+     *
+     */
+    CENTER, /* The candidate image overlaps the center of the ROI */
+    /**
+     *
+     */
+    OVERLAPS /* The candidate image overlaps some part of the ROI */
+
+  };
+
+  /**
+   *
+   */
+  public enum SpectrumService {
+
+    /**
+     *
+     */
+    POINTED_SPECTRAL_ARCHIVE("Spectral Archive Service"),
+    SPECTRAL_CUTOUT_SERVICE("Spectral Cutout Service"),
+    SPECTRAL_MOSAICING_SERVICE("Spectral Mosaicing Service"),
+    SPECTRAL_EXTRACTION_SERVICE("Spectral Extraction Service");
+    public final String serviceName;
+
+    SpectrumService(String serviceName) {
+      this.serviceName = serviceName;
+    }
+
+    /**
+     *
+     * @return
+     */
+    public final String getServiceName() {
+      return this.serviceName;
+    }
+  }
+
+  /**
+   *
+   */
+  public enum ImageGenerationParameters {
+
+    /**
+     *
+     */
+    NAXIS,
+    /**
+     *
+     */
+    CFRAME,
+    /**
+     *
+     */
+    EQUINOX,
+    /**
+     *
+     */
+    CRPIX,
+    /**
+     *
+     */
+    CRVAL,
+    /**
+     *
+     */
+    CDELT,
+    /**
+     *
+     */
+    ROTANG,
+    /**
+     *
+     */
+    PROJ
+  };
+
+  /**
+   *
+   */
+  public enum Verb {
+
+    /**
+     *
+     */
+    VERBOSITY_0(0), /* The output table should contain only the minimum columns required */
+    /**
+     *
+     */
+    VERBOSITY_1(1), /* In addition to level 0, the output table should contain columns sufficient for uniquely describing the image */
+    /**
+     *
+     */
+    VERBOSITY_2(2), /*  In addition to level 1, the output table should contain, if possible, columns that contain values for all parameters supported as query constraints */
+    /**
+     *
+     */
+    VERBOSITY_3(3); /* The output table should return as much information about the images as possible. A table metadata query automatically implies the highest level of verbosity */
+
+    /**
+     *
+     */
+    public final int verbosityMode;
+
+    Verb(final int verbosityMode) {
+      this.verbosityMode = verbosityMode;
+    }
+
+    /**
+     *
+     * @return
+     */
+    public final int getVerbosityMode() {
+      return this.verbosityMode;
+    }
+  }
+
+  /**
+   * List of format for internet browser.
+   */
+  public enum GraphicBrowser {
+
+    /**
+     * JPEG format.
+     */
+    JPEG("image/jpeg"),
+    /**
+     * PNG format.
+     */
+    PNG("image/png"),
+    /**
+     * GIF format.
+     */
+    GIF("image/gif");
+    /**
+     * Format.
+     */
+    private final String format;
+
+    /**
+     * new Instance of Graphic browser.
+     *
+     * @param format Format name.
+     */
+    GraphicBrowser(final String format) {
+      this.format = format;
+    }
+
+    /**
+     * Get Format Name.
+     *
+     * @return Returns format name.
+     */
+    public String getFormat() {
+      return format;
+    }
+
+    /**
+     * Check if val is a graphic format.
+     *
+     * @param val Format.
+     * @return Returns True when val is contained in the list of Graphic format otherwise False.
+     */
+    public static boolean contains(final String val) {
+      for (GraphicBrowser it : GraphicBrowser.values()) {
+        if (it.getFormat().equals(val)) {
+          return true;
+        }
+      }
+      return false;
+    }
+  }
+
+  /**
+   * List of supported format.
+   */
+  public enum ParamStandardFormat {
+
+    /**
+     * All format.
+     */
+    ALL("ALL", new ArrayList<String>()),
+    /**
+     * Graphic format.
+     */
+    GRAPHIC("GRAPHIC", new ArrayList<String>()),
+    /**
+     * METADATA format.
+     */
+    METADATA("METADATA", new ArrayList<String>()),
+    /**
+     * GRAPHIC Format.
+     */
+    GRAPHIC_ALL("GRAPHIC-ALL", new ArrayList<String>());
+    /**
+     * format.
+     */
+    private final String format;
+    /**
+     * All formats.
+     */
+    private List<String> formats;
+
+    /**
+     * New instance of Standard Format.
+     *
+     * @param val format name.
+     * @param formats values for this format name.
+     */
+    ParamStandardFormat(final String val, final List<String> formats) {
+      this.format = val;
+      this.formats = formats;
+    }
+
+    /**
+     * Get the format name.
+     *
+     * @return Returns the format name.
+     */
+    public String getFormatName() {
+      return format;
+    }
+
+    /**
+     * Get the list of format.
+     *
+     * @return Returns the list of format for a format name.
+     */
+    public List<String> getFormats() {
+      return Collections.unmodifiableList(formats);
+    }
+
+    /**
+     * Add a format to the format name.
+     *
+     * @param val new supported format value.
+     */
+    private void addFormat(final String val) {
+      this.formats.add(val);
+    }
+
+    /**
+     * Set the list of format for a format name.
+     *
+     * @param val Set a list of formats for a format name.
+     */
+    private void setFormat(final List<String> val) {
+      this.formats.addAll(val);
+    }
+
+    /**
+     * Add a format value for a format name.
+     *
+     * @param format format Name.
+     * @param specialValue Value for a format name.
+     */
+    private static void addFormat(final String format, final ParamStandardFormat specialValue) {
+      for (ParamStandardFormat it : ParamStandardFormat.values()) {
+        if (it.equals(specialValue) && !ParamStandardFormat.hasFormat(format)) {
+          it.addFormat(format);
+        }
+      }
+    }
+
+    /**
+     * Set a list of format for a format name.
+     *
+     * @param format Format name.
+     * @param specialValue List of format.
+     */
+    private static void setFormat(final List<String> format, final ParamStandardFormat specialValue) {
+      for (ParamStandardFormat it : ParamStandardFormat.values()) {
+        if (it.equals(specialValue)) {
+          it.setFormat(format);
+        }
+      }
+    }
+
+    /**
+     * Get the list of supported format for a format name.
+     *
+     * @param format Format name.
+     * @return Returns the list of supported formats.
+     */
+    public static List<String> getFormats(final ParamStandardFormat format) {
+      for (ParamStandardFormat it : ParamStandardFormat.values()) {
+        if (it.equals(format)) {
+          return it.getFormats();
+        }
+      }
+      throw new IllegalAccessError();
+    }
+
+    /**
+     * Get the list of supported format for a format name.
+     *
+     * @param format Format name.
+     * @return Returns the list of supported formats.
+     */
+    public static List<String> getFormats(final String format) {
+      for (ParamStandardFormat it : ParamStandardFormat.values()) {
+        if (it.getFormatName().equals(format)) {
+          return it.getFormats();
+        }
+      }
+      throw new IllegalAccessError();
+    }
+
+    /**
+     * Get Format names.
+     *
+     * @return Returns format names.
+     */
+    public static List<String> getCtes() {
+      final List<String> formats = new ArrayList<String>();
+      for (ParamStandardFormat it : ParamStandardFormat.values()) {
+        formats.add(it.getFormatName());
+      }
+      return formats;
+    }
+
+    /**
+     * Test if format is included in the list of formats.
+     *
+     * @param format format to test
+     * @return Returns true when the format is included in the list otherwise false.
+     */
+    public static boolean hasFormat(final String format) {
+      for (ParamStandardFormat it : ParamStandardFormat.values()) {
+        if (it.getFormats().contains(format)) {
+          return true;
+        }
+      }
+      return false;
+    }
+  };
+
+  /**
+   *
+   */
+  public enum ParamStandardInput {
+
+    /**
+     *
+     */
+    POS("POS", Arrays.asList(SpectrumService.POINTED_SPECTRAL_ARCHIVE),
+    "The position of the region of interest, expressed as the right-ascension and declination of the field center, in decimal degrees using the ICRS coordinate system. A comma should delimit the two values; embedded whitespace is not permitted.", null, DataType.DOUBLE),
+    
+    /**
+     *
+     */
+    SIZE("SIZE", Arrays.asList(SpectrumService.POINTED_SPECTRAL_ARCHIVE),
+    "The coordinate angular size of the region given in decimal degrees. The region may be specified using either one or two values. If only one value is given it applies to both coordinate axes. If two values are given the first value is the angular width in degrees of the right-ascension axis of the region, and the second value is the angular width in degrees of the declination axis.", null, DataType.DOUBLE),
+    /**
+     * 
+     */
+    TIME("TIME",Arrays.asList(SpectrumService.POINTED_SPECTRAL_ARCHIVE),"zefzefze",null,DataType.DOUBLE),
+    /**
+     * 
+     */
+    BAND("BAND",Arrays.asList(SpectrumService.POINTED_SPECTRAL_ARCHIVE),"zefzefze",null,DataType.DOUBLE),
+    /**
+     *
+     */
+    INTERSECT("INTERSECT", Arrays.asList(SpectrumService.POINTED_SPECTRAL_ARCHIVE),
+    "A parameter that indicates how matched images should intersect the region of interest", Intersect.OVERLAPS.name(), DataType.CHAR),
+    /**
+     *
+     */
+    FORMAT("FORMAT", Arrays.asList(SpectrumService.POINTED_SPECTRAL_ARCHIVE),
+    "indicate the desired format or formats of the images referenced by the output table", "ALL", DataType.CHAR),
+    /**
+     *
+     */
+    VERB("VERB", Arrays.asList(SpectrumService.POINTED_SPECTRAL_ARCHIVE),
+    "This parameter indicates the desired level of information to be returned in the output table, particularly the number of columns to be returned to describe each image.", null, DataType.INT);
+    /**
+     *
+     */
+    //NAXIS("NAXIS", Arrays.asList(SpectrumService.POINTED_SPECTRAL_ARCHIVE),
+    //"The size of the output image in pixels. This is a vector-valued quantity, expressed as \"NAXIS=<width>,<height>\". If only one value is given it applies to both image axes", null, DataType.INT),
+    /**
+     *
+     */
+    //CFRAME("CFRAME", Arrays.asList(SpectrumService.IMAGE_CUTOUT_SERVICE, SpectrumService.IMAGE_MOSAICING_SERVICE),
+    //"The coordinate system reference frame, selected from ICRS, FK5, FK4, ECL, GAL, and SGAL (these abbreviations follow CDS Aladin). Default: ICRS. ", "ICRS", DataType.CHAR),
+    /**
+     *
+     */
+    //EQUINOX("EQUINOX", Arrays.asList(SpectrumService.IMAGE_CUTOUT_SERVICE, SpectrumService.IMAGE_MOSAICING_SERVICE),
+    //"Epoch of the mean equator and equinox for the specified coordinate system reference frame (CFRAME). Not required for ICRS. Default: B1950 for FK4, otherwise J2000.", "J2000", DataType.CHAR),
+    /**
+     *
+     */
+    //CRPIX("CRPIX", Arrays.asList(SpectrumService.IMAGE_CUTOUT_SERVICE, SpectrumService.IMAGE_MOSAICING_SERVICE),
+    //"The coordinates of the reference pixel, expressed in the pixel coordinates of the output image, with [1,1] being the center of the first pixel of the first row of the image. This is a vector-valued quantity; if only one value is given it applies to both image axes. Default: the image center.", null, DataType.DOUBLE),
+    /**
+     *
+     */
+    //CRVAL("CRVAL", Arrays.asList(SpectrumService.IMAGE_CUTOUT_SERVICE, SpectrumService.IMAGE_MOSAICING_SERVICE),
+    //"The world coordinates relative to CFRAME at the reference pixel. This is a vector-valued quantity; both array values are required. Default: the region center coordinates (POS) at the center of the image, transformed to the output coordinate system reference frame if other than ICRS. If CRPIX is specified to be other than the image center the corresponding CRVAL can be computed, but should be specified explicitly by the client.", null, DataType.DOUBLE),
+    /**
+     *
+     */
+    //CDELT("CDELT", Arrays.asList(SpectrumService.IMAGE_CUTOUT_SERVICE, SpectrumService.IMAGE_MOSAICING_SERVICE),
+    //"The scale of the output image in decimal degrees per pixel. A negative value implies an axis flip. Since the default image orientation is N up and E to the left, the default sign of CDELT is [-1,1].", null, DataType.DOUBLE),
+    /**
+     *
+     */
+    //ROTANG("ROTANG", Arrays.asList(SpectrumService.IMAGE_CUTOUT_SERVICE, SpectrumService.IMAGE_MOSAICING_SERVICE),
+    //"The rotation angle of the image in degrees relative to CFRAME (an image which is unrotated in one reference frame may be rotated in another). This is the rotation of the WCS declination or latitude axis with respect to the second axis of the image, measured in the counterclockwise direction (as for FITS WCS, which is in turn based on the old AIPS convention). Default: 0 (no rotation).", "0", DataType.DOUBLE),
+    
+    
+    private String inputParameterName;
+    private List<SpectrumService> supportedImageService;
+    private String description;
+    private String defaultValue;
+    private DataType dataType;
+
+    ParamStandardInput(final String inputParameterName, final List<SpectrumService> supportedImageService, final String description, final String defaultValue, final DataType dataType) {
+      this.inputParameterName = inputParameterName;
+      this.supportedImageService = supportedImageService;
+      this.description = description;
+      this.defaultValue = defaultValue;
+      this.dataType = dataType;
+    }
+
+    /**
+     *
+     * @return
+     */
+    public final String getInputParameterName() {
+      return this.inputParameterName;
+    }
+
+    /**
+     *
+     * @return
+     */
+    public final List<SpectrumService> getSupportedImageService() {
+      return Collections.unmodifiableList(this.supportedImageService);
+    }
+
+    /**
+     *
+     * @return
+     */
+    public final String getDescription() {
+      return this.description;
+    }
+
+    /**
+     *
+     * @return
+     */
+    public final String getDefaultValue() {
+      return this.defaultValue;
+    }
+
+    /**
+     *
+     * @return
+     */
+    public final DataType getDataType() {
+      return this.dataType;
+    }
+  };
+  //public enum ImageFormat{}//public enum ImageFormat{}//public enum ImageFormat{}//public enum ImageFormat{}
+
+  /**
+   * Constructor.
+   *
+   * @param datasetApp Dataset Application
+   * @param resourceModel Data model
+   * @param request Request
+   * @param context Context
+   */
+  public SimpleSpectralAccessProtocolLibrary(final DataSetApplication datasetApp, final ResourceModel resourceModel, final Request request, final Context context) {
+    this.datasetApp = datasetApp;
+    this.resourceModel = resourceModel;
+    this.request = request;
+    this.context = context;
+  }
+
+  /**
+   * Fill data Model that will be used in the template.
+   *
+   * @return data model for the template
+   */
+  private Map fillDataModel() {
+    // init
+    Map dataModel;
+
+    // Handling input parameters
+    final DataModelInterface inputParameters = new SimpleSpectralAccessInputParameters(datasetApp, request, this.context, this.resourceModel);
+      
+    // data model response
+    if (inputParameters.getDataModel().containsKey("infos")) {
+      dataModel = inputParameters.getDataModel();
+    } else {
+      final SimpleSpectralAccessDataModelInterface response = new SimpleSpectralAccessResponse((SimpleSpectralAccessInputParameters) inputParameters, resourceModel);
+      dataModel = response.getDataModel();
+    }
+    return dataModel;
+  }
+
+  /**
+   * VOTable response.
+   *
+   * @return VOTable response
+   */
+  public final VOTableRepresentation getResponse() {
+    final Map dataModel = fillDataModel();
+    return new VOTableRepresentation(dataModel);
+  }  
+}
diff --git a/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/ssa/SimpleSpectralAccessResponse.java b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/ssa/SimpleSpectralAccessResponse.java
new file mode 100644
index 0000000..13db01d
--- /dev/null
+++ b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/ssa/SimpleSpectralAccessResponse.java
@@ -0,0 +1,600 @@
+ /*******************************************************************************
+ * Copyright 2010-2013 CNES - CENTRE NATIONAL d'ETUDES SPATIALES
+ *
+ * This file is part of SITools2.
+ *
+ * SITools2 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * SITools2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with SITools2.  If not, see <http://www.gnu.org/licenses/>.
+ ******************************************************************************/
+package fr.ias.sitools.vo.ssa;
+
+import fr.cnes.sitools.astro.representation.DatabaseRequestModel;
+import fr.cnes.sitools.common.SitoolsSettings;
+import fr.cnes.sitools.common.application.ContextAttributes;
+import fr.cnes.sitools.common.exception.SitoolsException;
+import fr.cnes.sitools.dataset.DataSetApplication;
+import fr.cnes.sitools.dataset.converter.business.ConverterChained;
+import fr.cnes.sitools.dataset.database.DatabaseRequest;
+import fr.cnes.sitools.dataset.database.DatabaseRequestFactory;
+import fr.cnes.sitools.dataset.database.DatabaseRequestParameters;
+import fr.cnes.sitools.dataset.database.common.DataSetExplorerUtil;
+import fr.cnes.sitools.dataset.dto.ColumnConceptMappingDTO;
+import fr.cnes.sitools.dataset.dto.DictionaryMappingDTO;
+import fr.cnes.sitools.dataset.model.Predicat;
+import fr.cnes.sitools.dictionary.model.Concept;
+import fr.cnes.sitools.plugins.resources.model.ResourceModel;
+import fr.cnes.sitools.util.Util;
+import freemarker.template.TemplateSequenceModel;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import net.ivoa.xml.votable.v1.AnyTEXT;
+import net.ivoa.xml.votable.v1.DataType;
+import net.ivoa.xml.votable.v1.Field;
+import net.ivoa.xml.votable.v1.Info;
+import net.ivoa.xml.votable.v1.Param;
+
+
+
+/**
+ * Votable response for cone search.
+ *
+ * @author Jean-Christophe Malapert <jean-christophe.malapert@cnes.fr>
+ */
+public class SimpleSpectralAccessResponse implements SimpleSpectralAccessDataModelInterface {
+    
+  /**
+   * Logger.
+   */
+  private static final Logger LOG = Logger.getLogger(SimpleSpectralAccessResponse.class.getName());
+  
+  /**
+   * Data model.
+   */
+  private final transient Map dataModel = new HashMap();
+  
+  /**
+   * Sitools Settings
+   */
+  private SitoolsSettings sitoolsSettings = null;
+  /**
+   * Right Ascenscion.
+   */
+  private final double ra;
+  /**
+   * Declination.
+   */
+  private final double dec;
+
+  /**
+   * Time 
+   */
+  private final String[] time;
+  /**
+   * Band 
+   */
+  private final double[] band;
+  
+  /**
+   * Constructor.
+   *
+   * @param inputParameters input parameters
+   * @param model data model
+   */
+  public SimpleSpectralAccessResponse(final SimpleSpectralAccessInputParameters inputParameters, final ResourceModel model) {
+      this.sitoolsSettings = (SitoolsSettings) inputParameters.getContext().getAttributes().get(ContextAttributes.SETTINGS);
+      this.ra = inputParameters.getRa();
+      this.dec = inputParameters.getDec();
+      this.time= inputParameters.getTime();
+      this.band = inputParameters.getBand();
+      createResponse(inputParameters, model);
+  }
+
+  /**
+   * Creates VOTable response.
+   *
+   * @param inputParameters Input parameters
+   * @param model data model
+   */
+  private void createResponse(final SimpleSpectralAccessInputParameters inputParameters, final ResourceModel model) {
+    // createResponse
+    final String dictionaryName = model.getParameterByName(SimpleSpectralAccessProtocolLibrary.DICTIONARY).getValue();
+
+    // Set Votable parameters
+    setVotableParametersFromConfiguration(dataModel, model);
+
+    // Set Votable resources
+    setVotableResource(inputParameters.getDatasetApplication(), inputParameters, model, dictionaryName);
+   
+  }
+
+  /**
+   * Sets VOTable parameters coming from administration configuration.
+   *
+   * @param dataModel data model to set
+   * @param model parameters from administration
+   */
+  private void setVotableParametersFromConfiguration(final Map dataModel, final ResourceModel model) {
+    final List<Param> params = new ArrayList<Param>();
+    //setVotableParam(params, model, SimpleSpectralAccessProtocolLibrary.COVERAGE, DataType.CHAR);
+    //setVotableParam(params, model, SimpleSpectralAccessProtocolLibrary.TEMPORAL, DataType.CHAR);
+    setVotableParam(params, model, SimpleSpectralAccessProtocolLibrary.INSTRUMENT, DataType.CHAR);
+    setVotableParam(params, model, SimpleSpectralAccessProtocolLibrary.MAX_FILE_SIZE, DataType.LONG);
+    setVotableParam(params, model, SimpleSpectralAccessProtocolLibrary.RESPONSIBLE_PARTY, DataType.CHAR);
+    setVotableParam(params, model, SimpleSpectralAccessProtocolLibrary.SERVICE_NAME, DataType.CHAR);
+    //setVotableParam(params, model, SimpleSpectralAccessProtocolLibrary.WAVEBAND, DataType.CHAR);
+    setVotableParam(params, model, SimpleSpectralAccessProtocolLibrary.MAX_RECORDS, DataType.INT);
+    setVotableParam(params, model, SimpleSpectralAccessProtocolLibrary.MAX_QUERY_SIZE, DataType.CHAR);
+    setVotableParam(params, model, SimpleSpectralAccessProtocolLibrary.MAX_IMAGE_SIZE, DataType.CHAR);
+    setVotableParam(params, model, SimpleSpectralAccessProtocolLibrary.VERB, DataType.INT);
+/* POURQUOI BOOLEAN ?? Alors qu'il peut prendre 0,1,2 ou 3 comme valeurs    setVotableParam(params, model, SimpleSpectralAccessProtocolLibrary.VERB, DataType.BOOLEAN);*/
+    if (Util.isSet(params)) {
+      dataModel.put("params", params);
+    }
+  }
+
+  /**
+   * Sets Votable Param.
+   *
+   * @param params List of params
+   * @param model data model
+   * @param parameterName parameter name
+   * @param datatype datatype
+   */
+  private void setVotableParam(final List<Param> params, final ResourceModel model, final String parameterName,
+          final DataType datatype) {
+    final String parameterValue = model.getParameterByName(parameterName).getValue();
+    if (Util.isNotEmpty(parameterValue)) {
+      final Param param = new Param();
+      param.setName(parameterName);
+      param.setValue(parameterValue);
+      param.setDatatype(datatype);
+      params.add(param);
+    }
+  }
+
+  /**
+   * Creates the response based on Table.
+   *
+   * @param datasetApp Dataset application
+   * @param inputParameters Input Parameters
+   * @param model data model
+   * @param dictionaryName Cone search dictionary
+   */
+  private void setVotableResource(final DataSetApplication datasetApp, final SimpleSpectralAccessInputParameters inputParameters,
+          final ResourceModel model, final String dictionaryName) {
+    
+    final List<Field> fieldList = new ArrayList<Field>();
+    final List<String> columnList = new ArrayList<String>();
+    DatabaseRequest databaseRequest = null;
+
+    try {
+      // Get the concepts from the dictionary
+      List<ColumnConceptMappingDTO> mappingList = getDicoFromConfiguration(datasetApp, dictionaryName);
+
+      mappingList = checkRequiredMapping(mappingList, inputParameters.getVerb());
+
+      // Get query parameters
+      final DatabaseRequestParameters dbParams = setQueryParameters(datasetApp, model, inputParameters, mappingList);
+      databaseRequest = DatabaseRequestFactory.getDatabaseRequest(dbParams);
+      // Execute query
+      databaseRequest.createRequest();
+
+      LOG.log(Level.FINEST, "DB request: {0}", databaseRequest.getRequestAsString());
+      
+      //Fill the template with query status and param
+      fillInfosParamAboutQuery(model);
+      
+      // complete data model with fields
+      setFields(fieldList, columnList, mappingList);
+      dataModel.put("fields", fieldList);
+      dataModel.put("sqlColAlias", columnList);
+      Map conceptColAlias = new HashMap();
+       for (ColumnConceptMappingDTO map:mappingList) {
+          conceptColAlias.put(map.getColumnAlias(), map.getConcept().getPropertyFromName("ucd").getValue());
+      }
+      dataModel.put("mappingColAliasConceptSql", conceptColAlias);
+     
+      // Complete data model with data
+      final int count = (databaseRequest.getCount() > dbParams.getPaginationExtend()) ? dbParams.getPaginationExtend() : databaseRequest.getCount();
+      dataModel.put("nrows", count);
+      final ConverterChained converterChained = datasetApp.getConverterChained();
+      
+      final TemplateSequenceModel rows = new DatabaseRequestModel(databaseRequest, converterChained);
+      ((DatabaseRequestModel) rows).setSize(count);
+      dataModel.put("rows", rows);
+
+    } catch (SitoolsException ex) {
+      try {
+        if (Util.isSet(databaseRequest)) {
+          databaseRequest.close();
+        }
+      } catch (SitoolsException ex1) {
+          LOG.log(Level.FINER, null, ex1);
+      } finally {
+        final List<Info> infos = new ArrayList<Info>();
+        LOG.log(Level.FINEST, "ERROR: {0}", ex.getMessage());
+        setVotableError(infos, "Query", "Error in query", "Error in input query: " + ex.getMessage());
+        if (!infos.isEmpty()) {
+          this.dataModel.put("infos", infos);
+        }
+      }
+    }
+  }
+
+  /**
+   * Set Query parameters to the database.
+   *
+   * @param datasetApp Dataset Application
+   * @param model Data model
+   * @param inputParameters Input Parameters
+   * @return DatabaseRequestParamerters object
+   */
+  @SuppressWarnings("empty-statement")
+  private DatabaseRequestParameters setQueryParameters(final DataSetApplication datasetApp, final ResourceModel model,
+          final SimpleSpectralAccessInputParameters inputParameters, List<ColumnConceptMappingDTO> mappingList) {
+
+    // Get the dataset
+    final DataSetExplorerUtil dsExplorerUtil = new DataSetExplorerUtil(datasetApp, inputParameters.getRequest(),
+            inputParameters.getContext());
+
+    // Get query parameters
+    final DatabaseRequestParameters dbParams = dsExplorerUtil.getDatabaseParams();
+
+    // Get dataset records
+    final int nbRecordsInDataSet = datasetApp.getDataSet().getNbRecords();
+
+    // Get max records that is defined by admin
+    int nbMaxRecords = Integer.valueOf(model.getParameterByName(SimpleSpectralAccessProtocolLibrary.MAX_RECORDS).getValue());
+    nbMaxRecords = (nbMaxRecords > nbRecordsInDataSet || nbMaxRecords == -1) ? nbRecordsInDataSet : nbMaxRecords;
+
+    // Set max records
+    dbParams.setPaginationExtend(nbMaxRecords);
+
+    // Create predicat definition   
+    String raColTarget = null;
+    String decColTarget = null;
+    String timeColTarget = null;
+    String bandColTarget = null;
+    for (ColumnConceptMappingDTO mapIter : mappingList) {
+      final String ucd = mapIter.getConcept().getPropertyFromName("ucd").getValue();
+      if (ucd.equals(SimpleSpectralAccessProtocolLibrary.REQUIRED_UCD_CONCEPTS.get(1))) {
+        raColTarget = mapIter.getColumnAlias();
+      }
+      if (ucd.equals(SimpleSpectralAccessProtocolLibrary.REQUIRED_UCD_CONCEPTS.get(2))) {
+        decColTarget = mapIter.getColumnAlias();
+      }
+      if (ucd.equals(SimpleSpectralAccessProtocolLibrary.REQUIRED_UCD_CONCEPTS.get(4))) {
+        timeColTarget = mapIter.getColumnAlias();
+      }
+      if (ucd.equals(SimpleSpectralAccessProtocolLibrary.REQUIRED_UCD_CONCEPTS.get(5))) {
+        bandColTarget = mapIter.getColumnAlias();
+      }
+    }
+    final AbstractSqlGeometryConstraint sql = SqlGeometryFactory.create(String.valueOf(model.getParameterByName(SimpleSpectralAccessProtocolLibrary.INTERSECT).getValue()));
+    sql.setInputParameters(inputParameters);
+    String[] geo = null;
+    if(!Util.isNotEmpty(model.getParameterByName(SimpleSpectralAccessProtocolLibrary.GEO_ATTRIBUT).getValue())){
+        geo = new String[]{raColTarget, decColTarget,timeColTarget,bandColTarget};
+    }
+    
+    final Object geometry = (Util.isNotEmpty(model.getParameterByName(SimpleSpectralAccessProtocolLibrary.GEO_ATTRIBUT).getValue()))
+                      ? model.getParameterByName(SimpleSpectralAccessProtocolLibrary.GEO_ATTRIBUT).getValue()
+                      : geo;//Arrays.asList(raColTarget, decColTarget,timeColTarget,bandColTarget);
+    //final Object geometry = 
+    sql.setGeometry(geometry);
+    if (sql.getSqlPredicat() != null) {
+      final Predicat predicat = new Predicat();
+      predicat.setStringDefinition(sql.getSqlPredicat());
+      final List<Predicat> predicatList = dbParams.getPredicats();
+      predicatList.add(predicat);
+      dbParams.setPredicats(predicatList);
+    }
+    return dbParams;
+  }
+
+  /**
+   * Set the votable error.
+   *
+   * @param infos infos
+   * @param id id 
+   * @param name name
+   * @param value value
+   */
+  private void setVotableError(final List<Info> infos, final String id, final String name, final String value) {
+    if (Util.isNotEmpty(name)) {
+      final Info info = new Info();
+      info.setID(id);
+      info.setName(name);
+      info.setValueAttribute(value);
+      infos.add(info);
+    }
+  }
+
+  /**
+   * Returns the data model.
+   * @return the data model
+   */
+  @Override
+  public final Map getDataModel() {
+    return Collections.unmodifiableMap(this.dataModel);
+  }
+
+  /**
+   * Provide the mapping between SQL column/concept for a given dictionary.
+   *
+   * @param datasetApp Application where this service is attached
+   * @param dicoToFind Dictionary name to find
+   * @return Returns a mapping SQL column/Concept
+   * @throws SitoolsException No mapping has been done or cannot find the dico
+   */
+  private List<ColumnConceptMappingDTO> getDicoFromConfiguration(final DataSetApplication datasetApp,
+          final String dicoToFind) throws SitoolsException {
+    List<ColumnConceptMappingDTO> colConceptMappingDTOList = null;
+
+    // Get the list of dictionnaries related to the datasetApplication
+    final List<DictionaryMappingDTO> dicoMappingList = datasetApp.getDictionaryMappings();
+    if (!Util.isSet(dicoMappingList) || dicoMappingList.isEmpty()) {
+      throw new SitoolsException("No mapping with VO concepts has been done. please contact the administrator");
+    }
+
+    // For each dictionary, find the interesting one and return the mapping SQLcolumn/concept
+    for (DictionaryMappingDTO dicoMappingIter : dicoMappingList) {
+      final String dicoName = dicoMappingIter.getDictionaryName();
+      if (dicoToFind.equals(dicoName)) {
+        colConceptMappingDTOList = dicoMappingIter.getMapping();
+        break;
+      }
+    }
+    return colConceptMappingDTOList;
+  }
+
+  /**
+   * Set Fields and columnSqlAliasList.
+   *
+   * @param fieldList List of fields to display on the VOTable
+   * @param columnList List of SQL column
+   * @param mappingList List of SQL column/concept
+   */
+  private void setFields(final List<Field> fieldList, final List<String> columnList, final List<ColumnConceptMappingDTO> mappingList) {
+
+    for (ColumnConceptMappingDTO mappingIter : mappingList) {
+
+      String id = null;
+      String name = null;
+      String ucd = null;
+      String utype = null;
+      String ref = null;
+      String datatype = null;
+      String width = null;
+      String precision = null;
+      String unit = null;
+      String type = null;
+      String xtype = null;
+      String arraysize = null;
+      String descriptionValue = null;
+      columnList.add(mappingIter.getColumnAlias());
+      final Concept concept = mappingIter.getConcept();
+      if (concept.getName() != null) {
+        name = concept.getName();
+      }
+      if (concept.getPropertyFromName("ID").getValue() != null) {
+        id = concept.getPropertyFromName("ID").getValue();
+      }
+      if (concept.getPropertyFromName("ucd").getValue() != null) {
+        ucd = concept.getPropertyFromName("ucd").getValue();
+      }
+      if (concept.getPropertyFromName("utype").getValue() != null) {
+        utype = concept.getPropertyFromName("utype").getValue();
+      }
+      if (concept.getPropertyFromName("ref").getValue() != null) {
+        ref = concept.getPropertyFromName("ref").getValue();
+      }
+      if (concept.getPropertyFromName("datatype").getValue() != null) {
+        datatype = concept.getPropertyFromName("datatype").getValue();
+      }
+      if (concept.getPropertyFromName("width").getValue() != null) {
+        width = concept.getPropertyFromName("width").getValue();
+      }
+      if (concept.getPropertyFromName("precision").getValue() != null) {
+        precision = concept.getPropertyFromName("precision").getValue();
+      }
+      if (concept.getPropertyFromName("unit").getValue() != null) {
+        unit = concept.getPropertyFromName("unit").getValue();
+      }
+      if (concept.getPropertyFromName("type").getValue() != null) {
+        type = concept.getPropertyFromName("type").getValue();
+      }
+      if (concept.getPropertyFromName("xtype").getValue() != null) {
+        xtype = concept.getPropertyFromName("xtype").getValue();
+      }
+      if (concept.getPropertyFromName("arraysize").getValue() != null) {
+        arraysize = concept.getPropertyFromName("arraysize").getValue();
+      }
+      if (concept.getDescription() != null) {
+        descriptionValue = concept.getDescription();
+      }
+      final Field field = new Field();
+      field.setID(id);
+      field.setName(name);
+      field.setUcd(ucd);
+      field.setUtype(utype);
+      field.setRef(ref);
+      field.setDatatype(DataType.fromValue(datatype));
+      if (width != null) {
+        field.setWidth(BigInteger.valueOf(Long.valueOf(width)));
+      }
+      field.setPrecision(precision);
+      field.setUnit(unit);
+      field.setType(type);
+      field.setXtype(xtype);
+      field.setArraysize(arraysize);
+      final AnyTEXT anyText = new AnyTEXT();
+      anyText.getContent().add(descriptionValue);
+      field.setDESCRIPTION(anyText);
+      fieldList.add(field);
+    }
+  }
+
+  /**
+   * Checks required mapping and filter columns to map according to VERB.
+   *
+   * @param mappingList list of mapping defined by the administrator
+   * @param verb VERB of Cone search protocol
+   * @return Returns the new mapping according to VERB
+   * @throws SitoolsException columns with UCD ID_MAIN, POS_EQ_RA_MAIN, POS_EQ_DEC_MAIN must be mapped
+   */
+  private List<ColumnConceptMappingDTO> checkRequiredMapping(final List<ColumnConceptMappingDTO> mappingList, final int verb)
+          throws SitoolsException {
+      
+    final int nbConceptToMap = SimpleSpectralAccessProtocolLibrary.REQUIRED_UCD_CONCEPTS.size();
+    int nbConcept = 0;
+    final List<ColumnConceptMappingDTO> conceptToMap = new ArrayList<ColumnConceptMappingDTO>(mappingList);
+    for (ColumnConceptMappingDTO mappingIter : mappingList) {
+      final Concept concept = mappingIter.getConcept();
+      final String ucdValue = concept.getPropertyFromName("ucd").getValue();
+      if (Util.isNotEmpty(ucdValue) && SimpleSpectralAccessProtocolLibrary.REQUIRED_UCD_CONCEPTS.contains(ucdValue)) {
+        nbConcept++;
+      } else if (verb == 1) {
+        conceptToMap.remove(mappingIter);
+      }
+    }
+    if (nbConceptToMap != nbConcept) {
+        
+      final StringBuilder buffer = new StringBuilder("columns with ");
+      for (ColumnConceptMappingDTO mappingIter : mappingList) {
+        buffer.append(mappingIter.getConcept().getName()).append(" ");
+      }
+      buffer.append("must be mapped");
+      throw new SitoolsException(buffer.toString());
+    }
+
+    return conceptToMap;
+
+  }
+ 
+  private void fillInfosParamAboutQuery(final ResourceModel model){
+    final List<Info> listQueryInfos = new ArrayList<Info>();
+    
+    final Info info = new Info();
+    info.setName("QUERY_STATUS");
+    info.setValueAttribute("OK");
+    listQueryInfos.add(info);
+    this.dataModel.put("queryInfos", listQueryInfos);
+   
+    final List<Param> listQueryParam = new ArrayList<Param>();
+    Param param = new Param();
+    param.setName("POS");
+    param.setValue(this.ra+","+this.dec);
+    param.setUnit("deg");
+    param.setDatatype(DataType.DOUBLE);
+    listQueryParam.add(param);
+
+//-------------------------- AJOUT POUR LE PROTOCOLE SSA --------------------------------------------
+    /*
+    param = new Param();
+    param.setName("TIME");
+    param.setValue(this.time.toString());
+    //param.setUnit("");
+    param.setDatatype(DataType.CHAR);
+    listQueryParam.add(param);
+    
+    param = new Param();
+    param.setName("BAND");
+    param.setValue(this.band.toString());
+    param.setUnit("m");
+    param.setDatatype(DataType.DOUBLE);
+    listQueryParam.add(param);
+    */
+    addTimeBandAndSize(listQueryParam);
+//**************************** FIN DU RAJOUT *********************************
+    param = new Param();
+    param.setName("FORMAT");
+    param.setValue(SimpleSpectralAccessProtocolLibrary.ParamStandardFormat.ALL.name().toLowerCase());
+    param.setDatatype(DataType.CHAR);
+    param.setArraysize("*");
+    listQueryParam.add(param);
+    
+    param = new Param();
+    param.setName("INTERSECT");
+    param.setValue(model.getParameterByName(SimpleSpectralAccessProtocolLibrary.INTERSECT).getValue());
+    param.setDatatype(DataType.CHAR);
+    listQueryParam.add(param);
+
+    param = new Param();
+    param.setName("VERB");
+    param.setValue(model.getParameterByName(SimpleSpectralAccessProtocolLibrary.VERB).getValue());
+    param.setDatatype(DataType.INT);
+    listQueryParam.add(param);
+    
+     dataModel.put("queryParams", listQueryParam);
+  }
+  
+  private List<Param> addTimeBandAndSize(List<Param> listOfParams){
+      // ADD TIME
+      if(this.time.length == 2){
+        Param param = new Param();
+        param.setName("TIME");
+        param.setValue("From : "+this.time[0]+" to "+this.time[1]);
+        param.setDatatype(DataType.CHAR);
+        listOfParams.add(param);
+      }else{
+        Param param = new Param();
+        param.setName("TIME");
+        param.setValue(this.time[0]);
+        param.setDatatype(DataType.CHAR);
+        listOfParams.add(param);
+      }
+      // ADD BAND
+      if(this.band.length == 2){
+          Double bandMin = this.band[0];
+          Double bandMax = this.band[1];
+          Param param = new Param();
+          param.setName("BAND");
+          param.setValue(bandMin.toString()+" , "+bandMax);
+          param.setUnit("m");
+          param.setDatatype(DataType.DOUBLE);
+          listOfParams.add(param);
+      }else{
+          Double bandValue =  this.band[0];
+          Param param = new Param();
+          param.setName("BAND");
+          param.setValue(bandValue.toString());
+          param.setUnit("m");
+          param.setDatatype(DataType.DOUBLE);
+        listOfParams.add(param);
+      }
+      // ADD SIZE 
+      /*
+      if(this.time.length == 2){
+        Param param = new Param();
+        param.setName("TIME");
+        param.setValue("From : "+this.time[0]+" to "+this.time[1]);
+        param.setDatatype(DataType.CHAR);
+        listOfParams.add(param);
+      }else{
+        Param param = new Param();
+        param.setName("TIME");
+        param.setValue(this.time[0]);
+        param.setDatatype(DataType.CHAR);
+        listOfParams.add(param);
+      }*/
+      return listOfParams;
+  }
+}
diff --git a/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/ssa/SqlGeometryFactory.java b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/ssa/SqlGeometryFactory.java
new file mode 100644
index 0000000..caa00ce
--- /dev/null
+++ b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/ssa/SqlGeometryFactory.java
@@ -0,0 +1,53 @@
+ /*******************************************************************************
+ * Copyright 2010-2013 CNES - CENTRE NATIONAL d'ETUDES SPATIALES
+ *
+ * This file is part of SITools2.
+ *
+ * SITools2 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * SITools2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with SITools2.  If not, see <http://www.gnu.org/licenses/>.
+ ******************************************************************************/
+package fr.ias.sitools.vo.ssa;
+
+/**
+ * Chooses the implementation of the SQL request
+ * based on the geometry intersection algorithm.
+ * @author Jean-Christophe Malapert <jean-christophe.malapert@cnes.fr>
+ */
+public final class SqlGeometryFactory {
+  /**
+   * Empty constructor.
+   */
+  private SqlGeometryFactory() {
+  }
+  /**
+   * Returns the Object responsible of creating the SQL request to send to the server.
+   *
+   * <p>
+   * The supported geometryIntersection is either CENTER or OVERLAPS otherwise
+   * an IllegalArgumentException is raised.
+   * </p>
+   * @param geometryIntersection Geometry Intersection algorithm
+   * @return the Object responsible of creating the SQL request to send to the server
+   */
+  public static AbstractSqlGeometryConstraint create(final String geometryIntersection) {
+    AbstractSqlGeometryConstraint result;
+    if ("OVERLAPS".equals(geometryIntersection)) {
+      result = new OverlapsModeIntersection();
+    } else if ("CENTER".equals(geometryIntersection)) {
+      result = new CenterModeIntersection();
+    } else {
+      throw new IllegalArgumentException("geometryMode " + geometryIntersection + " is unknown or not supported");
+    }
+    return result;
+  }
+}
diff --git a/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/tap/DataModelInterface.java b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/tap/DataModelInterface.java
new file mode 100644
index 0000000..d46bb42
--- /dev/null
+++ b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/tap/DataModelInterface.java
@@ -0,0 +1,36 @@
+ /*******************************************************************************
+ * Copyright 2010-2013 CNES - CENTRE NATIONAL d'ETUDES SPATIALES
+ *
+ * This file is part of SITools2.
+ *
+ * SITools2 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * SITools2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with SITools2.  If not, see <http://www.gnu.org/licenses/>.
+ ******************************************************************************/
+package fr.ias.sitools.vo.tap;
+
+import java.util.Map;
+
+/**
+ * Provides an interface to get the data model.
+ *
+ * @author Jean-Christophe Malapert
+ */
+public interface DataModelInterface {
+
+  /**
+   * Returns the data model.
+   *
+   * @return data model
+   */
+  Map getDataModel();
+}
diff --git a/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/tap/TableAccessProtocolAsynchronousResponse.java b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/tap/TableAccessProtocolAsynchronousResponse.java
new file mode 100644
index 0000000..619bc74
--- /dev/null
+++ b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/tap/TableAccessProtocolAsynchronousResponse.java
@@ -0,0 +1,82 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package fr.ias.sitools.vo.tap;
+
+import fr.cnes.sitools.extensions.astro.application.uws.common.Util;
+import fr.cnes.sitools.extensions.astro.application.uws.jobmanager.AbstractJobTask;
+import fr.cnes.sitools.xml.uws.v1.Job;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.logging.Level;
+import javax.xml.datatype.DatatypeConfigurationException;
+import net.ivoa.xml.uws.v1.ErrorSummary;
+import net.ivoa.xml.uws.v1.ErrorType;
+import net.ivoa.xml.uws.v1.ExecutionPhase;
+import org.restlet.engine.Engine;
+
+/**
+ *
+ * @author marc
+ */
+public class TableAccessProtocolAsynchronousResponse extends AbstractJobTask {
+
+    final TableAccessProtocolInputParameters inputParams;
+    
+    public TableAccessProtocolAsynchronousResponse(final TableAccessProtocolInputParameters inputParameters) {
+        this.inputParams = inputParameters;
+    }
+    
+    @Override
+    public void run() {
+        Engine.getLogger(TableAccessProtocolAsynchronousResponse.class.getName()).log(Level.SEVERE, "***************** JE SUIS DANS LE RUN !!!");
+        try {
+            setBlinker(Thread.currentThread());
+            setStartTime(Util.convertIntoXMLGregorian(new Date()));
+            setPhase(ExecutionPhase.EXECUTING);
+            final List<String> filenameList = createJob();
+            //createResults(filenameList);
+            setEndTime(Util.convertIntoXMLGregorian(new Date()));
+            setPhase(ExecutionPhase.COMPLETED);
+        } catch (DatatypeConfigurationException ex) {
+            Engine.getLogger(TableAccessProtocolAsynchronousResponse.class.getName()).log(Level.SEVERE, null, ex);
+            final ErrorSummary errorSumm = new ErrorSummary();
+            errorSumm.setMessage(ex.getMessage());
+            errorSumm.setType(ErrorType.FATAL);
+            errorSumm.setHasDetail(true);
+            setError(errorSumm);
+            setPhase(ExecutionPhase.ERROR);
+        } catch (Error error) {
+            Engine.getLogger(TableAccessProtocolAsynchronousResponse.class.getName()).log(Level.SEVERE, null, error);
+            final ErrorSummary errorSumm = new ErrorSummary();
+            errorSumm.setMessage(error.getMessage());
+            errorSumm.setType(ErrorType.FATAL);
+            errorSumm.setHasDetail(true);
+            setError(errorSumm);
+            setPhase(ExecutionPhase.ERROR);
+        }
+    }
+
+    private List<String> createJob(){
+        List<String> a = new ArrayList<String>();
+        Engine.getLogger(TableAccessProtocolAsynchronousResponse.class.getName()).log(Level.SEVERE,"+++++++++++++++++++++++");
+        
+        final String query = this.inputParams.getQuery();
+        a.add("Test");
+        Engine.getLogger(TableAccessProtocolAsynchronousResponse.class.getName()).log(Level.SEVERE,"+++++++++++++++++++++++ QUERY : "+query);
+        //final String format = String.valueOf(getParameterValue(TableAccessProtocolLibrary.FORMAT));
+        //final String lang = String.valueOf(getParameterValue(TableAccessProtocolLibrary.LANG));
+        Engine.getLogger(TableAccessProtocolAsynchronousResponse.class.getName()).log(Level.SEVERE,"+++++++++++++++++++++++ getJobInfo "+getJobInfo().toString());
+        return a;
+    }
+    
+    @Override
+    public Job getCapabilities() {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+    
+}
diff --git a/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/tap/TableAccessProtocolDataModelInterface.java b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/tap/TableAccessProtocolDataModelInterface.java
new file mode 100644
index 0000000..50be249
--- /dev/null
+++ b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/tap/TableAccessProtocolDataModelInterface.java
@@ -0,0 +1,34 @@
+ /*******************************************************************************
+ * Copyright 2010-2013 CNES - CENTRE NATIONAL d'ETUDES SPATIALES
+ *
+ * This file is part of SITools2.
+ *
+ * SITools2 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * SITools2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with SITools2.  If not, see <http://www.gnu.org/licenses/>.
+ ******************************************************************************/
+package fr.ias.sitools.vo.tap;
+import java.util.Map;
+
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+/**
+ *
+ * @author marc
+ */
+interface TableAccessProtocolDataModelInterface {
+     Map getDataModel();
+}
\ No newline at end of file
diff --git a/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/tap/TableAccessProtocolException.java b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/tap/TableAccessProtocolException.java
new file mode 100644
index 0000000..e2ee53f
--- /dev/null
+++ b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/tap/TableAccessProtocolException.java
@@ -0,0 +1,19 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package fr.ias.sitools.vo.tap;
+
+import fr.cnes.sitools.common.exception.SitoolsException;
+
+/**
+ * @author marc
+ */
+public class TableAccessProtocolException extends SitoolsException {
+
+    public TableAccessProtocolException(String message) {
+        super(message);
+    }
+}
diff --git a/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/tap/TableAccessProtocolInputParameters.java b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/tap/TableAccessProtocolInputParameters.java
new file mode 100644
index 0000000..03ec4f7
--- /dev/null
+++ b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/tap/TableAccessProtocolInputParameters.java
@@ -0,0 +1,179 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package fr.ias.sitools.vo.tap;
+
+import fr.cnes.sitools.dataset.DataSetApplication;
+import fr.cnes.sitools.plugins.resources.model.ResourceModel;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import net.ivoa.xml.votable.v1.Info;
+import org.restlet.Context;
+import org.restlet.Request;
+
+/**
+ *
+ * @author marc
+ */
+public class TableAccessProtocolInputParameters implements DataModelInterface {
+     
+    /**
+    * Data model that stores the metadata response of the service.
+    */
+    private final transient Map dataModel = new HashMap();
+    /**
+    * Request.
+    */
+    private final transient Request request;
+    /**
+    * Context.
+    */
+    private final transient Context context;
+    /**
+    * Application where this resources is linked.
+    */
+    private final transient DataSetApplication datasetApp;
+    /**
+    * Configuration parameters of this resource.
+    */
+    private final transient ResourceModel resourceModel;
+
+    private final String query;
+    private final String format;
+   
+    
+    /**
+    * Constructs the objet that returns the metadata of the service.
+    * @param datasetAppVal application
+    * @param requestVal request
+    * @param contextVal context
+    * @param resourceModelVal configuration parameters
+    */
+    public TableAccessProtocolInputParameters(final DataSetApplication datasetAppVal, final Request requestVal, final Context contextVal, final ResourceModel resourceModelVal) {
+        this.request = requestVal;
+        this.context = contextVal;
+        this.datasetApp = datasetAppVal;
+        this.resourceModel = resourceModelVal;
+        final String requestType = this.request.getResourceRef().getQueryAsForm().getFirstValue(TableAccessProtocolLibrary.REQUEST);
+        final String langRequest = this.request.getResourceRef().getQueryAsForm().getFirstValue(TableAccessProtocolLibrary.LANG);
+        final String phase = this.request.getResourceRef().getQueryAsForm().getFirstValue(TableAccessProtocolLibrary.PHASE);
+        this.query = this.request.getResourceRef().getQueryAsForm().getFirstValue(TableAccessProtocolLibrary.QUERY);
+        this.format = this.request.getResourceRef().getQueryAsForm().getFirstValue(TableAccessProtocolLibrary.FORMAT);
+        //if(langRequestTableAccessProtocolLibrary.langSupported.)
+        //fillMetadataFormat();
+    }
+    
+   /**
+   * Fills metadata response.
+   */
+  private void fillMetadataFormat() {
+      
+    this.dataModel.put("description", this.resourceModel.getParameterByName(TableAccessProtocolLibrary.DESCRIPTION).getValue());
+
+    final Info info = new Info();
+    info.setName("QUERY_STATUS");
+    info.setValueAttribute("OK");
+    final List<Info> listInfos = new ArrayList<Info>();
+    listInfos.add(info);
+    this.dataModel.put("infos", listInfos);
+   
+    /* ON EN N'A PAS BESOIN
+    final List<Param> listParam = new ArrayList<Param>();
+    Param param = new Param();
+    param.setName("INPUT:POS");
+    param.setValue("0,0");
+    param.setDatatype(DataType.DOUBLE);
+    AnyTEXT anyText = new AnyTEXT();
+    anyText.getContent().add("Search Position in the form ra,dec where ra and dec are given in decimal degrees in the ICRS coordinate system.");
+    param.setDESCRIPTION(anyText);
+    listParam.add(param);
+
+    param = new Param();
+    param.setName("INPUT:SIZE");
+    param.setValue("0.05");
+    param.setDatatype(DataType.DOUBLE);
+    anyText = new AnyTEXT();
+    anyText.getContent().add("Size of search region in the RA and Dec directions.");
+    param.setDESCRIPTION(anyText);
+    listParam.add(param);
+
+    param = new Param();
+    param.setName("INPUT:FORMAT");
+    param.setValue(TableAccessProtocolLibrary.ParamStandardFormat.ALL.name());
+    param.setDatatype(DataType.CHAR);
+    param.setArraysize("*");
+    AnyTEXT anyText = new AnyTEXT();
+    anyText.getContent().add("Requested format of result.");
+    param.setDESCRIPTION(anyText);
+    
+
+    //TODO : le faire pour chaque format
+    listParam.add(param);
+ ON EN N'A PAS BESOIN    
+    param = new Param();
+    param.setName("INPUT:INTERSECT");
+    param.setValue(this.resourceModel.getParameterByName(TableAccessProtocolLibrary.INTERSECT).getValue());
+    param.setDatatype(DataType.CHAR);
+    anyText = new AnyTEXT();
+    anyText.getContent().add("Choice of overlap with requested region.");
+    param.setDESCRIPTION(anyText);
+    listParam.add(param);
+
+    param = new Param();
+    param.setName("INPUT:VERB");
+    param.setValue(this.resourceModel.getParameterByName(TableAccessProtocolLibrary.VERB).getValue());
+    param.setDatatype(DataType.INT);
+    anyText = new AnyTEXT();
+    anyText.getContent().add("Verbosity level, controlling the number of columns returned.");
+    param.setDESCRIPTION(anyText);
+    listParam.add(param);
+
+    dataModel.put("params", listParam);
+
+    String dictionaryName = resourceModel.getParameterByName(TableAccessProtocolLibrary.DICTIONARY).getValue();
+    final List<String> columnList = new ArrayList<String>();
+    List<Field> fieldList = new ArrayList<Field>();
+    try {
+        List<ColumnConceptMappingDTO> mappingList = getDicoFromConfiguration(datasetApp, dictionaryName);
+        setFields(fieldList, columnList, mappingList);
+    }catch (SitoolsException ex) {
+             
+    }
+   */ 
+  }
+    
+    @Override
+    public final Map getDataModel() {
+      return Collections.unmodifiableMap(this.dataModel);
+    }
+
+    /* GETTER DE LA CLASSE */
+    public String getQuery() {
+        return query;
+    }
+    public String getFormat() {
+        return format;
+    }
+    public Context getContext() {
+        return context;
+    }
+
+    public Request getRequest() {
+        return request;
+    }
+    public DataSetApplication getDatasetApp() {
+        return datasetApp;
+    }
+
+    public ResourceModel getResourceModel() {
+        return resourceModel;
+    }
+ 
+}
diff --git a/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/tap/TableAccessProtocolLibrary.java b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/tap/TableAccessProtocolLibrary.java
new file mode 100644
index 0000000..d441c38
--- /dev/null
+++ b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/tap/TableAccessProtocolLibrary.java
@@ -0,0 +1,129 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package fr.ias.sitools.vo.tap;
+
+import fr.ias.sitools.vo.representation.VOTableRepresentation;
+import fr.cnes.sitools.dataset.DataSetApplication;
+import fr.cnes.sitools.plugins.resources.model.ResourceModel;
+import java.util.Map;
+import java.util.logging.Level;
+import org.restlet.Context;
+import org.restlet.Request;
+
+/**
+ *
+ * @author marc
+ */
+public class TableAccessProtocolLibrary {
+
+    public enum langSupported {
+
+        ADQL
+    };
+
+    public enum formatResultsSupported {
+
+        VOTABLE
+    };
+
+    // Pour la requete
+    public static final String FORMAT = "FORMAT";
+    public static final String QUERY = "QUERY";
+    public static final String LANG = "LANG";
+    public static final String PHASE = "PHASE";
+    public static final String REQUEST = "REQUEST";
+    // String pour décomposer la requete ADQL
+    public static final String SELECT = "SELECT";
+    public static final String FROM = "FROM";
+    public static final String WHERE = "WHERE";
+    public static final String SELECT_ALL = "*";
+    public static final String BLANCK = " ";
+
+    private transient DataSetApplication datasetApp;
+    private transient ResourceModel resourceModel;
+    private transient Request request;
+    private transient Context context;
+
+    /**
+     *
+     */
+    public static final String DICTIONARY = "PARAM_Dictionary";
+    //Pour les Metadata
+    /**
+     *
+     */
+    public static final String DESCRIPTION = "Description";
+    /**
+     *
+     */
+    public static final String INSTRUMENT = "Instrument";
+    /**
+     *
+     */
+    public static final String SERVICE_NAME = "Service Name";
+    /**
+     *
+     */
+    public static final String MAX_RECORDS = "Max records";
+
+    public TableAccessProtocolLibrary(final DataSetApplication datasetApp, final ResourceModel resourceModel, final Request request, final Context context) {
+        this.datasetApp = datasetApp;
+        this.resourceModel = resourceModel;
+        this.request = request;
+        this.context = context;
+    }
+
+    /**
+     * Fill data Model that will be used in the template.
+     *
+     * @return data model for the template
+     */
+    private Map fillDataModel() {
+        // init
+        Map dataModel = null;
+        Map<String, Object> map = this.request.getAttributes();
+        /*
+         String entityAsText = this.request.getEntityAsText(); 
+         String query1 = this.request.getResourceRef().getQuery();
+         String queryDecoded = this.request.getResourceRef().getQuery(true);
+         String queryNotDecoded = this.request.getResourceRef().getQuery(false);
+         */
+        String tapRequestType = this.request.getAttributes().get("tapRequestType").toString();
+        // Handling input parameters
+        final DataModelInterface inputParameters = new TableAccessProtocolInputParameters(datasetApp, request, this.context, this.resourceModel);
+        if (tapRequestType.equalsIgnoreCase("sync")) {
+            this.context.getLogger().log(Level.INFO, "JE SUIS DANS LE SYNC !!!");
+            // data model response
+            if (inputParameters.getDataModel().containsKey("infos")) {
+                dataModel = inputParameters.getDataModel();
+            } else {
+                final TableAccessProtocolDataModelInterface response = new TableAccessProtocolResponse((TableAccessProtocolInputParameters) inputParameters, resourceModel);
+                dataModel = response.getDataModel();
+            }
+        } else if (tapRequestType.equalsIgnoreCase("async")) {
+            this.context.getLogger().log(Level.INFO, "JE SUIS DANS LE ASYNC !!!");
+            TableAccessProtocolAsynchronousResponse asyncTask = new TableAccessProtocolAsynchronousResponse((TableAccessProtocolInputParameters) inputParameters);
+            asyncTask.run();
+            this.context.getLogger().log(Level.INFO, "Apres le run de la tache async !!!");
+            
+        } else {
+            this.context.getLogger().log(Level.INFO, "JE SUIS DANS NI SYNC NI ASYNC !!!");
+        }
+
+        return dataModel;
+    }
+
+    /**
+     * VOTable response.
+     *
+     * @return VOTable response
+     */
+    public final VOTableRepresentation getResponse() {
+        final Map dataModel = fillDataModel();
+        return new VOTableRepresentation(dataModel, "votable.ftl");
+    }
+
+}
diff --git a/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/tap/TableAccessProtocolResponse.java b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/tap/TableAccessProtocolResponse.java
new file mode 100644
index 0000000..6b1f392
--- /dev/null
+++ b/sitools-idoc/hesiod/javaExt/src/fr/ias/sitools/vo/tap/TableAccessProtocolResponse.java
@@ -0,0 +1,487 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package fr.ias.sitools.vo.tap;
+
+import adql.parser.ADQLParser;
+import adql.parser.ParseException;
+import adql.query.ADQLQuery;
+import adql.translator.ADQLTranslator;
+import adql.translator.PostgreSQLTranslator;
+import adql.translator.TranslationException;
+import fr.cnes.sitools.common.exception.SitoolsException;
+import fr.cnes.sitools.dataset.DataSetApplication;
+import fr.cnes.sitools.dataset.converter.business.ConverterChained;
+import fr.cnes.sitools.dataset.database.DatabaseRequest;
+import fr.cnes.sitools.dataset.database.DatabaseRequestFactory;
+import fr.cnes.sitools.dataset.database.DatabaseRequestParameters;
+import fr.cnes.sitools.dataset.database.common.DataSetExplorerUtil;
+import fr.cnes.sitools.dataset.dto.ColumnConceptMappingDTO;
+import fr.cnes.sitools.dataset.dto.DictionaryMappingDTO;
+import fr.cnes.sitools.dataset.model.Column;
+import fr.cnes.sitools.dataset.model.Predicat;
+import fr.cnes.sitools.dictionary.model.Concept;
+import fr.cnes.sitools.plugins.resources.model.ResourceModel;
+import fr.cnes.sitools.util.Util;
+import fr.ias.sitools.vo.representation.DatabaseRequestIasModel;
+import freemarker.template.TemplateSequenceModel;
+import java.math.BigInteger;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import net.ivoa.xml.votable.v1.AnyTEXT;
+import net.ivoa.xml.votable.v1.DataType;
+import net.ivoa.xml.votable.v1.Field;
+import net.ivoa.xml.votable.v1.Info;
+import net.ivoa.xml.votable.v1.Param;
+import org.restlet.Context;
+
+/**
+ *
+ * @author marc
+ */
+class TableAccessProtocolResponse implements TableAccessProtocolDataModelInterface { 
+    
+    /**
+    * Data model.
+    */
+    private final transient Map dataModel = new HashMap();
+    
+    /**
+    * Context 
+    **/
+    private final transient Context ctx;
+    
+    /**
+    * The ADQL Query
+    */
+    private final String adqlQuery;
+    
+    /**
+     * The Psql Query from the ADQL query
+     */
+    private transient String psqlQuery;
+    /**
+     * The col to query
+     */
+    private ArrayList<String> colsToQuery = new ArrayList<String>();
+    
+    private String clauseWhereToQuery;
+    
+    private String clauseLimit;
+    private int clauseLimitInt;
+    private String format;
+    
+    boolean isPrimaryKey;
+    
+    public TableAccessProtocolResponse(final TableAccessProtocolInputParameters inputParameters, final ResourceModel model) {        
+        this.format = inputParameters.getFormat();
+        this.adqlQuery = inputParameters.getQuery();
+        this.ctx = inputParameters.getContext();
+
+        if(this.adqlQuery == null || this.adqlQuery .equalsIgnoreCase("")){
+            // TO DO
+        }else{
+            processQuery();
+            createResponse(inputParameters, model); 
+        }
+    }
+
+    private void createResponse(final TableAccessProtocolInputParameters inputParameters, final ResourceModel model){
+
+
+        // On récupère le nom du dico
+        final String dictionaryName = model.getParameterByName(TableAccessProtocolLibrary.DICTIONARY).getValue();
+
+        //On set les params
+        setVotableParametersFromConfiguration(this.dataModel, model);
+        //On requete la base et on remplit le template
+        setVotableResource(inputParameters.getDatasetApp(), inputParameters, model, dictionaryName);
+
+        // On set le query_status à OK
+        setQueryInfos(model);
+   
+    }
+    // FONCTIONS PRIVATE
+    /**
+    * Creates the response based on Table.
+    *
+    * @param datasetApp Dataset application
+    * @param inputParameters Input Parameters
+    * @param model data model
+    * @param dictionaryName TAP dictionary
+    */
+    private void setVotableResource(final DataSetApplication datasetApp, final TableAccessProtocolInputParameters inputParameters,
+          final ResourceModel model, final String dictionaryName) {
+        
+        final List<Field> fieldList = new ArrayList<Field>();
+        final List<String> columnStringList = new ArrayList<String>();
+        final List<Column> columnList = datasetApp.getDataSet().getColumnModel();
+        
+        DatabaseRequest databaseRequest = null;
+        try {
+            // On récupère les columns
+
+            // On récupere le mapping
+            List<ColumnConceptMappingDTO> mappingList = getDicoFromConfiguration(datasetApp, dictionaryName);
+            
+            final DatabaseRequestParameters dbParams = setQueryParameters(datasetApp, model, inputParameters, mappingList);
+
+            // On récupère les colonnes à requeter
+            List<Column> listCol = getColumnToQuery(columnList);
+            listCol = checkPrimaryKeyAndAddItColTQuery(columnList, listCol);
+            // On envoie les colonnes à requeter
+            dbParams.setSqlVisibleColumns(listCol);
+            
+            // S'il y a un parametre Limit on le rajoute au parametre de requete
+            if(this.clauseLimitInt > 0)
+            {
+                dbParams.setMaxrows(this.clauseLimitInt);
+            }   
+            databaseRequest = DatabaseRequestFactory.getDatabaseRequest(dbParams);
+            databaseRequest.checkRequest();
+            // Execute query
+            databaseRequest.createRequest();
+
+            getCtx().getLogger().log(Level.FINEST, "-------- DB REQUEST : {0}", databaseRequest.getRequestAsString());
+
+            setFields(fieldList, columnStringList, mappingList, listCol);
+            
+            final int count = (databaseRequest.getCount() > dbParams.getPaginationExtend()) ? dbParams.getPaginationExtend() : databaseRequest.getCount();
+            dataModel.put("nrows", count);
+            dataModel.put("fields", fieldList);
+            dataModel.put("sqlColAlias", columnStringList);
+            
+            final ConverterChained converterChained = datasetApp.getConverterChained();
+            
+            //final TemplateSequenceModel rows = new DatabaseRequestModel(databaseRequest, converterChained);
+            final TemplateSequenceModel rows = new DatabaseRequestIasModel(databaseRequest, converterChained);
+
+            dataModel.put("rows", rows);
+        } catch (SitoolsException ex) {
+            Logger.getLogger(TableAccessProtocolResponse.class.getName()).log(Level.SEVERE, null, ex);
+        }            
+    }
+    
+    /**
+   * Set Query parameters to the database.
+   *
+   * @param datasetApp Dataset Application
+   * @param model Data model
+   * @param inputParameters Input Parameters
+   * @return DatabaseRequestParamerters object
+   */
+  @SuppressWarnings("empty-statement")
+  private DatabaseRequestParameters setQueryParameters(final DataSetApplication datasetApp, final ResourceModel model,
+          final TableAccessProtocolInputParameters inputParameters, List<ColumnConceptMappingDTO> mappingList) {
+
+    // Get the dataset
+    final DataSetExplorerUtil dsExplorerUtil = new DataSetExplorerUtil(datasetApp, inputParameters.getRequest(),
+            inputParameters.getContext());
+
+    // Get query parameters
+    final DatabaseRequestParameters dbParams = dsExplorerUtil.getDatabaseParams();
+    // Get dataset records
+    final int nbRecordsInDataSet = datasetApp.getDataSet().getNbRecords();
+
+    // Get max records that is defined by admin
+    int nbMaxRecords = Integer.valueOf(model.getParameterByName(TableAccessProtocolLibrary.MAX_RECORDS).getValue());
+    nbMaxRecords = (nbMaxRecords > nbRecordsInDataSet || nbMaxRecords == -1) ? nbRecordsInDataSet : nbMaxRecords;
+    // if a limit clause is defined, used it.
+    if(this.clauseLimit != null){        
+        nbMaxRecords = Integer.parseInt(this.clauseLimit);
+    }
+    // Set max records
+    dbParams.setPaginationExtend(nbMaxRecords);
+    
+    
+    
+    final List<Predicat> predicatList = dbParams.getPredicats();
+    //String customQuery = "AND ra > 25 and dec < 180 and flux > 0.256";
+    Predicat predicat = new Predicat();
+    
+    predicat.setStringDefinition(this.clauseWhereToQuery);
+    predicatList.add(predicat);
+    dbParams.setPredicats(predicatList);
+    
+    return dbParams;
+  }
+
+    
+    private void setQueryInfos(final ResourceModel model){
+        final List<Info> queryInfos = new ArrayList<Info>();
+        
+        Info info = new Info();
+        info.setName("QUERY_STATUS");
+        info.setValueAttribute("OK");
+        queryInfos.add(info);
+        info = new Info();
+        info.setName("ADQL query");
+        String query = this.adqlQuery.replaceAll("\"", "").replaceAll(">","&gt;").replaceAll("<","&lt;");
+        info.setValueAttribute(query);
+        
+        queryInfos.add(info);
+
+        this.dataModel.put("queryInfos", queryInfos);
+    }
+    /**
+   * Sets VOTable parameters coming from administration configuration.
+   *
+   * @param dataModel data model to set
+   * @param model parameters from administration
+   */
+  private void setVotableParametersFromConfiguration(final Map dataModel, final ResourceModel model) {
+    final List<Param> params = new ArrayList<Param>();
+    setVotableParam(params, model, TableAccessProtocolLibrary.INSTRUMENT, DataType.CHAR);
+    setVotableParam(params, model, TableAccessProtocolLibrary.SERVICE_NAME, DataType.CHAR);
+    if (Util.isSet(params)) {
+      this.dataModel.put("params", params);
+    }
+  }
+
+  /**
+   * Sets Votable Param.
+   *
+   * @param params List of params
+   * @param model data model
+   * @param parameterName parameter name
+   * @param datatype datatype
+   */
+  private void setVotableParam(final List<Param> params, final ResourceModel model, final String parameterName,
+          final DataType datatype) {
+    final String parameterValue = model.getParameterByName(parameterName).getValue();
+    if (Util.isNotEmpty(parameterValue)) {
+        final Param param = new Param();
+        param.setName(parameterName);
+        param.setValue(parameterValue);
+        param.setDatatype(datatype);
+        params.add(param);
+    }
+  }
+    /**
+    * Provide the mapping between SQL column/concept for a given dictionary.
+    *
+    * @param datasetApp Application where this service is attached
+    * @param dicoToFind Dictionary name to find
+    * @return Returns a mapping SQL column/Concept
+    * @throws SitoolsException No mapping has been done or cannot find the dico
+    */
+    private List<ColumnConceptMappingDTO> getDicoFromConfiguration(final DataSetApplication datasetApp,
+          final String dicoToFind) throws SitoolsException {
+        List<ColumnConceptMappingDTO> colConceptMappingDTOList = null;
+        
+        // Get the list of dictionnaries related to the datasetApplication
+        final List<DictionaryMappingDTO> dicoMappingList = datasetApp.getDictionaryMappings();
+        if (!Util.isSet(dicoMappingList) || dicoMappingList.isEmpty()) {
+          throw new SitoolsException("No mapping with VO concepts has been done. please contact the administrator");
+        }
+
+        // For each dictionary, find the interesting one and return the mapping SQLcolumn/concept
+        for (DictionaryMappingDTO dicoMappingIter : dicoMappingList) {
+          final String dicoName = dicoMappingIter.getDictionaryName();
+          if (dicoToFind.equals(dicoName)) {
+            colConceptMappingDTOList = dicoMappingIter.getMapping();
+            break;
+          }
+        }
+        return colConceptMappingDTOList;
+    }
+    
+    
+    private List<Column> getColumnToQuery(List<Column> columnList){
+        List<Column> colsToQueryList = new ArrayList<Column>();
+        String all = this.adqlQuery.split(TableAccessProtocolLibrary.SELECT)[1].split(TableAccessProtocolLibrary.FROM)[0];      
+        if(this.colsToQuery.size() == 1 && all.contains("*")){
+            for(Column colCol : columnList){ 
+                colsToQueryList.add(colCol);
+            }
+            return colsToQueryList;
+        }
+        for(String col : this.colsToQuery){          
+            for(Column colCol : columnList){            
+                if(col.equalsIgnoreCase(colCol.getColumnAlias())){
+                    colsToQueryList.add(colCol);
+                }
+            }
+        }
+        
+        return colsToQueryList;
+    }
+    
+    /**
+   * Set Fields and columnSqlAliasList.
+   *
+   * @param fieldList List of fields to display on the VOTable
+   * @param colToQuery List of column to query and so to display in VOTable
+   * @param columnList List of SQL column
+   * @param mappingList List of SQL column/concept
+   */
+  private void setFields(final List<Field> fieldList, final List<String> columnList, final List<ColumnConceptMappingDTO> mappingList, final List<Column> colToQuery) {
+    
+    List<Column> colToQuery2 = colToQuery;
+    if(!isPrimaryKey){
+        colToQuery2.remove(colToQuery2.size()-1);
+    }
+    for(Column col : colToQuery2){
+        
+        for (ColumnConceptMappingDTO mappingIter : mappingList) {
+            if(col.getColumnAlias().equalsIgnoreCase(mappingIter.getColumnAlias())){
+                
+                String id = null;
+                String name = null;
+                String ucd = null;
+                String utype = null;
+                String ref = null;
+                String datatype = null;
+                String width = null;
+                String precision = null;
+                String unit = null;
+                String type = null;
+                String xtype = null;
+                String arraysize = null;
+                String descriptionValue = null;
+                columnList.add(mappingIter.getColumnAlias());
+                final Concept concept = mappingIter.getConcept();
+                if (concept.getName() != null) {
+                  name = concept.getName();
+                }
+                if (concept.getPropertyFromName("ID").getValue() != null) {
+                  id = concept.getPropertyFromName("ID").getValue();
+                }
+                if (concept.getPropertyFromName("ucd").getValue() != null) {
+                  ucd = concept.getPropertyFromName("ucd").getValue();
+                }
+                if (concept.getPropertyFromName("utype").getValue() != null) {
+                  utype = concept.getPropertyFromName("utype").getValue();
+                }
+                if (concept.getPropertyFromName("ref").getValue() != null) {
+                  ref = concept.getPropertyFromName("ref").getValue();
+                }
+                if (concept.getPropertyFromName("datatype").getValue() != null) {
+                  datatype = concept.getPropertyFromName("datatype").getValue();
+                }
+                if (concept.getPropertyFromName("width").getValue() != null) {
+                  width = concept.getPropertyFromName("width").getValue();
+                }
+                if (concept.getPropertyFromName("precision").getValue() != null) {
+                  precision = concept.getPropertyFromName("precision").getValue();
+                }
+                if (concept.getPropertyFromName("unit").getValue() != null) {
+                  unit = concept.getPropertyFromName("unit").getValue();
+                }
+                if (concept.getPropertyFromName("type").getValue() != null) {
+                  type = concept.getPropertyFromName("type").getValue();
+                }
+                if (concept.getPropertyFromName("xtype").getValue() != null) {
+                  xtype = concept.getPropertyFromName("xtype").getValue();
+                }
+                if (concept.getPropertyFromName("arraysize").getValue() != null) {
+                  arraysize = concept.getPropertyFromName("arraysize").getValue();
+                }
+                if (concept.getDescription() != null) {
+                  descriptionValue = concept.getDescription();
+                }
+                final Field field = new Field();
+                field.setID(id);
+                field.setName(name);
+                field.setUcd(ucd);
+                field.setUtype(utype);
+                field.setRef(ref);
+                field.setDatatype(DataType.fromValue(datatype));
+                if (width != null) {
+                  field.setWidth(BigInteger.valueOf(Long.valueOf(width)));
+                }
+                field.setPrecision(precision);
+                field.setUnit(unit);
+                field.setType(type);
+                field.setXtype(xtype);
+                field.setArraysize(arraysize);
+                final AnyTEXT anyText = new AnyTEXT();
+                anyText.getContent().add(descriptionValue);
+                field.setDESCRIPTION(anyText);
+                fieldList.add(field);
+            }
+        }
+    }
+  }
+  //List<Column> columnList = datasetApp.getDataSet().getColumnModel();
+  private List<Column> checkPrimaryKeyAndAddItColTQuery(List<Column> columnList, List<Column> colToQuery){
+      Column colPrimKey = null;
+      for(Column co : columnList){
+          if(co.isPrimaryKey()){
+              colPrimKey = co;
+          }
+      }
+      for(Column col : colToQuery){
+          if(col.isPrimaryKey()){
+              isPrimaryKey = true; 
+          }
+      }
+      if(!isPrimaryKey &&  "" != colPrimKey.getColumnAlias()){
+          colToQuery.add(colPrimKey);
+      }
+      
+      return colToQuery;
+  }
+    
+    private void processQuery(){
+        try {
+            // On crée un parser pour transformer notre string query en adql query
+            ADQLParser parser = new ADQLParser();
+            ADQLQuery adqlQueryValue = parser.parseQuery(this.adqlQuery);
+            // On traduit l'adql query en psql query
+            ADQLTranslator translator = new PostgreSQLTranslator();
+
+            this.psqlQuery = translator.translate(adqlQueryValue);
+            ctx.getLogger().log(Level.SEVERE, "#### ADQL request : "+this.adqlQuery);
+            ctx.getLogger().log(Level.SEVERE, "#### PSQL request : "+this.psqlQuery);
+
+            if(this.psqlQuery.contains("Limit ")){
+                this.clauseLimit = this.psqlQuery.split("Limit ")[1];
+                this.clauseLimitInt = Integer.parseInt(this.clauseLimit.replaceAll(" ", ""));
+                this.psqlQuery = this.psqlQuery.split("Limit ")[0];
+            }else{
+                this.clauseLimit = null;
+                this.clauseLimitInt = -1;
+            }
+
+            this.clauseWhereToQuery = "AND"+ this.psqlQuery.split(TableAccessProtocolLibrary.FROM)[1].split(TableAccessProtocolLibrary.WHERE)[1];  
+
+            String[] colsToQueryTmp = this.psqlQuery.split(TableAccessProtocolLibrary.FROM)[0].split(TableAccessProtocolLibrary.SELECT)[1].split(",");
+            for(String col : colsToQueryTmp){
+                if(col.equalsIgnoreCase(TableAccessProtocolLibrary.SELECT_ALL)){
+                    colsToQuery.add(col.replaceAll(TableAccessProtocolLibrary.BLANCK, ""));
+                    break;
+                }else{
+                    colsToQuery.add(col.split("AS")[0].replaceAll(TableAccessProtocolLibrary.BLANCK, ""));
+                }
+            }
+            if(format == null || format.equalsIgnoreCase("")){
+                // TO DO
+            }else{
+                ctx.getLogger().log(Level.INFO, "format = "+format);
+            }
+        } catch (TranslationException ex) {
+            Logger.getLogger(TableAccessProtocolResponse.class.getName()).log(Level.SEVERE, null, ex);
+        } catch (ParseException ex) {
+            Logger.getLogger(TableAccessProtocolResponse.class.getName()).log(Level.SEVERE, null, ex);
+        }
+  }
+    @Override
+    public final Map getDataModel() {
+        return Collections.unmodifiableMap(this.dataModel);
+    }
+    
+    // GETTER DE LA CLASSE
+    public Context getCtx() {
+        return ctx;
+    }
+}
diff --git a/sitools-idoc/hesiod/js/workspace/client-user/js/components/datasetServices/viewCubeService.js b/sitools-idoc/hesiod/js/workspace/client-user/js/components/datasetServices/viewCubeService.js
new file mode 100644
index 0000000..d4c3761
--- /dev/null
+++ b/sitools-idoc/hesiod/js/workspace/client-user/js/components/datasetServices/viewCubeService.js
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright 2010-2013 CNES - CENTRE NATIONAL d'ETUDES SPATIALES
+ * 
+ * This file is part of SITools2.
+ * 
+ * SITools2 is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ * 
+ * SITools2 is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * SITools2. If not, see <http://www.gnu.org/licenses/>.
+ ******************************************************************************/
+/*global Ext, sitools, ID, i18n, document, showResponse, alertFailure, LOCALE, ImageChooser, loadUrl, extColModelToStorage, SitoolsDesk, WARNING_NB_RECORDS_PLOT*/
+
+Ext.namespace('sitools.user.component.dataviews.services');
+
+/**
+ * service used to show the plot
+ * 
+ * @required datasetId
+ * @required datasetUrl
+ * @cfg {Ext.data.JsonStore} the store where nodes are saved
+ * @class sitools.user.component.dataviews.services.addSelectionService
+ * @extends Ext.Window
+ */
+sitools.user.component.dataviews.services.viewCubeService = {};
+
+Ext.reg('sitools.user.component.dataviews.services.viewCubeService', sitools.user.component.dataviews.services.viewCubeService);
+
+sitools.user.component.dataviews.services.viewCubeService.getParameters = function () {
+	return [];
+};
+
+sitools.user.component.dataviews.services.viewCubeService.getDefaultParameters = function () {
+	console.log("Je suis dans le sitools.user.component.dataviews.services.viewCubeService ");
+	return [{
+			name : "featureType",
+			value : "URL"
+		}, {
+			name : "columnAlias",
+			value : "cube"
+		}];
+};
+
+sitools.user.component.dataviews.services.viewCubeService.executeAsService = function (config) {
+
+    var grid = config.dataview;
+    var datasetId = grid.datasetId;
+    var datasetUrl = grid.sitoolsAttachementForUsers;
+    var datasetName = grid.datasetName;
+    //var sortInfo = grid.getSortInfo();
+    var colModel = config.columnModel;
+
+    
+   /* Ext.each(config.parameters, function (param) {
+        if (param.name === "columnAlias") {
+        	columnAlias = param.value;
+        }
+    }, this);
+    */
+    var jsObj = sitools.user.component.viewCubeService;
+    var componentCfg = {
+        dataUrl : datasetUrl,
+        datasetName : datasetName,
+        datasetId : datasetId,
+        componentType : "viewCube",
+        preferencesPath : "/" + datasetName,
+        preferencesFileName : "viewCube",
+        dataview : config.dataview,
+        columnAlias : config.columnAlias,
+	record : config.record,
+        columnModel : colModel
+    };
+    var windowConfig = {
+        id : "viewCube" + datasetId,
+        title : "View cube : " + datasetName,
+        iconCls : "viewCube",
+        datasetName : datasetName,
+        type : "viewCube",
+        saveToolbar : true,
+    };
+    SitoolsDesk.addDesktopWindow(windowConfig, componentCfg, jsObj);
+};
diff --git a/sitools-idoc/hesiod/js/workspace/client-user/js/components/viewCube/viewCubeFits.js b/sitools-idoc/hesiod/js/workspace/client-user/js/components/viewCube/viewCubeFits.js
new file mode 100644
index 0000000..e1162d7
--- /dev/null
+++ b/sitools-idoc/hesiod/js/workspace/client-user/js/components/viewCube/viewCubeFits.js
@@ -0,0 +1,745 @@
+/***************************************
+* Copyright 2010-2013 CNES - CENTRE NATIONAL d'ETUDES SPATIALES
+* 
+* This file is part of SITools2.
+* 
+* SITools2 is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+* 
+* SITools2 is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+* 
+* You should have received a copy of the GNU General Public License
+* along with SITools2.  If not, see <http://www.gnu.org/licenses/>.
+***************************************/
+/*global Ext, sitools, projectGlobal, commonTreeUtils, showResponse, DEFAULT_PREFERENCES_FOLDER, 
+ document, i18n, $, Flotr, userLogin, SitoolsDesk, sql2ext, loadUrl,SitoolsDesk,,
+ SITOOLS_DATE_FORMAT, SITOOLS_DEFAULT_IHM_DATE_FORMAT, DEFAULT_LIVEGRID_BUFFER_SIZE*/
+/*
+ * @include "../viewDataDetail/viewDataDetail.js"
+ * @include "../../sitoolsProject.js"
+ * @include "../../desktop/desktop.js"
+ * @include "../../desktop/navProfile/fixed.js"
+ */
+/**
+ * 
+ * <a href="https://sourceforge.net/tracker/?func=detail&aid=3313793&group_id=531341&atid=2158259">[3313793]</a><br/>
+ * 16/06/2011 m.gond {Display the right number of data plotted} <br/>
+ * 
+ * ExtJS layout for plotting data
+ */
+
+Ext.namespace('sitools.user.component');
+/**
+ * @cfg {String} dataUrl the dataset url attachment
+ * @cfg {} columnModel the dataset's column model
+ * @cfg {} filters the list of filters to apply (filters from the dataview)
+ * @cfg {String} selections the selections as a String to add to the URL (selections from the dataview) 
+ * @cfg {String} datasetName the name of the dataset
+ * @cfg {} formParam list of parameters from a query form
+ * @cfg {} formMultiDsParams list of parameters from a multidataset query form
+ * @cfg {String} datasetId the id of the dataset
+ * @cfg {string} componentType Should be "plot"
+ * @requires sitools.user.component.viewDataDetail
+ * @class sitools.user.component.viewCubeService
+ * @extends Ext.Panel
+ */
+
+sitools.user.component.viewCubeService = function (config) {
+
+	Ext.apply(this, config);
+	
+   this.datasetName = config.datasetName;
+   this.datasetId = config.datasetId;
+   this.columnModel = config.columnModel;
+   var mapCanvasID,selCanvasID,canHistoID,sliderColorID,controlHistoID;
+    
+   var rec;
+	if (Ext.isEmpty(this.record)) {
+		rec = config.dataview.getSelections()[0];
+   }else{ 
+   	rec = this.record;
+	}
+	
+	var naxis1, naxis2, naxis3, sizePix;
+
+	var selectionType = "pixel";
+	var slice;
+	var imageSlice;
+	var limitVal = [];
+	var pixelSelected = [];
+	var colors = [];
+	
+	this.tabPanel = new Ext.TabPanel({ name:'tabPanel',region : 'center',autoScroll : true});
+	var itemsTab = [];
+	
+	this.panels = new Ext.Panel({ name:'panels', title: 'Cube Explorer', layout: 'table', layoutConfig: {columns:2},autoScroll : true });
+	var itemsPanels = [];
+
+    // Searching for primary key name
+	var primaryKeyName = "";
+	Ext.each(rec.fields.items, function (field) {
+        if (field.primaryKey) { primaryKeyName = field.name; }
+    });
+	var primaryKeyValue = rec.get(primaryKeyName);
+	var request = "?1=1&p[0]=LISTBOXMULTIPLE|" + primaryKeyName + "|" + primaryKeyValue + "|";
+	
+	Ext.Ajax.on('beforerequest', function(connection,options){ Ext.getBody().mask('Retrieving data from fits file...'); });
+	Ext.Ajax.on('requestcomplete', function(connection,options){ Ext.getBody().unmask(); });
+	Ext.Ajax.on('requestexception', function(connection,options){ Ext.getBody().unmask(); });
+
+	Ext.Ajax.request({
+   	url : this.dataview.sitoolsAttachementForUsers+"/plugin/getFitsDataSpectro"+request,
+      method : "GET",
+      scope : this,
+      waitMsg : 'Processing your request...',
+      success : function (ret) { 
+      	var json = Ext.decode(ret.responseText);
+			naxis1 = json.NAXIS1;
+			naxis2 = json.NAXIS2;
+			naxis3 = json.NAXIS3;
+			var imageWidth, imageHeight;
+			var margin = 0;
+			var destopHeight = Ext.get("x-desktop").getHeight() - 50 - 4*margin;
+    		var destopWidth = Ext.get("x-desktop").getWidth();
+			var controlHeight = 200;
+			var controlWidth = 400;
+			var imageHeightWanted = destopHeight - controlHeight;
+	
+		sizePix = Math.floor(imageHeightWanted/naxis2);
+		imageWidth = naxis1 * sizePix;
+		imageHeight = naxis2 * sizePix;
+		slice = parseInt(naxis3/2);
+	   var layersZone = "";
+   	// layer for map
+   	mapCanvasID = "mapCanvas"+getAnId();
+	   layersZone = layersZone + '<canvas id="'+mapCanvasID+'"+ style="z-index: 1; position:absolute; left:0px; top:0px;" width="'+imageWidth+'" height="'+imageHeight+'"></canvas>';
+   	// layer for selection tool 
+   	selCanvasID = "selCanvas"+getAnId();
+	   layersZone = layersZone + '<canvas id="'+selCanvasID+'" style="z-index: 2; position:absolute; left:0px; top:0px;" width="'+imageWidth+'" height="'+imageHeight+'"></canvas>';
+   	
+   	var map = new Ext.Panel({
+	   	id: 'panelImage',
+   	 	region: 'west',
+    		html: layersZone,
+	    	width: imageWidth,
+   	 	height: imageHeight,
+		});
+   	itemsPanels.push(map);
+
+		var spectrum = new Ext.Panel({
+   		id: 'panelSpectrum',
+	    	rowspan: 2,
+   	 	width: destopWidth-Math.max(controlWidth,imageWidth),
+    		height: destopHeight,
+		});
+   	itemsPanels.push(spectrum);
+
+   	var sliderDepth = new Ext.Slider({
+   		id: 'sliderDepthID',
+	    	width: 114,
+   	 	minValue: 0,
+    		maxValue: json.WAVE.length-1,
+	    	value: parseInt(naxis3/2),
+   	 	listeners : {
+    			change: function(slider){
+    	   		slice = slider.getValue();
+    	      	plotColorHisto(slice,json,0,100);
+	    	      Ext.getCmp('sliderColorID').setValue(0,0,false);
+   	 	      Ext.getCmp('sliderColorID').setValue(1,100,false);
+    		      drawMap(sizePix,json,slice,false,[]);
+    	   	   Ext.getCmp('wave').setValue('<b>'+slice+' - '+json.WAVE[slice].toFixed(2)+' ('+json.UNIT_WAVE+')</b>');
+    	      	plotSpectra(pixelSelected,selectionType,json,spectrum,slice);
+				},
+	    	   dragend: function(slider){
+   	 	   	slice = slider.getValue();
+    		      limitVal = [];//plotColorHisto(slice,json,0,100);
+    	   	   plotColorHisto(slice,json,0,100);
+    	      	drawMap(sizePix,json,slice,false,[]);
+				}
+			}     
+		});
+    	canHistoID= "canHisto"+getAnId();
+   	var colorHisto = new Ext.Panel({
+   		html: '<canvas id="'+canHistoID+'" width="'+120+'" height="'+50+'"></canvas>',
+   		width: 120,
+    		height: 50
+   	});
+    	sliderColorID = "sliderColor"+getAnId();
+   	var sliderColor = new Ext.slider.MultiSlider({
+   		id: sliderColorID,
+    		width: 114,//parseInt(imageWidth/4),
+    		minValue: 0,
+    		maxValue: 100,
+    		values: [0,100],
+    		listeners : {
+    			change: function(slider){
+    	   		limitVal = plotColorHisto(slice,json,slider.thumbs[0].value,slider.thumbs[1].value);
+    	      	drawMap(sizePix,json,slice,false,limitVal);
+    	   	},
+    	   	dragend: function(slider){
+    	   		limitVal = plotColorHisto(slice,json,slider.thumbs[0].value,slider.thumbs[1].value);
+    	      	drawMap(sizePix,json,slice,false,limitVal);
+    	   	}
+   		}
+		});
+    	controlHistoID = "controlHisto"+getAnId();
+		var controlHisto = new Ext.Panel({
+   		id: controlHistoID,
+	    	fieldLabel: "Slice color scale",
+   	 	heigth: controlHeight,
+      	xtype: 'compositefield',
+      	items   : [ sliderColor, colorHisto ]
+		});
+		controlPanelID = "controlPanel"+getAnId();
+   	var controlForm = new Ext.form.FormPanel({
+   		id: controlPanelID,
+    		heigth: controlHeight,
+    		width: controlWidth,
+	    	items   : [{
+   	 	           	fieldLabel: 'Coordinates',
+    		            xtype: 'compositefield',
+    	   	         items: [{ xtype: 'displayfield', value: 'RA'},
+    	      	              { xtype: 'displayfield', id: 'ra_field', name : 'ra', width: 75 },
+    	         	           { xtype: 'displayfield', value: 'DEC'},
+    	            	        { xtype: 'displayfield', id: 'dec_field', name : 'dec', width: 75  }]
+	    	           },
+   	 	           {
+      	  		    	fieldLabel: 'Selection Type',
+        			    	xtype: 'compositefield',
+        			    	padding: '5px',
+        		   	 	items: [{xtype: 'radiogroup',
+        		    		        	width: parseInt(imageWidth/2),
+	        	        		      listeners: {
+   	     	        		      	change:function( radiogroup, newValue ) {
+      	  	        	            	selectionType = newValue.inputValue;
+// ORIGINAL        		        	               can = document.getElementById('selCanvas');
+        										can = document.getElementById(selCanvasID);        	               
+        	   	     	               clearArea(can);
+        		   	 	        			pixelSelected = [];
+        		    		        			plotSpectra(pixelSelected,selectionType,json,spectrum,slice);
+        	        	   	            drawSelectionPlot(sizePix,spectrum,json,selectionType);
+        	        	      	      }
+        	        	         	},
+        	        		        	items: [{ inputValue: 'pixel', boxLabel: 'Pixel(s)', name: 'radioGroup', checked: true},
+        	        		         	  	 { inputValue: 'line',  boxLabel: 'Line',     name: 'radioGroup' }/*,*/
+        	        		        	]
+        		    	        	},{
+        		    	        		xtype: 'button',
+        		    	        		width: 50,
+        		    	        		height: 30,
+        		    	        		text: 'Clear',
+        		    	        		handler: function(){
+ // ORIGINAL        		        	               can = document.getElementById('selCanvas');
+        									can = document.getElementById(selCanvasID);
+        		    	        			clearArea(can);
+        		    	        			pixelSelected = [];
+        		    	        			plotSpectra(pixelSelected,selectionType,json,spectrum,slice);
+        		    	        		} 
+        		    	        }	        		    	        
+        		    	    ]
+    	          },{
+        		    		fieldLabel: 'Cube Depth Index',
+        		    		xtype: 'compositefield',
+        		    		items: [sliderDepth,{id: 'wave',	xtype: 'displayfield',value: '<b>'+sliderDepth.getValue()+' - '+json.WAVE[sliderDepth.getValue()].toFixed(2)+' ('+json.UNIT_WAVE+')</b>'/*,*/}]		        		   
+        		    	},
+        		    		controlHisto
+        		 	]
+    	});
+    	itemsPanels.push(controlForm);
+    	this.panels.add(itemsPanels);
+    	this.panels.doLayout();	        		        		
+    	itemsTab.push(this.panels);
+    	var headerPanel = new Ext.Panel({
+    		title: 'Header(s)',
+    		id: 'headerPanel',
+    		autoScroll: true,
+    		layout: 'accordion',
+    		width: imageWidth+(imageHeight+controlHeight),
+    		height: imageHeight+controlHeight,
+		});
+    		
+    	itemsAccordion = [];
+    	nbreHDUs = json.HDUs;
+    	for (var i=0; i<nbreHDUs; i++){
+    		var extension = "";
+    		var extensionName = "Header "+i;
+    		if (i==0) {extensionName = "Primary";}
+    		var jsonHeader = [];
+    		for (var j = 0; j < json.HEADERSGRID[i].length; j++) {
+    			if (json.HEADERSGRID[i][j][0]=="EXTNAME") {extensionName=json.HEADERSGRID[i][j][1];}
+    			if (json.HEADERSGRID[i][j][0]=="XTENSION") {extension=json.HEADERSGRID[i][j][1];}
+    			extensionName = extensionName.charAt(0).toUpperCase() + extensionName.slice(1).toLowerCase();
+    			jsonHeader.push({
+    		        key: json.HEADERSGRID[i][j][0],
+    		        value: json.HEADERSGRID[i][j][1],
+    		        description: json.HEADERSGRID[i][j][2]
+    		   });
+    		}
+    		var storeHeader = new Ext.data.JsonStore({
+    			fields : ['key','value','description'],
+    		}); 
+    		storeHeader.loadData(jsonHeader, false); 
+    		var gridHeader = new Ext.grid.GridPanel({
+         	title: "<html><b>"+i+" - "+extensionName+" - <font color='red'>"+extension+"</font></b></html>",
+            autoScroll: true,
+            layout: 'fit',
+    			store : storeHeader,
+    		   colModel: new Ext.grid.ColumnModel({
+    		   	columns: [{header: 'Key', width: 200, dataIndex: 'key', sortable: true},
+    		                {header: 'Value', width: 300, dataIndex: 'value'},
+    		                {header: 'Description', width: 600, dataIndex: 'description'},
+    		               ]
+    		      })
+    		}); 
+    		itemsAccordion.push(gridHeader);
+    	}
+    	headerPanel.add(itemsAccordion);
+  		itemsTab.push(headerPanel);
+  		this.tabPanel.add(itemsTab);
+  		this.tabPanel.setActiveTab(0);
+  		this.tabPanel.doLayout();
+    		        		
+  		plotColorHisto(slice,json,0,100);
+  		drawMap(sizePix,json,slice,true,limitVal);
+  		plotSpectra(pixelSelected,selectionType,json,spectrum,slice);
+    		
+  		drawSelectionPlot(sizePix,spectrum,json,selectionType);
+    		
+     	},
+    	failure: function(){ alert("Ajax Request Failed !"); }
+   });
+	this.items = [this.tabPanel];
+	
+	function getImageSlice(jSON,slice,limitValues) {
+		imageSlice = [];
+		for (var x = 0; x < naxis1; x++) {
+			for (var y = 0; y < naxis2; y++) {
+				b = jSON.SPECTRUM[x][(naxis2-1)-y][slice];
+				if (limitValues.length==0){
+					if (b!="NaN"){ imageSlice.push(b); }
+				} else {
+					if (b!="NaN" && b>limitValues[0] && b<limitValues[1]){ imageSlice.push(b); }
+				}
+			}
+		}
+		return imageSlice;
+	}
+	
+	function drawMap(sizeRec, jSON, slice, init, limitValues) {
+		
+		// ORIGINAL canMap = document.getElementById('mapCanvas');
+		canMap = document.getElementById(mapCanvasID);
+		ctxCube = canMap.getContext('2d');
+		if (init) { ctxCube.scale(sizeRec,sizeRec); }
+		drawSlice(jSON,slice,limitValues);
+			
+		function drawSlice(jSON,slice,limitValues) {
+
+			imageSlice = getImageSlice(jSON,slice,limitValues);
+			if (imageSlice.length!=0) {
+				var min = Math.min.apply(Math, imageSlice);
+				var max = Math.max.apply(Math, imageSlice);
+				
+				for (var x = 0; x < naxis1; x++) {
+					for (var y = 0; y < naxis2; y++) {
+					    b = jSON.SPECTRUM[x][(naxis2-1)-y][slice];
+					    if (b!="NaN"){
+					    	b = ((b - min)/(min+max))*256 | 0;
+					    	ctxCube.fillStyle = 'rgb('+b+','+b+','+b+')';
+							ctxCube.fillRect(x, y, 1, 1);
+					    }
+					}	
+				}
+			}				
+		}			
+	}
+
+	function clearArea(can) { 
+		ctx = can.getContext('2d');
+		ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
+	}
+	
+	function drawSelectionPlot(sizeRec,containerSpec,jSON,selectionType) {
+					
+		var can, ctx, canX, canY, lastX, lastY, mouseIsDown = false;
+		
+		// Selection drawing
+// ORIGINAL        		        	               canOrig = document.getElementById('selCanvas');
+        									canOrig = document.getElementById(selCanvasID);		
+		can = canOrig.cloneNode(true);
+		canOrig.parentNode.replaceChild(can, canOrig);
+
+		ctx = can.getContext('2d');
+		ctx.strokeStyle = 'white';
+		ctx.lineWidth = 2;
+		
+				
+		clearArea(can);
+	   pixelSelected = [];
+	   colors = [];
+      
+	   can.addEventListener("mousedown", mouseDown);
+	   can.addEventListener("mousemove", mouseMove);
+	   can.addEventListener("mouseup", mouseUp);
+        
+		function deg_to_dms (deg) {
+	    	var d = Math.floor (deg);
+	    	var minfloat = (deg-d)*60;
+	    	var m = Math.floor(minfloat);
+	    	var secfloat = (minfloat-m)*60;
+	    	var s = Math.round(secfloat);
+	    	if (s==60) { m++; s=0; }
+	    	if (m==60) { d++; m=0; }
+	   	return ("" + d + "°" + m + "'" + secfloat.toFixed(2) + '"');
+	   }
+	        
+	   function mouseDown(e) {            	
+	     	clearArea(can);
+			mouseIsDown = true;
+			var rect = can.getBoundingClientRect();
+			lastX = e.clientX - rect.left* (can.width  / rect.width);
+			lastY = e.clientY - rect.top* (can.height  / rect.height);
+	   }
+	
+	   function mouseMove(e) {
+			var rect = can.getBoundingClientRect();
+			canX = e.clientX - rect.left;
+			canY = e.clientY - rect.top;
+			if (mouseIsDown) { drawSelection(lastX,lastY,canX,canY,selectionType); }
+			displayRaDec(canX,canY);
+	   }
+	        
+		function mouseUp(e) {
+	      mouseIsDown = false;
+		   var rect = can.getBoundingClientRect();
+	      canX = e.clientX- rect.left* (can.width  / rect.width);
+	      canY = e.clientY-rect.top* (can.height  / rect.height);
+	   	drawSelectedPixels(lastX,lastY,canX,canY,selectionType);
+	   }
+	
+		function drawSelection(lastX, lastY, x, y, selectionType) {
+        	clearArea(can);
+        	ctx.strokeStyle = 'red';
+		  
+	    	if (selectionType=="line"){ 
+	    		ctx.beginPath();
+	    		ctx.moveTo(lastX, lastY);
+	    		ctx.lineTo(x, y);
+		      ctx.stroke();
+	        }    	
+		}
+		
+		function displayRaDec(canX,canY) {
+			xFits = Math.floor(canX/sizeRec);
+			yFits = Math.floor(canY/sizeRec);
+			var ra  = jSON.CRVAL1 + (xFits-(jSON.CRPIX1-1))*jSON.CDELT1;
+			var dec = jSON.CRVAL2 + (((naxis2-1)-(jSON.CRPIX2-1))-yFits)*jSON.CDELT2;
+			Ext.getCmp('ra_field').setValue('<b>'+deg_to_dms(ra)+'</b>');
+			Ext.getCmp('dec_field').setValue('<b>'+deg_to_dms(dec)+'</b>');
+		}
+		
+		function allreadySelected(array,x,y){
+			for ( var pix = 0; pix<array.length; pix++) {
+				if ( array[pix][0]==x && array[pix][1]==y ) { return pix;}
+			}
+			return -1;
+		}
+		
+		function hexaDecimalColor(i) {
+			function componentToHex(c) {
+			    var hex = c.toString(16);
+			    return hex.length == 1 ? "0" + hex : hex;
+			}
+			function rgbToHex(r, g, b) {
+			    return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
+			}
+			
+			if (i%3 == 1) {return rgbToHex(0,Math.random()*256|0,Math.random()*256|0);}
+			if (i%3 == 2) {return rgbToHex(Math.random()*256|0,0,Math.random()*256|0);}
+			if (i%3 == 0) {return rgbToHex(Math.random()*256|0,Math.random()*256|0,0);}
+			
+		}
+		
+		function drawSelectedPixels(startx,starty,endx,endy,selectionType) {
+							
+			clearArea(can);
+			
+			if (selectionType=="pixel"){
+				xFits = Math.floor(startx/sizeRec);
+				yFits = Math.floor(starty/sizeRec);
+				
+				if (jSON.SPECTRUM[xFits][(naxis2-1)-yFits][parseInt(naxis3/2)]!="NaN"){
+					if (allreadySelected(pixelSelected,xFits,yFits)!=-1){
+						var idx = allreadySelected(pixelSelected,xFits,yFits);
+						pixelSelected = pixelSelected.slice(0,idx).concat( pixelSelected.slice(idx+1) );
+						colors = colors.slice(0,idx).concat( colors.slice(idx+1) );
+					} else {
+						pixelSelected.push([xFits,yFits]);
+						colors.push(hexaDecimalColor(colors.length));
+					}
+					for ( var pixel = 0; pixel<pixelSelected.length; pixel++) {
+						xFits = pixelSelected[pixel][0];
+						yFits = pixelSelected[pixel][1];
+						ctx.strokeStyle = colors[pixel];
+						ctx.strokeRect(xFits*sizeRec+1,yFits*sizeRec+1,sizeRec-1,sizeRec-1);
+					}
+				}					
+			}
+			
+			if (selectionType=="line"){
+				
+				pixelSelected = [];
+				colors = [];
+				
+				startX = Math.floor(startx/sizeRec);
+				startY = Math.floor(starty/sizeRec);
+				endX = Math.ceil(endx/sizeRec);
+				endY = Math.ceil(endy/sizeRec);
+				slope = (endY-startY)/(endX-startX);
+				
+				for (var x = Math.min(startX,endX); x <= Math.max(startX,endX); x++) {
+					if (slope>0) { y = Math.floor(slope*(x-Math.min(startX,endX))) + Math.min(startY,endY); }
+					else { y = Math.floor(slope*(x-Math.min(startX,endX))) + Math.max(startY,endY); }
+					if (jSON.SPECTRUM[x][(naxis2-1)-y][parseInt(naxis3/2)]!="NaN" ){
+						color = hexaDecimalColor(colors.length);
+						colors.push(color);
+						ctx.strokeStyle = color;
+						ctx.strokeRect(x*sizeRec+1,y*sizeRec+1,sizeRec-1,sizeRec-1);
+						pixelSelected.push([x,y]);
+					}
+				}
+				
+				slope = (endX-startX)/(endY-startY);
+				for (var y = Math.min(startY,endY); y <= Math.max(startY,endY); y++) {
+					if (slope>0) { x = Math.floor(slope*(y-Math.min(startY,endY))) + Math.min(startX,endX); }
+					else { x = Math.floor(slope*(y-Math.min(startY,endY))) + Math.max(startX,endX); }
+					if (jSON.SPECTRUM[x][(naxis2-1)-y][parseInt(naxis3/2)]!="NaN" && allreadySelected(pixelSelected,x,y)==-1){
+						//color = '#'+Math.floor(Math.random()*16777215).toString(16);
+						color = hexaDecimalColor(colors.length);
+						colors.push(color);
+						ctx.strokeStyle = color;
+						ctx.strokeRect(x*sizeRec+1,y*sizeRec+1,sizeRec-1,sizeRec-1);
+						pixelSelected.push([x,y]);
+					}
+				}
+			}
+			plotSpectra(pixelSelected,selectionType,jSON,containerSpec,slice);
+		}
+		
+	}
+		
+	function plotSpectra(pixelSelected,selectionType,jSON,containerSpec,slice){
+	
+		//Spectrum
+		var spec = [];
+		var zero = [];
+		
+		var minF, maxF, xFits, yFits, titlePlot = "";
+		
+		var trunc = 3;
+		
+		zero.push([parseFloat(jSON.WAVE[trunc]),0]);
+		zero.push([parseFloat(jSON.WAVE[jSON.WAVE.length-trunc]),0]);
+		
+		var unitWave = "("+jSON.UNIT_WAVE+")";
+		var unitFlux = "("+jSON.UNIT_QTTY+")";
+		var infoFlux = jSON.INFO_QTTY;
+		var infoWave = jSON.INFO_WAVE;	
+			
+		if (selectionType=="rect" || selectionType=="circ") {
+			var specLine = [];
+			for ( var i = trunc; i <= jSON.WAVE.length - trunc; i++) {
+				var fluxXY = 0;
+				var nbPix = 0;
+				for ( var pixel = 0; pixel<pixelSelected.length; pixel++){
+					xFits = pixelSelected[pixel][0];
+					yFits = pixelSelected[pixel][1];
+					if (jSON.SPECTRUM[xFits][(naxis2-1)-yFits][i]!="Nan"){
+						fluxXY = fluxXY+ ( jSON.SPECTRUM[xFits][(naxis2-1)-yFits][i] / (pixelSelected.length) );							
+						nbPix++;
+						}
+					}
+				fluxXY = fluxXY / nbPix;
+				if (i==trunc){minF = fluxXY; maxF = fluxXY;}
+				if (fluxXY<minF && !isNaN(fluxXY)){minF = fluxXY;}
+				if (fluxXY>maxF && !isNaN(fluxXY)){maxF = fluxXY;}
+				waveXY = parseFloat(jSON.WAVE[i]);
+				specLine.push([waveXY,fluxXY]);
+				}
+			
+			titlePlot = "Average "+infoFlux+" "+unitFlux+" for all selected pixel(s)";
+			spec.push(specLine);
+		}
+		
+		
+		if (selectionType=="line" || selectionType=="pixel" ){
+			for ( var pixel = 0; pixel<pixelSelected.length; pixel++) {
+				var specLine = [];
+				for ( var i = trunc; i <= jSON.WAVE.length - trunc; i++) {
+					xFits = pixelSelected[pixel][0];
+					yFits = pixelSelected[pixel][1];
+					fluxXY = jSON.SPECTRUM[xFits][(naxis2-1)-yFits][i];
+					if (i==trunc && pixel == 0){minF = fluxXY; maxF = fluxXY;}
+					if (fluxXY<minF && !isNaN(fluxXY)){minF = fluxXY;}
+					if (fluxXY>maxF && !isNaN(fluxXY)){maxF = fluxXY;}
+					waveXY = parseFloat(jSON.WAVE[i]);
+					specLine.push([waveXY,fluxXY]);
+					}
+				spec.push(specLine);
+				
+				}
+			
+			titlePlot = infoFlux+" "+unitFlux+" for each selected pixel(s)";
+		}
+		
+		margeF = 0.1*(maxF-minF);
+
+		var sliceLine = [];
+		sliceLine.push([parseFloat(jSON.WAVE[slice]),minF-margeF]);
+		sliceLine.push([parseFloat(jSON.WAVE[slice]),maxF+margeF]);
+		
+		options = {
+			HtmlText: true,
+		   xaxis: { title: infoWave+" "+unitWave, noTicks: 4 },
+		   yaxis: { min: minF-margeF, max: maxF+margeF, base: Math.E,
+		   	tickFormatter: function(x) {
+		      	return parseFloat(x).toExponential();
+		      }
+		   },
+		   lines: { show: true },
+		   points: { show: false },//{ show: true, radius: 1 },
+		   selection: { mode: 'xy', fps: 50 },
+		   title: titlePlot,
+		   subtitle: "Click on pixel(s) to display spectra - Select plot area to zoom on - Click to unzoom",
+		   mouse: { track: true, relative: true }
+		};
+		
+		container = $(containerSpec.body.id);
+		
+		function drawGraph(spectralData,opts) {
+	        var o = Flotr._.extend(Flotr._.clone(options), opts || {});
+	        varToPlot = [];
+	        varToPlot.push(
+        			{
+		            data: zero,
+		            color: '#FC0000',
+	            	});
+/*		        varToPlot.push(
+        			{
+		            data: sliceLine,
+		            color: '#FC0000',
+	            	});*/
+	        if (spectralData.length!=0) {
+	        	for (var i = 0; i<=spectralData.length;i++){
+	        		varToPlot.push(
+		        			{
+	        				data: spectralData[i],
+	        				color: colors[i]
+		        			});
+	        	}
+	        }
+	        Flotr.draw(container, varToPlot, o);
+	        
+	    }
+		drawGraph(spec);
+		
+		Flotr.EventAdapter.observe(container, 'flotr:select', function(area) {
+	        drawGraph(spec,{
+	            xaxis: { min: area.x1, max: area.x2 },
+	            yaxis: { min: area.y1, max: area.y2 }
+	        });
+	    });
+
+	    Flotr.EventAdapter.observe(container, 'flotr:click', function() {
+	        drawGraph(spec);
+	    });
+		
+	}
+	
+	function plotColorHisto(slice,jSON,sliderL,sliderR){
+		
+		imageSlice = getImageSlice(jSON,slice,[]);
+		
+		var nbrBin = 100;
+		
+		var minS = Math.min.apply(Math, imageSlice);
+		var maxS = Math.max.apply(Math, imageSlice);	
+		var binSize = (maxS-minS)/nbrBin;
+		
+		histo = [];
+		for (var x = 0; x < nbrBin; x++) { histo.push(0);}
+		for (var x = 0; x < imageSlice.length; x++) { histo[Math.floor((imageSlice[x]-minS)/binSize)-1] += 1; }
+		
+		var maxHisto = Math.max.apply(Math, histo);
+		
+		console.log("histo.length :"+histo.length+"  maxHisto : "+maxHisto+"  minS : "+minS+" maxS :"+maxS+"  binSize : "+binSize);		
+		// ORIGINAL canHisto = document.getElementById(canHistoID);
+		canHisto = document.getElementById(canHistoID);
+		ctxHisto = canHisto.getContext('2d');
+		
+		ctxHisto.clearRect(0, 0, ctxHisto.canvas.width, ctxHisto.canvas.height);
+		
+		ctxHisto.strokeStyle = 'black';
+		ctxHisto.lineWidth = 1;	
+		var c = Math.floor((ctxHisto.canvas.height-10)/maxHisto);
+
+		for (var x = 0; x < histo.length; x++){
+			if(c == 0) c=1; 
+			// ORIGINAL ctxHisto.strokeRect( 6+x, ctxHisto.canvas.height-5, 1, (-1)*histo[x]*Math.floor((ctxHisto.canvas.height-10)/maxHisto) );
+			ctxHisto.strokeRect( 6+x, ctxHisto.canvas.height-5, 1, (-1)*histo[x]*c );
+		}
+		ctxHisto.strokeStyle = 'red';
+		ctxHisto.strokeRect( 6+sliderL, ctxHisto.canvas.height-5, 1, (-1)*(ctxHisto.canvas.height-10) );
+		ctxHisto.strokeRect( 6+sliderR, ctxHisto.canvas.height-5, 1, (-1)*(ctxHisto.canvas.height-10) );
+		
+		return [minS+sliderL*binSize, minS+sliderR*binSize];
+		
+	}
+	
+	function getAnId(){
+		var id = Ext.id();
+		id = parseInt(id.replace("ext-gen", ""));
+		return id;
+	}
+    //***********************************************************************************************************************************************************
+    /*
+     * Constructor call
+     */
+    sitools.user.component.viewCubeService.superclass.constructor.call(this, Ext.apply({
+      id : 'viewCube-panel',
+      datasetName : config.datasetName, 
+    	layout : 'border',
+		autoScroll : true,
+      items : [ this.tabPanel ]
+    }, config));	
+    
+};
+
+Ext.extend(sitools.user.component.viewCubeService, Ext.Panel, {
+	/** 
+     * Must be implemented to save window Settings
+     * @return {}
+     */
+    _getSettings : function () {
+        return {
+            datasetName : this.datasetName, 
+            preferencesPath : this.preferencesPath, 
+            preferencesFileName : this.preferencesFileName
+        };
+    }, 
+    /**
+     * Load the userPreferences...
+     */
+    afterRender : function () {
+        sitools.user.component.viewCubeService.superclass.afterRender.call(this); 
+    },
+   
+});
+
+Ext.reg('sitools.user.component.viewCubeService', sitools.user.component.viewCubeService);
+
